summaryrefslogtreecommitdiffstats
path: root/nixos/modules
diff options
context:
space:
mode:
authorLily Foster <lily@lily.flowers>2023-11-03 09:42:24 -0400
committerGitHub <noreply@github.com>2023-11-03 09:42:24 -0400
commit5c5d7300674d295f18f52e3c73a8dbfc9886c29b (patch)
tree8a36e5d552717b28d9d4a4714ac81395570b0f07 /nixos/modules
parent5e57c1a3a7b6434a821e25cd4198c0195c19707d (diff)
parentf12af77bd8af86a2b2709dc9c14256e1a2c3aca1 (diff)
Merge pull request #262347 from adamcstephens/incus/module
nixos/incus: init module and tests
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/virtualisation/incus.nix236
2 files changed, 237 insertions, 0 deletions
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 2a6ca202024b..9a1bc0450d26 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -1506,6 +1506,7 @@
./virtualisation/docker.nix
./virtualisation/ecs-agent.nix
./virtualisation/hyperv-guest.nix
+ ./virtualisation/incus.nix
./virtualisation/kvmgt.nix
./virtualisation/libvirtd.nix
./virtualisation/lxc.nix
diff --git a/nixos/modules/virtualisation/incus.nix b/nixos/modules/virtualisation/incus.nix
new file mode 100644
index 000000000000..3a4f0d7157a0
--- /dev/null
+++ b/nixos/modules/virtualisation/incus.nix
@@ -0,0 +1,236 @@
+{ config, lib, pkgs, ... }:
+
+let
+ cfg = config.virtualisation.incus;
+ preseedFormat = pkgs.formats.yaml { };
+in
+{
+ meta.maintainers = [ lib.maintainers.adamcstephens ];
+
+ options = {
+ virtualisation.incus = {
+ enable = lib.mkEnableOption (lib.mdDoc ''
+ incusd, a daemon that manages containers and virtual machines.
+
+ Users in the "incus-admin" group can interact with
+ the daemon (e.g. to start or stop containers) using the
+ {command}`incus` command line tool, among others.
+ '');
+
+ package = lib.mkPackageOptionMD pkgs "incus" { };
+
+ lxcPackage = lib.mkPackageOptionMD pkgs "lxc" { };
+
+ preseed = lib.mkOption {
+ type = lib.types.nullOr (
+ lib.types.submodule { freeformType = preseedFormat.type; }
+ );
+
+ default = null;
+
+ description = lib.mdDoc ''
+ Configuration for Incus preseed, see
+ <https://linuxcontainers.org/incus/docs/main/howto/initialize/#non-interactive-configuration>
+ for supported values.
+
+ Changes to this will be re-applied to Incus which will overwrite existing entities or create missing ones,
+ but entities will *not* be removed by preseed.
+ '';
+
+ example = {
+ networks = [
+ {
+ name = "incusbr0";
+ type = "bridge";
+ config = {
+ "ipv4.address" = "10.0.100.1/24";
+ "ipv4.nat" = "true";
+ };
+ }
+ ];
+ profiles = [
+ {
+ name = "default";
+ devices = {
+ eth0 = {
+ name = "eth0";
+ network = "incusbr0";
+ type = "nic";
+ };
+ root = {
+ path = "/";
+ pool = "default";
+ size = "35GiB";
+ type = "disk";
+ };
+ };
+ }
+ ];
+ storage_pools = [
+ {
+ name = "default";
+ driver = "dir";
+ config = {
+ source = "/var/lib/incus/storage-pools/default";
+ };
+ }
+ ];
+ };
+ };
+
+ socketActivation = lib.mkEnableOption (
+ lib.mdDoc ''
+ socket-activation for starting incus.service. Enabling this option
+ will stop incus.service from starting automatically on boot.
+ ''
+ );
+
+ startTimeout = lib.mkOption {
+ type = lib.types.ints.unsigned;
+ default = 600;
+ apply = toString;
+ description = lib.mdDoc ''
+ Time to wait (in seconds) for incusd to become ready to process requests.
+ If incusd does not reply within the configured time, `incus.service` will be
+ considered failed and systemd will attempt to restart it.
+ '';
+ };
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ # https://github.com/lxc/incus/blob/f145309929f849b9951658ad2ba3b8f10cbe69d1/doc/reference/server_settings.md
+ boot.kernel.sysctl = {
+ "fs.aio-max-nr" = lib.mkDefault 524288;
+ "fs.inotify.max_queued_events" = lib.mkDefault 1048576;
+ "fs.inotify.max_user_instances" = lib.mkOverride 1050 1048576; # override in case conflict nixos/modules/services/x11/xserver.nix
+ "fs.inotify.max_user_watches" = lib.mkOverride 1050 1048576; # override in case conflict nixos/modules/services/x11/xserver.nix
+ "kernel.dmesg_restrict" = lib.mkDefault 1;
+ "kernel.keys.maxbytes" = lib.mkDefault 2000000;
+ "kernel.keys.maxkeys" = lib.mkDefault 2000;
+ "net.core.bpf_jit_limit" = lib.mkDefault 1000000000;
+ "net.ipv4.neigh.default.gc_thresh3" = lib.mkDefault 8192;
+ "net.ipv6.neigh.default.gc_thresh3" = lib.mkDefault 8192;
+ # vm.max_map_count is set higher in nixos/modules/config/sysctl.nix
+ };
+
+ boot.kernelModules = [
+ "veth"
+ "xt_comment"
+ "xt_CHECKSUM"
+ "xt_MASQUERADE"
+ "vhost_vsock"
+ ] ++ lib.optionals (!config.networking.nftables.enable) [ "iptable_mangle" ];
+
+ environment.systemPackages = [ cfg.package ];
+
+ # Note: the following options are also declared in virtualisation.lxc, but
+ # the latter can't be simply enabled to reuse the formers, because it
+ # does a bunch of unrelated things.
+ systemd.tmpfiles.rules = [ "d /var/lib/lxc/rootfs 0755 root root -" ];
+
+ security.apparmor = {
+ packages = [ cfg.lxcPackage ];
+ policies = {
+ "bin.lxc-start".profile = ''
+ include ${cfg.lxcPackage}/etc/apparmor.d/usr.bin.lxc-start
+ '';
+ "lxc-containers".profile = ''
+ include ${cfg.lxcPackage}/etc/apparmor.d/lxc-containers
+ '';
+ };
+ };
+
+ systemd.services.incus = {
+ description = "Incus Container and Virtual Machine Management Daemon";
+
+ wantedBy = lib.mkIf (!cfg.socketActivation) [ "multi-user.target" ];
+ after = [
+ "network-online.target"
+ "lxcfs.service"
+ ] ++ (lib.optional cfg.socketActivation "incus.socket");
+ requires = [
+ "lxcfs.service"
+ ] ++ (lib.optional cfg.socketActivation "incus.socket");
+ wants = [
+ "network-online.target"
+ ];
+
+ path = lib.mkIf config.boot.zfs.enabled [ config.boot.zfs.package ];
+
+ environment = {
+ # Override Path to the LXC template configuration directory
+ INCUS_LXC_TEMPLATE_CONFIG = "${pkgs.lxcfs}/share/lxc/config";
+ };
+
+ serviceConfig = {
+ ExecStart = "${cfg.package}/bin/incusd --group incus-admin";
+ ExecStartPost = "${cfg.package}/bin/incusd waitready --timeout=${cfg.startTimeout}";
+ ExecStop = "${cfg.package}/bin/incus admin shutdown";
+
+ KillMode = "process"; # when stopping, leave the containers alone
+ Delegate = "yes";
+ LimitMEMLOCK = "infinity";
+ LimitNOFILE = "1048576";
+ LimitNPROC = "infinity";
+ TasksMax = "infinity";
+
+ Restart = "on-failure";
+ TimeoutStartSec = "${cfg.startTimeout}s";
+ TimeoutStopSec = "30s";
+ };
+ };
+
+ systemd.sockets.incus = lib.mkIf cfg.socketActivation {
+ description = "Incus UNIX socket";
+ wantedBy = [ "sockets.target" ];
+
+ socketConfig = {
+ ListenStream = "/var/lib/incus/unix.socket";
+ SocketMode = "0660";
+ SocketGroup = "incus-admin";
+ Service = "incus.service";
+ };
+ };
+
+ systemd.services.incus-preseed = lib.mkIf (cfg.preseed != null) {
+ description = "Incus initialization with preseed file";
+
+ wantedBy = ["incus.service"];
+ after = ["incus.service"];
+ bindsTo = ["incus.service"];
+ partOf = ["incus.service"];
+
+ script = ''
+ ${cfg.package}/bin/incus admin init --preseed <${
+ preseedFormat.generate "incus-preseed.yaml" cfg.preseed
+ }
+ '';
+
+ serviceConfig = {
+ Type = "oneshot";
+ RemainAfterExit = true;
+ };
+ };
+
+ users.groups.incus-admin = { };
+
+ users.users.root = {
+ # match documented default ranges https://linuxcontainers.org/incus/docs/main/userns-idmap/#allowed-ranges
+ subUidRanges = [
+ {
+ startUid = 1000000;
+ count = 1000000000;
+ }
+ ];
+ subGidRanges = [
+ {
+ startGid = 1000000;
+ count = 1000000000;
+ }
+ ];
+ };
+
+ virtualisation.lxc.lxcfs.enable = true;
+ };
+}