From 1dd95432a640a54b3f1049d8eb9ddb60750df71b Mon Sep 17 00:00:00 2001 From: tv Date: Thu, 23 Jul 2015 18:20:41 +0200 Subject: 2 tv git-public: s/shitment/stockholm/ --- 2configs/tv/git-public.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to '2configs/tv/git-public.nix') diff --git a/2configs/tv/git-public.nix b/2configs/tv/git-public.nix index aef8366..7babcbb 100644 --- a/2configs/tv/git-public.nix +++ b/2configs/tv/git-public.nix @@ -22,8 +22,8 @@ let (public "quipper") (public "regfish") (public' { - name = "shitment"; - desc = "turn all the computers into one computer!"; + name = "stockholm"; + desc = "take all the computers hostage, they'll love you!"; }) (public "wai-middleware-time") (public "web-routes-wai-custom") -- cgit v1.3.1 From 41b55d174d3d813f84be96b5033cffe9d7ffe926 Mon Sep 17 00:00:00 2001 From: tv Date: Fri, 24 Jul 2015 00:24:12 +0200 Subject: 2 tv git-public: simplify --- 2configs/tv/git-public.nix | 141 +++++++++++++++++++++------------------------ 1 file changed, 67 insertions(+), 74 deletions(-) (limited to '2configs/tv/git-public.nix') diff --git a/2configs/tv/git-public.nix b/2configs/tv/git-public.nix index 7babcbb..7222f99 100644 --- a/2configs/tv/git-public.nix +++ b/2configs/tv/git-public.nix @@ -1,87 +1,80 @@ { config, lib, pkgs, ... }: - -with lib; +with import ../../4lib/tv { inherit lib pkgs; }; let - inherit (builtins) map readFile; - inherit (lib) concatMap listToAttrs; - # TODO lib should already include our stuff - inherit (import ../../4lib/tv { inherit lib pkgs; }) addNames git; - - public-git-repos = [ - (public "cgserver") - (public "crude-mail-setup") - (public "dot-xmonad") - (public "hack") - (public "load-env") - (public "make-snapshot") - (public "mime") - (public "much") - (public "nixos-infest") - (public "nixpkgs") - (public "painload") - (public "quipper") - (public "regfish") - (public' { - name = "stockholm"; - desc = "take all the computers hostage, they'll love you!"; - }) - (public "wai-middleware-time") - (public "web-routes-wai-custom") - (public "xintmap") - ]; - users = addNames { - tv = { pubkey = readFile ../../Zpubkeys/tv_wu.ssh.pub; }; - lass = { pubkey = readFile ../../Zpubkeys/lass.ssh.pub; }; - uriel = { pubkey = readFile ../../Zpubkeys/uriel.ssh.pub; }; - makefu = { pubkey = readFile ../../Zpubkeys/makefu.ssh.pub; }; + out = { + imports = [ ../../3modules/tv/git.nix ]; + tv.git = { + enable = true; + root-title = "public repositories at ${config.tv.identity.self.name}"; + root-desc = "keep calm and engage"; + inherit repos rules users; + }; }; - repos = listToAttrs (map ({ repo, ... }: { name = repo.name; value = repo; }) public-git-repos); + repos = public-repos; + rules = concatMap make-rules (attrValues repos); - rules = concatMap ({ rules, ... }: rules) public-git-repos; + public-repos = mapAttrs make-public-repo { + cgserver = {}; + crude-mail-setup = {}; + dot-xmonad = {}; + hack = {}; + load-env = {}; + make-snapshot = {}; + mime = {}; + much = {}; + nixos-infest = {}; + nixpkgs = {}; + painload = {}; + quipper = {}; + regfish = {}; + stockholm = { + desc = "take all the computers hostage, they'll love you!"; + }; + wai-middleware-time = {}; + web-routes-wai-custom = {}; + xintmap = {}; + }; - public' = { name, desc }: - let - x = public name; - in - x // { repo = x.repo // { inherit desc; }; }; + # TODO move users to separate module + users = mapAttrs make-user { + tv = ../../Zpubkeys/tv_wu.ssh.pub; + lass = ../../Zpubkeys/lass.ssh.pub; + uriel = ../../Zpubkeys/uriel.ssh.pub; + makefu = ../../Zpubkeys/makefu.ssh.pub; + }; - public = repo-name: - rec { - repo = { - name = repo-name; - hooks = { - post-receive = git.irc-announce { - nick = config.networking.hostName; # TODO make this the default - channel = "#retiolum"; - server = "cd.retiolum"; - }; - }; - public = true; + make-public-repo = name: { desc ? null, ... }: { + inherit name desc; + public = true; + hooks = { + post-receive = git.irc-announce { + # TODO make nick = config.tv.identity.self.name the default + nick = config.tv.identity.self.name; + channel = "#retiolum"; + server = "cd.retiolum"; }; - rules = with git; with users; [ - { user = tv; - repo = [ repo ]; - perm = push "refs/*" [ non-fast-forward create delete merge ]; - } - { user = [ lass makefu uriel ]; - repo = [ repo ]; - perm = fetch; - } - ]; }; + }; -in + make-rules = + with git // users; + repo: + singleton { + user = tv; + repo = [ repo ]; + perm = push "refs/*" [ non-fast-forward create delete merge ]; + } ++ + optional repo.public { + user = [ lass makefu uriel ]; + repo = [ repo ]; + perm = fetch; + }; -{ - imports = [ - ../../3modules/tv/git.nix - ]; - tv.git = { - enable = true; - inherit repos rules users; - root-title = "public repositories at ${config.networking.hostName}"; - root-desc = "keep calm and engage"; + make-user = name: pubkey-file: { + inherit name; + pubkey = readFile pubkey-file; }; -} + +in out -- cgit v1.3.1 From cdb20d229315429b9be5b729233c5eec1c137f44 Mon Sep 17 00:00:00 2001 From: tv Date: Fri, 24 Jul 2015 11:44:49 +0200 Subject: 3: {tv -> krebs}.git --- 2configs/tv/git-public.nix | 4 +- 3modules/krebs/git.nix | 484 +++++++++++++++++++++++++++++++++++++++++++++ 3modules/tv/git.nix | 484 --------------------------------------------- 3 files changed, 486 insertions(+), 486 deletions(-) create mode 100644 3modules/krebs/git.nix delete mode 100644 3modules/tv/git.nix (limited to '2configs/tv/git-public.nix') diff --git a/2configs/tv/git-public.nix b/2configs/tv/git-public.nix index 7222f99..7f2b513 100644 --- a/2configs/tv/git-public.nix +++ b/2configs/tv/git-public.nix @@ -3,8 +3,8 @@ with import ../../4lib/tv { inherit lib pkgs; }; let out = { - imports = [ ../../3modules/tv/git.nix ]; - tv.git = { + imports = [ ../../3modules/krebs/git.nix ]; + krebs.git = { enable = true; root-title = "public repositories at ${config.tv.identity.self.name}"; root-desc = "keep calm and engage"; diff --git a/3modules/krebs/git.nix b/3modules/krebs/git.nix new file mode 100644 index 0000000..3c3e934 --- /dev/null +++ b/3modules/krebs/git.nix @@ -0,0 +1,484 @@ +{ config, pkgs, lib, ... }: + +# TODO unify logging of shell scripts to user and journal +# TODO move all scripts to ${etcDir}, so ControlMaster connections +# immediately pick up new authenticators +# TODO when authorized_keys changes, then restart ssh +# (or kill already connected users somehow) + +with builtins; +with lib; +let + cfg = config.krebs.git; + + out = { + # TODO don't import krebs.nginx here + imports = [ + ../../3modules/krebs/nginx.nix + ]; + options.krebs.git = api; + config = mkIf cfg.enable (mkMerge [ + (mkIf cfg.cgit cgit-imp) + git-imp + ]); + }; + + api = { + enable = mkEnableOption "krebs.git"; + + cgit = mkOption { + type = types.bool; + default = true; + description = "Enable cgit."; # TODO better desc; talk about nginx + }; + dataDir = mkOption { + type = types.str; + default = "/var/lib/git"; + description = "Directory used to store repositories."; + }; + etcDir = mkOption { + type = types.str; + default = "/etc/git"; + }; + repos = mkOption { + type = types.attrsOf (types.submodule ({ + options = { + desc = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Repository description. + ''; + }; + section = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Repository section. + ''; + }; + name = mkOption { + type = types.str; + description = '' + Repository name. + ''; + }; + hooks = mkOption { + type = types.attrsOf types.str; + description = '' + Repository-specific hooks. + ''; + }; + public = mkOption { + type = types.bool; + default = false; + description = '' + Allow everybody to read the repository via HTTP if cgit enabled. + ''; + # TODO allow every configured user to fetch the repository via SSH. + }; + }; + })); + + default = {}; + + example = literalExample '' + { + testing = { + name = "testing"; + hooks.post-update = ''' + #! /bin/sh + set -euf + echo post-update hook: $* >&2 + '''; + }; + testing2 = { name = "testing2"; }; + } + ''; + + description = '' + Repositories. + ''; + }; + root-desc = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Text printed below the heading on the repository index page. + Default value: "a fast webinterface for the git dscm". + ''; + }; + root-title = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Text printed as heading on the repository index page. + Default value: "Git Repository Browser". + ''; + }; + rules = mkOption { + type = types.unspecified; + }; + users = mkOption { + type = types.unspecified; + }; + }; + + git-imp = { + system.activationScripts.git-init = "${init-script}"; + + # TODO maybe put all scripts here and then use PATH? + environment.etc."${etc-base}".source = + scriptFarm "git-ssh-authorizers" { + authorize-command = makeAuthorizeScript (map ({ repo, user, perm }: [ + (map getName (ensureList user)) + (map getName (ensureList repo)) + (map getName perm.allow-commands) + ]) cfg.rules); + + authorize-push = makeAuthorizeScript (map ({ repo, user, perm }: [ + (map getName (ensureList user)) + (map getName (ensureList repo)) + (ensureList perm.allow-receive-ref) + (map getName perm.allow-receive-modes) + ]) (filter (x: hasAttr "allow-receive-ref" x.perm) cfg.rules)); + }; + + users.extraUsers = singleton { + description = "Git repository hosting user"; + name = "git"; + shell = "/bin/sh"; + openssh.authorizedKeys.keys = + mapAttrsToList (_: makeAuthorizedKey git-ssh-command) cfg.users; + uid = 129318403; # genid git + }; + }; + + cgit-imp = { + users.extraUsers = lib.singleton { + inherit (fcgitwrap-user) group name uid; + home = toString (pkgs.runCommand "empty" {} "mkdir -p $out"); + }; + + users.extraGroups = lib.singleton { + inherit (fcgitwrap-group) gid name; + }; + + services.fcgiwrap = { + enable = true; + user = fcgitwrap-user.name; + group = fcgitwrap-user.group; + # socketAddress = "/run/fcgiwrap.sock" (default) + # socketType = "unix" (default) + }; + + environment.etc."cgitrc".text = '' + css=/static/cgit.css + logo=/static/cgit.png + + # if you do not want that webcrawler (like google) index your site + robots=noindex, nofollow + + virtual-root=/ + + # TODO make this nicer (and/or somewhere else) + cache-root=/tmp/cgit + + cache-size=1000 + enable-commit-graph=1 + enable-index-links=1 + enable-index-owner=0 + enable-log-filecount=1 + enable-log-linecount=1 + enable-remote-branches=1 + + ${optionalString (cfg.root-title != null) "root-title=${cfg.root-title}"} + ${optionalString (cfg.root-desc != null) "root-desc=${cfg.root-desc}"} + + snapshots=0 + max-stats=year + + ${concatMapStringsSep "\n" (repo: '' + repo.url=${repo.name} + repo.path=${cfg.dataDir}/${repo.name} + ${optionalString (repo.section != null) "repo.section=${repo.section}"} + ${optionalString (repo.desc != null) "repo.desc=${repo.desc}"} + '') (filter isPublicRepo (attrValues cfg.repos))} + ''; + + system.activationScripts.cgit = '' + mkdir -m 0700 -p /tmp/cgit + chown ${toString fcgitwrap-user.uid}:${toString fcgitwrap-group.gid} /tmp/cgit + ''; + + krebs.nginx = { + enable = true; + servers.cgit = { + server-names = [ + "cgit.${config.networking.hostName}" + "cgit.${config.networking.hostName}.retiolum" + ]; + locations = [ + (nameValuePair "/" '' + include ${pkgs.nginx}/conf/fastcgi_params; + fastcgi_param SCRIPT_FILENAME ${pkgs.cgit}/cgit/cgit.cgi; + fastcgi_param PATH_INFO $uri; + fastcgi_param QUERY_STRING $args; + fastcgi_param HTTP_HOST $server_name; + fastcgi_pass unix:${config.services.fcgiwrap.socketAddress}; + '') + (nameValuePair "/static/" '' + root ${pkgs.cgit}/cgit; + rewrite ^/static(/.*)$ $1 break; + '') + ]; + }; + }; + }; + + fcgitwrap-user = { + name = "fcgiwrap"; + uid = 2867890860; # genid fcgiwrap + group = "fcgiwrap"; + }; + + fcgitwrap-group = { + name = fcgitwrap-user.name; + gid = fcgitwrap-user.uid; + }; + + + ensureList = x: + if typeOf x == "list" then x else [x]; + + getName = x: x.name; + + isPublicRepo = getAttr "public"; # TODO this is also in ./cgit.nix + + makeAuthorizedKey = git-ssh-command: user@{ name, pubkey }: + # TODO assert name + # TODO assert pubkey + let + options = concatStringsSep "," [ + ''command="exec ${git-ssh-command} ${name}"'' + "no-agent-forwarding" + "no-port-forwarding" + "no-pty" + "no-X11-forwarding" + ]; + in + "${options} ${pubkey}"; + + # [case-pattern] -> shell-script + # Create a shell script that succeeds (exit 0) when all its arguments + # match the case patterns (in the given order). + makeAuthorizeScript = + let + # TODO escape + to-pattern = x: concatStringsSep "|" (ensureList x); + go = i: ps: + if ps == [] + then "exit 0" + else '' + case ''$${toString i} in ${to-pattern (head ps)}) + ${go (i + 1) (tail ps)} + esac''; + in + patterns: '' + #! /bin/sh + set -euf + ${concatStringsSep "\n" (map (go 1) patterns)} + exit -1 + ''; + + reponames = rules: sort lessThan (unique (map (x: x.repo.name) rules)); + + # TODO makeGitHooks that uses runCommand instead of scriptFarm? + scriptFarm = + farm-name: scripts: + let + makeScript = script-name: script-string: { + name = script-name; + path = pkgs.writeScript "${farm-name}_${script-name}" script-string; + }; + in + pkgs.linkFarm farm-name (mapAttrsToList makeScript scripts); + + + git-ssh-command = pkgs.writeScript "git-ssh-command" '' + #! /bin/sh + set -euf + + PATH=${makeSearchPath "bin" (with pkgs; [ + coreutils + git + gnugrep + gnused + systemd + ])} + + abort() { + echo "error: $1" >&2 + systemd-cat -p err -t git echo "error: $1" + exit -1 + } + + GIT_SSH_USER=$1 + + systemd-cat -p info -t git echo \ + "authorizing $GIT_SSH_USER $SSH_CONNECTION $SSH_ORIGINAL_COMMAND" + + # References: The Base Definitions volume of + # POSIX.1‐2013, Section 3.278, Portable Filename Character Set + portable_filename_bre="^[A-Za-z0-9._-]\\+$" + + command=$(echo "$SSH_ORIGINAL_COMMAND" \ + | sed -n 's/^\([^ ]*\) '"'"'\(.*\)'"'"'/\1/p' \ + | grep "$portable_filename_bre" \ + || abort 'cannot read command') + + GIT_SSH_REPO=$(echo "$SSH_ORIGINAL_COMMAND" \ + | sed -n 's/^\([^ ]*\) '"'"'\(.*\)'"'"'/\2/p' \ + | grep "$portable_filename_bre" \ + || abort 'cannot read reponame') + + ${cfg.etcDir}/authorize-command \ + "$GIT_SSH_USER" "$GIT_SSH_REPO" "$command" \ + || abort 'access denied' + + repodir=${escapeShellArg cfg.dataDir}/$GIT_SSH_REPO + + systemd-cat -p info -t git \ + echo "authorized exec $command $repodir" + + export GIT_SSH_USER + export GIT_SSH_REPO + exec "$command" "$repodir" + ''; + + init-script = pkgs.writeScript "git-init" '' + #! /bin/sh + set -euf + + PATH=${makeSearchPath "bin" (with pkgs; [ + coreutils + findutils + gawk + git + gnugrep + gnused + ])} + + dataDir=${escapeShellArg cfg.dataDir} + mkdir -p "$dataDir" + + # Notice how the presence of hooks symlinks determine whether + # we manage a repositry or not. + + # Make sure that no existing repository has hooks. We can delete + # symlinks because we assume we created them. + find "$dataDir" -mindepth 2 -maxdepth 2 -name hooks -type l -delete + bad_hooks=$(find "$dataDir" -mindepth 2 -maxdepth 2 -name hooks) + if echo "$bad_hooks" | grep -q .; then + printf 'error: unknown hooks:\n%s\n' \ + "$(echo "$bad_hooks" | sed 's/^/ /')" \ + >&2 + exit -1 + fi + + # Initialize repositories. + ${concatMapStringsSep "\n" (repo: + let + hooks = scriptFarm "git-hooks" (makeHooks repo); + in + '' + reponame=${escapeShellArg repo.name} + repodir=$dataDir/$reponame + mode=${toString (if isPublicRepo repo then 0711 else 0700)} + if ! test -d "$repodir"; then + mkdir -m "$mode" "$repodir" + git init --bare --template=/var/empty "$repodir" + chown -R git:nogroup "$repodir" + fi + ln -s ${hooks} "$repodir/hooks" + '' + ) (attrValues cfg.repos)} + + # Warn about repositories that exist but aren't mentioned in the + # current configuration (and thus didn't receive a hooks symlink). + unknown_repos=$(find "$dataDir" -mindepth 1 -maxdepth 1 \ + -type d \! -exec test -e '{}/hooks' \; -print) + if echo "$unknown_repos" | grep -q .; then + printf 'warning: stale repositories:\n%s\n' \ + "$(echo "$unknown_repos" | sed 's/^/ /')" \ + >&2 + fi + ''; + + makeHooks = repo: removeAttrs repo.hooks [ "pre-receive" ] // { + pre-receive = '' + #! /bin/sh + set -euf + + PATH=${makeSearchPath "bin" (with pkgs; [ + coreutils # env + git + systemd + ])} + + accept() { + #systemd-cat -p info -t git echo "authorized $1" + accept_string="''${accept_string+$accept_string + }authorized $1" + } + reject() { + #systemd-cat -p err -t git echo "denied $1" + #echo 'access denied' >&2 + #exit_code=-1 + reject_string="''${reject_string+$reject_string + }access denied: $1" + } + + empty=0000000000000000000000000000000000000000 + + accept_string= + reject_string= + while read oldrev newrev ref; do + + if [ $oldrev = $empty ]; then + receive_mode=create + elif [ $newrev = $empty ]; then + receive_mode=delete + elif [ "$(git merge-base $oldrev $newrev)" = $oldrev ]; then + receive_mode=fast-forward + else + receive_mode=non-fast-forward + fi + + if ${cfg.etcDir}/authorize-push \ + "$GIT_SSH_USER" "$GIT_SSH_REPO" "$ref" "$receive_mode"; then + accept "$receive_mode $ref" + else + reject "$receive_mode $ref" + fi + done + + if [ -n "$reject_string" ]; then + systemd-cat -p err -t git echo "$reject_string" + exit -1 + fi + + systemd-cat -p info -t git echo "$accept_string" + + ${optionalString (hasAttr "post-receive" repo.hooks) '' + # custom post-receive hook + ${repo.hooks.post-receive}''} + ''; + }; + + etc-base = + assert (hasPrefix "/etc/" cfg.etcDir); + removePrefix "/etc/" cfg.etcDir; + +in +out diff --git a/3modules/tv/git.nix b/3modules/tv/git.nix deleted file mode 100644 index ea014e2..0000000 --- a/3modules/tv/git.nix +++ /dev/null @@ -1,484 +0,0 @@ -{ config, pkgs, lib, ... }: - -# TODO unify logging of shell scripts to user and journal -# TODO move all scripts to ${etcDir}, so ControlMaster connections -# immediately pick up new authenticators -# TODO when authorized_keys changes, then restart ssh -# (or kill already connected users somehow) - -with builtins; -with lib; -let - cfg = config.tv.git; - - out = { - # TODO don't import krebs.nginx here - imports = [ - ../../3modules/krebs/nginx.nix - ]; - options.tv.git = api; - config = mkIf cfg.enable (mkMerge [ - (mkIf cfg.cgit cgit-imp) - git-imp - ]); - }; - - api = { - enable = mkEnableOption "tv.git"; - - cgit = mkOption { - type = types.bool; - default = true; - description = "Enable cgit."; # TODO better desc; talk about nginx - }; - dataDir = mkOption { - type = types.str; - default = "/var/lib/git"; - description = "Directory used to store repositories."; - }; - etcDir = mkOption { - type = types.str; - default = "/etc/git"; - }; - repos = mkOption { - type = types.attrsOf (types.submodule ({ - options = { - desc = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - Repository description. - ''; - }; - section = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - Repository section. - ''; - }; - name = mkOption { - type = types.str; - description = '' - Repository name. - ''; - }; - hooks = mkOption { - type = types.attrsOf types.str; - description = '' - Repository-specific hooks. - ''; - }; - public = mkOption { - type = types.bool; - default = false; - description = '' - Allow everybody to read the repository via HTTP if cgit enabled. - ''; - # TODO allow every configured user to fetch the repository via SSH. - }; - }; - })); - - default = {}; - - example = literalExample '' - { - testing = { - name = "testing"; - hooks.post-update = ''' - #! /bin/sh - set -euf - echo post-update hook: $* >&2 - '''; - }; - testing2 = { name = "testing2"; }; - } - ''; - - description = '' - Repositories. - ''; - }; - root-desc = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - Text printed below the heading on the repository index page. - Default value: "a fast webinterface for the git dscm". - ''; - }; - root-title = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - Text printed as heading on the repository index page. - Default value: "Git Repository Browser". - ''; - }; - rules = mkOption { - type = types.unspecified; - }; - users = mkOption { - type = types.unspecified; - }; - }; - - git-imp = { - system.activationScripts.git-init = "${init-script}"; - - # TODO maybe put all scripts here and then use PATH? - environment.etc."${etc-base}".source = - scriptFarm "git-ssh-authorizers" { - authorize-command = makeAuthorizeScript (map ({ repo, user, perm }: [ - (map getName (ensureList user)) - (map getName (ensureList repo)) - (map getName perm.allow-commands) - ]) cfg.rules); - - authorize-push = makeAuthorizeScript (map ({ repo, user, perm }: [ - (map getName (ensureList user)) - (map getName (ensureList repo)) - (ensureList perm.allow-receive-ref) - (map getName perm.allow-receive-modes) - ]) (filter (x: hasAttr "allow-receive-ref" x.perm) cfg.rules)); - }; - - users.extraUsers = singleton { - description = "Git repository hosting user"; - name = "git"; - shell = "/bin/sh"; - openssh.authorizedKeys.keys = - mapAttrsToList (_: makeAuthorizedKey git-ssh-command) cfg.users; - uid = 129318403; # genid git - }; - }; - - cgit-imp = { - users.extraUsers = lib.singleton { - inherit (fcgitwrap-user) group name uid; - home = toString (pkgs.runCommand "empty" {} "mkdir -p $out"); - }; - - users.extraGroups = lib.singleton { - inherit (fcgitwrap-group) gid name; - }; - - services.fcgiwrap = { - enable = true; - user = fcgitwrap-user.name; - group = fcgitwrap-user.group; - # socketAddress = "/run/fcgiwrap.sock" (default) - # socketType = "unix" (default) - }; - - environment.etc."cgitrc".text = '' - css=/static/cgit.css - logo=/static/cgit.png - - # if you do not want that webcrawler (like google) index your site - robots=noindex, nofollow - - virtual-root=/ - - # TODO make this nicer (and/or somewhere else) - cache-root=/tmp/cgit - - cache-size=1000 - enable-commit-graph=1 - enable-index-links=1 - enable-index-owner=0 - enable-log-filecount=1 - enable-log-linecount=1 - enable-remote-branches=1 - - ${optionalString (cfg.root-title != null) "root-title=${cfg.root-title}"} - ${optionalString (cfg.root-desc != null) "root-desc=${cfg.root-desc}"} - - snapshots=0 - max-stats=year - - ${concatMapStringsSep "\n" (repo: '' - repo.url=${repo.name} - repo.path=${cfg.dataDir}/${repo.name} - ${optionalString (repo.section != null) "repo.section=${repo.section}"} - ${optionalString (repo.desc != null) "repo.desc=${repo.desc}"} - '') (filter isPublicRepo (attrValues cfg.repos))} - ''; - - system.activationScripts.cgit = '' - mkdir -m 0700 -p /tmp/cgit - chown ${toString fcgitwrap-user.uid}:${toString fcgitwrap-group.gid} /tmp/cgit - ''; - - krebs.nginx = { - enable = true; - servers.cgit = { - server-names = [ - "cgit.${config.networking.hostName}" - "cgit.${config.networking.hostName}.retiolum" - ]; - locations = [ - (nameValuePair "/" '' - include ${pkgs.nginx}/conf/fastcgi_params; - fastcgi_param SCRIPT_FILENAME ${pkgs.cgit}/cgit/cgit.cgi; - fastcgi_param PATH_INFO $uri; - fastcgi_param QUERY_STRING $args; - fastcgi_param HTTP_HOST $server_name; - fastcgi_pass unix:${config.services.fcgiwrap.socketAddress}; - '') - (nameValuePair "/static/" '' - root ${pkgs.cgit}/cgit; - rewrite ^/static(/.*)$ $1 break; - '') - ]; - }; - }; - }; - - fcgitwrap-user = { - name = "fcgiwrap"; - uid = 2867890860; # genid fcgiwrap - group = "fcgiwrap"; - }; - - fcgitwrap-group = { - name = fcgitwrap-user.name; - gid = fcgitwrap-user.uid; - }; - - - ensureList = x: - if typeOf x == "list" then x else [x]; - - getName = x: x.name; - - isPublicRepo = getAttr "public"; # TODO this is also in ./cgit.nix - - makeAuthorizedKey = git-ssh-command: user@{ name, pubkey }: - # TODO assert name - # TODO assert pubkey - let - options = concatStringsSep "," [ - ''command="exec ${git-ssh-command} ${name}"'' - "no-agent-forwarding" - "no-port-forwarding" - "no-pty" - "no-X11-forwarding" - ]; - in - "${options} ${pubkey}"; - - # [case-pattern] -> shell-script - # Create a shell script that succeeds (exit 0) when all its arguments - # match the case patterns (in the given order). - makeAuthorizeScript = - let - # TODO escape - to-pattern = x: concatStringsSep "|" (ensureList x); - go = i: ps: - if ps == [] - then "exit 0" - else '' - case ''$${toString i} in ${to-pattern (head ps)}) - ${go (i + 1) (tail ps)} - esac''; - in - patterns: '' - #! /bin/sh - set -euf - ${concatStringsSep "\n" (map (go 1) patterns)} - exit -1 - ''; - - reponames = rules: sort lessThan (unique (map (x: x.repo.name) rules)); - - # TODO makeGitHooks that uses runCommand instead of scriptFarm? - scriptFarm = - farm-name: scripts: - let - makeScript = script-name: script-string: { - name = script-name; - path = pkgs.writeScript "${farm-name}_${script-name}" script-string; - }; - in - pkgs.linkFarm farm-name (mapAttrsToList makeScript scripts); - - - git-ssh-command = pkgs.writeScript "git-ssh-command" '' - #! /bin/sh - set -euf - - PATH=${makeSearchPath "bin" (with pkgs; [ - coreutils - git - gnugrep - gnused - systemd - ])} - - abort() { - echo "error: $1" >&2 - systemd-cat -p err -t git echo "error: $1" - exit -1 - } - - GIT_SSH_USER=$1 - - systemd-cat -p info -t git echo \ - "authorizing $GIT_SSH_USER $SSH_CONNECTION $SSH_ORIGINAL_COMMAND" - - # References: The Base Definitions volume of - # POSIX.1‐2013, Section 3.278, Portable Filename Character Set - portable_filename_bre="^[A-Za-z0-9._-]\\+$" - - command=$(echo "$SSH_ORIGINAL_COMMAND" \ - | sed -n 's/^\([^ ]*\) '"'"'\(.*\)'"'"'/\1/p' \ - | grep "$portable_filename_bre" \ - || abort 'cannot read command') - - GIT_SSH_REPO=$(echo "$SSH_ORIGINAL_COMMAND" \ - | sed -n 's/^\([^ ]*\) '"'"'\(.*\)'"'"'/\2/p' \ - | grep "$portable_filename_bre" \ - || abort 'cannot read reponame') - - ${cfg.etcDir}/authorize-command \ - "$GIT_SSH_USER" "$GIT_SSH_REPO" "$command" \ - || abort 'access denied' - - repodir=${escapeShellArg cfg.dataDir}/$GIT_SSH_REPO - - systemd-cat -p info -t git \ - echo "authorized exec $command $repodir" - - export GIT_SSH_USER - export GIT_SSH_REPO - exec "$command" "$repodir" - ''; - - init-script = pkgs.writeScript "git-init" '' - #! /bin/sh - set -euf - - PATH=${makeSearchPath "bin" (with pkgs; [ - coreutils - findutils - gawk - git - gnugrep - gnused - ])} - - dataDir=${escapeShellArg cfg.dataDir} - mkdir -p "$dataDir" - - # Notice how the presence of hooks symlinks determine whether - # we manage a repositry or not. - - # Make sure that no existing repository has hooks. We can delete - # symlinks because we assume we created them. - find "$dataDir" -mindepth 2 -maxdepth 2 -name hooks -type l -delete - bad_hooks=$(find "$dataDir" -mindepth 2 -maxdepth 2 -name hooks) - if echo "$bad_hooks" | grep -q .; then - printf 'error: unknown hooks:\n%s\n' \ - "$(echo "$bad_hooks" | sed 's/^/ /')" \ - >&2 - exit -1 - fi - - # Initialize repositories. - ${concatMapStringsSep "\n" (repo: - let - hooks = scriptFarm "git-hooks" (makeHooks repo); - in - '' - reponame=${escapeShellArg repo.name} - repodir=$dataDir/$reponame - mode=${toString (if isPublicRepo repo then 0711 else 0700)} - if ! test -d "$repodir"; then - mkdir -m "$mode" "$repodir" - git init --bare --template=/var/empty "$repodir" - chown -R git:nogroup "$repodir" - fi - ln -s ${hooks} "$repodir/hooks" - '' - ) (attrValues cfg.repos)} - - # Warn about repositories that exist but aren't mentioned in the - # current configuration (and thus didn't receive a hooks symlink). - unknown_repos=$(find "$dataDir" -mindepth 1 -maxdepth 1 \ - -type d \! -exec test -e '{}/hooks' \; -print) - if echo "$unknown_repos" | grep -q .; then - printf 'warning: stale repositories:\n%s\n' \ - "$(echo "$unknown_repos" | sed 's/^/ /')" \ - >&2 - fi - ''; - - makeHooks = repo: removeAttrs repo.hooks [ "pre-receive" ] // { - pre-receive = '' - #! /bin/sh - set -euf - - PATH=${makeSearchPath "bin" (with pkgs; [ - coreutils # env - git - systemd - ])} - - accept() { - #systemd-cat -p info -t git echo "authorized $1" - accept_string="''${accept_string+$accept_string - }authorized $1" - } - reject() { - #systemd-cat -p err -t git echo "denied $1" - #echo 'access denied' >&2 - #exit_code=-1 - reject_string="''${reject_string+$reject_string - }access denied: $1" - } - - empty=0000000000000000000000000000000000000000 - - accept_string= - reject_string= - while read oldrev newrev ref; do - - if [ $oldrev = $empty ]; then - receive_mode=create - elif [ $newrev = $empty ]; then - receive_mode=delete - elif [ "$(git merge-base $oldrev $newrev)" = $oldrev ]; then - receive_mode=fast-forward - else - receive_mode=non-fast-forward - fi - - if ${cfg.etcDir}/authorize-push \ - "$GIT_SSH_USER" "$GIT_SSH_REPO" "$ref" "$receive_mode"; then - accept "$receive_mode $ref" - else - reject "$receive_mode $ref" - fi - done - - if [ -n "$reject_string" ]; then - systemd-cat -p err -t git echo "$reject_string" - exit -1 - fi - - systemd-cat -p info -t git echo "$accept_string" - - ${optionalString (hasAttr "post-receive" repo.hooks) '' - # custom post-receive hook - ${repo.hooks.post-receive}''} - ''; - }; - - etc-base = - assert (hasPrefix "/etc/" cfg.etcDir); - removePrefix "/etc/" cfg.etcDir; - -in -out -- cgit v1.3.1 From 4165440f467e2c573ba248ae9cdcae54d1488bc5 Mon Sep 17 00:00:00 2001 From: tv Date: Fri, 24 Jul 2015 17:34:08 +0200 Subject: autoimport 3*/{krebs,$(LOGNAME)} --- 1systems/tv/cd.nix | 12 ------------ 1systems/tv/mkdir.nix | 2 -- 1systems/tv/nomic.nix | 3 --- 1systems/tv/rmdir.nix | 2 -- 1systems/tv/wu.nix | 6 +----- 2configs/tv/consul-server.nix | 1 - 2configs/tv/git-public.nix | 1 - 2configs/tv/identity.nix | 1 - 3modules/krebs/default.nix | 11 +++++++++++ 3modules/tv/consul.nix | 1 - 3modules/tv/default.nix | 10 ++++++++++ Makefile | 27 ++++++++++++++++----------- 12 files changed, 38 insertions(+), 39 deletions(-) create mode 100644 3modules/krebs/default.nix create mode 100644 3modules/tv/default.nix (limited to '2configs/tv/git-public.nix') diff --git a/1systems/tv/cd.nix b/1systems/tv/cd.nix index bf556e0..b15b189 100644 --- a/1systems/tv/cd.nix +++ b/1systems/tv/cd.nix @@ -22,14 +22,12 @@ in }; } { - imports = [ ../../3modules/tv/ejabberd.nix ]; tv.ejabberd = { enable = true; hosts = [ "jabber.viljetic.de" ]; }; } { - imports = [ ../../3modules/krebs/github-hosts-sync.nix ]; krebs.github-hosts-sync.enable = true; tv.iptables.input-internet-accept-new-tcp = singleton config.krebs.github-hosts-sync.port; @@ -39,7 +37,6 @@ in tv.identity.self = config.tv.identity.hosts.cd; } { - imports = [ ../../3modules/tv/iptables.nix ]; tv.iptables = { enable = true; input-internet-accept-new-tcp = [ @@ -55,19 +52,11 @@ in }; } { - imports = [ - ../../3modules/tv/iptables.nix - ../../3modules/krebs/nginx.nix - ]; tv.iptables.input-internet-accept-new-tcp = singleton "http"; krebs.nginx.servers.cgit.server-names = singleton "cgit.cd.viljetic.de"; } { # TODO make public_html also available to cd, cd.retiolum (AKA default) - imports = [ - ../../3modules/tv/iptables.nix - ../../3modules/krebs/nginx.nix - ]; tv.iptables.input-internet-accept-new-tcp = singleton "http"; krebs.nginx.servers.public_html = { server-names = singleton "cd.viljetic.de"; @@ -86,7 +75,6 @@ in }; } { - imports = [ ../../3modules/krebs/retiolum.nix ]; krebs.retiolum = { enable = true; connectTo = [ diff --git a/1systems/tv/mkdir.nix b/1systems/tv/mkdir.nix index 823f044..03d0c00 100644 --- a/1systems/tv/mkdir.nix +++ b/1systems/tv/mkdir.nix @@ -15,7 +15,6 @@ with lib; tv.identity.self = config.tv.identity.hosts.mkdir; } { - imports = [ ../../3modules/tv/iptables.nix ]; tv.iptables = { enable = true; input-internet-accept-new-tcp = [ @@ -29,7 +28,6 @@ with lib; }; } { - imports = [ ../../3modules/krebs/retiolum.nix ]; krebs.retiolum = { enable = true; connectTo = [ diff --git a/1systems/tv/nomic.nix b/1systems/tv/nomic.nix index ef4a5ca..367502e 100644 --- a/1systems/tv/nomic.nix +++ b/1systems/tv/nomic.nix @@ -14,7 +14,6 @@ with lib; tv.identity.self = config.tv.identity.hosts.nomic; } { - imports = [ ../../3modules/tv/iptables.nix ]; tv.iptables = { enable = true; input-internet-accept-new-tcp = [ @@ -26,7 +25,6 @@ with lib; }; } { - imports = [ ../../3modules/krebs/nginx.nix ]; krebs.nginx = { enable = true; servers.default.locations = [ @@ -37,7 +35,6 @@ with lib; }; } { - imports = [ ../../3modules/krebs/retiolum.nix ]; krebs.retiolum = { enable = true; connectTo = [ diff --git a/1systems/tv/rmdir.nix b/1systems/tv/rmdir.nix index f15c790..497354e 100644 --- a/1systems/tv/rmdir.nix +++ b/1systems/tv/rmdir.nix @@ -15,7 +15,6 @@ with lib; tv.identity.self = config.tv.identity.hosts.rmdir; } { - imports = [ ../../3modules/tv/iptables.nix ]; tv.iptables = { enable = true; input-internet-accept-new-tcp = [ @@ -29,7 +28,6 @@ with lib; }; } { - imports = [ ../../3modules/krebs/retiolum.nix ]; krebs.retiolum = { enable = true; connectTo = [ diff --git a/1systems/tv/wu.nix b/1systems/tv/wu.nix index 0b5b828..8470a4f 100644 --- a/1systems/tv/wu.nix +++ b/1systems/tv/wu.nix @@ -24,7 +24,7 @@ in { environment.systemPackages = with pkgs; [ - # shitment + # stockholm git gnumake parallel @@ -122,7 +122,6 @@ in ]; } { - imports = [ ../../3modules/tv/iptables.nix ]; tv.iptables = { enable = true; input-internet-accept-new-tcp = [ @@ -134,7 +133,6 @@ in }; } { - imports = [ ../../3modules/krebs/nginx.nix ]; krebs.nginx = { enable = true; servers.default.locations = [ @@ -145,7 +143,6 @@ in }; } { - imports = [ ../../3modules/krebs/retiolum.nix ]; krebs.retiolum = { enable = true; connectTo = [ @@ -155,7 +152,6 @@ in }; } { - imports = [ ../../3modules/krebs/urlwatch.nix ]; krebs.urlwatch = { enable = true; mailto = "tv@wu.retiolum"; # TODO diff --git a/2configs/tv/consul-server.nix b/2configs/tv/consul-server.nix index 1c8dcb8..5d3fd55 100644 --- a/2configs/tv/consul-server.nix +++ b/2configs/tv/consul-server.nix @@ -1,7 +1,6 @@ { config, ... }: { - imports = [ ../../3modules/tv/consul.nix ]; tv.consul = rec { enable = true; diff --git a/2configs/tv/git-public.nix b/2configs/tv/git-public.nix index 7f2b513..1bf44e0 100644 --- a/2configs/tv/git-public.nix +++ b/2configs/tv/git-public.nix @@ -3,7 +3,6 @@ with import ../../4lib/tv { inherit lib pkgs; }; let out = { - imports = [ ../../3modules/krebs/git.nix ]; krebs.git = { enable = true; root-title = "public repositories at ${config.tv.identity.self.name}"; diff --git a/2configs/tv/identity.nix b/2configs/tv/identity.nix index 44208c9..bcfdc29 100644 --- a/2configs/tv/identity.nix +++ b/2configs/tv/identity.nix @@ -1,7 +1,6 @@ { config, ... }: { - imports = [ ../../3modules/tv/identity.nix ]; tv.identity = { enable = true; search = "retiolum"; diff --git a/3modules/krebs/default.nix b/3modules/krebs/default.nix new file mode 100644 index 0000000..fe94e09 --- /dev/null +++ b/3modules/krebs/default.nix @@ -0,0 +1,11 @@ +_: + +{ + imports = [ + ./github-hosts-sync.nix + ./git.nix + ./nginx.nix + ./retiolum.nix + ./urlwatch.nix + ]; +} diff --git a/3modules/tv/consul.nix b/3modules/tv/consul.nix index 312faa0..4e54c2a 100644 --- a/3modules/tv/consul.nix +++ b/3modules/tv/consul.nix @@ -10,7 +10,6 @@ let cfg = config.tv.consul; out = { - imports = [ ../../3modules/tv/iptables.nix ]; options.tv.consul = api; config = mkIf cfg.enable (mkMerge [ imp diff --git a/3modules/tv/default.nix b/3modules/tv/default.nix new file mode 100644 index 0000000..e267d0b --- /dev/null +++ b/3modules/tv/default.nix @@ -0,0 +1,10 @@ +_: + +{ + imports = [ + ./consul.nix + ./ejabberd.nix + ./identity.nix + ./iptables.nix + ]; +} diff --git a/Makefile b/Makefile index da23467..6d075e6 100644 --- a/Makefile +++ b/Makefile @@ -41,13 +41,14 @@ deploy:;@ "$$src/" "$$deploy_host:$$dst" )} - prepush /root/src/shitment "$$PWD" + prepush /root/src/stockholm "$$PWD" prepush /root/src/secrets "$$secrets_dir" ssh -S none "$$deploy_host" -T env \ nixpkgs_url="$$nixpkgs_url" \ nixpkgs_rev="$$nixpkgs_rev" \ system_name="$$system_name" \ + user_name="$$LOGNAME" \ sh -euf \ <<-\EOF prefetch(){( @@ -77,26 +78,30 @@ deploy:;@ prefetch /root/src/nixpkgs "$$nixpkgs_url" "$$nixpkgs_rev" echo build system... - NIXOS_CONFIG=/root/src/shitment/1systems/$(LOGNAME)/$$system_name.nix \ - NIX_PATH=src \ - nix-build -Q -A system '' + NIX_PATH=/root/src \ + nix-build \ + -Q \ + -A system \ + '' \ + --argstr user-name "$$user_name" \ + --argstr system-name "$$system_name" result/bin/switch-to-configuration switch EOF .PHONY: eval eval: - @nix-instantiate \ + @ + NIX_PATH=stockholm=$$PWD:$$NIX_PATH \ + nix-instantiate \ --json \ --eval \ --strict \ -A "$$get" \ - -E ' - import { - system = builtins.currentSystem; - modules = [ ./1systems/$(LOGNAME)/$(system).nix ]; - } - ' | jq -r . + '' \ + --argstr user-name "$$LOGNAME" \ + --argstr system-name "$$system" \ + | jq -r . else $(error unbound variable: system[s]) endif -- cgit v1.3.1 From e1d542e07d5ee9c26a04f273b0eb6ff8adccf756 Mon Sep 17 00:00:00 2001 From: tv Date: Fri, 24 Jul 2015 19:33:20 +0200 Subject: tv git: add restricted repos --- 1systems/tv/cd.nix | 2 +- 1systems/tv/mkdir.nix | 2 +- 1systems/tv/nomic.nix | 2 +- 1systems/tv/rmdir.nix | 2 +- 1systems/tv/wu.nix | 3 +- 2configs/tv/git-public.nix | 79 ---------------------------------- 2configs/tv/git.nix | 103 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 108 insertions(+), 85 deletions(-) delete mode 100644 2configs/tv/git-public.nix create mode 100644 2configs/tv/git.nix (limited to '2configs/tv/git-public.nix') diff --git a/1systems/tv/cd.nix b/1systems/tv/cd.nix index b15b189..d30e7ed 100644 --- a/1systems/tv/cd.nix +++ b/1systems/tv/cd.nix @@ -13,7 +13,7 @@ in ../../2configs/tv/base.nix ../../2configs/tv/consul-server.nix ../../2configs/tv/exim-smarthost.nix - ../../2configs/tv/git-public.nix + ../../2configs/tv/git.nix { imports = [ ../../2configs/tv/charybdis.nix ]; tv.charybdis = { diff --git a/1systems/tv/mkdir.nix b/1systems/tv/mkdir.nix index 03d0c00..3e5fb72 100644 --- a/1systems/tv/mkdir.nix +++ b/1systems/tv/mkdir.nix @@ -9,7 +9,7 @@ with lib; ../../2configs/tv/base.nix ../../2configs/tv/consul-server.nix ../../2configs/tv/exim-smarthost.nix - ../../2configs/tv/git-public.nix + ../../2configs/tv/git.nix { imports = [ ../../2configs/tv/identity.nix ]; tv.identity.self = config.tv.identity.hosts.mkdir; diff --git a/1systems/tv/nomic.nix b/1systems/tv/nomic.nix index 367502e..2d32d9e 100644 --- a/1systems/tv/nomic.nix +++ b/1systems/tv/nomic.nix @@ -8,7 +8,7 @@ with lib; ../../2configs/tv/base.nix ../../2configs/tv/consul-server.nix ../../2configs/tv/exim-retiolum.nix - ../../2configs/tv/git-public.nix + ../../2configs/tv/git.nix { imports = [ ../../2configs/tv/identity.nix ]; tv.identity.self = config.tv.identity.hosts.nomic; diff --git a/1systems/tv/rmdir.nix b/1systems/tv/rmdir.nix index 497354e..c470086 100644 --- a/1systems/tv/rmdir.nix +++ b/1systems/tv/rmdir.nix @@ -9,7 +9,7 @@ with lib; ../../2configs/tv/base.nix ../../2configs/tv/consul-server.nix ../../2configs/tv/exim-smarthost.nix - ../../2configs/tv/git-public.nix + ../../2configs/tv/git.nix { imports = [ ../../2configs/tv/identity.nix ]; tv.identity.self = config.tv.identity.hosts.rmdir; diff --git a/1systems/tv/wu.nix b/1systems/tv/wu.nix index 8470a4f..234b805 100644 --- a/1systems/tv/wu.nix +++ b/1systems/tv/wu.nix @@ -12,8 +12,7 @@ in ../../2configs/tv/base.nix ../../2configs/tv/consul-client.nix ../../2configs/tv/exim-retiolum.nix - ../../2configs/tv/git-public.nix - # TODO git-private.nix + ../../2configs/tv/git.nix ../../2configs/tv/mail-client.nix ../../2configs/tv/xserver.nix ../../2configs/tv/synaptics.nix # TODO w110er if xserver is enabled diff --git a/2configs/tv/git-public.nix b/2configs/tv/git-public.nix deleted file mode 100644 index 1bf44e0..0000000 --- a/2configs/tv/git-public.nix +++ /dev/null @@ -1,79 +0,0 @@ -{ config, lib, pkgs, ... }: -with import ../../4lib/tv { inherit lib pkgs; }; -let - - out = { - krebs.git = { - enable = true; - root-title = "public repositories at ${config.tv.identity.self.name}"; - root-desc = "keep calm and engage"; - inherit repos rules users; - }; - }; - - repos = public-repos; - rules = concatMap make-rules (attrValues repos); - - public-repos = mapAttrs make-public-repo { - cgserver = {}; - crude-mail-setup = {}; - dot-xmonad = {}; - hack = {}; - load-env = {}; - make-snapshot = {}; - mime = {}; - much = {}; - nixos-infest = {}; - nixpkgs = {}; - painload = {}; - quipper = {}; - regfish = {}; - stockholm = { - desc = "take all the computers hostage, they'll love you!"; - }; - wai-middleware-time = {}; - web-routes-wai-custom = {}; - xintmap = {}; - }; - - # TODO move users to separate module - users = mapAttrs make-user { - tv = ../../Zpubkeys/tv_wu.ssh.pub; - lass = ../../Zpubkeys/lass.ssh.pub; - uriel = ../../Zpubkeys/uriel.ssh.pub; - makefu = ../../Zpubkeys/makefu.ssh.pub; - }; - - make-public-repo = name: { desc ? null, ... }: { - inherit name desc; - public = true; - hooks = { - post-receive = git.irc-announce { - # TODO make nick = config.tv.identity.self.name the default - nick = config.tv.identity.self.name; - channel = "#retiolum"; - server = "cd.retiolum"; - }; - }; - }; - - make-rules = - with git // users; - repo: - singleton { - user = tv; - repo = [ repo ]; - perm = push "refs/*" [ non-fast-forward create delete merge ]; - } ++ - optional repo.public { - user = [ lass makefu uriel ]; - repo = [ repo ]; - perm = fetch; - }; - - make-user = name: pubkey-file: { - inherit name; - pubkey = readFile pubkey-file; - }; - -in out diff --git a/2configs/tv/git.nix b/2configs/tv/git.nix new file mode 100644 index 0000000..ac1c413 --- /dev/null +++ b/2configs/tv/git.nix @@ -0,0 +1,103 @@ +{ config, lib, pkgs, ... }: +with import ../../4lib/tv { inherit lib pkgs; }; +let + + out = { + krebs.git = { + enable = true; + root-title = "public repositories at ${config.tv.identity.self.name}"; + root-desc = "keep calm and engage"; + inherit repos rules users; + }; + }; + + repos = mapAttrs (_: s: removeAttrs s ["collaborators"]) ( + public-repos // + optionalAttrs config.tv.identity.self.secure restricted-repos + ); + + rules = concatMap make-rules (attrValues repos); + + public-repos = mapAttrs make-public-repo { + cgserver = {}; + crude-mail-setup = {}; + dot-xmonad = {}; + hack = {}; + load-env = {}; + make-snapshot = {}; + mime = {}; + much = {}; + nixos-infest = {}; + nixpkgs = {}; + painload = {}; + quipper = {}; + regfish = {}; + stockholm = { + desc = "take all the computers hostage, they'll love you!"; + }; + wai-middleware-time = {}; + web-routes-wai-custom = {}; + xintmap = {}; + }; + + restricted-repos = mapAttrs make-restricted-repo ( + { + brain = { + collaborators = with users; [ lass makefu ]; + }; + } // + import /root/src/secrets/repos.nix { inherit config lib pkgs users; } + ); + + # TODO move users to separate module + users = mapAttrs make-user { + tv = ../../Zpubkeys/tv_wu.ssh.pub; + lass = ../../Zpubkeys/lass.ssh.pub; + uriel = ../../Zpubkeys/uriel.ssh.pub; + makefu = ../../Zpubkeys/makefu.ssh.pub; + }; + + make-public-repo = name: { desc ? null, ... }: { + inherit name desc; + public = true; + hooks = { + post-receive = git.irc-announce { + # TODO make nick = config.tv.identity.self.name the default + nick = config.tv.identity.self.name; + channel = "#retiolum"; + server = "cd.retiolum"; + }; + }; + }; + + make-restricted-repo = name: { desc ? null, ... }: { + inherit name desc; + public = false; + hooks = {}; # TODO default + }; + + make-rules = + with git // users; + repo: + singleton { + user = tv; + repo = [ repo ]; + perm = push "refs/*" [ non-fast-forward create delete merge ]; + } ++ + optional repo.public { + user = [ lass makefu uriel ]; + repo = [ repo ]; + perm = fetch; + } ++ + optional (length (repo.collaborators or []) > 0) { + user = repo.collaborators; + repo = [ repo ]; + perm = fetch; + }; + + make-user = name: pubkey-file: { + inherit name; + pubkey = readFile pubkey-file; + }; + +in out -- cgit v1.3.1