Goodbye old world, and thanks for all the fish!

This commit is contained in:
tv 2015-07-16 23:22:30 +02:00
parent 447c63edbd
commit 57c520b722
118 changed files with 0 additions and 8659 deletions

View File

@ -1,48 +0,0 @@
all:;@exit 23
tv-cluster := cd mkdir nomic rmdir wu
deploy-cd:; ./deploy cd
deploy-mkdir:; ./deploy mkdir
deploy-nomic:; ./deploy nomic root@nomic-local
deploy-rmdir:; ./deploy rmdir
deploy-wu:; ./deploy wu root@localhost
ifndef cluster
cluster := $(LOGNAME)
endif
hosts := $($(cluster)-cluster)
ifeq ($(hosts),)
$(error bad cluster: $(cluster))
else
.ONESHELL:
.PHONY: deploy $(addprefix deploy-,$(hosts))
deploy:
exec parallel \
-j 0 \
--no-notice \
--rpl '{u} s/^.* deploy-(.*)/\1/' \
--tagstring '{u}' \
--line-buffer \
$(MAKE) deploy-{} ::: $(hosts)
.PHONY: rotate-consul-encrypt
rotate-consul-encrypt:
umask 0377
mkencrypt() { dd status=none if=/dev/random bs=1 count=16 | base64; }
json=$$(printf '{"encrypt":"%s"}\n' $$(mkencrypt))
cmd='
f=secrets/{}/rsync/etc/consul/encrypt.json
rm -f "$$f"
echo "$$json" > "$$f"
'
export json
exec parallel \
-j 0 \
--no-notice \
--rpl '{u} s/^.* deploy-(.*)/\1/' \
--tagstring '{u}' \
--line-buffer \
--quote \
sh -eufc "$$cmd" ::: $(hosts)
endif

View File

@ -1,32 +0,0 @@
# Turn a Cloud at Cost CentOS-7-64bit server into NixOS
1. Configure the system (`$systemname`) you'd like to install (see Configuration below).
2. Create new server instance (either Custom or cloudpro) using "CentOS-7-64bit".
Note the servername (something like c731445864-cloudpro-388922936).
3. `cac_login=xxx cac_key=yyy ./infest-cac-CentOS-7-64bit.sh servername:$servername $systename`
4. Enjoy. (`ssh root@$systename`)
# Configuration
Configure your system in modules/$systemname
See modules/cd/default.nix as an example.
Notice that modules/$systemname/networking will be autogenerated (but not committed).
secrets/$systemname/nix/foo can be accessed as `<secrets/foo>` from within the configuration.
You might want `secrets/$systemname/rsync/etc/tinc/retiolum/rsa_key.priv`.
You might want `secrets/$systemname/nix/hashedPasswords.nix`, which looks like
```nix
_: { users.extraUsers.root.hashedPassword = "XXX"; }
```
`XXX` can be generated with e.g.
```
mkpasswd -m sha-512 -S $(openssl rand -base64 16 | tr -d '+=' | head -c 16)
```

View File

@ -1,69 +0,0 @@
#! /bin/sh
#
# copy-secrets system_name target
#
set -euf
system_name=$1
target=$2
nixos_config=$config_root/modules/$system_name
secrets_nix=$secrets_root/$system_name/nix
secrets_rsync=$secrets_root/$system_name/rsync
if ! test -e "$secrets_rsync"; then
exit # nothing to do
fi
# XXX this is ugly
# Notice NIX_PATH used from host
# Notice secrets required to evaluate configuration
NIX_PATH=$NIX_PATH:nixos-config=$PWD/modules/$system_name
NIX_PATH=$NIX_PATH:secrets=$PWD/secrets/$system_name/nix
export NIX_PATH
case $(nixos-query tv.retiolum.enable 2>/dev/null) in true)
retiolum_secret=$(nixos-query tv.retiolum.privateKeyFile)
retiolum_uid=$(nixos-query users.extraUsers.retiolum-tinc.uid)
esac
case $(nixos-query services.ejabberd-cd.enable 2>/dev/null) in true)
ejabberd_secret=$(nixos-query services.ejabberd-cd.certFile)
ejabberd_uid=$(nixos-query users.extraUsers.ejabberd.uid)
esac
case $(nixos-query tv.consul.enable 2>/dev/null) in true)
consul_secret=$(nixos-query tv.consul.encrypt-file)
consul_uid=$(nixos-query users.extraUsers.consul.uid)
esac
(set -x
rsync \
--rsync-path="mkdir -p \"$2\" && rsync" \
-vzrlptD \
"$secrets_rsync/" \
"$target:/")
ssh "$target" -T <<EOF
set -euf
retiolum_secret=${retiolum_secret-}
retiolum_uid=${retiolum_uid-}
ejabberd_secret=${ejabberd_secret-}
ejabberd_uid=${ejabberd_uid-}
consul_secret=${consul_secret-}
consul_uid=${consul_uid-}
if test -n "\$retiolum_secret"; then
chown -v "\$retiolum_uid:0" "\$retiolum_secret"
fi
if test -n "\$ejabberd_secret"; then
chown -v "\$ejabberd_uid:0" "\$ejabberd_secret"
fi
if test -n "\$consul_secret"; then
chown -v "\$consul_uid:0" "\$consul_secret"
fi
EOF

View File

@ -1,11 +0,0 @@
#! /bin/sh
# usage: genid NAME
set -euf
name=$1
hash=$(printf %s "$name" | sha1sum | cut -d\ -f1 | tr a-f A-F)
echo "
min=2^16 # bigger than nobody and nogroup, see <nixos/modules/misc/ids.nix>
max=2^32 # see 2^(8*sizeof(uid_t))
ibase=16
($hash + min) % max
" | bc

View File

@ -1,12 +0,0 @@
#! /bin/sh
set -euf
netmask=$1
binaryNetmask=$(echo $1 | sed 's/^/obase=2;/;s/\./;/g' | bc | tr -d \\n)
binaryPrefix=$(echo $binaryNetmask | sed -n 's/^\(1*\)0*$/\1/p')
if ! echo $binaryPrefix | grep -q .; then
echo $0: bad netmask: $netmask >&2
exit 4
fi
printf %s $binaryPrefix | tr -d 0 | wc -c

View File

@ -1,4 +0,0 @@
#! /bin/sh
set -euf
result=$(nix-instantiate -A config."$1" --eval --json '<nixos>')
echo $result | jq -r .

View File

