1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8
9 cfg = config.virtualisation.docker.rootless;
10 proxy_env = config.networking.proxy.envVars;
11 settingsFormat = pkgs.formats.json { };
12 daemonSettingsFile = settingsFormat.generate "daemon.json" cfg.daemon.settings;
13
14in
15
16{
17 ###### interface
18
19 options.virtualisation.docker.rootless = {
20 enable = lib.mkOption {
21 type = lib.types.bool;
22 default = false;
23 description = ''
24 This option enables docker in a rootless mode, a daemon that manages
25 linux containers. To interact with the daemon, one needs to set
26 {command}`DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock`.
27 '';
28 };
29
30 setSocketVariable = lib.mkOption {
31 type = lib.types.bool;
32 default = false;
33 description = ''
34 Point {command}`DOCKER_HOST` to rootless Docker instance for
35 normal users by default.
36 '';
37 };
38
39 daemon.settings = lib.mkOption {
40 type = settingsFormat.type;
41 default = { };
42 example = {
43 ipv6 = true;
44 "fixed-cidr-v6" = "fd00::/80";
45 };
46 description = ''
47 Configuration for docker daemon. The attributes are serialized to JSON used as daemon.conf.
48 See https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file
49 '';
50 };
51
52 package = lib.mkPackageOption pkgs "docker" { };
53 };
54
55 ###### implementation
56
57 config = lib.mkIf cfg.enable {
58 environment.systemPackages = [ cfg.package ];
59
60 environment.extraInit = lib.optionalString cfg.setSocketVariable ''
61 if [ -z "$DOCKER_HOST" -a -n "$XDG_RUNTIME_DIR" ]; then
62 export DOCKER_HOST="unix://$XDG_RUNTIME_DIR/docker.sock"
63 fi
64 '';
65
66 # Taken from https://github.com/moby/moby/blob/master/contrib/dockerd-rootless-setuptool.sh
67 systemd.user.services.docker = {
68 wantedBy = [ "default.target" ];
69 description = "Docker Application Container Engine (Rootless)";
70 # needs newuidmap from pkgs.shadow
71 path = [ "/run/wrappers" ];
72 environment = proxy_env;
73 unitConfig = {
74 # docker-rootless doesn't support running as root.
75 ConditionUser = "!root";
76 StartLimitInterval = "60s";
77 };
78 serviceConfig = {
79 Type = "notify";
80 ExecStart = "${cfg.package}/bin/dockerd-rootless --config-file=${daemonSettingsFile}";
81 ExecReload = "${pkgs.procps}/bin/kill -s HUP $MAINPID";
82 TimeoutSec = 0;
83 RestartSec = 2;
84 Restart = "always";
85 StartLimitBurst = 3;
86 LimitNOFILE = "infinity";
87 LimitNPROC = "infinity";
88 LimitCORE = "infinity";
89 Delegate = true;
90 NotifyAccess = "all";
91 KillMode = "mixed";
92 };
93 };
94 };
95
96}