tv retiolum: split module into options and config

This commit is contained in:
tv 2015-06-22 20:11:02 +02:00
parent f825bf5e9e
commit 68a968ac1b
11 changed files with 284 additions and 292 deletions

View File

@ -15,7 +15,7 @@ if ! test -e "$secrets_rsync"; then
exit # nothing to do
fi
retiolum_secret=$(nixos-query $system_name services.retiolum.privateKeyFile)
retiolum_secret=$(nixos-query $system_name tv.retiolum.privateKeyFile)
retiolum_uid=$(nixos-query $system_name users.extraUsers.retiolum-tinc.uid)
ejabberd_secret=/etc/ejabberd/ejabberd.pem

View File

@ -16,7 +16,6 @@ in
../tv/ejabberd.nix # XXX echtes modul
../tv/exim-smarthost.nix
../tv/git/public.nix
../tv/retiolum.nix
../tv/sanitize.nix
{
imports = [ ../tv/iptables ];
@ -34,6 +33,18 @@ in
];
};
}
{
imports = [ ../tv/retiolum ];
tv.retiolum = {
enable = true;
hosts = <retiolum-hosts>;
connectTo = [
"fastpoke"
"pigstarter"
"ire"
];
};
}
];
# "Developer 2" plan has two vCPUs.
@ -80,16 +91,5 @@ in
permitRootLogin = "yes";
};
services.retiolum = {
enable = true;
hosts = <retiolum-hosts>;
privateKeyFile = "/etc/tinc/retiolum/rsa_key.priv";
connectTo = [
"fastpoke"
"pigstarter"
"ire"
];
};
sound.enable = false;
}

View File

@ -15,7 +15,6 @@ in
../tv/base-cac-CentOS-7-64bit.nix
../tv/exim-smarthost.nix
../tv/git/public.nix
../tv/retiolum.nix
../tv/sanitize.nix
{
imports = [ ../tv/iptables ];
@ -33,6 +32,19 @@ in
];
};
}
{
imports = [ ../tv/retiolum ];
tv.retiolum = {
enable = true;
hosts = <retiolum-hosts>;
connectTo = [
"cd"
"fastpoke"
"pigstarter"
"ire"
];
};
}
];
nix.maxJobs = 1;
@ -74,17 +86,5 @@ in
permitRootLogin = "yes";
};
services.retiolum = {
enable = true;
hosts = <retiolum-hosts>;
privateKeyFile = "/etc/tinc/retiolum/rsa_key.priv";
connectTo = [
"cd"
"fastpoke"
"pigstarter"
"ire"
];
};
sound.enable = false;
}

View File

@ -15,7 +15,6 @@ in
../tv/base-cac-CentOS-7-64bit.nix
../tv/exim-smarthost.nix
../tv/git/public.nix
../tv/retiolum.nix
../tv/sanitize.nix
{
imports = [ ../tv/iptables ];
@ -33,6 +32,20 @@ in
];
};
}
{
imports = [ ../tv/retiolum ];
tv.retiolum = {
enable = true;
hosts = <retiolum-hosts>;
connectTo = [
"cd"
"mkdir"
"fastpoke"
"pigstarter"
"ire"
];
};
}
];
nix.maxJobs = 1;
@ -74,18 +87,5 @@ in
permitRootLogin = "yes";
};
services.retiolum = {
enable = true;
hosts = <retiolum-hosts>;
privateKeyFile = "/etc/tinc/retiolum/rsa_key.priv";
connectTo = [
"cd"
"rmdir"
"fastpoke"
"pigstarter"
"ire"
];
};
sound.enable = false;
}

View File

