| 
									
										
										
										
											2016-09-18 20:57:01 +02:00
										 |  |  | { config, lib, pkgs, ... }: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | with lib; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | let | 
					
						
							|  |  |  |   cfg = config.services.dockerRegistry; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-06 12:06:46 +02:00
										 |  |  |   blobCache = if cfg.enableRedisCache | 
					
						
							|  |  |  |     then "redis" | 
					
						
							|  |  |  |     else "inmemory"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   registryConfig = { | 
					
						
							|  |  |  |     version =  "0.1"; | 
					
						
							|  |  |  |     log.fields.service = "registry"; | 
					
						
							|  |  |  |     storage = { | 
					
						
							|  |  |  |       cache.blobdescriptor = blobCache; | 
					
						
							|  |  |  |       delete.enabled = cfg.enableDelete; | 
					
						
							| 
									
										
										
										
											2019-03-12 17:32:29 -04:00
										 |  |  |     } // (if cfg.storagePath != null | 
					
						
							|  |  |  |           then { filesystem.rootdirectory = cfg.storagePath; } | 
					
						
							|  |  |  |           else {}); | 
					
						
							| 
									
										
										
										
											2018-08-06 12:06:46 +02:00
										 |  |  |     http = { | 
					
						
							| 
									
										
										
										
											2019-02-08 14:19:53 +02:00
										 |  |  |       addr = "${cfg.listenAddress}:${builtins.toString cfg.port}"; | 
					
						
							| 
									
										
										
										
											2018-08-06 12:06:46 +02:00
										 |  |  |       headers.X-Content-Type-Options = ["nosniff"]; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     health.storagedriver = { | 
					
						
							|  |  |  |       enabled = true; | 
					
						
							|  |  |  |       interval = "10s"; | 
					
						
							|  |  |  |       threshold = 3; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   registryConfig.redis = mkIf cfg.enableRedisCache { | 
					
						
							|  |  |  |     addr = "${cfg.redisUrl}"; | 
					
						
							|  |  |  |     password = "${cfg.redisPassword}"; | 
					
						
							|  |  |  |     db = 0; | 
					
						
							|  |  |  |     dialtimeout = "10ms"; | 
					
						
							|  |  |  |     readtimeout = "10ms"; | 
					
						
							|  |  |  |     writetimeout = "10ms"; | 
					
						
							|  |  |  |     pool = { | 
					
						
							|  |  |  |       maxidle = 16; | 
					
						
							|  |  |  |       maxactive = 64; | 
					
						
							|  |  |  |       idletimeout = "300s"; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-05 11:26:02 +02:00
										 |  |  |   configFile = pkgs.writeText "docker-registry-config.yml" (builtins.toJSON (recursiveUpdate registryConfig cfg.extraConfig)); | 
					
						
							| 
									
										
										
										
											2018-04-06 15:11:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-18 20:57:01 +02:00
										 |  |  | in { | 
					
						
							|  |  |  |   options.services.dockerRegistry = { | 
					
						
							|  |  |  |     enable = mkEnableOption "Docker Registry"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     listenAddress = mkOption { | 
					
						
							|  |  |  |       description = "Docker registry host or ip to bind to."; | 
					
						
							|  |  |  |       default = "127.0.0.1"; | 
					
						
							|  |  |  |       type = types.str; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     port = mkOption { | 
					
						
							|  |  |  |       description = "Docker registry port to bind to."; | 
					
						
							|  |  |  |       default = 5000; | 
					
						
							|  |  |  |       type = types.int; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     storagePath = mkOption { | 
					
						
							| 
									
										
										
										
											2019-03-12 17:32:29 -04:00
										 |  |  |       type = types.nullOr types.path; | 
					
						
							| 
									
										
										
										
											2016-09-18 20:57:01 +02:00
										 |  |  |       default = "/var/lib/docker-registry"; | 
					
						
							| 
									
										
										
										
											2019-03-12 17:32:29 -04:00
										 |  |  |       description = ''
 | 
					
						
							|  |  |  |         Docker registry storage path for the filesystem storage backend. Set to | 
					
						
							|  |  |  |         null to configure another backend via extraConfig. | 
					
						
							|  |  |  |       '';
 | 
					
						
							| 
									
										
										
										
											2016-09-18 20:57:01 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-04 14:15:47 +01:00
										 |  |  |     enableDelete = mkOption { | 
					
						
							|  |  |  |       type = types.bool; | 
					
						
							|  |  |  |       default = false; | 
					
						
							|  |  |  |       description = "Enable delete for manifests and blobs."; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-06 15:11:52 +02:00
										 |  |  |     enableRedisCache = mkEnableOption "redis as blob cache"; | 
					
						
							| 
									
										
										
										
											2018-02-04 14:15:47 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     redisUrl = mkOption { | 
					
						
							|  |  |  |       type = types.str; | 
					
						
							|  |  |  |       default = "localhost:6379"; | 
					
						
							|  |  |  |       description = "Set redis host and port."; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     redisPassword = mkOption { | 
					
						
							|  |  |  |       type = types.str; | 
					
						
							| 
									
										
										
										
											2018-03-26 13:54:01 +02:00
										 |  |  |       default = ""; | 
					
						
							| 
									
										
										
										
											2018-02-04 14:15:47 +01:00
										 |  |  |       description = "Set redis password."; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-18 20:57:01 +02:00
										 |  |  |     extraConfig = mkOption { | 
					
						
							|  |  |  |       description = ''
 | 
					
						
							|  |  |  |         Docker extra registry configuration via environment variables. | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  |       default = {}; | 
					
						
							| 
									
										
										
										
											2018-06-05 11:26:02 +02:00
										 |  |  |       type = types.attrs; | 
					
						
							| 
									
										
										
										
											2016-09-18 20:57:01 +02:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2018-04-06 15:11:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     enableGarbageCollect = mkEnableOption "garbage collect"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     garbageCollectDates = mkOption { | 
					
						
							|  |  |  |       default = "daily"; | 
					
						
							|  |  |  |       type = types.str; | 
					
						
							|  |  |  |       description = ''
 | 
					
						
							|  |  |  |         Specification (in the format described by | 
					
						
							|  |  |  |         <citerefentry><refentrytitle>systemd.time</refentrytitle> | 
					
						
							|  |  |  |         <manvolnum>7</manvolnum></citerefentry>) of the time at | 
					
						
							|  |  |  |         which the garbage collect will occur. | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2016-09-18 20:57:01 +02:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   config = mkIf cfg.enable { | 
					
						
							|  |  |  |     systemd.services.docker-registry = { | 
					
						
							|  |  |  |       description = "Docker Container Registry"; | 
					
						
							|  |  |  |       wantedBy = [ "multi-user.target" ]; | 
					
						
							|  |  |  |       after = [ "network.target" ]; | 
					
						
							| 
									
										
										
										
											2018-04-06 15:11:52 +02:00
										 |  |  |       script = ''
 | 
					
						
							| 
									
										
										
										
											2018-03-26 13:54:01 +02:00
										 |  |  |         ${pkgs.docker-distribution}/bin/registry serve ${configFile} | 
					
						
							| 
									
										
										
										
											2016-09-18 20:57:01 +02:00
										 |  |  |       '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       serviceConfig = { | 
					
						
							|  |  |  |         User = "docker-registry"; | 
					
						
							|  |  |  |         WorkingDirectory = cfg.storagePath; | 
					
						
							| 
									
										
										
										
											2018-06-05 11:27:03 +02:00
										 |  |  |         AmbientCapabilities = mkIf (cfg.port < 1024) "cap_net_bind_service"; | 
					
						
							| 
									
										
										
										
											2016-09-18 20:57:01 +02:00
										 |  |  |       }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-06 15:11:52 +02:00
										 |  |  |     systemd.services.docker-registry-garbage-collect = { | 
					
						
							|  |  |  |       description = "Run Garbage Collection for docker registry"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       restartIfChanged = false; | 
					
						
							|  |  |  |       unitConfig.X-StopOnRemoval = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       serviceConfig.Type = "oneshot"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       script = ''
 | 
					
						
							|  |  |  |         ${pkgs.docker-distribution}/bin/registry garbage-collect ${configFile} | 
					
						
							|  |  |  |         ${pkgs.systemd}/bin/systemctl restart docker-registry.service | 
					
						
							|  |  |  |       '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       startAt = optional cfg.enableGarbageCollect cfg.garbageCollectDates; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-12 17:32:29 -04:00
										 |  |  |     users.users.docker-registry = | 
					
						
							| 
									
										
										
										
											2019-10-12 22:25:28 +02:00
										 |  |  |       (if cfg.storagePath != null | 
					
						
							| 
									
										
										
										
											2019-03-12 17:32:29 -04:00
										 |  |  |       then { | 
					
						
							|  |  |  |         createHome = true; | 
					
						
							|  |  |  |         home = cfg.storagePath; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-10-12 22:25:28 +02:00
										 |  |  |       else {}) // { | 
					
						
							|  |  |  |         isSystemUser = true; | 
					
						
							|  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2016-09-18 20:57:01 +02:00
										 |  |  |   }; | 
					
						
							|  |  |  | } |