80 lines
3.3 KiB
Nix
80 lines
3.3 KiB
Nix
# oci-containers runs `docker login` in ExecStartPre, which stores plaintext credentials
|
|
# in /root/.docker/config.json. For any container with `login` set, use in-memory
|
|
# DOCKER_AUTH_CONFIG instead (no per-service list to maintain).
|
|
{ ... }: {
|
|
flake.nixosModules.systemDockerRegistryAuth =
|
|
{ config, lib, pkgs, ... }:
|
|
let
|
|
cfg = config.chiasson.system.docker.ephemeralRegistryAuth;
|
|
ociCfg = lib.attrByPath [ "virtualisation" "oci-containers" ] null config;
|
|
backend = if ociCfg == null then "docker" else ociCfg.backend or "docker";
|
|
|
|
containerBackend =
|
|
if backend == "podman" then
|
|
lib.attrByPath [ "virtualisation" "podman" "package" ] pkgs.podman config
|
|
else
|
|
lib.attrByPath [ "virtualisation" "docker" "package" ] pkgs.docker config;
|
|
|
|
isValidLogin =
|
|
login: login.registry != null && login.username != null && login.passwordFile != null;
|
|
|
|
mkRegistryAuthPreStart =
|
|
login: lib.mkBefore ''
|
|
export DOCKER_AUTH_CONFIG="$(${pkgs.jq}/bin/jq -cn \
|
|
--arg registry ${lib.escapeShellArg login.registry} \
|
|
--arg user ${lib.escapeShellArg login.username} \
|
|
--arg pass "$(${pkgs.coreutils}/bin/tr -d '\n\r' < ${login.passwordFile})" \
|
|
'{auths: {($registry): {username: $user, password: $pass, auth: (($user + ":" + $pass) | @base64)}}}')"
|
|
'';
|
|
|
|
mkPreStartWithoutLogin =
|
|
name: container:
|
|
pkgs.writeShellScript "oci-pre-start-${name}" ''
|
|
${containerBackend}/bin/${backend} rm -f ${lib.escapeShellArg name} || true
|
|
${
|
|
lib.optionalString (container.imageFile != null) ''
|
|
${containerBackend}/bin/${backend} load -i ${container.imageFile}
|
|
''
|
|
}
|
|
${
|
|
lib.optionalString (container.imageStream != null) ''
|
|
${container.imageStream} | ${containerBackend}/bin/${backend} load
|
|
''
|
|
}
|
|
'';
|
|
in
|
|
{
|
|
options.chiasson.system.docker.ephemeralRegistryAuth = {
|
|
enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = ''
|
|
Authenticate oci-containers registry pulls via in-memory `DOCKER_AUTH_CONFIG`
|
|
instead of `docker login`. Applies automatically to every container that sets
|
|
`virtualisation.oci-containers.containers.<name>.login`.
|
|
'';
|
|
};
|
|
};
|
|
|
|
# Read merged container config only when defining systemd overrides — never write back
|
|
# to `virtualisation.oci-containers.containers` (that causes infinite recursion).
|
|
config =
|
|
let
|
|
containers =
|
|
lib.attrByPath [ "virtualisation" "oci-containers" "containers" ] { } config;
|
|
containersWithLogin = lib.filterAttrs (_: c: isValidLogin (c.login or { })) containers;
|
|
in
|
|
lib.mkIf (cfg.enable && containersWithLogin != { }) {
|
|
systemd.services = lib.mapAttrs' (
|
|
name: container:
|
|
lib.nameValuePair (container.serviceName or "${backend}-${name}") {
|
|
preStart = mkRegistryAuthPreStart container.login;
|
|
serviceConfig.ExecStartPre = lib.mkForce [
|
|
"${mkPreStartWithoutLogin name container}"
|
|
];
|
|
}
|
|
) containersWithLogin;
|
|
};
|
|
};
|
|
}
|