@ -4,9 +4,9 @@
services.exim =
# This configuration makes only sense for retiolum-enabled hosts.
# TODO modular configuration
assert config.services.retiolum.enable;
assert config.tv.retiolum.enable;
let
# TODO get the hostname from config.services.retiolum.
# TODO get the hostname from config.tv.retiolum.
retiolumHostname = "${config.networking.hostName}.retiolum";
in
{ enable = true;

View File

@ -15,10 +15,10 @@ in
{
services.nginx =
let
name = config.services.retiolum.name;
name = config.tv.retiolum.name;
qname = "${name}.retiolum";
in
assert config.services.retiolum.enable;
assert config.tv.retiolum.enable;
{
enable = true;
httpConfig = ''

View File

@ -1,228 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
{
###### interface
options = {
services.retiolum = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable tinc daemon for Retiolum.";
};
name = mkOption {
type = types.string;
default = config.networking.hostName;
# Description stolen from tinc.conf(5).
description = ''
This is the name which identifies this tinc daemon. It must
be unique for the virtual private network this daemon will
connect to. The Name may only consist of alphanumeric and
underscore characters. If Name starts with a $, then the
contents of the environment variable that follows will be
used. In that case, invalid characters will be converted to
underscores. If Name is $HOST, but no such environment
variable exist, the hostname will be read using the
gethostnname() system call This is the name which identifies
the this tinc daemon.
'';
};
generateEtcHosts = mkOption {
type = types.string;
default = "both";
description = ''
If set to <literal>short</literal>, <literal>long</literal>, or <literal>both</literal>,
then generate entries in <filename>/etc/hosts</filename> from subnets.
'';
};
network = mkOption {
type = types.string;
default = "retiolum";
description = ''
The tinc network name.
It is used to generate long host entries,
derive the name of the user account under which tincd runs,
and name the TUN device.
'';
};
tincPackage = mkOption {
type = types.package;
default = pkgs.tinc;
description = "Tincd package to use.";
};
hosts = mkOption {
default = null;
description = ''
Hosts package or path to use.
If a path is given, then it will be used to generate an ad-hoc package.
'';
};
iproutePackage = mkOption {
type = types.package;
default = pkgs.iproute;
description = "Iproute2 package to use.";
};
privateKeyFile = mkOption {
# TODO if it's types.path then it gets copied to /nix/store with
# bad unsafe permissions...
type = types.string;
default = "/etc/tinc/retiolum/rsa_key.priv";
description = "Generate file with <literal>tincd -K</literal>.";
};
connectTo = mkOption {
type = types.listOf types.string;
default = [ "fastpoke" "pigstarter" "kheurop" ];
description = "TODO describe me";
};
};
};
###### implementation
config =
let
cfg = config.services.retiolum;
tinc = cfg.tincPackage;
hostsType = builtins.typeOf cfg.hosts;
hosts =
if hostsType == "package" then
# use package as is
cfg.hosts
else if hostsType == "path" then
# use path to generate a package
pkgs.stdenv.mkDerivation {
name = "custom-retiolum-hosts";
src = cfg.hosts;
installPhase = ''
mkdir $out
find . -name .git -prune -o -type f -print0 | xargs -0 cp --target-directory $out
'';
}
else
abort "The option `services.retiolum.hosts' must be set to a package or a path"
;
iproute = cfg.iproutePackage;
retiolumExtraHosts = import (pkgs.runCommand "retiolum-etc-hosts"
{ }
''
generate() {
(cd ${hosts}
printf \'\'
for i in `ls`; do
names=$(hostnames $i)
for j in `sed -En 's|^ *Aliases *= *(.+)|\1|p' $i`; do
names="$names $(hostnames $j)"
done
sed -En '
s|^ *Subnet *= *([^ /]*)(/[0-9]*)? *$|\1 '"$names"'|p
' $i
done | sort
printf \'\'
)
}
case ${cfg.generateEtcHosts} in
short)
hostnames() { echo "$1"; }
generate
;;
long)
hostnames() { echo "$1.${cfg.network}"; }
generate
;;
both)
hostnames() { echo "$1.${cfg.network} $1"; }
generate
;;
*)
echo '""'
;;
esac > $out
'');
confDir = pkgs.runCommand "retiolum" {
# TODO text
executable = true;
preferLocalBuild = true;
} ''
set -euf
mkdir -p $out
ln -s ${hosts} $out/hosts
cat > $out/tinc.conf <<EOF
Name = ${cfg.name}
Device = /dev/net/tun
Interface = ${cfg.network}
${concatStrings (map (c : "ConnectTo = " + c + "\n") cfg.connectTo)}
PrivateKeyFile = ${cfg.privateKeyFile}
EOF
# source: krebscode/painload/retiolum/scripts/tinc_setup/tinc-up
cat > $out/tinc-up <<EOF
host=$out/hosts/${cfg.name}
${iproute}/sbin/ip link set \$INTERFACE up
addr4=\$(sed -n 's|^ *Subnet *= *\(10[.][^ ]*\) *$|\1|p' \$host)
if [ -n "\$addr4" ];then
${iproute}/sbin/ip -4 addr add \$addr4 dev \$INTERFACE
${iproute}/sbin/ip -4 route add 10.243.0.0/16 dev \$INTERFACE
fi
addr6=\$(sed -n 's|^ *Subnet *= *\(42[:][^ ]*\) *$|\1|p' \$host)
${iproute}/sbin/ip -6 addr add \$addr6 dev \$INTERFACE
${iproute}/sbin/ip -6 route add 42::/16 dev \$INTERFACE
EOF
chmod +x $out/tinc-up
'';
user = cfg.network + "-tinc";
in
mkIf cfg.enable {
environment.systemPackages = [ tinc hosts iproute ];
networking.extraHosts = retiolumExtraHosts;
systemd.services.retiolum = {
description = "Tinc daemon for Retiolum";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
path = [ tinc iproute ];
serviceConfig = {
# TODO we cannot chroot (-R) b/c we use symlinks to hosts
# and the private key.
ExecStart = "${tinc}/sbin/tincd -c ${confDir} -d 0 -U ${user} -D";
SyslogIdentifier = "retiolum-tincd";
};
restartIfChanged = true;
};
users.extraUsers = singleton {
name = user;
uid = 42; # TODO config.ids.uids.retiolum
};
};
}

