Merge remote-tracking branch 'cd/master'

This commit is contained in:
makefu 2016-02-22 14:35:59 +01:00
commit b25d15573a
54 changed files with 1418 additions and 1120 deletions

View File

@ -1,5 +1,32 @@
ifndef system
$(error unbound variable: system)
stockholm ?= .
ifndef nixos-config
$(if $(system),,$(error unbound variable: system))
nixos-config = ./$(LOGNAME)/1systems/$(system).nix
endif
# target = [target_user@]target_host[:target_port][/target_path]
ifdef target
_target_user != echo $(target) | sed -n 's/@.*//p'
_target_path != echo $(target) | sed -n 's/^[^/]*//p'
_target_port != echo $(target) | sed -En 's|^.*:([^/]*)(/.*)?$$|\1|p'
_target_host != echo $(target) | sed -En 's/^(.*@)?([^:/]*).*/\2/p'
ifneq ($(_target_host),)
$(if $(target_host),$(error cannot define both, target_host and host in target))
target_host ?= $(_target_host)
endif
ifneq ($(_target_user),)
$(if $(target_user),$(error cannot define both, target_user and user in target))
target_user ?= $(_target_user)
endif
ifneq ($(_target_port),)
$(if $(target_port),$(error cannot define both, target_port and port in target))
target_port ?= $(_target_port)
endif
ifneq ($(_target_path),)
$(if $(target_path),$(error cannot define both, target_path and path in target))
target_path ?= $(_target_path)
endif
endif
export target_host ?= $(system)
@ -7,29 +34,37 @@ export target_user ?= root
export target_port ?= 22
export target_path ?= /var/src
$(if $(target_host),,$(error unbound variable: target_host))
$(if $(target_user),,$(error unbound variable: target_user))
$(if $(target_port),,$(error unbound variable: target_port))
$(if $(target_path),,$(error unbound variable: target_path))
evaluate = \
nix-instantiate \
--eval \
--readonly-mode \
--show-trace \
-I nixos-config=./$(LOGNAME)/1systems/$(system).nix \
-I stockholm=. \
$(1)
-I nixos-config=$(nixos-config) \
-I stockholm=$(stockholm) \
-E '{ eval, f }: f eval' \
--arg eval 'import ./.' \
--arg f "eval@{ config, ... }: $(1)"
execute = \
result=$$($(call evaluate,-A config.krebs.build.$(1) --json)) && \
result=$$($(call evaluate,config.krebs.build.$(1))) && \
script=$$(echo "$$result" | jq -r .) && \
echo "$$script" | sh
echo "$$script" | PS5=% sh
# usage: make deploy system=foo [target_host=bar]
deploy: ssh ?= ssh
deploy:
$(call execute,populate)
ssh $(target_user)@$(target_host) -p $(target_port) \
$(ssh) $(target_user)@$(target_host) -p $(target_port) \
nixos-rebuild switch --show-trace -I $(target_path)
# usage: make LOGNAME=shared system=wolf eval.config.krebs.build.host.name
eval eval.:;@$(call evaluate)
eval.%:;@$(call evaluate,-A $*)
eval eval.:;@$(call evaluate,$${expr-eval})
eval.%:;@$(call evaluate,$*)
# usage: make install system=foo [target_host=bar]
install: ssh ?= ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
@ -41,3 +76,21 @@ install:
$(ssh) $(target_user)@$(target_host) -p $(target_port) \
env NIXOS_CONFIG=$(target_path)/nixos-config \
nixos-install
# usage: make test system=foo [target=bar] [method={eval,build}]
method ?= eval
ifeq ($(method),build)
test: command = nix-build --no-out-link
else
ifeq ($(method),eval)
test: command ?= nix-instantiate --eval --json --readonly-mode --strict
else
$(error bad method: $(method))
endif
endif
test: ssh ?= ssh
test:
$(call execute,populate)
$(ssh) $(target_user)@$(target_host) -p $(target_port) \
$(command) --show-trace -I $(target_path) \
-A config.system.build.toplevel $(target_path)/stockholm

View File

@ -117,6 +117,14 @@ let
"$dst_user@$dst_host" \
-T "$with_dst_path_lock_script"
}
rsh="ssh -F /dev/null -i $identity ''${dst_port:+-p $dst_port}"
local_rsync() {
rsync "$@"
}
remote_rsync=${shell.escape (concatStringsSep " && " [
"mkdir -m 0700 -p ${shell.escape plan.dst.path}/current"
"exec flock -n ${shell.escape plan.dst.path} rsync"
])}
'';
pull = ''
identity=${shell.escape plan.dst.host.ssh.privkey.path}
@ -131,6 +139,12 @@ let
dst_shell() {
eval "$with_dst_path_lock_script"
}
rsh="ssh -F /dev/null -i $identity ''${src_port:+-p $src_port}"
local_rsync() {
mkdir -m 0700 -p ${shell.escape plan.dst.path}/current
flock -n ${shell.escape plan.dst.path} rsync "$@"
}
remote_rsync=rsync
'';
}}
# Note that this only works because we trust date +%s to produce output
@ -140,13 +154,10 @@ let
with_dst_path_lock_script="exec env start_date=$(date +%s) "${shell.escape
"flock -n ${shell.escape plan.dst.path} /bin/sh"
}
rsync >&2 \
local_rsync >&2 \
-aAXF --delete \
-e "ssh -F /dev/null -i $identity ''${dst_port:+-p $dst_port}" \
--rsync-path ${shell.escape (concatStringsSep " && " [
"mkdir -m 0700 -p ${shell.escape plan.dst.path}/current"
"exec flock -n ${shell.escape plan.dst.path} rsync"
])} \
--rsh="$rsh" \
--rsync-path="$remote_rsync" \
--link-dest="$dst_path/current" \
"$src/" \
"$dst/.partial"

View File

@ -20,35 +20,19 @@ let
type = types.user;
};
options.krebs.build.source = let
raw = types.either types.str types.path;
url = types.submodule {
options.krebs.build.source = mkOption {
type = with types; attrsOf (either str (submodule {
options = {
url = mkOption {
type = types.str;
};
rev = mkOption {
type = types.str;
};
dev = mkOption {
type = types.str;
};
url = str;
rev = 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.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-port = maybeEnv "target_port" "22";
@ -57,13 +41,16 @@ let
#! /bin/sh
set -eu
ssh=''${ssh-ssh}
verbose() {
printf '+%s\n' "$(printf ' %q' "$@")" >&2
printf '%s%s\n' "$PS5$(printf ' %q' "$@")" >&2
"$@"
}
echo ${shell.escape git-script} \
| ssh -p ${shell.escape target-port} \
{ printf 'PS5=%q%q\n' @ "$PS5"
echo ${shell.escape git-script}
} | verbose $ssh -p ${shell.escape target-port} \
${shell.escape "${target-user}@${target-host}"} -T
unset tmpdir
@ -75,61 +62,34 @@ let
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)}
${concatStringsSep "\n" (mapAttrsToList (name: symlink: ''
verbose ln -s ${shell.escape symlink.target} \
"$tmpdir"/${shell.escape name}
'') source-by-method.symlink)}
verbose proot \
-b $tmpdir:${shell.escape target-path} \
${concatStringsSep " \\\n "
(mapAttrsToList
(name: spec:
"-b ${shell.escape "${get-url spec}:${target-path}/${name}"}")
file-specs)} \
-b "$tmpdir":${shell.escape target-path} \
${concatStringsSep " \\\n " (mapAttrsToList (name: file:
"-b ${shell.escape "${file.path}:${target-path}/${name}"}"
) source-by-method.file)} \
rsync \
-f ${shell.escape "P /*"} \
${concatMapStringsSep " \\\n "
(name: "-f ${shell.escape "R /${name}"}")
(attrNames file-specs)} \
${concatMapStringsSep " \\\n " (name:
"-f ${shell.escape "R /${name}"}"
) (attrNames source-by-method.file)} \
--delete \
-vFrlptD \
-e ${shell.escape "ssh -p ${target-port}"} \
-e "$ssh -p ${shell.escape target-port}" \
${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
printf '%s%s\n' "$PS5$(printf ' %q' "$@")" >&2
"$@"
}
@ -156,26 +116,48 @@ let
if ! test "$(git log --format=%H -1)" = "$hash"; then
git fetch origin
git checkout "$hash" -- "$dst_dir"
git checkout "$hash"
git checkout -f "$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)}
${concatStringsSep "\n" (mapAttrsToList (name: git: ''
verbose fetch_git ${concatMapStringsSep " " shell.escape [
"${target-path}/${name}"
git.url
git.rev
]}
'') source-by-method.git)}
'';
in out;
};
};
source-by-method = let
known-methods = ["git" "file" "symlink"];
in genAttrs known-methods (const {}) // recursiveUpdate source-by-scheme {
git = source-by-scheme.http or {} //
source-by-scheme.https or {};
};
source-by-scheme = foldl' (out: { k, v }: recursiveUpdate out {
${v.scheme}.${k} = v;
}) {} (mapAttrsToList (k: v: { inherit k v; }) normalized-source);
normalized-source = mapAttrs (name: let f = x: getAttr (typeOf x) {
path = f (toString x);
string = f {
url = if substring 0 1 x == "/" then "file://${x}" else x;
};
set = let scheme = head (splitString ":" x.url); in recursiveUpdate x {
inherit scheme;
} // {
symlink.target = removePrefix "symlink:" x.url;
file.path = # TODO file://host/...
assert hasPrefix "file:///" x.url;
removePrefix "file://" x.url;
}.${scheme} or {};
}; in f) config.krebs.build.source;
in out

View File

