at 25.11-pre 5.0 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.services.dockerRegistry; 9 10 blobCache = if cfg.enableRedisCache then "redis" else "inmemory"; 11 12 registryConfig = { 13 version = "0.1"; 14 log.fields.service = "registry"; 15 storage = { 16 cache.blobdescriptor = blobCache; 17 delete.enabled = cfg.enableDelete; 18 } // (lib.optionalAttrs (cfg.storagePath != null) { filesystem.rootdirectory = cfg.storagePath; }); 19 http = { 20 addr = "${cfg.listenAddress}:${builtins.toString cfg.port}"; 21 headers.X-Content-Type-Options = [ "nosniff" ]; 22 }; 23 health.storagedriver = { 24 enabled = true; 25 interval = "10s"; 26 threshold = 3; 27 }; 28 }; 29 30 registryConfig.redis = lib.mkIf cfg.enableRedisCache { 31 addr = "${cfg.redisUrl}"; 32 password = "${cfg.redisPassword}"; 33 db = 0; 34 dialtimeout = "10ms"; 35 readtimeout = "10ms"; 36 writetimeout = "10ms"; 37 pool = { 38 maxidle = 16; 39 maxactive = 64; 40 idletimeout = "300s"; 41 }; 42 }; 43 44 configFile = cfg.configFile; 45in 46{ 47 options.services.dockerRegistry = { 48 enable = lib.mkEnableOption "Docker Registry"; 49 50 package = lib.mkPackageOption pkgs "docker-distribution" { 51 example = "gitlab-container-registry"; 52 }; 53 54 listenAddress = lib.mkOption { 55 description = "Docker registry host or ip to bind to."; 56 default = "127.0.0.1"; 57 type = lib.types.str; 58 }; 59 60 port = lib.mkOption { 61 description = "Docker registry port to bind to."; 62 default = 5000; 63 type = lib.types.port; 64 }; 65 66 openFirewall = lib.mkOption { 67 type = lib.types.bool; 68 default = false; 69 description = "Opens the port used by the firewall."; 70 }; 71 72 storagePath = lib.mkOption { 73 type = lib.types.nullOr lib.types.path; 74 default = "/var/lib/docker-registry"; 75 description = '' 76 Docker registry storage path for the filesystem storage backend. Set to 77 null to configure another backend via extraConfig. 78 ''; 79 }; 80 81 enableDelete = lib.mkOption { 82 type = lib.types.bool; 83 default = false; 84 description = "Enable delete for manifests and blobs."; 85 }; 86 87 enableRedisCache = lib.mkEnableOption "redis as blob cache"; 88 89 redisUrl = lib.mkOption { 90 type = lib.types.str; 91 default = "localhost:6379"; 92 description = "Set redis host and port."; 93 }; 94 95 redisPassword = lib.mkOption { 96 type = lib.types.str; 97 default = ""; 98 description = "Set redis password."; 99 }; 100 101 extraConfig = lib.mkOption { 102 description = '' 103 Docker extra registry configuration. 104 ''; 105 example = lib.literalExpression '' 106 { 107 log.level = "debug"; 108 } 109 ''; 110 default = { }; 111 type = lib.types.attrs; 112 }; 113 114 configFile = lib.mkOption { 115 default = pkgs.writeText "docker-registry-config.yml" ( 116 builtins.toJSON (lib.recursiveUpdate registryConfig cfg.extraConfig) 117 ); 118 defaultText = lib.literalExpression ''pkgs.writeText "docker-registry-config.yml" "# my custom docker-registry-config.yml ..."''; 119 description = '' 120 Path to CNCF distribution config file. 121 122 Setting this option will override any configuration applied by the extraConfig option. 123 ''; 124 type = lib.types.path; 125 }; 126 127 enableGarbageCollect = lib.mkEnableOption "garbage collect"; 128 129 garbageCollectDates = lib.mkOption { 130 default = "daily"; 131 type = lib.types.str; 132 description = '' 133 Specification (in the format described by 134 {manpage}`systemd.time(7)`) of the time at 135 which the garbage collect will occur. 136 ''; 137 }; 138 }; 139 140 config = lib.mkIf cfg.enable { 141 systemd.services.docker-registry = { 142 description = "Docker Container Registry"; 143 wantedBy = [ "multi-user.target" ]; 144 after = [ "network.target" ]; 145 script = '' 146 ${cfg.package}/bin/registry serve ${configFile} 147 ''; 148 149 serviceConfig = { 150 User = "docker-registry"; 151 WorkingDirectory = cfg.storagePath; 152 AmbientCapabilities = lib.mkIf (cfg.port < 1024) "cap_net_bind_service"; 153 }; 154 }; 155 156 systemd.services.docker-registry-garbage-collect = { 157 description = "Run Garbage Collection for docker registry"; 158 159 restartIfChanged = false; 160 unitConfig.X-StopOnRemoval = false; 161 162 serviceConfig.Type = "oneshot"; 163 164 script = '' 165 ${cfg.package}/bin/registry garbage-collect ${configFile} 166 /run/current-system/systemd/bin/systemctl restart docker-registry.service 167 ''; 168 169 startAt = lib.optional cfg.enableGarbageCollect cfg.garbageCollectDates; 170 }; 171 172 users.users.docker-registry = 173 (lib.optionalAttrs (cfg.storagePath != null) { 174 createHome = true; 175 home = cfg.storagePath; 176 }) 177 // { 178 group = "docker-registry"; 179 isSystemUser = true; 180 }; 181 users.groups.docker-registry = { }; 182 183 networking.firewall = lib.mkIf cfg.openFirewall { 184 allowedTCPPorts = [ cfg.port ]; 185 }; 186 }; 187}