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:
parent
a5261d8ff0
commit
5ba78886d2
44 changed files with 3570 additions and 609 deletions
174
docs/services/sops.md
Normal file
174
docs/services/sops.md
Normal 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`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue