Deployment & operations
Everything here runs from inside the dev shell (nix develop, or direnv allow to auto-load via .envrc), which provides all the tooling. Most tasks are wrapped in the justfile — run just to list them.
First install (bare metal → NixOS)
avocado is installed onto an existing box with nixos-anywhere. This erases both disks and lays down the ZFS layout.
nix run github:nix-community/nixos-anywhere -- \
--flake .#avocado \
--build-on remote \
--sudo \
rithviknishad@avocado.local
--build-on remotebuilds on the x86_64 target, avoiding a cross-build from an arm64 Mac.--sudois used because the source box needs a sudo password (or enable temporary root SSH first).- There’s also a
just installrecipe (targetsroot@avocado,--build-on remote).
Post-install checklist
- SSH back in as
rithviknishad. - Set the UEFI boot order to the new pool’s disk (the
sdaESP). sudo tailscale upto (re)join the tailnet.- Provision the host age key at
/var/lib/sops-nix/key.txtso secrets decrypt. - Set up off-box
zfs sendbackups — the pool has no redundancy. - Deploy the k3s workloads and monitoring stack.
Day-2: change the system
Edit the Nix files, then apply. Two equivalent paths:
From your Mac (remote build + activate):
just deploy # nixos-rebuild switch, building ON the box
just boot # stage for next boot without activating now (safe for risky changes)
just dry # preview what activating would change
just rollback # revert the box to the previous generation
On the box itself (via nh, pointed at /etc/nixos):
nh os switch # build + activate
nh os boot # stage for next boot
nh os build # build only (no sudo)
Sanity-check without deploying:
just eval # evaluate the whole config locally (no build)
just fmt # format all Nix files (nix fmt)
just generations
The just reference
System
| Recipe | Action |
|---|---|
just deploy | build on the box + activate (switch) |
just boot | stage for next boot |
just dry | preview changes (dry-activate) |
just rollback | revert to previous generation |
just eval | evaluate config locally (no build) |
just fmt | format Nix files |
just update [input] | update all flake inputs (or one) |
just generations | list the box’s generations |
just install | fresh nixos-anywhere install (destroys disks) |
Access & logs
| Recipe | Action |
|---|---|
just ssh / just ssh-root | SSH as your user / as root |
just logs [unit] | tail the box’s journal (optionally one unit) |
just kubeconfig | fetch kubeconfig to ~/.kube/avocado (server → avocado) |
Secrets
| Recipe | Action |
|---|---|
just secrets / just secrets-show / just secrets-rekey | edit / view / re-encrypt secrets/avocado.yaml |
just mon-secrets* | same for secrets/monitoring.enc.yaml |
just passwd | generate a SHA-512 password hash |
Monitoring
| Recipe | Action |
|---|---|
just mon-deploy | namespace + helm release + CR layer |
just mon-status | pods/svc/ingress/vmrule in monitoring |
just mon-grafana | port-forward Grafana → :3000 |
just mon-gatus | port-forward Gatus → :8080 |
just mon-logs | port-forward VictoriaLogs → :9428 |
just mon-ntfy-logs | tail the ntfy bridge |
just mon-ntfy-test [topic] | send a test push |
just mon-destroy | remove the CR layer + helm release |
The
justfileconnects over Tailscale MagicDNS (avocado) and disablesknown_hostschecking (NIX_SSHOPTS) so deploys don’t trip over stale host keys.
Deploying the Kubernetes workloads
just kubeconfig # once
kubectl apply -f k8s/sample.yaml # smoke test
kubectl apply -k k8s/immich # after creating k8s/immich/secret.yaml
just mon-deploy # monitoring stack
See Kubernetes and Monitoring for the per-workload details.
Publishing these docs to GitHub Pages
This docs/ folder is a self-contained Jekyll site using the just-the-docs theme (see docs/Gemfile). It’s built and deployed by GitHub Actions (.github/workflows/pages.yml).
- Push the repo to GitHub (it’s the primary now).
- In the GitHub repo: Settings → Pages → Build and deployment.
- Source: GitHub Actions.
- Push any change under
docs/(or run the workflow manually). The action builds the site and publishes it athttps://<user>.github.io/systems.nix/.
Why Actions and not “deploy from a branch”: the classic branch build only ships a small set of built-in themes, so a gem-based theme: just-the-docs needs a real Jekyll build. Mermaid diagrams render natively (configured in docs/_config.yml), and relative .md links resolve via the jekyll-relative-links plugin.
Preview locally:
cd docs
bundle install
bundle exec jekyll serve # http://localhost:4000