diff options
author | lassulus <lass@aidsballs.de> | 2016-06-12 21:37:27 +0200 |
---|---|---|
committer | lassulus <lass@aidsballs.de> | 2016-06-12 21:37:27 +0200 |
commit | 4e001014c925288834a31ecf14345b34c1e7e212 (patch) | |
tree | 876860b97bbbc82108a74897834d67e05a21df49 /krebs | |
parent | 5dfc8d41d91fd6a48fb55e34e2b12d2012d37a38 (diff) | |
parent | ac3b87b9a62929a81d2a275b808681352cc3c10e (diff) |
Merge remote-tracking branch 'cd/master'
Diffstat (limited to 'krebs')
-rw-r--r-- | krebs/3modules/git.nix | 294 | ||||
-rw-r--r-- | krebs/4lib/default.nix | 2 | ||||
-rw-r--r-- | krebs/4lib/types.nix | 27 | ||||
-rw-r--r-- | krebs/5pkgs/builders.nix | 20 | ||||
-rw-r--r-- | krebs/5pkgs/cgit/default.nix | 64 | ||||
-rw-r--r-- | krebs/5pkgs/default.nix | 2 |
6 files changed, 224 insertions, 185 deletions
diff --git a/krebs/3modules/git.nix b/krebs/3modules/git.nix index d2d73ba3d..0f5e3172e 100644 --- a/krebs/3modules/git.nix +++ b/krebs/3modules/git.nix @@ -13,7 +13,7 @@ let out = { options.krebs.git = api; config = with lib; mkIf cfg.enable (mkMerge [ - (mkIf cfg.cgit cgit-imp) + (mkIf cfg.cgit.enable cgit-imp) git-imp ]); }; @@ -22,10 +22,33 @@ let enable = mkEnableOption "krebs.git"; cgit = mkOption { - type = types.bool; - default = true; + type = types.submodule { + options = { + enable = mkEnableOption "krebs.git.cgit" // { default = true; }; + fcgiwrap = { + group = mkOption { + type = types.group; + default = { + name = "fcgiwrap"; + }; + }; + user = mkOption { + type = types.user; + default = { + name = "fcgiwrap"; + home = toString pkgs.empty; + }; + }; + }; + settings = mkOption { + apply = flip removeAttrs ["_module"]; + default = {}; + type = subtypes.cgit-settings; + }; + }; + }; + default = {}; description = '' - Enable cgit. Cgit is an attempt to create a fast web interface for the git version control system, using a built in cache to decrease pressure on the git server. @@ -40,7 +63,11 @@ let description = "Directory used to store repositories."; }; etcDir = mkOption { - type = types.str; + type = mkOptionType { + name = "${types.absolute-pathname.name} starting with `/etc/'"; + check = x: types.absolute-pathname.check x && hasPrefix "/etc/" x; + merge = mergeOneOption; + }; default = "/etc/git"; }; repos = mkOption { @@ -63,22 +90,6 @@ let 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.listOf subtypes.rule; default = []; @@ -95,12 +106,117 @@ let access and permission rules for git repositories. ''; }; + + user = mkOption { + type = types.user; + default = { + name = "git"; + home = toString pkgs.empty; + }; + }; }; # TODO put into krebs/4lib/types.nix? subtypes = { - repo = types.submodule ({ + cgit-settings = types.submodule { + # A setting's value of `null` means cgit's default should be used. options = { + cache-root = mkOption { + type = types.absolute-pathname; + default = "/tmp/cgit"; + }; + cache-size = mkOption { + type = types.uint; + default = 1000; + }; + css = mkOption { + type = types.absolute-pathname; + default = "/static/cgit.css"; + }; + enable-commit-graph = mkOption { + type = types.bool; + default = true; + }; + enable-index-links = mkOption { + type = types.bool; + default = true; + }; + enable-index-owner = mkOption { + type = types.bool; + default = false; + }; + enable-log-filecount = mkOption { + type = types.bool; + default = true; + }; + enable-log-linecount = mkOption { + type = types.bool; + default = true; + }; + enable-remote-branches = mkOption { + type = types.bool; + default = true; + }; + logo = mkOption { + type = types.absolute-pathname; + default = "/static/cgit.png"; + }; + max-stats = mkOption { + type = + types.nullOr (types.enum ["week" "month" "quarter" "year"]); + default = "year"; + }; + robots = mkOption { + type = types.nullOr (types.listOf types.str); + default = ["nofollow" "noindex"]; + }; + root-desc = mkOption { + type = types.nullOr types.str; + default = null; + }; + root-title = mkOption { + type = types.nullOr types.str; + default = null; + }; + virtual-root = mkOption { + type = types.nullOr types.absolute-pathname; + default = "/"; + }; + }; + }; + repo = types.submodule ({ config, ... }: { + options = { + cgit = { + desc = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Repository description. + ''; + }; + path = mkOption { + type = types.str; + default = "${cfg.dataDir}/${config.name}"; + description = '' + An absolute path to the repository directory. For non-bare + repositories this is the .git-directory. + ''; + }; + section = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Repository section. + ''; + }; + url = mkOption { + type = types.str; + default = config.name; + description = '' + The relative url used to access the repository. + ''; + }; + }; collaborators = mkOption { type = types.listOf types.user; default = []; @@ -112,20 +228,6 @@ let an example. ''; }; - 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 = '' @@ -216,90 +318,80 @@ let system.activationScripts.git-init = "${init-script}"; # TODO maybe put all scripts here and then use PATH? - environment.etc."${etc-base}".source = + environment.etc.${removePrefix "/etc/" cfg.etcDir}.source = scriptFarm "git-ssh-authorizers" { authorize-command = makeAuthorizeScript (map (rule: [ - (map getName (ensureList rule.user)) - (map getName (ensureList rule.repo)) + (map getName (toList rule.user)) + (map getName (toList rule.repo)) (map getName rule.perm.allow-commands) ]) cfg.rules); authorize-push = makeAuthorizeScript (map (rule: [ - (map getName (ensureList rule.user)) - (map getName (ensureList rule.repo)) - (ensureList rule.perm.allow-receive-ref) + (map getName (toList rule.user)) + (map getName (toList rule.repo)) + (toList rule.perm.allow-receive-ref) (map getName rule.perm.allow-receive-modes) ]) (filter (rule: rule.perm.allow-receive-ref != null) cfg.rules)); }; - # TODO cfg.user - users.users.git = rec { + users.users.${cfg.user.name} = { + inherit (cfg.user) home name uid; description = "Git repository hosting user"; - name = "git"; shell = "/bin/sh"; openssh.authorizedKeys.keys = mapAttrsToList (_: makeAuthorizedKey git-ssh-command) (filterAttrs (_: user: isString user.pubkey) config.krebs.users); - uid = genid name; }; }; 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; + users = { + groups.${cfg.cgit.fcgiwrap.group.name} = { + inherit (cfg.cgit.fcgiwrap.group) name gid; + }; + users.${cfg.cgit.fcgiwrap.user.name} = { + inherit (cfg.cgit.fcgiwrap.user) home name uid; + group = cfg.cgit.fcgiwrap.group.name; + }; }; services.fcgiwrap = { enable = true; - user = fcgitwrap-user.name; - group = fcgitwrap-user.group; + user = cfg.cgit.fcgiwrap.user.name; + group = cfg.cgit.fcgiwrap.group.name; # 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))} - ''; + environment.etc."cgitrc".text = let + repo-to-cgitrc = _: repo: + optionals (isPublicRepo repo) (concatLists [ + [""] # empty line + [(kv-to-cgitrc "repo.url" repo.cgit.url)] + (mapAttrsToList kv-to-cgitrc + (mapAttrs' (k: nameValuePair "repo.${k}") + (removeAttrs repo.cgit ["url"]))) + ]); + + kv-to-cgitrc = k: v: getAttr (typeOf v) { + bool = kv-to-cgitrc k (if v then 1 else 0); + null = []; # This will be removed by `flatten`. + list = "${k}=${concatStringsSep ", " v}"; + int = "${k}=${toString v}"; + string = "${k}=${v}"; + }; + in + concatStringsSep "\n" + (flatten ( + mapAttrsToList kv-to-cgitrc cfg.cgit.settings + ++ + mapAttrsToList repo-to-cgitrc cfg.repos + )); system.activationScripts.cgit = '' - mkdir -m 0700 -p /tmp/cgit - chown ${toString fcgitwrap-user.uid}:${toString fcgitwrap-group.gid} /tmp/cgit + mkdir -m 0700 -p ${cfg.cgit.settings.cache-root} + chown ${toString cfg.cgit.fcgiwrap.user.uid}:${toString cfg.cgit.fcgiwrap.group.gid} ${cfg.cgit.settings.cache-root} ''; krebs.nginx = { @@ -307,6 +399,7 @@ let servers.cgit = { server-names = [ "cgit.${config.networking.hostName}" + "cgit.${config.networking.hostName}.r" "cgit.${config.networking.hostName}.retiolum" ]; locations = [ @@ -327,21 +420,6 @@ let }; }; - fcgitwrap-user = rec { - name = "fcgiwrap"; - uid = genid name; - 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 @@ -366,7 +444,7 @@ let makeAuthorizeScript = let # TODO escape - to-pattern = x: concatStringsSep "|" (ensureList x); + to-pattern = x: concatStringsSep "|" (toList x); go = i: ps: if ps == [] then "exit 0" @@ -567,9 +645,5 @@ let ''; }; - etc-base = - assert (hasPrefix "/etc/" cfg.etcDir); - removePrefix "/etc/" cfg.etcDir; - in out diff --git a/krebs/4lib/default.nix b/krebs/4lib/default.nix index 585bd313f..bfe8c581c 100644 --- a/krebs/4lib/default.nix +++ b/krebs/4lib/default.nix @@ -41,8 +41,6 @@ let out = rec { mapAttrs (name: _: path + "/${name}") (filterAttrs (_: eq "directory") (readDir path)); - getAttrDef = name: set: set.${name} or set.default or null; - mapAttrValues = f: mapAttrs (_: f); setAttr = name: value: set: set // { ${name} = value; }; optionalTrace = c: msg: x: if c then trace msg x else x; diff --git a/krebs/4lib/types.nix b/krebs/4lib/types.nix index 66191d0b3..4742877a7 100644 --- a/krebs/4lib/types.nix +++ b/krebs/4lib/types.nix @@ -154,6 +154,12 @@ types // rec { merge = mergeOneOption; }; + uint = mkOptionType { + name = "unsigned integer"; + check = x: isInt x && x >= 0; + merge = mergeOneOption; + }; + secret-file = submodule ({ config, ... }: { options = { path = mkOption { type = str; }; @@ -199,8 +205,9 @@ types // rec { description = '' Set of user's PGP public keys. - Modules supporting PGP may use well-known key names to define option - defaults, e.g. using `getAttrDef well-known-name pubkeys`. + Modules supporting PGP may use well-known key names to define + default values for options, in which case the well-known name + should be documented in the respective option's description. ''; }; pubkey = mkOption { @@ -318,10 +325,7 @@ types // rec { # POSIX.1‐2013, 3.278 Portable Filename Character Set filename = mkOptionType { name = "POSIX filename"; - check = let - filename-chars = stringToCharacters - "-.0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - in s: all (flip elem filename-chars) (stringToCharacters s); + check = x: match "([0-9A-Za-z._])[0-9A-Za-z._-]*" x != null; merge = mergeOneOption; }; @@ -330,19 +334,24 @@ types // rec { # TODO two slashes absolute-pathname = mkOptionType { name = "POSIX absolute pathname"; - check = s: pathname.check s && substring 0 1 s == "/"; + check = x: let xs = splitString "/" x; xa = head xs; in + xa == "/" || (xa == "" && all filename.check (tail xs)); + merge = mergeOneOption; }; # POSIX.1‐2013, 3.267 Pathname # TODO normalize slashes pathname = mkOptionType { name = "POSIX pathname"; - check = s: isString s && all filename.check (splitString "/" s); + check = x: let xs = splitString "/" x; in + all filename.check (if head xs == "" then tail xs else xs); + merge = mergeOneOption; }; # POSIX.1-2013, 3.431 User Name username = mkOptionType { name = "POSIX username"; - check = s: filename.check s && substring 0 1 s != "-"; + check = filename.check; + merge = mergeOneOption; }; } diff --git a/krebs/5pkgs/builders.nix b/krebs/5pkgs/builders.nix index f60bbc9d0..8ba0ab5a7 100644 --- a/krebs/5pkgs/builders.nix +++ b/krebs/5pkgs/builders.nix @@ -81,6 +81,26 @@ rec { mv "$textPath" $out ''; + writeFiles = name: specs0: + let + specs = mapAttrsToList (path: spec0: { + path = assert types.pathname.check path; path; + var = "file_${hashString "sha1" path}"; + text = spec0.text; + }) specs0; + + filevars = genAttrs' specs (spec: nameValuePair spec.var spec.text); + + env = filevars // { passAsFile = attrNames filevars; }; + in + pkgs.runCommand name env /* sh */ '' + set -efu + PATH=${makeBinPath [pkgs.coreutils]} + ${concatMapStrings (spec: /* sh */ '' + install -D ''$${spec.var}Path $out${spec.path} + '') specs} + ''; + writeHaskell = k: let diff --git a/krebs/5pkgs/cgit/default.nix b/krebs/5pkgs/cgit/default.nix deleted file mode 100644 index 3180a5bd3..000000000 --- a/krebs/5pkgs/cgit/default.nix +++ /dev/null @@ -1,64 +0,0 @@ -{ stdenv, fetchurl, openssl, zlib, asciidoc, libxml2, libxslt -, docbook_xml_xslt, pkgconfig, luajit -, gzip, bzip2, xz -}: - -stdenv.mkDerivation rec { - name = "cgit-${version}"; - version = "0.12"; - - src = fetchurl { - url = "http://git.zx2c4.com/cgit/snapshot/${name}.tar.xz"; - sha256 = "1dx54hgfyabmg9nm5qp6d01f54nlbqbbdwhwl0llb9imjf237qif"; - }; - - # cgit is tightly coupled with git and needs a git source tree to build. - # IMPORTANT: Remember to check which git version cgit needs on every version - # bump (look in the Makefile). - # NOTE: as of 0.10.1, the git version is compatible from 1.9.0 to - # 1.9.2 (see the repository history) - gitSrc = fetchurl { - url = "mirror://kernel/software/scm/git/git-2.7.2.tar.xz"; - sha256 = "086ga30ksijfxad085ply83ddf955d2b8qxph5sw6c9hab77j15j"; - }; - - buildInputs = [ - openssl zlib asciidoc libxml2 libxslt docbook_xml_xslt pkgconfig luajit - ]; - - postPatch = '' - sed -e 's|"gzip"|"${gzip}/bin/gzip"|' \ - -e 's|"bzip2"|"${bzip2}/bin/bzip2"|' \ - -e 's|"xz"|"${xz}/bin/xz"|' \ - -i ui-snapshot.c - ''; - - # Give cgit a git source tree and pass configuration parameters (as make - # variables). - preBuild = '' - mkdir -p git - tar --strip-components=1 -xf "$gitSrc" -C git - - makeFlagsArray+=(prefix="$out" CGIT_SCRIPT_PATH="$out/cgit/") - ''; - - # Install manpage. - postInstall = '' - # xmllint fails: - #make install-man - - # bypassing xmllint works: - a2x --no-xmllint -f manpage cgitrc.5.txt - mkdir -p "$out/share/man/man5" - cp cgitrc.5 "$out/share/man/man5" - ''; - - meta = { - homepage = http://git.zx2c4.com/cgit/about/; - repositories.git = git://git.zx2c4.com/cgit; - description = "Web frontend for git repositories"; - license = stdenv.lib.licenses.gpl2; - platforms = stdenv.lib.platforms.linux; - maintainers = with stdenv.lib.maintainers; [ bjornfor ]; - }; -} diff --git a/krebs/5pkgs/default.nix b/krebs/5pkgs/default.nix index 53fc4de44..f2bbaf7f4 100644 --- a/krebs/5pkgs/default.nix +++ b/krebs/5pkgs/default.nix @@ -20,6 +20,8 @@ with config.krebs.lib; (filterAttrs (_: dir.has-default-nix) (subdirsOf ./.)) // { + empty = pkgs.runCommand "empty-1.0.0" {} "mkdir $out"; + haskellPackages = pkgs.haskellPackages.override { overrides = self: super: mapAttrs (name: path: self.callPackage path {}) |