@ -1,35 +0,0 @@
#! /bin/sh
set -euf
exec sed '
s/%/%25/g
s/ /%20/g
s/!/%21/g
s/"/%22/g
s/#/%23/g
s/\$/%24/g
s/\&/%26/g
s/'\''/%27/g
s/(/%28/g
s/)/%29/g
s/\*/%2a/g
s/+/%2b/g
s/,/%2c/g
s/-/%2d/g
s/\./%2e/g
s/\//%2f/g
s/:/%3a/g
s/;/%3b/g
s//%3e/g
s/?/%3f/g
s/@/%40/g
s/\[/%5b/g
s/\\/%5c/g
s/\]/%5d/g
s/\^/%5e/g
s/_/%5f/g
s/`/%60/g
s/{/%7b/g
s/|/%7c/g
s/}/%7d/g
s/~/%7e/g
'

337
old/cac
View File

@ -1,337 +0,0 @@
#! /bin/sh
set -euf
PATH=$PWD/bin:$PATH
export PATH
cac_listservers_cache=$PWD/tmp/cac_listservers_cache.json
cac() {
__cac_cli__command=$1
shift
__cac_cli__"$__cac_cli__command" "$@"
}
# WIP
__cac_cli__help() {(
exec sed < "$0" -n '
s/^__cac_cli__\([^(]\+\)().*/\1/p
'
)}
# usage: console
__cac_cli__console() {(
server=$(__cac_cli__getserver "$1")
sid=$(echo $server | jq -r .sid)
# TODO check reply status == ok
_cac_post_api_v1 console sid="$sid" | jq -r .console
)}
__cac_cli__listservers() {
jq -r . $cac_listservers_cache
}
__cac_cli__update() {(
umask 0077
servers=$(_cac_listservers)
echo $servers > $cac_listservers_cache.tmp
mv $cac_listservers_cache.tmp $cac_listservers_cache
)}
__cac_cli__getserver() {(
case $1 in
*:*)
k=${1%%:*}
v=${1#*:}
;;
*)
k=label
v=${1#*:}
;;
esac
if result=$(jq \
-e \
--arg k "$k" \
--arg v "$v" \
'
map(select(.[$k]==$v)) |
if (. | length) == 1 then
.[0]
else
null
end
' \
$cac_listservers_cache); then
echo $result | jq -r .
else
echo "$0 getserver $k:$v => not unique server found" >&2
exit 23
fi
)}
__cac_cli__generatenetworking() {(
server=$(__cac_cli__getserver "$1")
hostname=$(echo $server | jq -r .label)
address=$(echo $server | jq -r .ip)
gateway=$(echo $server | jq -r .gateway)
nameserver=8.8.8.8
netmask=$(echo $server | jq -r .netmask)
prefix=$(netmask-to-prefix $netmask)
#printf '# Generated file: %s generatenetworking %s %s\n' "$0" "$1" "$2"
#printf '# on %s\n' "$(date -Is)"
#printf '\n'
printf '_:\n'
printf '\n'
printf '{\n'
printf ' networking.hostName = "%s";\n' $hostname
printf ' networking.interfaces.enp2s1.ip4 = [\n'
printf ' {\n'
printf ' address = "%s";\n' $address
printf ' prefixLength = %d;\n' $prefix
printf ' }\n'
printf ' ];\n'
printf ' networking.defaultGateway = "%s";\n' $gateway
printf ' networking.nameservers = [\n'
printf ' "%s"\n' $nameserver
printf ' ];\n'
printf '}\n'
)}
__cac_cli__powerop() {(
server=$(__cac_cli__getserver "$1")
action=$2
sid=$(echo $server | jq -r .sid)
reply=$(_cac_post_api_v1 powerop sid="$sid" action="$action")
case $(echo $reply | jq -r .status) in
ok)
echo $reply | jq -r . >&2
__cac_cli__update
;;
*)
echo bad reply: >&2
echo $reply | jq -r . >&2
exit 23
;;
esac
)}
__cac_cli__pushconfig() {(
server=$(__cac_cli__getserver "$1")
prefix=${2-/}
hostname=$(echo $server | jq -r .label)
address=$(echo $server | jq -r .ip)
target=root@$address
RSYNC_RSH='sshpass -e ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
SSHPASS=$(echo $server | jq -r .rootpass)
export RSYNC_RSH SSHPASS
pushgit . $target:$prefix/etc/nixos/
pushgit hosts $target:$prefix/etc/nixos/hosts/
pushgit tmp/nixpkgs/$hostname $target:$prefix/etc/nixos/nixpkgs/
pushdir secrets/$hostname/nix $target:$prefix/etc/nixos/secrets/
pushdir secrets/$hostname/rsync $target:$prefix/
echo "_:{imports=[./modules/$hostname];}" \
| $RSYNC_RSH "$target" tee "$prefix/etc/nixos/configuration.nix" \
> /dev/null
## TODO chmod and chown secrets
)}
__cac_cli__setlabel() {(
server=$(__cac_cli__getserver "$1")
label=$2
sid=$(echo $server | jq -r .sid)
reply=$(_cac_post_api_v1 renameserver sid="$sid" name="$label")
case $(echo $reply | jq -r .status) in
ok)
echo $reply | jq -r . >&2
__cac_cli__update
;;
*)
echo bad reply: >&2
echo $reply | jq -r . >&2
exit 23
;;
esac
)}
__cac_cli__setmode() {(
server=$(__cac_cli__getserver "$1")
mode=$2
sid=$(echo $server | jq -r .sid)
reply=$(_cac_post_api_v1 runmode sid="$sid" mode="$mode")
case $(echo $reply | jq -r .status) in
ok)
echo $reply | jq -r . >&2
__cac_cli__update
;;
*)
echo bad reply: >&2
echo $reply | jq -r .
exit 23
;;
esac
)}
__cac_cli__ssh() {(
server=$(__cac_cli__getserver "$1")
shift
address=$(echo $server | jq -r .ip)
target=root@$address
SSHPASS=$(echo $server | jq -r .rootpass)
export SSHPASS
exec sshpass -e ssh \
-S none \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
$target \
"$@"
)}
# usage: ./cac waitstatus mode:Safe 'Powered On'
# blocks until server has specfied state
__cac_cli__waitstatus() {
server=$(__cac_cli__getserver "$1")
status=$(echo $server | jq -r .status)
case $status in
$2)
return
;;
esac
echo "$(date -Is) Waiting for status: $2; current status: $status ..." >&2
__cac_cli__waitforcacheupdate __cac_cli__waitstatus "$@"
}
# XXX for __cac_cli__waitforcacheupdate and __cac_cli__poll cache means $cac_listservers_cache
# blocks until cache has been updated then executes "$@"
__cac_cli__waitforcacheupdate() {
case $(inotifywait --format %f -q -e moved_to $(dirname $cac_listservers_cache)) in
$(basename $cac_listservers_cache)) "$@";;
*) __cac_cli__waitforcacheupdate "$@";;
esac
}
# usage: with cac ./cac poll 60s
# continuously update cache, sleeping at least $1 between updates
__cac_cli__poll() {
__cac_cli__update
t=${1-1m}
echo "$(date -Is) cache updated; sleeping $t ..." >&2
sleep "$t"
__cac_cli__poll "$@"
}
_cac_listservers() {(
servers=$(_cac_get_api_v1 listservers)
status=$(echo $servers | jq -r .status)
if [ "$status" = ok ]; then
echo "$servers" | jq -r .data
else
echo "cac_listservers: bad listservers status: $status" >&2
exit 1
fi
)}
# rsyncfiles : lines filename |> local-dir x rsync-target -> ? |> ?
rsyncfiles() {(
set -x
rsync \
--rsync-path="mkdir -p \"$2\" && rsync" \
-vzrlptD \
--files-from=- \
"$1"/ \
"$2"
)}
# gitfiles : git-work-tree -> lines filename
gitfiles() {
git -C "$1" archive --format=tar HEAD | tar t | sed '/\/$/d'
}
# pushgit : git-work-tree x rsync-target -> ?
pushgit() {
gitfiles "$1" | rsyncfiles "$1" "$2"
}
# dirfiles : local-dir -> lines filename
dirfiles() {(
cd "$1"
find . -type f | sed 's/^\.\///'
)}
# pushdir : local-dir x rsync-target -> ?
pushdir() {
dirfiles "$1" | rsyncfiles "$1" "$2"
}
_cac_get_api_v1() {
_cac_curl_api_v1 -G "$@"
}
_cac_post_api_v1() {
_cac_curl_api_v1 -XPOST "$@"
}
_cac_curl_api_v1() {
_cac_exec curl -sS "$1" "https://panel.cloudatcost.com/api/v1/$2.php" $(
shift 2
set -- "$@" login="$cac_login" key="$cac_key"
for arg; do
echo -d $(printf '%s' "$arg" | urlencode)
done
)
}
_cac_exec() {
if test -z "${cac_via-}"; then
env -- "$@"
else
ssh -q "$cac_via" -t "$@"
fi
}
case ${run-true} in
true) cac "$@";;
esac

View File

@ -1,24 +0,0 @@
-----BEGIN CERTIFICATE-----
MIID7zCCAtegAwIBAgIJAPImpJwMgGmhMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYD
VQQGEwJTRzESMBAGA1UECAwJU2luZ2Fwb3JlMQ8wDQYDVQQKDAZaYWxvcmExCzAJ
BgNVBAsMAklUMSUwIwYDVQQDDBxaYWxvcmEgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
MSUwIwYJKoZIhvcNAQkBFhZpdC1zZXJ2aWNlc0B6YWxvcmEuY29tMB4XDTE0MDkx
ODIxNDY0N1oXDTI0MDkxNTIxNDY0N1owgY0xCzAJBgNVBAYTAlNHMRIwEAYDVQQI
DAlTaW5nYXBvcmUxDzANBgNVBAoMBlphbG9yYTELMAkGA1UECwwCSVQxJTAjBgNV
BAMMHFphbG9yYSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxJTAjBgkqhkiG9w0BCQEW
Fml0LXNlcnZpY2VzQHphbG9yYS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQDi48Tkh6XuS2gdE1+gsPPQjTI8Q2wbXqZGTHnyAZx75btOIUZHeHJm
Fvu8erAD+vtx1nD1GOG30uvHFk9Of2mFY1fxw0R1LthJHSLFJU1/GjFSggHWkaI3
HBSmeALjss/XHG3EtShLo8SHBc/+B8ehqj1JqcXF8q50JtfTQ+zlf+k26ke2S5Xo
OdHLxjlNaPwj+TgJI1DHqs/bTapaPHPKk5+jFQzAcMmq0bygzpQTHCvvKqcoXaJk
UgDBQnVsJUtwfObrM1TKu2TOXUhqgfnnflYf2sz5Sr30QlkrHP+PM3BRLB+6FXhr
UlKKVcAcIwrBo0aJ5Sd0fv39GwV1XCWVAgMBAAGjUDBOMB0GA1UdDgQWBBQFftMH
5/dc0pUNDqLbVQ8gm7+I5TAfBgNVHSMEGDAWgBQFftMH5/dc0pUNDqLbVQ8gm7+I
5TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQC2aSKJ15v5OI7Zj/HQ
lW+iY9STBPJi9lgOjaGrNaPX0IuhJLkeKDntmzjvpGwvcylHMp6Im02svTymteNN
38s8A0aStnmW4ysGT853H7L7Jxzf7J2vrUF0Dj4QkZ07Gp3vAgKnWVcqz36Xr0Se
DEqrKMl/6fq3Ygl35fZXP1kb6t/wP6qx69bnENH6ksHFpZapWYssKNZO9yiB8+Eq
ngB22X/ycMmAqOnNQDzw1JBw7LzdXypCG75UKEK6kbnUy2yPADdHpH8v9qcRa1U9
vEmUTJs6i1CpPO+2frPJ8A8QIp61nNxe7xJ1SnNVtwk9d6SRet6YGySvgG748Wjw
GwWx
-----END CERTIFICATE-----

View File

@ -1,151 +0,0 @@
{ system-name
, rsync-target ? null
, deploy-target ? null
}:
# TODO assert that only one of rsync-target or deploy-target is not null
with builtins;
assert (typeOf system-name == "string");
with import <nixpkgs/lib>;
let
paths-file = toPath "${dirOf __curPos.file}/modules/${system-name}/paths.nix";
paths = import paths-file;
prefetch.file = ''
echo "$prefetch_in_url"
'';
prefetch.git = ''
${concatMapStringsSep "\n" (attr-name: ''
case ''${prefetch_in_${escapeShellArg attr-name}-?} in \?)
printf '%s: %s: missing attribute: %s' \
${escapeShellArg paths-file} \
"$prefetch_name" \
${escapeShellArg attr-name} \
>&2
return 1
esac
'') [ "rev" "url" "cache" ]}
git_rev=$prefetch_in_rev
git_url=$prefetch_in_url
# cache_dir points to a (maybe non-existent) directory, where a shared cache of
# the repository should be maintained. The shared cache is used to create
# multiple working trees of the repository.
cache_dir=$prefetch_in_cache/$(echo "$git_url" | urlencode)
cache_git() {
git --git-dir="$cache_dir" "$@"
}
# work_dir points to a (maybe non-existent) directory, where a specific
# revision of the repository is checked out.
# XXX this is probably a bad idea if git_rev is not a commit
work_dir=$cache_dir-$(cache_git rev-parse --verify "$git_rev" | urlencode)
work_git() {
git -C "$work_dir" "$@"
}
is_up_to_date() {
test -d "$cache_dir" &&
test -d "$work_dir" &&
test "$(cache_git rev-parse --verify "$git_rev")" = "$git_rev" &&
test "$(work_git rev-parse --verify HEAD)" = "$git_rev"
}
# Notice how the remote name "origin" has been chosen arbitrarily, but must be
# kept in sync with the default value of nixpkgs.rev.
if ! is_up_to_date; then
if ! test -d "$cache_dir"; then
mkdir -p "$cache_dir"
cache_git init --bare
fi
if ! cache_git_url=$(cache_git config remote.origin.url); then
cache_git remote add origin "$git_url"
elif test "$cache_git_url" != "$git_url"; then
cache_git remote set-url origin "$git_url"
fi
cache_git fetch origin
if ! test -d "$work_dir"; then
git clone -n --shared "$cache_dir" "$work_dir"
fi
commit_name=$(cache_git rev-parse --verify "$git_rev")
work_git checkout "$commit_name" -- "$(readlink -f "$work_dir")"
work_git checkout -q "$commit_name"
work_git submodule init
work_git submodule update
fi
work_git clean -dxf
echo "$work_dir"
'';
f = pkg-name: pkg-spec:
let
types = attrNames pkg-spec;
type = elemAt types 0;
in
assert (length types == 1); # there can be only one source type
''
out=$(${concatStringsSep " \\\n" (mapAttrsToList (k: v:
"prefetch_in_${escapeShellArg k}=${escapeShellArg (toString v)}") pkg-spec.${type})} \
prefetch_name=${escapeShellArg pkg-name} \
__prefetch_${escapeShellArg type})
printf '%s=%s\n' \
${escapeShellArg pkg-name} \
"$out"
'';
in
''
#! /bin/sh
set -euf
PATH=${toString ./.}/bin:$PATH
export PATH
__prefetch_file() {
${prefetch.file}
}
__prefetch_git() {
${prefetch.git}
}
# TODO make sure x contains only sane chars
x=$(${concatStrings (mapAttrsToList f paths)})
${optionalString (rsync-target != null) ''
proot $(echo "$x" | sed -n 's@^\([^=]\+\)=\(.*\)@-b \2:/shitment/\1@p') \
rsync --delete --delete-excluded \
--filter='- /*/.git' \
--rsync-path='mkdir -p -m 0700 /shitment/ && rsync' \
-vaz \
--no-owner \
--no-group \
'/shitment/' \
${escapeShellArg rsync-target}
''}
${optionalString (deploy-target != null) ''
system_path=$(proot $(echo "$x" | sed -n 's@^\([^=]\+\)=\(.*\)@-b \2:/shitment/\1@p') \
env \
NIX_PATH=/shitment \
NIXOS_CONFIG=/shitment/modules/${escapeShellArg system-name} \
nix-build -A system --no-out-link '<nixpkgs/nixos>')
system_name=${escapeShellArg system-name}
target=${escapeShellArg deploy-target}
nix-copy-closure --gzip --to "$target" "$system_path"
secrets_root=${toString ./.}/secrets \
config_root=${toString ./.} \
copy-secrets "$system_name" "$target"
ssh ''${NIX_SSHOPTS-} "$target" "$system_path/bin/switch-to-configuration" switch
''}
''

View File

@ -1,15 +0,0 @@
#! /bin/sh
#
# usage: ./deploy system_name [target]
#
set -euf
system_name=$1
target=${2-root@$system_name}
nix-instantiate \
--argstr system-name "$system_name" \
--argstr deploy-target "$target" \
--eval --json . \
| jq -r . \
| sh

View File

@ -1,51 +0,0 @@
#! /bin/sh
set -xeuf
serverspec=$1
systemname=$2
(
PATH=$PWD/bin:$PATH
export PATH
# Notice NIX_PATH used from host
# Notice secrets required to evaluate configuration
NIX_PATH=$NIX_PATH:nixos-config=$PWD/modules/$systemname
NIX_PATH=$NIX_PATH:secrets=$PWD/secrets/$systemname/nix
export NIX_PATH
case $(nixos-query nixpkgs.dirty) in true)
echo "$0: cannot use nixpkgs.dirty" >&2 # b/c ./cac pushconfig
exit -1
esac
prefetch nixpkgs tmp/nixpkgs/$systemname
)
./cac poll 10s 2>/dev/null &
pollpid=$!
trap "kill $pollpid; trap - EXIT" EXIT
./cac waitstatus $serverspec 'Powered On'
# TODO don't set label/mode if they're already good
./cac setlabel $serverspec $systemname
./cac setmode $systemname normal
./cac generatenetworking $systemname > modules/$systemname/networking.nix
cat infest.d/cac-CentOS-7-64bit/prepare.sh | ./cac ssh $systemname \
nix_url=https://nixos.org/releases/nix/nix-1.9/nix-1.9-x86_64-linux.tar.bz2 \
nix_sha256=5c76611c631e79aef5faf3db2d253237998bbee0f61fa093f925fa32203ae32b \
/bin/sh
./cac pushconfig $systemname /mnt
# This needs to be run twice because (at least):
# Initialized empty Git repository in /var/lib/git/$reponame
# chown: invalid user: 'git:nogroup'
cat infest.d/nixos-install.sh | ./cac ssh $systemname || :
cat infest.d/nixos-install.sh | ./cac ssh $systemname
cat infest.d/cac-CentOS-7-64bit/finalize.sh | ./cac ssh $systemname
./cac powerop $systemname reset

View File

@ -1,66 +0,0 @@
#! /bin/sh
set -eu
{
umount /mnt2
umount /mnt/nix
umount /mnt/boot
umount /mnt
umount /boot
PATH=$(for i in /nix/store/*coreutils*/bin; do :; done; echo $i)
export PATH
mkdir /oldshit
mv /bin /oldshit/
mv /newshit/bin /
# TODO ensure /boot is empty
rmdir /newshit/boot
# skip /dev
rmdir /newshit/dev
mv /etc /oldshit/
mv /newshit/etc /
# TODO ensure /home is empty
rmdir /newshit/home
# skip /nix (it's already there)
rmdir /newshit/nix
# skip /proc
rmdir /newshit/proc
# skip /run
rmdir /newshit/run
# skip /sys
rmdir /newshit/sys
# skip /tmp
# TODO rmdir /newshit/tmp
mv /usr /oldshit/
mv /newshit/usr /
mv /var /oldshit/
mv /newshit/var /
mv /root /oldshit/
mv /newshit/root /
mv /lib /oldshit/
mv /lib64 /oldshit/
mv /sbin /oldshit/
mv /mnt2 /oldshit/
mv /srv /oldshit/
mv /opt /oldshit/
mv /newshit /root/ # TODO this one shoult be empty
mv /oldshit /root/
sync
}

View File

@ -1,104 +0,0 @@
#! /bin/sh
set -euf
: $nix_url
: $nix_sha256
{
#
# prepare host
#
type bzip2 2>/dev/null || yum install -y bzip2
type rsync 2>/dev/null || yum install -y rsync
if ! getent group nixbld >/dev/null; then
groupadd -g 30000 -r nixbld
fi
for i in `seq 1 10`; do
if ! getent passwd nixbld$i 2>/dev/null; then
useradd \
-c "CentOS Nix build user $i" \
-d /var/empty \
-g 30000 \
-G 30000 \
-l \
-M \
-s /sbin/nologin \
-u $(expr 30000 + $i) \
nixbld$i
rm -f /var/spool/mail/nixbld$i
fi
done
# generate fake sudo because
# sudo: sorry, you must have a tty to run sudo
mkdir -p bin
printf '#! /bin/sh\nexec env "$@"\n' > bin/sudo
chmod +x bin/sudo
PATH=$PWD/bin:$PATH
export PATH
# install nix on host (cf. https://nixos.org/nix/install)
if ! test -e /root/.nix-profile/etc/profile.d/nix.sh; then
(
verify() {
echo $nix_sha256 $(basename $nix_url) | sha256sum -c
}
if ! verify; then
curl -C - -O "$nix_url"
verify
fi
)
tar jxf $(basename $nix_url)
$(basename $nix_url .tar.bz2)/install
fi
MANPATH=/var/empty . /root/.nix-profile/etc/profile.d/nix.sh
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
fi
#
# mount install directory
#
if ! mount | grep -Fq '/dev/mapper/centos-root on /mnt type xfs'; then
mkdir -p /newshit
mount --bind /newshit /mnt
fi
if ! mount | grep -Fq '/dev/sda1 on /mnt/boot type xfs'; then
mkdir -p /mnt/boot
mount /dev/sda1 /mnt/boot
fi
if ! mount | grep -Fq '/dev/mapper/centos-root on /mnt/nix type xfs'; then
mkdir -p /mnt/nix
mount --bind /nix /mnt/nix
fi
mount | grep 'on /mnt\>' >&2
#
# prepare install directory
#
# XXX This should be done by (?)
# remote_dir=/mnt ./cac pushconfig servername:c731445864-cloudpro-134581046 rmdir
mkdir -p /mnt/etc/nixos
mkdir -m 0555 -p /mnt/var/empty
# add eye candy
address=$(echo $SSH_CONNECTION | awk '{print$3}')
echo 'PS1='\''\[\e[1;31m\]\u@'"$address"'\[\e[m\] \[\e[1;32m\]\w\[\e[m\] '\' > .bashrc
}

View File

@ -1,8 +0,0 @@
#! /bin/sh
# usage: cat infest-nixos-install.sh | ./cac ssh ...
set -euf
nixos-install \
-I secrets=/etc/nixos/secrets \
-I retiolum-hosts=/etc/nixos/hosts \
-I pubkeys=/etc/nixos/pubkeys \
-I nixpkgs=/etc/nixos/nixpkgs

View File

@ -1,62 +0,0 @@
{ lib, pkgs, ... }:
with builtins;
let
inherit (lib) mapAttrs stringAsChars;
in
rec {
git = import ./git.nix {
lib = lib // {
inherit addNames;
};
inherit pkgs;
};
addName = name: set:
set // { inherit name; };
addNames = mapAttrs addName;
# "7.4.335" -> "74"
majmin = with lib; x : concatStrings (take 2 (splitString "." x));
concat = xs :
if xs == []
then ""
else head xs + concat (tail xs)
;
flip = f : x : y : f y x;
# isSuffixOf :: String -> String -> Bool
isSuffixOf =
s : xs :
let
sn = stringLength s;
xsn = stringLength xs;
in
xsn >= sn && substring (xsn - sn) sn xs == s ;
removeSuffix =
s : xs : substring 0 (stringLength xs - stringLength s) xs;
# setMap :: (String -> a -> b) -> Set String a -> [b]
#setMap = f: xs: map (k : f k (getAttr k xs)) (attrNames xs);
# setToList :: Set k a -> [a]
#setToList = setMap (_: v: v);
shell-escape =
let
isSafeChar = c: match "[-./0-9_a-zA-Z]" c != null;
in
stringAsChars (c:
if isSafeChar c then c
else if c == "\n" then "'\n'"
else "\\${c}");
}

View File

@ -1,181 +0,0 @@
{ lib, pkgs, ... }:
let
inherit (lib) addNames escapeShellArg makeSearchPath;
commands = addNames {
git-receive-pack = {};
git-upload-pack = {};
};
receive-modes = addNames {
fast-forward = {};
non-fast-forward = {};
create = {};
delete = {};
merge = {}; # TODO implement in git.nix
};
permissions = {
fetch = {
allow-commands = [
commands.git-upload-pack
];
};
push = ref: extra-modes: {
allow-commands = [
commands.git-receive-pack
commands.git-upload-pack
];
allow-receive-ref = ref;
allow-receive-modes = [ receive-modes.fast-forward ] ++ extra-modes;
};
};
refs = {
master = "refs/heads/master";
all-heads = "refs/heads/*";
};
irc-announce-script = pkgs.writeScript "irc-announce-script" ''
#! /bin/sh
set -euf
export PATH=${makeSearchPath "bin" (with pkgs; [
coreutils
gawk
gnused
netcat
nettools
])}
IRC_SERVER=$1
IRC_PORT=$2
IRC_NICK=$3$$
IRC_CHANNEL=$4
message=$5
export IRC_CHANNEL # for privmsg_cat
# echo2 and cat2 are used output to both, stdout and stderr
# This is used to see what we send to the irc server. (debug output)
echo2() { echo "$*"; echo "$*" >&2; }
cat2() { tee /dev/stderr; }
# privmsg_cat transforms stdin to a privmsg
privmsg_cat() { awk '{ print "PRIVMSG "ENVIRON["IRC_CHANNEL"]" :"$0 }'; }
# ircin is used to feed the output of netcat back to the "irc client"
# so we can implement expect-like behavior with sed^_^
# XXX mkselfdestructingtmpfifo would be nice instead of this cruft
tmpdir="$(mktemp -d irc-announce_XXXXXXXX)"
cd "$tmpdir"
mkfifo ircin
trap "
rm ircin
cd '$OLDPWD'
rmdir '$tmpdir'
trap - EXIT INT QUIT
" EXIT INT QUIT
{
echo2 "USER $LOGNAME 0 * :$LOGNAME@$(hostname)"
echo2 "NICK $IRC_NICK"
# wait for MODE message
sed -n '/^:[^ ]* MODE /q'
echo2 "JOIN $IRC_CHANNEL"
printf '%s' "$message" \
| privmsg_cat \
| cat2
echo2 "PART $IRC_CHANNEL"
# wait for PART confirmation
sed -n '/:'"$IRC_NICK"'![^ ]* PART /q'
echo2 'QUIT :Gone to have lunch'
} < ircin \
| nc "$IRC_SERVER" "$IRC_PORT" | tee -a ircin
'';
hooks = {
# TODO make this a package?
irc-announce = { nick, channel, server, port ? 6667 }: ''
#! /bin/sh
set -euf
export PATH=${makeSearchPath "bin" (with pkgs; [
coreutils
git
gnused
])}
nick=${escapeShellArg nick}
channel=${escapeShellArg channel}
server=${escapeShellArg server}
port=${toString port}
host=$nick
empty=0000000000000000000000000000000000000000
unset message
while read oldrev newrev ref; do
if [ $oldrev = $empty ]; then
receive_mode=create
elif [ $newrev = $empty ]; then
receive_mode=delete
elif [ "$(git merge-base $oldrev $newrev)" = $oldrev ]; then
receive_mode=fast-forward
else
receive_mode=non-fast-forward
fi
h=$(echo $ref | sed 's:^refs/heads/::')
# empty_tree=$(git hash-object -t tree /dev/null
empty_tree=4b825dc6
id=$(echo $newrev | cut -b-7)
id2=$(echo $oldrev | cut -b-7)
if [ $newrev = $empty ]; then id=$empty_tree; fi
if [ $oldrev = $empty ]; then id2=$empty_tree; fi
case $receive_mode in
create)
#git log --oneline $id2
link="http://$host/cgit/$GIT_SSH_REPO/?h=$h"
;;
delete)
#git log --oneline $id2
link="http://$host/cgit/$GIT_SSH_REPO/ ($h)"
;;
fast-forward|non-fast-forward)
#git diff --stat $id..$id2
link="http://$host/cgit/$GIT_SSH_REPO/diff/?h=$h&id=$id&id2=$id2"
;;
esac
#$host $GIT_SSH_REPO $ref $link
message="''${message+$message
}$GIT_SSH_USER $receive_mode $link"
done
if test -n "''${message-}"; then
exec ${irc-announce-script} \
"$server" \
"$port" \
"$nick" \
"$channel" \
"$message"
fi
'';
};
in
commands // receive-modes // permissions // refs // hooks

View File

@ -1,21 +0,0 @@
let
pkgs = import <nixpkgs> {};
inherit (pkgs.lib) concatMap hasAttr;
in rec {
no-touch-args = {
config = throw "no-touch-args: can't touch config!";
lib = throw "no-touch-args: can't touch lib!";
pkgs = throw "no-touch-args: can't touch pkgs!";
};
# list-imports : path -> [path]
# Return a module's transitive list of imports.
# XXX duplicates won't get eliminated from the result.
list-imports = path:
let module = import path no-touch-args;
imports = if hasAttr "imports" module
then concatMap list-imports module.imports
else [];
in [path] ++ imports;
}

View File

@ -1,91 +0,0 @@
{ config, pkgs, ... }:
let
inherit (builtins) readFile;
in
{
imports =
[
{ users.extraUsers = import <secrets/extraUsers.nix>; }
./networking.nix
./users.nix
../tv/base.nix
../tv/base-cac-CentOS-7-64bit.nix
../tv/config/consul-server.nix
../tv/ejabberd.nix # XXX echtes modul
../tv/exim-smarthost.nix
../tv/git/public.nix
../tv/sanitize.nix
{
imports = [ ../tv/identity ];
tv.identity = {
enable = true;
self = config.tv.identity.hosts.cd;
};
}
{
imports = [ ../tv/iptables ];
tv.iptables = {
enable = true;
input-internet-accept-new-tcp = [
"ssh"
"tinc"
"smtp"
"xmpp-client"
"xmpp-server"
];
input-retiolum-accept-new-tcp = [
"http"
];
};
}
{
imports = [ ../tv/retiolum ];
tv.retiolum = {
enable = true;
hosts = <retiolum-hosts>;
connectTo = [
"fastpoke"
"pigstarter"
"ire"
];
};
}
];
# "Developer 2" plan has two vCPUs.
nix.maxJobs = 2;
environment.systemPackages = with pkgs; [
git # required for ./deploy, clone_or_update
htop
iftop
iotop
iptables
mutt # for mv
nethogs
rxvt_unicode.terminfo
tcpdump
];
services.ejabberd-cd = {
enable = true;
};
services.journald.extraConfig = ''
SystemMaxUse=1G
RuntimeMaxUse=128M
'';
services.openssh = {
enable = true;
hostKeys = [
# XXX bits here make no science
{ bits = 8192; type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; }
];
permitRootLogin = "yes";
};
sound.enable = false;
}

View File

@ -1,14 +0,0 @@
{...}:
{
networking.hostName = "cd";
networking.interfaces.enp2s1.ip4 = [
{
address = "162.219.7.216";
prefixLength = 24;
}
];
networking.defaultGateway = "162.219.7.1";
networking.nameservers = [
"8.8.8.8"
];
}

View File

@ -1,12 +0,0 @@
{
lib.file.url = ../../lib;
modules.file.url = ../../modules;
nixpkgs.git = {
url = https://github.com/NixOS/nixpkgs;
rev = "4c01e6d91993b6de128795f4fbdd25f6227fb870";
cache = ../../tmp/git-cache;
};
pubkeys.file.url = ../../pubkeys;
retiolum-hosts.file.url = ../../hosts;
secrets.file.url = ../../secrets/cd/nix;
}

View File

@ -1,53 +0,0 @@
{ ... }:
let
inherit (builtins) readFile;
in
{
users.extraGroups = {
# ● systemd-tmpfiles-setup.service - Create Volatile Files and Directories
# Loaded: loaded (/nix/store/2l33gg7nmncqkpysq9f5fxyhlw6ncm2j-systemd-217/example/systemd/system/systemd-tmpfiles-setup.service)
# Active: failed (Result: exit-code) since Mon 2015-03-16 10:29:18 UTC; 4s ago
# Docs: man:tmpfiles.d(5)
# man:systemd-tmpfiles(8)
# Process: 19272 ExecStart=/nix/store/2l33gg7nmncqkpysq9f5fxyhlw6ncm2j-systemd-217/bin/systemd-tmpfiles --create --remove --boot --exclude-prefix=/dev (code=exited, status=1/FAILURE)
# Main PID: 19272 (code=exited, status=1/FAILURE)
#
# Mar 16 10:29:17 cd systemd-tmpfiles[19272]: [/usr/lib/tmpfiles.d/legacy.conf:26] Unknown group 'lock'.
# Mar 16 10:29:18 cd systemd-tmpfiles[19272]: Two or more conflicting lines for /var/log/journal configured, ignoring.
# Mar 16 10:29:18 cd systemd-tmpfiles[19272]: Two or more conflicting lines for /var/log/journal/7b35116927d74ea58785e00b47ac0f0d configured, ignoring.
# Mar 16 10:29:18 cd systemd[1]: systemd-tmpfiles-setup.service: main process exited, code=exited, status=1/FAILURE
# Mar 16 10:29:18 cd systemd[1]: Failed to start Create Volatile Files and Directories.
# Mar 16 10:29:18 cd systemd[1]: Unit systemd-tmpfiles-setup.service entered failed state.
# Mar 16 10:29:18 cd systemd[1]: systemd-tmpfiles-setup.service failed.
# warning: error(s) occured while switching to the new configuration
lock.gid = 10001;
};
users.extraUsers =
{
root = {
openssh.authorizedKeys.keys = [
(readFile <pubkeys/deploy_wu.ssh.pub>)
(readFile <pubkeys/tv_wu.ssh.pub>)
];
};
mv = rec {
name = "mv";
uid = 1338;
group = "users";
home = "/home/${name}";
createHome = true;
useDefaultShell = true;
openssh.authorizedKeys.keys = [
(readFile <pubkeys/mv_vod.ssh.pub>)
];
};
};
users.mutableUsers = false;
}

View File

@ -1,71 +0,0 @@
{ config, pkgs, ... }:
{
imports = [
../tv/base-cac-CentOS-7-64bit.nix
./retiolum.nix
./networking.nix
../../secrets/cloudkrebs-pw.nix
../lass/sshkeys.nix
../lass/base.nix
../common/nixpkgs.nix
];
nixpkgs = {
url = "https://github.com/Lassulus/nixpkgs";
rev = "b42ecfb8c61e514bf7733b4ab0982d3e7e27dacb";
};
nix.maxJobs = 1;
#tmpfiles Unknown group 'lock' workaround:
users.extraGroups = {
lock.gid = 10001;
};
#TODO move into modules
users.extraUsers = {
#main user
root = {
openssh.authorizedKeys.keys = [
config.sshKeys.lass.pub
];
};
mainUser = {
uid = 1337;
name = "lass";
#isNormalUser = true;
group = "users";
createHome = true;
home = "/home/lass";
useDefaultShell = true;
isSystemUser = false;
description = "lassulus";
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [
config.sshKeys.lass.pub
];
};
};
environment.systemPackages = with pkgs; [
];
services.openssh = {
enable = true;
hostKeys = [
# XXX bits here make no science
{ bits = 8192; type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; }
];
permitRootLogin = "yes";
};
networking.firewall = {
enable = true;
allowedTCPPorts = [
22
];
};
}

View File

@ -1,14 +0,0 @@
{...}:
{
networking.hostName = "cloudkrebs";
networking.interfaces.enp2s1.ip4 = [
{
address = "104.167.113.104";
prefixLength = 24;
}
];
networking.defaultGateway = "104.167.113.1";
networking.nameservers = [
"8.8.8.8"
];
}

View File

@ -1,21 +0,0 @@
{ config, pkgs, ... }:
{
imports = [
../tv/retiolum
];
tv.retiolum = {
enable = true;
hosts = ../../hosts;
privateKeyFile = "/etc/nixos/secrets/cloudkrebs.retiolum.rsa_key.priv";
connectTo = [
"fastpoke"
"gum"
"ire"
];
};
networking.firewall.allowedTCPPorts = [ 655 ];
networking.firewall.allowedUDPPorts = [ 655 ];
}

View File

@ -1,18 +0,0 @@
# alle public keys der krebsminister fuer R in krebs repos
{ config, ... }:
let
inherit (builtins) readFile;
in
with import ../lass/sshkeys.nix {
config.sshKeys.lass.pub = config.sshKeys.lass.pub;
config.sshKeys.uriel.pub = config.sshKeys.uriel.pub;
};
{
imports = [
./sshkeys.nix
];
config.sshKeys.tv.pub = readFile <pubkeys/tv_wu.ssh.pub>;
}

View File

@ -1,36 +0,0 @@
{ lib, ... }:
let
inherit (lib) mkDefault;
mkSecureRepo = name:
{ inherit name;
value = {
users = {
lass = mkDefault "R";
tv = mkDefault "R";
makefu = mkDefault "R";
};
};
};
mkRepo = name:
{ inherit name;
value = {
users = {
lass = mkDefault "R";
tv = mkDefault "R";
makefu = mkDefault "R";
};
};
};
in {
services.gitolite.repos =
(lib.listToAttrs (map mkSecureRepo [ "brain" ])) //
(lib.listToAttrs (map mkRepo [
"painload"
"services"
"hosts"
]));
}

View File

@ -1,25 +0,0 @@
{ lib, ... }:
with lib;
{
options = {
nixpkgs.url = mkOption {
type = types.str;
description = "URL of the nixpkgs repository.";
};
nixpkgs.rev = mkOption {
type = types.str;
default = "origin/master";
description = "Revision of the remote repository.";
};
nixpkgs.dirty = mkOption {
type = types.bool;
default = false;
description = ''
If nixpkgs.url is a local path, then use that as it is.
TODO this break if URL is not a local path.
'';
};
};
}

View File

@ -1,26 +0,0 @@
{ lib, ... }:
with lib;
{
options = {
sshKeys = mkOption {
type = types.attrsOf (types.submodule (
{ config, ... }:
{
options = {
pub = mkOption {
type = types.str;
description = "Public part of the ssh key.";
};
priv = mkOption {
type = types.str;
description = "Private part of the ssh key.";
};
};
}));
description = "collection of ssh-keys";
};
};
}

View File

@ -1,129 +0,0 @@
{ config, pkgs, ... }:
{
imports = [
./sshkeys.nix
./iptables
];
nix.useChroot = true;
users.mutableUsers = false;
boot.tmpOnTmpfs = true;
# see tmpfiles.d(5)
systemd.tmpfiles.rules = [
"d /tmp 1777 root root - -"
];
# multiple-definition-problem when defining environment.variables.EDITOR
environment.extraInit = ''
EDITOR=vim
PAGER=most
'';
environment.systemPackages = with pkgs; [
git
most
rxvt_unicode.terminfo
#network
iptables
];
programs.bash = {
enableCompletion = true;
interactiveShellInit = ''
HISTCONTROL='erasedups:ignorespace'
HISTSIZE=65536
HISTFILESIZE=$HISTSIZE
shopt -s checkhash
shopt -s histappend histreedit histverify
shopt -s no_empty_cmd_completion
complete -d cd
#fancy colors
if [ -e ~/LS_COLORS ]; then
eval $(dircolors ~/LS_COLORS)
fi
if [ -e /etc/nixos/dotfiles/link ]; then
/etc/nixos/dotfiles/link
fi
'';
promptInit = ''
if test $UID = 0; then
PS1='\[\033[1;31m\]\w\[\033[0m\] '
elif test $UID = 1337; then
PS1='\[\033[1;32m\]\w\[\033[0m\] '
else
PS1='\[\033[1;33m\]\u@\w\[\033[0m\] '
fi
if test -n "$SSH_CLIENT"; then
PS1='\[\033[35m\]\h'" $PS1"
fi
'';
};
security.setuidPrograms = [
"sendmail"
];
services.gitolite = {
enable = true;
dataDir = "/home/gitolite";
adminPubkey = config.sshKeys.lass.pub;
};
services.openssh = {
enable = true;
hostKeys = [
# XXX bits here make no science
{ bits = 8192; type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; }
];
};
services.journald.extraConfig = ''
SystemMaxUse=1G
RuntimeMaxUse=128M
'';
lass.iptables = {
enable = true;
tables = {
filter.INPUT.policy = "DROP";
filter.FORWARD.policy = "DROP";
filter.INPUT.rules = [
{ predicate = "-i lo"; target = "ACCEPT"; }
{ predicate = "-m conntrack --ctstate RELATED,ESTABLISHED"; target = "ACCEPT"; }
{ predicate = "-p icmp"; target = "ACCEPT"; }
{ predicate = "-p tcp --dport 22"; target = "ACCEPT"; }
];
};
};
#Networking.firewall = {
# enable = true;
# allowedTCPPorts = [
# 22
# ];
# extraCommands = ''
# iptables -A INPUT -j ACCEPT -m conntrack --ctstate RELATED,ESTABLISHED
# iptables -A INPUT -j ACCEPT -i lo
# #http://serverfault.com/questions/84963/why-not-block-icmp
# iptables -A INPUT -j ACCEPT -p icmp
# #TODO: fix Retiolum firewall
# #iptables -N RETIOLUM
# #iptables -A INPUT -j RETIOLUM -i retiolum
# #iptables -A RETIOLUM -j ACCEPT -m conntrack --ctstate RELATED,ESTABLISHED
# #iptables -A RETIOLUM -j REJECT -p tcp --reject-with tcp-reset
# #iptables -A RETIOLUM -j REJECT -p udp --reject-with icmp-port-unreachable
# #iptables -A RETIOLUM -j REJECT --reject-with icmp-proto-unreachable
# #iptables -A RETIOLUM -j REJECT
# '';
#};
}

View File

@ -1,13 +0,0 @@
{ config, ... }:
{
nix.sshServe.enable = true;
nix.sshServe.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBF9SBNKE3Pw/ALwTfzpzs+j6Rpaf0kUy6FiPMmgNNNt root@mors"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFCZSq5oLrokkh3F+MOdK5/nzVIEDvqyvfzLMNWmzsYD root@uriel"
];
nix.binaryCaches = [
#"scp://nix-ssh@mors"
#"scp://nix-ssh@uriel"
];
}

View File

@ -1,13 +0,0 @@
{ config, ... }:
{
config.services.bird = {
enable = true;
config = ''
router id 192.168.122.1;
protocol device {
scan time 10;
}
'';
};
}

View File

@ -1,17 +0,0 @@
{ config, pkgs, ... }:
{
environment.systemPackages = with pkgs; [
electrum
];
users.extraUsers = {
bitcoin = {
name = "bitcoin";
description = "user for bitcoin stuff";
home = "/home/bitcoin";
useDefaultShell = true;
createHome = true;
};
};
}

View File

@ -1,67 +0,0 @@
{ config, pkgs, ... }:
let
mainUser = config.users.extraUsers.mainUser;
in {
nixpkgs.config.packageOverrides = pkgs : {
chromium = pkgs.chromium.override {
pulseSupport = true;
};
};
environment.systemPackages = with pkgs; [
firefox
];
users.extraUsers = {
firefox = {
name = "firefox";
description = "user for running firefox";
home = "/home/firefox";
useDefaultShell = true;
extraGroups = [ "audio" ];
createHome = true;
};
chromium = {
name = "chromium";
description = "user for running chromium";
home = "/home/chromium";
useDefaultShell = true;
extraGroups = [ "audio" ];
createHome = true;
};
facebook = {
name = "facebook";
description = "user for running facebook in chromium";
home = "/home/facebook";
useDefaultShell = true;
extraGroups = [ "audio" ];
createHome = true;
};
google = {
name = "google";
description = "user for running google+/gmail in chromium";
home = "/home/google";
useDefaultShell = true;
createHome = true;
};
flash = {
name = "flash";
description = "user for running flash stuff";
home = "/home/flash";
useDefaultShell = true;
extraGroups = [ "audio" ];
createHome = true;
};
};
security.sudo.extraConfig = ''
${mainUser.name} ALL=(firefox) NOPASSWD: ALL
${mainUser.name} ALL=(chromium) NOPASSWD: ALL
${mainUser.name} ALL=(facebook) NOPASSWD: ALL
${mainUser.name} ALL=(google) NOPASSWD: ALL
${mainUser.name} ALL=(flash) NOPASSWD: ALL
'';
}

View File

@ -1,48 +0,0 @@
{ config, pkgs, ... }:
#settings to test:
#
#"ForceEphemeralProfiles": true,
let
masterPolicy = pkgs.writeText "master.json" ''
{
"PasswordManagerEnabled": false,
"DefaultGeolocationSetting": 2,
"RestoreOnStartup": 1,
"AutoFillEnabled": false,
"BackgroundModeEnabled": false,
"DefaultBrowserSettingEnabled": false,
"SafeBrowsingEnabled": false,
"ExtensionInstallForcelist": [
"cjpalhdlnbpafiamejdnhcphjbkeiagm;https://clients2.google.com/service/update2/crx",
"ihlenndgcmojhcghmfjfneahoeklbjjh;https://clients2.google.com/service/update2/crx"
]
}
'';
master_preferences = pkgs.writeText "master_preferences" ''
{
"browser": {
"custom_chrome_frame": true
},
"extensions": {
"theme": {
"id": "",
"use_system": true
}
}
}
'';
in {
environment.etc."chromium/policies/managed/master.json".source = pkgs.lib.mkForce masterPolicy;
environment.systemPackages = [
#pkgs.chromium
(pkgs.lib.overrideDerivation pkgs.chromium (attrs: {
buildCommand = attrs.buildCommand + ''
touch $out/TEST123
'';
}))
];
}

View File

@ -1,65 +0,0 @@
{ config, pkgs, ... }:
let
mainUser = config.users.extraUsers.mainUser;
in {
imports = [
./base.nix
];
time.timeZone = "Europe/Berlin";
virtualisation.libvirtd.enable = true;
hardware.pulseaudio = {
enable = true;
systemWide = true;
};
programs.ssh.startAgent = false;
security.setuidPrograms = [ "slock" ];
services.printing = {
enable = true;
drivers = [ pkgs.foomatic_filters ];
};
environment.systemPackages = with pkgs; [
powertop
#window manager stuff
haskellPackages.xmobar
haskellPackages.yeganesh
dmenu2
xlibs.fontschumachermisc
];
fonts.fonts = [
pkgs.xlibs.fontschumachermisc
];
services.xserver = {
enable = true;
windowManager.xmonad.extraPackages = hspkgs: with hspkgs; [
X11-xshape
];
windowManager.xmonad.enable = true;
windowManager.xmonad.enableContribAndExtras = true;
windowManager.default = "xmonad";
desktopManager.default = "none";
desktopManager.xterm.enable = false;
displayManager.slim.enable = true;
displayManager.auto.enable = true;
displayManager.auto.user = mainUser.name;
layout = "us,de";
xkbModel = "evdev";
xkbVariant = "altgr-intl,nodeadkeys";
xkbOptions = "grp:caps_toggle";
};
}

View File

@ -1,20 +0,0 @@
{ config, pkgs, ... }:
let
mainUser = config.users.extraUsers.mainUser;
in {
users.extraUsers = {
elster = {
name = "elster";
description = "user for running elster-online";
home = "/home/elster";
useDefaultShell = true;
extraGroups = [];
createHome = true;
};
};
security.sudo.extraConfig = ''
${mainUser.name} ALL=(elster) NOPASSWD: ALL
'';
}

View File

@ -1,25 +0,0 @@
{ config, pkgs, ... }:
let
mainUser = config.users.extraUsers.mainUser;
in {
environment.systemPackages = with pkgs; [
dwarf_fortress
];
users.extraUsers = {
games = {
name = "games";
description = "user playing games";
home = "/home/games";
extraGroups = [ "audio" "video" "input" ];
createHome = true;
useDefaultShell = true;
};
};
security.sudo.extraConfig = ''
${mainUser.name} ALL=(games) NOPASSWD: ALL
'';
}

View File

@ -1,173 +0,0 @@
{ config, ... }:
{
services.gitolite = {
mutable = false;
keys = {
lass = config.sshKeys.lass.pub;
uriel = config.sshKeys.uriel.pub;
};
rc = ''
%RC = (
UMASK => 0077,
GIT_CONFIG_KEYS => "",
LOG_EXTRA => 1,
ROLES => {
READERS => 1,
WRITERS => 1,
},
LOCAL_CODE => "$ENV{HOME}/.gitolite",
ENABLE => [
'help',
'desc',
'info',
'perms',
'writable',
'ssh-authkeys',
'git-config',
'daemon',
'gitweb',
'repo-specific-hooks',
],
);
1;
'';
repoSpecificHooks = {
irc-announce = ''
#! /bin/sh
set -euf
config_file="$GL_ADMIN_BASE/conf/irc-announce.conf"
if test -f "$config_file"; then
. "$config_file"
fi
# XXX when changing IRC_CHANNEL or IRC_SERVER/_PORT, don't forget to update
# any relevant gitolite LOCAL_CODE!
# CAVEAT we hope that IRC_NICK is unique
IRC_NICK="''${IRC_NICK-gl$GL_TID}"
IRC_CHANNEL="''${IRC_CHANNEL-#retiolum}"
IRC_SERVER="''${IRC_SERVER-ire.retiolum}"
IRC_PORT="''${IRC_PORT-6667}"
# for privmsg_cat below
export IRC_CHANNEL
# collect users that are mentioned in the gitolite configuration
interested_users="$(perl -e '
do "gl-conf";
print join(" ", keys%{ $one_repo{$ENV{"GL_REPO"}} });
')"
# CAVEAT beware of real TABs in grep pattern!
# CAVEAT there will never be more than 42 relevant log entries!
tab=$(printf '\x09')
log="$(tail -n 42 "$GL_LOGFILE" | grep "^[^$tab]*$tab$GL_TID$tab" || :)"
update_log="$(echo "$log" | grep "^[^$tab]*$tab$GL_TID''${tab}update")"
# (debug output)
env | sed 's/^/env: /'
echo "$log" | sed 's/^/log: /'
# see http://gitolite.com/gitolite/dev-notes.html#lff
reponame=$(echo "$update_log" | cut -f 4)
username=$(echo "$update_log" | cut -f 5)
ref_name=$(echo "$update_log" | cut -f 7 | sed 's|^refs/heads/||')
old_sha=$(echo "$update_log" | cut -f 8)
new_sha=$(echo "$update_log" | cut -f 9)
# check if new branch is created
if test $old_sha = 0000000000000000000000000000000000000000; then
# TODO what should we really show?
old_sha=$new_sha^
fi
#
git_log="$(git log $old_sha..$new_sha --pretty=oneline --abbrev-commit)"
commit_count=$(echo "$git_log" | wc -l)
# echo2 and cat2 are used output to both, stdout and stderr
# This is used to see what we send to the irc server. (debug output)
echo2() { echo "$*"; echo "$*" >&2; }
cat2() { tee /dev/stderr; }
# privmsg_cat transforms stdin to a privmsg
privmsg_cat() { awk '{ print "PRIVMSG "ENVIRON["IRC_CHANNEL"]" :"$0 }'; }
# ircin is used to feed the output of netcat back to the "irc client"
# so we can implement expect-like behavior with sed^_^
# XXX mkselfdestructingtmpfifo would be nice instead of this cruft
tmpdir="$(mktemp -d irc-announce_XXXXXXXX)"
cd "$tmpdir"
mkfifo ircin
trap "
rm ircin
cd '$OLDPWD'
rmdir '$tmpdir'
trap - EXIT INT QUIT
" EXIT INT QUIT
#
#
#
{
echo2 "USER $LOGNAME 0 * :$LOGNAME@$(hostname)"
echo2 "NICK $IRC_NICK"
# wait for MODE message
sed -n '/^:[^ ]* MODE /q'
echo2 "JOIN $IRC_CHANNEL"
echo "$interested_users" \
| tr ' ' '\n' \
| grep -v "^$GL_USER" \
| sed 's/$/: poke/' \
| privmsg_cat \
| cat2
printf '[\x0313%s\x03] %s pushed %s new commit%s to \x036%s %s\x03\n' \
"$reponame" \
"$username" \
"$commit_count" \
"$(test $commit_count = 1 || echo s)" \
"$(hostname)" \
"$ref_name" \
| privmsg_cat \
| cat2
echo "$git_log" \
| sed 's/^/\x0314/;s/ /\x03 /' \
| privmsg_cat \
| cat2
echo2 "PART $IRC_CHANNEL"
# wait for PART confirmation
sed -n '/:'"$IRC_NICK"'![^ ]* PART /q'
echo2 'QUIT :Gone to have lunch'
} < ircin \
| nc "$IRC_SERVER" "$IRC_PORT" | tee -a ircin
'';
};
customFiles = [
{
path = ".gitolite/conf/irc-announce.conf";
file = ''
IRC_NICK="$(hostname)$GL_TID"
case "$GL_REPO" in
brain|painload|services|load-env|config)
IRC_CHANNEL='#retiolum'
;;
*)
IRC_CHANNEL='&testing'
;;
esac
'';
}
];
};
}

View File

@ -1,119 +0,0 @@
{ cfg, lib, pkgs, ... }:
let
inherit (pkgs) writeScript writeText;
inherit (lib) concatMapStringsSep concatStringsSep attrNames unique fold any attrValues catAttrs filter flatten length hasAttr;
#===== new api v4
#buildTable :: iptablesAttrSet` -> str
#todo: differentiate by iptables-version
buildTables = iptv: ts:
let
declareChain = t: cn:
#TODO: find out what to do whit these count numbers
":${cn} ${t."${cn}".policy} [0:0]";
buildChain = tn: cn:
#"${concatStringsSep " " ((attrNames t."${cn}") ++ [cn])}";
#TODO: sort by precedence
#TODO: double check should be unneccessary, refactor!
if (hasAttr "rules" ts."${tn}"."${cn}") then
if (ts."${tn}"."${cn}".rules == null) then
""
else
concatMapStringsSep "\n" (rule: "\n-A ${cn} ${rule}") ([]
++ map buildRule ts."${tn}"."${cn}".rules
)
else
""
;
buildRule = rule:
#TODO implement rule validation-test here
#
#target:
#target needs to be an existing chain (in the same table) or ACCEPT, REJECT, DROP, LOG, QUEUE, RETURN
#predicate:
#maybe use iptables-test
#TODO: howto exit with evaluation error by shellscript?
#apperantly not possible from nix because evalatution wouldn't be deterministic.
"${rule.predicate} -j ${rule.target}";
buildTable = tn:
"*${tn}\n" +
concatStringsSep "\n" ([]
++ map (declareChain ts."${tn}") (attrNames ts."${tn}")
) +
#this looks dirty, find a better way to do this (maybe optionalString)
concatStringsSep "" ([]
++ map (buildChain tn) (attrNames ts."${tn}")
) +
"\nCOMMIT";
in
concatStringsSep "\n" ([]
++ map buildTable (attrNames ts)
);
#=====
rules4 = iptables-version:
let
#TODO: find out good defaults.
tables-defaults = {
nat.PREROUTING.policy = "ACCEPT";
nat.INPUT.policy = "ACCEPT";
nat.OUTPUT.policy = "ACCEPT";
nat.POSTROUTING.policy = "ACCEPT";
filter.INPUT.policy = "ACCEPT";
filter.FORWARD.policy = "ACCEPT";
filter.OUTPUT.policy = "ACCEPT";
#if someone specifies any other rules on this chain, the default rules get lost.
#is this wanted beahiviour or a bug?
#TODO: implement abstraction of rules
filter.INPUT.rules = [
{ predicate = "-m conntrack --ctstate RELATED,ESTABLISHED"; target = "ACCEPT"; }
];
};
tables = tables-defaults // cfg.tables;
in
writeText "lass-iptables-rules${toString iptables-version}" ''
${buildTables iptables-version tables}
'';
startScript = writeScript "lass-iptables_start" ''
#! /bin/sh
set -euf
iptables-restore < ${rules4 4}
ip6tables-restore < ${rules4 6}
'';
in
{
networking.firewall.enable = false;
systemd.services.lass-iptables = {
description = "lass-iptables";
wantedBy = [ "network-pre.target" ];
before = [ "network-pre.target" ];
after = [ "systemd-modules-load.service" ];
path = with pkgs; [
iptables
];
restartIfChanged = true;
serviceConfig = {
Type = "simple";
RemainAfterExit = true;
Restart = "always";
ExecStart = "@${startScript} lass-iptables_start";
};
};
}

