at 18.09-beta 3.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 filesystem.rootdirectory = cfg.storagePath; 18 delete.enabled = cfg.enableDelete; 19 }; 20 http = { 21 addr = ":${builtins.toString cfg.port}"; 22 headers.X-Content-Type-Options = ["nosniff"]; 23 }; 24 health.storagedriver = { 25 enabled = true; 26 interval = "10s"; 27 threshold = 3; 28 }; 29 }; 30 31 registryConfig.redis = mkIf cfg.enableRedisCache { 32 addr = "${cfg.redisUrl}"; 33 password = "${cfg.redisPassword}"; 34 db = 0; 35 dialtimeout = "10ms"; 36 readtimeout = "10ms"; 37 writetimeout = "10ms"; 38 pool = { 39 maxidle = 16; 40 maxactive = 64; 41 idletimeout = "300s"; 42 }; 43 }; 44 45 configFile = pkgs.writeText "docker-registry-config.yml" (builtins.toJSON (recursiveUpdate registryConfig cfg.extraConfig)); 46 47in { 48 options.services.dockerRegistry = { 49 enable = mkEnableOption "Docker Registry"; 50 51 listenAddress = mkOption { 52 description = "Docker registry host or ip to bind to."; 53 default = "127.0.0.1"; 54 type = types.str; 55 }; 56 57 port = mkOption { 58 description = "Docker registry port to bind to."; 59 default = 5000; 60 type = types.int; 61 }; 62 63 storagePath = mkOption { 64 type = types.path; 65 default = "/var/lib/docker-registry"; 66 description = "Docker registry storage path."; 67 }; 68 69 enableDelete = mkOption { 70 type = types.bool; 71 default = false; 72 description = "Enable delete for manifests and blobs."; 73 }; 74 75 enableRedisCache = mkEnableOption "redis as blob cache"; 76 77 redisUrl = mkOption { 78 type = types.str; 79 default = "localhost:6379"; 80 description = "Set redis host and port."; 81 }; 82 83 redisPassword = mkOption { 84 type = types.str; 85 default = ""; 86 description = "Set redis password."; 87 }; 88 89 extraConfig = mkOption { 90 description = '' 91 Docker extra registry configuration via environment variables. 92 ''; 93 default = {}; 94 type = types.attrs; 95 }; 96 97 enableGarbageCollect = mkEnableOption "garbage collect"; 98 99 garbageCollectDates = mkOption { 100 default = "daily"; 101 type = types.str; 102 description = '' 103 Specification (in the format described by 104 <citerefentry><refentrytitle>systemd.time</refentrytitle> 105 <manvolnum>7</manvolnum></citerefentry>) of the time at 106 which the garbage collect will occur. 107 ''; 108 }; 109 }; 110 111 config = mkIf cfg.enable { 112 systemd.services.docker-registry = { 113 description = "Docker Container Registry"; 114 wantedBy = [ "multi-user.target" ]; 115 after = [ "network.target" ]; 116 script = '' 117 ${pkgs.docker-distribution}/bin/registry serve ${configFile} 118 ''; 119 120 serviceConfig = { 121 User = "docker-registry"; 122 WorkingDirectory = cfg.storagePath; 123 AmbientCapabilities = mkIf (cfg.port < 1024) "cap_net_bind_service"; 124 }; 125 }; 126 127 systemd.services.docker-registry-garbage-collect = { 128 description = "Run Garbage Collection for docker registry"; 129 130 restartIfChanged = false; 131 unitConfig.X-StopOnRemoval = false; 132 133 serviceConfig.Type = "oneshot"; 134 135 script = '' 136 ${pkgs.docker-distribution}/bin/registry garbage-collect ${configFile} 137 ${pkgs.systemd}/bin/systemctl restart docker-registry.service 138 ''; 139 140 startAt = optional cfg.enableGarbageCollect cfg.garbageCollectDates; 141 }; 142 143 users.users.docker-registry = { 144 createHome = true; 145 home = cfg.storagePath; 146 }; 147 }; 148}