@ -28,6 +28,7 @@ let
./realwallpaper.nix
./retiolum-bootstrap.nix
./retiolum.nix
./secret.nix
./setuid.nix
./tinc_graphs.nix
./urlwatch.nix
@ -42,9 +43,7 @@ let
dns = {
providers = mkOption {
# TODO with types; tree dns.label dns.provider, so we can merge.
# Currently providers can only be merged if aliases occur just once.
type = with types; attrsOf unspecified;
type = with types; attrsOf str;
};
};
@ -94,7 +93,7 @@ let
{ krebs = import ./tv { inherit config lib; }; }
{
krebs.dns.providers = {
de.krebsco = "zones";
"krebsco.de" = "zones";
gg23 = "hosts";
shack = "hosts";
i = "hosts";
@ -103,13 +102,27 @@ let
retiolum = "hosts";
};
networking.extraHosts = concatStringsSep "\n" (flatten (
krebs.users = {
krebs = {
home = "/krebs";
mail = "spam@krebsco.de";
};
root = {
home = "/root";
pubkey = config.krebs.build.host.ssh.pubkey;
uid = 0;
};
};
networking.extraHosts = let
domains = attrNames (filterAttrs (_: eq "hosts") cfg.dns.providers);
check = hostname: any (domain: hasSuffix ".${domain}" hostname) domains;
in concatStringsSep "\n" (flatten (
mapAttrsToList (hostname: host:
mapAttrsToList (netname: net:
let
aliases = longs ++ shorts;
providers = dns.split-by-provider net.aliases cfg.dns.providers;
longs = providers.hosts;
longs = filter check net.aliases;
shorts = let s = ".${cfg.search-domain}"; in
map (removeSuffix s) (filter (hasSuffix s) longs);
in
@ -130,12 +143,11 @@ let
{ text=(stripEmptyLines value); }) all-zones;
krebs.exim-smarthost.internet-aliases = let
format = from: to:
format = from: to: {
inherit from;
# TODO assert is-retiolum-mail-address to;
{ inherit from;
to = if typeOf to == "list"
then concatMapStringsSep "," (getAttr "mail") to
else to.mail; };
to = concatMapStringsSep "," (getAttr "mail") (toList to);
};
in mapAttrsToList format (with config.krebs.users; let
spam-ml = [
lass
@ -154,6 +166,10 @@ let
"makefu@retiolum" = makefu;
"spam@retiolum" = spam-ml;
"tv@retiolum" = tv;
"lass@r" = lass;
"makefu@r" = makefu;
"spam@r" = spam-ml;
"tv@r" = tv;
});
services.openssh.hostKeys =

View File

@ -11,6 +11,24 @@ let
api = {
enable = mkEnableOption "krebs.exim-retiolum";
local_domains = mkOption {
type = with types; listOf hostname;
default = ["localhost"] ++ config.krebs.build.host.nets.retiolum.aliases;
};
primary_hostname = mkOption {
type = types.str;
default = let x = "${config.krebs.build.host.name}.r"; in
assert elem x config.krebs.build.host.nets.retiolum.aliases;
x;
};
relay_to_domains = mkOption {
# TODO hostname with wildcards
type = with types; listOf str;
default = [
"*.r"
"*.retiolum"
];
};
};
imp = {
@ -21,9 +39,9 @@ let
# TODO modular configuration
assert config.krebs.retiolum.enable;
''
primary_hostname = ${retiolumHostname}
domainlist local_domains = @ : localhost
domainlist relay_to_domains = *.retiolum
primary_hostname = ${cfg.primary_hostname}
domainlist local_domains = ${concatStringsSep ":" cfg.local_domains}
domainlist relay_to_domains = ${concatStringsSep ":" cfg.relay_to_domains}
hostlist relay_from_hosts = <; 127.0.0.1 ; ::1
acl_smtp_rcpt = acl_check_rcpt
@ -85,7 +103,7 @@ let
retiolum:
driver = manualroute
domains = ! ${retiolumHostname} : *.retiolum
domains = ! +local_domains : +relay_to_domains
transport = remote_smtp
route_list = ^.* $0 byname
no_more
@ -125,8 +143,8 @@ let
# mode = 0660
begin retry
*.retiolum * F,42d,1m
* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
${concatMapStringsSep "\n" (k: "${k} * F,42d,1m") cfg.relay_to_domains}
* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
begin rewrite
@ -134,8 +152,4 @@ let
'';
};
};
# TODO get the hostname from somewhere else.
retiolumHostname = "${config.networking.hostName}.retiolum";
in
out
in out

View File

@ -25,14 +25,31 @@ let
}));
};
local_domains = mkOption {
type = with types; listOf hostname;
default = ["localhost"] ++ config.krebs.build.host.nets.retiolum.aliases;
};
relay_from_hosts = mkOption {
type = with types; listOf str;
default = [];
apply = xs: ["127.0.0.1" "::1"] ++ xs;
};
relay_to_domains = mkOption {
# TODO hostname with wildcards
type = with types; listOf str;
default = [
"*.r"
"*.retiolum"
];
};
primary_hostname = mkOption {
type = types.str;
default = "${config.networking.hostName}.retiolum";
default = let x = "${config.krebs.build.host.name}.r"; in
assert elem x config.krebs.build.host.nets.retiolum.aliases;
x;
};
sender_domains = mkOption {
@ -63,19 +80,11 @@ let
# HOST_REDIR contains the real destinations for "local_domains".
#HOST_REDIR = /etc/exim4/host_redirect
# Domains not listed in local_domains need to be deliverable remotely.
# XXX We abuse local_domains to mean "domains, we're the gateway for".
domainlist local_domains = @ : localhost
domainlist relay_to_domains =
hostlist relay_from_hosts = <;${concatStringsSep ";" (
[
"127.0.0.1"
"::1"
]
++
cfg.relay_from_hosts
)}
domainlist local_domains = ${concatStringsSep ":" cfg.local_domains}
domainlist relay_to_domains = ${concatStringsSep ":" cfg.relay_to_domains}
hostlist relay_from_hosts = <;${concatStringsSep ";" cfg.relay_from_hosts}
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data
@ -144,7 +153,7 @@ let
retiolum:
debug_print = "R: retiolum for $local_part@$domain"
driver = manualroute
domains = ! ${cfg.primary_hostname} : *.retiolum
domains = ! +local_domains : +relay_to_domains
transport = retiolum_smtp
route_list = ^.* $0 byname
no_more
@ -197,8 +206,11 @@ let
return_path_add
begin retry
*.retiolum * F,42d,1m
* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
${concatMapStringsSep "\n" (k: "${k} * F,42d,1m") cfg.relay_to_domains}
${concatMapStringsSep "\n" (k: "${k} * F,42d,1m")
# TODO don't include relay_to_domains
(map (getAttr "from") cfg.internet-aliases)}
* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
begin rewrite
begin authenticators

View File

@ -232,13 +232,15 @@ let
]) (filter (rule: rule.perm.allow-receive-ref != null) cfg.rules));
};
users.extraUsers = singleton rec {
# TODO cfg.user
users.users.git = rec {
description = "Git repository hosting user";
name = "git";
shell = "/bin/sh";
openssh.authorizedKeys.keys =
mapAttrsToList (_: makeAuthorizedKey git-ssh-command)
config.krebs.users;
(filterAttrs (_: user: isString user.pubkey)
config.krebs.users);
uid = genid name;
};
};

View File

