1{ config, lib, pkgs, utils, ... }:
2let
3 cfg = config.virtualisation.containers;
4
5 inherit (lib) literalExpression mkOption types;
6
7 toml = pkgs.formats.toml { };
8in
9{
10 meta = {
11 maintainers = [] ++ lib.teams.podman.members;
12 };
13
14
15 imports = [
16 (
17 lib.mkRemovedOptionModule
18 [ "virtualisation" "containers" "users" ]
19 "All users with `isNormalUser = true` set now get appropriate subuid/subgid mappings."
20 )
21 (
22 lib.mkRemovedOptionModule
23 [ "virtualisation" "containers" "containersConf" "extraConfig" ]
24 "Use virtualisation.containers.containersConf.settings instead."
25 )
26 ];
27
28 options.virtualisation.containers = {
29
30 enable =
31 mkOption {
32 type = types.bool;
33 default = false;
34 description = ''
35 This option enables the common /etc/containers configuration module.
36 '';
37 };
38
39 ociSeccompBpfHook.enable = mkOption {
40 type = types.bool;
41 default = false;
42 description = "Enable the OCI seccomp BPF hook";
43 };
44
45 containersConf.settings = mkOption {
46 type = toml.type;
47 default = { };
48 description = "containers.conf configuration";
49 };
50
51 containersConf.cniPlugins = mkOption {
52 type = types.listOf types.package;
53 defaultText = literalExpression ''
54 [
55 pkgs.cni-plugins
56 ]
57 '';
58 example = literalExpression ''
59 [
60 pkgs.cniPlugins.dnsname
61 ]
62 '';
63 description = ''
64 CNI plugins to install on the system.
65 '';
66 };
67
68 storage.settings = mkOption {
69 type = toml.type;
70 default = {
71 storage = {
72 driver = "overlay";
73 graphroot = "/var/lib/containers/storage";
74 runroot = "/run/containers/storage";
75 };
76 };
77 description = "storage.conf configuration";
78 };
79
80 registries = {
81 search = mkOption {
82 type = types.listOf types.str;
83 default = [ "docker.io" "quay.io" ];
84 description = ''
85 List of repositories to search.
86 '';
87 };
88
89 insecure = mkOption {
90 default = [];
91 type = types.listOf types.str;
92 description = ''
93 List of insecure repositories.
94 '';
95 };
96
97 block = mkOption {
98 default = [];
99 type = types.listOf types.str;
100 description = ''
101 List of blocked repositories.
102 '';
103 };
104 };
105
106 policy = mkOption {
107 default = {};
108 type = types.attrs;
109 example = literalExpression ''
110 {
111 default = [ { type = "insecureAcceptAnything"; } ];
112 transports = {
113 docker-daemon = {
114 "" = [ { type = "insecureAcceptAnything"; } ];
115 };
116 };
117 }
118 '';
119 description = ''
120 Signature verification policy file.
121 If this option is empty the default policy file from
122 <literal>skopeo</literal> will be used.
123 '';
124 };
125
126 };
127
128 config = lib.mkIf cfg.enable {
129
130 virtualisation.containers.containersConf.cniPlugins = [ pkgs.cni-plugins ];
131
132 virtualisation.containers.containersConf.settings = {
133 network.cni_plugin_dirs = map (p: "${lib.getBin p}/bin") cfg.containersConf.cniPlugins;
134 engine = {
135 init_path = "${pkgs.catatonit}/bin/catatonit";
136 } // lib.optionalAttrs cfg.ociSeccompBpfHook.enable {
137 hooks_dir = [ config.boot.kernelPackages.oci-seccomp-bpf-hook ];
138 };
139 };
140
141 environment.etc."containers/containers.conf".source =
142 toml.generate "containers.conf" cfg.containersConf.settings;
143
144 environment.etc."containers/storage.conf".source =
145 toml.generate "storage.conf" cfg.storage.settings;
146
147 environment.etc."containers/registries.conf".source = toml.generate "registries.conf" {
148 registries = lib.mapAttrs (n: v: { registries = v; }) cfg.registries;
149 };
150
151 environment.etc."containers/policy.json".source =
152 if cfg.policy != {} then pkgs.writeText "policy.json" (builtins.toJSON cfg.policy)
153 else utils.copyFile "${pkgs.skopeo.src}/default-policy.json";
154 };
155
156}