- Nix 94%
- Shell 6%
| docs | ||
| hooks | ||
| modules | ||
| .gitignore | ||
| disk.nix | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
| setup.sh | ||
vm
NixOS framework for dev VMs. Exports the shared QEMU-guest and Home Manager
modules plus the agenix app. Per-VM profiles (host configs, secrets, keys) live
in the companion profiles repo.
Repo purpose
This repo owns:
- shared NixOS module (
nixosModules.qemuGuest) — disk layout + system boilerplate - shared Home Manager module (
homeModules.base) — GPG and SSH base config - the agenix app re-export (
apps.x86_64-linux.agenix)
This repo does not own:
- per-VM NixOS configs (
profilesrepo) - per-VM secrets and SSH keys (
profilesrepo) - host NixOS config and provisioning scripts (
nexusrepo) - editor and other user preferences supplied by a consumer profile
Exported outputs
| Output | Type | Description |
|---|---|---|
nixosModules.qemuGuest |
NixOS module | QEMU guest profile, disk layout (disko), boot, networking, SSH, users, nix settings |
homeModules.base |
Home Manager module | GPG base config, gnupg socket tmpfile, SSH enable |
apps.x86_64-linux.agenix |
app | re-exports the agenix CLI |
nixosModules.qemuGuest
Includes:
disko.nixosModules.disko+./disk.nix— GPT layout, 512M EF00 ESP on/boot, ext4 on/- QEMU guest kernel modules;
nixpkgs.hostPlatformdefaults tox86_64-linux systemd-boot+ EFInetworkmanager(hostname-mode=none)openssh(StreamLocalBindUnlink, no password auth)users.${username}with host SSH key(s) authorized, sudo wheel passwordlessnix.settings.experimental-features,nix.settings.trusted-users,nix.extraOptions = "netrc-file = /etc/nix/netrc"/etc/gitconfigcredential store helper (lets root fetch private HTTPS flake inputs)fix-home-ownershipactivation script — re-chowns the home dir after the nixos-anywhere bootstrapsystem.stateVersion = "25.11"
This module does not enable unfree packages. Consumer profiles that ship
unfree tools (e.g. claude-code, codex) set nixpkgs.config.allowUnfree = true
themselves.
homeModules.base
Includes:
programs.gpg.enable = true+settings.no-autostart = truesystemd.user.tmpfiles.rules— creates the%t/gnupgsocket dir at login (sshd's RemoteForward target)programs.ssh.enable = true+enableDefaultConfig = false
Related repos
profiles— consumer VM configs and profile modules (consumes this repo as a flake input)nexus— host NixOS config and the host-side provisioning scriptssecrets— identity and credential-schema examples consumed byprofiles
Cloning
git clone https://forge.anarch.diy/allod/vm.git
Architecture
- The host machine runs libvirt/QEMU. Dev VMs are the main development environments.
- VMs are accessed over SSH from the host. No shared folders.
- All shared VM configuration (disk layout, system boilerplate, home boilerplate) lives here.
- Per-VM configuration (packages, forge identity, secrets) lives in
profiles. profilespins all flake inputs throughvmviafollows.
Provisioning
Provisioning is host-side and owned by nexus. Its commands are built into the
nexus provisioning-scripts package and installed on the host through
nexus.homeModules.host, so they run from the Nix store — editing a checkout
does not change the installed command until the host is rebuilt.
At a high level, provision-vm-from-host <vm-name>:
- creates the libvirt VM (
new-vm, booting the installer ISO); - runs
nixos-anywhere(disko + install), injecting the pre-generated VM SSH host key via--extra-filesso agenix can decrypt secrets on first boot; - boots the VM from disk and bootstraps it — clones the workspace and runs
nixos-rebuild switch --flake .../profiles#<vm-name>.
VM specs (sizing, networking, repo lists, rebuild policy) come from inventory.
See the nexus docs for the full provisioning and host-key/token lifecycle.
SSH keys
| Key | Location | Purpose |
|---|---|---|
host |
~/.ssh/host on host |
Host identity: SSH to VMs; age decryption of all secrets |
<vm-forge-key> |
~/.ssh/<vm-forge-key> on host |
Dev VM forge SSH key; copied to VM during bootstrap |
<vm-name> host key |
/etc/ssh/<vm-name> on VM |
VM SSH host key; pre-generated, injected by nixos-anywhere before first boot |
Adding a new VM
See the profiles README for the full guide. At the framework level, adding a
new VM requires zero changes to this repo — all per-VM configuration goes in
profiles.