@ -3,7 +3,7 @@
with config.krebs.lib;
{
hosts = {
hosts = mapAttrs (_: setAttr "owner" config.krebs.users.lass) {
dishfire = {
cores = 4;
nets = rec {

View File

@ -10,6 +10,6 @@ let
type = types.attrs;
};
imp = {
krebs.lib = lib // import ../4lib { inherit lib; } // builtins;
krebs.lib = lib // import ../4lib { inherit config lib; } // builtins;
};
in out

View File

@ -3,7 +3,7 @@
with config.krebs.lib;
{
hosts = {
hosts = mapAttrs (_: setAttr "owner" config.krebs.users.makefu) {
pnp = {
cores = 1;
nets = {

View File

@ -3,7 +3,7 @@
with config.krebs.lib;
{
hosts = {
hosts = mapAttrs (_: setAttr "owner" config.krebs.users.miefda) {
bobby = {
cores = 4;
nets = {

View File

@ -3,7 +3,7 @@
with config.krebs.lib;
{
hosts = {
hosts = mapAttrs (_: setAttr "owner" config.krebs.users.mv) {
stro = {
cores = 4;
nets = {

39
krebs/3modules/secret.nix Normal file
View File

@ -0,0 +1,39 @@
{ config, lib, pkgs, ... }@args: with config.krebs.lib; let
cfg = config.krebs.secret;
in {
options.krebs.secret = {
files = mkOption {
type = with types; attrsOf secret-file;
default = {};
};
};
config = lib.mkIf (cfg.files != {}) {
systemd.services.secret = let
# TODO fail if two files have the same path but differ otherwise
files = unique (map (flip removeAttrs ["_module"])
(attrValues cfg.files));
in {
serviceConfig = {
Type = "oneshot";
RemainAfterExit = "yes";
SyslogIdentifier = "secret";
ExecStart = pkgs.writeDash "install-secret-files" ''
exit_code=0
${concatMapStringsSep "\n" (file: ''
${pkgs.coreutils}/bin/install \
-D \
--compare \
--verbose \
--mode=${shell.escape file.mode} \
--owner=${shell.escape file.owner.name} \
--group=${shell.escape file.group-name} \
${shell.escape file.source-path} \
${shell.escape file.path} \
|| exit_code=1
'') files}
exit $exit_code
'';
};
};
};
}

View File

@ -15,6 +15,7 @@ let
addrs4 = ["10.243.111.111"];
addrs6 = ["42:0:0:0:0:0:0:7357"];
aliases = [
"test.r"
"test.retiolum"
];
tinc.pubkey = ''

View File

@ -4,9 +4,9 @@ with config.krebs.lib;
{
dns.providers = {
de.viljetic = "regfish";
"viljetic.de" = "regfish";
};
hosts = {
hosts = mapAttrs (_: setAttr "owner" config.krebs.users.tv) {
cd = rec {
cores = 2;
extraZones = {
@ -352,8 +352,9 @@ with config.krebs.lib;
pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGer9e2+Lew7vnisgBbsFNECEIkpNJgEaqQqgb9inWkQ mv@vod";
};
tv = {
mail = "tv@wu.retiolum";
mail = "tv@nomic.retiolum";
pubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAEAQDFR//RnCvEZAt0F6ExDsatKZ/DDdifanuSL360mqOhaFieKI34RoOwfQT9T+Ga52Vh5V2La6esvlph686EdgzeKLvDoxEwFM9ZYFBcMrNzu4bMTlgE7YUYw5JiORyXNfznBGnme6qpuvx9ibYhUyiZo99kM8ys5YrUHrP2JXQJMezDFZHxT4GFMOuSdh/1daGoKKD6hYL/jEHX8CI4E3BSmKK6ygYr1fVX0K0Tv77lIi5mLXucjR7CytWYWYnhM6DC3Hxpv2zRkPgf3k0x/Y1hrw3V/r0Me5h90pd2C8pFaWA2ZoUT/fmyVqvx1tZPYToU/O2dMItY0zgx2kR0yD+6g7Aahz3R+KlXkV8k5c8bbTbfGnZWDR1ZlbLRM9Yt5vosfwapUD90MmVkpmR3wUkO2sUKi80QfC7b4KvSDXQ+MImbGxMaU5Bnsq1PqLN95q+uat3nlAVBAELkcx51FlE9CaIS65y4J7FEDg8BE5JeuCNshh62VSYRXVSFt8bk3f/TFGgzC8OIo14BhVmiRQQ503Z1sROyf5xLX2a/EJavMm1i2Bs2TH6ROKY9z5Pz8hT5US0r381V8oG7TZyLF9HTtoy3wCYsgWA5EmLanjAsVU2YEeAA0rxzdtYP8Y2okFiJ6u+M4HQZ3Wg3peSodyp3vxdYce2vk4EKeqEFuuS82850DYb7Et7fmp+wQQUT8Q/bMO0DreWjHoMM5lE4LJ4ME6AxksmMiFtfo/4Fe2q9D+LAqZ+ANOcv9M+8Rn6ngiYmuRNd0l/a02q1PEvO6vTfXgcl4f7Z1IULHPEaDNZHCJS1K5RXYFqYQ6OHsTmOm7hnwaRAS97+VFMo1i5uvTx9nYaAcY7yzq3Ckfb67dMBKApGOpJpkvPgfrP7bgBO5rOZXM1opXqVPb09nljAhhAhyCTh1e/8+mJrBo0cLQ/LupQzVxGDgm3awSMPxsZAN45PSWz76zzxdDa1MMo51do+VJHfs7Wl0NcXAQrniOBYL9Wqt0qNkn1gY5smkkISGeQ/vxNap4MmzeZE7b5fpOy+2fpcRVQLpc4nooQzJvSVTFz+25lgZ6iHf45K87gQFMIAri1Pf/EDDpL87az+bRWvWi+BA2kMe1kf+Ay1LyMz8r+g51H0ma0bNFh6+fbWMfUiD9JCepIObclnUJ4NlWfcgHxTf17d/4tl6z4DTcLpCCk8Da77JouSHgvtcRbRlFV1OfhWZLXUsrlfpaQTiItv6TGIr3k7+7b66o3Qw/GQVs5GmYifaIZIz8n8my4XjkaMBd0SZfBzzvFjHMq6YUP9+SbjvReqofuoO+5tW1wTYZXitFFBfwuHlXm6w77K5QDBW6olT7pat41/F5eGxLcz tv@wu";
uid = 1337; # TODO use default
};
tv-nomic = {
inherit (tv) mail;

View File

@ -3,7 +3,6 @@
# TODO multiple users
# TODO inform about unused caches
# cache = url: "${cfg.dataDir}/.urlwatch/cache/${hashString "sha1" url}"
# TODO hooks.py
with config.krebs.lib;
let
@ -32,6 +31,14 @@ let
Content of the From: header of the generated mails.
'';
};
# TODO hooks :: attrsOf hook
hooksFile = mkOption {
type = with types; nullOr path;
default = null;
description = ''
File to use as hooks.py module.
'';
};
mailto = mkOption {
type = types.str;
default = config.krebs.build.user.mail;
@ -48,7 +55,7 @@ let
'';
};
urls = mkOption {
type = with types; listOf str;
type = with types; listOf (either str subtypes.job);
default = [];
description = "URL to watch.";
example = [
@ -56,7 +63,10 @@ let
];
apply = map (x: getAttr (typeOf x) {
set = x;
string.url = x;
string = {
url = x;
filter = null;
};
});
};
verbose = mkOption {
@ -68,9 +78,12 @@ let
};
};
urlsFile = toFile "urls" (concatMapStringsSep "\n---\n" toJSON cfg.urls);
urlsFile = pkgs.writeText "urls"
(concatMapStringsSep "\n---\n" toJSON cfg.urls);
configFile = toFile "urlwatch.yaml" (toJSON {
hooksFile = cfg.hooksFile;
configFile = pkgs.writeText "urlwatch.yaml" (toJSON {
display = {
error = true;
new = true;
@ -127,10 +140,10 @@ let
User = user.name;
PermissionsStartOnly = "true";
PrivateTmp = "true";
SyslogIdentifier = "urlwatch";
Type = "oneshot";
ExecStartPre =
pkgs.writeScript "urlwatch-prestart" ''
#! /bin/sh
pkgs.writeDash "urlwatch-prestart" ''
set -euf
dataDir=$HOME
@ -140,31 +153,29 @@ let
chown ${user.name}: "$dataDir"
fi
'';
ExecStart = pkgs.writeScript "urlwatch" ''
#! /bin/sh
ExecStart = pkgs.writeDash "urlwatch" ''
set -euf
from=${escapeShellArg cfg.from}
mailto=${escapeShellArg cfg.mailto}
urlsFile=${escapeShellArg urlsFile}
configFile=${escapeShellArg configFile}
cd /tmp
urlwatch \
${optionalString cfg.verbose "-v"} \
--urls="$urlsFile" \
--config="$configFile" \
--config=${shell.escape configFile} \
${optionalString (hooksFile != null)
"--hooks=${shell.escape hooksFile}"
} \
--urls=${shell.escape urlsFile} \
> changes || :
if test -s changes; then
date=$(date -R)
subject=$(sed -n 's/^\(CHANGED\|ERROR\|NEW\): //p' changes \
| tr \\n \ )
{
echo "Date: $date"
echo "From: $from"
echo "Subject: $subject"
echo "To: $mailto"
echo Date: $(date -R)
echo From: ${shell.escape cfg.from}
echo Subject: $(
sed -n 's/^\(CHANGED\|ERROR\|NEW\): //p' changes \
| tr '\n' ' '
)
echo To: ${shell.escape cfg.mailto}
echo
cat changes
} | /var/setuid-wrappers/sendmail -t
@ -181,5 +192,15 @@ let
name = "urlwatch";
uid = genid name;
};
in
out
subtypes.job = types.submodule {
options = {
url = mkOption {
type = types.str;
};
filter = mkOption {
type = with types; nullOr str; # TODO nullOr subtypes.filter
};
};
};
in out

View File

@ -1,4 +1,4 @@
{ lib, ... }:
{ config, lib, ... }:
with builtins;
with lib;
@ -15,14 +15,15 @@ let out = rec {
addNames = mapAttrs addName;
types = import ./types.nix { inherit lib; };
types = import ./types.nix {
inherit config;
lib = lib // { inherit genid; };
};
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; };
tree = import ./tree.nix { inherit lib; };

View File

@ -1,31 +0,0 @@
{ lib, ... }:
let
listset = import ./listset.nix { inherit lib; };
in
with builtins;
with lib;
rec {
# label = string
# TODO does it make sense to have alias = list label?
# split-by-provider :
# [[label]] -> tree label provider -> listset provider alias
split-by-provider = as: providers:
foldl (m: a: listset.insert (provider-of a providers) a m) {} as;
# provider-of : alias -> tree label provider -> provider
# Note that we cannot use tree.get here, because path can be longer
# than the tree depth.
provider-of = a:
let
go = path: tree:
if typeOf tree == "string"
then tree
else go (tail path) tree.${head path};
in
go (reverseList (splitString "." a));
}

View File

@ -184,26 +184,21 @@ prepare_common() {(
. /root/.nix-profile/etc/profile.d/nix.sh
for i in \
bash \
coreutils \
# This line intentionally left blank.
do
if ! nix-env -q $i | grep -q .; then
nix-env -iA nixpkgs.pkgs.$i
fi
done
mkdir -p /mnt/"$target_path"
mkdir -p "$target_path"
# install nixos-install
if ! type nixos-install 2>/dev/null; then
nixpkgs_expr='import <nixpkgs> { system = builtins.currentSystem; }'
nixpkgs_path=$(find /nix/store -mindepth 1 -maxdepth 1 -name *-nixpkgs-* -type d)
nix-env \
--arg config "{ nix.package = ($nixpkgs_expr).nix; }" \
--arg pkgs "$nixpkgs_expr" \
--arg modulesPath 'throw "no modulesPath"' \
-f $nixpkgs_path/nixpkgs/nixos/modules/installer/tools/tools.nix \
-iA config.system.build.nixos-install
if ! mountpoint "$target_path"; then
mount --rbind /mnt/"$target_path" "$target_path"
fi
mkdir -p bin
rm -f bin/nixos-install
cp "$(type -p nixos-install)" bin/nixos-install
sed -i "s@^NIX_PATH=\"[^\"]*\"@NIX_PATH=$target_path@" bin/nixos-install
if ! grep -q '^PATH.*#krebs' .bashrc; then
echo '. /root/.nix-profile/etc/profile.d/nix.sh' >> .bashrc
echo 'PATH=$HOME/bin:$PATH #krebs' >> .bashrc
fi
)}

View File

@ -1,11 +0,0 @@
{ lib, ... }:
with lib;
rec {
# listset k v = set k [v]
# insert : k -> v -> listset k v -> listset k v
insert = name: value: set:
set // { ${name} = set.${name} or [] ++ [value]; };
}

View File

@ -1,9 +1,14 @@
{ lib, ... }:
{ config, lib, ... }:
with builtins;
with lib;
with types;
let
# Inherited attributes are used in submodules that have their own `config`.
inherit (config.krebs) users;
in
types // rec {
host = submodule ({ config, ... }: {
@ -20,25 +25,17 @@ types // rec {
default = {};
};
owner = mkOption {
type = user;
default = users.krebs;
};
extraZones = mkOption {
default = {};
# TODO: string is either MX, NS, A or AAAA
type = with types; attrsOf string;
};
infest = {
addr = mkOption {
type = str;
apply = trace "Obsolete option `krebs.hosts.${config.name}.infest.addr' is used. It was replaced by the `target' argument to `make` or `get`. See Makefile for more information.";
};
port = mkOption {
type = int;
default = 22;
# TODO replacement: allow target with port, SSH-style: [lol]:666
apply = trace "Obsolete option `krebs.hosts.${config.name}.infest.port' is used. It's gone without replacement.";
};
};
secure = mkOption {
type = bool;
default = false;
@ -147,6 +144,25 @@ types // rec {
merge = mergeOneOption;
};
secret-file = submodule ({ config, ... }: {
options = {
path = mkOption { type = str; };
mode = mkOption { type = str; default = "0400"; };
owner = mkOption {
type = user;
default = config.krebs.users.root;
};
group-name = mkOption {
type = str;
default = "root";
};
source-path = mkOption {
type = str;
default = toString <secrets> + "/${config._module.args.name}";
};
};
});
suffixed-str = suffs:
mkOptionType {
name = "string suffixed by ${concatStringsSep ", " suffs}";
@ -156,6 +172,10 @@ types // rec {
user = submodule ({ config, ... }: {
options = {
home = mkOption {
type = absolute-pathname;
default = "/home/${config.name}";
};
mail = mkOption {
type = str; # TODO retiolum mail address
};
@ -164,7 +184,12 @@ types // rec {
default = config._module.args.name;
};
pubkey = mkOption {
type = str;
type = nullOr str;
default = null;
};
uid = mkOption {
type = int;
default = genid config.name;
};
};
});
@ -217,6 +242,21 @@ types // rec {
merge = mergeOneOption;
};
# POSIX.12013, 3.2 Absolute Pathname
# TODO normalize slashes
# TODO two slashes
absolute-pathname = mkOptionType {
name = "POSIX absolute pathname";
check = s: pathname.check s && substring 0 1 s == "/";
};
# POSIX.12013, 3.267 Pathname
# TODO normalize slashes
pathname = mkOptionType {
name = "POSIX pathname";
check = s: isString s && all filename.check (splitString "/" s);
};
# POSIX.1-2013, 3.431 User Name
username = mkOptionType {
name = "POSIX username";

View File

@ -1,12 +1,12 @@
{ stdenv, fetchgit, bc, cac-cert, coreutils, curl, dash, gnugrep, gnused, inotifyTools, jq, ncurses, openssh, sshpass, ... }:
stdenv.mkDerivation {
name = "cac-api-1.1.0";
name = "cac-api-1.1.2";
src = fetchgit {
url = http://cgit.cd.krebsco.de/cac-api;
rev = "0809fae379239687ed1170e04311dc2880ef0aba";
sha256 = "357ced27c9ed88028967c934178a1d230bf38617a7494cd4632fabdd2a04fcdd";
rev = "67e93510e7742acae44db30275abbfe671aa9b7b";
sha256 = "1vxh57j7vrq5sg9j1sam0538kkkhqpgf230vvdz2ifzgkj01z27l";
};
phases = [
@ -29,7 +29,7 @@ stdenv.mkDerivation {
ncurses
openssh
sshpass
]}
]}:"$PATH"
EOF
# [1]: Disable fetching tasks; listtasks is currently broken:
# Unknown column 'iod.apitask.cid' in 'field list'

View File

@ -1,20 +1,21 @@
{ fetchgit, lib, stdenv
, coreutils
, get
, git
, gnumake
, gnused
, jq
, nix
, openssh
, parallel
, ... }:
stdenv.mkDerivation {
name = "push-1.1.1";
name = "push-1.1.2";
src = fetchgit {
url = http://cgit.cd.krebsco.de/push;
rev = "ea8b76569c6b226fe148e559477669b095408472";
sha256 = "c305a1515d30603f6ed825d44487e863fdc7d90400620ceaf2c335a3b5d1e221";
rev = "da5b3a4b05ef822cc41d36b6cc2071a2e78506d4";
sha256 = "0gfxz207lm11g77rw02jcqpvzhx07j9hzgjgscbmslzl5r8icd6g";
};
phases = [
@ -26,10 +27,11 @@ stdenv.mkDerivation {
let
path = lib.makeSearchPath "bin" [
coreutils
get
git
gnumake
gnused
jq
nix
openssh
parallel
];

View File

@ -1,4 +1,4 @@
# nix-shell -p gnumake jq openssh cac-api cac-panel
# nix-shell -p gnumake jq openssh cac-api cac-panel sshpass
set -eufx
# 2 secrets are required:
@ -99,7 +99,7 @@ defer "cac-api delete $id;$old_trapstr"
mkdir -p shared/2configs/temp
cac-api generatenetworking $id > \
shared/2configs/temp/networking.nix
# new temporary ssh key we will use to log in after infest
# new temporary ssh key we will use to log in after install
ssh-keygen -f $krebs_ssh -N ""
cp $retiolum_key $krebs_secrets/retiolum.rsa_key.priv
# we override the directories for secrets and stockholm
@ -118,12 +118,12 @@ _: {
}
EOF
LOGNAME=shared make eval get=krebs.infest \
target=derp system=test-centos7 filter=json \
| sed -e "s#^ssh.*<<#cac-api ssh $id<<#" \
-e "/^rsync/a -e 'cac-api ssh $id' \\\\" \
-e "s#root.derp:#:#" > $krebs_secrets/infest
sh -x $krebs_secrets/infest
make install \
LOGNAME=shared \
SSHPASS="$(cac-api getserver $id | jq -r .rootpass)" \
ssh='sshpass -e ssh -S none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' \
system=test-centos7 \
target=$ip
# TODO: generate secrets directory $krebs_secrets for nix import
cac-api powerop $id reset

View File

@ -8,6 +8,7 @@ with builtins;
../2configs/browsers.nix
../2configs/programs.nix
../2configs/git.nix
../2configs/pass.nix
#{
# users.extraUsers = {
# root = {
@ -17,6 +18,15 @@ with builtins;
# };
# };
#}
{
krebs.iptables = {
tables = {
filter.INPUT.rules = [
{ predicate = "-p tcp --dport 8000"; target = "ACCEPT"; precedence = 9001; }
];
};
};
}
];
krebs.build.host = config.krebs.hosts.helios;
@ -53,15 +63,6 @@ with builtins;
# SUBSYSTEM=="net", ATTR{address}=="f0:de:f1:b8:c8:2e", NAME="et0"
#'';
services.xserver = {
videoDriver = "intel";
vaapiDrivers = [ pkgs.vaapiIntel ];
deviceSection = ''
Option "AccelMethod" "sna"
BusID "PCI:0:2:0"
'';
};
services.xserver.synaptics = {
enable = true;
twoFingerScroll = true;

View File

@ -20,12 +20,12 @@
../2configs/git.nix
#../2configs/wordpress.nix
../2configs/bitlbee.nix
../2configs/firefoxPatched.nix
#../2configs/firefoxPatched.nix
../2configs/skype.nix
../2configs/teamviewer.nix
../2configs/libvirt.nix
../2configs/fetchWallpaper.nix
../2configs/buildbot-standalone.nix
#../2configs/buildbot-standalone.nix
{
#risk of rain port
krebs.iptables.tables.filter.INPUT.rules = [
@ -97,6 +97,54 @@
# { predicate = "-i retiolum -p tcp --dport 80"; target = "ACCEPT"; precedence = 9998; }
# ];
#}
{
containers.pythonenv = {
config = {
services.openssh.enable = true;
users.users.root.openssh.authorizedKeys.keys = [
config.krebs.users.lass.pubkey
];
environment = {
systemPackages = with pkgs; [
git
libxml2
libxslt
libzip
python27Full
python27Packages.buildout
stdenv
zlib
];
pathsToLink = [ "/include" ];
shellInit = ''
# help pip to find libz.so when building lxml
export LIBRARY_PATH=/var/run/current-system/sw/lib
# ditto for header files, e.g. sqlite
export C_INCLUDE_PATH=/var/run/current-system/sw/include
'';
};
};
};
}
{
services.mysql = {
enable = true;
package = pkgs.mariadb;
rootPassword = "<secrets>/mysql_rootPassword";
};
}
{
services.elasticsearch = {
enable = true;
plugins = [
pkgs.elasticsearchPlugins.elasticsearch_kopf
];
};
}
];
krebs.build.host = config.krebs.hosts.mors;
@ -170,6 +218,11 @@
device = "/dev/big/public";
fsType = "ext4";
};
"/mnt/conf" = {
device = "/dev/big/conf";
fsType = "ext4";
};
};
services.udev.extraRules = ''

View File

@ -58,7 +58,7 @@ in {
( createChromiumUser "cr" [ "audio" ] [ pkgs.chromium ] )
( createChromiumUser "fb" [ ] [ pkgs.chromium ] )
( createChromiumUser "gm" [ ] [ pkgs.chromium ] )
( createChromiumUser "flash" [ ] [ pkgs.flash ] )
( createChromiumUser "flash" [ "audio" ] [ pkgs.flash ] )
];
nixpkgs.config.packageOverrides = pkgs : {

View File

@ -42,6 +42,8 @@ let
brain = {
collaborators = with config.krebs.users; [ tv makefu ];
};
extraction_webinterface = {};
politics-fetching = {};
} //
import <secrets/repos.nix> { inherit config lib pkgs; }
);

View File

@ -2,13 +2,14 @@
let
mainUser = config.users.extraUsers.mainUser;
inherit (config.krebs.lib) genid;
in {
virtualisation.libvirtd.enable = true;
users.extraUsers = {
libvirt = {
uid = lib.genid "libvirt";
uid = genid "libvirt";
description = "user for running libvirt stuff";
home = "/home/libvirt";
useDefaultShell = true;

View File

@ -2,12 +2,13 @@
let
mainUser = config.users.extraUsers.mainUser;
inherit (config.krebs.lib) genid;
in {
users.extraUsers = {
skype = {
name = "skype";
uid = lib.genid "skype";
uid = genid "skype";
description = "user for running skype";
home = "/home/skype";
useDefaultShell = true;

View File

@ -93,11 +93,9 @@ let
xmonad-start = pkgs.writeScriptBin "xmonad" ''
#! ${pkgs.bash}/bin/bash
set -efu
export PATH; PATH=${makeSearchPath "bin" [
pkgs.alsaUtils
pkgs.pulseaudioLight
export PATH; PATH=${makeSearchPath "bin" ([
pkgs.rxvt_unicode
]}:/var/setuid-wrappers
] ++ config.environment.systemPackages)}:/var/setuid-wrappers
settle() {(
# Use PATH for a clean journal
command=''${1##*/}

View File

@ -1,16 +1,13 @@
{ pkgs, ... }:
let
inherit (pkgs) callPackage;
in
{
nixpkgs.config.packageOverrides = rec {
firefoxPlugins = {
noscript = callPackage ./firefoxPlugins/noscript.nix {};
ublock = callPackage ./firefoxPlugins/ublock.nix {};
vimperator = callPackage ./firefoxPlugins/vimperator.nix {};
noscript = pkgs.callPackage ./firefoxPlugins/noscript.nix {};
ublock = pkgs.callPackage ./firefoxPlugins/ublock.nix {};
vimperator = pkgs.callPackage ./firefoxPlugins/vimperator.nix {};
};
newsbot-js = callPackage ./newsbot-js/default.nix {};
newsbot-js = pkgs.callPackage ./newsbot-js/default.nix {};
xmonad-lass =
let src = pkgs.writeNixFromCabal "xmonad-lass.nix" ./xmonad-lass; in
pkgs.haskellPackages.callPackage src {};

View File

@ -12,7 +12,6 @@ import XMonad
import System.IO (hPutStrLn, stderr)
import System.Environment (getArgs, withArgs, getEnv, getEnvironment)
import System.Posix.Process (executeFile)
import XMonad.Prompt (defaultXPConfig)
import XMonad.Actions.DynamicWorkspaces ( addWorkspacePrompt, renameWorkspace
, removeEmptyWorkspace)
import XMonad.Actions.GridSelect
@ -73,7 +72,7 @@ mainNoArgs = do
-- $ withUrgencyHook borderUrgencyHook "magenta"
-- $ withUrgencyHookC BorderUrgencyHook { urgencyBorderColor = "magenta" } urgencyConfig { suppressWhen = Never }
$ withUrgencyHook (SpawnUrgencyHook "echo emit Urgency ")
$ defaultConfig
$ def
{ terminal = myTerm
, modMask = mod4Mask
, workspaces = workspaces0
@ -169,7 +168,7 @@ myWSConfig = myGSConfig
}
pagerConfig :: PagerConfig
pagerConfig = defaultPagerConfig
pagerConfig = def
{ pc_font = myFont
, pc_cellwidth = 64
--, pc_cellheight = 36 -- TODO automatically keep screen aspect
@ -182,13 +181,13 @@ pagerConfig = defaultPagerConfig
where
windowColors _ _ _ True _ = ("#ef4242","#ff2323")
windowColors wsf m c u wf = do
let def = defaultWindowColors wsf m c u wf
let y = defaultWindowColors wsf m c u wf
if m == False && wf == True
then ("#402020", snd def)
else def
then ("#402020", snd y)
else y
wGSConfig :: GSConfig Window
wGSConfig = defaultGSConfig
wGSConfig = def
{ gs_cellheight = 20
, gs_cellwidth = 192
, gs_cellpadding = 5

View File

@ -3,5 +3,6 @@ _:
imports = [
../krebs
./3modules
./5pkgs
];
}

View File

@ -19,9 +19,13 @@ in {
username = "lol";
password = "wut";
};
exim-retiolum.enable = true;
exim-retiolum = {
enable = true;
primary_hostname = "test.r";
};
exim-smarthost = {
enable = true;
primary_hostname = "test.r";
system-aliases = [ { from = "dick"; to = "butt"; } ];
};
go.enable = true;

View File

@ -14,11 +14,14 @@ with config.krebs.lib;
../2configs/retiolum.nix
../2configs/urlwatch.nix
{
imports = [ ../2configs/charybdis.nix ];
tv.charybdis = {
enable = true;
sslCert = ../Zcerts/charybdis_cd.crt.pem;
ssl_cert = ../Zcerts/charybdis_cd.crt.pem;
};
tv.iptables.input-retiolum-accept-new-tcp = [
config.tv.charybdis.port
config.tv.charybdis.sslport
];
}
{
tv.ejabberd = {

View File

@ -10,6 +10,8 @@ with config.krebs.lib;
../2configs/hw/AO753.nix
../2configs/exim-retiolum.nix
../2configs/git.nix
../2configs/im.nix
../2configs/mail-client.nix
../2configs/nginx-public_html.nix
../2configs/pulse.nix
../2configs/retiolum.nix

View File

@ -10,7 +10,9 @@ with config.krebs.lib;
../2configs/hw/w110er.nix
../2configs/exim-retiolum.nix
../2configs/git.nix
../2configs/im.nix
../2configs/mail-client.nix
../2configs/man.nix
../2configs/nginx-public_html.nix
../2configs/pulse.nix
../2configs/retiolum.nix
@ -23,19 +25,6 @@ with config.krebs.lib;
hashPassword
haskellPackages.lentil
parallel
(pkgs.writeScriptBin "im" ''
#! ${pkgs.bash}/bin/bash
export PATH=${makeSearchPath "bin" (with pkgs; [
tmux
gnugrep
weechat
])}
if tmux list-sessions -F\#S | grep -q '^im''$'; then
exec tmux attach -t im
else
exec tmux new -s im weechat
fi
'')
# root
cryptsetup
@ -52,14 +41,12 @@ with config.krebs.lib;
haskellPackages.hledger
htop
jq
manpages
mkpasswd
netcat
nix-repl
nmap
nq
p7zip
posix_man_pages
push
qrencode
texLive
@ -165,11 +152,7 @@ with config.krebs.lib;
hardware.opengl.driSupport32Bit = true;
environment.systemPackages = with pkgs; [
xlibs.fontschumachermisc
slock
ethtool
#firefoxWrapper # with plugins
#chromiumDevWrapper
tinc
iptables
#jack2
@ -177,7 +160,6 @@ with config.krebs.lib;
security.setuidPrograms = [
"sendmail" # for cron
"slock"
];
services.printing.enable = true;
@ -201,12 +183,6 @@ with config.krebs.lib;
KERNEL=="hpet", GROUP="audio"
'';
services.bitlbee = {
enable = true;
plugins = [
pkgs.bitlbee-facebook
];
};
services.tor.client.enable = true;
services.tor.enable = true;
services.virtualboxHost.enable = true;

View File

@ -11,6 +11,7 @@ with config.krebs.lib;
../2configs/exim-retiolum.nix
../2configs/git.nix
../2configs/mail-client.nix
../2configs/man.nix
../2configs/nginx-public_html.nix
../2configs/pulse.nix
../2configs/retiolum.nix
@ -52,7 +53,6 @@ with config.krebs.lib;
haskellPackages.hledger
htop
jq
manpages
mkpasswd
netcat
nix-repl
@ -60,7 +60,6 @@ with config.krebs.lib;
nq
p7zip
pass
posix_man_pages
qrencode
texLive
tmux
@ -163,11 +162,7 @@ with config.krebs.lib;
#hardware.opengl.driSupport32Bit = true;
environment.systemPackages = with pkgs; [
#xlibs.fontschumachermisc
#slock
ethtool
#firefoxWrapper # with plugins
#chromiumDevWrapper
tinc
iptables
#jack2

View File

@ -2,29 +2,43 @@
with config.krebs.lib;
{
krebs.backup.plans = {
} // mapAttrs (_: recursiveUpdate {
snapshots = {
daily = { format = "%Y-%m-%d"; retain = 7; };
weekly = { format = "%YW%W"; retain = 4; };
monthly = { format = "%Y-%m"; retain = 12; };
yearly = { format = "%Y"; };
};
}) {
nomic-home-xu = {
method = "push";
src = { host = config.krebs.hosts.nomic; path = "/home"; };
dst = { host = config.krebs.hosts.xu; path = "/bku/nomic-home"; };
startAt = "05:00";
};
wu-home-xu = {
method = "push";
src = { host = config.krebs.hosts.wu; path = "/home"; };
dst = { host = config.krebs.hosts.xu; path = "/bku/wu-home"; };
startAt = "05:00";
snapshots = {
daily = { format = "%Y-%m-%d"; retain = 7; };
weekly = { format = "%YW%W"; retain = 4; };
monthly = { format = "%Y-%m"; retain = 12; };
yearly = { format = "%Y"; };
};
};
xu-home-wu = {
method = "push";
src = { host = config.krebs.hosts.xu; path = "/home"; };
dst = { host = config.krebs.hosts.wu; path = "/bku/xu-home"; };
startAt = "06:00";
snapshots = {
daily = { format = "%Y-%m-%d"; retain = 7; };
weekly = { format = "%YW%W"; retain = 4; };
monthly = { format = "%Y-%m"; retain = 12; };
yearly = { format = "%Y"; };
};
};
xu-pull-cd-ejabberd = {
method = "pull";
src = { host = config.krebs.hosts.cd; path = "/var/ejabberd"; };
dst = { host = config.krebs.hosts.xu; path = "/bku/cd-ejabberd"; };
startAt = "07:00";
};
xu-pull-cd-home = {
method = "pull";
src = { host = config.krebs.hosts.cd; path = "/home"; };
dst = { host = config.krebs.hosts.xu; path = "/bku/cd-home"; };
startAt = "07:00";
};
} // mapAttrs (_: recursiveUpdate {
snapshots = {

View File

@ -1,601 +0,0 @@
{ config, lib, pkgs, ... }:
with config.krebs.lib;
let
cfg = config.tv.charybdis;
out = {
options.tv.charybdis = api;
config = lib.mkIf cfg.enable (lib.mkMerge [
imp
{ tv.iptables.input-retiolum-accept-new-tcp = [ 6667 6697 ]; }
]);
};
api = {
enable = mkEnableOption "tv.charybdis";
dataDir = mkOption {
type = types.str;
default = "/var/lib/charybdis";
};
dhParams = mkOption {
type = types.str;
default = toString <secrets/charybdis.dh.pem>;
};
motd = mkOption {
type = types.str;
default = "/join #retiolum";
};
sslCert = mkOption {
type = types.path;
};
sslKey = mkOption {
type = types.str;
default = toString <secrets/charybdis.key.pem>;
};
};
imp = {
systemd.services.charybdis = {
wantedBy = [ "multi-user.target" ];
environment = {
BANDB_DBPATH = "${cfg.dataDir}/ban.db";
};
serviceConfig = {
PermissionsStartOnly = "true";
SyslogIdentifier = "charybdis";
User = user.name;
PrivateTmp = "true";
Restart = "always";
ExecStartPre = pkgs.writeScript "charybdis-init" ''
#! /bin/sh
mkdir -p ${cfg.dataDir}
chown ${user.name}: ${cfg.dataDir}
install -o ${user.name} -m 0400 ${cfg.sslKey} /tmp/ssl.key
install -o ${user.name} -m 0400 ${cfg.dhParams} /tmp/dh.pem
echo ${escapeShellArg cfg.motd} > /tmp/ircd.motd
'';
ExecStart = pkgs.writeScript "charybdis-service" ''
#! /bin/sh
set -euf
exec ${pkgs.charybdis}/bin/charybdis-ircd \
-foreground \
-logfile /dev/stderr \
-configfile ${configFile}
'';
};
};
users.extraUsers = singleton {
inherit (user) name uid;
};
};
user = rec {
name = "charybdis";
uid = genid name;
};
configFile = toFile "charybdis-ircd.conf" ''
/* doc/example.conf - brief example configuration file
*
* Copyright (C) 2000-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
* Copyright (C) 2005-2006 charybdis development team
*
* $Id: example.conf 3582 2007-11-17 21:55:48Z jilles $
*
* See reference.conf for more information.
*/
/* Extensions */
#loadmodule "extensions/chm_operonly_compat.so";
#loadmodule "extensions/chm_quietunreg_compat.so";
#loadmodule "extensions/chm_sslonly_compat.so";
#loadmodule "extensions/createauthonly.so";
#loadmodule "extensions/extb_account.so";
#loadmodule "extensions/extb_canjoin.so";
#loadmodule "extensions/extb_channel.so";
#loadmodule "extensions/extb_extgecos.so";
#loadmodule "extensions/extb_oper.so";
#loadmodule "extensions/extb_realname.so";
#loadmodule "extensions/extb_server.so";
#loadmodule "extensions/extb_ssl.so";
#loadmodule "extensions/hurt.so";
#loadmodule "extensions/m_findforwards.so";
#loadmodule "extensions/m_identify.so";
#loadmodule "extensions/no_oper_invis.so";
#loadmodule "extensions/sno_farconnect.so";
#loadmodule "extensions/sno_globalkline.so";
#loadmodule "extensions/sno_globaloper.so";
#loadmodule "extensions/sno_whois.so";
loadmodule "extensions/override.so";
/*
* IP cloaking extensions: use ip_cloaking_4.0
* if you're linking 3.2 and later, otherwise use
* ip_cloaking.so, for compatibility with older 3.x
* releases.
*/
#loadmodule "extensions/ip_cloaking_4.0.so";
#loadmodule "extensions/ip_cloaking.so";
serverinfo {
name = ${toJSON (head config.krebs.build.host.nets.retiolum.aliases)};
sid = "4z3";
description = "miep!";
network_name = "irc.retiolum";
#network_desc = "Retiolum IRC Network";
hub = yes;
/* On multi-homed hosts you may need the following. These define
* the addresses we connect from to other servers. */
/* for IPv4 */
vhost = ${concatMapStringsSep ", " toJSON config.krebs.build.host.nets.retiolum.addrs4};
/* for IPv6 */
vhost6 = ${concatMapStringsSep ", " toJSON config.krebs.build.host.nets.retiolum.addrs6};
/* ssl_private_key: our ssl private key */
ssl_private_key = "/tmp/ssl.key";
/* ssl_cert: certificate for our ssl server */
ssl_cert = ${toJSON cfg.sslCert};
/* ssl_dh_params: DH parameters, generate with openssl dhparam -out dh.pem 1024 */
ssl_dh_params = "/tmp/dh.pem";
/* ssld_count: number of ssld processes you want to start, if you
* have a really busy server, using N-1 where N is the number of
* cpu/cpu cores you have might be useful. A number greater than one
* can also be useful in case of bugs in ssld and because ssld needs
* two file descriptors per SSL connection.
*/
ssld_count = 1;
/* default max clients: the default maximum number of clients
* allowed to connect. This can be changed once ircd has started by
* issuing:
* /quote set maxclients <limit>
*/
default_max_clients = 1024;
/* nicklen: enforced nickname length (for this server only; must not
* be longer than the maximum length set while building).
*/
nicklen = 30;
};
admin {
name = "tv";
description = "peer";
mail = "${config.krebs.users.tv.mail}";
};
log {
fname_userlog = "/dev/stderr";
fname_fuserlog = "/dev/stderr";
fname_operlog = "/dev/stderr";
fname_foperlog = "/dev/stderr";
fname_serverlog = "/dev/stderr";
fname_klinelog = "/dev/stderr";
fname_killlog = "/dev/stderr";
fname_operspylog = "/dev/stderr";
fname_ioerrorlog = "/dev/stderr";
};
/* class {} blocks MUST be specified before anything that uses them. That
* means they must be defined before auth {} and before connect {}.
*/
class "krebs" {
ping_time = 2 minutes;
number_per_ident = 10;
number_per_ip = 2048;
number_per_ip_global = 4096;
cidr_ipv4_bitlen = 24;
cidr_ipv6_bitlen = 64;
number_per_cidr = 65536;
max_number = 3000;
sendq = 1 megabyte;
};
class "users" {
ping_time = 2 minutes;
number_per_ident = 10;
number_per_ip = 1024;
number_per_ip_global = 4096;
cidr_ipv4_bitlen = 24;
cidr_ipv6_bitlen = 64;
number_per_cidr = 65536;
max_number = 3000;
sendq = 400 kbytes;
};
class "opers" {
ping_time = 5 minutes;
number_per_ip = 10;
max_number = 1000;
sendq = 1 megabyte;
};
class "server" {
ping_time = 5 minutes;
connectfreq = 5 minutes;
max_number = 1;
sendq = 4 megabytes;
};
listen {
/* defer_accept: wait for clients to send IRC handshake data before
* accepting them. if you intend to use software which depends on the
* server replying first, such as BOPM, you should disable this feature.
* otherwise, you probably want to leave it on.
*/
defer_accept = yes;
/* If you want to listen on a specific IP only, specify host.
* host definitions apply only to the following port line.
*/
# XXX This is stupid because only one host is allowed[?]
#host = ''${concatMapStringsSep ", " toJSON (
# config.krebs.build.host.nets.retiolum.addrs
#)};
port = 6667;
sslport = 6697;
};
/* auth {}: allow users to connect to the ircd (OLD I:)
* auth {} blocks MUST be specified in order of precedence. The first one
* that matches a user will be used. So place spoofs first, then specials,
* then general access, then restricted.
*/
auth {
/* user: the user@host allowed to connect. Multiple IPv4/IPv6 user
* lines are permitted per auth block. This is matched against the
* hostname and IP address (using :: shortening for IPv6 and
* prepending a 0 if it starts with a colon) and can also use CIDR
* masks.
*/
user = "*@10.243.0.0/12";
user = "*@42::/16";
/* password: an optional password that is required to use this block.
* By default this is not encrypted, specify the flag "encrypted" in
* flags = ...; below if it is.
*/
#password = "letmein";
/* spoof: fake the users user@host to be be this. You may either
* specify a host or a user@host to spoof to. This is free-form,
* just do everyone a favour and dont abuse it. (OLD I: = flag)
*/
#spoof = "I.still.hate.packets";
/* Possible flags in auth:
*
* encrypted | password is encrypted with mkpasswd
* spoof_notice | give a notice when spoofing hosts
* exceed_limit (old > flag) | allow user to exceed class user limits
* kline_exempt (old ^ flag) | exempt this user from k/g/xlines&dnsbls
* dnsbl_exempt | exempt this user from dnsbls
* spambot_exempt | exempt this user from spambot checks
* shide_exempt | exempt this user from serverhiding
* jupe_exempt | exempt this user from generating
* warnings joining juped channels
* resv_exempt | exempt this user from resvs
* flood_exempt | exempt this user from flood limits
* USE WITH CAUTION.
* no_tilde (old - flag) | don't prefix ~ to username if no ident
* need_ident (old + flag) | require ident for user in this class
* need_ssl | require SSL/TLS for user in this class
* need_sasl | require SASL id for user in this class
*/
flags = kline_exempt, exceed_limit, flood_exempt;
/* class: the class the user is placed in */
class = "krebs";
};
auth {
user = "*@*";
class = "users";
};
/* privset {} blocks MUST be specified before anything that uses them. That
* means they must be defined before operator {}.
*/
privset "local_op" {
privs = oper:local_kill, oper:operwall;
};
privset "server_bot" {
extends = "local_op";
privs = oper:kline, oper:remoteban, snomask:nick_changes;
};
privset "global_op" {
extends = "local_op";
privs = oper:global_kill, oper:routing, oper:kline, oper:unkline, oper:xline,
oper:resv, oper:mass_notice, oper:remoteban;
};
privset "admin" {
extends = "global_op";
privs = oper:admin, oper:die, oper:rehash, oper:spy, oper:override;
};
privset "aids" {
privs = oper:override, oper:rehash;
};
operator "aids" {
user = "*@10.243.*";
privset = "aids";
flags = ~encrypted;
password = "balls";
};
operator "god" {
/* name: the name of the oper must go above */
/* user: the user@host required for this operator. CIDR *is*
* supported now. auth{} spoofs work here, other spoofs do not.
* multiple user="" lines are supported.
*/
user = "*god@127.0.0.1";
/* password: the password required to oper. Unless ~encrypted is
* contained in flags = ...; this will need to be encrypted using
* mkpasswd, MD5 is supported
*/
password = "5";
/* rsa key: the public key for this oper when using Challenge.
* A password should not be defined when this is used, see
* doc/challenge.txt for more information.
*/
#rsa_public_key_file = "/usr/local/ircd/etc/oper.pub";
/* umodes: the specific umodes this oper gets when they oper.
* If this is specified an oper will not be given oper_umodes
* These are described above oper_only_umodes in general {};
*/
#umodes = locops, servnotice, operwall, wallop;
/* fingerprint: if specified, the oper's client certificate
* fingerprint will be checked against the specified fingerprint
* below.
*/
#fingerprint = "c77106576abf7f9f90cca0f63874a60f2e40a64b";
/* snomask: specific server notice mask on oper up.
* If this is specified an oper will not be given oper_snomask.
*/
snomask = "+Zbfkrsuy";
/* flags: misc options for the operator. You may prefix an option
* with ~ to disable it, e.g. ~encrypted.
*
* Default flags are encrypted.
*
* Available options:
*
* encrypted: the password above is encrypted [DEFAULT]
* need_ssl: must be using SSL/TLS to oper up
*/
flags = encrypted;
/* privset: privileges set to grant */
privset = "admin";
};
service {
name = "services.int";
};
cluster {
name = "*";
flags = kline, tkline, unkline, xline, txline, unxline, resv, tresv, unresv;
};
shared {
oper = "*@*", "*";
flags = all, rehash;
};
/* exempt {}: IPs that are exempt from Dlines and rejectcache. (OLD d:) */
exempt {
ip = "127.0.0.1";
};
channel {
use_invex = yes;
use_except = yes;
use_forward = yes;
use_knock = yes;
knock_delay = 5 minutes;
knock_delay_channel = 1 minute;
max_chans_per_user = 15;
max_bans = 100;
max_bans_large = 500;
default_split_user_count = 0;
default_split_server_count = 0;
no_create_on_split = no;
no_join_on_split = no;
burst_topicwho = yes;
kick_on_split_riding = no;
only_ascii_channels = no;
resv_forcepart = yes;
channel_target_change = yes;
disable_local_channels = no;
};
serverhide {
flatten_links = yes;
links_delay = 5 minutes;
hidden = no;
disable_hidden = no;
};
/* These are the blacklist settings.
* You can have multiple combinations of host and rejection reasons.
* They are used in pairs of one host/rejection reason.
*
* These settings should be adequate for most networks, and are (presently)
* required for use on StaticBox.
*
* Word to the wise: Do not use blacklists like SPEWS for blocking IRC
* connections.
*
* As of charybdis 2.2, you can do some keyword substitution on the rejection
* reason. The available keyword substitutions are:
*
* ''${ip} - the user's IP
* ''${host} - the user's canonical hostname
* ''${dnsbl-host} - the dnsbl hostname the lookup was done against
* ''${nick} - the user's nickname
* ''${network-name} - the name of the network
*
* As of charybdis 3.4, a type parameter is supported, which specifies the
* address families the blacklist supports. IPv4 and IPv6 are supported.
* IPv4 is currently the default as few blacklists support IPv6 operation
* as of this writing.
*
* Note: AHBL (the providers of the below *.ahbl.org BLs) request that they be
* contacted, via email, at admins@2mbit.com before using these BLs.
* See <http://www.ahbl.org/services.php> for more information.
*/
blacklist {
host = "rbl.efnetrbl.org";
type = ipv4;
reject_reason = "''${nick}, your IP (''${ip}) is listed in EFnet's RBL. For assistance, see http://efnetrbl.org/?i=''${ip}";
# host = "ircbl.ahbl.org";
# type = ipv4;
# reject_reason = "''${nick}, your IP (''${ip}) is listed in ''${dnsbl-host} for having an open proxy. In order to protect ''${network-name} from abuse, we are not allowing connections with open proxies to connect.";
#
# host = "tor.ahbl.org";
# type = ipv4;
# reject_reason = "''${nick}, your IP (''${ip}) is listed as a TOR exit node. In order to protect ''${network-name} from tor-based abuse, we are not allowing TOR exit nodes to connect to our network.";
#
/* Example of a blacklist that supports both IPv4 and IPv6 */
# host = "foobl.blacklist.invalid";
# type = ipv4, ipv6;
# reject_reason = "''${nick}, your IP (''${ip}) is listed in ''${dnsbl-host} for some reason. In order to protect ''${network-name} from abuse, we are not allowing connections listed in ''${dnsbl-host} to connect";
};
alias "NickServ" {
target = "NickServ";
};
alias "ChanServ" {
target = "ChanServ";
};
alias "OperServ" {
target = "OperServ";
};
alias "MemoServ" {
target = "MemoServ";
};
alias "NS" {
target = "NickServ";
};
alias "CS" {
target = "ChanServ";
};
alias "OS" {
target = "OperServ";
};
alias "MS" {
target = "MemoServ";
};
general {
hide_error_messages = opers;
hide_spoof_ips = yes;
/*
* default_umodes: umodes to enable on connect.
* If you have enabled the new ip_cloaking_4.0 module, and you want
* to make use of it, add +x to this option, i.e.:
* default_umodes = "+ix";
*
* If you have enabled the old ip_cloaking module, and you want
* to make use of it, add +h to this option, i.e.:
* default_umodes = "+ih";
*/
default_umodes = "+i";
default_operstring = "is an IRC Operator";
default_adminstring = "is a Server Administrator";
servicestring = "is a Network Service";
disable_fake_channels = no;
tkline_expire_notices = no;
default_floodcount = 1000;
failed_oper_notice = yes;
dots_in_ident=2;
min_nonwildcard = 4;
min_nonwildcard_simple = 3;
max_accept = 100;
max_monitor = 100;
anti_nick_flood = yes;
max_nick_time = 20 seconds;
max_nick_changes = 5;
anti_spam_exit_message_time = 5 minutes;
ts_warn_delta = 30 seconds;
ts_max_delta = 5 minutes;
client_exit = yes;
collision_fnc = yes;
resv_fnc = yes;
global_snotices = yes;
dline_with_reason = yes;
kline_delay = 0 seconds;
kline_with_reason = yes;
kline_reason = "K-Lined";
identify_service = "NickServ@services.int";
identify_command = "IDENTIFY";
non_redundant_klines = yes;
warn_no_nline = yes;
use_propagated_bans = yes;
stats_e_disabled = no;
stats_c_oper_only=no;
stats_h_oper_only=no;
client_flood_max_lines = 16000;
client_flood_burst_rate = 32000;
client_flood_burst_max = 32000;
client_flood_message_num = 32000;
client_flood_message_time = 32000;
use_whois_actually = no;
oper_only_umodes = operwall, locops, servnotice;
oper_umodes = locops, servnotice, operwall, wallop;
oper_snomask = "+s";
burst_away = yes;
nick_delay = 0 seconds; # 15 minutes if you want to enable this
reject_ban_time = 1 minute;
reject_after_count = 3;
reject_duration = 5 minutes;
throttle_duration = 60;
throttle_count = 4;
max_ratelimit_tokens = 30;
away_interval = 30;
disable_auth = yes;
};
modules {
path = "modules";
path = "modules/autoload";
};
exempt {
ip = "10.243.0.0/16";
};
'';
in
out

View File

@ -40,8 +40,8 @@ with config.krebs.lib;
mutableUsers = false;
users = {
tv = {
inherit (config.krebs.users.tv) home uid;
isNormalUser = true;
uid = 1337;
extraGroups = [ "tv" ];
};
};
@ -50,6 +50,7 @@ with config.krebs.lib;
{
security.sudo.extraConfig = ''
Defaults mailto="${config.krebs.users.tv.mail}"
Defaults !lecture
'';
time.timeZone = "Europe/Berlin";
}
@ -123,7 +124,7 @@ with config.krebs.lib;
0)
PS1='\[\e[1;31m\]\w\[\e[0m\] '
;;
1337)
${toString config.krebs.users.tv.uid})
PS1='\[\e[1;32m\]\w\[\e[0m\] '
;;
*)

View File

@ -5,19 +5,23 @@ with config.krebs.lib;
{
krebs.exim-smarthost = {
enable = true;
primary_hostname = "${config.networking.hostName}.retiolum";
sender_domains = [
"krebsco.de"
"shackspace.de"
"viljetic.de"
];
relay_from_hosts = [
"10.243.13.37"
relay_from_hosts = concatMap (host: host.nets.retiolum.addrs4) [
config.krebs.hosts.nomic
config.krebs.hosts.wu
config.krebs.hosts.xu
];
internet-aliases = with config.krebs.users; [
{ from = "postmaster@viljetic.de"; to = tv.mail; } # RFC 822
{ from = "mirko@viljetic.de"; to = mv.mail; }
{ from = "tomislav@viljetic.de"; to = tv.mail; }
{ from = "tv@destroy.dyn.shackspace.de"; to = tv.mail; }
{ from = "tv@viljetic.de"; to = tv.mail; }
{ from = "tv@shackspace.de"; to = tv.mail; }
];
system-aliases = [
{ from = "mailer-daemon"; to = "postmaster"; }

24
tv/2configs/im.nix Normal file
View File

@ -0,0 +1,24 @@
{ config, lib, pkgs, ... }:
with config.krebs.lib;
{
environment.systemPackages = with pkgs; [
(pkgs.writeDashBin "im" ''
export PATH=${makeSearchPath "bin" (with pkgs; [
tmux
gnugrep
weechat
])}
if tmux list-sessions -F\#S | grep -q '^im''$'; then
exec tmux attach -t im
else
exec tmux new -s im weechat
fi
'')
];
services.bitlbee = {
enable = true;
plugins = [
pkgs.bitlbee-facebook
];
};
}

12
tv/2configs/man.nix Normal file
View File

@ -0,0 +1,12 @@
{ config, lib, pkgs, ... }:
{
environment.etc."man.conf".source = pkgs.runCommand "man.conf" {} ''
${pkgs.gnused}/bin/sed <${pkgs.man}/lib/man.conf >$out '
s:^NROFF\t.*:& -Wbreak:
'
'';
environment.systemPackages = with pkgs; [
manpages
posix_man_pages
];
}

View File

@ -1,5 +1,5 @@
{ config, ... }:
{ config, pkgs, ... }:
with config.krebs.lib;
{
krebs.urlwatch = {
enable = true;
@ -52,8 +52,43 @@
# is derived from `configFile` in:
https://raw.githubusercontent.com/NixOS/nixpkgs/master/nixos/modules/services/x11/xserver.nix
https://pypi.python.org/pypi/vncdotool
{
url = https://pypi.python.org/pypi/vncdotool/json;
filter = "system:${pkgs.jq}/bin/jq -r '.releases|keys[]'";
}
https://api.github.com/repos/kanaka/noVNC/tags
];
hooksFile = toFile "hooks.py" ''
import subprocess
import urlwatch
class CaseFilter(urlwatch.filters.FilterBase):
"""Filter for piping data through an external process"""
__kind__ = 'system'
def filter(self, data, subfilter=None):
if subfilter is None:
raise ValueError('The system filter needs a command')
proc = subprocess.Popen(
subfilter,
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
(stdout, stderr) = proc.communicate(data.encode())
if proc.returncode != 0:
raise RuntimeError(
"system filter returned non-zero exit status %d; stderr:\n"
% proc.returncode
+ stderr.decode()
)
return stdout.decode()
'';
};
}

View File

@ -15,18 +15,26 @@ in
#
# make [install] system=xu-qemu0 target_host=10.56.0.101
# TODO iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# TODO iptables -A FORWARD -i qemubr0 -s 10.56.0.1/24 -m conntrack --ctstate NEW -j ACCEPT
# TODO iptables -A POSTROUTING -t nat -j MASQUERADE
# TODO iptables -A INPUT -i qemubr0 -p udp -m udp --dport bootps -j ACCEPT
# TODO iptables -A INPUT -i qemubr0 -p udp -m udp --dport domain -j ACCEPT
with config.krebs.lib;
{
networking.dhcpcd.denyInterfaces = [ "qemubr0" ];
tv.iptables.extra = {
nat.POSTROUTING = ["-j MASQUERADE"];
filter.FORWARD = [
"-m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT"
"-i qemubr0 -s 10.56.0.1/24 -m conntrack --ctstate NEW -j ACCEPT"
];
filter.INPUT = [
"-i qemubr0 -p udp -m udp --dport bootps -j ACCEPT"
"-i qemubr0 -p udp -m udp --dport domain -j ACCEPT"
];
};
systemd.network.enable = true;
systemd.services.systemd-networkd-wait-online.enable = false;
services.resolved.enable = mkForce false;
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;

View File

@ -0,0 +1,522 @@
{ config, ... }: with config.krebs.lib; let
cfg = config.tv.charybdis;
in toFile "charybdis.conf" ''
/* doc/example.conf - brief example configuration file
*
* Copyright (C) 2000-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
* Copyright (C) 2005-2006 charybdis development team
*
* $Id: example.conf 3582 2007-11-17 21:55:48Z jilles $
*
* See reference.conf for more information.
*/
/* Extensions */
#loadmodule "extensions/chm_operonly_compat.so";
#loadmodule "extensions/chm_quietunreg_compat.so";
#loadmodule "extensions/chm_sslonly_compat.so";
#loadmodule "extensions/createauthonly.so";
#loadmodule "extensions/extb_account.so";
#loadmodule "extensions/extb_canjoin.so";
#loadmodule "extensions/extb_channel.so";
#loadmodule "extensions/extb_extgecos.so";
#loadmodule "extensions/extb_oper.so";
#loadmodule "extensions/extb_realname.so";
#loadmodule "extensions/extb_server.so";
#loadmodule "extensions/extb_ssl.so";
#loadmodule "extensions/hurt.so";
#loadmodule "extensions/m_findforwards.so";
#loadmodule "extensions/m_identify.so";
#loadmodule "extensions/no_oper_invis.so";
#loadmodule "extensions/sno_farconnect.so";
#loadmodule "extensions/sno_globalkline.so";
#loadmodule "extensions/sno_globaloper.so";
#loadmodule "extensions/sno_whois.so";
loadmodule "extensions/override.so";
/*
* IP cloaking extensions: use ip_cloaking_4.0
* if you're linking 3.2 and later, otherwise use
* ip_cloaking.so, for compatibility with older 3.x
* releases.
*/
#loadmodule "extensions/ip_cloaking_4.0.so";
#loadmodule "extensions/ip_cloaking.so";
serverinfo {
name = ${toJSON (head config.krebs.build.host.nets.retiolum.aliases)};
sid = "4z3";
description = "miep!";
network_name = "irc.retiolum";
#network_desc = "Retiolum IRC Network";
hub = yes;
/* On multi-homed hosts you may need the following. These define
* the addresses we connect from to other servers. */
/* for IPv4 */
vhost = ${concatMapStringsSep ", " toJSON config.krebs.build.host.nets.retiolum.addrs4};
/* for IPv6 */
vhost6 = ${concatMapStringsSep ", " toJSON config.krebs.build.host.nets.retiolum.addrs6};
/* ssl_private_key: our ssl private key */
ssl_private_key = ${toJSON cfg.ssl_private_key.path};
/* ssl_cert: certificate for our ssl server */
ssl_cert = ${toJSON cfg.ssl_cert};
/* ssl_dh_params: DH parameters, generate with openssl dhparam -out dh.pem 1024 */
ssl_dh_params = ${toJSON cfg.ssl_dh_params.path};
/* ssld_count: number of ssld processes you want to start, if you
* have a really busy server, using N-1 where N is the number of
* cpu/cpu cores you have might be useful. A number greater than one
* can also be useful in case of bugs in ssld and because ssld needs
* two file descriptors per SSL connection.
*/
ssld_count = 1;
/* default max clients: the default maximum number of clients
* allowed to connect. This can be changed once ircd has started by
* issuing:
* /quote set maxclients <limit>
*/
default_max_clients = 1024;
/* nicklen: enforced nickname length (for this server only; must not
* be longer than the maximum length set while building).
*/
nicklen = 30;
};
admin {
name = "tv";
description = "peer";
};
log {
fname_userlog = "/dev/stderr";
fname_fuserlog = "/dev/stderr";
fname_operlog = "/dev/stderr";
fname_foperlog = "/dev/stderr";
fname_serverlog = "/dev/stderr";
fname_klinelog = "/dev/stderr";
fname_killlog = "/dev/stderr";
fname_operspylog = "/dev/stderr";
fname_ioerrorlog = "/dev/stderr";
};
/* class {} blocks MUST be specified before anything that uses them. That
* means they must be defined before auth {} and before connect {}.
*/
class "krebs" {
ping_time = 2 minutes;
number_per_ident = 10;
number_per_ip = 2048;
number_per_ip_global = 4096;
cidr_ipv4_bitlen = 24;
cidr_ipv6_bitlen = 64;
number_per_cidr = 65536;
max_number = 3000;
sendq = 1 megabyte;
};
class "users" {
ping_time = 2 minutes;
number_per_ident = 10;
number_per_ip = 1024;
number_per_ip_global = 4096;
cidr_ipv4_bitlen = 24;
cidr_ipv6_bitlen = 64;
number_per_cidr = 65536;
max_number = 3000;
sendq = 400 kbytes;
};
class "opers" {
ping_time = 5 minutes;
number_per_ip = 10;
max_number = 1000;
sendq = 1 megabyte;
};
class "server" {
ping_time = 5 minutes;
connectfreq = 5 minutes;
max_number = 1;
sendq = 4 megabytes;
};
listen {
/* defer_accept: wait for clients to send IRC handshake data before
* accepting them. if you intend to use software which depends on the
* server replying first, such as BOPM, you should disable this feature.
* otherwise, you probably want to leave it on.
*/
defer_accept = yes;
/* If you want to listen on a specific IP only, specify host.
* host definitions apply only to the following port line.
*/
# XXX This is stupid because only one host is allowed[?]
#host = ''${concatMapStringsSep ", " toJSON (
# config.krebs.build.host.nets.retiolum.addrs
#)};
port = ${toString cfg.port};
sslport = ${toString cfg.sslport};
};
/* auth {}: allow users to connect to the ircd (OLD I:)
* auth {} blocks MUST be specified in order of precedence. The first one
* that matches a user will be used. So place spoofs first, then specials,
* then general access, then restricted.
*/
auth {
/* user: the user@host allowed to connect. Multiple IPv4/IPv6 user
* lines are permitted per auth block. This is matched against the
* hostname and IP address (using :: shortening for IPv6 and
* prepending a 0 if it starts with a colon) and can also use CIDR
* masks.
*/
user = "*@10.243.0.0/16";
user = "*@42::/16";
/* password: an optional password that is required to use this block.
* By default this is not encrypted, specify the flag "encrypted" in
* flags = ...; below if it is.
*/
#password = "letmein";
/* spoof: fake the users user@host to be be this. You may either
* specify a host or a user@host to spoof to. This is free-form,
* just do everyone a favour and dont abuse it. (OLD I: = flag)
*/
#spoof = "I.still.hate.packets";
/* Possible flags in auth:
*
* encrypted | password is encrypted with mkpasswd
* spoof_notice | give a notice when spoofing hosts
* exceed_limit (old > flag) | allow user to exceed class user limits
* kline_exempt (old ^ flag) | exempt this user from k/g/xlines&dnsbls
* dnsbl_exempt | exempt this user from dnsbls
* spambot_exempt | exempt this user from spambot checks
* shide_exempt | exempt this user from serverhiding
* jupe_exempt | exempt this user from generating
* warnings joining juped channels
* resv_exempt | exempt this user from resvs
* flood_exempt | exempt this user from flood limits
* USE WITH CAUTION.
* no_tilde (old - flag) | don't prefix ~ to username if no ident
* need_ident (old + flag) | require ident for user in this class
* need_ssl | require SSL/TLS for user in this class
* need_sasl | require SASL id for user in this class
*/
flags = kline_exempt, exceed_limit, flood_exempt;
/* class: the class the user is placed in */
class = "krebs";
};
auth {
user = "*@*";
class = "users";
};
/* privset {} blocks MUST be specified before anything that uses them. That
* means they must be defined before operator {}.
*/
privset "local_op" {
privs = oper:local_kill, oper:operwall;
};
privset "server_bot" {
extends = "local_op";
privs = oper:kline, oper:remoteban, snomask:nick_changes;
};
privset "global_op" {
extends = "local_op";
privs = oper:global_kill, oper:routing, oper:kline, oper:unkline, oper:xline,
oper:resv, oper:mass_notice, oper:remoteban;
};
privset "admin" {
extends = "global_op";
privs = oper:admin, oper:die, oper:rehash, oper:spy, oper:override;
};
privset "aids" {
privs = oper:override, oper:rehash;
};
operator "aids" {
user = "*@10.243.*";
privset = "aids";
flags = ~encrypted;
password = "balls";
};
operator "god" {
/* name: the name of the oper must go above */
/* user: the user@host required for this operator. CIDR *is*
* supported now. auth{} spoofs work here, other spoofs do not.
* multiple user="" lines are supported.
*/
user = "*god@127.0.0.1";
/* password: the password required to oper. Unless ~encrypted is
* contained in flags = ...; this will need to be encrypted using
* mkpasswd, MD5 is supported
*/
password = "5";
/* rsa key: the public key for this oper when using Challenge.
* A password should not be defined when this is used, see
* doc/challenge.txt for more information.
*/
#rsa_public_key_file = "/usr/local/ircd/etc/oper.pub";
/* umodes: the specific umodes this oper gets when they oper.
* If this is specified an oper will not be given oper_umodes
* These are described above oper_only_umodes in general {};
*/
#umodes = locops, servnotice, operwall, wallop;
/* fingerprint: if specified, the oper's client certificate
* fingerprint will be checked against the specified fingerprint
* below.
*/
#fingerprint = "c77106576abf7f9f90cca0f63874a60f2e40a64b";
/* snomask: specific server notice mask on oper up.
* If this is specified an oper will not be given oper_snomask.
*/
snomask = "+Zbfkrsuy";
/* flags: misc options for the operator. You may prefix an option
* with ~ to disable it, e.g. ~encrypted.
*
* Default flags are encrypted.
*
* Available options:
*
* encrypted: the password above is encrypted [DEFAULT]
* need_ssl: must be using SSL/TLS to oper up
*/
flags = encrypted;
/* privset: privileges set to grant */
privset = "admin";
};
service {
name = "services.int";
};
cluster {
name = "*";
flags = kline, tkline, unkline, xline, txline, unxline, resv, tresv, unresv;
};
shared {
oper = "*@*", "*";
flags = all, rehash;
};
/* exempt {}: IPs that are exempt from Dlines and rejectcache. (OLD d:) */
exempt {
ip = "127.0.0.1";
};
channel {
use_invex = yes;
use_except = yes;
use_forward = yes;
use_knock = yes;
knock_delay = 5 minutes;
knock_delay_channel = 1 minute;
max_chans_per_user = 15;
max_bans = 100;
max_bans_large = 500;
default_split_user_count = 0;
default_split_server_count = 0;
no_create_on_split = no;
no_join_on_split = no;
burst_topicwho = yes;
kick_on_split_riding = no;
only_ascii_channels = no;
resv_forcepart = yes;
channel_target_change = yes;
disable_local_channels = no;
};
serverhide {
flatten_links = yes;
links_delay = 5 minutes;
hidden = no;
disable_hidden = no;
};
/* These are the blacklist settings.
* You can have multiple combinations of host and rejection reasons.
* They are used in pairs of one host/rejection reason.
*
* These settings should be adequate for most networks, and are (presently)
* required for use on StaticBox.
*
* Word to the wise: Do not use blacklists like SPEWS for blocking IRC
* connections.
*
* As of charybdis 2.2, you can do some keyword substitution on the rejection
* reason. The available keyword substitutions are:
*
* ''${ip} - the user's IP
* ''${host} - the user's canonical hostname
* ''${dnsbl-host} - the dnsbl hostname the lookup was done against
* ''${nick} - the user's nickname
* ''${network-name} - the name of the network
*
* As of charybdis 3.4, a type parameter is supported, which specifies the
* address families the blacklist supports. IPv4 and IPv6 are supported.
* IPv4 is currently the default as few blacklists support IPv6 operation
* as of this writing.
*
* Note: AHBL (the providers of the below *.ahbl.org BLs) request that they be
* contacted, via email, at admins@2mbit.com before using these BLs.
* See <http://www.ahbl.org/services.php> for more information.
*/
blacklist {
host = "rbl.efnetrbl.org";
type = ipv4;
reject_reason = "''${nick}, your IP (''${ip}) is listed in EFnet's RBL. For assistance, see http://efnetrbl.org/?i=''${ip}";
# host = "ircbl.ahbl.org";
# type = ipv4;
# reject_reason = "''${nick}, your IP (''${ip}) is listed in ''${dnsbl-host} for having an open proxy. In order to protect ''${network-name} from abuse, we are not allowing connections with open proxies to connect.";
#
# host = "tor.ahbl.org";
# type = ipv4;
# reject_reason = "''${nick}, your IP (''${ip}) is listed as a TOR exit node. In order to protect ''${network-name} from tor-based abuse, we are not allowing TOR exit nodes to connect to our network.";
#
/* Example of a blacklist that supports both IPv4 and IPv6 */
# host = "foobl.blacklist.invalid";
# type = ipv4, ipv6;
# reject_reason = "''${nick}, your IP (''${ip}) is listed in ''${dnsbl-host} for some reason. In order to protect ''${network-name} from abuse, we are not allowing connections listed in ''${dnsbl-host} to connect";
};
alias "NickServ" {
target = "NickServ";
};
alias "ChanServ" {
target = "ChanServ";
};
alias "OperServ" {
target = "OperServ";
};
alias "MemoServ" {
target = "MemoServ";
};
alias "NS" {
target = "NickServ";
};
alias "CS" {
target = "ChanServ";
};
alias "OS" {
target = "OperServ";
};
alias "MS" {
target = "MemoServ";
};
general {
hide_error_messages = opers;
hide_spoof_ips = yes;
/*
* default_umodes: umodes to enable on connect.
* If you have enabled the new ip_cloaking_4.0 module, and you want
* to make use of it, add +x to this option, i.e.:
* default_umodes = "+ix";
*
* If you have enabled the old ip_cloaking module, and you want
* to make use of it, add +h to this option, i.e.:
* default_umodes = "+ih";
*/
default_umodes = "+i";
default_operstring = "is an IRC Operator";
default_adminstring = "is a Server Administrator";
servicestring = "is a Network Service";
disable_fake_channels = no;
tkline_expire_notices = no;
default_floodcount = 1000;
failed_oper_notice = yes;
dots_in_ident=2;
min_nonwildcard = 4;
min_nonwildcard_simple = 3;
max_accept = 100;
max_monitor = 100;
anti_nick_flood = yes;
max_nick_time = 20 seconds;
max_nick_changes = 5;
anti_spam_exit_message_time = 5 minutes;
ts_warn_delta = 30 seconds;
ts_max_delta = 5 minutes;
client_exit = yes;
collision_fnc = yes;
resv_fnc = yes;
global_snotices = yes;
dline_with_reason = yes;
kline_delay = 0 seconds;
kline_with_reason = yes;
kline_reason = "K-Lined";
identify_service = "NickServ@services.int";
identify_command = "IDENTIFY";
non_redundant_klines = yes;
warn_no_nline = yes;
use_propagated_bans = yes;
stats_e_disabled = no;
stats_c_oper_only=no;
stats_h_oper_only=no;
client_flood_max_lines = 16000;
client_flood_burst_rate = 32000;
client_flood_burst_max = 32000;
client_flood_message_num = 32000;
client_flood_message_time = 32000;
use_whois_actually = no;
oper_only_umodes = operwall, locops, servnotice;
oper_umodes = locops, servnotice, operwall, wallop;
oper_snomask = "+s";
burst_away = yes;
nick_delay = 0 seconds; # 15 minutes if you want to enable this
reject_ban_time = 1 minute;
reject_after_count = 3;
reject_duration = 5 minutes;
throttle_duration = 60;
throttle_count = 4;
max_ratelimit_tokens = 30;
away_interval = 30;
disable_auth = yes;
};
modules {
path = "modules";
path = "modules/autoload";
};
exempt {
ip = "10.243.0.0/16";
};
''

View File

@ -0,0 +1,80 @@
{ config, lib, pkgs, ... }@args: with config.krebs.lib; let
cfg = config.tv.charybdis;
in {
options.tv.charybdis = {
enable = mkEnableOption "tv.charybdis";
motd = mkOption {
type = types.str;
default = "/join #retiolum";
};
port = mkOption {
type = types.int;
default = 6667;
};
ssl_cert = mkOption {
type = types.path;
};
ssl_dh_params = mkOption {
type = types.secret-file;
default = {
path = "${cfg.user.home}/dh.pem";
owner = cfg.user;
source-path = toString <secrets> + "/charybdis.dh.pem";
};
};
ssl_private_key = mkOption {
type = types.secret-file;
default = {
path = "${cfg.user.home}/ssl.key.pem";
owner = cfg.user;
source-path = toString <secrets> + "/charybdis.key.pem";
};
};
sslport = mkOption {
type = types.int;
default = 6697;
};
user = mkOption {
type = types.user;
default = {
name = "charybdis";
home = "/var/lib/charybdis";
};
};
};
config = lib.mkIf cfg.enable {
krebs.secret.files.charybdis-ssl_dh_params = cfg.ssl_dh_params;
krebs.secret.files.charybdis-ssl_private_key = cfg.ssl_private_key;
environment.etc."charybdis-ircd.motd".text = cfg.motd;
systemd.services.charybdis = {
wantedBy = [ "multi-user.target" ];
requires = [ "secret.service" ];
after = [ "network.target" "secret.service" ];
environment = {
BANDB_DBPATH = "${cfg.user.home}/ban.db";
};
serviceConfig = {
SyslogIdentifier = "charybdis";
User = cfg.user.name;
PrivateTmp = true;
Restart = "always";
ExecStartPre =
"${pkgs.coreutils}/bin/ln -s /etc/charybdis-ircd.motd /tmp/ircd.motd";
ExecStart = toString [
"${pkgs.charybdis}/bin/charybdis-ircd"
"-configfile ${import ./config.nix args}"
"-foreground"
"-logfile /dev/stderr"
];
};
};
users.users.${cfg.user.name} = {
inherit (cfg.user) home name uid;
createHome = true;
};
};
}

View File

@ -2,7 +2,8 @@ _:
{
imports = [
./ejabberd.nix
./charybdis
./ejabberd
./iptables.nix
];
}

View File

@ -1,165 +0,0 @@
{ config, lib, pkgs, ... }:
with config.krebs.lib;
let
cfg = config.tv.ejabberd;
out = {
options.tv.ejabberd = api;
config = lib.mkIf cfg.enable imp;
};
api = {
enable = mkEnableOption "tv.ejabberd";
certFile = mkOption {
type = types.str;
default = toString <secrets/ejabberd.pem>;
};
hosts = mkOption {
type = with types; listOf str;
};
};
imp = {
environment.systemPackages = [ my-ejabberdctl ];
systemd.services.ejabberd = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = "yes";
PermissionsStartOnly = "true";
SyslogIdentifier = "ejabberd";
User = user.name;
ExecStartPre = pkgs.writeScript "ejabberd-start" ''
#! /bin/sh
install -o ${user.name} -m 0400 ${cfg.certFile} /etc/ejabberd/ejabberd.pem
'';
ExecStart = pkgs.writeScript "ejabberd-service" ''
#! /bin/sh
${my-ejabberdctl}/bin/ejabberdctl start
'';
};
};
users.extraUsers = singleton {
inherit (user) name uid;
home = "/var/ejabberd";
createHome = true;
};
};
user = rec {
name = "ejabberd";
uid = genid name;
};
my-ejabberdctl = pkgs.writeScriptBin "ejabberdctl" ''
#! /bin/sh
set -euf
exec env \
SPOOLDIR=/var/ejabberd \
EJABBERD_CONFIG_PATH=${config-file} \
${pkgs.ejabberd}/bin/ejabberdctl \
--logs /var/ejabberd \
"$@"
'';
config-file = pkgs.writeText "ejabberd.cfg" ''
{loglevel, 3}.
{hosts, ${toErlang cfg.hosts}}.
{listen,
[
{5222, ejabberd_c2s, [
starttls,
{certfile, "/etc/ejabberd/ejabberd.pem"},
{access, c2s},
{shaper, c2s_shaper},
{max_stanza_size, 65536}
]},
{5269, ejabberd_s2s_in, [
{shaper, s2s_shaper},
{max_stanza_size, 131072}
]},
{5280, ejabberd_http, [
captcha,
http_bind,
http_poll,
web_admin
]}
]}.
{s2s_use_starttls, required}.
{s2s_certfile, "/etc/ejabberd/ejabberd.pem"}.
{auth_method, internal}.
{shaper, normal, {maxrate, 1000}}.
{shaper, fast, {maxrate, 50000}}.
{max_fsm_queue, 1000}.
{acl, local, {user_regexp, ""}}.
{access, max_user_sessions, [{10, all}]}.
{access, max_user_offline_messages, [{5000, admin}, {100, all}]}.
{access, local, [{allow, local}]}.
{access, c2s, [{deny, blocked},
{allow, all}]}.
{access, c2s_shaper, [{none, admin},
{normal, all}]}.
{access, s2s_shaper, [{fast, all}]}.
{access, announce, [{allow, admin}]}.
{access, configure, [{allow, admin}]}.
{access, muc_admin, [{allow, admin}]}.
{access, muc_create, [{allow, local}]}.
{access, muc, [{allow, all}]}.
{access, pubsub_createnode, [{allow, local}]}.
{access, register, [{allow, all}]}.
{language, "en"}.
{modules,
[
{mod_adhoc, []},
{mod_announce, [{access, announce}]},
{mod_blocking,[]},
{mod_caps, []},
{mod_configure,[]},
{mod_disco, []},
{mod_irc, []},
{mod_http_bind, []},
{mod_last, []},
{mod_muc, [
{access, muc},
{access_create, muc_create},
{access_persistent, muc_create},
{access_admin, muc_admin}
]},
{mod_offline, [{access_max_user_messages, max_user_offline_messages}]},
{mod_ping, []},
{mod_privacy, []},
{mod_private, []},
{mod_pubsub, [
{access_createnode, pubsub_createnode},
{ignore_pep_from_offline, true},
{last_item_cache, false},
{plugins, ["flat", "hometree", "pep"]}
]},
{mod_register, [
{welcome_message, {"Welcome!",
"Hi.\nWelcome to this XMPP server."}},
{ip_access, [{allow, "127.0.0.0/8"},
{deny, "0.0.0.0/0"}]},
{access, register}
]},
{mod_roster, []},
{mod_shared_roster,[]},
{mod_stats, []},
{mod_time, []},
{mod_vcard, []},
{mod_version, []}
]}.
'';
# XXX this is a placeholder that happens to work the default strings.
toErlang = builtins.toJSON;
in
out

View File

@ -0,0 +1,93 @@
{ config, ... }: with config.krebs.lib; let
cfg = config.tv.ejabberd;
# XXX this is a placeholder that happens to work the default strings.
toErlang = builtins.toJSON;
in toFile "ejabberd.conf" ''
{loglevel, 3}.
{hosts, ${toErlang cfg.hosts}}.
{listen,
[
{5222, ejabberd_c2s, [
starttls,
{certfile, ${toErlang cfg.certfile.path}},
{access, c2s},
{shaper, c2s_shaper},
{max_stanza_size, 65536}
]},
{5269, ejabberd_s2s_in, [
{shaper, s2s_shaper},
{max_stanza_size, 131072}
]},
{5280, ejabberd_http, [
captcha,
http_bind,
http_poll,
web_admin
]}
]}.
{s2s_use_starttls, required}.
{s2s_certfile, ${toErlang cfg.s2s_certfile.path}}.
{auth_method, internal}.
{shaper, normal, {maxrate, 1000}}.
{shaper, fast, {maxrate, 50000}}.
{max_fsm_queue, 1000}.
{acl, local, {user_regexp, ""}}.
{access, max_user_sessions, [{10, all}]}.
{access, max_user_offline_messages, [{5000, admin}, {100, all}]}.
{access, local, [{allow, local}]}.
{access, c2s, [{deny, blocked},
{allow, all}]}.
{access, c2s_shaper, [{none, admin},
{normal, all}]}.
{access, s2s_shaper, [{fast, all}]}.
{access, announce, [{allow, admin}]}.
{access, configure, [{allow, admin}]}.
{access, muc_admin, [{allow, admin}]}.
{access, muc_create, [{allow, local}]}.
{access, muc, [{allow, all}]}.
{access, pubsub_createnode, [{allow, local}]}.
{access, register, [{allow, all}]}.
{language, "en"}.
{modules,
[
{mod_adhoc, []},
{mod_announce, [{access, announce}]},
{mod_blocking,[]},
{mod_caps, []},
{mod_configure,[]},
{mod_disco, []},
{mod_irc, []},
{mod_http_bind, []},
{mod_last, []},
{mod_muc, [
{access, muc},
{access_create, muc_create},
{access_persistent, muc_create},
{access_admin, muc_admin}
]},
{mod_offline, [{access_max_user_messages, max_user_offline_messages}]},
{mod_ping, []},
{mod_privacy, []},
{mod_private, []},
{mod_pubsub, [
{access_createnode, pubsub_createnode},
{ignore_pep_from_offline, true},
{last_item_cache, false},
{plugins, ["flat", "hometree", "pep"]}
]},
{mod_register, [
{welcome_message, {"Welcome!",
"Hi.\nWelcome to this XMPP server."}},
{ip_access, [{allow, "127.0.0.0/8"},
{deny, "0.0.0.0/0"}]},
{access, register}
]},
{mod_roster, []},
{mod_shared_roster,[]},
{mod_stats, []},
{mod_time, []},
{mod_vcard, []},
{mod_version, []}
]}.
''

View File

@ -0,0 +1,67 @@
{ config, lib, pkgs, ... }@args: with config.krebs.lib; let
cfg = config.tv.ejabberd;
in {
options.tv.ejabberd = {
enable = mkEnableOption "tv.ejabberd";
certfile = mkOption {
type = types.secret-file;
default = {
path = "${cfg.user.home}/ejabberd.pem";
owner = cfg.user;
source-path = toString <secrets> + "/ejabberd.pem";
};
};
hosts = mkOption {
type = with types; listOf str;
};
pkgs.ejabberdctl = mkOption {
type = types.package;
default = pkgs.writeDashBin "ejabberdctl" ''
set -efu
export SPOOLDIR=${shell.escape cfg.user.home}
export EJABBERD_CONFIG_PATH=${shell.escape (import ./config.nix args)}
exec ${pkgs.ejabberd}/bin/ejabberdctl \
--logs ${shell.escape cfg.user.home} \
"$@"
'';
};
s2s_certfile = mkOption {
type = types.secret-file;
default = cfg.certfile;
};
user = mkOption {
type = types.user;
default = {
name = "ejabberd";
home = "/var/ejabberd";
};
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.pkgs.ejabberdctl ];
krebs.secret.files = {
ejabberd-certfile = cfg.certfile;
ejabberd-s2s_certfile = cfg.s2s_certfile;
};
systemd.services.ejabberd = {
wantedBy = [ "multi-user.target" ];
requires = [ "secret.service" ];
after = [ "network.target" "secret.service" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = "yes";
PermissionsStartOnly = "true";
SyslogIdentifier = "ejabberd";
User = cfg.user.name;
ExecStart = "${cfg.pkgs.ejabberdctl}/bin/ejabberdctl start";
};
};
users.users.${cfg.user.name} = {
inherit (cfg.user) home name uid;
createHome = true;
};
};
}

View File

@ -26,6 +26,21 @@ let
type = with types; listOf (either int str);
default = [];
};
extra = {
nat.POSTROUTING = mkOption {
type = with types; listOf str;
default = [];
};
filter.FORWARD = mkOption {
type = with types; listOf str;
default = [];
};
filter.INPUT = mkOption {
type = with types; listOf str;
default = [];
};
};
};
imp = {
@ -57,6 +72,11 @@ let
};
};
formatTable = table:
(concatStringsSep "\n"
(mapAttrsToList
(chain: concatMapStringsSep "\n" (rule: "-A ${chain} ${rule}"))
table));
rules = iptables-version: let
accept-echo-request = {
@ -79,6 +99,7 @@ let
${concatMapStringsSep "\n" (rule: "-A OUTPUT ${rule}") [
"-o lo -p tcp -m tcp --dport 11423 -j REDIRECT --to-ports 22"
]}
${formatTable cfg.extra.nat}
COMMIT
*filter
:INPUT DROP [0:0]
@ -94,6 +115,7 @@ let
++ map accept-new-tcp (unique (map toString cfg.input-internet-accept-new-tcp))
++ ["-i retiolum -j Retiolum"]
)}
${formatTable cfg.extra.filter}
${concatMapStringsSep "\n" (rule: "-A Retiolum ${rule}") ([]
++ optional (cfg.accept-echo-request == "retiolum") accept-echo-request
++ map accept-new-tcp (unique (map toString cfg.input-retiolum-accept-new-tcp))