h0ffmann/skills
Star
Cite

APA

h0ffmann. (2026). skills [Computer software]. https://github.com/h0ffmann/skills

BibTeX

@software{h0ffmann_skills_2026,
  author = {h0ffmann},
  title = {skills},
  year = {2026},
  url = {https://github.com/h0ffmann/skills},
  license = {MPL-2.0},
  note = {ORCID 0009-0009-1056-7661}
}

Source: CITATION.cff

nixos-vps

Change the NixOS configuration of a small live VPS that a merge to main deploys (deploy-rs with magic rollback). Use for modules, services, nginx, ACME, users, the resource budget, flake updates and the deploy itself. Never deploys.

nixnixosdeploy

← Back to all skills · SKILL.md on GitHub

# 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.