diff options
Diffstat (limited to 'microvms/cgit/cgit.nix')
| -rw-r--r-- | microvms/cgit/cgit.nix | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/microvms/cgit/cgit.nix b/microvms/cgit/cgit.nix new file mode 100644 index 0000000..09b1048 --- /dev/null +++ b/microvms/cgit/cgit.nix @@ -0,0 +1,203 @@ +{ pkgs, lib, ... }: +let + host = "git.oxapentane.com"; + gitHome = "/var/lib/git"; + cgitPort = 8080; + + defaultBranch = "main"; + + mkCreateRepoCommand = + { + command, + visibility, + }: + pkgs.writeShellApplication { + name = command; + + runtimeInputs = [ + pkgs.coreutils + pkgs.git + pkgs.gnugrep + ]; + + text = '' + set -eu + + if [ "$#" -ne 1 ]; then + printf 'usage: ${command} NAME\n' >&2 + exit 2 + fi + + name=$1 + + # Accept either "foo" or "foo.git". + case "$name" in + *.git) + name="''${name%.git}" + ;; + esac + + # Deliberately only allow a single path component. + # This excludes traversal, slashes, spaces and shell metacharacters. + if ! printf '%s\n' "$name" \ + | grep -Eq '^[A-Za-z0-9][A-Za-z0-9._-]*$' + then + printf '%s\n' \ + 'invalid repository name: use letters, digits, ".", "_" and "-"' \ + >&2 + exit 2 + fi + + base=${lib.escapeShellArg "${gitHome}/${visibility}"} + repo="$base/$name.git" + + umask 0027 + + # mkdir is the existence check: never silently reinitialize a repo. + if ! mkdir -- "$repo" 2>/dev/null; then + printf 'repository already exists or cannot be created: %s\n' \ + "$name.git" >&2 + exit 1 + fi + + if ! git init \ + --bare \ + --initial-branch=${lib.escapeShellArg defaultBranch} \ + "$repo" \ + >/dev/null + then + printf 'failed to initialize repository: %s\n' "$name.git" >&2 + exit 1 + fi + + # Avoid Git's default "Unnamed repository..." text appearing in cgit. + : > "$repo/description" + + # This is the only successful stdout output, making $() safe. + printf '%s\n' "git@${host}:${visibility}/$name.git" + ''; + }; + + createPrivate = mkCreateRepoCommand { + command = "create"; + visibility = "private"; + }; + + createPublic = mkCreateRepoCommand { + command = "create-pub"; + visibility = "public"; + }; + + noInteractiveLogin = pkgs.writeShellScript "no-interactive-login" '' + printf '%s\n' "Interactive shell access is disabled." >&2 + exit 128 + ''; + + restrictedGitShell = + (pkgs.writeShellApplication { + name = "restricted-git-shell"; + + text = '' + umask 0027 + exec ${pkgs.git}/bin/git-shell "$@" + ''; + }).overrideAttrs (old: { + passthru = (old.passthru or { }) // { + shellPath = "/bin/restricted-git-shell"; + }; + }); +in +{ + # public repos in cgit + services.cgit."${host}" = { + enable = true; + user = "cgit"; + group = "cgit"; + scanPath = "${gitHome}/public"; + gitHttpBackend = { + enable = true; + checkExportOkFiles = false; # /public is unconditionally public anyway... + }; + + settings = { + root-title = "0xa's compilable shitposts"; + root-desc = "Public directory of my finest spaghetti"; + + remove-suffix = true; + clone-url = + "https://${host}/$CGIT_REPO_URL.git " + + "git@${host}:public/$CGIT_REPO_URL.git"; + + enable-http-clone = false; + enable-filter-overrides = false; + enable-git-config = false; + enable-http-serving = false; + + max-blob-size = 2048; + noplainemail = true; + + snapshots = ""; + }; + + nginx = { + virtualHost = host; + location = "/"; + }; + }; + + # just bind to proxy interface, everything's handeled by caddy + services.nginx.virtualHosts.${host}.listen = [ + { + addr = "10.89.88.19"; + port = cgitPort; + } + ]; + + # private - bare repos behind separate user + users.groups.git = {}; + users.users.git = { + isSystemUser = true; + group = "git"; + home = gitHome; + createHome = false; + shell = restrictedGitShell; + hashedPassword = "!"; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAXrwZsBChUhVuF5gFEfj8GwQlnrqEttAytS5jVCfuE4 0xa@frituurpan" + ]; + }; + + # enable and cofigure ssh + services.openssh = { + enable = true; + extraConfig = '' + Match User git + AuthenticationMethods publickey + PasswordAuthentication no + KbdInteractiveAuthentication no + DisableForwarding yes + PermitTTY no + PermitUserRC no + ''; + }; + + # ensure directories and rights + systemd.tmpfiles.rules = [ + "d ${gitHome} 0711 git git -" + "d ${gitHome}/public 2750 git cgit -" + "d ${gitHome}/private 0711 git git -" + "d ${gitHome}/git-shell-commands 0700 git git -" + + + "L+ ${gitHome}/git-shell-commands/create - - - - ${createPrivate}/bin/create" + "L+ ${gitHome}/git-shell-commands/create-pub - - - - ${createPublic}/bin/create-pub" + "L+ ${gitHome}/git-shell-commands/no-interactive-login - - - - ${noInteractiveLogin}" + ]; + + # dubious ownership error + systemd.services."fcgiwrap-cgit-${host}".environment = { + GIT_CONFIG_COUNT = "1"; + GIT_CONFIG_KEY_0 = "safe.directory"; + GIT_CONFIG_VALUE_0 = "${gitHome}/public/*"; + }; +} |
