Add Docker registry authentication support to NixOS configurations
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# 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;
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user