Skip to content

vmhost

The vmhost host uses incus and guest. knixl writes one file for it. The Nix below is the golden test output, so it is exactly what knixl emits.

hosts/vmhost.kdl
host "vmhost" {
system "x86_64-linux"
incus {
ui
https-address-from-interface "tailscale0"
firewall {
trust-interface "incusbr0"
open-api-on "tailscale0"
}
storage-pool "default" driver="zfs" source="rpool/incus"
network "incusbr0" type="bridge" ipv4="auto" nat="true" ipv6="fd42::1/64" ipv6-nat="true"
profile "default" pool="default" network="incusbr0"
}
guest "sandbox" {
autostart #true
private-network #true
host-address "10.100.0.1"
local-address "10.100.0.2"
bind-mount "/data" host-path="/srv/sandbox" read-only=#true
config {
os {
state-version "25.11"
}
openssh {
permit-root "no"
}
}
}
}
generated/hosts/vmhost.nix
# Generated by knixl 1.5.2 from hosts/vmhost.kdl
# Do NOT edit. Regenerate from the KDL source.
# Overrides: add a sibling module and use lib.mkForce / lib.mkAfter.
{
config,
lib,
pkgs,
...
}:
{
nixpkgs.hostPlatform = "x86_64-linux";
networking.hostName = "vmhost";
virtualisation.incus.enable = true;
virtualisation.incus.ui.enable = true;
virtualisation.incus.preseed.storage_pools = [
{
config = {
source = "rpool/incus";
};
driver = "zfs";
name = "default";
}
];
virtualisation.incus.preseed.networks = [
{
config = {
"ipv4.address" = "auto";
"ipv4.nat" = "true";
"ipv6.address" = "fd42::1/64";
"ipv6.nat" = "true";
};
name = "incusbr0";
type = "bridge";
}
];
virtualisation.incus.preseed.profiles = [
{
devices = {
eth0 = {
name = "eth0";
network = "incusbr0";
type = "nic";
};
root = {
path = "/";
pool = "default";
type = "disk";
};
};
name = "default";
}
];
systemd.services."incus-https-address" = {
after = [
"incus.service"
"network-online.target"
];
description = "Bind the Incus HTTPS API to the tailscale0 address";
path = [
pkgs.iproute2
pkgs.gawk
pkgs.coreutils
pkgs.incus
];
requires = [
"incus.service"
];
script = ''
addr=$(ip -4 -o addr show dev tailscale0 scope global | awk '{print $4}' | cut -d/ -f1 | head -n1)
if [ -n "$addr" ]; then
incus config set core.https_address "$addr:8443"
fi
'';
serviceConfig = {
Type = "oneshot";
};
wantedBy = [
"multi-user.target"
];
wants = [
"network-online.target"
];
};
networking.firewall.trustedInterfaces = [
"incusbr0"
];
networking.firewall.interfaces."tailscale0".allowedTCPPorts = [
8443
];
containers."sandbox".autoStart = true;
containers."sandbox".privateNetwork = true;
containers."sandbox".hostAddress = "10.100.0.1";
containers."sandbox".localAddress = "10.100.0.2";
containers."sandbox".bindMounts."/data" = {
hostPath = "/srv/sandbox";
isReadOnly = true;
};
containers."sandbox".config.system.stateVersion = "25.11";
containers."sandbox".config.services.openssh.enable = true;
containers."sandbox".config.services.openssh.settings.PasswordAuthentication = false;
containers."sandbox".config.services.openssh.settings.KbdInteractiveAuthentication = false;
containers."sandbox".config.services.openssh.settings.PermitRootLogin = "no";
}