SKILL.md
# nixos-vps
The VPS is live, small and remote. **A merge to `main` is the deploy.** Thus each PR is a change
to production. An agent works in a clone, opens a PR and never deploys.
## Hard rules
- **Never run** `nixos-rebuild`, `deploy`, `just deploy` or a `switch`. The merge deploys.
- **Never tighten** the services that keep the box reachable: `sshd`, `qemu-guest-agent` and
`cloud-init`. A bad sandbox there locks everyone out.
- **Secrets stay on the box** (for example `/var/lib/<name>-secrets/*.env`, mode 0600). Never in
the repository, never in the Nix store.
- **`nix flake update` goes in its own PR**, with the closure difference in the body.
- **Nothing unfree.** `allowUnfree` stays off.
- **A risky switch** (a new kernel, a new bootloader, a large service) waits for a snapshot of
the VPS that the owner makes.
## The resource budget
Judge each change by what it adds to the system closure and to memory.
- No GUI, no fonts, no display server.
- Give each new service `MemoryMax` and `CPUQuota`.
- Compare closures before and after: `nix run nixpkgs#dix -- <old> <new>`.
- Put large build tools on the builder only. Use `allowedReferences = [ ]` for a static site
derivation, so the build tools never reach the box.
## Steps
1. Read `AGENTS.md`, `flake.nix`, `configuration.nix` and the module that you change.
2. Make the change as a module with an `enable` option. With the option off, the system is
unchanged.
3. Evaluate: `nix flake check --no-build --no-update-lock-file`.
4. Read one option: `nix eval .#nixosConfigurations.<host>.config.<path>`.
5. Build the system: `nix build .#nixosConfigurations.<host>.config.system.build.toplevel`.
6. Test a service in a VM check (`pkgs.testers.nixosTest`) when it has state or a port.
7. Run the gate: `nixpkgs-fmt --check`, `statix check`, `deadnix --fail`, `shellcheck`.
8. Open the PR. State what the merge changes on the box, and the closure difference.
## Rollback
Say the rollback in the PR of each risky change:
1. Revert the PR. The merge of the revert deploys the old system.
2. On the box: `nixos-rebuild switch --rollback`, or select the old generation in GRUB.
3. Remove state that the change left in `/var/lib/<name>`.
4. Last: restore the snapshot of the VPS.
## A service
Use the `systemd-hardening` skill for each new `systemd.services.<name>`. Bind the service to
loopback when nginx is in front of it. Open a firewall port only when the owner asks for it.