View File

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

View File

@ -1,44 +0,0 @@
{ lib, ... }:
let
inherit (lib) mkEnableOption mkOption types;
in
{
enable = mkEnableOption "iptables";
#tables.filter.INPUT = {
# policy = "DROP";
# rules = [
# { predicate = "-i retiolum"; target = "ACCEPT"; priority = -10; }
# ];
#};
#new api
tables = mkOption {
type = with types; attrsOf (attrsOf (submodule ({
options = {
policy = mkOption {
type = str;
default = "-";
};
rules = mkOption {
type = nullOr (listOf (submodule ({
options = {
predicate = mkOption {
type = str;
};
target = mkOption {
type = str;
};
precedence = mkOption {
type = int;
default = 0;
};
};
})));
default = null;
};
};
})));
};
}

View File

@ -1,88 +0,0 @@
{ config, pkgs, ... }:
{
config.services.charybdis = {
enable = true;
config = ''
serverinfo {
name = "ire.irc.retiolum";
sid = "4z3";
description = "miep!";
network_name = "irc.retiolum";
network_desc = "Retiolum IRC Network";
hub = yes;
vhost = "0.0.0.0";
vhost6 = "::";
#ssl_private_key = "etc/ssl.key";
#ssl_cert = "etc/ssl.cert";
#ssl_dh_params = "etc/dh.pem";
#ssld_count = 1;
default_max_clients = 10000;
#nicklen = 30;
};
listen {
defer_accept = yes;
/* If you want to listen on a specific IP only, specify host.
* host definitions apply only to the following port line.
*/
host = "0.0.0.0";
port = 6667;
sslport = 6697;
/* Listen on IPv6 (if you used host= above). */
host = "::";
port = 6667;
sslport = 9999;
};
class "users" {
ping_time = 2 minutes;
number_per_ident = 200;
number_per_ip = 200;
number_per_ip_global = 500;
cidr_ipv4_bitlen = 24;
cidr_ipv6_bitlen = 64;
number_per_cidr = 9000;
max_number = 10000;
sendq = 400 kbytes;
};
exempt {
ip = "127.0.0.1";
};
auth {
user = "*@*";
class = "users";
flags = exceed_limit;
};
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;
};
'';
};
}

View File

@ -1,10 +0,0 @@
{ config, pkgs, ... }:
{
environment.systemPackages = with pkgs; [
pass
gnupg1
];
services.xserver.startGnuPGAgent = true;
}

View File

@ -1,24 +0,0 @@
{ config, pkgs, ... }:
## TODO sort and split up
{
environment.systemPackages = with pkgs; [
aria2
gnupg1compat
htop
i3lock
mc
mosh
mpv
pass
pavucontrol
pv
pwgen
python34Packages.livestreamer
remmina
silver-searcher
wget
xsel
youtube-dl
];
}

View File

