summaryrefslogtreecommitdiffstats
path: root/krebs
diff options
context:
space:
mode:
authormakefu <makefu@nixos.dev>2016-01-18 12:50:20 +0100
committermakefu <makefu@nixos.dev>2016-01-18 12:50:20 +0100
commitf4754010336a1d7c876bc6797a44f30e3d4b4ead (patch)
treede4dff5340b76d970cc404146e688726e4446e0f /krebs
parentb86daca11669019d3c2218e623bfb57b5a8033d7 (diff)
parentde891cf43181d28cbc9526993df4e55022d230da (diff)
Merge branch 'master' of gum:stockholm
Diffstat (limited to 'krebs')
-rw-r--r--krebs/3modules/Reaktor.nix47
-rw-r--r--krebs/3modules/apt-cacher-ng.nix6
-rw-r--r--krebs/3modules/backup.nix286
-rw-r--r--krebs/3modules/bepasty-server.nix4
-rw-r--r--krebs/3modules/buildbot/master.nix385
-rw-r--r--krebs/3modules/buildbot/slave.nix186
-rw-r--r--krebs/3modules/default.nix3
-rw-r--r--krebs/3modules/exim-retiolum.nix20
-rw-r--r--krebs/3modules/fetchWallpaper.nix2
-rw-r--r--krebs/3modules/git.nix8
-rw-r--r--krebs/3modules/github-hosts-sync.nix4
-rw-r--r--krebs/3modules/go.nix5
-rw-r--r--krebs/3modules/makefu/default.nix11
-rw-r--r--krebs/3modules/realwallpaper.nix10
-rw-r--r--krebs/3modules/retiolum.nix4
-rw-r--r--krebs/3modules/shared/default.nix1
-rw-r--r--krebs/3modules/tinc_graphs.nix2
-rw-r--r--krebs/3modules/urlwatch.nix5
-rw-r--r--krebs/4lib/default.nix3
-rw-r--r--krebs/4lib/genid.nix37
-rw-r--r--krebs/4lib/types.nix17
-rw-r--r--krebs/5pkgs/Reaktor/plugins.nix120
-rw-r--r--krebs/5pkgs/Reaktor/scripts/random-emoji.sh6
-rw-r--r--krebs/5pkgs/Reaktor/scripts/random-issue.sh20
-rw-r--r--krebs/5pkgs/Reaktor/scripts/sed-plugin.py53
-rw-r--r--krebs/5pkgs/Reaktor/scripts/shack-correct.sh6
-rw-r--r--krebs/5pkgs/cacpanel/default.nix4
-rw-r--r--krebs/5pkgs/default.nix6
-rw-r--r--krebs/5pkgs/genid/default.nix22
-rw-r--r--krebs/5pkgs/krebszones/default.nix5
-rw-r--r--krebs/5pkgs/snapraid/default.nix33
-rw-r--r--krebs/5pkgs/test/infest-cac-centos7/default.nix (renamed from krebs/5pkgs/krebs-ci/default.nix)10
-rwxr-xr-xkrebs/5pkgs/test/infest-cac-centos7/notes (renamed from krebs/5pkgs/krebs-ci/notes)95
-rw-r--r--krebs/Zhosts/bobby11
-rw-r--r--krebs/Zhosts/kebsco11
-rw-r--r--krebs/default.nix20
36 files changed, 1312 insertions, 156 deletions
diff --git a/krebs/3modules/Reaktor.nix b/krebs/3modules/Reaktor.nix
index 1ec49b81e..92400139c 100644
--- a/krebs/3modules/Reaktor.nix
+++ b/krebs/3modules/Reaktor.nix
@@ -1,25 +1,15 @@
-{ config, pkgs,lib, ... }:
-
+{ config, lib, pkgs, ... }:
+with lib;
let
- inherit (lib)
- mkIf
- mkOption
- types
- singleton
- isString
- optionalString
- concatStrings
- escapeShellArg
- ;
-
ReaktorConfig = pkgs.writeText "config.py" ''
${if (isString cfg.overrideConfig ) then ''
# Overriden Config
${cfg.overrideConfig}
'' else ""}
## Extra Config
+ ${concatStringsSep "\n" (map (plug: plug.config) cfg.plugins)}
${cfg.extraConfig}
'';
cfg = config.krebs.Reaktor;
@@ -46,7 +36,6 @@ let
'';
};
-
overrideConfig = mkOption {
default = null;
type = types.nullOr types.str;
@@ -55,6 +44,9 @@ let
Reaktor default cfg can be retrieved via `reaktor get-config`
'';
};
+ plugins = mkOption {
+ default = [pkgs.ReaktorPlugins.nixos-version];
+ };
extraConfig = mkOption {
default = "";
type = types.string;
@@ -62,6 +54,14 @@ let
configuration appended to the default or overridden configuration
'';
};
+
+ workdir = mkOption {
+ default = "/var/lib/Reaktor";
+ type = types.str;
+ description = ''
+ Reaktor working directory
+ '';
+ };
extraEnviron = mkOption {
default = {};
type = types.attrsOf types.str;
@@ -70,12 +70,17 @@ let
REAKTOR_HOST
REAKTOR_PORT
REAKTOR_STATEDIR
- REAKTOR_CHANNELS
debug and nickname can be set separately via the Reaktor api
'';
};
-
+ channels = mkOption {
+ default = [ "#krebs" ];
+ type = types.listOf types.str;
+ description = ''
+ Channels the Reaktor should connect to at startup.
+ '';
+ };
debug = mkOption {
default = false;
description = ''
@@ -86,12 +91,11 @@ let
imp = {
# for reaktor get-config
- users.extraUsers = singleton {
+ users.extraUsers = singleton rec {
name = "Reaktor";
- # uid = config.ids.uids.Reaktor;
- uid = 2066439104; #genid Reaktor
+ uid = genid name;
description = "Reaktor user";
- home = "/var/lib/Reaktor";
+ home = cfg.workdir;
createHome = true;
};
@@ -113,6 +117,9 @@ let
GIT_SSL_CAINFO = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
REAKTOR_NICKNAME = cfg.nickname;
REAKTOR_DEBUG = (if cfg.debug then "True" else "False");
+ REAKTOR_CHANNELS = lib.concatStringsSep "," cfg.channels;
+ state_dir = cfg.workdir;
+
} // cfg.extraEnviron;
serviceConfig= {
ExecStartPre = pkgs.writeScript "Reaktor-init" ''
diff --git a/krebs/3modules/apt-cacher-ng.nix b/krebs/3modules/apt-cacher-ng.nix
index 75296bafb..371d39b6f 100644
--- a/krebs/3modules/apt-cacher-ng.nix
+++ b/krebs/3modules/apt-cacher-ng.nix
@@ -119,16 +119,14 @@ let
imp = {
users.extraUsers.acng = {
- # uid = config.ids.uids.acng;
- uid = 897955083; #genid Reaktor
+ uid = genid "acng";
description = "apt-cacher-ng";
home = acng-home;
createHome = false;
};
users.extraGroups.acng = {
- gid = 897955083; #genid Reaktor
- # gid = config.ids.gids.Reaktor;
+ gid = genid "acng";
};
systemd.services.apt-cacher-ng = {
diff --git a/krebs/3modules/backup.nix b/krebs/3modules/backup.nix
new file mode 100644
index 000000000..01bb16a2b
--- /dev/null
+++ b/krebs/3modules/backup.nix
@@ -0,0 +1,286 @@
+{ config, lib, pkgs, ... }:
+with lib;
+let
+ out = {
+ options.krebs.backup = api;
+ config = mkIf cfg.enable imp;
+ };
+
+ cfg = config.krebs.backup;
+
+ api = {
+ enable = mkEnableOption "krebs.backup" // { default = true; };
+ plans = mkOption {
+ default = {};
+ type = types.attrsOf (types.submodule ({
+ # TODO enable = mkEnableOption "TODO" // { default = true; };
+ options = {
+ method = mkOption {
+ type = types.enum ["pull" "push"];
+ };
+ name = mkOption {
+ type = types.str;
+ };
+ src = mkOption {
+ type = types.krebs.file-location;
+ };
+ dst = mkOption {
+ type = types.krebs.file-location;
+ };
+ startAt = mkOption {
+ type = types.str;
+ };
+ snapshots = mkOption {
+ type = types.attrsOf (types.submodule {
+ options = {
+ format = mkOption {
+ type = types.str; # TODO date's +FORMAT
+ };
+ retain = mkOption {
+ type = types.nullOr types.int;
+ default = null; # null = retain all snapshots
+ };
+ };
+ });
+ };
+ };
+ }));
+ };
+ };
+
+ imp = {
+ users.groups.backup.gid = genid "backup";
+ users.users = {}
+ // {
+ root.openssh.authorizedKeys.keys =
+ map (plan: plan.dst.host.ssh.pubkey)
+ (filter isPullSrc (attrValues cfg.plans))
+ ++
+ map (plan: plan.src.host.ssh.pubkey)
+ (filter isPushDst (attrValues cfg.plans))
+ ;
+ }
+ ;
+ systemd.services =
+ flip mapAttrs' (filterAttrs (_:isPullDst) cfg.plans) (name: plan: {
+ name = "backup.${name}.pull";
+ value = makePullService plan;
+ })
+ //
+ flip mapAttrs' (filterAttrs (_:isPushSrc) cfg.plans) (name: plan: {
+ name = "backup.${name}.push";
+ value = makePushService plan;
+ })
+ ;
+ };
+
+ isPushSrc = plan:
+ plan.method == "push" &&
+ plan.src.host.name == config.krebs.build.host.name;
+
+ isPullSrc = plan:
+ plan.method == "pull" &&
+ plan.src.host.name == config.krebs.build.host.name;
+
+ isPushDst = plan:
+ plan.method == "push" &&
+ plan.dst.host.name == config.krebs.build.host.name;
+
+ isPullDst = plan:
+ plan.method == "pull" &&
+ plan.dst.host.name == config.krebs.build.host.name;
+
+ # TODO push destination needs this in the dst.user's PATH
+ service-path = [
+ pkgs.coreutils
+ pkgs.gnused
+ pkgs.openssh
+ pkgs.rsync
+ pkgs.utillinux
+ ];
+
+ # TODO if there is plan.user, then use its privkey
+ makePushService = plan: assert isPushSrc plan; {
+ path = service-path;
+ serviceConfig = {
+ ExecStart = push plan;
+ Type = "oneshot";
+ };
+ startAt = plan.startAt;
+ };
+
+ makePullService = plan: assert isPullDst plan; {
+ path = service-path;
+ serviceConfig = {
+ ExecStart = pull plan;
+ Type = "oneshot";
+ };
+ startAt = plan.startAt;
+ };
+
+ push = plan: let
+ # We use writeDashBin and return the absolute path so systemd will produce
+ # nice names in the log, i.e. without the Nix store hash.
+ out = "${main}/bin/${main.name}";
+
+ main = writeDashBin "backup.${plan.name}.push" ''
+ set -efu
+ dst=${shell.escape plan.dst.path}
+
+ mkdir -m 0700 -p "$dst"
+ exec flock -n "$dst" ${critical-section}
+ '';
+
+ critical-section = writeDash "backup.${plan.name}.push.critical-section" ''
+ # TODO check if there is a previous
+ set -efu
+ identity=${shell.escape plan.src.host.ssh.privkey.path}
+ src=${shell.escape plan.src.path}
+ dst_target=${shell.escape "root@${getFQDN plan.dst.host}"}
+ dst_path=${shell.escape plan.dst.path}
+ dst=$dst_target:$dst_path
+
+ # Export NOW so runtime of rsync doesn't influence snapshot naming.
+ export NOW
+ NOW=$(date +%s)
+
+ echo >&2 "update snapshot: current; $src -> $dst"
+ rsync >&2 \
+ -aAXF --delete \
+ -e "ssh -F /dev/null -i $identity" \
+ --rsync-path ${shell.escape
+ "mkdir -m 0700 -p ${shell.escape plan.dst.path} && rsync"} \
+ --link-dest="$dst_path/current" \
+ "$src/" \
+ "$dst/.partial"
+
+ exec ssh -F /dev/null \
+ -i "$identity" \
+ "$dst_target" \
+ -T \
+ env NOW="$NOW" /bin/sh < ${remote-snapshot}
+ EOF
+ '';
+
+ remote-snapshot = writeDash "backup.${plan.name}.push.remote-snapshot" ''
+ set -efu
+ dst=${shell.escape plan.dst.path}
+
+ if test -e "$dst/current"; then
+ mv "$dst/current" "$dst/.previous"
+ fi
+ mv "$dst/.partial" "$dst/current"
+ rm -fR "$dst/.previous"
+ echo >&2
+
+ (${(take-snapshots plan).text})
+ '';
+
+ in out;
+
+ # TODO admit plan.dst.user and its ssh identity
+ pull = plan: let
+ # We use writeDashBin and return the absolute path so systemd will produce
+ # nice names in the log, i.e. without the Nix store hash.
+ out = "${main}/bin/${main.name}";
+
+ main = writeDashBin "backup.${plan.name}.pull" ''
+ set -efu
+ dst=${shell.escape plan.dst.path}
+
+ mkdir -m 0700 -p "$dst"
+ exec flock -n "$dst" ${critical-section}
+ '';
+
+ critical-section = writeDash "backup.${plan.name}.pull.critical-section" ''
+ # TODO check if there is a previous
+ set -efu
+ identity=${shell.escape plan.dst.host.ssh.privkey.path}
+ src=${shell.escape "root@${getFQDN plan.src.host}:${plan.src.path}"}
+ dst=${shell.escape plan.dst.path}
+
+ # Export NOW so runtime of rsync doesn't influence snapshot naming.
+ export NOW
+ NOW=$(date +%s)
+
+ echo >&2 "update snapshot: current; $dst <- $src"
+ mkdir -m 0700 -p ${shell.escape plan.dst.path}
+ rsync >&2 \
+ -aAXF --delete \
+ -e "ssh -F /dev/null -i $identity" \
+ --link-dest="$dst/current" \
+ "$src/" \
+ "$dst/.partial"
+ mv "$dst/current" "$dst/.previous"
+ mv "$dst/.partial" "$dst/current"
+ rm -fR "$dst/.previous"
+ echo >&2
+
+ exec ${take-snapshots plan}
+ '';
+ in out;
+
+ take-snapshots = plan: writeDash "backup.${plan.name}.take-snapshots" ''
+ set -efu
+ NOW=''${NOW-$(date +%s)}
+ dst=${shell.escape plan.dst.path}
+
+ snapshot() {(
+ : $ns $format $retain
+ name=$(date --date="@$NOW" +"$format")
+ if ! test -e "$dst/$ns/$name"; then
+ echo >&2 "create snapshot: $ns/$name"
+ mkdir -m 0700 -p "$dst/$ns"
+ rsync >&2 \
+ -aAXF --delete \
+ --link-dest="$dst/current" \
+ "$dst/current/" \
+ "$dst/$ns/.partial.$name"
+ mv "$dst/$ns/.partial.$name" "$dst/$ns/$name"
+ echo >&2
+ fi
+ case $retain in
+ ([0-9]*)
+ delete_from=$(($retain + 1))
+ ls -r "$dst/$ns" \
+ | sed -n "$delete_from,\$p" \
+ | while read old_name; do
+ echo >&2 "delete snapshot: $ns/$old_name"
+ rm -fR "$dst/$ns/$old_name"
+ done
+ ;;
+ (ALL)
+ :
+ ;;
+ esac
+ )}
+
+ ${concatStringsSep "\n" (mapAttrsToList (ns: { format, retain ? null, ... }:
+ toString (map shell.escape [
+ "ns=${ns}"
+ "format=${format}"
+ "retain=${if retain == null then "ALL" else toString retain}"
+ "snapshot"
+ ]))
+ plan.snapshots)}
+ '';
+
+ # TODO getFQDN: admit hosts in other domains
+ getFQDN = host: "${host.name}.${config.krebs.search-domain}";
+
+ writeDash = name: text: pkgs.writeScript name ''
+ #! ${pkgs.dash}/bin/dash
+ ${text}
+ '';
+
+ writeDashBin = name: text: pkgs.writeTextFile {
+ executable = true;
+ destination = "/bin/${name}";
+ name = name;
+ text = ''
+ #! ${pkgs.dash}/bin/dash
+ ${text}
+ '';
+ };
+
+in out
diff --git a/krebs/3modules/bepasty-server.nix b/krebs/3modules/bepasty-server.nix
index c99c3d11a..e74841205 100644
--- a/krebs/3modules/bepasty-server.nix
+++ b/krebs/3modules/bepasty-server.nix
@@ -130,12 +130,12 @@ let
) cfg.servers;
users.extraUsers.bepasty = {
- uid = 2796546855; #genid bepasty
+ uid = genid "bepasty";
group = "bepasty";
home = "/var/lib/bepasty-server";
};
users.extraGroups.bepasty = {
- gid = 2796546855; #genid bepasty
+ gid = genid "bepasty";
};
};
diff --git a/krebs/3modules/buildbot/master.nix b/krebs/3modules/buildbot/master.nix
new file mode 100644
index 000000000..74385a433
--- /dev/null
+++ b/krebs/3modules/buildbot/master.nix
@@ -0,0 +1,385 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+let
+ buildbot = pkgs.buildbot;
+ buildbot-master-config = pkgs.writeText "buildbot-master.cfg" ''
+ # -*- python -*-
+ from buildbot.plugins import *
+ import re
+ import json
+ c = BuildmasterConfig = {}
+
+ c['slaves'] = []
+ slaves = json.loads('${builtins.toJSON cfg.slaves}')
+ slavenames = [ s for s in slaves ]
+ for k,v in slaves.items():
+ c['slaves'].append(buildslave.BuildSlave(k, v))
+
+ # TODO: configure protocols?
+ c['protocols'] = {'pb': {'port': 9989}}
+
+ ####### Build Inputs
+ c['change_source'] = cs = []
+
+ ${ concatStringsSep "\n"
+ (mapAttrsToList (n: v: ''
+ #### Change_Source: Begin of ${n}
+ ${v}
+ #### Change_Source: End of ${n}
+ '') cfg.change_source )}
+
+ ####### Build Scheduler
+ c['schedulers'] = sched = []
+
+ ${ concatStringsSep "\n"
+ (mapAttrsToList (n: v: ''
+ #### Schedulers: Begin of ${n}
+ ${v}
+ #### Schedulers: End of ${n}
+ '') cfg.scheduler )}
+
+ ###### Builder
+ c['builders'] = bu = []
+
+ # Builder Pre: Begin
+ ${cfg.builder_pre}
+ # Builder Pre: End
+
+ ${ concatStringsSep "\n"
+ (mapAttrsToList (n: v: ''
+ #### Builder: Begin of ${n}
+ ${v}
+ #### Builder: End of ${n}
+ '') cfg.builder )}
+
+
+ ####### Status
+ c['status'] = st = []
+
+ # If you want to configure this url, override with extraConfig
+ c['buildbotURL'] = "http://${config.networking.hostName}:${toString cfg.web.port}/"
+
+ ${optionalString (cfg.web.enable) ''
+ from buildbot.status import html
+ from buildbot.status.web import authz, auth
+ authz_cfg=authz.Authz(
+ auth=auth.BasicAuth([ ("${cfg.web.username}","${cfg.web.password}") ]),
+ # TODO: configure harder
+ gracefulShutdown = False,
+ forceBuild = 'auth',
+ forceAllBuilds = 'auth',
+ pingBuilder = False,
+ stopBuild = 'auth',
+ stopAllBuilds = 'auth',
+ cancelPendingBuild = 'auth'
+ )
+ # TODO: configure krebs.nginx
+ st.append(html.WebStatus(http_port=${toString cfg.web.port}, authz=authz_cfg))
+ ''}
+
+ ${optionalString (cfg.irc.enable) ''
+ from buildbot.status import words
+ irc = words.IRC("${cfg.irc.server}", "${cfg.irc.nick}",
+ channels=${builtins.toJSON cfg.irc.channels},
+ notify_events={
+ 'success': 1,
+ 'failure': 1,
+ 'exception': 1,
+ 'successToFailure': 1,
+ 'failureToSuccess': 1,
+ }${optionalString cfg.irc.allowForce ",allowForce=True"})
+ c['status'].append(irc)
+ ''}
+
+ ${ concatStringsSep "\n"
+ (mapAttrsToList (n: v: ''
+ #### Status: Begin of ${n}
+ ${v}
+ #### Status: End of ${n}
+ '') cfg.status )}
+
+ ####### PROJECT IDENTITY
+ c['title'] = "${cfg.title}"
+ c['titleURL'] = "http://krebsco.de"
+
+
+ ####### DB URL
+ # TODO: configure
+ c['db'] = {
+ 'db_url' : "sqlite:///state.sqlite",
+ }
+ ${cfg.extraConfig}
+ '';
+
+ cfg = config.krebs.buildbot.master;
+
+ api = {
+ enable = mkEnableOption "Buildbot Master";
+ title = mkOption {
+ default = "Buildbot CI";
+ type = types.str;
+ description = ''
+ Title of the Buildbot Installation
+ '';
+ };
+ workDir = mkOption {
+ default = "/var/lib/buildbot/master";
+ type = types.str;
+ description = ''
+ Path to build bot master directory.
+ Will be created on startup.
+ '';
+ };
+
+ secrets = mkOption {
+ default = [];
+ type = types.listOf types.str;
+ example = [ "cac.json" ];
+ description = ''
+ List of all the secrets in <secrets> which should be copied into the
+ buildbot master directory.
+ '';
+ };
+
+ slaves = mkOption {
+ default = {};
+ type = types.attrsOf types.str;
+ description = ''
+ Attrset of slavenames with their passwords
+ slavename = slavepassword
+ '';
+ };
+
+ change_source = mkOption {
+ default = {};
+ type = types.attrsOf types.str;
+ example = {
+ stockholm = ''
+ cs.append(changes.GitPoller(
+ 'http://cgit.gum/stockholm',
+ workdir='stockholm-poller', branch='master',
+ project='stockholm',
+ pollinterval=120))
+ '';
+ };
+ description = ''
+ Attrset of all the change_sources which should be configured.
+ It will be directly included into the master configuration.
+
+ At the end an change object should be appended to <literal>cs</literal>
+ '';
+ };
+
+ scheduler = mkOption {
+ default = {};
+ type = types.attrsOf types.str;
+ example = {
+ force-scheduler = ''
+ sched.append(schedulers.ForceScheduler(
+ name="force",
+ builderNames=["full-tests"]))
+ '';
+ };
+ description = ''
+ Attrset of all the schedulers which should be configured.
+ It will be directly included into the master configuration.
+
+ At the end an change object should be appended to <literal>sched</literal>
+ '';
+ };
+
+ builder_pre = mkOption {
+ default = "";
+ type = types.lines;
+ example = ''
+ grab_repo = steps.Git(repourl=stockholm_repo, mode='incremental')
+ '';
+ description = ''
+ some code before the builders are being assembled.
+ can be used to define functions used by multiple builders
+ '';
+ };
+
+ builder = mkOption {
+ default = {};
+ type = types.attrsOf types.str;
+ example = {
+ fast-test = ''
+ '';
+ };
+ description = ''
+ Attrset of all the builder which should be configured.
+ It will be directly included into the master configuration.
+
+ At the end an change object should be appended to <literal>bu</literal>
+ '';
+ };
+
+ status = mkOption {
+ default = {};
+ type = types.attrsOf types.str;
+ description = ''
+ Attrset of all the extra status which should be configured.
+ It will be directly included into the master configuration.
+
+ At the end an change object should be appended to <literal>st</literal>
+
+ Right now IRC and Web status can be configured by setting
+ <literal>buildbot.master.irc.enable</literal> and
+ <literal>buildbot.master.web.enable</literal>
+ '';
+ };
+
+ # Configurable Stati
+ web = mkOption {
+ default = {};
+ type = types.submodule ({ config2, ... }: {
+ options = {
+ enable = mkEnableOption "Buildbot Master Web Status";
+ username = mkOption {
+ default = "krebs";
+ type = types.str;
+ description = ''
+ username for web authentication
+ '';
+ };
+ hostname = mkOption {
+ default = config.networking.hostName;
+ type = types.str;
+ description = ''
+ web interface Hostname
+ '';
+ };
+ password = mkOption {
+ default = "bob";
+ type = types.str;
+ description = ''
+ password for web authentication
+ '';
+ };
+ port = mkOption {
+ default = 8010;
+ type = types.int;
+ description = ''
+ port for buildbot web status
+ '';
+ };
+ };
+ });
+ };
+
+ irc = mkOption {
+ default = {};
+ type = types.submodule ({ config, ... }: {
+ options = {
+ enable = mkEnableOption "Buildbot Master IRC Status";
+ channels = mkOption {
+ default = [ "nix-buildbot-meetup" ];
+ type = with types; listOf str;
+ description = ''
+ irc channels the bot should connect to
+ '';
+ };
+ allowForce = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ Determines if builds can be forced via IRC
+ '';
+ };
+ nick = mkOption {
+ default = "nix-buildbot";
+ type = types.str;
+ description = ''
+ nickname for IRC
+ '';
+ };
+ server = mkOption {
+ default = "irc.freenode.net";
+ type = types.str;
+ description = ''
+ Buildbot Status IRC Server to connect to
+ '';
+ };
+ };
+ });
+ };
+
+ extraConfig = mkOption {
+ default = "";
+ type = types.lines;
+ description = ''
+ extra config appended to the generated master.cfg
+ '';
+ };
+ };
+
+ imp = {
+
+ users.extraUsers.buildbotMaster = {
+ uid = genid "buildbotMaster";
+ description = "Buildbot Master";
+ home = cfg.workDir;
+ createHome = false;
+ };
+
+ users.extraGroups.buildbotMaster = {
+ gid = 672626386;
+ };
+
+ systemd.services.buildbotMaster = {
+ description = "Buildbot Master";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ # TODO: add extra dependencies to master like svn and cvs
+ path = [ pkgs.git ];
+ environment = {
+ SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
+ };
+ serviceConfig = let
+ workdir="${lib.shell.escape cfg.workDir}";
+ secretsdir="${lib.shell.escape (toString <secrets>)}";
+ in {
+ PermissionsStartOnly = true;
+ Type = "forking";
+ PIDFile = "${workdir}/twistd.pid";
+ # TODO: maybe also prepare buildbot.tac?
+ ExecStartPre = pkgs.writeScript "buildbot-master-init" ''
+ #!/bin/sh
+ set -efux
+ if [ ! -e ${workdir} ];then
+ mkdir -p ${workdir}
+ ${buildbot}/bin/buildbot create-master -r -l 10 -f ${workdir}
+ fi
+ # always override the master.cfg
+ cp ${buildbot-master-config} ${workdir}/master.cfg
+
+ # copy secrets
+ ${ concatMapStringsSep "\n"
+ (f: "cp ${secretsdir}/${f} ${workdir}/${f}" ) cfg.secrets }
+ # sanity
+ ${buildbot}/bin/buildbot checkconfig ${workdir}
+
+ # TODO: maybe upgrade? not sure about this
+ # normally we should write buildbot.tac by our own
+ # ${buildbot}/bin/buildbot upgrade-master ${workdir}
+
+ chmod 700 -R ${workdir}
+ chown buildbotMaster:buildbotMaster -R ${workdir}
+ '';
+ ExecStart = "${buildbot}/bin/buildbot start ${workdir}";
+ ExecStop = "${buildbot}/bin/buildbot stop ${workdir}";
+ ExecReload = "${buildbot}/bin/buildbot reconfig ${workdir}";
+ PrivateTmp = "true";
+ User = "buildbotMaster";
+ Restart = "always";
+ RestartSec = "10";
+ };
+ };
+ };
+in
+{
+ options.krebs.buildbot.master = api;
+ config = mkIf cfg.enable imp;
+}
diff --git a/krebs/3modules/buildbot/slave.nix b/krebs/3modules/buildbot/slave.nix
new file mode 100644
index 000000000..0e7796d8a
--- /dev/null
+++ b/krebs/3modules/buildbot/slave.nix
@@ -0,0 +1,186 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+let
+ buildbot-slave-init = pkgs.writeText "buildbot-slave.tac" ''
+ import os
+
+ from buildslave.bot import BuildSlave
+ from twisted.application import service
+
+ basedir = '${cfg.workDir}'
+ rotateLength = 10000000
+ maxRotatedFiles = 10
+
+ application = service.Application('buildslave')
+
+ from twisted.python.logfile import LogFile
+ from twisted.python.log import ILogObserver, FileLogObserver
+ logfile = LogFile.fromFullPath(os.path.join(basedir, "twistd.log"), rotateLength=rotateLength,
+ maxRotatedFiles=maxRotatedFiles)
+ application.setComponent(ILogObserver, FileLogObserver(logfile).emit)
+
+ buildmaster_host = '${cfg.masterhost}'
+ # TODO: masterport?
+ port = 9989
+ slavename = '${cfg.username}'
+ passwd = '${cfg.password}'
+ keepalive = 600
+ usepty = 0
+ umask = None
+ maxdelay = 300
+ allow_shutdown = None
+
+ ${cfg.extraConfig}
+
+ s = BuildSlave(buildmaster_host, port, slavename, passwd, basedir,
+ keepalive, usepty, umask=umask, maxdelay=maxdelay,
+ allow_shutdown=allow_shutdown)
+ s.setServiceParent(application)
+ '';
+ default-packages = [ pkgs.git pkgs.bash ];
+ cfg = config.krebs.buildbot.slave;
+
+ api = {
+ enable = mkEnableOption "Buildbot Slave";
+
+ workDir = mkOption {
+ default = "/var/lib/buildbot/slave";
+ type = types.str;
+ description = ''
+ Path to build bot slave directory.
+ Will be created on startup.
+ '';
+ };
+
+ masterhost = mkOption {
+ default = "localhost";
+ type = types.str;
+ description = ''
+ Hostname/IP of the buildbot master
+ '';
+ };
+
+ username = mkOption {
+ type = types.str;
+ description = ''
+ slavename used to authenticate with master
+ '';
+ };
+
+ password = mkOption {
+ type = types.str;
+ description = ''
+ slave password used to authenticate with master
+ '';
+ };
+
+ contact = mkOption {
+ default = "nix slave <buildslave@${config.networking.hostName}>";
+ type = types.str;
+ description = ''
+ contact to be announced by buildslave
+ '';
+ };
+
+ description = mkOption {
+ default = "Nix Generated BuildSlave";
+ type = types.str;
+ description = ''
+ description for hostto be announced by buildslave
+ '';
+ };
+
+ packages = mkOption {
+ default = [ pkgs.git ];
+ type = with types; listOf package;
+ description = ''
+ packages which should be in path for buildslave
+ '';
+ };
+
+ extraEnviron = mkOption {
+ default = {};
+ example = {
+ NIX_PATH = "nixpkgs=/path/to/my/nixpkgs";
+ };
+ type = types.attrsOf types.str;
+ description = ''
+ extra environment variables to be provided to the buildslave service
+ if you need nixpkgs, e.g. for running nix-shell you can set NIX_PATH here.
+ '';
+ };
+
+ extraConfig = mkOption {
+ default = "";
+ type = types.lines;
+ example = ''
+ port = 443
+ keepalive = 600
+ '';
+ description = ''
+ extra config evaluated before calling BuildSlave init in .tac file
+ '';
+ };
+ };
+
+ imp = {
+
+ users.extraUsers.buildbotSlave = {
+ uid = genid "buildbotSlave";
+ description = "Buildbot Slave";
+ home = cfg.workDir;
+ createHome = false;
+ };
+
+ users.extraGroups.buildbotSlave = {
+ gid = 1408105834;
+ };
+
+ systemd.services."buildbotSlave-${cfg.username}-${cfg.masterhost}" = {
+ description = "Buildbot Slave for ${cfg.username}@${cfg.masterhost}";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ path = default-packages ++ cfg.packages;
+
+ environment = {
+ SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
+ NIX_REMOTE="daemon";
+ } // cfg.extraEnviron;
+
+ serviceConfig = let
+ workdir = "${lib.shell.escape cfg.workDir}";
+ contact = "${lib.shell.escape cfg.contact}";
+ description = "${lib.shell.escape cfg.description}";
+ buildbot = pkgs.buildbot-slave;
+ # TODO:make this
+ in {
+ PermissionsStartOnly = true;
+ Type = "forking";
+ PIDFile = "${workdir}/twistd.pid";
+ # TODO: maybe also prepare buildbot.tac?
+ ExecStartPre = pkgs.writeScript "buildbot-master-init" ''
+ #!/bin/sh
+ set -efux
+ mkdir -p ${workdir}/info
+ cp ${buildbot-slave-init} ${workdir}/buildbot.tac
+ echo ${contact} > ${workdir}/info/admin
+ echo ${description} > ${workdir}/info/host
+
+ chown buildbotSlave:buildbotSlave -R ${workdir}
+ chmod 700 -R ${workdir}
+ '';
+ ExecStart = "${buildbot}/bin/buildslave start ${workdir}";
+ ExecStop = "${buildbot}/bin/buildslave stop ${workdir}";
+ PrivateTmp = "true";
+ User = "buildbotSlave";
+ Restart = "always";
+ RestartSec = "10";
+ };
+ };
+ };
+in
+{
+ options.krebs.buildbot.slave = api;
+ config = mkIf cfg.enable imp;
+}
diff --git a/krebs/3modules/default.nix b/krebs/3modules/default.nix
index 740ba67b8..ba1f425d9 100644
--- a/krebs/3modules/default.nix
+++ b/krebs/3modules/default.nix
@@ -7,8 +7,11 @@ let
out = {
imports = [
./apt-cacher-ng.nix
+ ./backup.nix
./bepasty-server.nix
./build.nix
+ ./buildbot/master.nix
+ ./buildbot/slave.nix
./current.nix
./exim-retiolum.nix
./exim-smarthost.nix
diff --git a/krebs/3modules/exim-retiolum.nix b/krebs/3modules/exim-retiolum.nix
index e1315d8c8..ea012c38c 100644
--- a/krebs/3modules/exim-retiolum.nix
+++ b/krebs/3modules/exim-retiolum.nix
@@ -1,14 +1,12 @@
{ config, pkgs, lib, ... }:
-with builtins;
with lib;
let
cfg = config.krebs.exim-retiolum;
out = {
options.krebs.exim-retiolum = api;
- config =
- mkIf cfg.enable imp;
+ config = mkIf cfg.enable imp;
};
api = {
@@ -16,13 +14,13 @@ let
};
imp = {
- services.exim =
- # This configuration makes only sense for retiolum-enabled hosts.
- # TODO modular configuration
- assert config.krebs.retiolum.enable;
- {
- enable = true;
- config = ''
+ services.exim = {
+ enable = true;
+ config =
+ # This configuration makes only sense for retiolum-enabled hosts.
+ # TODO modular configuration
+ assert config.krebs.retiolum.enable;
+ ''
primary_hostname = ${retiolumHostname}
domainlist local_domains = @ : localhost
domainlist relay_to_domains = *.retiolum
@@ -134,7 +132,7 @@ let
begin authenticators
'';
- };
+ };
};
# TODO get the hostname from somewhere else.
diff --git a/krebs/3modules/fetchWallpaper.nix b/krebs/3modules/fetchWallpaper.nix
index 83ecf4177..f320c7505 100644
--- a/krebs/3modules/fetchWallpaper.nix
+++ b/krebs/3modules/fetchWallpaper.nix
@@ -51,7 +51,7 @@ let
imp = {
users.users.fetchWallpaper = {
name = "fetchWallpaper";
- uid = 3332383611; #genid fetchWallpaper
+ uid = genid "fetchWallpaper";
description = "fetchWallpaper user";
home = cfg.stateDir;
createHome = true;
diff --git a/krebs/3modules/git.nix b/krebs/3modules/git.nix
index 234129497..e6267d7e6 100644
--- a/krebs/3modules/git.nix
+++ b/krebs/3modules/git.nix
@@ -145,14 +145,14 @@ let
]) (filter (x: hasAttr "allow-receive-ref" x.perm) cfg.rules));
};
- users.extraUsers = singleton {
+ users.extraUsers = singleton rec {
description = "Git repository hosting user";
name = "git";
shell = "/bin/sh";
openssh.authorizedKeys.keys =
mapAttrsToList (_: makeAuthorizedKey git-ssh-command)
config.krebs.users;
- uid = 129318403; # genid git
+ uid = genid name;
};
};
@@ -238,9 +238,9 @@ let
};
};
- fcgitwrap-user = {
+ fcgitwrap-user = rec {
name = "fcgiwrap";
- uid = 2867890860; # genid fcgiwrap
+ uid = genid name;
group = "fcgiwrap";
};
diff --git a/krebs/3modules/github-hosts-sync.nix b/krebs/3modules/github-hosts-sync.nix
index 5503ee8d6..2aa18d53a 100644
--- a/krebs/3modules/github-hosts-sync.nix
+++ b/krebs/3modules/github-hosts-sync.nix
@@ -56,9 +56,9 @@ let
};
};
- user = {
+ user = rec {
name = "github-hosts-sync";
- uid = 3220554646; # genid github-hosts-sync
+ uid = genid name;
};
# TODO move to lib?
diff --git a/krebs/3modules/go.nix b/krebs/3modules/go.nix
index 793d1f60d..08a93dab7 100644
--- a/krebs/3modules/go.nix
+++ b/krebs/3modules/go.nix
@@ -1,6 +1,5 @@
{ config, lib, pkgs, ... }:
-with builtins;
with lib;
let
@@ -31,9 +30,9 @@ let
bind = mkDefault "127.0.0.1";
};
- users.extraUsers.go = {
+ users.extraUsers.go = rec {
name = "go";
- uid = 42774411; #genid go
+ uid = genid name;
description = "go url shortener user";
home = "/var/lib/go";
createHome = true;
diff --git a/krebs/3modules/makefu/default.nix b/krebs/3modules/makefu/default.nix
index 1970a0777..31516d591 100644
--- a/krebs/3modules/makefu/default.nix
+++ b/krebs/3modules/makefu/default.nix
@@ -83,6 +83,9 @@ with lib;
'';
};
};
+ ssh.privkey.path = <secrets/ssh_host_ed25519_key>;
+ ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHDM0E608d/6rGzXqGbNSuMb2RlCojCJSiiz6QcPOC2G root@pornocauster";
+
};
vbob = {
@@ -108,6 +111,8 @@ with lib;
'';
};
};
+ ssh.privkey.path = <secrets/ssh_host_ed25519_key>;
+ ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICPLTMl+thSq77cjYa2XF7lz5fA7JMftrLo8Dy/OBXSg root@nixos";
};
flap = rec {
cores = 1;
@@ -238,6 +243,8 @@ with lib;
'';
};
};
+ ssh.privkey.path = <secrets/ssh_host_ed25519_key>;
+ ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH4Tjx9qK6uWtxT1HCpeC0XvDZKO/kaPygyKatpAqU6I root@wry";
};
filepimp = rec {
cores = 1;
@@ -287,6 +294,8 @@ with lib;
'';
};
};
+ ssh.privkey.path = <secrets/ssh_host_ed25519_key>;
+ ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIujMZ3ZFxKpWeB/cjfKfYRr77+VRZk0Eik+92t03NoA root@servarch";
};
gum = rec {
cores = 1;
@@ -327,6 +336,8 @@ with lib;
'';
};
};
+ ssh.privkey.path = <secrets/ssh_host_ed25519_key>;
+ ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIcxWFEPzke/Sdd9qNX6rSJgXal8NmINYajpFCxXfYdj root@gum";
};
};
users = addNames rec {
diff --git a/krebs/3modules/realwallpaper.nix b/krebs/3modules/realwallpaper.nix
index 7e02538f5..b377368f7 100644
--- a/krebs/3modules/realwallpaper.nix
+++ b/krebs/3modules/realwallpaper.nix
@@ -1,13 +1,7 @@
arg@{ config, lib, pkgs, ... }:
+with lib;
let
- inherit (lib)
- mkEnableOption
- mkOption
- types
- mkIf
- ;
-
cfg = config.krebs.realwallpaper;
out = {
@@ -89,7 +83,7 @@ let
};
users.extraUsers.realwallpaper = {
- uid = 2009435407; #genid realwallpaper
+ uid = genid "realwallpaper";
home = cfg.workingDir;
createHome = true;
};
diff --git a/krebs/3modules/retiolum.nix b/krebs/3modules/retiolum.nix
index 28ac67306..e0e2692a8 100644
--- a/krebs/3modules/retiolum.nix
+++ b/krebs/3modules/retiolum.nix
@@ -133,9 +133,9 @@ let
};
};
- user = {
+ user = rec {
name = "retiolum";
- uid = 301281149; # genid retiolum
+ uid = genid name;
};
tinc = cfg.tincPackage;
diff --git a/krebs/3modules/shared/default.nix b/krebs/3modules/shared/default.nix
index b332676c6..518e46587 100644
--- a/krebs/3modules/shared/default.nix
+++ b/krebs/3modules/shared/default.nix
@@ -7,6 +7,7 @@ let
"test-arch"
"test-centos6"
"test-centos7"
+ "test-all-krebs-modules"
] (name: {
inherit name;
cores = 1;
diff --git a/krebs/3modules/tinc_graphs.nix b/krebs/3modules/tinc_graphs.nix
index ba81dd416..1f32c2e59 100644
--- a/krebs/3modules/tinc_graphs.nix
+++ b/krebs/3modules/tinc_graphs.nix
@@ -120,7 +120,7 @@ let
};
users.extraUsers.tinc_graphs = {
- uid = 3925439960; #genid tinc_graphs
+ uid = genid "tinc_graphs";
home = "/var/spool/tinc_graphs";
};
diff --git a/krebs/3modules/urlwatch.nix b/krebs/3modules/urlwatch.nix
index 206bc5697..31cbfcf6e 100644
--- a/krebs/3modules/urlwatch.nix
+++ b/krebs/3modules/urlwatch.nix
@@ -5,7 +5,6 @@
# cache = url: "${cfg.dataDir}/.urlwatch/cache/${hashString "sha1" url}"
# TODO hooks.py
-with builtins;
with lib;
let
cfg = config.krebs.urlwatch;
@@ -136,9 +135,9 @@ let
};
};
- user = {
+ user = rec {
name = "urlwatch";
- uid = 3467631196; # genid urlwatch
+ uid = genid name;
};
in
out
diff --git a/krebs/4lib/default.nix b/krebs/4lib/default.nix
index 1cabeae27..dfc51bbe4 100644
--- a/krebs/4lib/default.nix
+++ b/krebs/4lib/default.nix
@@ -7,6 +7,8 @@ let out = rec {
eq = x: y: x == y;
+ mod = x: y: x - y * (x / y);
+
addName = name: set:
set // { inherit name; };
@@ -17,6 +19,7 @@ let out = rec {
dir.has-default-nix = path: pathExists (path + "/default.nix");
dns = import ./dns.nix { inherit lib; };
+ genid = import ./genid.nix { lib = lib // out; };
git = import ./git.nix { lib = lib // out; };
listset = import ./listset.nix { inherit lib; };
shell = import ./shell.nix { inherit lib; };
diff --git a/krebs/4lib/genid.nix b/krebs/4lib/genid.nix
new file mode 100644
index 000000000..0aed1d351
--- /dev/null
+++ b/krebs/4lib/genid.nix
@@ -0,0 +1,37 @@
+{ lib, ... }:
+with lib;
+with builtins;
+let out = genid;
+
+ # id = genid s = (hash s + min) % max
+ # min <= genid s < max
+ #
+ # min = 2^24 = 16777216 = 0x001000000
+ # max = 2^32 = 4294967296 = 0x100000000
+ #
+ # id is bigger than UID of nobody and GID of nogroup
+ # see <nixos/modules/misc/ids.nix> and some spare for stuff like lxd.
+ #
+ # :: str -> uint32
+ genid = s: sum16 (addmod16_16777216 (hash s));
+
+ # :: str -> list8 uint4
+ hash = s:
+ map hexint (stringToCharacters (substring 32 8 (hashString "sha1" s)));
+
+ # :: list uint -> uint
+ sum16 = foldl (a: i: a * 16 + i) 0;
+
+ # :: list8 uint4 -> list1 uint8 ++ list6 uint4
+ addmod16_16777216 = x: let
+ a = 16 * head x + head (tail x);
+ d = tail (tail x);
+ in [(mod (a + 1) 256)] ++ d;
+
+ # :: char -> uint4
+ hexint = x: hexvals.${toLower x};
+
+ # :: attrset char uint4
+ hexvals = listToAttrs (imap (i: c: { name = c; value = i - 1; })
+ (stringToCharacters "0123456789abcdef"));
+in out
diff --git a/krebs/4lib/types.nix b/krebs/4lib/types.nix
index c52afa246..81ce659bd 100644
--- a/krebs/4lib/types.nix
+++ b/krebs/4lib/types.nix
@@ -177,4 +177,21 @@ types // rec {
addr6 = str;
hostname = str;
label = str;
+
+ krebs.file-location = types.submodule {
+ options = {
+ # TODO user
+ host = mkOption {
+ type = host;
+ };
+ # TODO merge with ssl.privkey.path
+ path = mkOption {
+ type = types.either types.path types.str;
+ apply = x: {
+ path = toString x;
+ string = x;
+ }.${typeOf x};
+ };
+ };
+ };
}
diff --git a/krebs/5pkgs/Reaktor/plugins.nix b/krebs/5pkgs/Reaktor/plugins.nix
new file mode 100644
index 000000000..7490be4ca
--- /dev/null
+++ b/krebs/5pkgs/Reaktor/plugins.nix
@@ -0,0 +1,120 @@
+{ stdenv, lib, pkgs, makeWrapper }:
+
+rec {
+ # Begin API
+ buildBaseReaktorPlugin = { name
+ , config # python extra configuration for plugin
+ , phases ? []
+ , ... } @ attrs:
+ stdenv.mkDerivation (attrs // {
+ name = "Reaktor-plugin-" + name;
+ isReaktorPlugin = true;
+ });
+
+ buildSimpleReaktorPlugin = name: { script
+ , path ? []
+ , env ? {}
+ , append_rule ? false # append the rule instead of insert
+ , pattern ? ""
+ , ... } @ attrs:
+ let
+ path_env = { "PATH" = lib.makeSearchPath "bin" (path ++ [ pkgs.coreutils ]); };
+ src_dir = pkgs.substituteAll ( {
+ inherit name;
+ dir = "bin";
+ isExecutable = true;
+ src = script;
+ });
+ src_file = "${src_dir}/bin/${name}";
+ config = ''
+ public_commands.${if append_rule then "append(" else "insert(0," }{
+ 'capname' : "${name}",
+ 'pattern' : ${if pattern == "" then
+ ''indirect_pattern.format("${name}")'' else
+ ''"${pattern}"'' },
+ 'argv' : ["${src_file}"],
+ 'env' : ${builtins.toJSON (path_env // env)} })
+ '';
+ config_file = pkgs.writeText "plugin.py" config;
+ in buildBaseReaktorPlugin (attrs // rec {
+ inherit name config;
+
+ phases = [ "installPhase" ];
+ buildInputs = [ makeWrapper ];
+ installPhase = ''
+ mkdir -p $out/bin $out/etc/Reaktor
+ ln -s ${src_file} $out/bin
+ wrapProgram $out/bin/${name} \
+ --prefix PATH : ${path_env.PATH}
+ ln -s ${config_file} $out/etc/Reaktor/plugin.py
+ '';
+
+ });
+ # End API
+
+ # Begin Plugins
+ random-emoji = buildSimpleReaktorPlugin "emoji" {
+ path = with pkgs; [ gnused gnugrep xmlstarlet curl ];
+ script = ./scripts/random-emoji.sh;
+ };
+
+ sed-plugin = buildSimpleReaktorPlugin "sed-plugin" {
+ path = [ pkgs.gnused pkgs.python3 ];
+ # only support s///gi the plugin needs to see every msg
+ # TODO: this will eat up the last regex, fix Reaktor to support fallthru
+ append_rule = true;
+ pattern = "^(?P<args>.*)$$";
+ script = ./scripts/sed-plugin.py;
+ };
+
+ shack-correct = buildSimpleReaktorPlugin "shack-correct" {
+ path = [ pkgs.gnused ];
+ pattern = "^(?P<args>.*Shack.*)$$";
+ script = ./scripts/shack-correct.sh;
+ };
+
+ nixos-version = buildSimpleReaktorPlugin "nixos-version" {
+ script = pkgs.writeScript "nixos-version" ''
+ #! /bin/sh
+ . /etc/os-release
+ echo "$PRETTY_NAME"
+ '';
+ };
+ stockholm-issue = buildSimpleReaktorPlugin "stockholm-issue" {
+ script = ./scripts/random-issue.sh;
+ path = with pkgs; [ git gnused lentil ];
+ env = { "origin" = "http://cgit.gum/stockholm"; };
+ };
+
+ titlebot =
+ let
+ pypkgs = pkgs.python3Packages;
+ titlebot_cmds = pypkgs.buildPythonPackage {
+ name = "titlebot_cmds";
+ propagatedBuildInputs = with pypkgs; [ setuptools ];
+ src = pkgs.fetchurl {
+ url = "https://github.com/makefu/reaktor-titlebot/archive/2.1.0.tar.gz";
+ sha256 = "0wvf09wmk8b52f9j65qrw81nwrhs9pfhijwrlkzp5l7l2q8cjkp6";
+ };
+ };
+ in buildBaseReaktorPlugin rec {
+ name = "titlebot";
+ phases = [ "installPhase" ];
+ installPhase = ''
+ mkdir -p $out
+ ln -s ${titlebot_cmds}/* $out
+ '';
+ config = ''
+ def titlebot_cmd(cmd):
+ from os import environ
+ return { 'capname': None,
+ 'env': { 'TITLEDB':
+ environ['state_dir']+'/suggestions.json' },
+ 'pattern': '^\\.' + cmd + '\\s*(?:\\s+(?P<args>.*))?$$',
+ 'argv': [ '${titlebot_cmds}/bin/' + cmd ] }
+ for i in ['up','help','list','top','new']:
+ public_commands.insert(0,titlebot_cmd(i))
+ commands.insert(0,titlebot_cmd('clear'))
+ '';
+ };
+}
diff --git a/krebs/5pkgs/Reaktor/scripts/random-emoji.sh b/krebs/5pkgs/Reaktor/scripts/random-emoji.sh
new file mode 100644
index 000000000..386aa68b9
--- /dev/null
+++ b/krebs/5pkgs/Reaktor/scripts/random-emoji.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+curl http://emojicons.com/random -s | \
+ grep data-text | \
+ sed -n 's/.*>\(.*\)<\/textarea>/\1/p' | \
+ head -n 1 | \
+ xmlstarlet unesc
diff --git a/krebs/5pkgs/Reaktor/scripts/random-issue.sh b/krebs/5pkgs/Reaktor/scripts/random-issue.sh
new file mode 100644
index 000000000..5c47c6156
--- /dev/null
+++ b/krebs/5pkgs/Reaktor/scripts/random-issue.sh
@@ -0,0 +1,20 @@
+#! /bin/sh
+set -eu
+# requires env:
+# $state_dir
+# $origin
+
+# in PATH: git,lentil,coreutils
+subdir=`echo "$1" | tr -dc "[:alnum:]"`
+name=`echo "$origin" | tr -dc "[:alnum:]"`
+track="$state_dir/$name-checkout"
+(if test -e "$track" ;then
+ cd "$track"
+ git fetch origin master
+ git reset --hard origin/master
+else
+ git clone "$origin" "$track"
+fi) >&2
+
+cd "$track"
+lentil "${subdir:-.}" -f csv | sed 1d | shuf | head -1
diff --git a/krebs/5pkgs/Reaktor/scripts/sed-plugin.py b/krebs/5pkgs/Reaktor/scripts/sed-plugin.py
new file mode 100644
index 000000000..8103c9585
--- /dev/null
+++ b/krebs/5pkgs/Reaktor/scripts/sed-plugin.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+
+# Usage:
+# _from=krebs state_dir=. python sed-plugin.py 'dick butt'
+# _from=krebs state_dir=. python sed-plugin.py 's/t/l/g'
+## dick bull
+import shelve
+from os import environ
+from os.path import join
+from sys import argv
+d = shelve.open(join(environ['state_dir'],'sed-plugin.shelve'),writeback=True)
+usr = environ['_from']
+import re
+
+def is_regex(line):
+ myre = re.compile(r'^s/((?:\\/|[^/])+)/((?:\\/|[^/])*)/([ig]*)$')
+ return myre.match(line)
+
+line = argv[1]
+m = is_regex(line)
+
+if m:
+ f,t,flagstr = m.groups()
+ fn = f.replace('\/','/')
+ tn = t.replace('\/','/')
+ flags = 0
+ count = 1
+ if flagstr:
+ if 'i' in flagstr:
+ flags = re.IGNORECASE
+ if 'g' in flagstr:
+ count = 0
+ else:
+ flagstr = ''
+ last = d.get(usr,None)
+ if last:
+ #print(re.sub(fn,tn,last,count=count,flags=flags))
+ from subprocess import Popen,PIPE
+ p = Popen(['sed','s/{}/{}/{}'.format(f,t,flagstr)],stdin=PIPE,stdout=PIPE )
+ so,se = p.communicate(bytes("{}\n".format(last),"UTF-8"))
+ if p.returncode:
+ print("something went wrong when trying to process your regex: {}".format(se.decode()))
+ ret = so.decode()
+ print("\x1b[1m{}\x1b[0m meinte: {}".format(usr,ret.strip()))
+ if ret:
+ d[usr] = ret
+
+ else:
+ print("no last message")
+else:
+ d[usr] = line
+
+d.close()
diff --git a/krebs/5pkgs/Reaktor/scripts/shack-correct.sh b/krebs/5pkgs/Reaktor/scripts/shack-correct.sh
new file mode 100644
index 000000000..3b4d04f80
--- /dev/null
+++ b/krebs/5pkgs/Reaktor/scripts/shack-correct.sh
@@ -0,0 +1,6 @@
+#! /bin/sh
+set -eu
+printf "Sie meinten wohl \""
+echo -n $@ | sed 's/Shack/shack/g'
+echo "\""
+echo "${_from}--"
diff --git a/krebs/5pkgs/cacpanel/default.nix b/krebs/5pkgs/cacpanel/default.nix
index 3e3e2e1fc..3df4dffed 100644
--- a/krebs/5pkgs/cacpanel/default.nix
+++ b/krebs/5pkgs/cacpanel/default.nix
@@ -2,11 +2,11 @@
python3Packages.buildPythonPackage rec {
name = "cacpanel-${version}";
- version = "0.2.1";
+ version = "0.2.3";
src = pkgs.fetchurl {
url = "https://pypi.python.org/packages/source/c/cacpanel/cacpanel-${version}.tar.gz";
- sha256 = "1zaazg5r10kgva32zh4fhpw6l6h51ijkwpa322na0kh4x6f6aqj3";
+ sha256 = "1fib7416qqv8yzrj75kxra7ccpz9abqh58b6gkaavws2fa6m3mm8";
};
propagatedBuildInputs = with python3Packages; [
diff --git a/krebs/5pkgs/default.nix b/krebs/5pkgs/default.nix
index 7df7b7d3c..c4b1dafe4 100644
--- a/krebs/5pkgs/default.nix
+++ b/krebs/5pkgs/default.nix
@@ -26,6 +26,8 @@ subdirs // rec {
inherit (subdirs) get jq;
};
+ ReaktorPlugins = pkgs.callPackage ./Reaktor/plugins.nix {};
+
execve = name: { filename, argv, envp ? {}, destination ? "" }:
writeC name { inherit destination; } ''
#include <unistd.h>
@@ -40,6 +42,10 @@ subdirs // rec {
}
'';
+ test = {
+ infest-cac-centos7 = pkgs.callPackage ./test/infest-cac-centos7 {};
+ };
+
execveBin = name: cfg: execve name (cfg // { destination = "/bin/${name}"; });
writeC = name: { destination ? "" }: src: pkgs.runCommand name {} ''
diff --git a/krebs/5pkgs/genid/default.nix b/krebs/5pkgs/genid/default.nix
deleted file mode 100644
index c75bec317..000000000
--- a/krebs/5pkgs/genid/default.nix
+++ /dev/null
@@ -1,22 +0,0 @@
-{ lib, pkgs, ... }:
-
-pkgs.writeScriptBin "genid" ''
- #! /bin/sh
- # usage: genid NAME
- set -euf
-
- export PATH=${lib.makeSearchPath "bin" (with pkgs; [
- bc
- coreutils
- ])}
-
- name=$1
- hash=$(printf %s "$name" | sha1sum | cut -d\ -f1 | tr a-f A-F)
- echo "
- min=2^24 # bigger than nobody and nogroup, see <nixos/modules/misc/ids.nix>
- # and some spare for stuff like lxd.
- max=2^32 # see 2^(8*sizeof(uid_t))
- ibase=16
- ($hash + min) % max
- " | bc
-''
diff --git a/krebs/5pkgs/krebszones/default.nix b/krebs/5pkgs/krebszones/default.nix
index f6fd672dc..9230192bd 100644
--- a/krebs/5pkgs/krebszones/default.nix
+++ b/krebs/5pkgs/krebszones/default.nix
@@ -1,5 +1,10 @@
{ lib, pkgs,python3Packages,fetchurl, ... }:
+# TODO: Prepare a diff of future and current
+## ovh-zone export krebsco.de --config ~/secrets/krebs/cfg.json |sed 's/[ ]\+/ /g' | sort current
+## sed 's/[ ]\+/ /g'/etc/zones/krebsco.de | sort > future
+## diff future.sorted current.sorted
+
python3Packages.buildPythonPackage rec {
name = "krebszones-${version}";
version = "0.4.4";
diff --git a/krebs/5pkgs/snapraid/default.nix b/krebs/5pkgs/snapraid/default.nix
deleted file mode 100644
index 41db0f284..000000000
--- a/krebs/5pkgs/snapraid/default.nix
+++ /dev/null
@@ -1,33 +0,0 @@
-{stdenv, fetchurl}:
-let
- s = # Generated upstream information
- rec {
- baseName="jq";
- version="1.5";
- name="${baseName}-${version}";
- url=https://github.com/stedolan/jq/releases/download/jq-1.5/jq-1.5.tar.gz;
- sha256="0g29kyz4ykasdcrb0zmbrp2jqs9kv1wz9swx849i2d1ncknbzln4";
- };
- buildInputs = [
- ];
-in
-stdenv.mkDerivation {
- inherit (s) name version;
- inherit buildInputs;
- src = fetchurl {
- inherit (s) url sha256;
- };
-
- # jq is linked to libjq:
- configureFlags = [
- "LDFLAGS=-Wl,-rpath,\\\${libdir}"
- ];
- meta = {
- inherit (s) version;
- description = ''A lightweight and flexible command-line JSON processor'';
- license = stdenv.lib.licenses.mit ;
- maintainers = [stdenv.lib.maintainers.raskin];
- platforms = stdenv.lib.platforms.linux ++ stdenv.lib.platforms.darwin;
- };
-}
-
diff --git a/krebs/5pkgs/krebs-ci/default.nix b/krebs/5pkgs/test/infest-cac-centos7/default.nix
index f5b302b52..7f2e3f231 100644
--- a/krebs/5pkgs/krebs-ci/default.nix
+++ b/krebs/5pkgs/test/infest-cac-centos7/default.nix
@@ -1,7 +1,9 @@
{ stdenv, coreutils,makeWrapper, cac, cacpanel, gnumake, gnused, jq, openssh, ... }:
stdenv.mkDerivation rec {
- name = "krebs-ci-0.1.0";
+ name = "${shortname}-${version}";
+ shortname = "infest-cac-centos7";
+ version = "0.2.0";
src = ./notes;
@@ -23,9 +25,9 @@ stdenv.mkDerivation rec {
installPhase =
''
mkdir -p $out/bin
- cp ${src} $out/bin/krebs-ci
- chmod +x $out/bin/krebs-ci
- wrapProgram $out/bin/krebs-ci \
+ cp ${src} $out/bin/${shortname}
+ chmod +x $out/bin/${shortname}
+ wrapProgram $out/bin/${shortname} \
--prefix PATH : ${path}
'';
meta = with stdenv.lib; {
diff --git a/krebs/5pkgs/krebs-ci/notes b/krebs/5pkgs/test/infest-cac-centos7/notes
index 7e34d6a28..6bfb6906e 100755
--- a/krebs/5pkgs/krebs-ci/notes
+++ b/krebs/5pkgs/test/infest-cac-centos7/notes
@@ -1,12 +1,24 @@
#! /bin/sh
# nix-shell -p gnumake jq openssh cac cacpanel
-set -euf
+set -eufx
# 2 secrets are required:
+
krebs_cred=${krebs_cred-./cac.json}
retiolum_key=${retiolum_key-./retiolum.rsa_key.priv}
+clear_defer(){
+ echo "${trapstr:-exit}"
+ trap - INT TERM EXIT KILL
+}
+defer(){
+ if test -z "${debug:-}"; then
+ trapstr="$1;${trapstr:-exit}"
+ trap "$trapstr" INT TERM EXIT KILL
+ fi
+}
+
# Sanity
if test ! -r "$krebs_cred";then
echo "\$krebs_cred=$krebs_cred must be readable"; exit 1
@@ -18,46 +30,73 @@ fi
krebs_secrets=$(mktemp -d)
sec_file=$krebs_secrets/cac_config
krebs_ssh=$krebs_secrets/tempssh
+export cac_resources_cache=$krebs_secrets/res_cache.json
+export cac_servers_cache=$krebs_secrets/servers_cache.json
+export cac_tasks_cache=$krebs_secrets/tasks_cache.json
+export cac_templates_cache=$krebs_secrets/templates_cache.json
# we need to receive this key from buildmaster to speed up tinc bootstrap
-TRAP="rm $sec_file;rm -r $krebs_secrets"
-trap "$TRAP" INT TERM EXIT
+defer "trap - INT TERM EXIT"
+defer "rm -r $krebs_secrets"
cat > $sec_file <<EOF
cac_login="$(jq -r .email $krebs_cred)"
-cac_key="$(cac-cli panel --config $krebs_cred settings | jq -r .apicode)"
+cac_key="$(cac-cli --config $krebs_cred panel settings | jq -r .apicode)"
EOF
export cac_secrets=$sec_file
-cac-cli panel --config $krebs_cred update-api-ip
+cac-cli --config $krebs_cred panel add-api-ip
# test login:
cac update
cac servers
-# Template 26: CentOS7
-# TODO: use cac templates to determine the real Centos7 template in case it changes
-name=$( cac build cpu=1 ram=512 storage=10 os=26 2>&1\
- | jq -r .servername)
+# preserve old trap
+old_trapstr=$(clear_defer)
+while true;do
+ # Template 26: CentOS7
+ # TODO: use cac templates to determine the real Centos7 template in case it changes
+ out=$(cac build cpu=1 ram=512 storage=10 os=26 2>&1)
+ if name=$(echo "$out" | jq -r .servername);then
+ id=servername:$name
+ echo "got a working machine, id=$id"
+ else
+ echo "Unable to build a virtual machine, retrying in 15 seconds" >&2
+ echo "Output of build program: $out" >&2
+ sleep 15
+ continue
+ fi
-id=servername:$name
-trap "cac delete $id;$TRAP" INT TERM EXIT
-# TODO: timeout?
-always_update=true cac waitstatus $id "Powered On"
+ clear_defer >/dev/null
+ defer "cac delete $id"
-wait_login_cac(){
- # timeout
- for t in `seq 60`;do
- # now we have a working cac server
- if cac ssh $1 cat /etc/redhat-release | \
- grep CentOS ;then
- return 0
- fi
- sleep 10
- done
- return 1
-}
-# die on timeout
-wait_login_cac $id
+ # TODO: timeout?
+
+ wait_login_cac(){
+ # we wait for 30 minutes
+ for t in `seq 180`;do
+ # now we have a working cac server
+ if cac ssh $1 -o ConnectTimeout=10 \
+ cat /etc/redhat-release | \
+ grep CentOS ;then
+ return 0
+ fi
+ sleep 10
+ done
+ return 1
+ }
+ # die on timeout
+ if ! wait_login_cac $id;then
+ echo "unable to boot a working system within time frame, retrying..." >&2
+ echo "Cleaning up old image,last status: $(cac update;cac getserver $id | jq -r .status)"
+ eval "$(clear_defer | sed 's/;exit//')"
+ sleep 15
+ else
+ echo "got a working system" >&2
+ break
+ fi
+done
+clear_defer >/dev/null
+defer "cac delete $id;$old_trapstr"
mkdir -p shared/2configs/temp
cac generatenetworking $id > \
@@ -94,7 +133,7 @@ cac powerop $id reset
wait_login(){
# timeout
- for t in `seq 20`;do
+ for t in `seq 90`;do
# now we have a working cac server
if ssh -o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
diff --git a/krebs/Zhosts/bobby b/krebs/Zhosts/bobby
new file mode 100644
index 000000000..aac6e377b
--- /dev/null
+++ b/krebs/Zhosts/bobby
@@ -0,0 +1,11 @@
+Subnet = 10.243.111.112/32
+Subnet = 42:0:0:0:0:0:111:112/128
+
+-----BEGIN RSA PUBLIC KEY-----
+MIIBCgKCAQEA+AScnIqFdzGl+iRZTNZ7r91n/r1H4GzDsrAupUvJ4mi7nDN4eP8s
+uLvKtJp22RxfuF3Kf4KhHb8LHQ8bLLN/KDaNDXrCNBc69d7vvLsjoY+wfGLJNu4Y
+Ad/8J4r3rdb83mTA3IHb47T/70MERPBr2gF84YiG6ZoQrPQuTk4lHxaI83SOhjny
+0F0ucS/rBV6Vv9y5/756TKi1cFPSpY4X+qeWc8xWrBGJcJiiqYb8ZX2o/lkAJ5c+
+jI/VdybGFVGY9+bp4Jw5xBIo5KGuFnm8+blRmSDDl3joRneKQSx9FAu7RUwoajBu
+cEbi1529NReQzIFT6Vt22ymbHftxOiuh4QIDAQAB
+-----END RSA PUBLIC KEY-----
diff --git a/krebs/Zhosts/kebsco b/krebs/Zhosts/kebsco
new file mode 100644
index 000000000..2fd1c5f42
--- /dev/null
+++ b/krebs/Zhosts/kebsco
@@ -0,0 +1,11 @@
+Subnet = 10.243.212.68
+Subnet = 42:9d30:3845:c822:988b:96c5:39ab:90b7
+
+-----BEGIN RSA PUBLIC KEY-----
+MIIBCgKCAQEA0dEwTZh2uzJpP9GL7YRyiLuezJqYiJ8/4Bl4IPshJnuO9IGbEcto
+0cFm9uM9gxxqggfaCi96DsIQNlyqff2vDfEj3mdIu9T3tkRROByQF8y1NWX29NyH
+zZEX8Ri8u4U2KdYTEzPXEFxBEl0GQX9mMtlvwzCq7V4ueCcWB1xDA+DtJjpd894z
+3FOw0rIxYmfYhLAL5B3rzF74bcHFGV30f4JWq11wLBkyR6/Q5gxgZzkKYGwdZ/SN
+C6gg86abKdp65/Wq5P331IbwPBal1ZhGbaAo1y7JpjpLvZytI2jboXeQuPZ8P5hU
+L3zKKceAibPKrw9+y8lb+IKoYLF7I1KYIwIDAQAB
+-----END RSA PUBLIC KEY-----
diff --git a/krebs/default.nix b/krebs/default.nix
index ad0205426..15d0e8e2e 100644
--- a/krebs/default.nix
+++ b/krebs/default.nix
@@ -36,6 +36,7 @@ let out = {
{ system ? current-host-name
, target ? system
}@args: let
+ config = get-config system;
in ''
#! /bin/sh
# ${current-date} ${current-user-name}@${current-host-name}
@@ -47,6 +48,9 @@ let out = {
${builtins.readFile ./4lib/infest/install-nix.sh}
''}
+ # Prepare target source via bind-mounting
+
+
(${nixos-install args})
${rootssh target ''
@@ -98,7 +102,7 @@ let out = {
#! /bin/sh
# ${current-date} ${current-user-name}@${current-host-name}
# krebs.nixos-install
- (${populate args})
+ (${populate (args // { root = "/mnt"; })})
${rootssh target ''
export PATH; PATH=/root/.nix-profile/bin:$PATH
@@ -205,6 +209,7 @@ let out = {
populate =
{ system ? current-host-name
, target ? system
+ , root ? ""
}@args:
let out = ''
#! /bin/sh
@@ -217,6 +222,7 @@ let out = {
["dir" "git"])}
'';
+
config = get-config system;
current-host = config.krebs.hosts.${current-host-name};
@@ -225,17 +231,18 @@ let out = {
methods.dir = config:
let
can-push = config.host.name == current-host.name;
+ target-path = root + config.target-path;
push-method = ''
rsync \
--exclude .git \
--exclude .graveyard \
--exclude old \
--exclude tmp \
- --rsync-path='mkdir -p ${config.target-path} && rsync' \
+ --rsync-path='mkdir -p ${target-path} && rsync' \
--delete-excluded \
-vrLptgoD \
${config.path}/ \
- root@${target}:${config.target-path}
+ root@${target}:${target-path}
'';
in
if can-push then push-method else
@@ -244,9 +251,10 @@ let out = {
throw "No way to push ${dir} from ${current-host.name} to ${target}";
methods.git = config:
- rootssh target ''
- mkdir -p ${config.target-path}
- cd ${config.target-path}
+ let target-path = root + config.target-path;
+ in rootssh target ''
+ mkdir -p ${target-path}
+ cd ${target-path}
if ! test -e .git; then
git init
fi
[cgit] Unable to lock slot /tmp/cgit/ec200000.lock: No such file or directory (2)