← Back to list

vm-provision
by abl030
⭐ 1🍴 2📅 Jan 24, 2026
SKILL.md
name: vm-provision description: Provision and integrate new VMs into the NixOS Proxmox fleet
VM Provisioning Skill
This skill guides you through creating and integrating new VMs into the NixOS homelab fleet on Proxmox.
Overview
The VM automation system uses:
- Template 9002: Ubuntu cloud image with UEFI for initial bootstrap
- nixos-anywhere: Two-phase deployment (kexec → disko+install)
- Cloud-init: SSH key injection for initial access
- Disko: Declarative disk partitioning
Workflow
Step 1: Define the VM
Add entry to vms/definitions.nix under managed:
managed = {
my-vm = {
vmid = 111; # Unique, check vmidRanges (100-199 for production)
cores = 4;
memory = 8192; # MB
disk = "32G";
storage = "nvmeprom";
nixosConfig = "my-vm"; # Must match hosts/{name}
purpose = "Description of VM purpose";
services = ["service1" "service2"];
};
};
Step 2: Create Host Configuration
Create hosts/{name}/ with four files:
configuration.nix:
{pkgs, inputs, ...}: {
imports = [
inputs.disko.nixosModules.disko
./disko.nix
./hardware-configuration.nix
];
boot = {
loader.systemd-boot.enable = true;
loader.efi.canTouchEfiVariables = true;
};
homelab = {
ssh = {
enable = true;
secure = false; # or true for password auth disabled
};
tailscale.enable = true;
nixCaches = {
enable = true;
profile = "internal";
};
};
services.qemuGuest.enable = true;
system.stateVersion = "25.05";
}
disko.nix (standard for all VMs):
{
disko.devices = {
disk = {
main = {
type = "disk";
device = "/dev/sda";
content = {
type = "gpt";
partitions = {
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = ["umask=0077"];
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
};
};
}
hardware-configuration.nix:
{config, lib, modulesPath, ...}: {
imports = [(modulesPath + "/profiles/qemu-guest.nix")];
boot.initrd.availableKernelModules = ["ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod"];
boot.initrd.kernelModules = [];
boot.kernelModules = [];
boot.extraModulePackages = [];
# Filesystem definitions handled by disko.nix
swapDevices = [];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
home.nix:
{...}: {
imports = [
../../home/home.nix
../../home/utils/common.nix
];
}
Step 3: Add to hosts.nix
Add placeholder entry to hosts.nix:
my-vm = {
configurationFile = ./hosts/my-vm/configuration.nix;
homeFile = ./hosts/my-vm/home.nix;
user = "abl030";
homeDirectory = "/home/abl030";
hostname = "my-vm";
sshAlias = "my-vm";
sshKeyName = "ssh_key_abl030";
publicKey = "ssh-ed25519 PLACEHOLDER_KEY_WILL_BE_ADDED_DURING_PROVISIONING";
authorizedKeys = masterKeys;
};
Step 4: Provision
nix run .#provision-vm my-vm
This will:
- Clone template 9002
- Configure resources (CPU, RAM, disk)
- Inject SSH keys via cloud-init
- Install NixOS via nixos-anywhere (two-phase)
- Reboot and verify SSH access
Step 5: Post-Provision (Fleet Integration)
After provisioning completes, note the IP address and run:
nix run .#post-provision-vm my-vm <IP> <VMID>
This will:
- Extract SSH host key from VM
- Update hosts.nix with real public key
- Convert SSH key to age key
- Update secrets/.sops.yaml with age key
- Re-encrypt all secrets with new key
- Commit changes to git
Step 6: Deploy with Secrets
nixos-rebuild switch --flake .#my-vm --target-host my-vm
Key Files
| File | Purpose |
|---|---|
vms/definitions.nix | VM specs (source of truth) |
vms/provision.sh | Main provisioning script |
vms/post-provision.sh | Fleet integration |
vms/proxmox-ops.sh | Proxmox SSH wrapper |
hosts.nix | Host definitions with SSH keys |
secrets/.sops.yaml | Age keys for secrets |
Safety Notes
- Imported VMs (in
vms/definitions.nixunderimported) havereadonly = true- automation will refuse to touch them - VMID conflicts are checked before provisioning
- Confirmation prompt required before creating VM
- SSH access is via
abl030user, not root
Troubleshooting
- IP changes during provisioning: Normal - the script handles this automatically via MAC/ARP lookup
- SSH host key verification fails: Run
ssh-keygen -R <ip>to clear old key - sops updatekeys fails: Ensure you're using
--config secrets/.sops.yaml
Score
Total Score
50/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
Reviews
💬
Reviews coming soon