2023-08-20 12:29:50 +08:00
|
|
|
inputs:
|
|
|
|
{
|
2023-09-16 19:21:05 +08:00
|
|
|
options.nixos.services.docker = let inherit (inputs.lib) mkOption types; in mkOption
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
|
|
|
type = types.attrsOf (types.submodule (inputs: { options =
|
|
|
|
{
|
|
|
|
user = mkOption { type = types.nonEmptyStr; default = inputs.config._module.args.name; };
|
|
|
|
image = mkOption { type = types.package; };
|
|
|
|
imageName =
|
2023-09-16 19:21:05 +08:00
|
|
|
mkOption { type = types.nonEmptyStr; default = with inputs.config.image; (imageName + ":" + imageTag); };
|
2023-09-01 21:05:26 +08:00
|
|
|
ports = mkOption
|
|
|
|
{
|
|
|
|
type = types.listOf (types.oneOf
|
|
|
|
[
|
|
|
|
types.ints.unsigned
|
|
|
|
types.submodule (inputs: { options =
|
|
|
|
{
|
|
|
|
hostIp = mkOption { type = types.nonEmptyStr; default = "127.0.0.1"; };
|
|
|
|
hostPort = mkOption { type = types.ints.unsigned; };
|
|
|
|
containerPort = mkOption { type = types.ints.unsigned; };
|
|
|
|
protocol = mkOption { type = types.enum [ "tcp" "udp" ]; default = "tcp"; };
|
|
|
|
};})
|
|
|
|
]);
|
|
|
|
default = [];
|
|
|
|
};
|
|
|
|
environmentFile = mkOption { type = types.oneOf [ types.bool types.nonEmptyStr ]; default = false; };
|
|
|
|
};}));
|
|
|
|
default = {};
|
|
|
|
};
|
|
|
|
config =
|
|
|
|
let
|
2023-09-16 19:21:05 +08:00
|
|
|
inherit (inputs.lib) mkIf;
|
2023-09-01 21:05:26 +08:00
|
|
|
inherit (builtins) listToAttrs map concatLists;
|
|
|
|
inherit (inputs.localLib) attrsToList;
|
|
|
|
inherit (inputs.config.nixos.services) docker;
|
2023-09-16 19:21:05 +08:00
|
|
|
in mkIf (docker != {})
|
|
|
|
{
|
|
|
|
virtualisation.oci-containers.containers = listToAttrs (map
|
|
|
|
(container:
|
|
|
|
{
|
|
|
|
name = "${container.name}";
|
|
|
|
value =
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
2023-09-16 19:21:05 +08:00
|
|
|
image = container.value.imageName;
|
|
|
|
imageFile = container.value.image;
|
|
|
|
ports = map
|
|
|
|
(port:
|
|
|
|
(
|
|
|
|
if builtins.typeOf port == "int" then toString port
|
|
|
|
else ("${port.value.hostIp}:${toString port.value.hostPort}"
|
|
|
|
+ ":${toString port.value.containerPort}/${port.value.protocol}")
|
|
|
|
))
|
|
|
|
container.value.ports;
|
|
|
|
extraOptions = [ "--add-host=host.docker.internal:host-gateway" ];
|
|
|
|
environmentFiles =
|
|
|
|
if builtins.typeOf container.value.environmentFile == "bool" && container.value.environmentFile
|
|
|
|
then [ inputs.config.sops.templates."${container.name}.env".path ]
|
|
|
|
else if builtins.typeOf container.value.environmentFile == "bool" then []
|
|
|
|
else [ container.value.environmentFile ];
|
|
|
|
};
|
|
|
|
})
|
|
|
|
(attrsToList docker));
|
|
|
|
systemd =
|
|
|
|
{
|
|
|
|
services = listToAttrs (concatLists (map
|
|
|
|
(container: let user = container.value.user; in
|
2023-09-01 21:05:26 +08:00
|
|
|
[
|
|
|
|
{
|
2023-09-16 19:21:05 +08:00
|
|
|
name = "docker-${user}-daemon";
|
|
|
|
value = let originalService = inputs.config.systemd.user.services.docker; in
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
2023-09-16 19:21:05 +08:00
|
|
|
inherit (originalService) description path;
|
|
|
|
environment.XDG_RUNTIME_DIR = "/run/docker-rootless/${user}";
|
|
|
|
serviceConfig = originalService.serviceConfig //
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
2023-09-16 19:21:05 +08:00
|
|
|
User = user;
|
|
|
|
Group = user;
|
|
|
|
# AmbientCapabilities = "CAP_NET_BIND_SERVICE";
|
|
|
|
ExecStart = originalService.serviceConfig.ExecStart
|
|
|
|
+ " -H unix:///var/run/docker-rootless/${user}/docker.sock";
|
2023-09-01 21:05:26 +08:00
|
|
|
};
|
2023-09-16 19:21:05 +08:00
|
|
|
unitConfig = { inherit (originalService.unitConfig) StartLimitInterval; };
|
2023-09-01 21:05:26 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
{
|
|
|
|
name = "docker-${container.name}";
|
|
|
|
value =
|
|
|
|
{
|
2023-09-16 19:21:05 +08:00
|
|
|
requires = [ "docker-${user}-daemon.service" ];
|
|
|
|
after = [ "docker-${user}-daemon.service" ];
|
|
|
|
environment =
|
|
|
|
{
|
|
|
|
XDG_RUNTIME_DIR = "/run/docker-rootless/${user}";
|
|
|
|
DOCKER_HOST = "unix:///run/docker-rootless/${user}/docker.sock";
|
|
|
|
};
|
|
|
|
serviceConfig =
|
|
|
|
{
|
|
|
|
User = user;
|
|
|
|
Group = user;
|
|
|
|
CapabilityBoundingSet = "CAP_NET_ADMIN CAP_NET_BIND_SERVICE";
|
|
|
|
AmbientCapabilities = "CAP_NET_ADMIN CAP_NET_BIND_SERVICE";
|
|
|
|
};
|
2023-09-01 21:05:26 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
])
|
|
|
|
(attrsToList docker)));
|
2023-09-16 19:21:05 +08:00
|
|
|
tmpfiles.rules = map
|
|
|
|
(container: with container.value; "d /run/docker-rootless/${user} 0755 ${user} ${user}")
|
|
|
|
(attrsToList docker);
|
|
|
|
};
|
|
|
|
nixos.virtualization.docker.enable = true;
|
|
|
|
users =
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
2023-09-16 19:21:05 +08:00
|
|
|
users = listToAttrs (map
|
|
|
|
(container:
|
|
|
|
{
|
|
|
|
name = container.value.user;
|
|
|
|
value =
|
|
|
|
{
|
|
|
|
isSystemUser = true;
|
|
|
|
group = container.value.user;
|
|
|
|
autoSubUidGidRange = true;
|
|
|
|
home = "/run/docker-rootless/${container.value.user}";
|
|
|
|
};
|
|
|
|
})
|
|
|
|
(attrsToList docker));
|
|
|
|
groups = listToAttrs (map
|
|
|
|
(container: { name = container.value.user; value = {}; })
|
|
|
|
(attrsToList docker));
|
|
|
|
};
|
|
|
|
};
|
2023-08-20 12:29:50 +08:00
|
|
|
}
|