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
149
docs/services/forgejo.md
Normal file
149
docs/services/forgejo.md
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
# Forgejo
|
||||
|
||||
Forgejo is a self-hosted Git service (fork of Gitea) with built-in CI/CD Actions.
|
||||
|
||||
## References
|
||||
|
||||
- [Forgejo Documentation](https://forgejo.org/docs/)
|
||||
- [Forgejo Actions](https://forgejo.org/docs/latest/user/actions/)
|
||||
|
||||
## Setup
|
||||
|
||||
### DNS
|
||||
|
||||
Set a CNAME record for `git.cryodev.xyz` pointing to your main domain.
|
||||
|
||||
### Configuration
|
||||
|
||||
```nix
|
||||
# hosts/cryodev-main/services/forgejo.nix
|
||||
{ config, ... }:
|
||||
{
|
||||
services.forgejo = {
|
||||
enable = true;
|
||||
settings = {
|
||||
server = {
|
||||
DOMAIN = "git.cryodev.xyz";
|
||||
ROOT_URL = "https://git.cryodev.xyz";
|
||||
};
|
||||
mailer = {
|
||||
ENABLED = true;
|
||||
FROM = "forgejo@cryodev.xyz";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Forgejo Runner
|
||||
|
||||
The runner executes CI/CD pipelines defined in `.forgejo/workflows/`.
|
||||
|
||||
### Get Runner Token
|
||||
|
||||
1. Go to Forgejo Admin Panel
|
||||
2. Navigate to Actions > Runners
|
||||
3. Create a new runner and copy the token
|
||||
|
||||
### Add to Secrets
|
||||
|
||||
```bash
|
||||
sops hosts/cryodev-main/secrets.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
forgejo-runner:
|
||||
token: "your-runner-token"
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
```nix
|
||||
{
|
||||
sops.secrets."forgejo-runner/token" = { };
|
||||
|
||||
services.gitea-actions-runner = {
|
||||
instances.default = {
|
||||
enable = true;
|
||||
url = "https://git.cryodev.xyz";
|
||||
tokenFile = config.sops.secrets."forgejo-runner/token".path;
|
||||
labels = [ "ubuntu-latest:docker://node:20" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## CI/CD Workflows
|
||||
|
||||
### deploy-rs Workflow
|
||||
|
||||
`.forgejo/workflows/deploy.yaml`:
|
||||
|
||||
```yaml
|
||||
name: Deploy
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v24
|
||||
|
||||
- name: Deploy
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
nix run .#deploy
|
||||
```
|
||||
|
||||
## Administration
|
||||
|
||||
### Create Admin User
|
||||
|
||||
```bash
|
||||
sudo -u forgejo forgejo admin user create \
|
||||
--username admin \
|
||||
--password changeme \
|
||||
--email admin@cryodev.xyz \
|
||||
--admin
|
||||
```
|
||||
|
||||
### Reset User Password
|
||||
|
||||
```bash
|
||||
sudo -u forgejo forgejo admin user change-password \
|
||||
--username USER \
|
||||
--password NEWPASS
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Check Service Status
|
||||
|
||||
```bash
|
||||
sudo systemctl status forgejo
|
||||
sudo systemctl status gitea-runner-default
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
sudo journalctl -u forgejo -f
|
||||
sudo journalctl -u gitea-runner-default -f
|
||||
```
|
||||
|
||||
### Database Issues
|
||||
|
||||
Forgejo uses SQLite by default. Database location:
|
||||
|
||||
```bash
|
||||
ls -la /var/lib/forgejo/data/
|
||||
```
|
||||
107
docs/services/headplane.md
Normal file
107
docs/services/headplane.md
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
# Headplane
|
||||
|
||||
Headplane is a web-based admin interface for Headscale.
|
||||
|
||||
## References
|
||||
|
||||
- [GitHub](https://github.com/tale/headplane)
|
||||
|
||||
## Setup
|
||||
|
||||
### DNS
|
||||
|
||||
Set a CNAME record for `headplane.cryodev.xyz` pointing to your main domain.
|
||||
|
||||
### Generate Secrets
|
||||
|
||||
**Cookie Secret** (for session management):
|
||||
|
||||
```bash
|
||||
nix-shell -p openssl --run 'openssl rand -hex 16'
|
||||
```
|
||||
|
||||
**Agent Pre-Auth Key** (for Headplane's built-in agent):
|
||||
|
||||
```bash
|
||||
# First, create a dedicated user
|
||||
sudo headscale users create headplane-agent
|
||||
|
||||
# Then create a reusable pre-auth key
|
||||
sudo headscale preauthkeys create --expiration 99y --reusable --user headplane-agent
|
||||
```
|
||||
|
||||
### Add to Secrets
|
||||
|
||||
Edit `hosts/cryodev-main/secrets.yaml`:
|
||||
|
||||
```bash
|
||||
sops hosts/cryodev-main/secrets.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
headplane:
|
||||
cookie_secret: "your-generated-hex-string"
|
||||
agent_pre_authkey: "your-preauth-key"
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
```nix
|
||||
# hosts/cryodev-main/services/headplane.nix
|
||||
{ config, ... }:
|
||||
{
|
||||
sops.secrets."headplane/cookie_secret" = { };
|
||||
sops.secrets."headplane/agent_pre_authkey" = { };
|
||||
|
||||
services.headplane = {
|
||||
enable = true;
|
||||
settings = {
|
||||
server = {
|
||||
cookie_secret_file = config.sops.secrets."headplane/cookie_secret".path;
|
||||
};
|
||||
headscale = {
|
||||
url = "https://headscale.cryodev.xyz";
|
||||
};
|
||||
agent = {
|
||||
enable = true;
|
||||
authkey_file = config.sops.secrets."headplane/agent_pre_authkey".path;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Access Headplane at `https://headplane.cryodev.xyz`.
|
||||
|
||||
### Features
|
||||
|
||||
- View and manage users
|
||||
- View connected nodes
|
||||
- Manage routes and exit nodes
|
||||
- View pre-auth keys
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Check Service Status
|
||||
|
||||
```bash
|
||||
sudo systemctl status headplane
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
sudo journalctl -u headplane -f
|
||||
```
|
||||
|
||||
### Agent Not Connecting
|
||||
|
||||
Verify the agent pre-auth key is valid:
|
||||
|
||||
```bash
|
||||
sudo headscale preauthkeys list --user headplane-agent
|
||||
```
|
||||
|
||||
If expired, create a new one and update the secrets file.
|
||||
116
docs/services/headscale.md
Normal file
116
docs/services/headscale.md
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
# Headscale
|
||||
|
||||
Headscale is an open-source, self-hosted implementation of the Tailscale control server.
|
||||
|
||||
## References
|
||||
|
||||
- [Website](https://headscale.net/stable/)
|
||||
- [GitHub](https://github.com/juanfont/headscale)
|
||||
- [Example configuration](https://github.com/juanfont/headscale/blob/main/config-example.yaml)
|
||||
|
||||
## Setup
|
||||
|
||||
### DNS
|
||||
|
||||
Set a CNAME record for `headscale.cryodev.xyz` pointing to your main domain.
|
||||
|
||||
### Configuration
|
||||
|
||||
```nix
|
||||
# hosts/cryodev-main/services/headscale.nix
|
||||
{
|
||||
services.headscale = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Create a User
|
||||
|
||||
```bash
|
||||
sudo headscale users create <USERNAME>
|
||||
```
|
||||
|
||||
### List Users
|
||||
|
||||
```bash
|
||||
sudo headscale users list
|
||||
```
|
||||
|
||||
### Create Pre-Auth Key
|
||||
|
||||
```bash
|
||||
sudo headscale preauthkeys create --expiration 99y --reusable --user <USER_ID>
|
||||
```
|
||||
|
||||
The pre-auth key is used by clients to automatically authenticate and join the tailnet.
|
||||
|
||||
### List Nodes
|
||||
|
||||
```bash
|
||||
sudo headscale nodes list
|
||||
```
|
||||
|
||||
### Delete a Node
|
||||
|
||||
```bash
|
||||
sudo headscale nodes delete -i <NODE_ID>
|
||||
```
|
||||
|
||||
### Rename a Node
|
||||
|
||||
```bash
|
||||
sudo headscale nodes rename -i <NODE_ID> new-name
|
||||
```
|
||||
|
||||
## ACL Configuration
|
||||
|
||||
Access Control Lists define which nodes can communicate with each other.
|
||||
|
||||
### Validate ACL File
|
||||
|
||||
```bash
|
||||
sudo headscale policy check --file /path/to/acl.hujson
|
||||
```
|
||||
|
||||
### Example ACL
|
||||
|
||||
```json
|
||||
{
|
||||
"acls": [
|
||||
{
|
||||
"action": "accept",
|
||||
"src": ["*"],
|
||||
"dst": ["*:*"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Check Service Status
|
||||
|
||||
```bash
|
||||
sudo systemctl status headscale
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
sudo journalctl -u headscale -f
|
||||
```
|
||||
|
||||
### Test DERP Connectivity
|
||||
|
||||
```bash
|
||||
curl -I https://headscale.cryodev.xyz/derp
|
||||
```
|
||||
|
||||
## Integration
|
||||
|
||||
- [Headplane](headplane.md) - Web UI for managing Headscale
|
||||
- [Tailscale Client](tailscale.md) - Connect clients to Headscale
|
||||
147
docs/services/mailserver.md
Normal file
147
docs/services/mailserver.md
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
# Mailserver
|
||||
|
||||
NixOS mailserver module providing a complete email stack with Postfix and Dovecot.
|
||||
|
||||
## References
|
||||
|
||||
- [Simple NixOS Mailserver](https://gitlab.com/simple-nixos-mailserver/nixos-mailserver)
|
||||
|
||||
## Setup
|
||||
|
||||
### DNS Records
|
||||
|
||||
| Type | Hostname | Value |
|
||||
|------|----------|-------|
|
||||
| A | `mail` | `<SERVER_IP>` |
|
||||
| AAAA | `mail` | `<SERVER_IPV6>` |
|
||||
| MX | `@` | `10 mail.cryodev.xyz.` |
|
||||
| TXT | `@` | `"v=spf1 mx ~all"` |
|
||||
| TXT | `_dmarc` | `"v=DMARC1; p=none"` |
|
||||
|
||||
DKIM records are generated automatically after first deployment.
|
||||
|
||||
### Generate Password Hashes
|
||||
|
||||
```bash
|
||||
nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
|
||||
```
|
||||
|
||||
### Add to Secrets
|
||||
|
||||
```bash
|
||||
sops hosts/cryodev-main/secrets.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
mailserver:
|
||||
accounts:
|
||||
admin: "$2y$05$..."
|
||||
forgejo: "$2y$05$..."
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
```nix
|
||||
# hosts/cryodev-main/services/mailserver.nix
|
||||
{ config, ... }:
|
||||
{
|
||||
sops.secrets."mailserver/accounts/admin" = { };
|
||||
sops.secrets."mailserver/accounts/forgejo" = { };
|
||||
|
||||
mailserver = {
|
||||
enable = true;
|
||||
fqdn = "mail.cryodev.xyz";
|
||||
domains = [ "cryodev.xyz" ];
|
||||
|
||||
loginAccounts = {
|
||||
"admin@cryodev.xyz" = {
|
||||
hashedPasswordFile = config.sops.secrets."mailserver/accounts/admin".path;
|
||||
};
|
||||
"forgejo@cryodev.xyz" = {
|
||||
hashedPasswordFile = config.sops.secrets."mailserver/accounts/forgejo".path;
|
||||
sendOnly = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## DKIM Setup
|
||||
|
||||
After first deployment, get the DKIM public key:
|
||||
|
||||
```bash
|
||||
sudo cat /var/dkim/cryodev.xyz.mail.txt
|
||||
```
|
||||
|
||||
Add this as a TXT record:
|
||||
|
||||
| Type | Hostname | Value |
|
||||
|------|----------|-------|
|
||||
| TXT | `mail._domainkey` | `v=DKIM1; k=rsa; p=...` |
|
||||
|
||||
## Testing
|
||||
|
||||
### Send Test Email
|
||||
|
||||
```bash
|
||||
echo "Test" | mail -s "Test Subject" recipient@example.com
|
||||
```
|
||||
|
||||
### Check Mail Queue
|
||||
|
||||
```bash
|
||||
sudo postqueue -p
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
sudo journalctl -u postfix -f
|
||||
sudo journalctl -u dovecot2 -f
|
||||
```
|
||||
|
||||
### Test SMTP
|
||||
|
||||
```bash
|
||||
openssl s_client -connect mail.cryodev.xyz:587 -starttls smtp
|
||||
```
|
||||
|
||||
### Verify DNS Records
|
||||
|
||||
- [MXToolbox](https://mxtoolbox.com/)
|
||||
- [Mail-tester](https://www.mail-tester.com/)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Emails Not Sending
|
||||
|
||||
Check Postfix status:
|
||||
|
||||
```bash
|
||||
sudo systemctl status postfix
|
||||
```
|
||||
|
||||
Check firewall (ports 25, 465, 587 must be open):
|
||||
|
||||
```bash
|
||||
sudo iptables -L -n | grep -E '25|465|587'
|
||||
```
|
||||
|
||||
### DKIM Failing
|
||||
|
||||
Verify the DNS record matches the generated key:
|
||||
|
||||
```bash
|
||||
dig TXT mail._domainkey.cryodev.xyz
|
||||
```
|
||||
|
||||
### SPF Failing
|
||||
|
||||
Verify SPF record:
|
||||
|
||||
```bash
|
||||
dig TXT cryodev.xyz
|
||||
```
|
||||
|
||||
Should return: `"v=spf1 mx ~all"`
|
||||
181
docs/services/netdata.md
Normal file
181
docs/services/netdata.md
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
# Netdata Monitoring
|
||||
|
||||
Netdata provides real-time performance monitoring with parent/child streaming.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐ Stream over ┌─────────────────┐
|
||||
│ cryodev-pi │ ───────────────────>│ cryodev-main │
|
||||
│ (Child Node) │ Tailscale VPN │ (Parent Node) │
|
||||
└─────────────────┘ └─────────────────┘
|
||||
│
|
||||
v
|
||||
https://netdata.cryodev.xyz
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [Netdata Documentation](https://learn.netdata.cloud/)
|
||||
- [Streaming Configuration](https://learn.netdata.cloud/docs/streaming/streaming-configuration-reference)
|
||||
|
||||
## Parent Node (cryodev-main)
|
||||
|
||||
### DNS
|
||||
|
||||
Set a CNAME record for `netdata.cryodev.xyz` pointing to your main domain.
|
||||
|
||||
### Generate Stream API Key
|
||||
|
||||
```bash
|
||||
uuidgen
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
```nix
|
||||
# hosts/cryodev-main/services/netdata.nix
|
||||
{ config, ... }:
|
||||
{
|
||||
sops.secrets."netdata/stream-api-key" = { };
|
||||
|
||||
sops.templates."netdata-stream.conf" = {
|
||||
content = ''
|
||||
[${config.sops.placeholder."netdata/stream-api-key"}]
|
||||
enabled = yes
|
||||
default history = 3600
|
||||
default memory mode = ram
|
||||
health enabled by default = auto
|
||||
allow from = *
|
||||
'';
|
||||
owner = "netdata";
|
||||
};
|
||||
|
||||
services.netdata = {
|
||||
enable = true;
|
||||
configDir."stream.conf" = config.sops.templates."netdata-stream.conf".path;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Child Node (cryodev-pi)
|
||||
|
||||
### Generate Child UUID
|
||||
|
||||
```bash
|
||||
uuidgen
|
||||
```
|
||||
|
||||
### Add to Secrets
|
||||
|
||||
```bash
|
||||
sops hosts/cryodev-pi/secrets.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
netdata:
|
||||
stream:
|
||||
child-uuid: "your-generated-uuid"
|
||||
```
|
||||
|
||||
Note: The stream API key must match the parent's key. You can either:
|
||||
1. Share the same secret between hosts (complex with SOPS)
|
||||
2. Hardcode a known API key in both configurations
|
||||
|
||||
### Configuration
|
||||
|
||||
```nix
|
||||
# hosts/cryodev-pi/services/netdata.nix
|
||||
{ config, constants, ... }:
|
||||
{
|
||||
sops.secrets."netdata/stream/child-uuid" = { };
|
||||
|
||||
sops.templates."netdata-stream.conf" = {
|
||||
content = ''
|
||||
[stream]
|
||||
enabled = yes
|
||||
destination = ${constants.hosts.cryodev-main.ip}:19999
|
||||
api key = YOUR_STREAM_API_KEY
|
||||
send charts matching = *
|
||||
'';
|
||||
owner = "netdata";
|
||||
};
|
||||
|
||||
services.netdata = {
|
||||
enable = true;
|
||||
configDir."stream.conf" = config.sops.templates."netdata-stream.conf".path;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Email Alerts
|
||||
|
||||
Configure Netdata to send alerts via the mailserver:
|
||||
|
||||
```nix
|
||||
{
|
||||
services.netdata.configDir."health_alarm_notify.conf" = pkgs.writeText "notify.conf" ''
|
||||
SEND_EMAIL="YES"
|
||||
EMAIL_SENDER="netdata@cryodev.xyz"
|
||||
DEFAULT_RECIPIENT_EMAIL="admin@cryodev.xyz"
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Access Dashboard
|
||||
|
||||
Open `https://netdata.cryodev.xyz` in your browser.
|
||||
|
||||
### View Child Nodes
|
||||
|
||||
Child nodes appear in the left sidebar under "Nodes".
|
||||
|
||||
### Check Streaming Status
|
||||
|
||||
On parent:
|
||||
```bash
|
||||
curl -s http://localhost:19999/api/v1/info | jq '.hosts'
|
||||
```
|
||||
|
||||
On child:
|
||||
```bash
|
||||
curl -s http://localhost:19999/api/v1/info | jq '.streaming'
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Check Service Status
|
||||
|
||||
```bash
|
||||
sudo systemctl status netdata
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
sudo journalctl -u netdata -f
|
||||
```
|
||||
|
||||
### Child Not Streaming
|
||||
|
||||
1. Verify network connectivity:
|
||||
```bash
|
||||
tailscale ping cryodev-main
|
||||
nc -zv <parent-ip> 19999
|
||||
```
|
||||
|
||||
2. Check API key matches between parent and child
|
||||
|
||||
3. Verify firewall allows port 19999 on parent
|
||||
|
||||
### High Memory Usage
|
||||
|
||||
Adjust history settings in `netdata.conf`:
|
||||
|
||||
```ini
|
||||
[global]
|
||||
history = 1800 # seconds to retain
|
||||
memory mode = ram
|
||||
```
|
||||
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`.
|
||||
117
docs/services/tailscale.md
Normal file
117
docs/services/tailscale.md
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# Tailscale Client
|
||||
|
||||
Tailscale clients connect to the self-hosted Headscale server to join the mesh VPN.
|
||||
|
||||
## References
|
||||
|
||||
- [Tailscale Documentation](https://tailscale.com/kb)
|
||||
- [Headscale Client Setup](https://headscale.net/running-headscale-linux/)
|
||||
|
||||
## Setup
|
||||
|
||||
### Generate Auth Key
|
||||
|
||||
On the Headscale server (cryodev-main):
|
||||
|
||||
```bash
|
||||
sudo headscale preauthkeys create --expiration 99y --reusable --user default
|
||||
```
|
||||
|
||||
### Add to Secrets
|
||||
|
||||
```bash
|
||||
sops hosts/<hostname>/secrets.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
tailscale:
|
||||
auth-key: "your-preauth-key"
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
```nix
|
||||
# In your host configuration
|
||||
{ config, ... }:
|
||||
{
|
||||
sops.secrets."tailscale/auth-key" = { };
|
||||
|
||||
services.tailscale = {
|
||||
enable = true;
|
||||
authKeyFile = config.sops.secrets."tailscale/auth-key".path;
|
||||
extraUpFlags = [
|
||||
"--login-server=https://headscale.cryodev.xyz"
|
||||
];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Check Status
|
||||
|
||||
```bash
|
||||
tailscale status
|
||||
```
|
||||
|
||||
### View IP Address
|
||||
|
||||
```bash
|
||||
tailscale ip
|
||||
```
|
||||
|
||||
### Ping Another Node
|
||||
|
||||
```bash
|
||||
tailscale ping <hostname>
|
||||
```
|
||||
|
||||
### SSH to Another Node
|
||||
|
||||
```bash
|
||||
ssh user@<hostname>
|
||||
# or using Tailscale IP
|
||||
ssh user@100.64.0.X
|
||||
```
|
||||
|
||||
## MagicDNS
|
||||
|
||||
With Headscale's MagicDNS enabled, you can reach nodes by hostname:
|
||||
|
||||
```bash
|
||||
ping cryodev-pi
|
||||
ssh steffen@cryodev-main
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Check Service Status
|
||||
|
||||
```bash
|
||||
sudo systemctl status tailscaled
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
sudo journalctl -u tailscaled -f
|
||||
```
|
||||
|
||||
### Re-authenticate
|
||||
|
||||
If the node is not connecting:
|
||||
|
||||
```bash
|
||||
sudo tailscale up --login-server=https://headscale.cryodev.xyz --force-reauth
|
||||
```
|
||||
|
||||
### Node Not Appearing in Headscale
|
||||
|
||||
Check the auth key is valid:
|
||||
|
||||
```bash
|
||||
# On Headscale server
|
||||
sudo headscale preauthkeys list --user default
|
||||
```
|
||||
|
||||
Verify the login server URL is correct in the client configuration.
|
||||
Loading…
Add table
Add a link
Reference in a new issue