/ systems / modules / dev / containers-image-mirroring.nix
containers-image-mirroring.nix
 1  { config, lib, pkgs, ... }:
 2  
 3  let
 4    inherit (lib) mkEnableOption mkOption mkIf types;
 5    cfg = config.modules.dev.containers.image-mirroring;
 6    settingsFormat = pkgs.formats.yaml { };
 7    settingsFile = settingsFormat.generate "sync.yaml" cfg.settings;
 8  in
 9  {
10    ##### interface
11    options = {
12      modules.dev.containers.image-mirroring = {
13        enable = mkEnableOption "Enable container image mirroring service";
14        targets = mkOption {
15          type = types.listOf types.str;
16          example = [ "quay.io/vdemeest" "ghcr.io/vdemeester" ];
17          description = lib.mdDoc ''
18            A list of targets to sync images to. It will use the same
19            sync configuration to push on all.
20          '';
21        };
22        settings = mkOption {
23          type = settingsFormat.type;
24          default = { };
25          example = {
26            "docker.io" = {
27              "vdemeester/foo" = [ "latest" "bar" ];
28            };
29            "quay.io" = {
30              "buildah/stable" = [ "latest" ];
31            };
32          };
33          description = lib.mdDoc ''
34            Configuration of the image to sync, using skopeo-sync.
35            See skopeo-sync(1) for the content. 
36          '';
37        };
38      };
39    };
40    ##### implementation
41    config = mkIf cfg.enable {
42      systemd.services.container-image-mirroring = {
43        description = "Synchronize docker images to a set of targets";
44        requires = [ "network-online.target" ];
45  
46        restartIfChanged = false;
47        unitConfig.X-StopOnRemoval = false;
48  
49        serviceConfig = {
50          Type = "oneshot";
51          User = "vincent";
52          OnFailure = "status-email-root@%.service";
53        };
54  
55        path = with pkgs; [ skopeo ];
56        # ./scripts/docker.mirroring.script.sh;
57        script = ''
58          BUILDTMPDIR=$(mktemp -d)
59          trap 'rm -rf -- "$BUILDTMPDIR"' EXIT
60  
61  
62          # Pull to dir first
63          skopeo sync --preserve-digests --src yaml --dest dir \
64                 ${settingsFile} \
65                 $BUILDTMPDIR
66  
67          # Push to targets
68          for target in ${lib.strings.concatStringsSep " " cfg.targets}; do
69              skopeo sync --preserve-digests --src dir --dest docker \
70                     $BUILDTMPDIR \
71                     $target
72          done
73        '';
74  
75        after = [ "network-online.target" ];
76        # Make it configurable ?
77        startAt = "weekly";
78      };
79    };
80  }