diff --git a/cmd/ugitd/args.go b/cmd/ugitd/args.go index 5dd586ad4dc96aaabe420f74e02da5e4f4b09777..24109585663c4b7156f95becaddbb4609d543d39 100644 --- a/cmd/ugitd/args.go +++ b/cmd/ugitd/args.go @@ -101,7 +101,6 @@ return nil }) fs.BoolVar(&c.Log.JSON, "log.json", c.Log.JSON, "Print logs in JSON(L) format") fs.StringVar(&c.RepoDir, "repo-dir", c.RepoDir, "Path to directory containing repositories") - fs.BoolVar(&c.ShowPrivate, "show-private", c.ShowPrivate, "Show private repos in web interface") fs.BoolVar(&c.SSH.Enable, "ssh.enable", c.SSH.Enable, "Enable SSH server") fs.StringVar(&c.SSH.AuthorizedKeys, "ssh.authorized-keys", c.SSH.AuthorizedKeys, "Path to authorized_keys") fs.StringVar(&c.SSH.CloneURL, "ssh.clone-url", c.SSH.CloneURL, "SSH clone URL base") diff --git a/nix/module.nix b/nix/module.nix index aed867c7806f164d1524db64f02382d7678de6b0..d544007c55b669bc4de843a580ea62fe267e4dfd 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -8,13 +8,18 @@ let cfg = config.services.ugit; pkg = pkgs.callPackage ./pkg.nix { inherit pkgs; }; yamlFormat = pkgs.formats.yaml { }; - instanceOptions = - { name, config, ... }: + configFile = pkgs.writeText "ugit.yaml" ( + builtins.readFile (yamlFormat.generate "ugit-yaml" cfg.config) + ); + authorizedKeysFile = pkgs.writeText "ugit_keys" (builtins.concatStringsSep "\n" cfg.authorizedKeys); +in +{ + options = let inherit (lib) mkEnableOption mkOption types; in { - options = { + services.ugit = { enable = mkEnableOption "Enable ugit"; package = mkOption { @@ -23,16 +28,10 @@ description = "ugit package to use"; default = pkg; }; - homeDir = mkOption { - type = types.str; - description = "ugit home directory"; - default = "/var/lib/${name}"; - }; - repoDir = mkOption { type = types.str; description = "where ugit stores repositories"; - default = "/var/lib/${name}/repos"; + default = "/var/lib/ugit/repos"; }; authorizedKeys = mkOption { @@ -44,13 +43,13 @@ authorizedKeysFile = mkOption { type = types.str; description = "path to authorized_keys file ugit uses for auth"; - default = "/var/lib/${name}/authorized_keys"; + default = "/var/lib/ugit/authorized_keys"; }; hostKeyFile = mkOption { type = types.str; description = "path to host key file (will be created if it doesn't exist)"; - default = "/var/lib/${name}/ugit_ed25519"; + default = "/var/lib/ugit/ugit_ed25519"; }; config = mkOption { @@ -61,16 +60,21 @@ }; user = mkOption { type = types.str; - default = "ugit-${name}"; + default = "ugit"; description = "User account under which ugit runs"; }; group = mkOption { type = types.str; - default = "ugit-${name}"; + default = "ugit"; description = "Group account under which ugit runs"; }; + openFirewall = mkOption { + type = types.bool; + default = false; + }; + hooks = mkOption { type = types.listOf ( types.submodule { @@ -91,133 +95,95 @@ default = [ ]; }; }; }; -in -{ - options = { - services.ugit = lib.mkOption { - type = lib.types.attrsOf (lib.types.submodule instanceOptions); - default = { }; - description = "Attribute set of ugit instances"; + config = lib.mkIf cfg.enable { + users.users."${cfg.user}" = { + home = "/var/lib/ugit"; + createHome = true; + group = "${cfg.group}"; + isSystemUser = true; + isNormalUser = false; + description = "user for ugit service"; }; - }; - config = lib.mkIf (cfg != { }) { - users.users = lib.mapAttrs' ( - name: instanceCfg: - lib.nameValuePair instanceCfg.user { - home = instanceCfg.homeDir; - createHome = true; - group = instanceCfg.group; - isSystemUser = true; - isNormalUser = false; - description = "user for ugit ${name} service"; - } - ) (lib.filterAttrs (name: instanceCfg: instanceCfg.enable) cfg); + users.groups."${cfg.group}" = { }; + networking.firewall = lib.mkIf cfg.openFirewall { + allowedTCPPorts = [ + 8448 + 8449 + ]; + }; - users.groups = lib.mapAttrs' (name: instanceCfg: lib.nameValuePair instanceCfg.group { }) ( - lib.filterAttrs (name: instanceCfg: instanceCfg.enable) cfg - ); - - systemd.services = lib.foldl' ( - acc: name: - let - instanceCfg = cfg.${name}; - in - lib.recursiveUpdate acc ( - lib.optionalAttrs instanceCfg.enable { - "ugit-${name}" = { - enable = true; - description = "ugit instance ${name}"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - path = [ - instanceCfg.package - pkgs.git - pkgs.bash + systemd.services = { + ugit = { + enable = true; + script = + let + authorizedKeysPath = + if (builtins.length cfg.authorizedKeys) > 0 then authorizedKeysFile else cfg.authorizedKeysFile; + args = [ + "--config=${configFile}" + "--repo-dir=${cfg.repoDir}" + "--ssh.authorized-keys=${authorizedKeysPath}" + "--ssh.host-key=${cfg.hostKeyFile}" ]; - serviceConfig = { - User = instanceCfg.user; - Group = instanceCfg.group; - Restart = "always"; - RestartSec = "15"; - WorkingDirectory = instanceCfg.homeDir; - ExecStart = - let - configFile = pkgs.writeText "ugit-${name}.yaml" ( - builtins.readFile (yamlFormat.generate "ugit-${name}-yaml" instanceCfg.config) - ); - authorizedKeysFile = pkgs.writeText "ugit_${name}_keys" ( - builtins.concatStringsSep "\n" instanceCfg.authorizedKeys - ); - - authorizedKeysPath = - if (builtins.length instanceCfg.authorizedKeys) > 0 then - authorizedKeysFile - else - instanceCfg.authorizedKeysFile; - args = [ - "--config=${configFile}" - "--repo-dir=${instanceCfg.repoDir}" - "--ssh.authorized-keys=${authorizedKeysPath}" - "--ssh.host-key=${instanceCfg.hostKeyFile}" - ]; - in - "${instanceCfg.package}/bin/ugitd ${builtins.concatStringsSep " " args}"; - }; - }; - - "ugit-${name}-hooks" = { - description = "Setup hooks for ugit instance ${name}"; - wantedBy = [ "multi-user.target" ]; - after = [ "ugit-${name}.service" ]; - requires = [ "ugit-${name}.service" ]; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - User = instanceCfg.user; - Group = instanceCfg.group; - ExecStart = - let - hookDir = "${instanceCfg.repoDir}/hooks/pre-receive.d"; - mkHookScript = + in + "${cfg.package}/bin/ugitd ${builtins.concatStringsSep " " args}"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + path = [ + cfg.package + pkgs.git + pkgs.bash + ]; + serviceConfig = { + User = cfg.user; + Group = cfg.group; + Restart = "always"; + RestartSec = "15"; + WorkingDirectory = "/var/lib/ugit"; + }; + }; + ugit-hooks = { + wantedBy = [ "multi-user.target" ]; + after = [ "ugit.service" ]; + requires = [ "ugit.service" ]; + serviceConfig = { + Type = "oneshot"; + ExecStart = + let + script = pkgs.writeShellScript "ugit-hooks-link" ( + builtins.concatStringsSep "\n" ( + map ( hook: let - script = pkgs.writeShellScript "ugit-${name}-${hook.name}" hook.content; + script = pkgs.writeShellScript hook.name hook.content; + path = "${cfg.repoDir}/hooks/pre-receive.d/${hook.name}"; in - '' - mkdir -p ${hookDir} - ln -sf ${script} ${hookDir}/${hook.name} - ''; - in - pkgs.writeShellScript "ugit-${name}-hooks-setup" '' - ${builtins.concatStringsSep "\n" (map mkHookScript instanceCfg.hooks)} - ''; + "ln -s ${script} ${path}" + ) cfg.hooks + ) + ); + in + "${script}"; + }; + }; + }; + + systemd.tmpfiles.settings.ugit = builtins.listToAttrs ( + map ( + hook: + let + script = pkgs.writeShellScript hook.name hook.content; + path = "${cfg.repoDir}/hooks/pre-receive.d/${hook.name}"; + in + { + name = path; + value = { + "L" = { + argument = "${script}"; }; }; } - ) - ) { } (builtins.attrNames cfg); - - systemd.tmpfiles.settings = lib.mapAttrs' ( - name: instanceCfg: - lib.nameValuePair "ugit-${name}" ( - builtins.listToAttrs ( - map ( - hook: - let - script = pkgs.writeShellScript hook.name hook.content; - path = "${instanceCfg.repoDir}/hooks/pre-receive.d/${hook.name}"; - in - { - name = path; - value = { - "L" = { - argument = "${script}"; - }; - }; - } - ) instanceCfg.hooks - ) - ) - ) (lib.filterAttrs (name: instanceCfg: instanceCfg.enable) cfg); + ) cfg.hooks + ); }; }