View File

@ -0,0 +1,131 @@
{ cfg, config, lib, pkgs, ... }:
let
inherit (lib) concatStrings singleton;
tinc = cfg.tincPackage;
hostsType = builtins.typeOf cfg.hosts;
hosts =
if hostsType == "package" then
# use package as is
cfg.hosts
else if hostsType == "path" then
# use path to generate a package
pkgs.stdenv.mkDerivation {
name = "custom-retiolum-hosts";
src = cfg.hosts;
installPhase = ''
mkdir $out
find . -name .git -prune -o -type f -print0 | xargs -0 cp --target-directory $out
'';
}
else
abort "The option `services.retiolum.hosts' must be set to a package or a path"
;
iproute = cfg.iproutePackage;
retiolumExtraHosts = import (pkgs.runCommand "retiolum-etc-hosts"
{ }
''
generate() {
(cd ${hosts}
printf \'\'
for i in `ls`; do
names=$(hostnames $i)
for j in `sed -En 's|^ *Aliases *= *(.+)|\1|p' $i`; do
names="$names $(hostnames $j)"
done
sed -En '
s|^ *Subnet *= *([^ /]*)(/[0-9]*)? *$|\1 '"$names"'|p
' $i
done | sort
printf \'\'
)
}
case ${cfg.generateEtcHosts} in
short)
hostnames() { echo "$1"; }
generate
;;
long)
hostnames() { echo "$1.${cfg.network}"; }
generate
;;
both)
hostnames() { echo "$1.${cfg.network} $1"; }
generate
;;
*)
echo '""'
;;
esac > $out
'');
confDir = pkgs.runCommand "retiolum" {
# TODO text
executable = true;
preferLocalBuild = true;
} ''
set -euf
mkdir -p $out
ln -s ${hosts} $out/hosts
cat > $out/tinc.conf <<EOF
Name = ${cfg.name}
Device = /dev/net/tun
Interface = ${cfg.network}
${concatStrings (map (c : "ConnectTo = " + c + "\n") cfg.connectTo)}
PrivateKeyFile = ${cfg.privateKeyFile}
EOF
# source: krebscode/painload/retiolum/scripts/tinc_setup/tinc-up
cat > $out/tinc-up <<EOF
host=$out/hosts/${cfg.name}
${iproute}/sbin/ip link set \$INTERFACE up
addr4=\$(sed -n 's|^ *Subnet *= *\(10[.][^ ]*\) *$|\1|p' \$host)
if [ -n "\$addr4" ];then
${iproute}/sbin/ip -4 addr add \$addr4 dev \$INTERFACE
${iproute}/sbin/ip -4 route add 10.243.0.0/16 dev \$INTERFACE
fi
addr6=\$(sed -n 's|^ *Subnet *= *\(42[:][^ ]*\) *$|\1|p' \$host)
${iproute}/sbin/ip -6 addr add \$addr6 dev \$INTERFACE
${iproute}/sbin/ip -6 route add 42::/16 dev \$INTERFACE
EOF
chmod +x $out/tinc-up
'';
user = cfg.network + "-tinc";
in
{
environment.systemPackages = [ tinc hosts iproute ];
networking.extraHosts = retiolumExtraHosts;
systemd.services.retiolum = {
description = "Tinc daemon for Retiolum";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
path = [ tinc iproute ];
serviceConfig = {
# TODO we cannot chroot (-R) b/c we use symlinks to hosts
# and the private key.
ExecStart = "${tinc}/sbin/tincd -c ${confDir} -d 0 -U ${user} -D";
SyslogIdentifier = "retiolum-tincd";
};
restartIfChanged = true;
};
users.extraUsers = singleton {
name = user;
uid = 2961822815; # bin/genid retiolum-tinc
};
}

