diff options
Diffstat (limited to 'krebs/3modules')
-rw-r--r-- | krebs/3modules/build.nix | 218 | ||||
-rw-r--r-- | krebs/3modules/default.nix | 9 | ||||
-rw-r--r-- | krebs/3modules/git.nix | 201 | ||||
-rw-r--r-- | krebs/3modules/retiolum.nix | 94 | ||||
-rw-r--r-- | krebs/3modules/shared/default.nix | 1 | ||||
-rw-r--r-- | krebs/3modules/tv/default.nix | 69 |
6 files changed, 387 insertions, 205 deletions
diff --git a/krebs/3modules/build.nix b/krebs/3modules/build.nix index 0f8aec89d..0da5dd38a 100644 --- a/krebs/3modules/build.nix +++ b/krebs/3modules/build.nix @@ -28,81 +28,157 @@ let type = types.user; }; - options.krebs.build.source-version = mkOption { - type = types.enum [ 1 2 ]; - default = 1; + options.krebs.build.source = let + raw = types.either types.str types.path; + url = types.submodule { + options = { + url = mkOption { + type = types.str; + }; + rev = mkOption { + type = types.str; + }; + dev = mkOption { + type = types.str; + }; + }; + }; + in mkOption { + type = types.attrsOf (types.either types.str url); + apply = let f = mapAttrs (_: value: { + string = value; + path = toString value; + set = f value; + }.${typeOf value}); in f; + default = {}; }; - options.krebs.build.source = getAttr "v${toString config.krebs.build.source-version}" { - v1 = { - dir = mkOption { - type = let - default-host = config.krebs.current.host; - in types.attrsOf (types.submodule ({ config, ... }: { - options = { - host = mkOption { - type = types.host; - default = default-host; - }; - path = mkOption { - type = types.str; - }; - target-path = mkOption { - type = types.str; - default = "/root/${config._module.args.name}"; - }; - url = mkOption { - type = types.str; - default = "file://${config.host.name}${config.path}"; - }; - }; - })); - default = {}; - }; + options.krebs.build.populate = mkOption { + type = types.str; + default = let + source = config.krebs.build.source; + target-user = maybeEnv "target_user" "root"; + target-host = maybeEnv "target_host" config.krebs.build.host.name; + target-path = maybeEnv "target_path" "/var/src"; + out = '' + #! /bin/sh + set -eu - git = mkOption { - type = with types; attrsOf (submodule ({ config, ... }: { - options = { - url = mkOption { - type = types.str; # TODO must be shell safe - }; - rev = mkOption { - type = types.str; - }; - target-path = mkOption { - type = types.str; - default = "/root/${config._module.args.name}"; - }; - }; - })); - default = {}; - }; - }; + verbose() { + printf '+%s\n' "$(printf ' %q' "$@")" >&2 + "$@" + } - v2 = let - raw = types.either types.str types.path; - url = types.submodule { - options = { - url = mkOption { - type = types.str; - }; - rev = mkOption { - type = types.str; - }; - dev = mkOption { - type = types.str; - }; - }; - }; - in mkOption { - type = types.attrsOf (types.either types.str url); - apply = let f = mapAttrs (_: value: { - string = value; - path = toString value; - set = f value; - }.${typeOf value}); in f; - default = {}; - }; + echo ${shell.escape git-script} \ + | ssh ${shell.escape "${target-user}@${target-host}"} -T + + unset tmpdir + trap ' + rm -f "$tmpdir"/* + rmdir "$tmpdir" + trap - EXIT INT QUIT + ' EXIT INT QUIT + tmpdir=$(mktemp -dt stockholm.XXXXXXXX) + chmod 0755 "$tmpdir" + + ${concatStringsSep "\n" + (mapAttrsToList + (name: spec: let dst = removePrefix "symlink:" (get-url spec); in + "verbose ln -s ${shell.escape dst} $tmpdir/${shell.escape name}") + symlink-specs)} + + verbose proot \ + -b $tmpdir:${shell.escape target-path} \ + ${concatStringsSep " \\\n " + (mapAttrsToList + (name: spec: + "-b ${shell.escape "${get-url spec}:${target-path}/${name}"}") + file-specs)} \ + rsync \ + -f ${shell.escape "P /*"} \ + ${concatMapStringsSep " \\\n " + (name: "-f ${shell.escape "R /${name}"}") + (attrNames file-specs)} \ + --delete \ + -vFrlptD \ + ${shell.escape target-path}/ \ + ${shell.escape "${target-user}@${target-host}:${target-path}"} + ''; + + get-schema = uri: + if substring 0 1 uri == "/" + then "file" + else head (splitString ":" uri); + + has-schema = schema: uri: get-schema uri == schema; + + get-url = spec: { + string = spec; + path = toString spec; + set = get-url spec.url; + }.${typeOf spec}; + + git-specs = + filterAttrs (_: spec: has-schema "https" (get-url spec)) source // + filterAttrs (_: spec: has-schema "http" (get-url spec)) source // + filterAttrs (_: spec: has-schema "git" (get-url spec)) source; + + file-specs = + filterAttrs (_: spec: has-schema "file" (get-url spec)) source; + + symlink-specs = + filterAttrs (_: spec: has-schema "symlink" (get-url spec)) source; + + git-script = '' + #! /bin/sh + set -efu + + verbose() { + printf '+%s\n' "$(printf ' %q' "$@")" >&2 + "$@" + } + + fetch_git() {( + dst_dir=$1 + src_url=$2 + src_ref=$3 + + if ! test -e "$dst_dir"; then + git clone "$src_url" "$dst_dir" + fi + + cd "$dst_dir" + + if ! url=$(git config remote.origin.url); then + git remote add origin "$src_url" + elif test "$url" != "$src_url"; then + git remote set-url origin "$src_url" + fi + + # TODO resolve src_ref to commit hash + hash=$src_ref + + if ! test "$(git log --format=%H -1)" = "$hash"; then + git fetch origin + git checkout "$hash" -- "$dst_dir" + git checkout "$hash" + fi + + git clean -dxf + )} + + ${concatStringsSep "\n" + (mapAttrsToList + (name: spec: toString (map shell.escape [ + "verbose" + "fetch_git" + "${target-path}/${name}" + spec.url + spec.rev + ])) + git-specs)} + ''; + in out; }; }; diff --git a/krebs/3modules/default.nix b/krebs/3modules/default.nix index 65c1aa2ec..b1e0ef156 100644 --- a/krebs/3modules/default.nix +++ b/krebs/3modules/default.nix @@ -93,11 +93,12 @@ let de.krebsco = "zones"; gg23 = "hosts"; shack = "hosts"; + i = "hosts"; internet = "hosts"; + r = "hosts"; retiolum = "hosts"; }; - # XXX This overlaps with krebs.retiolum networking.extraHosts = concatStringsSep "\n" (flatten ( mapAttrsToList (hostname: host: mapAttrsToList (netname: net: @@ -105,10 +106,8 @@ let aliases = longs ++ shorts; providers = dns.split-by-provider net.aliases cfg.dns.providers; longs = providers.hosts; - shorts = - map (removeSuffix ".${cfg.search-domain}") - (filter (hasSuffix ".${cfg.search-domain}") - longs); + shorts = let s = ".${cfg.search-domain}"; in + map (removeSuffix s) (filter (hasSuffix s) longs); in map (addr: "${addr} ${toString aliases}") net.addrs ) (filterAttrs (name: host: host.aliases != []) host.nets) diff --git a/krebs/3modules/git.nix b/krebs/3modules/git.nix index e6267d7e6..11cf21b5f 100644 --- a/krebs/3modules/git.nix +++ b/krebs/3modules/git.nix @@ -27,7 +27,7 @@ let 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 + control system, using a built in cache to decrease pressure on the git server. cgit in this module is being served via fastcgi nginx.This module deploys a http://cgit.<hostname> nginx configuration and enables nginx @@ -44,48 +44,8 @@ let 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; - default = {}; - 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. - }; - }; - })); - + type = types.attrsOf subtypes.repo; default = {}; - example = literalExample '' { testing = { @@ -99,7 +59,6 @@ let testing2 = { name = "testing2"; }; } ''; - description = '' Repositories. ''; @@ -121,30 +80,158 @@ let ''; }; rules = mkOption { - type = types.unspecified; + type = types.listOf subtypes.rule; + default = []; + example = literalExample '' + singleton { + user = [ config.krebs.users.tv ]; + repo = [ testing ]; # see literal example of repos + perm = push "refs/*" (with lib.git; [ + non-fast-forward create delete merge + ]); + } + ''; + description = '' + access and permission rules for git repositories. + ''; }; }; + # TODO put into krebs/4lib/types.nix? + subtypes = { + repo = types.submodule ({ + options = { + collaborators = mkOption { + type = types.listOf types.user; + default = []; + description = '' + List of users that should be able to fetch from this repo. + + This option is currently not used by krebs.git but instead can be + used to create rules. See e.g. <stockholm/tv/2configs/git.nix> for + 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 = '' + Repository name. + ''; + }; + hooks = mkOption { + type = types.attrsOf types.str; + default = {}; + 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. + }; + }; + }); + rule = types.submodule ({ config, ... }: { + options = { + user = mkOption { + type = types.listOf types.user; + description = '' + List of users this rule should apply to. + Checked by authorize-command. + ''; + }; + repo = mkOption { + type = types.listOf subtypes.repo; + description = '' + List of repos this rule should apply to. + Checked by authorize-command. + ''; + }; + perm = mkOption { + type = types.submodule { + # TODO generate enum argument from krebs/4lib/git.nix + options = { + allow-commands = mkOption { + type = types.listOf (types.enum (with git; [ + git-receive-pack + git-upload-pack + ])); + default = []; + description = '' + List of commands the rule's users are allowed to execute. + Checked by authorize-command. + ''; + }; + allow-receive-ref = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Ref that can receive objects. + Checked by authorize-push. + ''; + }; + allow-receive-modes = mkOption { + type = types.listOf (types.enum (with git; [ + fast-forward + non-fast-forward + create + delete + merge + ])); + default = []; + description = '' + List of allowed receive modes. + Checked by pre-receive hook. + ''; + }; + }; + }; + description = '' + Permissions granted. + ''; + }; + }; + }); + }; + 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) + authorize-command = makeAuthorizeScript (map (rule: [ + (map getName (ensureList rule.user)) + (map getName (ensureList rule.repo)) + (map getName rule.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)); + + authorize-push = makeAuthorizeScript (map (rule: [ + (map getName (ensureList rule.user)) + (map getName (ensureList rule.repo)) + (ensureList rule.perm.allow-receive-ref) + (map getName rule.perm.allow-receive-modes) + ]) (filter (rule: rule.perm.allow-receive-ref != null) cfg.rules)); }; - + users.extraUsers = singleton rec { description = "Git repository hosting user"; name = "git"; diff --git a/krebs/3modules/retiolum.nix b/krebs/3modules/retiolum.nix index e0e2692a8..2bf8aa5db 100644 --- a/krebs/3modules/retiolum.nix +++ b/krebs/3modules/retiolum.nix @@ -1,6 +1,4 @@ { config, pkgs, lib, ... }: - -with builtins; with lib; let cfg = config.krebs.retiolum; @@ -31,22 +29,13 @@ let ''; }; - generateEtcHosts = mkOption { - type = types.str; - default = "both"; - description = '' - If set to <literal>short</literal>, <literal>long</literal>, or <literal>both</literal>, - then generate entries in <filename>/etc/hosts</filename> from subnets. - ''; - }; - - network = mkOption { + netname = mkOption { type = types.str; default = "retiolum"; description = '' The tinc network name. - It is used to generate long host entries, - and name the TUN device. + It is used to name the TUN device and to generate the default value for + <literal>config.krebs.retiolum.hosts</literal>. ''; }; @@ -65,10 +54,13 @@ let }; hosts = mkOption { - type = with types; either package path; - default = ../Zhosts; + type = with types; attrsOf host; + default = + filterAttrs (_: h: hasAttr cfg.netname h.nets) config.krebs.hosts; description = '' - If a path is given, then it will be used to generate an ad-hoc package. + Hosts which should be part of the tinc configuration. + Note that these hosts must have a correspondingly named network + configured, see <literal>config.krebs.retiolum.netname</literal>. ''; }; @@ -104,9 +96,7 @@ let }; imp = { - environment.systemPackages = [ tinc hosts iproute ]; - - networking.extraHosts = retiolumExtraHosts; + environment.systemPackages = [ tinc iproute ]; systemd.services.retiolum = { description = "Tinc daemon for Retiolum"; @@ -140,60 +130,20 @@ let tinc = cfg.tincPackage; - hosts = getAttr (typeOf cfg.hosts) { - package = cfg.hosts; - path = pkgs.stdenv.mkDerivation { - name = "custom-retiolum-hosts"; - src = cfg.hosts; - installPhase = '' - mkdir $out - find . -name .git -prune -o -type f -print0 \ - | xargs -0 cp --target-directory $out - ''; - }; + tinc-hosts = pkgs.stdenv.mkDerivation { + name = "${cfg.netname}-tinc-hosts"; + phases = [ "installPhase" ]; + installPhase = '' + mkdir $out + ${concatStrings (mapAttrsToList (_: host: '' + echo ${shell.escape host.nets.${cfg.netname}.tinc.config} \ + > $out/${shell.escape host.name} + '') cfg.hosts)} + ''; }; iproute = cfg.iproutePackage; - retiolumExtraHosts = import (pkgs.runCommand "retiolum-etc-hosts" - { } - '' - generate() { - (cd ${hosts} - printf \'\' - for i in `ls`; do - names=$(hostnames $i) - for j in `sed -En 's|^ *Aliases *= *(.+)|\1|p' $i`; do - names="$names $(hostnames $j)" - done - sed -En ' - s|^ *Subnet *= *([^ /]*)(/[0-9]*)? *$|\1 '"$names"'|p - ' $i - done | sort - printf \'\' - ) - } - - case ${cfg.generateEtcHosts} in - short) - hostnames() { echo "$1"; } - generate - ;; - long) - hostnames() { echo "$1.${cfg.network}"; } - generate - ;; - both) - hostnames() { echo "$1.${cfg.network} $1"; } - generate - ;; - *) - echo '""' - ;; - esac > $out - ''); - - confDir = pkgs.runCommand "retiolum" { # TODO text executable = true; @@ -203,12 +153,12 @@ let mkdir -p $out - ln -s ${hosts} $out/hosts + ln -s ${tinc-hosts} $out/hosts cat > $out/tinc.conf <<EOF Name = ${cfg.name} Device = /dev/net/tun - Interface = ${cfg.network} + Interface = ${cfg.netname} ${concatStrings (map (c : "ConnectTo = " + c + "\n") cfg.connectTo)} PrivateKeyFile = /tmp/retiolum-rsa_key.priv ${cfg.extraConfig} diff --git a/krebs/3modules/shared/default.nix b/krebs/3modules/shared/default.nix index 518e46587..91d92857b 100644 --- a/krebs/3modules/shared/default.nix +++ b/krebs/3modules/shared/default.nix @@ -50,6 +50,7 @@ in { addrs6 = ["42:0:0:0:0:0:77:1"]; aliases = [ "wolf.retiolum" + "cgit.wolf.retiolum" ]; tinc.pubkey = '' -----BEGIN RSA PUBLIC KEY----- diff --git a/krebs/3modules/tv/default.nix b/krebs/3modules/tv/default.nix index 31c1a375a..9adb0ce11 100644 --- a/krebs/3modules/tv/default.nix +++ b/krebs/3modules/tv/default.nix @@ -24,6 +24,7 @@ with lib; internet = { addrs4 = ["162.219.7.216"]; aliases = [ + "cd.i" "cd.internet" "cd.krebsco.de" "cgit.cd.krebsco.de" @@ -37,7 +38,9 @@ with lib; addrs4 = ["10.243.113.222"]; addrs6 = ["42:4522:25f8:36bb:8ccb:0150:231a:2af3"]; aliases = [ + "cd.r" "cd.retiolum" + "cgit.cd.r" "cgit.cd.retiolum" ]; tinc.pubkey = '' @@ -67,6 +70,7 @@ with lib; internet = { addrs4 = ["104.167.114.142"]; aliases = [ + "mkdir.i" "mkdir.internet" ]; }; @@ -75,7 +79,9 @@ with lib; addrs4 = ["10.243.113.223"]; addrs6 = ["42:4522:25f8:36bb:8ccb:0150:231a:2af4"]; aliases = [ + "mkdir.r" "mkdir.retiolum" + "cgit.mkdir.r" "cgit.mkdir.retiolum" ]; tinc.pubkey = '' @@ -104,6 +110,7 @@ with lib; internet = { addrs4 = ["198.147.22.115"]; aliases = [ + "ire.i" "ire.internet" "ire.krebsco.de" ]; @@ -113,6 +120,7 @@ with lib; addrs4 = ["10.243.231.66"]; addrs6 = ["42:b912:0f42:a82d:0d27:8610:e89b:490c"]; aliases = [ + "ire.r" "ire.retiolum" ]; tinc.pubkey = '' @@ -130,6 +138,59 @@ with lib; }; ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBaMjBJ/BfYlHjyn5CO0xzFNaQ0LPvMP3W9UlOs1OxGY"; }; + kaepsele = { + nets = { + internet = { + addrs4 = ["92.222.10.169"]; + aliases = [ + "kaepsele.i" + "kaepsele.internet" + # TODO "kaepsele.org" + ]; + }; + retiolum = { + addrs4 = ["10.243.166.2"]; + addrs6 = ["42:0b9d:6660:d07c:2bb7:4e91:1a01:2e7d"]; + aliases = [ + "kaepsele.r" + "kaepsele.retiolum" + ]; + tinc.pubkey = '' + -----BEGIN RSA PUBLIC KEY----- + MIIBCgKCAQEAxj7kaye4pGLou7mVRTVgtcWFjuEosJlxVg24gM7nU1EaoRnBD93/ + Y3Je7BSUbz5xMXr5SFTPSkitInL7vU+jDOf2bEpqv+uUJAJIz85494oPS9xocdWo + rQsrQRAtOg4MLD+YIoAxQm2Mc4nt2CSE1+UP4uXGxpuh0c051b+9Kmwv1bTyHB9y + y01VSkDvNyHk5eA+RGDiujBAzhi35hzTlQgCJ3REOBiq4YmE1d3qpk3oNiYUcrcu + yFzQrSRIfhXjuzIR+wxqS95HDUsewSwt9HgkjJzYF5sQZSea0/XsroFqZyTJ8iB5 + FQx2emBqB525cWKOt0f5jgyjklhozhJyiwIDAQAB + -----END RSA PUBLIC KEY----- + ''; + }; + }; + ssh.pubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDA9cDUg7qm37uOhQpdKSgpnJPWao9VZR6LFNphVcJQ++gYvVgWu6WMhigiy7DcGQSStUlXkZc4HZBBugwwNWcf7aAF6ijBuG5rVwb9AFQmSexpTOfWap33iA5f+LXYFHe7iv4Pt9TYO1ga1Ryl4EGKb7ol2h5vbKC+JiGaDejB0WqhBAyrTg4tTWO8k2JT11CrlTjNVctqV0IVAMtTc/hcJcNusnoGD4ic0QGSzEMYxcIGRNvIgWmxhI6GHeaHxXWH5fv4b0OpLlDfVUsIvEo9KVozoLGm/wgLBG/tQXKaF9qVMVgOYi9sX/hDLwhRrcD2cyAlq9djo2pMARYiriXF"; + }; + mu = { + nets = { + retiolum = { + addrs4 = ["10.243.20.01"]; + addrs6 = ["42:0:0:0:0:0:0:2001"]; + aliases = [ + "mu.r" + "mu.retiolum" + ]; + tinc.pubkey = '' + -----BEGIN RSA PUBLIC KEY----- + MIIBCgKCAQEApXErmPSn2CO4V25lqxanCGCFgxEAjdzFUiTCCu0IvELEuCc3PqVA + g4ecf8gGwPCbzMW/1txjlgbsQcm87U5enaCwzSv/pa7P9/memV74OhqEVOypFlDE + XeZczqQfNbjoLYl4cKZpTsSZmOgASXaMDrH2N37f50q35C0MQw0HRzaQM5VLrzb4 + o87MClS+yPqpvp34QjW+1lqnOKvMkr6mDrmtcAjCOs9Ma16txyfjGVFi8KmYqIs1 + QEJmyC9Uocz5zuoSLUghgVRn9yl4+MEw6++akFDwKt/eMkcSq0GPB+3Rz/WLDiBs + FK6BsssQWdwiEWpv6xIl1Fi+s7F0riq2cwIDAQAB + -----END RSA PUBLIC KEY----- + ''; + }; + }; + }; nomic = { cores = 2; dc = "tv"; #dc = "gg23"; @@ -142,7 +203,9 @@ with lib; addrs4 = ["10.243.0.110"]; addrs6 = ["42:02d5:733f:d6da:c0f5:2bb7:2b18:09ec"]; aliases = [ + "nomic.r" "nomic.retiolum" + "cgit.nomic.r" "cgit.nomic.retiolum" ]; tinc.pubkey = '' @@ -176,6 +239,7 @@ with lib; internet = { addrs4 = ["167.88.34.182"]; aliases = [ + "rmdir.i" "rmdir.internet" ]; }; @@ -184,7 +248,9 @@ with lib; addrs4 = ["10.243.113.224"]; addrs6 = ["42:4522:25f8:36bb:8ccb:0150:231a:2af5"]; aliases = [ + "rmdir.r" "rmdir.retiolum" + "cgit.rmdir.r" "cgit.rmdir.retiolum" ]; tinc.pubkey = '' @@ -231,7 +297,9 @@ with lib; addrs4 = ["10.243.13.37"]; addrs6 = ["42:0:0:0:0:0:0:1337"]; aliases = [ + "wu.r" "wu.retiolum" + "cgit.wu.r" "cgit.wu.retiolum" ]; tinc.pubkey = '' @@ -263,6 +331,7 @@ with lib; addrs4 = ["10.243.13.38"]; addrs6 = ["42:0:0:0:0:0:0:1338"]; aliases = [ + "xu.r" "xu.retiolum" ]; tinc.pubkey = '' |