{ config, lib, pkgs, ... }: let cfg = config.programs.docker; jsonFormat = pkgs.formats.json { }; settingsType = lib.types.submodule { freeformType = jsonFormat.type; }; in { options.programs.docker = { enable = lib.mkEnableOption "Container runtime client"; package = lib.mkOption { type = lib.types.package; default = pkgs.docker-client; defaultText = lib.literalExpression "pkgs.docker-client"; description = "Package providing {command}`docker`."; }; settings = lib.mkOption { type = settingsType; default = { }; description = '' This is written to {file}`$XDG_CONFIG_HOME/.docker/config.json`. For security reasons, never store cleartext passwords here. Instead use `credHelpersWrap` option to retrieve credentials from your favorite password manager at runtime. ''; example = lib.literalExpression '' { currentContext = "colima"; }; ''; }; # why not use the pass credstore directly? you do you, I don't want docker # messing with my bigbrain password-store layout credHelpersWrap = lib.mkOption { type = lib.types.attrsOf lib.types.str; default = { }; description = '' A mapping of registry URLs to commands to use as credential helpers. ''; example = lib.literalExpression '' { "docker.io": "$${pkgs.pass}/bin/pass show docker.io"; }; ''; }; }; config = let genWrapperId = name: builtins.hashString "sha1" name; genWrapperName = name: "docker-credential-" + (genWrapperId name); wrappers = lib.mapAttrsToList (registry: wrapper: pkgs.writeShellScriptBin (genWrapperName registry) wrapper ) cfg.credHelpersWrap; finalSettings = lib.recursiveUpdate cfg.settings { credHelpers = lib.mapAttrs (registry: _: genWrapperId registry) cfg.credHelpersWrap; }; in lib.mkIf cfg.enable { home.packages = [ cfg.package ] ++ wrappers; home.file.".docker/config.json".source = jsonFormat.generate "config.json" finalSettings; }; }