|
5 | 5 | etcEncrypted, |
6 | 6 | ... |
7 | 7 | }: let |
| 8 | + inherit (lib) boolToString last makeBinPath mkDefault mkEnableOption mkIf mkOption; |
| 9 | + inherit (lib.types) bool listOf package str; |
| 10 | + inherit (lib.types.ints) unsigned; |
| 11 | + |
8 | 12 | deployType = config.currentCoreNode.deployType or config.currentAwsAutoScalingGroup.deployType; |
9 | 13 | domain = |
10 | 14 | config |
|
15 | 19 | } |
16 | 20 | .domain; |
17 | 21 | isSops = deployType == "aws"; |
18 | | - relEncryptedFolder = lib.last (builtins.split "-" (toString config.secrets.encryptedRoot)); |
| 22 | + relEncryptedFolder = last (builtins.split "-" (toString config.secrets.encryptedRoot)); |
19 | 23 | cfg = config.services.docker-registry; |
20 | 24 | in { |
21 | 25 | options.services.docker-registry = { |
22 | | - enable = lib.mkEnableOption "Docker registry"; |
23 | | - registryFqdn = lib.mkOption { |
24 | | - type = lib.types.str; |
| 26 | + enable = mkEnableOption "Docker registry"; |
| 27 | + |
| 28 | + registryFqdn = mkOption { |
| 29 | + type = str; |
25 | 30 | default = "registry.${domain}"; |
26 | 31 | description = "The default host fqdn for the traefik routed registry service."; |
27 | 32 | }; |
28 | | - traefikTags = lib.mkOption { |
29 | | - type = with lib.types; listOf str; |
| 33 | + |
| 34 | + traefikTags = mkOption { |
| 35 | + type = listOf str; |
30 | 36 | default = [ |
31 | 37 | "ingress" |
32 | 38 | "traefik.enable=true" |
|
45 | 51 | a basic-auth file for registry authentication. |
46 | 52 | ''; |
47 | 53 | }; |
| 54 | + |
| 55 | + enableRepair = mkOption { |
| 56 | + type = bool; |
| 57 | + default = true; |
| 58 | + description = "Enables the docker registry repair service."; |
| 59 | + }; |
| 60 | + |
| 61 | + repairDeleteTag = mkOption { |
| 62 | + type = bool; |
| 63 | + default = false; |
| 64 | + description = "Also delete all tag references during repair."; |
| 65 | + }; |
| 66 | + |
| 67 | + repairDryRun = mkOption { |
| 68 | + type = bool; |
| 69 | + default = false; |
| 70 | + description = "Avoid deleting anything during repair."; |
| 71 | + }; |
| 72 | + |
| 73 | + repairPkg = mkOption { |
| 74 | + type = package; |
| 75 | + default = pkgs.docker-registry-repair; |
| 76 | + description = '' |
| 77 | + The registry repair package to utilize. |
| 78 | + Assumes a bin file of ''${cfg.repairPkg}/bin/docker-registry-repair. |
| 79 | + ''; |
| 80 | + }; |
| 81 | + |
| 82 | + repairRegistryPath = mkOption { |
| 83 | + type = str; |
| 84 | + default = "/var/lib/docker-registry/docker/registry/v2"; |
| 85 | + description = "The registry path."; |
| 86 | + }; |
| 87 | + |
| 88 | + repairTailDelay = mkOption { |
| 89 | + type = unsigned; |
| 90 | + default = 5; |
| 91 | + description = "The time delay in seconds between repair spawn jobs."; |
| 92 | + }; |
| 93 | + |
| 94 | + repairTailLookback = mkOption { |
| 95 | + type = str; |
| 96 | + default = "-1h"; |
| 97 | + description = '' |
| 98 | + The lookback period for journal history. |
| 99 | + This needs to be a valid journalctl -S parameter formatted string. |
| 100 | + ''; |
| 101 | + }; |
| 102 | + |
| 103 | + repairTailPkg = mkOption { |
| 104 | + type = package; |
| 105 | + default = pkgs.docker-registry-tail; |
| 106 | + description = '' |
| 107 | + The registry repair tail package to utilize. |
| 108 | + Assumes a bin file of ''${cfg.repairTailPkg}/bin/docker-registry-tail. |
| 109 | + ''; |
| 110 | + }; |
| 111 | + |
| 112 | + repairTailService = mkOption { |
| 113 | + type = str; |
| 114 | + default = "docker-registry.service"; |
| 115 | + description = "The systemd service to tail."; |
| 116 | + }; |
48 | 117 | }; |
49 | 118 |
|
50 | | - config = lib.mkIf cfg.enable { |
| 119 | + config = mkIf cfg.enable { |
51 | 120 | networking.firewall.allowedTCPPorts = [ |
52 | 121 | config.services.dockerRegistry.port |
53 | 122 | ]; |
54 | 123 |
|
55 | 124 | services = { |
56 | 125 | dockerRegistry = { |
57 | | - enable = lib.mkDefault true; |
| 126 | + enable = mkDefault true; |
58 | 127 | enableDelete = true; |
59 | 128 | enableGarbageCollect = true; |
60 | 129 | enableRedisCache = true; |
|
97 | 166 | }) |
98 | 167 | .systemdService; |
99 | 168 |
|
100 | | - secrets.generate.redis-password = lib.mkIf isSops '' |
101 | | - export PATH="${lib.makeBinPath (with pkgs; [coreutils sops xkcdpass])}" |
| 169 | + environment.systemPackages = with pkgs; [ |
| 170 | + docker-registry-repair |
| 171 | + docker-registry-tail |
| 172 | + ]; |
| 173 | + |
| 174 | + systemd.services.docker-registry-repair = mkIf cfg.enableRepair { |
| 175 | + wantedBy = ["multi-user.target"]; |
| 176 | + |
| 177 | + startLimitIntervalSec = 0; |
| 178 | + startLimitBurst = 0; |
| 179 | + |
| 180 | + serviceConfig = { |
| 181 | + Restart = "always"; |
| 182 | + RestartSec = 5; |
| 183 | + |
| 184 | + ExecStart = let |
| 185 | + script = pkgs.writeShellApplication { |
| 186 | + name = "docker-registry-repair-tail"; |
| 187 | + text = '' |
| 188 | + exec ${cfg.repairTailPkg}/bin/docker-registry-tail \ |
| 189 | + --since ${cfg.repairTailLookback} \ |
| 190 | + --service ${cfg.repairTailService} \ |
| 191 | + --repair-path ${cfg.repairPkg}/bin/docker-registry-repair \ |
| 192 | + --delay ${toString cfg.repairTailDelay} \ |
| 193 | + --delete-tag ${boolToString cfg.repairDeleteTag} \ |
| 194 | + --dry-run ${boolToString cfg.repairDryRun} |
| 195 | + ''; |
| 196 | + }; |
| 197 | + in "${script}/bin/docker-registry-repair-tail"; |
| 198 | + }; |
| 199 | + }; |
| 200 | + |
| 201 | + secrets.generate.redis-password = mkIf isSops '' |
| 202 | + export PATH="${makeBinPath (with pkgs; [coreutils sops xkcdpass])}" |
102 | 203 |
|
103 | 204 | if [ ! -s ${relEncryptedFolder}/redis-password.json ]; then |
104 | 205 | xkcdpass \ |
|
107 | 208 | fi |
108 | 209 | ''; |
109 | 210 |
|
110 | | - secrets.install.redis-password = lib.mkIf isSops { |
| 211 | + secrets.install.redis-password = mkIf isSops { |
111 | 212 | source = "${etcEncrypted}/redis-password.json"; |
112 | 213 | target = /run/keys/redis-password; |
113 | 214 | inputType = "binary"; |
|
117 | 218 | # For the prem case, hydrate-secrets handles the push to vault instead of sops |
118 | 219 | # TODO: add proper docker password generation creds in the Rakefile |
119 | 220 | # TODO: add more unified handling between aws and prem secrets |
120 | | - age.secrets = lib.mkIf (!isSops) { |
| 221 | + age.secrets = mkIf (!isSops) { |
121 | 222 | redis-password = { |
122 | 223 | file = config.age.encryptedRoot + "/redis/password.age"; |
123 | 224 | path = "/run/keys/redis-password"; |
|
0 commit comments