Nix-Vibe public snapshot (squashed history)
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
# Borg Backup Server Setup for Richmond-Server
|
||||
|
||||
This document outlines the research and recommended approach for setting up a secure Borg backup server on the NixOS host `richmond-server`.
|
||||
|
||||
## 1. Research Findings
|
||||
|
||||
The core security principle for a Borg server is to use SSH with a dedicated, unprivileged user account whose command execution is strictly limited to `borg serve`. I investigated two main ways to achieve this on your server.
|
||||
|
||||
### Method 1: Manual NixOS Configuration (Recommended)
|
||||
|
||||
This method involves declaratively configuring the necessary components directly within your `configuration.nix`. It leverages standard NixOS options for user management and OpenSSH, allowing for precise control and integration with the rest of your system.
|
||||
|
||||
* **How it works**: You define a new system user (e.g., `borg-x1carbon`) and configure its SSH `authorized_keys` entry. For security, the SSH access for this user is restricted by prepending `command="borg serve --restrict-to-path /path/to/repo"` to the public key entry. This ensures that when a client connects as this user via SSH, it can *only* execute the `borg serve` command and *only* within the specified repository path.
|
||||
|
||||
#### Pros
|
||||
- **Highly Secure**: Directly implements Borg's recommended security model (restricted SSH command).
|
||||
- **Idiomatic & Declarative**: Managed entirely within your NixOS configuration using standard options.
|
||||
- **Flexible**: Allows fine-grained control over user permissions and repository paths.
|
||||
- **Integrated**: Works seamlessly with other NixOS components like `users.users` and `services.openssh`.
|
||||
|
||||
#### Cons
|
||||
- Requires manual definition of each user and their SSH keys.
|
||||
|
||||
---
|
||||
|
||||
|
||||
### Method 2: Podman Container
|
||||
|
||||
This approach involves running a community-provided Docker image (like `borgmatic/borgserver` or `nold360/borgserver`) as a Podman container on `richmond-server`.
|
||||
|
||||
* **How it works**: You would define a `virtualisation.oci-containers.containers.<name>` block. This would involve:
|
||||
1. Pulling a suitable Borg server image from Docker Hub.
|
||||
2. Mapping a host directory (e.g., `/var/lib/borg-backups`) into the container as a volume to persist the backup data.
|
||||
3. Mapping a host directory containing the `authorized_keys` file into the container's SSH directory.
|
||||
4. Publishing the container's SSH port (e.g., 2222) to a port on the host.
|
||||
|
||||
#### Pros
|
||||
- **Encapsulated**: The Borg environment and its dependencies are isolated from the host system.
|
||||
- **Consistent Workflow**: Aligns with the existing use of Podman containers on `richmond-server`.
|
||||
|
||||
#### Cons
|
||||
- **Increased Complexity**: Managing persistent storage and SSH keys via volumes is more complex and prone to misconfiguration.
|
||||
- **Manual Security**: You are responsible for ensuring the container image is secure and that the SSH key restrictions are correctly implemented inside the container.
|
||||
- **Less Integrated**: Does not tie into the host's user or firewall management as cleanly as the native NixOS configuration.
|
||||
|
||||
---
|
||||
|
||||
|
||||
## 2. Recommendation
|
||||
|
||||
**The Manual NixOS Configuration is the best method.**
|
||||
|
||||
It is more secure, simpler to manage, and more robust than a container-based solution for this specific use case on a NixOS system. It perfectly embodies the declarative and security-focused principles of both NixOS and Borg.
|
||||
|
||||
## 3. Example Configuration for `richmond-server`
|
||||
|
||||
Here is a proposed configuration snippet that you would add to `hosts/richmond-server/configuration.nix`. This example sets up a repository for a hypothetical client named `x1carbon-laptop`.
|
||||
|
||||
```nix
|
||||
{
|
||||
config, pkgs, lib, ...
|
||||
}:
|
||||
|
||||
{
|
||||
# ... existing configuration ...
|
||||
|
||||
# Borg Backup Server Configuration
|
||||
# Create a dedicated system user for Borg backups
|
||||
users.users.borg-x1carbon = {
|
||||
isSystemUser = true;
|
||||
group = "borg-x1carbon";
|
||||
home = "/var/lib/borgbackup/x1carbon-main-backup"; # Home directory for this repo
|
||||
createHome = true;
|
||||
};
|
||||
users.groups.borg-x1carbon = {};
|
||||
|
||||
# Configure OpenSSH to allow access for the borg user with restricted commands
|
||||
services.openssh.enable = true; # Ensure OpenSSH is enabled
|
||||
services.openssh.authorizedKeys.keys = {
|
||||
"borg-x1carbon" = [
|
||||
# IMPORTANT: Replace this with the actual public SSH key from your x1carbon laptop.
|
||||
# The 'command' option restricts this key to only execute Borg serve commands.
|
||||
"command=\"/run/current-system/sw/bin/borg serve --restrict-to-path /var/lib/borgbackup/x1carbon-main-backup\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICyour_clients_public_key_here user@x1carbon"
|
||||
];
|
||||
};
|
||||
|
||||
# Ensure the base directory for backups exists and has correct permissions
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/borgbackup 0700 root root -"
|
||||
];
|
||||
|
||||
# Borg uses SSH, so ensure the SSH port is open in your firewall.
|
||||
# This is likely already enabled on your server.
|
||||
networking.firewall.allowedTCPPorts = [ 22 ];
|
||||
|
||||
# ... rest of your configuration ...
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Helpful Links
|
||||
|
||||
- [**BorgBackup Official Documentation - Usage with SSH**](https://borgbackup.readthedocs.io/en/stable/usage/ssh.html)
|
||||
- [**NixOS Wiki on BorgBackup**](https://nixos.wiki/wiki/BorgBackup)
|
||||
- [**NixOS `users.users` Options**](https://search.nixos.org/options?channel=unstable&show=users.users&from=0&size=50&sort=relevance&type=packages&query=users.users)
|
||||
- [**NixOS `services.openssh` Options**](https://search.nixos.org/options?channel=unstable&show=services.openssh&from=0&size=50&sort=relevance&type=packages&query=services.openssh)
|
||||
@@ -0,0 +1,275 @@
|
||||
# Homepage Dashboard — Adding Machines, Tabs & Services
|
||||
|
||||
This guide covers how to add new machines, tabs, and services to the **Homepage**
|
||||
dashboards on **homeserver-1** (and, by extension, any host that imports the
|
||||
Homepage module).
|
||||
|
||||
## Overview
|
||||
|
||||
Homepage (https://gethomepage.dev) is a self-hosted dashboard. All dashboard
|
||||
configuration lives in Nix and is rendered to YAML files that Homepage reads
|
||||
at `/etc/homepage-dashboard/`.
|
||||
|
||||
| Item | Location |
|
||||
|------|----------|
|
||||
| Homepage NixOS module (service wrapper) | `modules/services/homepage.nix` |
|
||||
| Dashboard definition for homeserver-1 | `hosts/homeserver-1/homepage.nix` |
|
||||
| Deployed config files | `/etc/homepage-dashboard/{settings,services,widgets}.yaml` |
|
||||
| API keys / secrets | `secrets.yaml` (SOPS) → `HOMEPAGE_VAR_*` env vars |
|
||||
|
||||
The dashboard definition is split from the host config so it's easy to edit:
|
||||
|
||||
- `hosts/homeserver-1/configuration.nix` enables Glances + firewall and imports:
|
||||
```nix
|
||||
imports = [
|
||||
# ...
|
||||
./homepage.nix
|
||||
];
|
||||
```
|
||||
|
||||
## Applying Changes
|
||||
|
||||
After editing `homepage.nix`:
|
||||
|
||||
```bash
|
||||
nixos-rebuild switch --target-host petere@homeserver-1 --flake .#homeserver-1 --use-remote-sudo
|
||||
```
|
||||
|
||||
> **Important:** Homepage reads its config files when the service starts. After
|
||||
> a `nixos-rebuild`, the unit's definition usually changes, but if only the
|
||||
> *contents* of the config files changed (e.g. just editing `homepage.nix`), the
|
||||
> service may keep the old config in memory. If your changes don't appear, restart it:
|
||||
>
|
||||
> ```bash
|
||||
> ssh petere@homeserver-1 "sudo systemctl restart homepage-dashboard"
|
||||
> ```
|
||||
|
||||
## Structure of the Dashboard Definition
|
||||
|
||||
`hosts/homeserver-1/homepage.nix` has three main parts:
|
||||
|
||||
```nix
|
||||
services.homepage = {
|
||||
enable = true;
|
||||
port = 8082;
|
||||
allowedHosts = [ ... ]; # Host header values Homepage responds to
|
||||
environmentFiles = [ ... ]; # SOPS-secret env file with HOMEPAGE_VAR_* keys
|
||||
|
||||
settings = {
|
||||
title = "HomeServer";
|
||||
# ...
|
||||
layout = { ... }; # Controls grouping, tabs, and column widths
|
||||
};
|
||||
|
||||
services = [ ... ]; # The service groups and tiles (services.yaml)
|
||||
widgets = [ ... ]; # Header info widgets (resources, search, clock)
|
||||
};
|
||||
```
|
||||
|
||||
## Tabs
|
||||
|
||||
Tabs are enabled by adding a `tab` field to a group's **layout** entry.
|
||||
|
||||
- Groups with the **same** `tab` value appear on that tab.
|
||||
- Groups with **no** `tab` appear on **every** tab.
|
||||
- Tabs are sorted by their order in the `layout` block.
|
||||
- Each tab is deep-linkable: `#monitoring`, `#homeserver-1`, etc.
|
||||
|
||||
Current tabs:
|
||||
|
||||
```
|
||||
Monitoring (default tab)
|
||||
├── Homeserver-1 Monitoring → 5 Glances tiles (localhost)
|
||||
└── MCF Server Monitoring → 5 Glances tiles (mcf-server via tailnet)
|
||||
|
||||
Homeserver-1 (#homeserver-1)
|
||||
├── Media → Jellyfin, Immich
|
||||
└── System → Backrest, Pocket ID, Tailscale
|
||||
|
||||
MCF Server (reserved; uncomment the placeholder to enable)
|
||||
```
|
||||
|
||||
## Adding a Service
|
||||
|
||||
1. **Add the service tile** to the relevant group in the `services` list:
|
||||
|
||||
```nix
|
||||
services = [
|
||||
# ...
|
||||
{
|
||||
System = [
|
||||
# ...existing tiles...
|
||||
{
|
||||
MyService = {
|
||||
icon = "sh-myservice";
|
||||
href = "http://homeserver-1.gerbil-opah.ts.net:<port>";
|
||||
description = "What it does";
|
||||
siteMonitor = "http://127.0.0.1:<port>"; # green/red status
|
||||
widget = { # optional live stats
|
||||
type = "myservice";
|
||||
url = "http://127.0.0.1:<port>";
|
||||
key = "{{HOMEPAGE_VAR_MYSERVICE_API_KEY}}"; # only if it needs a key
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
```
|
||||
|
||||
2. **Set the layout** so the group renders where you want (columns = how many
|
||||
tiles per row; groups span the full width with `style = "row"` when they're
|
||||
a single top-level group):
|
||||
|
||||
```nix
|
||||
layout = {
|
||||
# ...
|
||||
MyService = { # or add to an existing group's entry
|
||||
tab = "Homeserver-1";
|
||||
style = "row";
|
||||
columns = 4;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
3. **API keys**: never hardcode secrets. Add the value to `secrets.yaml` under
|
||||
the machine section and reference it via the environment file. The secret
|
||||
`homeserver-1/homepage-env` already provides `HOMEPAGE_VAR_JELLYFIN_API_KEY`,
|
||||
`HOMEPAGE_VAR_IMMICH_API_KEY`, `HOMEPAGE_VAR_TAILSCALE_API_KEY` and
|
||||
`HOMEPAGE_VAR_TAILSCALE_DEVICEID`. To add another:
|
||||
|
||||
```bash
|
||||
sops --set '["homeserver-1"]["homepage-env"] "HOMEPAGE_VAR_MYSERVICE_API_KEY=<value>"' secrets.yaml
|
||||
```
|
||||
|
||||
(This replaces the whole env file — include every existing `HOMEPAGE_VAR_*`
|
||||
line when setting it.)
|
||||
|
||||
## Adding a Tab
|
||||
|
||||
Add a new group to `services` and give it a `tab` in the layout:
|
||||
|
||||
```nix
|
||||
# services
|
||||
{
|
||||
"My New Group" = [
|
||||
{ "MyService" = { href = "..."; }; }
|
||||
];
|
||||
}
|
||||
|
||||
# layout
|
||||
"My New Group" = {
|
||||
tab = "My Tab";
|
||||
style = "row";
|
||||
columns = 4;
|
||||
};
|
||||
```
|
||||
|
||||
## Adding a New Machine to the Dashboard
|
||||
|
||||
To monitor another machine (e.g. `richmond-server`):
|
||||
|
||||
### 1. Enable Glances on the target machine
|
||||
|
||||
Add to that host's `configuration.nix` (Glances exposes system stats to the
|
||||
dashboard):
|
||||
|
||||
```nix
|
||||
services.glances = {
|
||||
enable = true;
|
||||
port = 61208;
|
||||
extraArgs = [ "--webserver" ];
|
||||
};
|
||||
|
||||
# Expose on Tailscale only
|
||||
networking.firewall.interfaces.tailscale.allowedTCPPorts = [ 61208 ];
|
||||
```
|
||||
|
||||
### 2. Add the monitoring group
|
||||
|
||||
In `hosts/homeserver-1/homepage.nix`, add a group with Glances tiles. **The
|
||||
group name must be unique** — Homepage's widget proxy resolves widget config by
|
||||
leaf group name, so duplicate group names cause one machine's stats to display
|
||||
on another's tiles.
|
||||
|
||||
```nix
|
||||
# services
|
||||
{
|
||||
"Richmond Server Monitoring" = [
|
||||
{ "System" = { widget = { type = "glances"; url = "http://richmond-server.gerbil-opah.ts.net:61208"; version = 4; metric = "info"; }; }; }
|
||||
{ "CPU" = { widget = { type = "glances"; url = "http://richmond-server.gerbil-opah.ts.net:61208"; version = 4; metric = "cpu"; }; }; }
|
||||
{ "Memory" = { widget = { type = "glances"; url = "http://richmond-server.gerbil-opah.ts.net:61208"; version = 4; metric = "memory"; }; }; }
|
||||
{ "Disk" = { widget = { type = "glances"; url = "http://richmond-server.gerbil-opah.ts.net:61208"; version = 4; metric = "fs:/"; }; }; }
|
||||
{ "Processes" = { widget = { type = "glances"; url = "http://richmond-server.gerbil-opah.ts.net:61208"; version = 4; metric = "process"; }; }; }
|
||||
];
|
||||
}
|
||||
|
||||
# layout
|
||||
"Richmond Server Monitoring" = {
|
||||
tab = "Monitoring";
|
||||
style = "row";
|
||||
columns = 5;
|
||||
};
|
||||
```
|
||||
|
||||
### 3. Add non-monitoring services for that machine
|
||||
|
||||
Add a group and give it its own tab (or reuse an existing one):
|
||||
|
||||
```nix
|
||||
# services
|
||||
{
|
||||
"Richmond Server Apps" = [
|
||||
{ "Ntfy" = { icon = "sh-ntfy"; href = "http://richmond-server.gerbil-opah.ts.net:8080"; }; }
|
||||
];
|
||||
}
|
||||
|
||||
# layout
|
||||
"Richmond Server Apps" = {
|
||||
tab = "Richmond Server";
|
||||
style = "row";
|
||||
columns = 4;
|
||||
};
|
||||
```
|
||||
|
||||
### 4. (Optional) Tailscale widget for the machine
|
||||
|
||||
Each machine's Tailscale node can be shown with its own widget, using the
|
||||
machine's numeric device ID (find it via the Tailscale API/admin console):
|
||||
|
||||
```nix
|
||||
{
|
||||
"Richmond Server" = [
|
||||
{
|
||||
Tailscale = {
|
||||
icon = "sh-tailscale";
|
||||
href = "https://login.tailscale.com/admin/machines";
|
||||
widget = {
|
||||
type = "tailscale";
|
||||
deviceid = "<numeric-device-id>"; # NOT the ...CNTRL value
|
||||
key = "{{HOMEPAGE_VAR_TAILSCALE_API_KEY}}";
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Cause / Fix |
|
||||
|---------|-------------|
|
||||
| Changes not appearing | Service not restarted — run `sudo systemctl restart homepage-dashboard` |
|
||||
| `t.metric is undefined` | Glances widget missing the `metric` field — every glances tile needs `metric` (e.g. `cpu`, `memory`, `fs:/`, `process`, `info`) |
|
||||
| `no manageable device matching this ID found` | Tailscale widget `deviceid` is wrong — must be the **numeric** device ID, not the `...CNTRL` value |
|
||||
| Two machines show the same stats | Duplicate group names — every group (especially monitoring) needs a unique name |
|
||||
| `Host validation failed` | The `Host` header isn't in `allowedHosts` — add the hostname (with port) to `allowedHosts` |
|
||||
| API keys showing in config | Keys must come from the SOPS env file (`HOMEPAGE_VAR_*`), never hardcoded |
|
||||
|
||||
## Glances Metrics
|
||||
|
||||
The Glances widget (`type = "glances"`) requires a `version` and `metric`:
|
||||
|
||||
- `version = 4` for Glances v4.x (installed)
|
||||
- `metric`: `info` (system summary), `cpu`, `memory`, `process`, `containers`,
|
||||
`fs:/` (disk usage), `network:<iface>`, `sensor:<id>`, `disk:<id>`, `gpu:<id>`
|
||||
@@ -0,0 +1,69 @@
|
||||
# Initial Installation
|
||||
|
||||
This repository uses [nixos-anywhere](https://github.com/nix-community/nixos-anywhere) for seamless deployment to new hardware.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. **SSH Access**: The target machine must be booted into a Linux environment (e.g., NixOS Installer ISO) with SSH enabled and your public key authorized.
|
||||
2. **Secrets Management**: If the target host requires secrets, ensure its Age key is generated and added to `.sops.yaml` as described in the [SOPS Guide](sops-secrets.md).
|
||||
3. **Disko**: Ensure the `disko-config.nix` for the host matches the target hardware's drive names (e.g., `/dev/nvme0n1` vs `/dev/sda`).
|
||||
|
||||
## Deployment Command
|
||||
|
||||
Run this command from the root of the repository:
|
||||
|
||||
```bash
|
||||
nix run github:nix-community/nixos-anywhere -- --flake .#<hostname> <target-ip>
|
||||
```
|
||||
|
||||
*Example:* `nix run github:nix-community/nixos-anywhere -- --flake .#x1carbon 192.168.1.50`
|
||||
|
||||
The process will automatically partition the drive via `disko`, install the system, and reboot into the new NixOS environment.
|
||||
|
||||
## Post-Installation
|
||||
|
||||
After the first boot, apply the configuration locally:
|
||||
|
||||
```bash
|
||||
sudo nixos-rebuild switch --flake /etc/nixos/#<hostname>
|
||||
```
|
||||
|
||||
For ongoing management, clone this repository and use the commands in the main [README.md](../README.md).
|
||||
|
||||
---
|
||||
|
||||
## Secrets: Using Age Keys with `--extra-files`
|
||||
|
||||
Some hosts require SOPS secrets at build time (e.g., user passwords with `neededForUsers = true`). The private age key must be available during `nixos-rebuild`, but it should **never** be committed to Git. Use the `extra-files/` directory (in `.gitignore`) and the `--extra-files` flag to supply the key securely.
|
||||
|
||||
### 1. Create the Age Key
|
||||
|
||||
Generate a new age key and store it in the untracked `extra-files/` tree:
|
||||
|
||||
```bash
|
||||
mkdir -p extra-files/root/.config/sops/age
|
||||
age-keygen -o extra-files/root/.config/sops/age/keys.txt
|
||||
```
|
||||
|
||||
Extract the **public key** and add it to `.sops.yaml`, then re-encrypt the secrets file so this key can decrypt them:
|
||||
|
||||
```bash
|
||||
cat extra-files/root/.config/sops/age/keys.txt | age-keygen -y
|
||||
# Copy the output public key into .sops.yaml under the `age` key list
|
||||
sops updatekeys secrets.yaml
|
||||
```
|
||||
|
||||
### 2. Deploy with `--extra-files`
|
||||
|
||||
The `--extra-files` flag copies the local `extra-files/` directory into the Nix store so the age key is available at build time:
|
||||
|
||||
```bash
|
||||
sudo nixos-rebuild switch --flake .#<hostname> --extra-files extra-files
|
||||
```
|
||||
|
||||
This makes `extra-files/root/.config/sops/age/keys.txt` available at `/root/.config/sops/age/keys.txt` during evaluation, allowing SOPS to decrypt `secrets.yaml` without the key ever touching the target machine's filesystem.
|
||||
|
||||
> **Note**: For `nixos-anywhere` initial deployments, supply the age key via `--extra-files` as well:
|
||||
> ```bash
|
||||
> nix run github:nix-community/nixos-anywhere -- --extra-files extra-files --flake .#<hostname> <target-ip>
|
||||
> ```
|
||||
@@ -0,0 +1,95 @@
|
||||
# Software Inventory
|
||||
|
||||
This table tracks which software is installed on each host and how it's installed.
|
||||
|
||||
| Software | Installation Method | X1C | CX1 | X470 | MX270 | RS | HS1 | HPL |
|
||||
| :------------------- | :------------------------------- | :-- | :-- | :--- | :---- | :- | :-- | :-: |
|
||||
| **Zsh** | NixOS System / HM Module | x | x | x | x | x | x | x |
|
||||
| **Tailscale** | NixOS System | x | x | x | x | x | x | x |
|
||||
| **GNOME** | NixOS System | x | x | x | x | | | |
|
||||
| **Hyprland** | NixOS System | | | | | | | x |
|
||||
| **QuickShell** | NixOS System | | | | | | | x |
|
||||
| **Wofi** | NixOS System | | | | | | | x |
|
||||
| **Thunar** | NixOS System | | | | | | | x |
|
||||
| **Power Mgmt** | NixOS System (upower, power-profiles-daemon, hypridle) | | | | | | | x |
|
||||
| **vdirsyncer** | HM (cal sync) | | | | | | | x |
|
||||
| **khal** | HM (cal sync) | | | | | | | x |
|
||||
| **Firefox** | NixOS System / HM Module | x | x | x | x | | | x |
|
||||
| **Chromium** | NixOS System | x | x | x | x | | | x |
|
||||
| **Thunderbird** | NixOS System | x | x | x | x | | | x |
|
||||
| **Bitwarden** | NixOS System | x | x | x | x | | | x |
|
||||
| **VLC** | NixOS System | x | x | x | x | | | x |
|
||||
| **Element Desktop** | NixOS System | x | x | x | x | | | x |
|
||||
| **Kdenlive** | NixOS System | x | x | x | x | | | x |
|
||||
| **Nextcloud Client** | NixOS System | x | x | x | x | | | x |
|
||||
| **OnlyOffice** | NixOS System | x | x | x | x | | | x |
|
||||
| **Gear Lever** | Flatpak | x | x | x | x | | | x |
|
||||
| **Flatseal** | Flatpak | x | x | x | x | | | x |
|
||||
| **Soundux** | Flatpak | x | x | | | | | |
|
||||
| **OpenLP** | Flatpak Bundle | | | x | | | | |
|
||||
| **FreeShow** | AppImage | x | x | x | | | | |
|
||||
| **GIMP** | NixOS System | x | | | | | | |
|
||||
| **Scribus** | NixOS System | x | | | | | | |
|
||||
| **OpenShot** | NixOS System | x | | | | | | |
|
||||
| **OBS Studio** | NixOS System (NDI / CUDA) | x | | | | | | |
|
||||
| **OpenCode** | NixOS System | x | | | | | | |
|
||||
| **MCP-NixOS** | HM User Package (x1carbon) | x | | | | | | |
|
||||
| **LM Studio** | NixOS System | x | | | | | | |
|
||||
| **Mixing Station** | NixOS System (Custom Derivation) | x | | | | | | |
|
||||
| **X32-Edit** | NixOS System | x | | | | | | |
|
||||
| **Vorta** | NixOS System | x | | | | | | |
|
||||
| **Paperless-ngx** | NixOS System (Module) | x | | | | | | |
|
||||
| **Winbox** | NixOS System | x | | x | | | | |
|
||||
| **wvkbd** | HM User Package (x1carbon) | x | | | | | | |
|
||||
| **matugen** | HM User Package (x1carbon) | x | | | | | | |
|
||||
| **Xournal++** | NixOS System | x | x | | | | | |
|
||||
| **Steam** | NixOS System | x | x | | | | | |
|
||||
| **Prism Launcher** | NixOS System | | x | | | | | |
|
||||
| **Rclone** | NixOS System | | x | | | | | |
|
||||
| **Pi-hole** | Container (Podman) | | | | | x | | |
|
||||
| **Castopod** | Container (Podman) | | | | | x | | |
|
||||
| **MCFNotices** | Container (Podman) | | | | | x | | |
|
||||
| **Ntfy** | NixOS System (Module) | | | | | x | | |
|
||||
| **Immich** | NixOS System (Module) | | | | | | x | |
|
||||
| **Pocket ID** | NixOS System (Module) | | | | | | x | |
|
||||
| **Jellyfin** | NixOS System (Module) | | | | | | x | |
|
||||
| **Backrest** | NixOS System (Module) | | | | | | x | |
|
||||
| **Gitea** | NixOS System (Module) | | | | | | x | |
|
||||
| **Homepage** | NixOS System (Module) | | | | | | x | |
|
||||
| **MariaDB** | NixOS System | | | | | x | | |
|
||||
| **BorgBackup** | _Removed - migrated to Backrest_ | | | | | | | |
|
||||
| **NVIDIA Drivers** | NixOS System | x | | | | | x | |
|
||||
| **VS Code** | HM Module | x | x | x | x | | | x |
|
||||
| **Kitty** | HM Module | x | x | x | x | | | x |
|
||||
| **Direnv** | HM User | x | x | x | x | x | | x |
|
||||
| **Git** | HM User / System | x | x | x | x | x | x | x |
|
||||
| **Fastfetch** | HM User | x | x | x | x | x | | x |
|
||||
| **Python / UV** | NixOS System | x | x | | x | | | x |
|
||||
| **Flutter** | NixOS System | x | x | | x | | | x |
|
||||
| **Disko** | NixOS Module | x | x | x | x | x | x | x |
|
||||
| **SOPS** | NixOS Module / System | x | x | x | x | x | x | x |
|
||||
| **Microsoft Core Fonts** | NixOS System (Fonts) | x | x | x | x | x | x | x |
|
||||
| **Admin tools** | NixOS System (`management.nix`) | x | x | x | x | x | x | x |
|
||||
|
||||
## Legend
|
||||
|
||||
| Code | Host |
|
||||
|------|------|
|
||||
| **X1C** | `x1carbon` |
|
||||
| **CX1** | `caitlin-x1` |
|
||||
| **X470** | `x470` |
|
||||
| **MX270** | `mary-x270` |
|
||||
| **RS** | `richmond-server` |
|
||||
| **HS1** | `homeserver-1` |
|
||||
| **HPL** | `hp-laptop` |
|
||||
|
||||
## Installation Methods
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| **NixOS System** | Package installed via `environment.systemPackages` or `services.<name>.enable` |
|
||||
| **HM Module** | Home Manager module (`programs.<name>.enable`) |
|
||||
| **HM User** | Home Manager user-level config (`home.packages`) |
|
||||
| **Flatpak** | Installed via `services.flatpak.packages` |
|
||||
| **Container (Podman)** | Runs as an OCI container via Podman |
|
||||
| **AppImage** | Standalone AppImage bundle |
|
||||
@@ -0,0 +1,128 @@
|
||||
# SOPS Secrets Management Guide
|
||||
|
||||
This guide covers how to manage encrypted secrets in Nix-Vibe using `sops-nix` with `age` encryption.
|
||||
|
||||
## Overview
|
||||
|
||||
- **Secrets File**: `secrets.yaml` (encrypted in Git)
|
||||
- **Configuration**: `.sops.yaml` (public keys and creation rules)
|
||||
- **Private Key**: Locally stored at `~/.config/sops/age/keys.txt` (Never commit this!)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
The project includes `sops` in the default development environment. You can also run it temporarily:
|
||||
|
||||
```bash
|
||||
nix shell nixpkgs#sops nixpkgs#age
|
||||
```
|
||||
|
||||
## Adding or Updating Secrets
|
||||
|
||||
The easiest way to add a new secret (like a password or API key) is to use the `sops --set` command from the root of the repository.
|
||||
|
||||
### Adding a Key-Value Pair
|
||||
|
||||
```bash
|
||||
sops --set '["<host-or-category>"]["<secret-name>"] "<value>"' secrets.yaml
|
||||
```
|
||||
|
||||
*Example (Adding a server password):*
|
||||
```bash
|
||||
sops --set '["richmond-server"]["new-password"] "supersecret123"' secrets.yaml
|
||||
```
|
||||
|
||||
*Example (Adding a global user password):*
|
||||
```bash
|
||||
sops --set '["users"]["petere-password"] "mypassword"' secrets.yaml
|
||||
```
|
||||
|
||||
### Editing the Secrets File Directly
|
||||
|
||||
To open the entire decrypted file in your editor:
|
||||
|
||||
```bash
|
||||
sops secrets.yaml
|
||||
```
|
||||
|
||||
## Using Secrets in Configuration
|
||||
|
||||
### 1. NixOS System Secrets
|
||||
|
||||
In `hosts/<hostname>/configuration.nix`:
|
||||
|
||||
```nix
|
||||
sops.secrets."machine-name/new-secret" = {
|
||||
owner = "root";
|
||||
group = "root";
|
||||
mode = "0400";
|
||||
};
|
||||
```
|
||||
|
||||
**Note:** For user passwords, add `neededForUsers = true;` to ensure the secret is decrypted early enough for the account to be created.
|
||||
|
||||
### 2. Home Manager Secrets
|
||||
|
||||
Home Manager secrets are defined in the user's profile (e.g., `home-manager/users/petere.nix`):
|
||||
|
||||
```nix
|
||||
sops.secrets."gemini-api-key" = { };
|
||||
```
|
||||
|
||||
Access the decrypted path in your configuration:
|
||||
`config.sops.secrets."gemini-api-key".path`
|
||||
|
||||
### 3. Rendered Templates (`sops.templates`)
|
||||
|
||||
For config files that embed a secret (e.g. an env file consumed by a container),
|
||||
use `sops.templates` so sops-nix renders the file with correct permissions and
|
||||
re-renders it at boot/switch — no shell `preStart` needed:
|
||||
|
||||
```nix
|
||||
sops.templates."pihole-env" = {
|
||||
content = ''
|
||||
FTLCONF_webserver_api_password=${config.sops.placeholder."richmond-server/pihole-password"}
|
||||
'';
|
||||
path = "/run/pihole-env";
|
||||
mode = "0600";
|
||||
};
|
||||
```
|
||||
|
||||
The `${config.sops.placeholder."<secret>"}` reference is substituted with the
|
||||
decrypted value at runtime. Live examples: `hosts/richmond-server/configuration.nix`
|
||||
(pihole + castopod env files).
|
||||
|
||||
### Multi-line Secrets
|
||||
|
||||
Store SSH keys and other multi-line values as YAML **block scalars** (using `|`)
|
||||
so they decrypt with real newlines. `hosts/homeserver-1/configuration.nix`
|
||||
installs the `restic-ssh-key` verbatim with `install`, so that secret must be
|
||||
multi-line (not a single line with escaped spaces).
|
||||
|
||||
## Rotating / Adding New Machine Keys
|
||||
|
||||
When deploying to a new machine, you must generate an age key and add its public key to `.sops.yaml`.
|
||||
|
||||
1. **Generate the key on the target machine**:
|
||||
```bash
|
||||
mkdir -p ~/.config/sops/age
|
||||
age-keygen -o ~/.config/sops/age/keys.txt
|
||||
```
|
||||
|
||||
2. **Get the public key**:
|
||||
```bash
|
||||
cat ~/.config/sops/age/keys.txt | age-keygen -y
|
||||
```
|
||||
|
||||
3. **Update `.sops.yaml`**:
|
||||
Add the new public key to the `age` list.
|
||||
|
||||
4. **Re-encrypt the secrets file**:
|
||||
```bash
|
||||
sops updatekeys secrets.yaml
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **"No sops config found"**: Ensure you are in the repository root.
|
||||
- **Decryption Failure**: Ensure your private key is at `~/.config/sops/age/keys.txt` or set `export SOPS_AGE_KEY_FILE=...`.
|
||||
- **Pure Evaluation Mode**: Nix Flakes in pure mode cannot read absolute paths (like `/run/secrets/...`). Use `sops.templates` or runtime injection instead of `preStart` (see `hosts/richmond-server/configuration.nix`).
|
||||
Reference in New Issue
Block a user