Kieran's opinionated (and probably slightly dumb) nix config
1# Deployment
2
3Two deploy paths: **infrastructure** (NixOS config changes) and **application code** (per-service repos).
4
5## Infrastructure
6
7Pushing to `main` triggers `.github/workflows/deploy.yaml` which runs `deploy-rs` over Tailscale to rebuild NixOS on the target machine.
8
9```sh
10# manual deploy
11nix run 'github:serokell/deploy-rs' -- --remote-build --ssh-user kierank .
12```
13
14## Application Code
15
16Each service repo has a minimal workflow calling the reusable `.github/workflows/deploy-service.yml`. On push to `main`:
17
181. Connects to Tailscale (`tag:deploy`)
192. SSHes as the **service user** (e.g., `cachet@terebithia`) via Tailscale SSH
203. Snapshots the SQLite DB (if `db_path` is provided)
214. `git pull` + `bun install --frozen-lockfile` + `sudo systemctl restart`
225. Health check (HTTP URL or systemd status fallback)
236. Auto-rollback on failure (restores DB snapshot + reverts to previous commit)
24
25Per-app workflow — copy and change the `with:` values:
26
27```yaml
28name: Deploy
29on:
30 push:
31 branches: [main]
32 workflow_dispatch:
33jobs:
34 deploy:
35 uses: taciturnaxolotl/dots/.github/workflows/deploy-service.yml@main
36 with:
37 service: cachet
38 health_url: https://cachet.dunkirk.sh/health
39 db_path: /var/lib/cachet/data/cachet.db
40 secrets:
41 TS_OAUTH_CLIENT_ID: ${{ secrets.TS_OAUTH_CLIENT_ID }}
42 TS_OAUTH_SECRET: ${{ secrets.TS_OAUTH_SECRET }}
43```
44
45Omit `health_url` to fall back to `systemctl is-active`. Omit `db_path` for stateless services.
46
47## mkService
48
49`modules/lib/mkService.nix` standardizes service modules. A call to `mkService { ... }` provides:
50
51- Systemd service with initial git clone (subsequent deploys via GitHub Actions)
52- Caddy reverse proxy with TLS via Cloudflare DNS and optional rate limiting
53- Data declarations (`sqlite`, `postgres`, `files`) that feed into automatic backups
54- Dedicated system user with sudo for restart/stop/start (enables per-user Tailscale ACLs)
55- Port conflict detection, security hardening, agenix secrets
56
57### Adding a new service
58
591. Create a module in `modules/nixos/services/`
602. Enable it in `machines/terebithia/default.nix`
613. Add a deploy workflow to the app repo
62
63See `modules/nixos/services/cachet.nix` for a minimal example.
64
65## Machine health checks
66
67Machines with Tailscale enabled automatically expose their hostname for reachability checks in the services manifest via `atelier.machine.tailscaleHost`. This defaults to `networking.hostName` when `services.tailscale.enable` is true.