diff options
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/default.nix | 3 | ||||
| -rw-r--r-- | modules/incus.nix | 150 |
2 files changed, 153 insertions, 0 deletions
diff --git a/modules/default.nix b/modules/default.nix index 04618ac..5599639 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -1,4 +1,7 @@ { ... }: { + imports = [ + ./incus.nix + ]; } diff --git a/modules/incus.nix b/modules/incus.nix new file mode 100644 index 0000000..3d64432 --- /dev/null +++ b/modules/incus.nix @@ -0,0 +1,150 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + # qemu 9.1.2 no longer supports strings being passed instead of some + # integer parameters. incus already has the fix, but it hasn't made it + # into a release yet. + # see: https://github.com/lxc/incus/issues/1522 + incusPatch = pkgs.fetchpatch { + name = "1531.patch"; + url = "https://github.com/lxc/incus/pull/1531.patch"; + sha256 = "sha256-tM/+JRH0OwR3bM8gk3yNo9SSAEMqpS2HP+OzooV3DJY="; + }; + incus = pkgs.incus.overrideAttrs (attrs: { + patches = (attrs.patches or [ ]) ++ [ incusPatch ]; + }); + + toYAML = lib.generators.toYAML { }; + + cloudInitConfiguration = { + users = [ + { + name = "admin"; + groups = "users"; + sudo = "ALL=(ALL) NOPASSWD:ALL"; + plain_text_passwd = "example"; + lock_passwd = false; + } + ]; + + # ssh configuration + allow_public_ssh_keys = true; + disable_root = true; + packages = [ "openssh-server" ]; + runcmd = [ + [ + "systemctl" + "enable" + "ssh.service" + ] + ]; + }; +in +{ + networking.firewall = { + # needed so that the nixos firewall does not block + # DHCP+DNS requests from incus, and to prevent conflicts + # between the two firewalls. + trustedInterfaces = [ "incusbr0" ]; + allowedTCPPorts = [ 23 ]; + }; + # needed so inscus instances can connect to the proxy. + boot.kernelModules = [ "br_netfilter" ]; + virtualisation.incus = { + enable = true; + package = incus; + preseed = { + networks = [ + { + config = { + "ipv4.address" = "10.0.100.1/24"; + "ipv4.nat" = "true"; + }; + name = "incusbr0"; + type = "bridge"; + } + ]; + profiles = [ + # this default profile gets applied to all + # new instances without an explicitly set profile. + { + name = "default"; + config = { }; + devices = { + eth0 = { + name = "eth0"; + network = "incusbr0"; + type = "nic"; + }; + root = { + path = "/"; + pool = "default"; + size = "35GiB"; + type = "disk"; + }; + }; + } + # this profile is the one we want to apply to an ubuntu example vm. + # it is provisioned with a static ipv4 (for nat-ted proxy) + # and cloud-init configuration + { + name = "vm-1"; + # config applied to new instances, + # this is how we can best control + # vm provisioning semi-declaratively. + # for options, see: https://linuxcontainers.org/incus/docs/main/reference/instance_options/ + config = { + # `vendor` is usually for defaults, but it doesn't actually matter here. + # NOTE: cloud-init requires either the incus-agent to be running, + # or that the image is a special cloud image. i.e. `images:ubuntu/22.04/cloud`. + "cloud-init.vendor-data" = '' + #cloud-config + ${toYAML cloudInitConfiguration} + ''; + }; + devices = { + eth0 = { + name = "eth0"; + network = "incusbr0"; + type = "nic"; + + # this is necessary for our nat proxy configuration. + # see: https://linuxcontainers.org/incus/docs/main/reference/devices_proxy/#nat-mode + "ipv4.address" = "10.0.100.123"; + }; + proxy = { + type = "proxy"; + listen = "tcp:127.0.0.1:2222"; + connect = "tcp:0.0.0.0:22"; + nat = true; + }; + root = { + path = "/"; + pool = "default"; + size = "35GiB"; + type = "disk"; + }; + }; + } + ]; + storage_pools = [ + { + config = { + source = "/var/lib/incus/storage-pools/default"; + }; + driver = "dir"; + name = "default"; + } + ]; + }; + }; + + # `incus-admin` essentially gives you root access anyway, + # let users in `wheel` use it freely. + users.groups."incus-admin".members = config.users.groups."wheel".members; +} |
