1 { config, lib, pkgs, ... }:
6 cfg = config.services.dockerRegistry;
8 blobCache = if cfg.enableRedisCache
14 log.fields.service = "registry";
16 cache.blobdescriptor = blobCache;
17 delete.enabled = cfg.enableDelete;
18 } // (if cfg.storagePath != null
19 then { filesystem.rootdirectory = cfg.storagePath; }
22 addr = "${cfg.listenAddress}:${builtins.toString cfg.port}";
23 headers.X-Content-Type-Options = ["nosniff"];
25 health.storagedriver = {
32 registryConfig.redis = mkIf cfg.enableRedisCache {
33 addr = "${cfg.redisUrl}";
34 password = "${cfg.redisPassword}";
38 writetimeout = "10ms";
46 configFile = pkgs.writeText "docker-registry-config.yml" (builtins.toJSON (recursiveUpdate registryConfig cfg.extraConfig));
49 options.services.dockerRegistry = {
50 enable = mkEnableOption (lib.mdDoc "Docker Registry");
52 listenAddress = mkOption {
53 description = lib.mdDoc "Docker registry host or ip to bind to.";
54 default = "127.0.0.1";
59 description = lib.mdDoc "Docker registry port to bind to.";
64 storagePath = mkOption {
65 type = types.nullOr types.path;
66 default = "/var/lib/docker-registry";
67 description = lib.mdDoc ''
68 Docker registry storage path for the filesystem storage backend. Set to
69 null to configure another backend via extraConfig.
73 enableDelete = mkOption {
76 description = lib.mdDoc "Enable delete for manifests and blobs.";
79 enableRedisCache = mkEnableOption (lib.mdDoc "redis as blob cache");
83 default = "localhost:6379";
84 description = lib.mdDoc "Set redis host and port.";
87 redisPassword = mkOption {
90 description = lib.mdDoc "Set redis password.";
93 extraConfig = mkOption {
94 description = lib.mdDoc ''
95 Docker extra registry configuration via environment variables.
101 enableGarbageCollect = mkEnableOption (lib.mdDoc "garbage collect");
103 garbageCollectDates = mkOption {
106 description = lib.mdDoc ''
107 Specification (in the format described by
108 {manpage}`systemd.time(7)`) of the time at
109 which the garbage collect will occur.
114 config = mkIf cfg.enable {
115 systemd.services.docker-registry = {
116 description = "Docker Container Registry";
117 wantedBy = [ "multi-user.target" ];
118 after = [ "network.target" ];
120 ${pkgs.docker-distribution}/bin/registry serve ${configFile}
124 User = "docker-registry";
125 WorkingDirectory = cfg.storagePath;
126 AmbientCapabilities = mkIf (cfg.port < 1024) "cap_net_bind_service";
130 systemd.services.docker-registry-garbage-collect = {
131 description = "Run Garbage Collection for docker registry";
133 restartIfChanged = false;
134 unitConfig.X-StopOnRemoval = false;
136 serviceConfig.Type = "oneshot";
139 ${pkgs.docker-distribution}/bin/registry garbage-collect ${configFile}
140 /run/current-system/systemd/bin/systemctl restart docker-registry.service
143 startAt = optional cfg.enableGarbageCollect cfg.garbageCollectDates;
146 users.users.docker-registry =
147 (if cfg.storagePath != null
150 home = cfg.storagePath;
153 group = "docker-registry";
156 users.groups.docker-registry = {};