@ -1,11 +0,0 @@
{ config, ... }:
{
imports = [
../common/sshkeys.nix
];
config.sshKeys.lass.pub = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAp83zynhIueJJsWlSEykVSBrrgBFKq38+vT8bRfa+csqyjZBl2SQFuCPo+Qbh49mwchpZRshBa9jQEIGqmXxv/PYdfBFQuOFgyUq9ZcTZUXqeynicg/SyOYFW86iiqYralIAkuGPfQ4howLPVyjTZtWeEeeEttom6p6LMY5Aumjz2em0FG0n9rRFY2fBzrdYAgk9C0N6ojCs/Gzknk9SGntA96MDqHJ1HXWFMfmwOLCnxtE5TY30MqSmkrJb7Fsejwjoqoe9Y/mCaR0LpG2cStC1+37GbHJNH0caCMaQCX8qdfgMVbWTVeFWtV6aWOaRgwLrPDYn4cHWQJqTfhtPrNQ== lass@mors";
config.sshKeys.uriel.pub = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDExWuRcltGM2FqXO695nm6/QY3wU3r1bDTyCpMrLfUSym7TxcXDSmZSWcueexPXV6GENuUfjJPZswOdWqIo5u2AXw9t0aGvwEDmI6uJ7K5nzQOsXIneGMdYuoOaAzWI8pxZ4N+lIP1HsOYttIPDp8RwU6kyG+Ud8mnVHWSTO13C7xC9vePnDP6b+44nHS691Zj3X/Cq35Ls0ISC3EM17jreucdP62L3TKk2R4NCm3Sjqj+OYEv0LAqIpgqSw5FypTYQgNByxRcIcNDlri63Q1yVftUP1338UiUfxtraUu6cqa2CdsHQmtX5mTNWEluVWO3uUKTz9zla3rShC+d3qvr lass@uriel";
}

View File

@ -1,29 +0,0 @@
{ config, pkgs, ... }:
{
imports = [
./games.nix
];
#
# Steam stuff
# source: https://nixos.org/wiki/Talk:Steam
#
##TODO: make steam module
hardware.opengl.driSupport32Bit = true;
environment.systemPackages = with pkgs; [
steam
];
networking.firewall = {
allowedUDPPorts = [
27031
27036
];
allowedTCPPorts = [
27036
27037
];
};
}

View File

@ -1,7 +0,0 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
(pkgs.texLiveAggregationFun { paths = [ pkgs.texLive pkgs.texLiveFull ]; })
];
}

View File

@ -1,40 +0,0 @@
{ config, pkgs, ... }:
let
inherit (config.users.extraUsers) mainUser;
in
{
imports = [
./urxvtd.nix
./xresources.nix
];
services.urxvtd = {
enable = true;
users = [ mainUser.name ];
urxvtPackage = pkgs.rxvt_unicode_with-plugins;
};
services.xresources.enable = true;
services.xresources.resources.urxvt = ''
URxvt*scrollBar: false
URxvt*urgentOnBell: true
URxvt*font: -*-clean-*-*-*-*-*-*-*-*-*-*-iso10646-*
URxvt*boldFont: -*-clean-*-*-*-*-*-*-*-*-*-*-iso10646-*
URxvt.perl-ext-common: default,clipboard,url-select,keyboard-select
URxvt.url-select.launcher: browser-select
URxvt.url-select.underline: true
URxvt.keysym.M-u: perl:url-select:select_next
URxvt.keysym.M-Escape: perl:keyboard-select:activate
URxvt.keysym.M-s: perl:keyboard-select:search
URxvt.intensityStyles: false
URxvt*background: #000000
URxvt*foreground: #ffffff
!change unreadable blue
URxvt*color4: #268bd2
'';
}

View File

@ -1,55 +0,0 @@
{ config, lib, pkgs, ... }:
let
in
with builtins;
with lib;
{
options = {
services.urxvtd = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable urxvtd per user";
};
users = mkOption {
type = types.listOf types.string;
default = [];
description = "users to run urxvtd for";
};
urxvtPackage = mkOption {
type = types.package;
default = pkgs.rxvt_unicode;
description = "urxvt package to use";
};
};
};
config =
let
cfg = config.services.urxvtd;
users = cfg.users;
urxvt = cfg.urxvtPackage;
mkService = user: {
description = "urxvt terminal daemon";
wantedBy = [ "multi-user.target" ];
restartIfChanged = false;
path = [ pkgs.xlibs.xrdb ];
environment = {
DISPLAY = ":0";
URXVT_PERL_LIB = "${urxvt}/lib/urxvt/perl";
};
serviceConfig = {
Restart = "always";
User = user;
ExecStart = "${urxvt}/bin/urxvtd";
};
};
in
mkIf cfg.enable {
environment.systemPackages = [ urxvt ];
systemd.services = listToAttrs (map (u: { name = "${u}-urxvtd"; value = mkService u; }) users);
};
}

View File

@ -1,118 +0,0 @@
{ config, pkgs, ... }:
let
customPlugins.mustang2 = pkgs.vimUtils.buildVimPlugin {
name = "Mustang2";
src = pkgs.fetchFromGitHub {
owner = "croaker";
repo = "mustang-vim";
rev = "6533d7d21bf27cae94d9c2caa575f627f003dfd5";
sha256 = "0zlmcrr04j3dkiivrhqi90f618lmnnnpvbz1b9msfs78cmgw9w67";
};
};
in {
environment.systemPackages = [
(pkgs.vim_configurable.customize {
name = "vim";
vimrcConfig.customRC = ''
set nocompatible
set t_Co=16
syntax on
" TODO autoload colorscheme file
set background=dark
colorscheme mustang
filetype off
filetype plugin indent on
imap <F1> <nop>
set mouse=a
set ruler
set showmatch
set backspace=2
set visualbell
set encoding=utf8
set showcmd
set wildmenu
set title
set titleold=
set titlestring=%t%(\ %M%)%(\ (%{expand(\"%:p:h\")})%)%(\ %a%)\ -\ %{v:servername}
set autoindent
set ttyfast
set pastetoggle=<INS>
" Force Saving Files that Require Root Permission
command! W silent w !sudo tee "%" >/dev/null
nnoremap <C-c> :q<Return>
vnoremap < <gv
vnoremap > >gv
nmap <esc>q :buffer
"Tabwidth
set ts=2 sts=2 sw=2 et
" create Backup/tmp/undo dirs
function! InitBackupDir()
let l:parent = $HOME . '/.vim/'
let l:backup = l:parent . 'backups/'
let l:tmpdir = l:parent . 'tmp/'
let l:undodi = l:parent . 'undo/'
if !isdirectory(l:parent)
call mkdir(l:parent)
endif
if !isdirectory(l:backup)
call mkdir(l:backup)
endif
if !isdirectory(l:tmpdir)
call mkdir(l:tmpdir)
endif
if !isdirectory(l:undodi)
call mkdir(l:undodi)
endif
endfunction
call InitBackupDir()
" Backups & Files
set backup
set backupdir=~/.vim/backups
set directory=~/.vim/tmp//
set viminfo='20,<1000,s100,h,n~/.vim/tmp/info
set undodir=$HOME/.vim/undo
set undofile
" highlight whitespaces
highlight ExtraWhitespace ctermbg=red guibg=red
match ExtraWhitespace /\s\+$/
autocmd BufWinEnter * match ExtraWhitespace /\s\+$/
autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/
autocmd InsertLeave * match ExtraWhitespace /\s\+$/
autocmd BufWinLeave * call clearmatches()
"ft specific stuff
autocmd BufRead *.js,*.json set ts=2 sts=2 sw=2 et
autocmd BufRead *.hs set ts=4 sts=4 sw=4 et
"esc timeout
set timeoutlen=1000 ttimeoutlen=0
'';
vimrcConfig.vam.knownPlugins = pkgs.vimPlugins // customPlugins;
vimrcConfig.vam.pluginDictionaries = [
{ names = [ "Gundo" "commentary" "mustang2" ]; }
{ names = [ "vim-addon-nix" ]; ft_regex = "^nix\$"; }
];
})
];
}

View File

@ -1,22 +0,0 @@
{ config, pkgs, ... }:
let
mainUser = config.users.extraUsers.mainUser;
in {
services.virtualboxHost.enable = true;
users.extraUsers = {
virtual = {
name = "virtual";
description = "user for running VirtualBox";
home = "/home/virtual";
useDefaultShell = true;
extraGroups = [ "vboxusers" "audio" ];
createHome = true;
};
};
security.sudo.extraConfig = ''
${mainUser.name} ALL=(virtual) NOPASSWD: ALL
'';
}

View File

@ -1,23 +0,0 @@
{ config, pkgs, ... }:
let
mainUser = config.users.extraUsers.mainUser;
in {
environment.systemPackages = with pkgs; [
wineUnstable
];
users.extraUsers = {
wine = {
name = "wine";
description = "user for running wine";
home = "/home/wine";
useDefaultShell = true;
extraGroups = [ "audio" ];
createHome = true;
};
};
security.sudo.extraConfig = ''
${mainUser.name} ALL=(wine) NOPASSWD: ALL
'';
}

View File

@ -1,57 +0,0 @@
{ config, lib, pkgs, ... }:
#TODO:
#prefix with Attribute Name
#ex: urxvt
#
#
with builtins;
with lib;
let
inherit (import ../../lib { inherit pkgs; inherit lib; }) shell-escape;
inherit (pkgs) writeScript;
in
{
options = {
services.xresources.enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable the automatic loading of Xresources definitions at display-manager start;
'';
};
services.xresources.resources = mkOption {
default = {};
type = types.attrsOf types.str;
example = {
urxvt = ''
URxvt*scrollBar: false
URxvt*urgentOnBell: true
'';
};
description = ''
Xresources definitions.
'';
};
};
config =
let
cfg = config.services.xresources;
xres = concatStringsSep "\n" (attrValues cfg.resources);
in mkIf cfg.enable {
services.xserver.displayManager.sessionCommands = ''
echo ${shell-escape xres} | xrdb -merge
'';
};
}

View File

@ -1,86 +0,0 @@
{ config, pkgs, ... }:
let
inherit (builtins) readFile;
in
{
imports =
[
{ users.extraUsers = import <secrets/extraUsers.nix>; }
./networking.nix
./users.nix
../tv/base.nix
../tv/base-cac-CentOS-7-64bit.nix
../tv/config/consul-server.nix
../tv/exim-smarthost.nix
../tv/git/public.nix
../tv/sanitize.nix
{
imports = [ ../tv/identity ];
tv.identity = {
enable = true;
self = config.tv.identity.hosts.mkdir;
};
}
{
imports = [ ../tv/iptables ];
tv.iptables = {
enable = true;
input-internet-accept-new-tcp = [
"ssh"
"tinc"
"smtp"
"xmpp-client"
"xmpp-server"
];
input-retiolum-accept-new-tcp = [
"http"
];
};
}
{
imports = [ ../tv/retiolum ];
tv.retiolum = {
enable = true;
hosts = <retiolum-hosts>;
connectTo = [
"cd"
"fastpoke"
"pigstarter"
"ire"
];
};
}
];
nix.maxJobs = 1;
environment.systemPackages = with pkgs; [
git # required for ./deploy, clone_or_update
htop
iftop
iotop
iptables
mutt # for mv
nethogs
rxvt_unicode.terminfo
tcpdump
];
services.journald.extraConfig = ''
SystemMaxUse=1G
RuntimeMaxUse=128M
'';
services.openssh = {
enable = true;
hostKeys = [
# XXX bits here make no science
{ bits = 8192; type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; }
];
permitRootLogin = "yes";
};
sound.enable = false;
}

View File

@ -1,14 +0,0 @@
{...}:
{
networking.hostName = "mkdir";
networking.interfaces.enp2s1.ip4 = [
{
address = "162.248.167.241";
prefixLength = 24;
}
];
networking.defaultGateway = "162.248.167.1";
networking.nameservers = [
"8.8.8.8"
];
}

View File

@ -1,12 +0,0 @@
{
lib.file.url = ../../lib;
modules.file.url = ../../modules;
nixpkgs.git = {
url = https://github.com/NixOS/nixpkgs;
rev = "4c01e6d91993b6de128795f4fbdd25f6227fb870";
cache = ../../tmp/git-cache;
};
pubkeys.file.url = ../../pubkeys;
retiolum-hosts.file.url = ../../hosts;
secrets.file.url = ../../secrets/cd/nix;
}

View File

@ -1,19 +0,0 @@
{ ... }:
let
inherit (builtins) readFile;
in
{
users.extraUsers =
{
root = {
openssh.authorizedKeys.keys = [
(readFile <pubkeys/deploy_wu.ssh.pub>)
(readFile <pubkeys/tv_wu.ssh.pub>)
];
};
};
users.mutableUsers = false;
}

View File

@ -1,294 +0,0 @@
{ config, pkgs, ... }:
{
imports = [
../lass/xresources.nix
../lass/desktop-base.nix
../lass/programs.nix
./retiolum.nix
../tv/synaptics.nix
../lass/bitcoin.nix
../lass/browsers.nix
../lass/games.nix
../tv/exim-retiolum.nix
../lass/pass.nix
../lass/vim.nix
../lass/virtualbox.nix
../lass/elster.nix
../lass/urxvt.nix
../lass/steam.nix
../lass/wine.nix
../lass/texlive.nix
../common/nixpkgs.nix
../lass/binary-caches.nix
../lass/ircd.nix
../../secrets/mors-pw.nix
./repos.nix
../lass/chromium-patched.nix
./git.nix
];
nixpkgs = {
url = "https://github.com/Lassulus/nixpkgs";
rev = "7ef800430789252dac47f0b67e75a6b9bb616397";
};
networking.hostName = "mors";
networking.wireless.enable = true;
networking.extraHosts = ''
'';
nix.maxJobs = 4;
hardware.enableAllFirmware = true;
nixpkgs.config.allowUnfree = true;
boot = {
kernelParams = [
"acpi.brightness_switch_enabled=0"
];
loader.grub.enable = true;
loader.grub.version = 2;
loader.grub.device = "/dev/sda";
initrd.luks.devices = [ { name = "luksroot"; device = "/dev/sda2"; } ];
initrd.luks.cryptoModules = [ "aes" "sha512" "sha1" "xts" ];
initrd.availableKernelModules = [ "xhci_hcd" "ehci_pci" "ahci" "usb_storage" ];
#kernelModules = [ "kvm-intel" "msr" ];
kernelModules = [ "msr" ];
};
fileSystems = {
"/" = {
device = "/dev/big/nix";
fsType = "ext4";
};
"/boot" = {
device = "/dev/sda1";
};
"/mnt/loot" = {
device = "/dev/big/loot";
fsType = "ext4";
};
"/home" = {
device = "/dev/big/home";
fsType = "ext4";
};
"/home/lass" = {
device = "/dev/big/home-lass";
fsType = "ext4";
};
"/mnt/backups" = {
device = "/dev/big/backups";
fsType = "ext4";
};
"/home/games/.local/share/Steam" = {
device = "/dev/big/steam";
fsType = "ext4";
};
"/home/virtual/virtual" = {
device = "/dev/big/virtual";
fsType = "ext4";
};
"/mnt/public" = {
device = "/dev/big/public";
fsType = "ext4";
};
};
services.udev.extraRules = ''
SUBSYSTEM=="net", ATTR{address}=="a0:88:b4:29:26:bc", NAME="wl0"
SUBSYSTEM=="net", ATTR{address}=="f0:de:f1:0c:a7:63", NAME="et0"
'';
#TODO activationScripts seem broken, fix them!
#activationScripts
#split up and move into base
system.activationScripts.powertopTunables = ''
#Enable Audio codec power management
echo '1' > '/sys/module/snd_hda_intel/parameters/power_save'
#VM writeback timeout
echo '1500' > '/proc/sys/vm/dirty_writeback_centisecs'
#Autosuspend for USB device Broadcom Bluetooth Device [Broadcom Corp]
echo 'auto' > '/sys/bus/usb/devices/1-1.4/power/control'
#Autosuspend for USB device Biometric Coprocessor
echo 'auto' > '/sys/bus/usb/devices/1-1.3/power/control'
#Runtime PMs
echo 'auto' > '/sys/bus/pci/devices/0000:00:02.0/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:00:16.0/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:00:00.0/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:03:00.0/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:00:1f.3/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:00:1f.2/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:00:1f.0/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:00:1d.0/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:00:1c.3/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:0d:00.0/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:00:1c.0/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:00:1b.0/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:00:1a.0/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:00:19.0/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:00:16.3/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:00:1c.1/power/control'
echo 'auto' > '/sys/bus/pci/devices/0000:00:1c.4/power/control'
'';
hardware.trackpoint = {
enable = true;
sensitivity = 220;
speed = 0;
emulateWheel = true;
};
#system.activationScripts.trackpoint = ''
# echo 0 > '/sys/devices/platform/i8042/serio1/serio2/speed'
# echo 220 > '/sys/devices/platform/i8042/serio1/serio2/sensitivity'
#'';
services.xserver = {
videoDriver = "intel";
vaapiDrivers = [ pkgs.vaapiIntel ];
deviceSection = ''
Option "AccelMethod" "sna"
BusID "PCI:0:2:0"
'';
};
users.extraUsers = {
#main user
mainUser = {
uid = 1337;
name = "lass";
#isNormalUser = true;
group = "users";
createHome = true;
home = "/home/lass";
useDefaultShell = true;
isSystemUser = false;
extraGroups = [ "wheel" "audio" ];
};
};
environment.systemPackages = with pkgs; [
];
#TODO: fix this shit
##fprint stuff
##sudo fprintd-enroll $USER to save fingerprints
#services.fprintd.enable = true;
#security.pam.services.sudo.fprintAuth = true;
users.extraGroups = {
loot = {
members = [
config.users.extraUsers.mainUser.name
"firefox"
"chromium"
"google"
"virtual"
];
};
};
networking.firewall = {
allowPing = true;
allowedTCPPorts = [
8000
];
allowedUDPPorts = [
67
];
};
services.mongodb = {
enable = true;
};
#services.ircdHybrid = {
# enable = true;
# description = "local test server";
#};
#TODO
#services.urxvtd = {
# enable = true;
# users = [ "lass" ];
# urxvtPackage = pkgs.rxvt_unicode_with-plugins;
#};
#system.activationScripts.iptables =
# let
# log = false;
# when = c: f: if c then f else "";
# in
# ''
# ip4tables() { ${pkgs.iptables}/sbin/iptables "$@"; }
# ip6tables() { ${pkgs.iptables}/sbin/ip6tables "$@"; }
# ipXtables() { ip4tables "$@"; ip6tables "$@"; }
# #
# # nat
# #
# # reset tables
# ipXtables -t nat -F
# ipXtables -t nat -X
# #
# #ipXtables -t nat -A PREROUTING -j REDIRECT ! -i retiolum -p tcp --dport ssh --to-ports 0
# ipXtables -t nat -A PREROUTING -j REDIRECT -p tcp --dport 11423 --to-ports ssh
# #
# # filter
# #
# # reset tables
# ipXtables -P INPUT DROP
# ipXtables -P FORWARD DROP
# ipXtables -F
# ipXtables -X
# # create custom chains
# ipXtables -N Retiolum
# # INPUT
# ipXtables -A INPUT -j ACCEPT -m conntrack --ctstate RELATED,ESTABLISHED
# ipXtables -A INPUT -j ACCEPT -i lo
# ipXtables -A INPUT -j ACCEPT -p tcp --dport ssh -m conntrack --ctstate NEW
# ipXtables -A INPUT -j ACCEPT -p tcp --dport http -m conntrack --ctstate NEW
# ipXtables -A INPUT -j ACCEPT -p tcp --dport tinc -m conntrack --ctstate NEW
# ipXtables -A INPUT -j ACCEPT -p tcp --dport smtp -m conntrack --ctstate NEW
# #mc
# ipXtables -A INPUT -j ACCEPT -p tcp --dport 25565
# ipXtables -A INPUT -j ACCEPT -p udp --dport 25565
# ipXtables -A INPUT -j Retiolum -i retiolum
# ${when log "ipXtables -A INPUT -j LOG --log-level info --log-prefix 'INPUT DROP '"}
# # FORWARD
# ${when log "ipXtables -A FORWARD -j LOG --log-level info --log-prefix 'FORWARD DROP '"}
# # Retiolum
# ip4tables -A Retiolum -j ACCEPT -p icmp --icmp-type echo-request
# ip6tables -A Retiolum -j ACCEPT -p ipv6-icmp -m icmp6 --icmpv6-type echo-request
# ${when log "ipXtables -A Retiolum -j LOG --log-level info --log-prefix 'REJECT '"}
# ipXtables -A Retiolum -j REJECT -p tcp --reject-with tcp-reset
# ip4tables -A Retiolum -j REJECT -p udp --reject-with icmp-port-unreachable
# ip4tables -A Retiolum -j REJECT --reject-with icmp-proto-unreachable
# ip6tables -A Retiolum -j REJECT -p udp --reject-with icmp6-port-unreachable
# ip6tables -A Retiolum -j REJECT
# '';
}

View File

@ -1,130 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (builtins) map readFile;
inherit (lib) concatMap listToAttrs;
# TODO lib should already include our stuff
inherit (import ../../lib { inherit lib pkgs; }) addNames git;
x-repos = [
(krebs-private "brain")
(public "painload")
(public "shitment")
(public "wai-middleware-time")
(public "web-routes-wai-custom")
(secret "pass")
(tv-lass "emse-drywall")
(tv-lass "emse-hsdb")
];
users = addNames {
tv = { pubkey = readFile <pubkeys/tv_wu.ssh.pub>; };
lass = { pubkey = readFile <pubkeys/lass.ssh.pub>; };
uriel = { pubkey = readFile <pubkeys/uriel.ssh.pub>; };
makefu = { pubkey = "xxx"; };
};
repos = listToAttrs (map ({ repo, ... }: { name = repo.name; value = repo; }) x-repos);
rules = concatMap ({ rules, ... }: rules) x-repos;
krebs-private = repo-name:
rec {
repo = {
name = repo-name;
hooks = {
post-receive = git.irc-announce {
nick = config.networking.hostName; # TODO make this the default
channel = "#retiolum";
server = "ire.retiolum";
};
};
};
rules = with git; with users; [
{ user = lass;
repo = [ repo ];
perm = push "refs/*" [ non-fast-forward create delete merge ];
}
{ user = [ tv makefu uriel ];
repo = [ repo ];
perm = fetch;
}
];
};
public = repo-name:
rec {
repo = {
name = repo-name;
hooks = {
post-receive = git.irc-announce {
nick = config.networking.hostName; # TODO make this the default
channel = "#retiolum";
server = "ire.retiolum";
};
};
public = true;
};
rules = with git; with users; [
{ user = lass;
repo = [ repo ];
perm = push "refs/*" [ non-fast-forward create delete merge ];
}
{ user = [ tv makefu uriel ];
repo = [ repo ];
perm = fetch;
}
];
};
secret = repo-name:
rec {
repo = {
name = repo-name;
hooks = {};
};
rules = with git; with users; [
{ user = lass;
repo = [ repo ];
perm = push "refs/*" [ non-fast-forward create delete merge ];
}
{ user = [ uriel ];
repo = [ repo ];
perm = fetch;
}
];
};
tv-lass = repo-name:
rec {
repo = {
name = repo-name;
hooks = {};
};
rules = with git; with users; [
{ user = lass;
repo = [ repo ];
perm = push "refs/*" [ non-fast-forward create delete merge ];
}
{ user = [ tv ];
repo = [ repo ];
perm = fetch;
}
];
};
in
{
imports = [
../tv/git
];
tv.git = {
enable = true;
inherit repos rules users;
};
}

View File

@ -1,12 +0,0 @@
{
lib.file.url = ../../lib;
modules.file.url = ../../modules;
nixpkgs.git = {
url = https://github.com/Lassulus/nixpkgs;
rev = "7ef800430789252dac47f0b67e75a6b9bb616397";
cache = ../../tmp/git-cache;
};
pubkeys.file.url = ../../pubkeys;
retiolum-hosts.file.url = ../../hosts;
secrets.file.url = ../../secrets;
}

View File

@ -1,87 +0,0 @@
{ ... }:
{
imports = [
../lass/gitolite-base.nix
../common/krebs-keys.nix
../common/krebs-repos.nix
];
services.gitolite = {
repos = {
config = {
users = {
lass = "RW+";
uriel = "R";
tv = "R";
};
extraConfig = "option hook.post-receive = irc-announce";
};
pass = {
users = {
lass = "RW+";
uriel = "R";
};
};
load-env = {
users = {
lass = "RW+";
uriel = "R";
tv = "R";
};
extraConfig = "option hook.post-receive = irc-announce";
};
emse-drywall = {
users = {
lass = "RW+";
uriel = "R";
tv = "R";
};
extraConfig = "option hook.post-receive = irc-announce";
};
emse-hsdb = {
users = {
lass = "RW+";
uriel = "R";
tv = "R";
};
extraConfig = "option hook.post-receive = irc-announce";
};
brain = {
users = {
lass = "RW+";
};
extraConfig = "option hook.post-receive = irc-announce";
#hooks.post-receive = irc-announce;
};
painload = {
users = {
lass = "RW+";
};
extraConfig = "option hook.post-receive = irc-announce";
};
services = {
users = {
lass = "RW+";
};
extraConfig = "option hook.post-receive = irc-announce";
};
xmonad-config = {
users = {
lass = "RW+";
uriel = "R";
};
};
};
};
}

View File

@ -1,21 +0,0 @@
{ config, pkgs, ... }:
{
imports = [
../tv/retiolum
];
tv.retiolum = {
enable = true;
hosts = <retiolum-hosts>;
privateKeyFile = "/etc/nixos/secrets/mors.retiolum.rsa_key.priv";
connectTo = [
"fastpoke"
"gum"
"ire"
];
};
networking.firewall.allowedTCPPorts = [ 655 ];
networking.firewall.allowedUDPPorts = [ 655 ];
}

View File

@ -1,466 +0,0 @@
# TODO maybe give RT-stuff only to group rt or sth.
{ config, pkgs, ... }:
let
lib = import ../../lib { inherit pkgs; };
inherit (lib) majmin;
in
{
imports = [
<secrets/mu.hashedPasswords.nix>
../tv/base.nix
../tv/exim-retiolum.nix
../tv/retiolum.nix
../tv/sanitize.nix
];
nix.maxJobs = 2;
services.udev.extraRules = ''
SUBSYSTEM=="net", ATTR{address}=="00:90:f5:da:aa:c3", NAME="en0"
SUBSYSTEM=="net", ATTR{address}=="a0:88:b4:1b:ae:6c", NAME="wl0"
# for jack
KERNEL=="rtc0", GROUP="audio"
KERNEL=="hpet", GROUP="audio"
'';
# hardware configuration
boot.initrd.luks.devices = [
{ name = "vgmu1"; device = "/dev/sda2"; }
];
boot.initrd.luks.cryptoModules = [ "aes" "sha512" "xts" ];
boot.initrd.availableKernelModules = [ "ahci" ];
#boot.kernelParams = [
# "intel_pstate=enable"
#];
boot.kernelModules = [ "fbcon" "kvm-intel" ];
boot.extraModulePackages = [ ];
#boot.kernelPackages = pkgs.linuxPackages_3_17;
boot.kernel.sysctl = {
# Enable IPv6 Privacy Extensions
"net.ipv6.conf.all.use_tempaddr" = 2;
"net.ipv6.conf.default.use_tempaddr" = 2;
};
boot.extraModprobeConfig = ''
options kvm_intel nested=1
'';
fileSystems = {
"/" = {
device = "/dev/vgmu1/nixroot";
fsType = "ext4";
options = "defaults,noatime";
};
"/home" = {
device = "/dev/vgmu1/home";
options = "defaults,noatime";
};
"/boot" = {
device = "/dev/sda1";
};
"/tmp" = {
device = "tmpfs";
fsType = "tmpfs";
options = "nosuid,nodev,noatime";
};
};
swapDevices =[ ];
nixpkgs.config.firefox.enableAdobeFlash = true;
nixpkgs.config.chromium.enablePepperFlash = true;
nixpkgs.config.allowUnfree = true;
hardware.opengl.driSupport32Bit = true;
hardware.pulseaudio.enable = true;
hardware.enableAllFirmware = true;
# Use the gummiboot efi boot loader.
boot.loader.gummiboot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
networking.hostName = "mu";
#networking.wireless.enable = true;
networking.networkmanager.enable = true;
networking.extraHosts = ''
'';
#system.activationScripts.powertopTunables =
# ''
# #echo 1 > /sys/module/snd_hda_intel/parameters/power_save
# echo 1500 > /proc/sys/vm/dirty_writeback_centisecs
# (cd /sys/bus/pci/devices
# for i in *; do
# echo auto > $i/power/control # defaults to 'on'
# done)
# # TODO maybe do this via udev or systemd
# # ref https://wiki.archlinux.org/index.php/Wake-on-LAN
# # disable wol this cannot find ethtool
# # TODO (cd /sys/class/net
# # TODO for i in *; do
# # TODO if ethtool $i | grep -q Wake-on &&
# # TODO ! ethtool $i | grep -q 'Wake-on: d'; then
# # TODO ethtool -s $i wol d
# # TODO fi
# # TODO done)
# ${pkgs.ethtool}/sbin/ethtool -s en0 wol d
# '';
environment.systemPackages = with pkgs; [
slock
tinc
iptables
vim
gimp
xsane
firefoxWrapper
chromiumDev
skype
libreoffice
kde4.l10n.de
kde4.networkmanagement
pidgin-with-plugins
pidginotr
kde4.print_manager
#foomatic_filters
#gutenprint
#cups_pdf_filter
#ghostscript
];
environment.etc."vim/vimrc".text = ''
set nocp
'';
environment.etc."vim/vim${majmin pkgs.vim.version}".source =
"${pkgs.vim}/share/vim/vim${majmin pkgs.vim.version}";
# multiple-definition-problem when defining environment.variables.EDITOR
environment.extraInit = ''
EDITOR=vim
'';
environment.variables.VIM = "/etc/vim";
i18n.defaultLocale = "de_DE.UTF-8";
environment.shellAliases = {
# alias cal='cal -m3'
bc = "bc -q";
gp = "gp -q";
df = "df -h";
du = "du -h";
# alias grep='grep --color=auto'
# TODO alias cannot contain #\'
# "ps?" = "ps ax | head -n 1;ps ax | fgrep -v ' grep --color=auto ' | grep";
# alias la='ls -lA'
lAtr = "ls -lAtr";
# alias ll='ls -l'
ls = "ls -h --color=auto --group-directories-first";
# alias vim='vim -p'
# alias vi='vim'
# alias view='vim -R'
dmesg = "dmesg -L --reltime";
};
programs.bash = {
interactiveShellInit = ''
HISTCONTROL='erasedups:ignorespace'
HISTSIZE=65536
HISTFILESIZE=$HISTSIZE
shopt -s checkhash
shopt -s histappend histreedit histverify
shopt -s no_empty_cmd_completion
complete -d cd
# TODO source bridge
'';
promptInit = ''
case $UID in
0)
PS1='\[\e[1;31m\]\w\[\e[0m\] '
;;
1337)
PS1='\[\e[1;32m\]\w\[\e[0m\] '
;;
2000)
PS1='\[\e[1;32m\]\w\[\e[0m\] '
;;
*)
PS1='\[\e[1;35m\]\u \[\e[1;32m\]\w\[\e[0m\] '
;;
esac
if test -n "$SSH_CLIENT"; then
PS1='\[\e[35m\]\h'" $PS1"
fi
'';
};
programs.ssh.startAgent = false;
security.setuidPrograms = [
"sendmail" # for cron
"slock"
];
security.pam.loginLimits = [
# for jack
{ domain = "@audio"; item = "memlock"; type = "-"; value = "unlimited"; }
{ domain = "@audio"; item = "rtprio"; type = "-"; value = "99"; }
];
#services.haveged.enable = true;
#security.rngd.enable = true;
services.retiolum = {
enable = true;
hosts = /etc/nixos/hosts;
connectTo = [
"gum"
"pigstarter"
];
};
#services.dbus.enable = true; # rqd4 wpa_supplicant
fonts.fonts = [
pkgs.xlibs.fontschumachermisc
];
#services.logind.extraConfig = ''
# HandleHibernateKey=ignore
# HandleLidSwitch=ignore
# HandlePowerKey=ignore
# HandleSuspendKey=ignore
#'';
#services.xserver.displayManager.desktopManagerHandlesLidAndPower = true;
# Enable the OpenSSH daemon.
services.openssh = {
enable = true;
hostKeys = [
# XXX bits here make no science
{ bits = 8192; type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; }
];
};
# Enable CUPS to print documents.
# services.printing.enable = true;
services.printing = {
enable = true;
#drivers = [
# #pkgs.foomatic_filters
# #pkgs.gutenprint
# #pkgs.cups_pdf_filter
# #pkgs.ghostscript
#];
#cupsdConf = ''
# LogLevel debug2
#'';
};
# Enable the X11 windowing system.
services.xserver.enable = true;
#services.xserver.display = 11;
#services.xserver.tty = 11;
services.xserver.layout = "de";
services.xserver.xkbOptions = "eurosign:e";
# TODO this is host specific
services.xserver.synaptics = {
enable = true;
twoFingerScroll = true;
#accelFactor = "0.035";
#additionalOptions = ''
# Option "FingerHigh" "60"
# Option "FingerLow" "60"
#'';
};
services.xserver.desktopManager.kde4.enable = true;
services.xserver.displayManager.auto = {
enable = true;
user = "vv";
};
users.defaultUserShell = "/run/current-system/sw/bin/bash";
users.mutableUsers = false;
users.extraGroups =
{
};
users.extraUsers =
{
tv = {
uid = 1337;
name = "tv";
group = "users";
home = "/home/tv";
useDefaultShell = true;
extraGroups = [
"audio"
"video"
"wheel"
];
createHome = true;
};
vv = {
uid = 2000;
name = "vv";
home = "/home/vv";
createHome = true;
group = "users";
useDefaultShell = true;
extraGroups = [
"audio"
"video"
"networkmanager"
];
};
};
services.journald.extraConfig = ''
SystemMaxUse=1G
RuntimeMaxUse=128M
'';
# see tmpfiles.d(5)
systemd.tmpfiles.rules = [
"d /tmp 1777 root root - -" # does this work with mounted /tmp?
];
# TODO services.smartd
# TODO services.statsd
# TODO services.tor
# TODO write arandr
# TODO what does system.copySystemConfiguration (we need some kind of bku scheme)
# TODO systemd.timers instead of cron(??)
virtualisation.libvirtd.enable = true;
#
# iptables
#
networking.firewall.enable = false;
system.activationScripts.iptables =
let
log = false;
when = c: f: if c then f else "";
in
''
ip4tables() { ${pkgs.iptables}/sbin/iptables "$@"; }
ip6tables() { ${pkgs.iptables}/sbin/ip6tables "$@"; }
ipXtables() { ip4tables "$@"; ip6tables "$@"; }
#
# nat
#
# reset tables
ipXtables -t nat -F
ipXtables -t nat -X
#
ipXtables -t nat -A PREROUTING -j REDIRECT ! -i retiolum -p tcp --dport ssh --to-ports 0
ipXtables -t nat -A PREROUTING -j REDIRECT -p tcp --dport 11423 --to-ports ssh
#
# filter
#
# reset tables
ipXtables -P INPUT DROP
ipXtables -P FORWARD DROP
ipXtables -F
ipXtables -X
# create custom chains
ipXtables -N Retiolum
# INPUT
ipXtables -A INPUT -j ACCEPT -m conntrack --ctstate RELATED,ESTABLISHED
ipXtables -A INPUT -j ACCEPT -i lo
ipXtables -A INPUT -j ACCEPT -p tcp --dport ssh -m conntrack --ctstate NEW
ipXtables -A INPUT -j ACCEPT -p tcp --dport http -m conntrack --ctstate NEW
ipXtables -A INPUT -j ACCEPT -p tcp --dport tinc -m conntrack --ctstate NEW
ipXtables -A INPUT -j ACCEPT -p tcp --dport smtp -m conntrack --ctstate NEW
ipXtables -A INPUT -j Retiolum -i retiolum
${when log "ipXtables -A INPUT -j LOG --log-level info --log-prefix 'INPUT DROP '"}
# FORWARD
${when log "ipXtables -A FORWARD -j LOG --log-level info --log-prefix 'FORWARD DROP '"}
# Retiolum
ip4tables -A Retiolum -j ACCEPT -p icmp --icmp-type echo-request
ip6tables -A Retiolum -j ACCEPT -p ipv6-icmp -m icmp6 --icmpv6-type echo-request
${when log "ipXtables -A Retiolum -j LOG --log-level info --log-prefix 'REJECT '"}
ipXtables -A Retiolum -j REJECT -p tcp --reject-with tcp-reset
ip4tables -A Retiolum -j REJECT -p udp --reject-with icmp-port-unreachable
ip4tables -A Retiolum -j REJECT --reject-with icmp-proto-unreachable
ip6tables -A Retiolum -j REJECT -p udp --reject-with icmp6-port-unreachable
ip6tables -A Retiolum -j REJECT
'';
#system.replaceRuntimeDependencies = with pkgs;
# let
# bashVulnPatches = [
# (fetchurl {
# url = "mirror://gnu/bash/bash-4.2-patches/bash42-048";
# sha256 = "091xk1ms7ycnczsl3fx461gjhj69j6ycnfijlymwj6mj60ims6km";
# })
# (fetchurl {
# url = "file:///etc/nixos/bash-20140926.patch";
# sha256 = "0gdwnimsbi4vh5l46krss4wjrgbch94skn4y2w3rpvb1w4jypha4";
# })
# ];
# in
# [
# {
# original = bash;
# replacement = pkgs.lib.overrideDerivation bash (oldAttrs: {
# patches = oldAttrs.patches ++ bashVulnPatches;
# });
# }
# {
# original = bashInteractive;
# replacement = pkgs.lib.overrideDerivation bashInteractive (oldAttrs: {
# patches = oldAttrs.patches ++ bashVulnPatches;
# });
# }
# {
# original = bitlbee;
# replacement = pkgs.lib.overrideDerivation bitlbee (oldAttrs: {
# configureFlags = [
# "--gcov=1"
# "--otr=1"
# "--ssl=gnutls"
# ];
# });
# }
#];
}

View File

@ -1,12 +0,0 @@
{
lib.file.url = ../../lib;
modules.file.url = ../../modules;
nixpkgs.git = {
url = https://github.com/NixOS/nixpkgs;
rev = "4c01e6d91993b6de128795f4fbdd25f6227fb870";
cache = ../../tmp/git-cache;
};
pubkeys.file.url = ../../pubkeys;
retiolum-hosts.file.url = ../../hosts;
secrets.file.url = ../../secrets/wu/nix;
}

View File

@ -1,105 +0,0 @@
{ config, pkgs, ... }:
let
location = pkgs.lib.nameValuePair; # TODO this is also in modules/tv/git/cgit.nix
in
{
imports = [
./hardware-configuration.nix
./users.nix
../tv/base.nix
../tv/config/consul-server.nix
../tv/environment.nix
../tv/exim-retiolum.nix
../tv/git/public.nix
../tv/sanitize.nix
../tv/smartd.nix
{
imports = [ ../tv/identity ];
tv.identity = {
enable = true;
self = config.tv.identity.hosts.nomic;
};
}
{
imports = [ ../tv/iptables ];
tv.iptables = {
enable = true;
input-internet-accept-new-tcp = [
"ssh"
"http"
"tinc"
"smtp"
];
};
}
{
imports = [ ../tv/nginx ];
tv.nginx = {
enable = true;
retiolum-locations = [
(location "~ ^/~(.+?)(/.*)?\$" ''
alias /home/$1/public_html$2;
'')
];
};
}
{
imports = [ ../tv/retiolum ];
tv.retiolum = {
enable = true;
hosts = <retiolum-hosts>;
connectTo = [
"gum"
"pigstarter"
];
};
}
];
boot.kernel.sysctl = {
# Enable IPv6 Privacy Extensions
"net.ipv6.conf.all.use_tempaddr" = 2;
"net.ipv6.conf.default.use_tempaddr" = 2;
};
boot.tmpOnTmpfs = true;
environment.systemPackages = with pkgs; [
(writeScriptBin "play" ''
#! /bin/sh
set -euf
mpv() { exec ${mpv}/bin/mpv "$@"; }
case $1 in
deepmix) mpv http://deepmix.ru/deepmix128.pls;;
groovesalad) mpv http://somafm.com/play/groovesalad;;
ntslive) mpv http://listen2.ntslive.co.uk/listen.pls;;
*)
echo "$0: bad argument: $*" >&2
exit 23
esac
'')
rxvt_unicode.terminfo
tmux
];
networking = {
hostName = "nomic";
wireless.enable = true;
};
services.logind.extraConfig = ''
HandleHibernateKey=ignore
HandleLidSwitch=ignore
HandlePowerKey=ignore
HandleSuspendKey=ignore
'';
services.openssh = {
enable = true;
hostKeys = [
{ type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; }
];
};
}

View File

@ -1,49 +0,0 @@
{ config, ... }:
{
boot.initrd.luks = {
cryptoModules = [ "aes" "sha1" "xts" ];
devices = [
{
name = "luks1";
device = "/dev/disk/by-uuid/cac73902-1023-4906-8e95-3a8b245337d4";
}
];
};
boot.initrd.availableKernelModules = [ "ahci" ];
boot.kernelModules = [ "kvm-intel" "wl" ];
boot.extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ];
boot.loader.grub = {
device = "/dev/sda";
splashImage = null;
};
fileSystems."/" =
{ device = "/dev/disk/by-uuid/de4780fc-0473-4708-81df-299b7383274c";
fsType = "btrfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/be3a1d80-3157-4d7c-86cc-ef01b64eff5e";
fsType = "ext4";
};
fileSystems."/home" =
{ device = "/dev/disk/by-uuid/9db9c8ff-51da-4cbd-9f0a-0cd3333bbaff";
fsType = "btrfs";
};
swapDevices = [ ];
nix = {
buildCores = 2;
maxJobs = 2;
daemonIONiceLevel = 1;
daemonNiceLevel = 1;
};
# For config.boot.kernelPackages.broadcom_sta
nixpkgs.config.allowUnfree = true;
}

View File

@ -1,12 +0,0 @@
{
lib.file.url = ../../lib;
modules.file.url = ../../modules;
nixpkgs.git = {
url = https://github.com/NixOS/nixpkgs;
rev = "4e5e441";
cache = ../../tmp/git-cache;
};
pubkeys.file.url = ../../pubkeys;
retiolum-hosts.file.url = ../../hosts;
secrets.file.url = ../../secrets/nomic/nix;
}

View File

@ -1,42 +0,0 @@
{ pkgs, ... }:
{
imports = [
{ users = import <secrets/users.nix>; }
{
users.extraUsers = {
root = {
openssh.authorizedKeys.keys = [
(pkgs.lib.readFile <pubkeys/tv_wu.ssh.pub>)
];
};
tv = {
uid = 1337;
group = "users";
home = "/home/tv";
createHome = true;
useDefaultShell = true;
extraGroups = [
"audio"
"video"
"wheel"
];
openssh.authorizedKeys.keys = [
(pkgs.lib.readFile <pubkeys/tv_wu.ssh.pub>)
];
};
};
}
];
users.defaultUserShell = "/run/current-system/sw/bin/bash";
users.mutableUsers = false;
security.setuidPrograms = [
"sendmail" # for sudo
];
security.sudo.extraConfig = ''
Defaults mailto="tv@wu.retiolum"
'';
}

View File

@ -1,87 +0,0 @@
{ config, pkgs, ... }:
let
inherit (builtins) readFile;
in
{
imports =
[
{ users.extraUsers = import <secrets/extraUsers.nix>; }
./networking.nix
./users.nix
../tv/base.nix
../tv/base-cac-CentOS-7-64bit.nix
../tv/config/consul-server.nix
../tv/exim-smarthost.nix
../tv/git/public.nix
../tv/sanitize.nix
{
imports = [ ../tv/identity ];
tv.identity = {
enable = true;
self = config.tv.identity.hosts.rmdir;
};
}
{
imports = [ ../tv/iptables ];
tv.iptables = {
enable = true;
input-internet-accept-new-tcp = [
"ssh"
"tinc"
"smtp"
"xmpp-client"
"xmpp-server"
];
input-retiolum-accept-new-tcp = [
"http"
];
};
}
{
imports = [ ../tv/retiolum ];
tv.retiolum = {
enable = true;
hosts = <retiolum-hosts>;
connectTo = [
"cd"
"mkdir"
"fastpoke"
"pigstarter"
"ire"
];
};
}
];
nix.maxJobs = 1;
environment.systemPackages = with pkgs; [
git # required for ./deploy, clone_or_update
htop
iftop
iotop
iptables
mutt # for mv
nethogs
rxvt_unicode.terminfo
tcpdump
];
services.journald.extraConfig = ''
SystemMaxUse=1G
RuntimeMaxUse=128M
'';
services.openssh = {
enable = true;
hostKeys = [
# XXX bits here make no science
{ bits = 8192; type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; }
];
permitRootLogin = "yes";
};
sound.enable = false;
}

View File

@ -1,15 +0,0 @@
_:
{
networking.hostName = "rmdir";
networking.interfaces.enp2s1.ip4 = [
{
address = "167.88.44.94";
prefixLength = 24;
}
];
networking.defaultGateway = "167.88.44.1";
networking.nameservers = [
"8.8.8.8"
];
}

View File

@ -1,12 +0,0 @@
{
lib.file.url = ../../lib;
modules.file.url = ../../modules;
nixpkgs.git = {
url = https://github.com/NixOS/nixpkgs;
rev = "4c01e6d91993b6de128795f4fbdd25f6227fb870";
cache = ../../tmp/git-cache;
};
pubkeys.file.url = ../../pubkeys;
retiolum-hosts.file.url = ../../hosts;
secrets.file.url = ../../secrets/cd/nix;
}

View File

@ -1,19 +0,0 @@
{ ... }:
let
inherit (builtins) readFile;
in
{
users.extraUsers =
{
root = {
openssh.authorizedKeys.keys = [
(readFile <pubkeys/deploy_wu.ssh.pub>)
(readFile <pubkeys/tv_wu.ssh.pub>)
];
};
};
users.mutableUsers = false;
}

View File

@ -1,27 +0,0 @@
{ config, pkgs, ... }:
{
boot.loader.grub.device = "/dev/sda";
boot.loader.grub.enable = true;
boot.loader.grub.version = 2;
boot.initrd.availableKernelModules = [
"ata_piix"
"vmw_pvscsi"
];
fileSystems."/" = {
device = "/dev/centos/root";
fsType = "xfs";
};
fileSystems."/boot" = {
device = "/dev/sda1";
fsType = "xfs";
};
swapDevices = [
{ device = "/dev/centos/swap"; }
];
}

View File

@ -1,16 +0,0 @@
{ config, pkgs, ... }:
{
time.timeZone = "Europe/Berlin";
# TODO check if both are required:
nix.chrootDirs = [ "/etc/protocols" pkgs.iana_etc.outPath ];
nix.trustedBinaryCaches = [
"https://cache.nixos.org"
"http://cache.nixos.org"
"http://hydra.nixos.org"
];
nix.useChroot = true;
}

View File

@ -1,9 +0,0 @@
{ pkgs, ... }:
{
imports = [ ./consul-server.nix ];
tv.consul = {
server = pkgs.lib.mkForce false;
};
}

View File

@ -1,22 +0,0 @@
{ config, ... }:
{
imports = [ ../../tv/consul ];
tv.consul = rec {
enable = true;
inherit (config.tv.identity) self;
inherit (self) dc;
server = true;
hosts = with config.tv.identity.hosts; [
# TODO get this list automatically from each host where tv.consul.enable is true
cd
mkdir
nomic
rmdir
#wu
];
};
}

View File

@ -1,121 +0,0 @@
{ config, lib, pkgs, ... }:
# if quorum gets lost, then start any node with a config that doesn't contain bootstrap_expect
# but -bootstrap
# TODO consul-bootstrap HOST that actually does is
# TODO tools to inspect state of a cluster in outage state
with builtins;
with lib;
let
cfg = config.tv.consul;
out = {
imports = [ ../../tv/iptables ];
options.tv.consul = api;
config = mkIf cfg.enable (mkMerge [
imp
{ tv.iptables.input-retiolum-accept-new-tcp = [ "8300" "8301" ]; }
# TODO udp for 8301
]);
};
api = {
# TODO inherit (lib) api.options.enable; oder so
enable = mkOption {
type = types.bool;
default = false;
description = "enable tv.consul";
};
dc = mkOption {
type = types.unspecified;
};
hosts = mkOption {
type = with types; listOf unspecified;
};
encrypt-file = mkOption {
type = types.str; # TODO path (but not just into store)
default = "/etc/consul/encrypt.json";
};
data-dir = mkOption {
type = types.str; # TODO path (but not just into store)
default = "/var/lib/consul";
};
self = mkOption {
type = types.unspecified;
};
server = mkOption {
type = types.bool;
default = false;
};
GOMAXPROCS = mkOption {
type = types.int;
default = cfg.self.cores;
};
};
consul-config = {
datacenter = cfg.dc;
data_dir = cfg.data-dir;
log_level = "INFO";
#node_name =
server = cfg.server;
bind_addr = cfg.self.addr; # TODO cfg.addr
enable_syslog = true;
retry_join = map (getAttr "addr") (filter (host: host.fqdn != cfg.self.fqdn) cfg.hosts);
leave_on_terminate = true;
} // optionalAttrs cfg.server {
bootstrap_expect = length cfg.hosts;
leave_on_terminate = false;
};
imp = {
environment.systemPackages = with pkgs; [
consul
];
systemd.services.consul = {
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
path = with pkgs; [
consul
];
environment = {
GOMAXPROCS = toString cfg.GOMAXPROCS;
};
serviceConfig = {
PermissionsStartOnly = "true";
SyslogIdentifier = "consul";
User = user.name;
PrivateTmp = "true";
Restart = "always";
ExecStartPre = pkgs.writeScript "consul-init" ''
#! /bin/sh
mkdir -p ${cfg.data-dir}
chown consul: ${cfg.data-dir}
'';
ExecStart = pkgs.writeScript "consul-service" ''
#! /bin/sh
set -euf
exec >/dev/null
exec consul agent \
-config-file=${toFile "consul.json" (toJSON consul-config)} \
-config-file=${cfg.encrypt-file} \
'';
#-node=${cfg.self.fqdn} \
#ExecStart = "${tinc}/sbin/tincd -c ${confDir} -d 0 -U ${user} -D";
};
};
users.extraUsers = singleton {
inherit (user) name uid;
};
};
user = {
name = "consul";
uid = 2983239726; # genid consul
};
in
out

View File

@ -1,867 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
inherit (pkgs) ejabberd writeScript writeScriptBin utillinux;
inherit (lib) makeSearchPath;
cfg = config.services.ejabberd-cd;
# XXX this is a placeholder that happens to work the default strings.
toErlang = builtins.toJSON;
in
{
####### interface
options = {
services.ejabberd-cd = {
enable = mkOption {
default = false;
description = "Whether to enable ejabberd server";
};
certFile = mkOption {
# TODO if it's types.path then it gets copied to /nix/store with
# bad unsafe permissions...
type = types.string;
default = "/etc/ejabberd/ejabberd.pem";
description = ''
TODO
'';
};
config = mkOption {
type = types.string;
default = "";
description = ''
TODO
'';
};
user = mkOption {
type = types.string;
default = "ejabberd";
description = ''
TODO
'';
};
group = mkOption {
type = types.string;
default = "ejabberd";
description = ''
TODO
'';
};
# spoolDir = mkOption {
# default = "/var/lib/ejabberd";
# description = "Location of the spooldir of ejabberd";
# };
# logsDir = mkOption {
# default = "/var/log/ejabberd";
# description = "Location of the logfile directory of ejabberd";
# };
# confDir = mkOption {
# default = "/var/ejabberd";
# description = "Location of the config directory of ejabberd";
# };
# virtualHosts = mkOption {
# default = "\"localhost\"";
# description = "Virtualhosts that ejabberd should host. Hostnames are surrounded with doublequotes and separated by commas";
# };
# loadDumps = mkOption {
# default = [];
# description = "Configuration dump that should be loaded on the first startup";
# example = literalExample "[ ./myejabberd.dump ]";
# };
# config
};
};
####### implementation
config =
let
my-ejabberdctl = writeScriptBin "ejabberdctl" ''
#! /bin/sh
set -euf
exec env \
SPOOLDIR=/var/ejabberd \
EJABBERD_CONFIG_PATH=/etc/ejabberd.cfg \
${ejabberd}/bin/ejabberdctl \
--logs /var/ejabberd \
"$@"
'';
in
mkIf cfg.enable {
#environment.systemPackages = [ pkgs.ejabberd ];
environment = {
etc."ejabberd.cfg".text = ''
%%%
%%% ejabberd configuration file
%%%
%%%'
%%% The parameters used in this configuration file are explained in more detail
%%% in the ejabberd Installation and Operation Guide.
%%% Please consult the Guide in case of doubts, it is included with
%%% your copy of ejabberd, and is also available online at
%%% http://www.process-one.net/en/ejabberd/docs/
%%% This configuration file contains Erlang terms.
%%% In case you want to understand the syntax, here are the concepts:
%%%
%%% - The character to comment a line is %
%%%
%%% - Each term ends in a dot, for example:
%%% override_global.
%%%
%%% - A tuple has a fixed definition, its elements are
%%% enclosed in {}, and separated with commas:
%%% {loglevel, 4}.
%%%
%%% - A list can have as many elements as you want,
%%% and is enclosed in [], for example:
%%% [http_poll, web_admin, tls]
%%%
%%% - A keyword of ejabberd is a word in lowercase.
%%% Strings are enclosed in "" and can contain spaces, dots, ...
%%% {language, "en"}.
%%% {ldap_rootdn, "dc=example,dc=com"}.
%%%
%%% - This term includes a tuple, a keyword, a list, and two strings:
%%% {hosts, ["jabber.example.net", "im.example.com"]}.
%%%
%%%. =======================
%%%' OVERRIDE STORED OPTIONS
%%
%% Override the old values stored in the database.
%%
%%
%% Override global options (shared by all ejabberd nodes in a cluster).
%%
%%override_global.
%%
%% Override local options (specific for this particular ejabberd node).
%%
%%override_local.
%%
%% Remove the Access Control Lists before new ones are added.
%%
%%override_acls.
%%%. =========
%%%' DEBUGGING
%%
%% loglevel: Verbosity of log files generated by ejabberd.
%% 0: No ejabberd log at all (not recommended)
%% 1: Critical
%% 2: Error
%% 3: Warning
%% 4: Info
%% 5: Debug
%%
{loglevel, 3}.
%%
%% watchdog_admins: Only useful for developers: if an ejabberd process
%% consumes a lot of memory, send live notifications to these XMPP
%% accounts.
%%
%%{watchdog_admins, ["bob@example.com"]}.
%%%. ================
%%%' SERVED HOSTNAMES
%%
%% hosts: Domains served by ejabberd.
%% You can define one or several, for example:
%% {hosts, ["example.net", "example.com", "example.org"]}.
%%
{hosts, ["jabber.viljetic.de"]}.
%%
%% route_subdomains: Delegate subdomains to other XMPP servers.
%% For example, if this ejabberd serves example.org and you want
%% to allow communication with an XMPP server called im.example.org.
%%
%%{route_subdomains, s2s}.
%%%. ===============
%%%' LISTENING PORTS
%%
%% listen: The ports ejabberd will listen on, which service each is handled
%% by and what options to start it with.
%%
{listen,
[
{5222, ejabberd_c2s, [
%%
%% If TLS is compiled in and you installed a SSL
%% certificate, specify the full path to the
%% file and uncomment this line:
%%
starttls,
{certfile, ${toErlang cfg.certFile}},
{access, c2s},
{shaper, c2s_shaper},
{max_stanza_size, 65536}
]},
{5269, ejabberd_s2s_in, [
{shaper, s2s_shaper},
{max_stanza_size, 131072}
]},
%%
%% ejabberd_service: Interact with external components (transports, ...)
%%
%%{8888, ejabberd_service, [
%% {access, all},
%% {shaper_rule, fast},
%% {ip, {127, 0, 0, 1}},
%% {hosts, ["icq.example.org", "sms.example.org"],
%% [{password, "secret"}]
%% }
%% ]},
%%
%% ejabberd_stun: Handles STUN Binding requests
%%
%%{{3478, udp}, ejabberd_stun, []},
{5280, ejabberd_http, [
%%{request_handlers,
%% [
%% {["pub", "archive"], mod_http_fileserver}
%% ]},
captcha,
http_bind,
http_poll,
%%register,
web_admin
]}
]}.
%%
%% s2s_use_starttls: Enable STARTTLS + Dialback for S2S connections.
%% Allowed values are: false optional required required_trusted
%% You must specify a certificate file.
%%
{s2s_use_starttls, required}.
%%
%% s2s_certfile: Specify a certificate file.
%%
{s2s_certfile, ${toErlang cfg.certFile}}.
%%
%% domain_certfile: Specify a different certificate for each served hostname.
%%
%%{domain_certfile, "example.org", "/path/to/example_org.pem"}.
%%{domain_certfile, "example.com", "/path/to/example_com.pem"}.
%%
%% S2S whitelist or blacklist
%%
%% Default s2s policy for undefined hosts.
%%
%%{s2s_default_policy, allow}.
%%
%% Allow or deny communication with specific servers.
%%
%%{{s2s_host, "goodhost.org"}, allow}.
%%{{s2s_host, "badhost.org"}, deny}.
%%
%% Outgoing S2S options
%%
%% Preferred address families (which to try first) and connect timeout
%% in milliseconds.
%%
%%{outgoing_s2s_options, [ipv4, ipv6], 10000}.
%%%. ==============
%%%' AUTHENTICATION
%%
%% auth_method: Method used to authenticate the users.
%% The default method is the internal.
%% If you want to use a different method,
%% comment this line and enable the correct ones.
%%
{auth_method, internal}.
%%
%% Store the plain passwords or hashed for SCRAM:
%%{auth_password_format, plain}.
%%{auth_password_format, scram}.
%%
%% Define the FQDN if ejabberd doesn't detect it:
%%{fqdn, "server3.example.com"}.
%%
%% Authentication using external script
%% Make sure the script is executable by ejabberd.
%%
%%{auth_method, external}.
%{extauth_program, "$ {ejabberd-auth}"}.
%%
%% Authentication using ODBC
%% Remember to setup a database in the next section.
%%
%%{auth_method, odbc}.
%%
%% Authentication using PAM
%%
%%{auth_method, pam}.
%%{pam_service, "pamservicename"}.
%%
%% Authentication using LDAP
%%
%%{auth_method, ldap}.
%%
%% List of LDAP servers:
%%{ldap_servers, ["localhost"]}.
%%
%% Encryption of connection to LDAP servers:
%%{ldap_encrypt, none}.
%%{ldap_encrypt, tls}.
%%
%% Port to connect to on LDAP servers:
%%{ldap_port, 389}.
%%{ldap_port, 636}.
%%
%% LDAP manager:
%%{ldap_rootdn, "dc=example,dc=com"}.
%%
%% Password of LDAP manager:
%%{ldap_password, "******"}.
%%
%% Search base of LDAP directory:
%%{ldap_base, "dc=example,dc=com"}.
%%
%% LDAP attribute that holds user ID:
%%{ldap_uids, [{"mail", "%u@mail.example.org"}]}.
%%
%% LDAP filter:
%%{ldap_filter, "(objectClass=shadowAccount)"}.
%%
%% Anonymous login support:
%% auth_method: anonymous
%% anonymous_protocol: sasl_anon | login_anon | both
%% allow_multiple_connections: true | false
%%
%%{host_config, "public.example.org", [{auth_method, anonymous},
%% {allow_multiple_connections, false},
%% {anonymous_protocol, sasl_anon}]}.
%%
%% To use both anonymous and internal authentication:
%%
%%{host_config, "public.example.org", [{auth_method, [internal, anonymous]}]}.
%%%. ==============
%%%' DATABASE SETUP
%% ejabberd by default uses the internal Mnesia database,
%% so you do not necessarily need this section.
%% This section provides configuration examples in case
%% you want to use other database backends.
%% Please consult the ejabberd Guide for details on database creation.
%%
%% MySQL server:
%%
%%{odbc_server, {mysql, "server", "database", "username", "password"}}.
%%
%% If you want to specify the port:
%%{odbc_server, {mysql, "server", 1234, "database", "username", "password"}}.
%%
%% PostgreSQL server:
%%
%%{odbc_server, {pgsql, "server", "database", "username", "password"}}.
%%
%% If you want to specify the port:
%%{odbc_server, {pgsql, "server", 1234, "database", "username", "password"}}.
%%
%% If you use PostgreSQL, have a large database, and need a
%% faster but inexact replacement for "select count(*) from users"
%%
%%{pgsql_users_number_estimate, true}.
%%
%% ODBC compatible or MSSQL server:
%%
%%{odbc_server, "DSN=ejabberd;UID=ejabberd;PWD=ejabberd"}.
%%
%% Number of connections to open to the database for each virtual host
%%
%%{odbc_pool_size, 10}.
%%
%% Interval to make a dummy SQL request to keep the connections to the
%% database alive. Specify in seconds: for example 28800 means 8 hours
%%
%%{odbc_keepalive_interval, undefined}.
%%%. ===============
%%%' TRAFFIC SHAPERS
%%
%% The "normal" shaper limits traffic speed to 1000 B/s
%%
{shaper, normal, {maxrate, 1000}}.
%%
%% The "fast" shaper limits traffic speed to 50000 B/s
%%
{shaper, fast, {maxrate, 50000}}.
%%
%% This option specifies the maximum number of elements in the queue
%% of the FSM. Refer to the documentation for details.
%%
{max_fsm_queue, 1000}.
%%%. ====================
%%%' ACCESS CONTROL LISTS
%%
%% The 'admin' ACL grants administrative privileges to XMPP accounts.
%% You can put here as many accounts as you want.
%%
%%{acl, admin, {user, "aleksey", "localhost"}}.
%%{acl, admin, {user, "ermine", "example.org"}}.
%%
%% Blocked users
%%
%%{acl, blocked, {user, "baduser", "example.org"}}.
%%{acl, blocked, {user, "test"}}.
%%
%% Local users: don't modify this line.
%%
{acl, local, {user_regexp, ""}}.
%%
%% More examples of ACLs
%%
%%{acl, jabberorg, {server, "jabber.org"}}.
%%{acl, aleksey, {user, "aleksey", "jabber.ru"}}.
%%{acl, test, {user_regexp, "^test"}}.
%%{acl, test, {user_glob, "test*"}}.
%%
%% Define specific ACLs in a virtual host.
%%
%%{host_config, "localhost",
%% [
%% {acl, admin, {user, "bob-local", "localhost"}}
%% ]
%%}.
%%%. ============
%%%' ACCESS RULES
%% Maximum number of simultaneous sessions allowed for a single user:
{access, max_user_sessions, [{10, all}]}.
%% Maximum number of offline messages that users can have:
{access, max_user_offline_messages, [{5000, admin}, {100, all}]}.
%% This rule allows access only for local users:
{access, local, [{allow, local}]}.
%% Only non-blocked users can use c2s connections:
{access, c2s, [{deny, blocked},
{allow, all}]}.
%% For C2S connections, all users except admins use the "normal" shaper
{access, c2s_shaper, [{none, admin},
{normal, all}]}.
%% All S2S connections use the "fast" shaper
{access, s2s_shaper, [{fast, all}]}.
%% Only admins can send announcement messages:
{access, announce, [{allow, admin}]}.
%% Only admins can use the configuration interface:
{access, configure, [{allow, admin}]}.
%% Admins of this server are also admins of the MUC service:
{access, muc_admin, [{allow, admin}]}.
%% Only accounts of the local ejabberd server can create rooms:
{access, muc_create, [{allow, local}]}.
%% All users are allowed to use the MUC service:
{access, muc, [{allow, all}]}.
%% Only accounts on the local ejabberd server can create Pubsub nodes:
{access, pubsub_createnode, [{allow, local}]}.
%% In-band registration allows registration of any possible username.
%% To disable in-band registration, replace 'allow' with 'deny'.
{access, register, [{allow, all}]}.
%% By default the frequency of account registrations from the same IP
%% is limited to 1 account every 10 minutes. To disable, specify: infinity
%%{registration_timeout, 600}.
%%
%% Define specific Access Rules in a virtual host.
%%
%%{host_config, "localhost",
%% [
%% {access, c2s, [{allow, admin}, {deny, all}]},
%% {access, register, [{deny, all}]}
%% ]
%%}.
%%%. ================
%%%' DEFAULT LANGUAGE
%%
%% language: Default language used for server messages.
%%
{language, "en"}.
%%
%% Set a different default language in a virtual host.
%%
%%{host_config, "localhost",
%% [{language, "ru"}]
%%}.
%%%. =======
%%%' CAPTCHA
%%
%% Full path to a script that generates the image.
%%
%%{captcha_cmd, "/lib/ejabberd/priv/bin/captcha.sh"}.
%%
%% Host for the URL and port where ejabberd listens for CAPTCHA requests.
%%
%%{captcha_host, "example.org:5280"}.
%%
%% Limit CAPTCHA calls per minute for JID/IP to avoid DoS.
%%
%%{captcha_limit, 5}.
%%%. =======
%%%' MODULES
%%
%% Modules enabled in all ejabberd virtual hosts.
%%
{modules,
[
{mod_adhoc, []},
{mod_announce, [{access, announce}]}, % recommends mod_adhoc
{mod_blocking,[]}, % requires mod_privacy
{mod_caps, []},
{mod_configure,[]}, % requires mod_adhoc
{mod_disco, []},
%%{mod_echo, [{host, "echo.localhost"}]},
{mod_irc, []},
{mod_http_bind, []},
%%{mod_http_fileserver, [
%% {docroot, "/var/www"},
%% {accesslog, "/var/log/ejabberd/access.log"}
%% ]},
{mod_last, []},
{mod_muc, [
%%{host, "conference.@HOST@"},
{access, muc},
{access_create, muc_create},
{access_persistent, muc_create},
{access_admin, muc_admin}
]},
%%{mod_muc_log,[]},
{mod_offline, [{access_max_user_messages, max_user_offline_messages}]},
{mod_ping, []},
%%{mod_pres_counter,[{count, 5}, {interval, 60}]},
{mod_privacy, []},
{mod_private, []},
%%{mod_proxy65,[]},
{mod_pubsub, [
{access_createnode, pubsub_createnode},
{ignore_pep_from_offline, true}, % reduces resource comsumption, but XEP incompliant
%%{ignore_pep_from_offline, false}, % XEP compliant, but increases resource comsumption
{last_item_cache, false},
{plugins, ["flat", "hometree", "pep"]} % pep requires mod_caps
]},
{mod_register, [
%%
%% Protect In-Band account registrations with CAPTCHA.
%%
%%{captcha_protected, true},
%%
%% Set the minimum informational entropy for passwords.
%%
%%{password_strength, 32},
%%
%% After successful registration, the user receives
%% a message with this subject and body.
%%
{welcome_message, {"Welcome!",
"Hi.\nWelcome to this XMPP server."}},
%%
%% When a user registers, send a notification to
%% these XMPP accounts.
%%
%%{registration_watchers, ["admin1@example.org"]},
%%
%% Only clients in the server machine can register accounts
%%
{ip_access, [{allow, "127.0.0.0/8"},
{deny, "0.0.0.0/0"}]},
%%
%% Local c2s or remote s2s users cannot register accounts
%%
%%{access_from, deny},
{access, register}
]},
%%{mod_register_web, [
%%
%% When a user registers, send a notification to
%% these XMPP accounts.
%%
%%{registration_watchers, ["admin1@example.org"]}
%% ]},
{mod_roster, []},
%%{mod_service_log,[]},
{mod_shared_roster,[]},
{mod_stats, []},
{mod_time, []},
{mod_vcard, []},
{mod_version, []}
]}.
%%
%% Enable modules with custom options in a specific virtual host
%%
%%{host_config, "localhost",
%% [{{add, modules},
%% [
%% {mod_echo, [{host, "mirror.localhost"}]}
%% ]
%% }
%% ]}.
%%%.
%%%'
%%% $Id$
%%% Local Variables:
%%% mode: erlang
%%% End:
%%% vim: set filetype=erlang tabstop=8 foldmarker=%%%',%%%. foldmethod=marker:
'';
# TODO properly configured wrapper
systemPackages = [ my-ejabberdctl ];
};
#exim_user = ${cfg.user}
#exim_group = ${cfg.group}
#exim_path = /var/setuid-wrappers/exim
#spool_directory = ${cfg.spoolDir}
#${cfg.config}
users.extraUsers = singleton {
name = "ejabberd";
description = "TODO";
uid = 405222;
group = "ejabberd";
home = "/var/ejabberd";
createHome = true;
};
users.extraGroups = singleton {
name = "ejabberd";
gid = 405222;
};
#security.setuidPrograms = [ "exim" ];
systemd.services.ejabberd = {
description = "ejabberd XMPP Daemon";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
reloadIfChanged = true;
serviceConfig = {
ExecStart = "${my-ejabberdctl}/bin/ejabberdctl start";
ExecStop = "${my-ejabberdctl}/bin/ejabberdctl stop";
ExecReload = "${my-ejabberdctl}/bin/ejabberdctl restart";
Type = "oneshot";
RemainAfterExit = "yes";
RestartSec = 5;
LimitNOFILE = 16000;
User = "ejabberd";
Group = "ejabberd";
};
};
systemd.services.ejabberd-prepare = {
description = "ejabberd XMPP Preparetion Service";
requiredBy = [ "ejabberd.service" ];
serviceConfig = {
Type = "oneshot";
RestartSec = 5;
ExecStart = "${writeScript "ejabberd-prepare"
''
#! /bin/sh
set -euf
chown ejabberd: /etc/nixos/secrets/ejabberd.cd.retiolum.pem
''
}";
};
};
};
#config = mkIf cfg.enable {
# environment.systemPackages = [ pkgs.ejabberd ];
# jobs.ejabberd =
# { description = "EJabberd server";
# startOn = "started network-interfaces";
# stopOn = "stopping network-interfaces";
# environment = {
# PATH = "$PATH:${pkgs.ejabberd}/sbin:${pkgs.ejabberd}/bin:${pkgs.coreutils}/bin:${pkgs.bash}/bin:${pkgs.gnused}/bin";
# };
# preStart =
# ''
# PATH="$PATH:${pkgs.ejabberd}/sbin:${pkgs.ejabberd}/bin:${pkgs.coreutils}/bin:${pkgs.bash}/bin:${pkgs.gnused}/bin";
#
# # Initialise state data
# mkdir -p ${cfg.logsDir}
# if ! test -d ${cfg.spoolDir}
# then
# initialize=1
# cp -av ${pkgs.ejabberd}/var/lib/ejabberd /var/lib
# fi
# #if ! test -d ${cfg.confDir}
# #then
# # mkdir -p ${cfg.confDir}
# # cp ${pkgs.ejabberd}/etc/ejabberd/* ${cfg.confDir}
# # sed -e 's|{hosts, \["localhost"\]}.|{hosts, \[${cfg.virtualHosts}\]}.|' ${pkgs.ejabberd}/etc/ejabberd/ejabberd.cfg > ${cfg.confDir}/ejabberd.cfg
# #fi
# mkdir -p ${cfg.confDir}
# ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} start
# ${if cfg.loadDumps == [] then "" else
# ''
# if [ "$initialize" = "1" ]
# then
# # Wait until the ejabberd server is available for use
# count=0
# while ! ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} status
# do
# if [ $count -eq 30 ]
# then
# echo "Tried 30 times, giving up..."
# exit 1
# fi
# echo "Ejabberd daemon not yet started. Waiting for 1 second..."
# count=$((count++))
# sleep 1
# done
# ${concatMapStrings (dump:
# ''
# echo "Importing dump: ${dump}"
# if [ -f ${dump} ]
# then
# ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} load ${dump}
# elif [ -d ${dump} ]
# then
# for i in ${dump}/ejabberd-dump/*
# do
# ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} load $i
# done
# fi
# '') cfg.loadDumps}
# fi
# ''}
# '';
# postStop =
# ''
# ejabberdctl --config-dir ${cfg.confDir} --logs ${cfg.logsDir} --spool ${cfg.spoolDir} stop
# '';
# };
# security.pam.services.ejabberd = {};
#};
}

View File

@ -1,93 +0,0 @@
{ pkgs, ... }:
let
lib = import ../../lib { lib = pkgs.lib; inherit pkgs; };
inherit (lib) majmin;
in
{
imports = [
{
imports = [ ../tv/users ];
tv.users.tv.packages = with pkgs; [
ascii
mpv
];
}
];
environment.systemPackages = with pkgs; [
vim
];
environment.etc."vim/vimrc".text = ''
set nocp
'';
environment.etc."vim/vim${majmin pkgs.vim.version}".source =
"${pkgs.vim}/share/vim/vim${majmin pkgs.vim.version}";
# multiple-definition-problem when defining environment.variables.EDITOR
environment.extraInit = ''
EDITOR=vim
'';
environment.shellAliases = {
# alias cal='cal -m3'
gp = "${pkgs.pari}/bin/gp -q";
df = "df -h";
du = "du -h";
# alias grep='grep --color=auto'
# TODO alias cannot contain #\'
# "ps?" = "ps ax | head -n 1;ps ax | fgrep -v ' grep --color=auto ' | grep";
# alias la='ls -lA'
lAtr = "ls -lAtr";
# alias ll='ls -l'
ls = "ls -h --color=auto --group-directories-first";
# alias vim='vim -p'
# alias vi='vim'
# alias view='vim -R'
dmesg = "dmesg -L --reltime";
};
environment.variables.VIM = "/etc/vim";
programs.bash = {
interactiveShellInit = ''
HISTCONTROL='erasedups:ignorespace'
HISTSIZE=65536
HISTFILESIZE=$HISTSIZE
shopt -s checkhash
shopt -s histappend histreedit histverify
shopt -s no_empty_cmd_completion
complete -d cd
# TODO source bridge
'';
promptInit = ''
case $UID in
0)
PS1='\[\e[1;31m\]\w\[\e[0m\] '
;;
1337)
PS1='\[\e[1;32m\]\w\[\e[0m\] '
;;
*)
PS1='\[\e[1;35m\]\u \[\e[1;32m\]\w\[\e[0m\] '
;;
esac
if test -n "$SSH_CLIENT"; then
PS1='\[\e[35m\]\h'" $PS1"
fi
if test -n "$SSH_AGENT_PID"; then
PS1="ssh-agent[$SSH_AGENT_PID] $PS1"
fi
'';
};
programs.ssh.startAgent = false;
}

View File

@ -1,126 +0,0 @@
{ config, pkgs, ... }:
{
services.exim =
# This configuration makes only sense for retiolum-enabled hosts.
# TODO modular configuration
assert config.tv.retiolum.enable;
let
# TODO get the hostname from config.tv.retiolum.
retiolumHostname = "${config.networking.hostName}.retiolum";
in
{ enable = true;
config = ''
primary_hostname = ${retiolumHostname}
domainlist local_domains = @ : localhost
domainlist relay_to_domains = *.retiolum
hostlist relay_from_hosts = <; 127.0.0.1 ; ::1
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data
host_lookup = *
rfc1413_hosts = *
rfc1413_query_timeout = 5s
log_file_path = syslog
syslog_timestamp = false
syslog_duplication = false
begin acl
acl_check_rcpt:
accept hosts = :
control = dkim_disable_verify
deny message = Restricted characters in address
domains = +local_domains
local_parts = ^[.] : ^.*[@%!/|]
deny message = Restricted characters in address
domains = !+local_domains
local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
accept local_parts = postmaster
domains = +local_domains
#accept
# hosts = *.retiolum
# domains = *.retiolum
# control = dkim_disable_verify
#require verify = sender
accept hosts = +relay_from_hosts
control = submission
control = dkim_disable_verify
accept authenticated = *
control = submission
control = dkim_disable_verify
require message = relay not permitted
domains = +local_domains : +relay_to_domains
require verify = recipient
accept
acl_check_data:
accept
begin routers
retiolum:
driver = manualroute
domains = ! ${retiolumHostname} : *.retiolum
transport = remote_smtp
route_list = ^.* $0 byname
no_more
nonlocal:
debug_print = "R: nonlocal for $local_part@$domain"
driver = redirect
domains = ! +local_domains
allow_fail
data = :fail: Mailing to remote domains not supported
no_more
local_user:
# debug_print = "R: local_user for $local_part@$domain"
driver = accept
check_local_user
# local_part_suffix = +* : -*
# local_part_suffix_optional
transport = home_maildir
cannot_route_message = Unknown user
begin transports
remote_smtp:
driver = smtp
home_maildir:
driver = appendfile
maildir_format
directory = $home/Maildir
directory_mode = 0700
delivery_date_add
envelope_to_add
return_path_add
# group = mail
# mode = 0660
begin retry
*.retiolum * F,42d,1m
* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
begin rewrite
begin authenticators
'';
};
}

View File

@ -1,474 +0,0 @@
{ config, pkgs, ... }:
let
inherit (builtins) toFile;
inherit (pkgs.lib.attrsets) mapAttrs;
inherit (pkgs.lib.strings) concatMapStringsSep;
in
{
services.exim =
let
retiolumHostname = "${config.networking.hostName}.retiolum";
internet-aliases = [
{ from = "tomislav@viljetic.de"; to = "tv@wu.retiolum"; }
# (mindestens) lisp-stammtisch und elli haben die:
{ from = "tv@viljetic.de"; to = "tv@wu.retiolum"; }
{ from = "tv@destroy.dyn.shackspace.de"; to = "tv@wu.retiolum"; }
{ from = "mirko@viljetic.de"; to = "mv@cd.retiolum"; }
# TODO killme (wo wird die benutzt?)
{ from = "tv@cd.retiolum"; to = "tv@wu.retiolum"; }
{ from = "postmaster@krebsco.de"; to = "tv@wu.retiolum"; }
];
system-aliases = [
{ from = "mailer-daemon"; to = "postmaster"; }
{ from = "postmaster"; to = "root"; }
{ from = "nobody"; to = "root"; }
{ from = "hostmaster"; to = "root"; }
{ from = "usenet"; to = "root"; }
{ from = "news"; to = "root"; }
{ from = "webmaster"; to = "root"; }
{ from = "www"; to = "root"; }
{ from = "ftp"; to = "root"; }
{ from = "abuse"; to = "root"; }
{ from = "noc"; to = "root"; }
{ from = "security"; to = "root"; }
{ from = "root"; to = "tv"; }
{ from = "mirko"; to = "mv"; }
];
to-lsearch = concatMapStringsSep "\n" ({ from, to }: "${from}: ${to}");
lsearch =
mapAttrs (name: set: toFile name (to-lsearch set)) {
inherit internet-aliases;
inherit system-aliases;
};
in
{
enable = true;
config =
''
primary_hostname = ${retiolumHostname}
# 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
#: viljetic.de : SHACK_REDIR_HOSTNAME
domainlist relay_to_domains =
hostlist relay_from_hosts = <; 127.0.0.1 ; ::1 ; 10.243.13.37
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data
# av_scanner = clamd:/tmp/clamd
# spamd_address = 127.0.0.1 783
# tls_advertise_hosts = *
# tls_certificate = /etc/ssl/exim.crt
# tls_privatekey = /etc/ssl/exim.pem
# (debian) tls_verify_certificates (to check client certs)
# daemon_smtp_ports = 25 : 465 : 587
# tls_on_connect_ports = 465
# qualify_domain defaults to primary_hostname
# qualify_recipient defaults to qualify_domain
# allow_domain_literals
never_users = root
host_lookup = *
# ident callbacks for all incoming SMTP calls
rfc1413_hosts = *
rfc1413_query_timeout = 5s
# sender_unqualified_hosts =
# recipient_unqualified_hosts =
# percent_hack_domains =
# arch & debian
#ignore_bounce_errors_after = 2d
#timeout_frozen_after = 7d
# debian
#smtp_banner = $smtp_active_hostname ESMTP Exim $version_number $tod_full
#freeze_tell = postmaster
#trusted_users = uucp
# arch
#split_spool_directory = true
log_selector = -queue_run +address_rewrite +all_parents +queue_time
log_file_path = syslog
syslog_timestamp = false
syslog_duplication = false
begin acl
acl_check_rcpt:
# Accept if the source is local SMTP (i.e. not over TCP/IP).
# We do this by testing for an empty sending host field.
accept hosts = :
# arch & debian:
control = dkim_disable_verify
deny message = Restricted characters in address
domains = +local_domains
local_parts = ^[.] : ^.*[@%!/|]
deny message = Restricted characters in address
domains = !+local_domains
local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
accept local_parts = postmaster
domains = +local_domains
## feature RETIOLUM_MAIL
#accept
# hosts = *.retiolum
# domains = *.retiolum
# control = dkim_disable_verify
#require verify = sender
accept hosts = +relay_from_hosts
control = submission
# debian: control = submission/sender_retain
# arch & debian:
control = dkim_disable_verify
accept authenticated = *
control = submission
control = dkim_disable_verify
accept message = relay not permitted 2
recipients = lsearch;${lsearch.internet-aliases}
require message = relay not permitted
domains = +local_domains : +relay_to_domains
require
message = unknown user
verify = recipient/callout
# deny message = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
# dnslists = black.list.example
#
# warn dnslists = black.list.example
# add_header = X-Warning: $sender_host_address is in a black list at $dnslist_domain
# log_message = found in $dnslist_domain
# Client SMTP Authorization (csa) checks on the sending host.
# Such checks do DNS lookups for special SRV records.
# require verify = csa
accept
acl_check_data:
# see av_scanner
#deny malware = *
# message = This message contains a virus ($malware_name).
# Add headers to a message if it is judged to be spam. Before enabling this,
# you must install SpamAssassin. You may also need to set the spamd_address
# option above.
#
# warn spam = nobody
# add_header = X-Spam_score: $spam_score\n\
# X-Spam_score_int: $spam_score_int\n\
# X-Spam_bar: $spam_bar\n\
# X-Spam_report: $spam_report
# feature HELO_REWRITE
# XXX note that the public ip (162.219.5.183) resolves to viljetic.de
warn
sender_domains = viljetic.de : shackspace.de
set acl_m_special_dom = $sender_address_domain
accept
begin routers
# feature RETIOLUM_MAIL
retiolum:
debug_print = "R: retiolum for $local_part@$domain"
driver = manualroute
domains = ! ${retiolumHostname} : *.retiolum
transport = retiolum_smtp
route_list = ^.* $0 byname
no_more
internet_aliases:
debug_print = "R: internet_aliases for $local_part@$domain"
driver = redirect
data = ''${lookup{$local_part@$domain}lsearch{${lsearch.internet-aliases}}}
dnslookup:
debug_print = "R: dnslookup for $local_part@$domain"
driver = dnslookup
domains = ! +local_domains
transport = remote_smtp
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
# if ipv6-enabled then instead use:
# ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1
# (debian) same_domain_copy_routing = yes
# (debian) ignore private rfc1918 and APIPA addresses
# (debian) ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 : 192.168.0.0/16 :\
# 172.16.0.0/12 : 10.0.0.0/8 : 169.254.0.0/16 :\
# 255.255.255.255
# Fail and bounce if the router does not find the domain in the DNS.
# I.e. no more routers are tried.
# There are a few cases where a dnslookup router will decline to accept an
# address; if such a router is expected to handle "all remaining non-local
# domains", then it is important to set no_more.
no_more
# XXX this is only used because these "well known aliases" goto tv@cd.retiolum
# TODO bounce everything, there is no @cd.retiolum
system_aliases:
debug_print = "R: system_aliases for $local_part@$domain"
driver = redirect
data = ''${lookup{$local_part}lsearch{${lsearch.system-aliases}}}
# TODO this is only b/c mv here... send mv's mails somewhere else...
local_user:
debug_print = "R: local_user for $local_part@$domain"
driver = accept
check_local_user
# local_part_suffix = +* : -*
# local_part_suffix_optional
transport = home_maildir
cannot_route_message = Unknown user
begin transports
retiolum_smtp:
driver = smtp
retry_include_ip_address = false
# serialize_hosts = TODO-all-slow-hosts
remote_smtp:
driver = smtp
# debian has also stuff for tls, headers_rewrite and more here
# feature HELO_REWRITE
# XXX note that the public ip (162.219.5.183) resolves to viljetic.de
helo_data = ''${if eq{$acl_m_special_dom}{} \
{$primary_hostname} \
{$acl_m_special_dom} }
home_maildir:
driver = appendfile
maildir_format
maildir_use_size_file
directory = $home/Mail
directory_mode = 0700
delivery_date_add
envelope_to_add
return_path_add
begin retry
*.retiolum * F,42d,1m
* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
begin rewrite
begin authenticators
'';
# group = mail
# mode = 0660
#address_pipe:
# driver = pipe
# return_output
#
#address_file:
# driver = appendfile
# delivery_date_add
# envelope_to_add
# return_path_add
#
#address_reply:
# driver = autoreply
#maildrop_pipe:
# debug_print = "T: maildrop_pipe for $local_part@$domain"
# driver = pipe
# path = "/bin:/usr/bin:/usr/local/bin"
# command = "/usr/bin/maildrop"
# return_path_add
# delivery_date_add
# envelope_to_add
##begin retry
# Address or Domain Error Retries
# Our host_redirect destinations might be offline a lot.
# TODO define fallback destinations(?)
#lsearch;${lsearch.internet-aliases} * F,42d,1m
## begin rewrite
# just in case (shackspace.de should already do this)
#tv@shackspace.de tv@SHACK_REDIR_HOSTNAME T
## begin authenticators
#PLAIN:
# driver = plaintext
# server_set_id = $auth2
# server_prompts = :
# server_condition = Authentication is not yet configured
# server_advertise_condition = ''${if def:tls_in_cipher }
#LOGIN:
# driver = plaintext
# server_set_id = $auth1
# server_prompts = <| Username: | Password:
# server_condition = Authentication is not yet configured
# server_advertise_condition = ''${if def:tls_in_cipher }
};
}
# config = ''
# primary_hostname = ${retiolumHostname}
# domainlist local_domains = @ : localhost
# domainlist relay_to_domains = *.retiolum
# hostlist relay_from_hosts = <; 127.0.0.1 ; ::1
#
# acl_smtp_rcpt = acl_check_rcpt
# acl_smtp_data = acl_check_data
#
# host_lookup = *
# rfc1413_hosts = *
# rfc1413_query_timeout = 5s
#
# log_file_path = syslog
# syslog_timestamp = false
# syslog_duplication = false
#
# begin acl
#
# acl_check_rcpt:
# accept hosts = :
# control = dkim_disable_verify
#
# deny message = Restricted characters in address
# domains = +local_domains
# local_parts = ^[.] : ^.*[@%!/|]
#
# deny message = Restricted characters in address
# domains = !+local_domains
# local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
#
# accept local_parts = postmaster
# domains = +local_domains
#
# #accept
# # hosts = *.retiolum
# # domains = *.retiolum
# # control = dkim_disable_verify
#
# #require verify = sender
#
# accept hosts = +relay_from_hosts
# control = submission
# control = dkim_disable_verify
#
# accept authenticated = *
# control = submission
# control = dkim_disable_verify
#
# require message = relay not permitted
# domains = +local_domains : +relay_to_domains
#
# require verify = recipient
#
# accept
#
#
# acl_check_data:
# accept
#
#
# begin routers
#
# retiolum:
# driver = manualroute
# domains = ! ${retiolumHostname} : *.retiolum
# transport = remote_smtp
# route_list = ^.* $0 byname
# no_more
#
# nonlocal:
# debug_print = "R: nonlocal for $local_part@$domain"
# driver = redirect
# domains = ! +local_domains
# allow_fail
# data = :fail: Mailing to remote domains not supported
# no_more
#
# local_user:
# # debug_print = "R: local_user for $local_part@$domain"
# driver = accept
# check_local_user
# # local_part_suffix = +* : -*
# # local_part_suffix_optional
# transport = home_maildir
# cannot_route_message = Unknown user
#
#
# begin transports
#
# remote_smtp:
# driver = smtp
#
# home_maildir:
# driver = appendfile
# maildir_format
# directory = $home/Maildir
# directory_mode = 0700
# delivery_date_add
# envelope_to_add
# return_path_add
# # group = mail
# # mode = 0660
#
# begin retry
# *.retiolum * F,42d,1m
# * * F,2h,15m; G,16h,1h,1.5; F,4d,6h
#
# begin rewrite
#
# begin authenticators
# '';
# };
#}

View File

@ -1,93 +0,0 @@
{ cfg, config, lib, pkgs, ... }:
let
inherit (builtins) attrValues filter getAttr;
inherit (lib) concatMapStringsSep mkIf optionalString;
location = lib.nameValuePair; # TODO this is also in modules/wu/default.nix
isPublicRepo = getAttr "public"; # TODO this is also in ./default.nix
in
{
users.extraUsers = lib.singleton {
name = "fcgiwrap";
uid = 2851179180; # genid fcgiwrap
group = "fcgiwrap";
home = toString (pkgs.runCommand "empty" {} "mkdir -p $out");
};
users.extraGroups = lib.singleton {
name = "fcgiwrap";
gid = 2851179180; # genid fcgiwrap
};
services.fcgiwrap = {
enable = true;
user = "fcgiwrap";
group = "fcgiwrap";
# socketAddress = "/run/fcgiwrap.sock" (default)
# socketType = "unix" (default)
};
environment.etc."cgitrc".text = ''
css=/cgit-static/cgit.css
logo=/cgit-static/cgit.png
# if you do not want that webcrawler (like google) index your site
robots=noindex, nofollow
virtual-root=/cgit
# TODO make this nicer (and/or somewhere else)
cache-root=/tmp/cgit
cache-size=1000
enable-commit-graph=1
enable-index-links=1
enable-index-owner=0
enable-log-filecount=1
enable-log-linecount=1
enable-remote-branches=1
root-title=public repositories at ${config.networking.hostName}
root-desc=keep calm and engage
snapshots=0
max-stats=year
${concatMapStringsSep "\n" (repo: ''
repo.url=${repo.name}
repo.path=${cfg.dataDir}/${repo.name}
${optionalString (repo.section != null) "repo.section=${repo.section}"}
${optionalString (repo.desc != null) "repo.desc=${repo.desc}"}
'') (filter isPublicRepo (attrValues cfg.repos))}
'';
system.activationScripts.cgit = ''
mkdir -m 0700 -p /tmp/cgit
chown fcgiwrap: /tmp/cgit
'';
tv.nginx = {
enable = true;
retiolum-locations = [
(location "/cgit/" ''
include ${pkgs.nginx}/conf/fastcgi_params;
fastcgi_param SCRIPT_FILENAME ${pkgs.cgit}/cgit/cgit.cgi;
fastcgi_split_path_info ^(/cgit/?)(.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param QUERY_STRING $args;
fastcgi_param HTTP_HOST $server_name;
fastcgi_pass unix:${config.services.fcgiwrap.socketAddress};
'')
(location "= /cgit" ''
return 301 /cgit/;
'')
(location "/cgit-static/" ''
root ${pkgs.cgit}/cgit;
rewrite ^/cgit-static(/.*)$ $1 break;
'')
];
};
}

View File

@ -1,272 +0,0 @@
arg@{ cfg, lib, pkgs, ... }:
let
inherit (builtins) head tail typeOf;
inherit (lib)
attrValues concatStringsSep concatMapStringsSep escapeShellArg filter
getAttr hasAttr hasPrefix lessThan makeSearchPath mapAttrsToList
optional optionalString removePrefix singleton sort unique;
inherit (pkgs) linkFarm writeScript;
ensureList = x:
if typeOf x == "list" then x else [x];
getName = x: x.name;
isPublicRepo = getAttr "public"; # TODO this is also in ./cgit.nix
makeAuthorizedKey = git-ssh-command: user@{ name, pubkey }:
# TODO assert name
# TODO assert pubkey
let
options = concatStringsSep "," [
''command="exec ${git-ssh-command} ${name}"''
"no-agent-forwarding"
"no-port-forwarding"
"no-pty"
"no-X11-forwarding"
];
in
"${options} ${pubkey}";
# [case-pattern] -> shell-script
# Create a shell script that succeeds (exit 0) when all its arguments
# match the case patterns (in the given order).
makeAuthorizeScript =
let
# TODO escape
to-pattern = x: concatStringsSep "|" (ensureList x);
go = i: ps:
if ps == []
then "exit 0"
else ''
case ''$${toString i} in ${to-pattern (head ps)})
${go (i + 1) (tail ps)}
esac'';
in
patterns: ''
#! /bin/sh
set -euf
${concatStringsSep "\n" (map (go 1) patterns)}
exit -1
'';
reponames = rules: sort lessThan (unique (map (x: x.repo.name) rules));
# TODO makeGitHooks that uses runCommand instead of scriptFarm?
scriptFarm =
farm-name: scripts:
let
makeScript = script-name: script-string: {
name = script-name;
path = writeScript "${farm-name}_${script-name}" script-string;
};
in
linkFarm farm-name (mapAttrsToList makeScript scripts);
git-ssh-command = writeScript "git-ssh-command" ''
#! /bin/sh
set -euf
PATH=${makeSearchPath "bin" (with pkgs; [
coreutils
git
gnugrep
gnused
systemd
])}
abort() {
echo "error: $1" >&2
systemd-cat -p err -t git echo "error: $1"
exit -1
}
GIT_SSH_USER=$1
systemd-cat -p info -t git echo \
"authorizing $GIT_SSH_USER $SSH_CONNECTION $SSH_ORIGINAL_COMMAND"
# References: The Base Definitions volume of
# POSIX.12013, Section 3.278, Portable Filename Character Set
portable_filename_bre="^[A-Za-z0-9._-]\\+$"
command=$(echo "$SSH_ORIGINAL_COMMAND" \
| sed -n 's/^\([^ ]*\) '"'"'\(.*\)'"'"'/\1/p' \
| grep "$portable_filename_bre" \
|| abort 'cannot read command')
GIT_SSH_REPO=$(echo "$SSH_ORIGINAL_COMMAND" \
| sed -n 's/^\([^ ]*\) '"'"'\(.*\)'"'"'/\2/p' \
| grep "$portable_filename_bre" \
|| abort 'cannot read reponame')
${cfg.etcDir}/authorize-command \
"$GIT_SSH_USER" "$GIT_SSH_REPO" "$command" \
|| abort 'access denied'
repodir=${escapeShellArg cfg.dataDir}/$GIT_SSH_REPO
systemd-cat -p info -t git \
echo "authorized exec $command $repodir"
export GIT_SSH_USER
export GIT_SSH_REPO
exec "$command" "$repodir"
'';
init-script = writeScript "git-init" ''
#! /bin/sh
set -euf
PATH=${makeSearchPath "bin" (with pkgs; [
coreutils
findutils
gawk
git
gnugrep
gnused
])}
dataDir=${escapeShellArg cfg.dataDir}
mkdir -p "$dataDir"
# Notice how the presence of hooks symlinks determine whether
# we manage a repositry or not.
# Make sure that no existing repository has hooks. We can delete
# symlinks because we assume we created them.
find "$dataDir" -mindepth 2 -maxdepth 2 -name hooks -type l -delete
bad_hooks=$(find "$dataDir" -mindepth 2 -maxdepth 2 -name hooks)
if echo "$bad_hooks" | grep -q .; then
printf 'error: unknown hooks:\n%s\n' \
"$(echo "$bad_hooks" | sed 's/^/ /')" \
>&2
exit -1
fi
# Initialize repositories.
${concatMapStringsSep "\n" (repo:
let
hooks = scriptFarm "git-hooks" (makeHooks repo);
in
''
reponame=${escapeShellArg repo.name}
repodir=$dataDir/$reponame
mode=${toString (if isPublicRepo repo then 0711 else 0700)}
if ! test -d "$repodir"; then
mkdir -m "$mode" "$repodir"
git init --bare --template=/var/empty "$repodir"
chown -R git:nogroup "$repodir"
fi
ln -s ${hooks} "$repodir/hooks"
''
) (attrValues cfg.repos)}
# Warn about repositories that exist but aren't mentioned in the
# current configuration (and thus didn't receive a hooks symlink).
unknown_repos=$(find "$dataDir" -mindepth 1 -maxdepth 1 \
-type d \! -exec test -e '{}/hooks' \; -print)
if echo "$unknown_repos" | grep -q .; then
printf 'warning: stale repositories:\n%s\n' \
"$(echo "$unknown_repos" | sed 's/^/ /')" \
>&2
fi
'';
makeHooks = repo: removeAttrs repo.hooks [ "pre-receive" ] // {
pre-receive = ''
#! /bin/sh
set -euf
PATH=${makeSearchPath "bin" (with pkgs; [
coreutils # env
git
systemd
])}
accept() {
#systemd-cat -p info -t git echo "authorized $1"
accept_string="''${accept_string+$accept_string
}authorized $1"
}
reject() {
#systemd-cat -p err -t git echo "denied $1"
#echo 'access denied' >&2
#exit_code=-1
reject_string="''${reject_string+$reject_string
}access denied: $1"
}
empty=0000000000000000000000000000000000000000
accept_string=
reject_string=
while read oldrev newrev ref; do
if [ $oldrev = $empty ]; then
receive_mode=create
elif [ $newrev = $empty ]; then
receive_mode=delete
elif [ "$(git merge-base $oldrev $newrev)" = $oldrev ]; then
receive_mode=fast-forward
else
receive_mode=non-fast-forward
fi
if ${cfg.etcDir}/authorize-push \
"$GIT_SSH_USER" "$GIT_SSH_REPO" "$ref" "$receive_mode"; then
accept "$receive_mode $ref"
else
reject "$receive_mode $ref"
fi
done
if [ -n "$reject_string" ]; then
systemd-cat -p err -t git echo "$reject_string"
exit -1
fi
systemd-cat -p info -t git echo "$accept_string"
${optionalString (hasAttr "post-receive" repo.hooks) ''
# custom post-receive hook
${repo.hooks.post-receive}''}
'';
};
etc-base =
assert (hasPrefix "/etc/" cfg.etcDir);
removePrefix "/etc/" cfg.etcDir;
in
{
system.activationScripts.git-init = "${init-script}";
# TODO maybe put all scripts here and then use PATH?
environment.etc."${etc-base}".source =
scriptFarm "git-ssh-authorizers" {
authorize-command = makeAuthorizeScript (map ({ repo, user, perm }: [
(map getName (ensureList user))
(map getName (ensureList repo))
(map getName perm.allow-commands)
]) cfg.rules);
authorize-push = makeAuthorizeScript (map ({ repo, user, perm }: [
(map getName (ensureList user))
(map getName (ensureList repo))
(ensureList perm.allow-receive-ref)
(map getName perm.allow-receive-modes)
]) (filter (x: hasAttr "allow-receive-ref" x.perm) cfg.rules));
};
users.extraUsers = singleton {
description = "Git repository hosting user";
name = "git";
shell = "/bin/sh";
openssh.authorizedKeys.keys =
mapAttrsToList (_: makeAuthorizedKey git-ssh-command) cfg.users;
uid = 112606723; # genid git
};
}

View File

@ -1,27 +0,0 @@
arg@{ config, pkgs, lib, ... }:
let
inherit (lib) mkIf mkMerge;
cfg = config.tv.git;
arg' = arg // { inherit cfg; };
in
# TODO unify logging of shell scripts to user and journal
# TODO move all scripts to ${etcDir}, so ControlMaster connections
# immediately pick up new authenticators
# TODO when authorized_keys changes, then restart ssh
# (or kill already connected users somehow)
{
imports = [
../../tv/nginx
];
options.tv.git = import ./options.nix arg';
config = mkIf cfg.enable (mkMerge [
(import ./config.nix arg')
(mkIf cfg.cgit (import ./cgit.nix arg'))
]);
}

View File

@ -1,93 +0,0 @@
{ lib, ... }:
let
inherit (lib) literalExample mkOption types;
in
{
enable = mkOption {
type = types.bool;
default = false;
description = "Enable Git repository hosting.";
};
cgit = mkOption {
type = types.bool;
default = true;
description = "Enable cgit."; # TODO better desc; talk about nginx
};
dataDir = mkOption {
type = types.str;
default = "/var/lib/git";
description = "Directory used to store repositories.";
};
etcDir = mkOption {
type = types.str;
default = "/etc/git";
};
rules = mkOption {
type = types.unspecified;
};
repos = mkOption {
type = types.attrsOf (types.submodule ({
options = {
desc = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Repository description.
'';
};
section = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Repository section.
'';
};
name = mkOption {
type = types.str;
description = ''
Repository name.
'';
};
hooks = mkOption {
type = types.attrsOf types.str;
description = ''
Repository-specific hooks.
'';
};
public = mkOption {
type = types.bool;
default = false;
description = ''
Allow everybody to read the repository via HTTP if cgit enabled.
'';
# TODO allow every configured user to fetch the repository via SSH.
};
};
}));
default = {};
example = literalExample ''
{
testing = {
name = "testing";
hooks.post-update = '''
#! /bin/sh
set -euf
echo post-update hook: $* >&2
''';
};
testing2 = { name = "testing2"; };
}
'';
description = ''
Repositories.
'';
};
users = mkOption {
type = types.unspecified;
};
}

View File

@ -1,82 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (builtins) map readFile;
inherit (lib) concatMap listToAttrs;
# TODO lib should already include our stuff
inherit (import ../../../lib { inherit lib pkgs; }) addNames git;
public-git-repos = [
(public "cgserver")
(public "crude-mail-setup")
(public "dot-xmonad")
(public "hack")
(public "load-env")
(public "make-snapshot")
(public "mime")
(public "much")
(public "nixos-infest")
(public "nixpkgs")
(public "painload")
(public "regfish")
(public' {
name = "shitment";
desc = "turn all the computers into one computer!";
})
(public "wai-middleware-time")
(public "web-routes-wai-custom")
];
users = addNames {
tv = { pubkey = readFile <pubkeys/tv_wu.ssh.pub>; };
lass = { pubkey = readFile <pubkeys/lass.ssh.pub>; };
uriel = { pubkey = readFile <pubkeys/uriel.ssh.pub>; };
makefu = { pubkey = readFile <pubkeys/makefu.ssh.pub>; };
};
repos = listToAttrs (map ({ repo, ... }: { name = repo.name; value = repo; }) public-git-repos);
rules = concatMap ({ rules, ... }: rules) public-git-repos;
public' = { name, desc }:
let
x = public name;
in
x // { repo = x.repo // { inherit desc; }; };
public = repo-name:
rec {
repo = {
name = repo-name;
hooks = {
post-receive = git.irc-announce {
nick = config.networking.hostName; # TODO make this the default
channel = "#retiolum";
server = "ire.retiolum";
};
};
public = true;
};
rules = with git; with users; [
{ user = tv;
repo = [ repo ];
perm = push "refs/*" [ non-fast-forward create delete merge ];
}
{ user = [ lass makefu uriel ];
repo = [ repo ];
perm = fetch;
}
];
};
in
{
imports = [
./.
];
tv.git = {
enable = true;
inherit repos rules users;
};
}

View File

@ -1,71 +0,0 @@
{ lib, ... }:
with lib;
let
cfg = config.tv.identity;
out = {
options.tv.identity = api;
#config = mkIf cfg.enable imp;
};
api = {
enable = mkOption {
type = types.bool;
default = false;
};
self = mkOption {
type = types.unspecified;
};
hosts = mkOption {
type = with types; attrsOf unspecified;
default = {
cd = {
#dc = "cac";
dc = "tv";
fqdn = "cd.retiolum";
addr = "10.243.113.222";
#addr6 = "42:4522:25f8:36bb:8ccb:0150:231a:2af3";
#internet-addr = "162.219.5.183";
cores = 2;
};
mkdir = {
#dc = "cac";
dc = "tv";
fqdn = "mkdir.retiolum";
addr = "10.243.113.223";
cores = 1;
};
nomic = {
#dc = "gg";
dc = "tv";
fqdn = "nomic.retiolum";
addr = "10.243.0.110";
cores = 2;
};
rmdir = {
#dc = "cac";
dc = "tv";
fqdn = "rmdir.retiolum";
addr = "10.243.113.224";
#addr = "42:4522:25f8:36bb:8ccb:0150:231a:2af5";
cores = 1;
};
wu = {
#dc = "gg";
dc = "tv";
fqdn = "wu.retiolum";
addr = "10.243.13.37";
cores = 8;
};
};
};
};
#imp = {
#};
in
out

View File

@ -1,93 +0,0 @@
{ cfg, lib, pkgs, ... }:
let
inherit (pkgs) writeScript writeText;
inherit (lib) concatMapStringsSep;
accept-new-tcp = port:
"-p tcp -m tcp --dport ${port} -m conntrack --ctstate NEW -j ACCEPT";
rules = iptables-version:
writeText "tv-iptables-rules${toString iptables-version}" ''
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
${concatMapStringsSep "\n" (rule: "-A PREROUTING ${rule}") ([]
++ [
"! -i retiolum -p tcp -m tcp --dport 22 -j REDIRECT --to-ports 0"
"-p tcp -m tcp --dport 11423 -j REDIRECT --to-ports 22"
]
)}
COMMIT
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:Retiolum - [0:0]
${concatMapStringsSep "\n" (rule: "-A INPUT ${rule}") ([]
++ [
"-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT"
"-i lo -j ACCEPT"
]
++ map accept-new-tcp cfg.input-internet-accept-new-tcp
++ ["-i retiolum -j Retiolum"]
)}
${concatMapStringsSep "\n" (rule: "-A Retiolum ${rule}") ([]
++ {
ip4tables = [
"-p icmp -m icmp --icmp-type echo-request -j ACCEPT"
];
ip6tables = [
"-p ipv6-icmp -m icmp6 --icmpv6-type echo-request -j ACCEPT"
];
}."ip${toString iptables-version}tables"
++ map accept-new-tcp cfg.input-retiolum-accept-new-tcp
++ {
ip4tables = [
"-p tcp -j REJECT --reject-with tcp-reset"
"-p udp -j REJECT --reject-with icmp-port-unreachable"
"-j REJECT --reject-with icmp-proto-unreachable"
];
ip6tables = [
"-p tcp -j REJECT --reject-with tcp-reset"
"-p udp -j REJECT --reject-with icmp6-port-unreachable"
"-j REJECT"
];
}."ip${toString iptables-version}tables"
)}
COMMIT
'';
startScript = writeScript "tv-iptables_start" ''
#! /bin/sh
set -euf
iptables-restore < ${rules 4}
ip6tables-restore < ${rules 6}
'';
in
{
networking.firewall.enable = false;
systemd.services.tv-iptables = {
description = "tv-iptables";
wantedBy = [ "network-pre.target" ];
before = [ "network-pre.target" ];
after = [ "systemd-modules-load.service" ];
path = with pkgs; [
iptables
];
restartIfChanged = true;
serviceConfig = {
Type = "simple";
RemainAfterExit = true;
Restart = "always";
ExecStart = "@${startScript} tv-iptables_start";
};
};
}

View File

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

View File

@ -1,29 +0,0 @@
{ lib, ... }:
let
inherit (lib) mkOption types;
in
{
enable = mkOption {
type = types.bool;
default = false;
description = "Enable iptables.";
};
input-internet-accept-new-tcp = mkOption {
type = with types; listOf str;
default = [];
description = ''
TCP ports, accepting incoming connections from anywhere.
'';
};
input-retiolum-accept-new-tcp = mkOption {
type = with types; listOf str;
default = [];
description = ''
TCP ports, accepting incoming connections from Retiolum.
'';
};
}

View File

@ -1,49 +0,0 @@
{ cfg, config, lib, pkgs, ... }:
let
inherit (lib) concatStrings replaceChars;
indent = replaceChars ["\n"] ["\n "];
to-location = { name, value }: ''
location ${name} {
${indent value}
}
'';
in
{
services.nginx =
let
name = config.tv.retiolum.name;
qname = "${name}.retiolum";
in
assert config.tv.retiolum.enable;
{
enable = true;
httpConfig = ''
include ${pkgs.nginx}/conf/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
server {
listen 80 default_server;
server_name _;
location / {
return 404;
}
}
server {
listen 80;
server_name ${name} ${qname};
${indent (concatStrings (map to-location cfg.retiolum-locations))}
location / {
return 404;
}
}
'';
};
}

View File

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

View File

@ -1,21 +0,0 @@
{ lib, ... }:
let
inherit (lib) mkOption types;
in
{
enable = mkOption {
type = types.bool;
default = false;
description = "Enable nginx.";
};
retiolum-locations = mkOption {
type = with types; listOf (attrsOf str);
default = [];
description = ''
TODO
'';
};
}

View File

@ -1,130 +0,0 @@
{ 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";
};
};
users.extraUsers = singleton {
name = user;
uid = 2961822815; # bin/genid retiolum-tinc
};
}

View File

@ -1,11 +0,0 @@
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

@ -1,87 +0,0 @@
{ 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

@ -1,12 +0,0 @@
{ ... }:
{
nixpkgs.config.packageOverrides = pkgs:
{
nano = pkgs.runCommand "empty" {} "mkdir -p $out";
};
services.cron.enable = false;
services.nscd.enable = false;
services.ntp.enable = false;
}

View File

@ -1,17 +0,0 @@
{ config, pkgs, ... }:
{
services.smartd = {
enable = true;
devices = [
{
device = "DEVICESCAN";
options = toString [
"-a"
"-m tv@wu.retiolum"
"-s (O/../.././09|S/../.././04|L/../../6/05)"
];
}
];
};
}

View File

@ -1,14 +0,0 @@
{ config, pkgs, ... }:
{
# TODO this is host specific
services.xserver.synaptics = {
enable = true;
twoFingerScroll = true;
accelFactor = "0.035";
additionalOptions = ''
Option "FingerHigh" "60"
Option "FingerLow" "60"
'';
};
}

Some files were not shown because too many files have changed in this diff Show More