M
Justfile
+14,
-10
1@@ -1,20 +1,24 @@
2-# Fleet workflow (README.md, docs/fleet-migration-plan.md). Run inside
3-# `nix develop`.
4+# Fleet workflow (README.md, docs/fleet-migration-plan.md). Runs from any
5+# shell: the tools only the dev shell has (colmena, nvd, nixos-anywhere) are
6+# called through `dev`; jq, ssh, nix and `secrets` come from the system.
7
8 # The `secrets` store (age-encrypted, one file per secret).
9 export SECRETS_DIR := env("SECRETS_DIR", home_directory() / "projects/data")
10
11+# Runs a command from this flake's dev shell (the pinned colmena 0.5.0 etc.).
12+dev := "nix develop " + quote(justfile_directory()) + " --command"
13+
14 # List recipes.
15 default:
16 @just --list
17
18 # Evaluate every host (fast sanity check; no builds).
19 eval:
20- colmena eval -E '{ nodes, ... }: builtins.mapAttrs (n: v: v.config.system.build.toplevel.drvPath) nodes'
21+ {{ dev }} colmena eval -E '{ nodes, ... }: builtins.mapAttrs (n: v: v.config.system.build.toplevel.drvPath) nodes'
22
23 # Build host systems without deploying (all hosts, or one).
24 build HOST="":
25- colmena build {{ if HOST == "" { "" } else { "--on " + HOST } }}
26+ {{ dev }} colmena build {{ if HOST == "" { "" } else { "--on " + HOST } }}
27
28 # Builds HOST's system, fetches the one it runs, and compares them with nvd.
29 # "identical" means a deploy would change nothing.
30@@ -31,14 +35,14 @@ diff-host HOST:
31 exit 0
32 fi
33 nix copy --no-check-sigs --from "ssh-ng://root@{{ HOST }}" "$running"
34- nvd diff "$running" "$new"
35+ {{ dev }} nvd diff "$running" "$new"
36
37 # Refuses to start if any secret HOST declares is missing from the store.
38 # Extra args go to `colmena apply`: `just deploy HOST dry-activate`,
39 # `just deploy HOST --reboot`.
40 # Deploy HOST with Colmena (build, copy, upload keys, switch).
41 deploy HOST *ARGS: (check-secrets HOST)
42- colmena apply {{ ARGS }} --on {{ HOST }}
43+ {{ dev }} colmena apply {{ ARGS }} --on {{ HOST }}
44
45 # Every host with a role from PROJECT ("moods" or "sovrn") gets the new
46 # version; the lock bump is the deploy log, so commit it afterwards.
47@@ -50,7 +54,7 @@ deploy-project PROJECT *ARGS:
48 hosts="$(jq -r --arg p "{{ PROJECT }}" '[to_entries[] | select(any(.value.roles[]?; . == $p or startswith($p + "-"))) | .key] | join(",")' hosts.json)"
49 [ -n "$hosts" ] || { echo "no host in hosts.json runs a {{ PROJECT }} role" >&2; exit 1; }
50 for h in ${hosts//,/ }; do just check-secrets "$h"; done
51- colmena apply {{ ARGS }} --on "$hosts"
52+ {{ dev }} colmena apply {{ ARGS }} --on "$hosts"
53 echo "deployed {{ PROJECT }} $(jq -r '.nodes["{{ PROJECT }}"].locked.rev' flake.lock) to $hosts; commit flake.lock"
54
55 # Covers every project's secrets: reads the `secrets decrypt <path>` key
56@@ -111,8 +115,8 @@ new-host IP HOSTNAME PROVIDER ROLES:
57 [[ "$HOST" =~ ^[a-z0-9-]+(\.[a-z0-9-]+)+$ ]] || fail "HOSTNAME must be a fully qualified lowercase name, got: $HOST"
58 case "$PROVIDER" in hetzner|netcup) ;; *) fail "PROVIDER must be hetzner or netcup, got: $PROVIDER" ;; esac
59 [[ "$ROLES" =~ ^[a-z0-9-]+(,[a-z0-9-]+)*$ ]] || fail "ROLES must be comma-separated role names, got: $ROLES"
60- for bin in nixos-anywhere secrets jq ssh ssh-keygen ssh-copy-id; do
61- command -v "$bin" >/dev/null || fail "$bin not on PATH (run inside nix develop)"
62+ for bin in secrets jq ssh ssh-keygen ssh-copy-id; do
63+ command -v "$bin" >/dev/null || fail "$bin not on PATH"
64 done
65 if jq -e --arg h "$HOST" '.[$h].layout == "legacy"' "$INVENTORY" >/dev/null; then
66 fail "$HOST is a legacy-layout host; new-host installs the standard layout (see plan 2.8)"
67@@ -206,7 +210,7 @@ new-host IP HOSTNAME PROVIDER ROLES:
68 jj st >/dev/null 2>&1 || true
69
70 # 4. Install (reboots into NixOS at the end).
71- nixos-anywhere --flake ".#$HOST" -i "$SSH_KEY" --extra-files "$tmp/extra" --target-host "root@$IP"
72+ {{ dev }} nixos-anywhere --flake ".#$HOST" -i "$SSH_KEY" --extra-files "$tmp/extra" --target-host "root@$IP"
73
74 # 5. Verify the pinned key, then trust it.
75 echo "$HOST,$IP $PUB" > "$tmp/known_hosts"
+1,
-1
1@@ -22,7 +22,7 @@ The fleet: every NixOS host, deployed with [Colmena](https://github.com/zhaofeng
2
3 ## Workflow
4
5-Everything runs inside `nix develop` (colmena, nvd, nixos-anywhere, just). `secrets` (the age-encrypted store CLI) must be on `PATH`, with `SECRETS_DIR` (default `~/projects/data`).
6+The recipes run from any shell: the tools only the dev shell provides (colmena, nvd, nixos-anywhere) are called through `nix develop --command` inside the `Justfile`. On `PATH` you need `just`, `nix`, `jq`, `ssh`/`ssh-keygen`/`ssh-copy-id`, and `secrets` (the age-encrypted store CLI) with `SECRETS_DIR` (default `~/projects/data`). `nix develop` is only for running those tools by hand.
7
8 | Command | What |
9 | --- | --- |