Skip to content

feat(incus-vm): Incus VM support, k3s/template fixes, docs#9

Open
bpmct wants to merge 10 commits into
coder:mainfrom
bpmct:incus-vm-support
Open

feat(incus-vm): Incus VM support, k3s/template fixes, docs#9
bpmct wants to merge 10 commits into
coder:mainfrom
bpmct:incus-vm-support

Conversation

@bpmct
Copy link
Copy Markdown
Member

@bpmct bpmct commented Jun 5, 2026

Closes DEVREL-69

Ports bpmct/coder-nixos#4 to coder/box. Validated end-to-end on a live Incus VM.

What's here

hosts/incus-vm/ — new

Config for running box on any headless NixOS host (Incus VM, ThinkStation, etc.). After nixos-rebuild switch the machine runs a full self-contained Coder deployment: Coder server + PostgreSQL + k3s + sysbox + template-sync.

  • incus-vm.nix — QEMU guest agents + virtio drivers (via upstream incus-virtual-machine.nix), systemd-networkd DHCP on enp5s0, disables the desktop/PipeWire/Avahi stack. Does not disable k3s — hosts opt in via default.nix.
  • default.nix — per-host entrypoint; imports incus-vm.nix + the two runtime files (/etc/nixos/incus.nix, /etc/nixos/coder.nix).
  • README.md — explains what box does, the difference between this and the bpmct/incus-nixos registry template, and a validated step-by-step setup guide (including bootstrap, git-add gotcha, admin first-run).

configuration.nix — two bugs fixed

Found and reproduced on a fresh Incus VM:

  1. coder-init-admin: bare hostname -s fails in a systemd unit because /usr/bin isn't in PATH. Fixed to ${pkgs.nettools}/bin/hostname -s.

  2. coder-template-sync activation script: mkdir -p "$STATE_DIR" runs as root but terraform runs as the coder user. Added chown coder:coder "$STATE_DIR" so terraform can write state.

Also cleans up mangled single-line shell commands in coder-reset and coder-workspace-reaper into readable multiline form.

nixos/k3s-sysbox.nix — add rsync

sysbox-mgr does a preflight check for rsync at startup. If absent it exits immediately and every pod stays stuck in ContainerCreating. Fix is one package in environment.systemPackages.

coderd/templates/k3s-sysbox/main.tf — two fixes

  • local.kubectl: was a hardcoded Nix store path. Replaced with /run/current-system/sw/bin/k3s (stable per-generation symlink).
  • hostAliases: was [{}] (empty object), which Kubernetes rejects. Made conditional on coder_lan_ip being non-empty.

coderd/templates/coder-cli/README.md — new

Was the only template missing a README.

Validation

Tested on a live Incus VM (NixOS 25.11, x86_64):

  • nixos-rebuild switch --flake /etc/nixos-repo#$(hostname -s) --impure — exit 0
  • coder.service, postgresql.service, k3s.service, sysbox-mgr.service, sysbox-fs.service — all active
  • template-sync — pushed all 4 templates (k3s-sysbox, k3s-podman, k3s-dev, coder-cli)
  • Created a k3s-sysbox workspace via API → pod Running with runtimeClassName: sysbox-runc, agent connected

bpmct added 8 commits June 4, 2026 21:20
Ports PR bpmct/coder-nixos#4 to coder/box.

### NixOS fixes

- **`hosts/incus-vm/`** — new template host for any Incus VM provisioned
  by the incus-vm Coder template. `incus-vm.nix` handles QEMU guest
  agents, networkd DHCP on enp5s0, and disables the desktop stack.
  `default.nix` imports incus-vm.nix plus the two runtime files written
  by the provisioner (`/etc/nixos/incus.nix`, `/etc/nixos/coder.nix`).
  `README.md` covers manual setup and how the provisioner flow works.

