From 15ede8a3a4e64f80416d70084d463a09286b5040 Mon Sep 17 00:00:00 2001 From: tv Date: Thu, 18 Jun 2015 20:12:05 +0200 Subject: [PATCH] module/tv/git: add cgit --- modules/tv/git/cgit.nix | 110 +++++++++++++++++++++++++++++++++++++ modules/tv/git/default.nix | 33 ++++++++++- 2 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 modules/tv/git/cgit.nix diff --git a/modules/tv/git/cgit.nix b/modules/tv/git/cgit.nix new file mode 100644 index 000000000..edee19909 --- /dev/null +++ b/modules/tv/git/cgit.nix @@ -0,0 +1,110 @@ +{ config, lib, pkgs, ... }: + +let + inherit (builtins) attrValues filter getAttr; + inherit (lib) concatMapStringsSep mkIf optionalString; + + cfg = config.services.git; + + isPublicRepo = getAttr "public"; # TODO this is also in ./default.nix +in + +{ + config = mkIf cfg.cgit { + + users.extraUsers = lib.singleton { + name = "fcgiwrap"; + uid = 2851179180; # genid fcgiwrap + group = "fcgiwrap"; + home = "/var/empty"; + }; + + users.extraGroups = lib.singleton { + name = "fcgiwrap"; + gid = 2851179180; # genid fcgiwrap + }; + + services.fcgiwrap = { + enable = true; + user = "fcgiwrap"; + group = "fcgiwrap"; + # socketAddress = "/run/fcgiwrap.sock" (default) + # socketType = "unix" (default) + }; + + environment.etc."cgitrc".text = '' + css=/cgit-static/cgit.css + logo=/cgit-static/cgit.png + + # if you do not want that webcrawler (like google) index your site + robots=noindex, nofollow + + virtual-root=/cgit + + # TODO make this nicer + 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 + + root-title=repositories at ${config.networking.hostName} + root-desc=keep calm and engage + + snapshots=0 + max-stats=year + + ${concatMapStringsSep "\n" (repo: '' + repo.url=${repo.name} + repo.path=${cfg.dataDir}/${repo.name} + ${optionalString (repo.desc != null) "repo.desc=${repo.desc}"} + '') (filter isPublicRepo (attrValues cfg.repos))} + ''; + + # TODO modular nginx configuration + services.nginx = + let + name = config.networking.hostName; + qname = "${name}.retiolum"; + in + { + enable = true; + httpConfig = '' + include ${pkgs.nginx}/conf/mime.types; + default_type application/octet-stream; + sendfile on; + keepalive_timeout 65; + gzip on; + server { + listen 80; + server_name ${name} ${qname} localhost; + root ${pkgs.cgit}/cgit; + + location /cgit-static { + rewrite ^/cgit-static(/.*)$ $1 break; + #expires 30d; + } + + location /cgit { + include ${pkgs.nginx}/conf/fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root/cgit.cgi; + #fastcgi_param PATH_INFO $uri; + fastcgi_split_path_info ^(/cgit/?)(.+)$; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param QUERY_STRING $args; + fastcgi_param HTTP_HOST $server_name; + fastcgi_pass unix:${config.services.fcgiwrap.socketAddress}; + } + + location / { + return 404; + } + } + ''; + }; + }; +} diff --git a/modules/tv/git/default.nix b/modules/tv/git/default.nix index d264125dc..50e2f9206 100644 --- a/modules/tv/git/default.nix +++ b/modules/tv/git/default.nix @@ -2,8 +2,8 @@ let inherit (builtins) - attrNames attrValues concatLists filter hasAttr head lessThan removeAttrs - tail toJSON typeOf; + attrNames attrValues concatLists getAttr filter hasAttr head lessThan + removeAttrs tail toJSON typeOf; inherit (lib) concatMapStringsSep concatStringsSep escapeShellArg hasPrefix literalExample makeSearchPath mapAttrsToList mkIf mkOption optionalString @@ -16,6 +16,8 @@ let getName = x: x.name; + isPublicRepo = getAttr "public"; # TODO this is also in ./cgit.nix + makeAuthorizedKey = command-script: user@{ name, pubkey }: # TODO assert name # TODO assert pubkey @@ -78,12 +80,21 @@ in # (or kill already connected users somehow) { + imports = [ + ./cgit.nix + ]; + options.services.git = { enable = mkOption { type = types.bool; default = false; description = "Enable Git repository hosting."; }; + 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"; @@ -99,6 +110,13 @@ in repos = mkOption { type = types.attrsOf (types.submodule ({ options = { + desc = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Repository description. + ''; + }; name = mkOption { type = types.str; description = '' @@ -111,6 +129,14 @@ in 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. + }; }; })); @@ -230,8 +256,9 @@ in '' reponame=${escapeShellArg repo.name} repodir=$dataDir/$reponame + mode=${toString (if isPublicRepo repo then 0711 else 0700)} if ! test -d "$repodir"; then - mkdir -m 0700 "$repodir" + mkdir -m "$mode" "$repodir" git init --bare --template=/var/empty "$repodir" chown -R git: "$repodir" fi