module/tv/git: add cgit

This commit is contained in:
tv 2015-06-18 20:12:05 +02:00
parent d906407a60
commit 15ede8a3a4
2 changed files with 140 additions and 3 deletions

110
modules/tv/git/cgit.nix Normal file
View File

@ -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;
}
}
'';
};
};
}

View File

@ -2,8 +2,8 @@
let let
inherit (builtins) inherit (builtins)
attrNames attrValues concatLists filter hasAttr head lessThan removeAttrs attrNames attrValues concatLists getAttr filter hasAttr head lessThan
tail toJSON typeOf; removeAttrs tail toJSON typeOf;
inherit (lib) inherit (lib)
concatMapStringsSep concatStringsSep escapeShellArg hasPrefix concatMapStringsSep concatStringsSep escapeShellArg hasPrefix
literalExample makeSearchPath mapAttrsToList mkIf mkOption optionalString literalExample makeSearchPath mapAttrsToList mkIf mkOption optionalString
@ -16,6 +16,8 @@ let
getName = x: x.name; getName = x: x.name;
isPublicRepo = getAttr "public"; # TODO this is also in ./cgit.nix
makeAuthorizedKey = command-script: user@{ name, pubkey }: makeAuthorizedKey = command-script: user@{ name, pubkey }:
# TODO assert name # TODO assert name
# TODO assert pubkey # TODO assert pubkey
@ -78,12 +80,21 @@ in
# (or kill already connected users somehow) # (or kill already connected users somehow)
{ {
imports = [
./cgit.nix
];
options.services.git = { options.services.git = {
enable = mkOption { enable = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
description = "Enable Git repository hosting."; description = "Enable Git repository hosting.";
}; };
cgit = mkOption {
type = types.bool;
default = true;
description = "Enable cgit."; # TODO better desc; talk about nginx
};
dataDir = mkOption { dataDir = mkOption {
type = types.str; type = types.str;
default = "/var/lib/git"; default = "/var/lib/git";
@ -99,6 +110,13 @@ in
repos = mkOption { repos = mkOption {
type = types.attrsOf (types.submodule ({ type = types.attrsOf (types.submodule ({
options = { options = {
desc = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Repository description.
'';
};
name = mkOption { name = mkOption {
type = types.str; type = types.str;
description = '' description = ''
@ -111,6 +129,14 @@ in
Repository-specific hooks. 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} reponame=${escapeShellArg repo.name}
repodir=$dataDir/$reponame repodir=$dataDir/$reponame
mode=${toString (if isPublicRepo repo then 0711 else 0700)}
if ! test -d "$repodir"; then if ! test -d "$repodir"; then
mkdir -m 0700 "$repodir" mkdir -m "$mode" "$repodir"
git init --bare --template=/var/empty "$repodir" git init --bare --template=/var/empty "$repodir"
chown -R git: "$repodir" chown -R git: "$repodir"
fi fi