Skip to content

Commit bfc3697

Browse files
committed
imp: adds auto-repair service to docker-registry module
1 parent 39fb844 commit bfc3697

File tree

1 file changed

+113
-12
lines changed

1 file changed

+113
-12
lines changed

modules/docker-registry.nix

Lines changed: 113 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
etcEncrypted,
66
...
77
}: 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+
812
deployType = config.currentCoreNode.deployType or config.currentAwsAutoScalingGroup.deployType;
913
domain =
1014
config
@@ -15,18 +19,20 @@
1519
}
1620
.domain;
1721
isSops = deployType == "aws";
18-
relEncryptedFolder = lib.last (builtins.split "-" (toString config.secrets.encryptedRoot));
22+
relEncryptedFolder = last (builtins.split "-" (toString config.secrets.encryptedRoot));
1923
cfg = config.services.docker-registry;
2024
in {
2125
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;
2530
default = "registry.${domain}";
2631
description = "The default host fqdn for the traefik routed registry service.";
2732
};
28-
traefikTags = lib.mkOption {
29-
type = with lib.types; listOf str;
33+
34+
traefikTags = mkOption {
35+
type = listOf str;
3036
default = [
3137
"ingress"
3238
"traefik.enable=true"
@@ -45,16 +51,79 @@ in {
4551
a basic-auth file for registry authentication.
4652
'';
4753
};
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+
};
48117
};
49118

50-
config = lib.mkIf cfg.enable {
119+
config = mkIf cfg.enable {
51120
networking.firewall.allowedTCPPorts = [
52121
config.services.dockerRegistry.port
53122
];
54123

55124
services = {
56125
dockerRegistry = {
57-
enable = lib.mkDefault true;
126+
enable = mkDefault true;
58127
enableDelete = true;
59128
enableGarbageCollect = true;
60129
enableRedisCache = true;
@@ -97,8 +166,40 @@ in {
97166
})
98167
.systemdService;
99168

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])}"
102203
103204
if [ ! -s ${relEncryptedFolder}/redis-password.json ]; then
104205
xkcdpass \
@@ -107,7 +208,7 @@ in {
107208
fi
108209
'';
109210

110-
secrets.install.redis-password = lib.mkIf isSops {
211+
secrets.install.redis-password = mkIf isSops {
111212
source = "${etcEncrypted}/redis-password.json";
112213
target = /run/keys/redis-password;
113214
inputType = "binary";
@@ -117,7 +218,7 @@ in {
117218
# For the prem case, hydrate-secrets handles the push to vault instead of sops
118219
# TODO: add proper docker password generation creds in the Rakefile
119220
# TODO: add more unified handling between aws and prem secrets
120-
age.secrets = lib.mkIf (!isSops) {
221+
age.secrets = mkIf (!isSops) {
121222
redis-password = {
122223
file = config.age.encryptedRoot + "/redis/password.age";
123224
path = "/run/keys/redis-password";

0 commit comments

Comments
 (0)