Merge remote-tracking branch 'ni/master'

This commit is contained in:
lassulus 2022-10-19 00:30:26 +02:00
commit c68da76ea1
9 changed files with 325 additions and 260 deletions

View File

@ -9,6 +9,48 @@ let
hooks = pkgs.reaktor2-plugins.hooks;
commands = pkgs.reaktor2-plugins.commands;
# bedger - the bier ledger
#
# logo: http://c.r/bedger2
#
bedger-add = {
pattern = ''^([\H-]*?):?\s+([+-][1-9][0-9]*)\s+(\S+)$'';
activate = "match";
arguments = [1 2 3];
command = {
env = {
# TODO; get state as argument
state_file = "${stateDir}/ledger";
};
filename = pkgs.writeDash "bedger-add" ''
set -x
tonick=$1
amt=$2
unit=$3
printf '%s\n %s %d %s\n %s %d %s\n' "$(date -Id)" "$tonick" "$amt" "$unit" "$_from" "$(expr 0 - "''${amt#+}")" "$unit" >> $state_file
${pkgs.hledger}/bin/hledger -f $state_file bal -N -O csv \
| ${pkgs.coreutils}/bin/tail +2 \
| ${pkgs.miller}/bin/mlr --icsv --opprint cat \
| ${pkgs.gnugrep}/bin/grep "$_from"
'';
};
};
bedger-balance = {
pattern = "^bier (ballern|bal(an(ce)?)?)$";
activate = "match";
command = {
env = {
state_file = "${stateDir}/ledger";
};
filename = pkgs.writeDash "bedger-balance" ''
${pkgs.hledger}/bin/hledger -f $state_file bal -N -O csv \
| ${pkgs.coreutils}/bin/tail +2 \
| ${pkgs.miller}/bin/mlr --icsv --opprint cat \
| ${pkgs.gnused}/bin/sed 's/^\(.\)/\1/'
'';
};
};
taskRcFile = builtins.toFile "taskrc" ''
confirmation=no
'';
@ -92,21 +134,6 @@ let
}
];
hooks.PRIVMSG = [
{
pattern = "^bier (ballern|bal(an(ce)?)?)$";
activate = "match";
command = {
env = {
state_file = "${stateDir}/ledger";
};
filename = pkgs.writeDash "bier-balance" ''
${pkgs.hledger}/bin/hledger -f $state_file bal -N -O csv \
| ${pkgs.coreutils}/bin/tail +2 \
| ${pkgs.miller}/bin/mlr --icsv --opprint cat \
| ${pkgs.gnused}/bin/sed 's/^\(.\)/\1/'
'';
};
}
{
pattern = "^list-locations";
activate = "match";
@ -205,6 +232,8 @@ let
'';
};
}
bedger-add
bedger-balance
hooks.sed
(generators.command_hook {
inherit (commands) dance random-emoji nixos-version;

View File

@ -25,8 +25,7 @@ let
./exim.nix
./fetchWallpaper.nix
./git.nix
./github-hosts-sync.nix
./github-known-hosts.nix
./github
./go.nix
./hidden-ssh.nix
./hosts.nix

View File

@ -1,78 +0,0 @@
{
services.openssh.knownHosts.github = {
hostNames = [
"github.com"
# List generated with (IPv6 addresses are currently ignored):
# curl -sS https://api.github.com/meta | jq -r .git[] | grep -v : | nix-shell -p cidr2glob --run cidr2glob | jq -R .
"192.30.252.*"
"192.30.253.*"
"192.30.254.*"
"192.30.255.*"
"185.199.108.*"
"185.199.109.*"
"185.199.110.*"
"185.199.111.*"
"140.82.112.*"
"140.82.113.*"
"140.82.114.*"
"140.82.115.*"
"140.82.116.*"
"140.82.117.*"
"140.82.118.*"
"140.82.119.*"
"140.82.120.*"
"140.82.121.*"
"140.82.122.*"
"140.82.123.*"
"140.82.124.*"
"140.82.125.*"
"140.82.126.*"
"140.82.127.*"
"143.55.64.*"
"143.55.65.*"
"143.55.66.*"
"143.55.67.*"
"143.55.68.*"
"143.55.69.*"
"143.55.70.*"
"143.55.71.*"
"143.55.72.*"
"143.55.73.*"
"143.55.74.*"
"143.55.75.*"
"143.55.76.*"
"143.55.77.*"
"143.55.78.*"
"143.55.79.*"
"13.114.40.48"
"52.192.72.89"
"52.69.186.44"
"15.164.81.167"
"52.78.231.108"
"13.234.176.102"
"13.234.210.38"
"13.236.229.21"
"13.237.44.5"
"52.64.108.95"
"20.201.28.151"
"20.205.243.166"
"102.133.202.242"
"20.248.137.48"
"18.181.13.223"
"54.238.117.237"
"54.168.17.15"
"3.34.26.58"
"13.125.114.27"
"3.7.2.84"
"3.6.106.81"
"52.63.152.235"
"3.105.147.174"
"3.106.158.203"
"20.201.28.152"
"20.205.243.160"
"102.133.202.246"
"20.248.137.50"
];
publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==";
};
}

View File

@ -0,0 +1,6 @@
{
imports = [
./hosts-sync.nix
./known-hosts.nix
];
}

View File

@ -0,0 +1,58 @@
[
"192.30.252.*",
"192.30.253.*",
"192.30.254.*",
"192.30.255.*",
"185.199.108.*",
"185.199.109.*",
"185.199.110.*",
"185.199.111.*",
"140.82.112.*",
"140.82.113.*",
"140.82.114.*",
"140.82.115.*",
"140.82.116.*",
"140.82.117.*",
"140.82.118.*",
"140.82.119.*",
"140.82.120.*",
"140.82.121.*",
"140.82.122.*",
"140.82.123.*",
"140.82.124.*",
"140.82.125.*",
"140.82.126.*",
"140.82.127.*",
"143.55.64.*",
"143.55.65.*",
"143.55.66.*",
"143.55.67.*",
"143.55.68.*",
"143.55.69.*",
"143.55.70.*",
"143.55.71.*",
"143.55.72.*",
"143.55.73.*",
"143.55.74.*",
"143.55.75.*",
"143.55.76.*",
"143.55.77.*",
"143.55.78.*",
"143.55.79.*",
"20.201.28.151",
"20.205.243.166",
"102.133.202.242",
"20.248.137.48",
"20.207.73.82",
"20.27.177.113",
"20.200.245.247",
"20.233.54.53",
"20.201.28.152",
"20.205.243.160",
"102.133.202.246",
"20.248.137.50",
"20.207.73.83",
"20.27.177.118",
"20.200.245.248",
"20.233.54.52"
]

View File

@ -0,0 +1,12 @@
{ lib, ... }: {
services.openssh.knownHosts.github = {
hostNames =
["github.com"]
++
# List generated with (IPv6 addresses are currently ignored):
# curl -sS https://api.github.com/meta | jq -r .git[] | grep -v : | nix-shell -p cidr2glob --run cidr2glob | jq -Rs 'split("\n")|map(select(.!=""))' > known-hosts.json
lib.importJSON ./known-hosts.json
;
publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==";
};
}

View File

@ -1,129 +0,0 @@
with import <stockholm/lib>;
{ config, ... }: let
# See https://github.com/processone/ejabberd/blob/master/ejabberd.yml.example
ciphers = concatStringsSep ":" [
"ECDHE-ECDSA-AES256-GCM-SHA384"
"ECDHE-RSA-AES256-GCM-SHA384"
"ECDHE-ECDSA-CHACHA20-POLY1305"
"ECDHE-RSA-CHACHA20-POLY1305"
"ECDHE-ECDSA-AES128-GCM-SHA256"
"ECDHE-RSA-AES128-GCM-SHA256"
"ECDHE-ECDSA-AES256-SHA384"
"ECDHE-RSA-AES256-SHA384"
"ECDHE-ECDSA-AES128-SHA256"
"ECDHE-RSA-AES128-SHA256"
];
protocol_options = [
"no_sslv2"
"no_sslv3"
"no_tlsv1"
"no_tlsv1_10"
];
in /* yaml */ ''
access_rules:
announce:
- allow: admin
local:
- allow: local
configure:
- allow: admin
register:
- allow
s2s:
- allow
trusted_network:
- allow: loopback
acl:
local:
user_regexp: ""
loopback:
ip:
- "127.0.0.0/8"
- "::1/128"
- "::FFFF:127.0.0.1/128"
certfiles:
- /tmp/credentials/certfile
hosts: ${toJSON config.hosts}
language: "en"
listen:
-
port: 5222
ip: "::"
module: ejabberd_c2s
shaper: c2s_shaper
ciphers: ${toJSON ciphers}
dhfile: /var/lib/ejabberd/dhfile
protocol_options: ${toJSON protocol_options}
starttls: true
starttls_required: true
tls: false
tls_compression: false
max_stanza_size: 65536
-
port: 5269
ip: "::"
module: ejabberd_s2s_in
shaper: s2s_shaper
max_stanza_size: 131072
loglevel: 4
modules:
mod_adhoc: {}
mod_admin_extra: {}
mod_announce:
access: announce
mod_caps: {}
mod_carboncopy: {}
mod_client_state: {}
mod_configure: {}
mod_disco: {}
mod_echo: {}
mod_bosh: {}
mod_last: {}
mod_offline:
access_max_user_messages: max_user_offline_messages
mod_ping: {}
mod_privacy: {}
mod_private: {}
mod_register:
access_from: deny
access: register
ip_access: trusted_network
registration_watchers: ${toJSON config.registration_watchers}
mod_roster: {}
mod_shared_roster: {}
mod_stats: {}
mod_time: {}
mod_vcard:
search: false
mod_version: {}
mod_http_api: {}
s2s_access: s2s
s2s_ciphers: ${toJSON ciphers}
s2s_dhfile: /var/lib/ejabberd/dhfile
s2s_protocol_options: ${toJSON protocol_options}
s2s_tls_compression: false
s2s_use_starttls: required
shaper_rules:
max_user_offline_messages:
- 5000: admin
- 100
max_user_sessions: 10
c2s_shaper:
- none: admin
- normal
s2s_shaper: fast
''

View File

@ -12,12 +12,43 @@
fi
'';
settingsFormat = pkgs.formats.json {};
in {
options.tv.ejabberd = {
enable = mkEnableOption "tv.ejabberd";
certfile = mkOption {
type = types.absolute-pathname;
default = toString <secrets> + "/ejabberd.pem";
certfiles = mkOption {
type = types.listOf types.absolute-pathname;
default = [
(toString <secrets> + "/ejabberd.pem")
];
};
configFile = mkOption {
type = types.either types.package types.absolute-pathname;
default = settingsFormat.generate "ejabberd.yaml" cfg.settings;
};
ciphers = mkOption {
type = types.listOf types.str;
default = [
"ECDHE-ECDSA-AES256-GCM-SHA384"
"ECDHE-RSA-AES256-GCM-SHA384"
"ECDHE-ECDSA-CHACHA20-POLY1305"
"ECDHE-RSA-CHACHA20-POLY1305"
"ECDHE-ECDSA-AES128-GCM-SHA256"
"ECDHE-RSA-AES128-GCM-SHA256"
"ECDHE-ECDSA-AES256-SHA384"
"ECDHE-RSA-AES256-SHA384"
"ECDHE-ECDSA-AES128-SHA256"
"ECDHE-RSA-AES128-SHA256"
];
};
credentials.certfiles = mkOption {
internal = true;
readOnly = true;
default =
imap
(i: const "/tmp/credentials/certfile${toJSON i}")
cfg.certfiles;
};
hosts = mkOption {
type = with types; listOf str;
@ -29,42 +60,66 @@ in {
paths = [
(pkgs.writeDashBin "ejabberdctl" ''
exec ${pkgs.ejabberd}/bin/ejabberdctl \
--config ${toFile "ejabberd.yaml" (import ./config.nix {
inherit pkgs;
config = cfg;
})} \
--logs ${shell.escape cfg.user.home} \
--spool ${shell.escape cfg.user.home} \
--config /etc/ejabberd/ejabberd.yaml \
--ctl-config /etc/ejabberd/ejabberdctl.cfg \
--logs ${cfg.stateDir} \
--spool ${cfg.stateDir} \
"$@"
'')
pkgs.ejabberd
];
};
};
protocol_options = mkOption {
type = types.listOf types.str;
default = [
"no_sslv2"
"no_sslv3"
"no_tlsv1"
"no_tlsv1_10"
];
};
registration_watchers = mkOption {
type = types.listOf types.str;
default = [
config.krebs.users.tv.mail
];
};
user = mkOption {
type = types.user;
default = {
name = "ejabberd";
home = "/var/lib/ejabberd";
};
settings = mkOption {
type = settingsFormat.type;
default = {};
};
stateDir = mkOption {
type =
types.addCheck
types.absolute-pathname
(path:
hasPrefix "/var/lib/" path &&
types.filename.check (removePrefix "/var/lib/" path)
);
default = "/var/lib/ejabberd";
};
};
config = lib.mkIf cfg.enable {
environment.etc."ejabberd/ejabberd.yaml".source = cfg.configFile;
environment.etc."ejabberd/ejabberdctl.cfg".source =
builtins.toFile "ejabberdctl.cfg" /* sh */ ''
ERL_OPTIONS='-setcookie ${cfg.stateDir}/.erlang.cookie'
'';
environment.systemPackages = [
(pkgs.symlinkJoin {
name = "ejabberd-sudo-wrapper";
paths = [
(pkgs.writeDashBin "ejabberdctl" ''
set -efu
cd ${shell.escape cfg.user.home}
exec /run/wrappers/bin/sudo \
-u ${shell.escape cfg.user.name} \
exec ${pkgs.systemd}/bin/systemd-run \
--unit=ejabberdctl \
--property=StateDirectory=ejabberd \
--property=User=ejabberd \
--collect \
--pipe \
--quiet \
${cfg.pkgs.ejabberd}/bin/ejabberdctl "$@"
'')
cfg.pkgs.ejabberd
@ -77,31 +132,144 @@ in {
systemd.services.ejabberd = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
reloadTriggers = [
config.environment.etc."ejabberd/ejabberd.yaml".source
config.environment.etc."ejabberd/ejabberdctl.cfg".source
];
serviceConfig = {
ExecStart = pkgs.writeDash "ejabberd" ''
${pkgs.coreutils}/bin/ln -s "$CREDENTIALS_DIRECTORY" /tmp/credentials
${gen-dhparam} /var/lib/ejabberd/dhfile
exec ${cfg.pkgs.ejabberd}/bin/ejabberdctl foreground
'';
LoadCredential = [
"certfile:${cfg.certfile}"
ExecStartPre = [
"${pkgs.coreutils}/bin/ln -s \${CREDENTIALS_DIRECTORY} /tmp/credentials"
"${gen-dhparam} ${cfg.stateDir}/dhfile"
];
PermissionsStartOnly = true;
ExecStart = "${cfg.pkgs.ejabberd}/bin/ejabberdctl foreground";
ExecStop = [
"${cfg.pkgs.ejabberd}/bin/ejabberdctl stop"
"${cfg.pkgs.ejabberd}/bin/ejabberdctl stopped"
];
ExecReload = "${cfg.pkgs.ejabberd}/bin/ejabberdctl reload_config";
LoadCredential =
zipListsWith
(dst: src: "${baseNameOf dst}:${src}")
cfg.credentials.certfiles
cfg.certfiles;
LimitNOFILE = 65536;
PrivateDevices = true;
PrivateTmp = true;
SyslogIdentifier = "ejabberd";
StateDirectory = "ejabberd";
User = cfg.user.name;
TimeoutStartSec = 60;
User = "ejabberd";
DynamicUser = true;
TimeoutSec = 60;
RestartSec = 5;
Restart = "on-failure";
Type = "notify";
NotifyAccess = "all";
WatchdogSec = 30;
};
};
users.users.${cfg.user.name} = {
inherit (cfg.user) home name uid;
createHome = true;
group = cfg.user.name;
isSystemUser = true;
};
# preset config values
tv.ejabberd.settings = {
access_rules = {
announce = mkDefault [{ allow = "admin"; }];
local = mkDefault [{ allow = "local"; }];
configure = mkDefault [{ allow = "admin"; }];
register = mkDefault ["allow"];
s2s = mkDefault ["allow"];
trusted_network = mkDefault [{ allow = "loopback"; }];
};
users.groups.${cfg.user.name} = {};
acl = {
local.user_regexp = mkDefault "";
loopback.ip = mkDefault [
"127.0.0.0/8"
"::1/128"
"::FFFF:127.0.0.1/128"
];
};
certfiles = mkDefault cfg.credentials.certfiles;
hosts = mkDefault cfg.hosts;
language = mkDefault "en";
listen = mkDefault [
{
port = 5222;
ip = "::";
module = "ejabberd_c2s";
shaper = "c2s_shaper";
ciphers = concatStringsSep ":" cfg.ciphers;
protocol_options = cfg.protocol_options;
starttls = true;
starttls_required = true;
tls = false;
tls_compression = false;
max_stanza_size = 65536;
}
{
port = 5269;
ip = "::";
module = "ejabberd_s2s_in";
shaper = "s2s_shaper";
dhfile = "${cfg.stateDir}/dhfile";
max_stanza_size = 131072;
}
];
loglevel = mkDefault "4";
modules = {
mod_adhoc = mkDefault {};
mod_admin_extra = mkDefault {};
mod_announce.access = mkDefault "announce";
mod_caps = mkDefault {};
mod_carboncopy = mkDefault {};
mod_client_state = mkDefault {};
mod_configure = mkDefault {};
mod_disco = mkDefault {};
mod_echo = mkDefault {};
mod_bosh = mkDefault {};
mod_last = mkDefault {};
mod_offline.access_max_user_messages = mkDefault "max_user_offline_messages";
mod_ping = mkDefault {};
mod_privacy = mkDefault {};
mod_private = mkDefault {};
mod_register = {
access_from = mkDefault "deny";
access = mkDefault "register";
ip_access = mkDefault "trusted_network";
registration_watchers = mkDefault cfg.registration_watchers;
};
mod_roster = mkDefault {};
mod_shared_roster = mkDefault {};
mod_stats = mkDefault {};
mod_time = mkDefault {};
mod_vcard.search = mkDefault false;
mod_version = mkDefault {};
mod_http_api = mkDefault {};
};
s2s_access = mkDefault "s2s";
s2s_ciphers = concatStringsSep ":" cfg.ciphers;
s2s_dhfile = mkDefault "${cfg.stateDir}/dhfile";
s2s_protocol_options = mkDefault cfg.protocol_options;
s2s_tls_compression = mkDefault false;
s2s_use_starttls = mkDefault "required";
shaper_rules = {
max_user_offline_messages = mkDefault [
{ "5000" = "admin"; }
100
];
max_user_sessions = mkDefault 10;
c2s_shaper = mkDefault [
{ "none" = "admin"; }
"normal"
];
s2s_shaper = mkDefault "fast";
};
};
};
}