Add SD image pipeline, documentation overhaul, and fix module issues

- Add automatic SD image builds for Raspberry Pi via Forgejo Actions
- Enable binfmt emulation on cryodev-main for aarch64 cross-builds
- Add sd-image.nix module to cryodev-pi configuration
- Create comprehensive docs/ structure with installation guides
- Split installation docs into: first-install (server), reinstall, new-client (Pi)
- Add lib/utils.nix and apps/rebuild from synix
- Fix headplane module for new upstream API (tale/headplane)
- Fix various module issues (mailserver stateVersion, option conflicts)
- Add placeholder secrets.yaml files for both hosts
- Remove old INSTRUCTIONS.md (content moved to docs/)
This commit is contained in:
steffen 2026-03-11 08:41:58 +01:00
parent a5261d8ff0
commit 5ba78886d2
44 changed files with 3570 additions and 609 deletions

174
docs/services/sops.md Normal file
View file

@ -0,0 +1,174 @@
# SOPS Secret Management
Atomic secret provisioning for NixOS using [sops-nix](https://github.com/Mic92/sops-nix).
## Overview
Secrets are encrypted with `age` using SSH host keys, ensuring:
- No plaintext secrets in the repository
- Secrets are decrypted at activation time
- Each host can only decrypt its own secrets
## Setup
### 1. Get Host's Age Public Key
After a host is installed, extract its age key from the SSH host key:
```bash
nix-shell -p ssh-to-age --run 'ssh-keyscan -t ed25519 <HOST_IP> | ssh-to-age'
```
Or locally on the host:
```bash
nix-shell -p ssh-to-age --run 'cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age'
```
### 2. Configure .sops.yaml
Add the host key to `.sops.yaml`:
```yaml
keys:
- &admin_key age1e8p35795htf7twrejyugpzw0qja2v33awcw76y4gp6acnxnkzq0s935t4t
- &main_key age1... # cryodev-main
- &pi_key age1... # cryodev-pi
creation_rules:
- path_regex: hosts/cryodev-main/secrets.yaml$
key_groups:
- age:
- *admin_key
- *main_key
- path_regex: hosts/cryodev-pi/secrets.yaml$
key_groups:
- age:
- *admin_key
- *pi_key
```
### 3. Create Secrets File
```bash
sops hosts/<hostname>/secrets.yaml
```
This opens your editor. Add secrets in YAML format:
```yaml
tailscale:
auth-key: "tskey-..."
some-service:
password: "secret123"
```
## Usage in Modules
### Declaring Secrets
```nix
{ config, ... }:
{
sops.secrets.my-secret = {
# Optional: set owner/group
owner = "myservice";
group = "myservice";
};
}
```
### Using Secrets
Reference the secret path in service configuration:
```nix
{
services.myservice = {
passwordFile = config.sops.secrets.my-secret.path;
};
}
```
### Using Templates
For secrets that need to be embedded in config files:
```nix
{
sops.secrets."netdata/stream-api-key" = { };
sops.templates."netdata-stream.conf" = {
content = ''
[stream]
enabled = yes
api key = ${config.sops.placeholder."netdata/stream-api-key"}
'';
owner = "netdata";
};
services.netdata.configDir."stream.conf" =
config.sops.templates."netdata-stream.conf".path;
}
```
## Common Secrets
### cryodev-main
```yaml
mailserver:
accounts:
forgejo: "$2y$05$..." # bcrypt hash
admin: "$2y$05$..."
forgejo-runner:
token: "..."
headplane:
cookie_secret: "..." # openssl rand -hex 16
agent_pre_authkey: "..." # headscale preauthkey
tailscale:
auth-key: "tskey-..."
```
### cryodev-pi
```yaml
tailscale:
auth-key: "tskey-..."
netdata:
stream:
child-uuid: "..." # uuidgen
```
## Generating Secret Values
| Secret | Command |
|--------|---------|
| Mailserver password | `nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'` |
| Random hex token | `nix-shell -p openssl --run 'openssl rand -hex 16'` |
| UUID | `uuidgen` |
| Tailscale preauth | `sudo headscale preauthkeys create --expiration 99y --reusable --user default` |
## Updating Keys
After modifying `.sops.yaml`, update existing secrets files:
```bash
sops --config .sops.yaml updatekeys hosts/<hostname>/secrets.yaml
```
## Troubleshooting
### "No matching keys found"
Ensure the host's age key is in `.sops.yaml` and you've run `updatekeys`.
### Secret not decrypting on host
Check that `/etc/ssh/ssh_host_ed25519_key` exists and matches the public key in `.sops.yaml`.