dxvk_1: fix build compatibility with GCC 14 (#360918)
[NixPkgs.git] / nixos / modules / virtualisation / lxd.nix
blob24d9701b06d626762b9abf10c11ebab911f3c42b
1 # Systemd services for lxd.
4   config,
5   lib,
6   pkgs,
7   ...
8 }:
10 let
11   cfg = config.virtualisation.lxd;
12   preseedFormat = pkgs.formats.yaml { };
15   imports = [
16     (lib.mkRemovedOptionModule [
17       "virtualisation"
18       "lxd"
19       "zfsPackage"
20     ] "Override zfs in an overlay instead to override it globally")
21   ];
23   options = {
24     virtualisation.lxd = {
25       enable = lib.mkOption {
26         type = lib.types.bool;
27         default = false;
28         description = ''
29           This option enables lxd, a daemon that manages
30           containers. Users in the "lxd" group can interact with
31           the daemon (e.g. to start or stop containers) using the
32           {command}`lxc` command line tool, among others.
34           Most of the time, you'll also want to start lxcfs, so
35           that containers can "see" the limits:
36           ```
37           virtualisation.lxc.lxcfs.enable = true;
38           ```
39         '';
40       };
42       package = lib.mkPackageOption pkgs "lxd-lts" { };
44       lxcPackage = lib.mkOption {
45         type = lib.types.package;
46         default = config.virtualisation.lxc.package;
47         defaultText = lib.literalExpression "config.virtualisation.lxc.package";
48         description = "The lxc package to use.";
49       };
51       zfsSupport = lib.mkOption {
52         type = lib.types.bool;
53         default = config.boot.zfs.enabled;
54         defaultText = lib.literalExpression "config.boot.zfs.enabled";
55         description = ''
56           Enables lxd to use zfs as a storage for containers.
58           This option is enabled by default if a zfs pool is configured
59           with nixos.
60         '';
61       };
63       recommendedSysctlSettings = lib.mkOption {
64         type = lib.types.bool;
65         default = false;
66         description = ''
67           Enables various settings to avoid common pitfalls when
68           running containers requiring many file operations.
69           Fixes errors like "Too many open files" or
70           "neighbour: ndisc_cache: neighbor table overflow!".
71           See https://lxd.readthedocs.io/en/latest/production-setup/
72           for details.
73         '';
74       };
76       preseed = lib.mkOption {
77         type = lib.types.nullOr (
78           lib.types.submodule {
79             freeformType = preseedFormat.type;
80           }
81         );
83         default = null;
85         description = ''
86           Configuration for LXD preseed, see
87           <https://documentation.ubuntu.com/lxd/en/latest/howto/initialize/#initialize-preseed>
88           for supported values.
90           Changes to this will be re-applied to LXD which will overwrite existing entities or create missing ones,
91           but entities will *not* be removed by preseed.
92         '';
94         example = lib.literalExpression ''
95           {
96             networks = [
97               {
98                 name = "lxdbr0";
99                 type = "bridge";
100                 config = {
101                   "ipv4.address" = "10.0.100.1/24";
102                   "ipv4.nat" = "true";
103                 };
104               }
105             ];
106             profiles = [
107               {
108                 name = "default";
109                 devices = {
110                   eth0 = {
111                     name = "eth0";
112                     network = "lxdbr0";
113                     type = "nic";
114                   };
115                   root = {
116                     path = "/";
117                     pool = "default";
118                     size = "35GiB";
119                     type = "disk";
120                   };
121                 };
122               }
123             ];
124             storage_pools = [
125               {
126                 name = "default";
127                 driver = "dir";
128                 config = {
129                   source = "/var/lib/lxd/storage-pools/default";
130                 };
131               }
132             ];
133           }
134         '';
135       };
137       startTimeout = lib.mkOption {
138         type = lib.types.int;
139         default = 600;
140         apply = toString;
141         description = ''
142           Time to wait (in seconds) for LXD to become ready to process requests.
143           If LXD does not reply within the configured time, lxd.service will be
144           considered failed and systemd will attempt to restart it.
145         '';
146       };
148       ui = {
149         enable = lib.mkEnableOption "(experimental) LXD UI";
151         package = lib.mkPackageOption pkgs [ "lxd-ui" ] { };
152       };
153     };
154   };
156   ###### implementation
157   config = lib.mkIf cfg.enable {
158     environment.systemPackages = [ cfg.package ];
160     # Note: the following options are also declared in virtualisation.lxc, but
161     # the latter can't be simply enabled to reuse the formers, because it
162     # does a bunch of unrelated things.
163     systemd.tmpfiles.rules = [ "d /var/lib/lxc/rootfs 0755 root root -" ];
165     security.apparmor = {
166       packages = [ cfg.lxcPackage ];
167       policies = {
168         "bin.lxc-start".profile = ''
169           include ${cfg.lxcPackage}/etc/apparmor.d/usr.bin.lxc-start
170         '';
171         "lxc-containers".profile = ''
172           include ${cfg.lxcPackage}/etc/apparmor.d/lxc-containers
173         '';
174       };
175     };
177     systemd.sockets.lxd = {
178       description = "LXD UNIX socket";
179       wantedBy = [ "sockets.target" ];
181       socketConfig = {
182         ListenStream = "/var/lib/lxd/unix.socket";
183         SocketMode = "0660";
184         SocketGroup = "lxd";
185         Service = "lxd.service";
186       };
187     };
189     systemd.services.lxd = {
190       description = "LXD Container Management Daemon";
192       wantedBy = [ "multi-user.target" ];
193       after = [
194         "network-online.target"
195         (lib.mkIf config.virtualisation.lxc.lxcfs.enable "lxcfs.service")
196       ];
197       requires = [
198         "network-online.target"
199         "lxd.socket"
200         (lib.mkIf config.virtualisation.lxc.lxcfs.enable "lxcfs.service")
201       ];
202       documentation = [ "man:lxd(1)" ];
204       path = [ pkgs.util-linux ] ++ lib.optional cfg.zfsSupport config.boot.zfs.package;
206       environment = lib.mkIf (cfg.ui.enable) {
207         "LXD_UI" = cfg.ui.package;
208       };
210       serviceConfig = {
211         ExecStart = "@${cfg.package}/bin/lxd lxd --group lxd";
212         ExecStartPost = "${cfg.package}/bin/lxd waitready --timeout=${cfg.startTimeout}";
213         ExecStop = "${cfg.package}/bin/lxd shutdown";
215         KillMode = "process"; # when stopping, leave the containers alone
216         LimitMEMLOCK = "infinity";
217         LimitNOFILE = "1048576";
218         LimitNPROC = "infinity";
219         TasksMax = "infinity";
220         Delegate = true; # LXD needs to manage cgroups in its subtree
222         # By default, `lxd` loads configuration files from hard-coded
223         # `/usr/share/lxc/config` - since this is a no-go for us, we have to
224         # explicitly tell it where the actual configuration files are
225         Environment = lib.mkIf (config.virtualisation.lxc.lxcfs.enable) "LXD_LXC_TEMPLATE_CONFIG=${pkgs.lxcfs}/share/lxc/config";
226       };
228       unitConfig.ConditionPathExists = "!/var/lib/incus/.migrated-from-lxd";
229     };
231     systemd.services.lxd-preseed = lib.mkIf (cfg.preseed != null) {
232       description = "LXD initialization with preseed file";
233       wantedBy = [ "multi-user.target" ];
234       requires = [ "lxd.service" ];
235       after = [ "lxd.service" ];
237       script = ''
238         ${pkgs.coreutils}/bin/cat ${preseedFormat.generate "lxd-preseed.yaml" cfg.preseed} | ${cfg.package}/bin/lxd init --preseed
239       '';
241       serviceConfig = {
242         Type = "oneshot";
243       };
244     };
246     users.groups.lxd = { };
248     users.users.root = {
249       subUidRanges = [
250         {
251           startUid = 1000000;
252           count = 65536;
253         }
254       ];
255       subGidRanges = [
256         {
257           startGid = 1000000;
258           count = 65536;
259         }
260       ];
261     };
263     boot.kernel.sysctl = lib.mkIf cfg.recommendedSysctlSettings {
264       "fs.inotify.max_queued_events" = 1048576;
265       "fs.inotify.max_user_instances" = 1048576;
266       "fs.inotify.max_user_watches" = 1048576;
267       "vm.max_map_count" = 262144; # TODO: Default vm.max_map_count has been increased system-wide
268       "kernel.dmesg_restrict" = 1;
269       "net.ipv4.neigh.default.gc_thresh3" = 8192;
270       "net.ipv6.neigh.default.gc_thresh3" = 8192;
271       "kernel.keys.maxkeys" = 2000;
272     };
274     boot.kernelModules = [
275       "veth"
276       "xt_comment"
277       "xt_CHECKSUM"
278       "xt_MASQUERADE"
279       "vhost_vsock"
280     ] ++ lib.optionals (!config.networking.nftables.enable) [ "iptable_mangle" ];
281   };