at 24.11-pre 4.8 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.dockerRegistry; 7 8 blobCache = if cfg.enableRedisCache 9 then "redis" 10 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 } // (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 = 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 options.services.dockerRegistry = { 47 enable = mkEnableOption "Docker Registry"; 48 49 package = mkPackageOption pkgs "docker-distribution" { 50 example = "gitlab-container-registry"; 51 }; 52 53 listenAddress = mkOption { 54 description = "Docker registry host or ip to bind to."; 55 default = "127.0.0.1"; 56 type = types.str; 57 }; 58 59 port = mkOption { 60 description = "Docker registry port to bind to."; 61 default = 5000; 62 type = types.port; 63 }; 64 65 openFirewall = mkOption { 66 type = types.bool; 67 default = false; 68 description = "Opens the port used by the firewall."; 69 }; 70 71 storagePath = mkOption { 72 type = types.nullOr types.path; 73 default = "/var/lib/docker-registry"; 74 description = '' 75 Docker registry storage path for the filesystem storage backend. Set to 76 null to configure another backend via extraConfig. 77 ''; 78 }; 79 80 enableDelete = mkOption { 81 type = types.bool; 82 default = false; 83 description = "Enable delete for manifests and blobs."; 84 }; 85 86 enableRedisCache = mkEnableOption "redis as blob cache"; 87 88 redisUrl = mkOption { 89 type = types.str; 90 default = "localhost:6379"; 91 description = "Set redis host and port."; 92 }; 93 94 redisPassword = mkOption { 95 type = types.str; 96 default = ""; 97 description = "Set redis password."; 98 }; 99 100 extraConfig = mkOption { 101 description = '' 102 Docker extra registry configuration via environment variables. 103 ''; 104 default = {}; 105 type = types.attrs; 106 }; 107 108 configFile = lib.mkOption { 109 default = pkgs.writeText "docker-registry-config.yml" (builtins.toJSON (recursiveUpdate registryConfig cfg.extraConfig)); 110 defaultText = literalExpression ''pkgs.writeText "docker-registry-config.yml" "# my custom docker-registry-config.yml ..."''; 111 description = '' 112 Path to CNCF distribution config file. 113 114 Setting this option will override any configuration applied by the extraConfig option. 115 ''; 116 type = types.path; 117 }; 118 119 enableGarbageCollect = mkEnableOption "garbage collect"; 120 121 garbageCollectDates = mkOption { 122 default = "daily"; 123 type = types.str; 124 description = '' 125 Specification (in the format described by 126 {manpage}`systemd.time(7)`) of the time at 127 which the garbage collect will occur. 128 ''; 129 }; 130 }; 131 132 config = mkIf cfg.enable { 133 systemd.services.docker-registry = { 134 description = "Docker Container Registry"; 135 wantedBy = [ "multi-user.target" ]; 136 after = [ "network.target" ]; 137 script = '' 138 ${cfg.package}/bin/registry serve ${configFile} 139 ''; 140 141 serviceConfig = { 142 User = "docker-registry"; 143 WorkingDirectory = cfg.storagePath; 144 AmbientCapabilities = mkIf (cfg.port < 1024) "cap_net_bind_service"; 145 }; 146 }; 147 148 systemd.services.docker-registry-garbage-collect = { 149 description = "Run Garbage Collection for docker registry"; 150 151 restartIfChanged = false; 152 unitConfig.X-StopOnRemoval = false; 153 154 serviceConfig.Type = "oneshot"; 155 156 script = '' 157 ${cfg.package}/bin/registry garbage-collect ${configFile} 158 /run/current-system/systemd/bin/systemctl restart docker-registry.service 159 ''; 160 161 startAt = optional cfg.enableGarbageCollect cfg.garbageCollectDates; 162 }; 163 164 users.users.docker-registry = 165 (optionalAttrs (cfg.storagePath != null) { 166 createHome = true; 167 home = cfg.storagePath; 168 }) // { 169 group = "docker-registry"; 170 isSystemUser = true; 171 }; 172 users.groups.docker-registry = {}; 173 174 networking.firewall = mkIf cfg.openFirewall { 175 allowedTCPPorts = [ cfg.port ]; 176 }; 177 }; 178}