1 { config, lib, pkgs, ... }:
3 cfg = config.services.dockerRegistry;
5 blobCache = if cfg.enableRedisCache
11 log.fields.service = "registry";
13 cache.blobdescriptor = blobCache;
14 delete.enabled = cfg.enableDelete;
15 } // (lib.optionalAttrs (cfg.storagePath != null) { filesystem.rootdirectory = cfg.storagePath; });
17 addr = "${cfg.listenAddress}:${builtins.toString cfg.port}";
18 headers.X-Content-Type-Options = ["nosniff"];
20 health.storagedriver = {
27 registryConfig.redis = lib.mkIf cfg.enableRedisCache {
28 addr = "${cfg.redisUrl}";
29 password = "${cfg.redisPassword}";
33 writetimeout = "10ms";
41 configFile = cfg.configFile;
43 options.services.dockerRegistry = {
44 enable = lib.mkEnableOption "Docker Registry";
46 package = lib.mkPackageOption pkgs "docker-distribution" {
47 example = "gitlab-container-registry";
50 listenAddress = lib.mkOption {
51 description = "Docker registry host or ip to bind to.";
52 default = "127.0.0.1";
57 description = "Docker registry port to bind to.";
59 type = lib.types.port;
62 openFirewall = lib.mkOption {
63 type = lib.types.bool;
65 description = "Opens the port used by the firewall.";
68 storagePath = lib.mkOption {
69 type = lib.types.nullOr lib.types.path;
70 default = "/var/lib/docker-registry";
72 Docker registry storage path for the filesystem storage backend. Set to
73 null to configure another backend via extraConfig.
77 enableDelete = lib.mkOption {
78 type = lib.types.bool;
80 description = "Enable delete for manifests and blobs.";
83 enableRedisCache = lib.mkEnableOption "redis as blob cache";
85 redisUrl = lib.mkOption {
87 default = "localhost:6379";
88 description = "Set redis host and port.";
91 redisPassword = lib.mkOption {
94 description = "Set redis password.";
97 extraConfig = lib.mkOption {
99 Docker extra registry configuration via environment variables.
102 type = lib.types.attrs;
105 configFile = lib.mkOption {
106 default = pkgs.writeText "docker-registry-config.yml" (builtins.toJSON (lib.recursiveUpdate registryConfig cfg.extraConfig));
107 defaultText = lib.literalExpression ''pkgs.writeText "docker-registry-config.yml" "# my custom docker-registry-config.yml ..."'';
109 Path to CNCF distribution config file.
111 Setting this option will override any configuration applied by the extraConfig option.
113 type = lib.types.path;
116 enableGarbageCollect = lib.mkEnableOption "garbage collect";
118 garbageCollectDates = lib.mkOption {
120 type = lib.types.str;
122 Specification (in the format described by
123 {manpage}`systemd.time(7)`) of the time at
124 which the garbage collect will occur.
129 config = lib.mkIf cfg.enable {
130 systemd.services.docker-registry = {
131 description = "Docker Container Registry";
132 wantedBy = [ "multi-user.target" ];
133 after = [ "network.target" ];
135 ${cfg.package}/bin/registry serve ${configFile}
139 User = "docker-registry";
140 WorkingDirectory = cfg.storagePath;
141 AmbientCapabilities = lib.mkIf (cfg.port < 1024) "cap_net_bind_service";
145 systemd.services.docker-registry-garbage-collect = {
146 description = "Run Garbage Collection for docker registry";
148 restartIfChanged = false;
149 unitConfig.X-StopOnRemoval = false;
151 serviceConfig.Type = "oneshot";
154 ${cfg.package}/bin/registry garbage-collect ${configFile}
155 /run/current-system/systemd/bin/systemctl restart docker-registry.service
158 startAt = lib.optional cfg.enableGarbageCollect cfg.garbageCollectDates;
161 users.users.docker-registry =
162 (lib.optionalAttrs (cfg.storagePath != null) {
164 home = cfg.storagePath;
166 group = "docker-registry";
169 users.groups.docker-registry = {};
171 networking.firewall = lib.mkIf cfg.openFirewall {
172 allowedTCPPorts = [ cfg.port ];