- **`configuration.nix`** — two bugs fixed during Incus VM testing:
  1. `coder-init-admin`: bare `hostname -s` fails in systemd units (not in
     PATH). Use `${pkgs.nettools}/bin/hostname -s` (fully qualified).
  2. `coder-template-sync` activation script: `mkdir -p "$STATE_DIR"`
     runs as root but terraform runs as `coder`. Add
     `chown coder:coder "$STATE_DIR"` so the coder user can write
     `.terraform` state into that directory.
  Also cleans up the mangled single-line `coder-reset` and
  `coder-workspace-reaper` shell commands into readable multiline form.

- **`nixos/k3s-sysbox.nix`** — add `rsync` to `environment.systemPackages`.
  `sysbox-mgr` checks for rsync at startup; if absent it exits immediately:
  `preflight check failed: rsync is not installed on host` and pods stay
  stuck in ContainerCreating.

### k3s-sysbox template fixes

- **`coderd/templates/k3s-sysbox/main.tf`**:
  - `local.kubectl`: was a hardcoded Nix store path
    (`/nix/store/-k3s-.../bin/k3s`). Store hashes change on every
    nixos-rebuild that touches the k3s derivation. Use
    `/run/current-system/sw/bin/k3s` (stable per-generation symlink).
  - `hostAliases`: was `[{}]` (empty object), which Kubernetes rejects
    with `Invalid value: "": must be a valid IP address`. Now conditional:
    entry only added when `coder_lan_ip` is non-empty.

### Docs

- **`coderd/templates/coder-cli/README.md`** — new; was the only template
  without one.
- nixos/k3s-sysbox.nix: add rsync to systemPackages; sysbox-mgr does a
  preflight check for rsync and exits if absent, leaving pods stuck in
  ContainerCreating
- coderd/templates/k3s-sysbox/main.tf: replace hardcoded Nix store path
  for kubectl with /run/current-system/sw/bin/k3s (stable across rebuilds)
- coderd/templates/k3s-sysbox/main.tf: fix hostAliases — was [{}] (empty
  object) which k8s rejects; now only added when coder_lan_ip is non-empty
…ership

Two bugs found during Incus VM testing:

1. coder-init-admin: bare `hostname -s` fails in systemd units because
   /usr/bin is not in PATH. Use ${pkgs.nettools}/bin/hostname -s.

2. coder-template-sync activation script: `mkdir -p "$STATE_DIR"` runs
   as root but terraform runs as the `coder` user. Add
   `chown coder:coder "$STATE_DIR"` so coder can write .terraform state.

Also cleans up mangled single-line shell in coder-reset and
coder-workspace-reaper into readable multiline form.
nixos/k3s-sysbox.nix: only change is adding rsync to systemPackages
configuration.nix: only changes are the hostname fix, chown STATE_DIR,
and multiline shell reformatting of the mangled single-line curl calls
(no comment banner changes)
@bpmct bpmct requested a review from phorcys420 June 5, 2026 16:44
bpmct added 2 commits June 5, 2026 11:46
- README: step 2 — warn that the copied default.nix imports coder.nix
  (only needed when the VM is also a coder-agent workspace); show how to
  remove it for a pure box host
- README: step 3 — add aarch64 note: set nixpkgs.hostPlatform =
  "aarch64-linux" in default.nix if the VM is ARM; flake defaults to
  x86_64-linux
- README: step 5 — add local.nix creation (copy from local.nix.example,
  set admin creds + LAN IP) before nixos-rebuild switch; this is what
  actually triggers coder-init-admin auto-bootstrap, not a browser wizard
- README: step 6 — rewrite to reflect that coder-init-admin.service
  handles bootstrap automatically if local.nix was set up; browser/CLI
  flow is the fallback, not the primary path
- hosts/incus-vm/default.nix — remove /etc/nixos/coder.nix import (that
  file is for coder-agent workspace VMs, not box hosts); add local.nix
  import with a comment; add nixpkgs.hostPlatform placeholder comment
- hosts/incus-vm/incus-vm.nix — clarify enp5s0 applies to both x86_64
  and aarch64 Incus VMs (confirmed on aarch64)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant