@@ -140,6 +140,14 @@ let
140140 port = 3807;
141141 };
142142 };
143+ registry = lib.optionalAttrs cfg.registry.enable {
144+ enabled = true;
145+ host = cfg.registry.externalAddress;
146+ port = cfg.registry.externalPort;
147+ key = cfg.registry.keyFile;
148+ api_url = "http://${config.services.dockerRegistry.listenAddress}:${toString config.services.dockerRegistry.port}/";
149+ issuer = "gitlab-issuer";
150+ };
143151 extra = {};
144152 uploads.storage_path = cfg.statePath;
145153 };
@@ -156,7 +164,7 @@ let
156164 prometheus_multiproc_dir = "/run/gitlab";
157165 RAILS_ENV = "production";
158166 MALLOC_ARENA_MAX = "2";
159− };
167+ } // cfg.extraEnv;
160168
161169 gitlab-rake = pkgs.stdenv.mkDerivation {
162170 name = "gitlab-rake";
@@ -277,6 +285,14 @@ in {
277285 '';
278286 };
279287
288+ extraEnv = mkOption {
289+ type = types.attrsOf types.str;
290+ default = {};
291+ description = ''
292+ Additional environment variables for the GitLab environment.
293+ '';
294+ };
295+
280296 backup.startAt = mkOption {
281297 type = with types; either str (listOf str);
282298 default = [];
@@ -508,6 +524,58 @@ in {
508524 '';
509525 };
510526
527+ registry = {
528+ enable = mkOption {
529+ type = types.bool;
530+ default = false;
531+ description = "Enable GitLab container registry.";
532+ };
533+ host = mkOption {
534+ type = types.str;
535+ default = config.services.gitlab.host;
536+ description = "GitLab container registry host name.";
537+ };
538+ port = mkOption {
539+ type = types.int;
540+ default = 4567;
541+ description = "GitLab container registry port.";
542+ };
543+ certFile = mkOption {
544+ type = types.path;
545+ default = null;
546+ description = "Path to GitLab container registry certificate.";
547+ };
548+ keyFile = mkOption {
549+ type = types.path;
550+ default = null;
551+ description = "Path to GitLab container registry certificate-key.";
552+ };
553+ defaultForProjects = mkOption {
554+ type = types.bool;
555+ default = cfg.registry.enable;
556+ description = "If GitLab container registry should be enabled by default for projects.";
557+ };
558+ issuer = mkOption {
559+ type = types.str;
560+ default = "gitlab-issuer";
561+ description = "GitLab container registry issuer.";
562+ };
563+ serviceName = mkOption {
564+ type = types.str;
565+ default = "container_registry";
566+ description = "GitLab container registry service name.";
567+ };
568+ externalAddress = mkOption {
569+ type = types.str;
570+ default = "";
571+ description = "External address used to access registry from the internet";
572+ };
573+ externalPort = mkOption {
574+ type = types.int;
575+ description = "External port used to access registry from the internet";
576+ };
577+ };
578+
511579 smtp = {
512580 enable = mkOption {
513581 type = types.bool;
@@ -905,6 +973,44 @@ in {
905973 };
906974 };
907975
976+ systemd.services.gitlab-registry-cert = optionalAttrs cfg.registry.enable {
977+ path = with pkgs; [ openssl ];
978+
979+ script = ''
980+ mkdir -p $(dirname ${cfg.registry.keyFile})
981+ mkdir -p $(dirname ${cfg.registry.certFile})
982+ openssl req -nodes -newkey rsa:4096 -keyout ${cfg.registry.keyFile} -out /tmp/registry-auth.csr -subj "/CN=${cfg.registry.issuer}"
983+ openssl x509 -in /tmp/registry-auth.csr -out ${cfg.registry.certFile} -req -signkey ${cfg.registry.keyFile} -days 3650
984+ chown ${cfg.user}:${cfg.group} $(dirname ${cfg.registry.keyFile})
985+ chown ${cfg.user}:${cfg.group} $(dirname ${cfg.registry.certFile})
986+ chown ${cfg.user}:${cfg.group} ${cfg.registry.keyFile}
987+ chown ${cfg.user}:${cfg.group} ${cfg.registry.certFile}
988+ '';
989+
990+ serviceConfig = {
991+ ConditionPathExists = "!${cfg.registry.certFile}";
992+ };
993+ };
994+
995+ # Ensure Docker Registry launches after the certificate generation job
996+ systemd.services.docker-registry = optionalAttrs cfg.registry.enable {
997+ wants = [ "gitlab-registry-cert.service" ];
998+ };
999+
1000+ # Enable Docker Registry, if GitLab-Container Registry is enabled
1001+ services.dockerRegistry = optionalAttrs cfg.registry.enable {
1002+ enable = true;
1003+ enableDelete = true; # This must be true, otherwise GitLab won't manage it correctly
1004+ extraConfig = {
1005+ auth.token = {
1006+ realm = "http${if cfg.https == true then "s" else ""}://${cfg.host}/jwt/auth";
1007+ service = cfg.registry.serviceName;
1008+ issuer = cfg.registry.issuer;
1009+ rootcertbundle = cfg.registry.certFile;
1010+ };
1011+ };
1012+ };
1013+
9081014 # Use postfix to send out mails.
9091015 services.postfix.enable = mkDefault (cfg.smtp.enable && cfg.smtp.address == "localhost");
9101016