View File

@ -0,0 +1,11 @@
arg@{ config, pkgs, lib, ... }:
let
cfg = config.tv.retiolum;
arg' = arg // { inherit cfg; };
in
{
options.tv.retiolum = import ./options.nix arg';
config = lib.mkIf cfg.enable (import ./config.nix arg');
}

View File

@ -0,0 +1,87 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkOption types;
in
{
enable = mkOption {
type = types.bool;
default = false;
description = "Enable tinc daemon for Retiolum.";
};
name = mkOption {
type = types.string;
default = config.networking.hostName;
# Description stolen from tinc.conf(5).
description = ''
This is the name which identifies this tinc daemon. It must
be unique for the virtual private network this daemon will
connect to. The Name may only consist of alphanumeric and
underscore characters. If Name starts with a $, then the
contents of the environment variable that follows will be
used. In that case, invalid characters will be converted to
underscores. If Name is $HOST, but no such environment
variable exist, the hostname will be read using the
gethostnname() system call This is the name which identifies
the this tinc daemon.
'';
};
generateEtcHosts = mkOption {
type = types.string;
default = "both";
description = ''
If set to <literal>short</literal>, <literal>long</literal>, or <literal>both</literal>,
then generate entries in <filename>/etc/hosts</filename> from subnets.
'';
};
network = mkOption {
type = types.string;
default = "retiolum";
description = ''
The tinc network name.
It is used to generate long host entries,
derive the name of the user account under which tincd runs,
and name the TUN device.
'';
};
tincPackage = mkOption {
type = types.package;
default = pkgs.tinc;
description = "Tincd package to use.";
};
hosts = mkOption {
default = null;
description = ''
Hosts package or path to use.
If a path is given, then it will be used to generate an ad-hoc package.
'';
};
iproutePackage = mkOption {
type = types.package;
default = pkgs.iproute;
description = "Iproute2 package to use.";
};
privateKeyFile = mkOption {
# TODO if it's types.path then it gets copied to /nix/store with
# bad unsafe permissions...
type = types.string;
default = "/etc/tinc/retiolum/rsa_key.priv";
description = "Generate file with <literal>tincd -K</literal>.";
};
connectTo = mkOption {
type = types.listOf types.string;
default = [ "fastpoke" "pigstarter" "kheurop" ];
description = "TODO describe me";
};
}

View File

@ -14,7 +14,6 @@ in
../common/nixpkgs.nix
../tv/base.nix
../tv/exim-retiolum.nix
../tv/retiolum.nix
../tv/sanitize.nix
../tv/smartd.nix
../tv/synaptics.nix
@ -44,6 +43,17 @@ in
];
};
}
{
imports = [ ../tv/retiolum ];
tv.retiolum = {
enable = true;
hosts = <retiolum-hosts>;
connectTo = [
"gum"
"pigstarter"
];
};
}
];
nix.maxJobs = 8;
@ -342,25 +352,6 @@ in
# '';
#};
services.retiolum = {
enable = true;
hosts = <retiolum-hosts>;
connectTo = [
"gum"
"pigstarter"
];
};
# TODO
#services.tinc = {
# enable = true;
# network = "retiolum";
# hosts = /home/tv/krebs/hosts;
# privateKeyFile = /etc/tinc/retiolum/rsa_key.priv;
# connectTo = [ "fastpoke" "pigstarter" "kheurop" ];
#};
security.rtkit.enable = false;
services.nscd.enable = false;
services.ntp.enable = false;