From 2b034797107660d4d83f8a7acdc55d32db785b82 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Thu, 2 Oct 2025 11:28:55 +0300 Subject: Update content for md --- gemfeed/examples/conf/frontends/Rexfile | 648 +++++++ .../conf/frontends/etc/acme-client.conf.tpl | 41 + .../conf/frontends/etc/dserver/dtail.json.tpl | 127 ++ .../examples/conf/frontends/etc/gogios.cron.tpl | 3 + .../examples/conf/frontends/etc/gogios.json.tpl | 98 + gemfeed/examples/conf/frontends/etc/gorum.json.tpl | 18 + gemfeed/examples/conf/frontends/etc/httpd.conf.tpl | 184 ++ gemfeed/examples/conf/frontends/etc/inetd.conf | 2 + .../examples/conf/frontends/etc/login.conf.d/inetd | 3 + gemfeed/examples/conf/frontends/etc/mail/aliases | 103 ++ .../conf/frontends/etc/mail/smtpd.conf.tpl | 23 + .../conf/frontends/etc/mail/virtualdomains | 20 + .../examples/conf/frontends/etc/mail/virtualusers | 5 + gemfeed/examples/conf/frontends/etc/myname.tpl | 1 + gemfeed/examples/conf/frontends/etc/newsyslog.conf | 14 + gemfeed/examples/conf/frontends/etc/rc.conf.local | 5 + .../examples/conf/frontends/etc/rc.d/dserver.tpl | 16 + gemfeed/examples/conf/frontends/etc/rc.d/gorum.tpl | 16 + .../examples/conf/frontends/etc/relayd.conf.tpl | 86 + .../examples/conf/frontends/etc/rsyncd.conf.tpl | 28 + gemfeed/examples/conf/frontends/etc/taskrc.tpl | 40 + gemfeed/examples/conf/frontends/etc/tmux.conf | 24 + .../examples/conf/frontends/scripts/acme.sh.tpl | 68 + .../conf/frontends/scripts/dns-failover.ksh | 133 ++ .../scripts/dserver-update-key-cache.sh.tpl | 34 + .../examples/conf/frontends/scripts/fooodds.txt | 191 ++ .../examples/conf/frontends/scripts/foostats.pl | 1910 ++++++++++++++++++++ .../conf/frontends/scripts/gemtexter.sh.tpl | 65 + .../examples/conf/frontends/scripts/rsync.sh.tpl | 8 + .../conf/frontends/scripts/taskwarrior.sh.tpl | 5 + .../conf/frontends/var/nsd/etc/key.conf.tpl | 4 + .../conf/frontends/var/nsd/etc/nsd.conf.master.tpl | 17 + .../conf/frontends/var/nsd/etc/nsd.conf.slave.tpl | 17 + .../var/nsd/zones/master/buetow.org.zone.tpl | 124 ++ .../var/nsd/zones/master/dtail.dev.zone.tpl | 21 + .../var/nsd/zones/master/foo.zone.zone.tpl | 34 + .../var/nsd/zones/master/irregular.ninja.zone.tpl | 23 + .../var/nsd/zones/master/paul.cyou.zone.tpl | 20 + .../var/nsd/zones/master/snonux.foo.zone.tpl | 20 + .../var/www/htdocs/buetow.org/self/index.txt.tpl | 1 + 40 files changed, 4200 insertions(+) create mode 100644 gemfeed/examples/conf/frontends/Rexfile create mode 100644 gemfeed/examples/conf/frontends/etc/acme-client.conf.tpl create mode 100644 gemfeed/examples/conf/frontends/etc/dserver/dtail.json.tpl create mode 100644 gemfeed/examples/conf/frontends/etc/gogios.cron.tpl create mode 100644 gemfeed/examples/conf/frontends/etc/gogios.json.tpl create mode 100644 gemfeed/examples/conf/frontends/etc/gorum.json.tpl create mode 100644 gemfeed/examples/conf/frontends/etc/httpd.conf.tpl create mode 100644 gemfeed/examples/conf/frontends/etc/inetd.conf create mode 100644 gemfeed/examples/conf/frontends/etc/login.conf.d/inetd create mode 100644 gemfeed/examples/conf/frontends/etc/mail/aliases create mode 100644 gemfeed/examples/conf/frontends/etc/mail/smtpd.conf.tpl create mode 100644 gemfeed/examples/conf/frontends/etc/mail/virtualdomains create mode 100644 gemfeed/examples/conf/frontends/etc/mail/virtualusers create mode 100644 gemfeed/examples/conf/frontends/etc/myname.tpl create mode 100644 gemfeed/examples/conf/frontends/etc/newsyslog.conf create mode 100644 gemfeed/examples/conf/frontends/etc/rc.conf.local create mode 100755 gemfeed/examples/conf/frontends/etc/rc.d/dserver.tpl create mode 100755 gemfeed/examples/conf/frontends/etc/rc.d/gorum.tpl create mode 100644 gemfeed/examples/conf/frontends/etc/relayd.conf.tpl create mode 100644 gemfeed/examples/conf/frontends/etc/rsyncd.conf.tpl create mode 100644 gemfeed/examples/conf/frontends/etc/taskrc.tpl create mode 100644 gemfeed/examples/conf/frontends/etc/tmux.conf create mode 100644 gemfeed/examples/conf/frontends/scripts/acme.sh.tpl create mode 100644 gemfeed/examples/conf/frontends/scripts/dns-failover.ksh create mode 100644 gemfeed/examples/conf/frontends/scripts/dserver-update-key-cache.sh.tpl create mode 100644 gemfeed/examples/conf/frontends/scripts/fooodds.txt create mode 100644 gemfeed/examples/conf/frontends/scripts/foostats.pl create mode 100644 gemfeed/examples/conf/frontends/scripts/gemtexter.sh.tpl create mode 100644 gemfeed/examples/conf/frontends/scripts/rsync.sh.tpl create mode 100644 gemfeed/examples/conf/frontends/scripts/taskwarrior.sh.tpl create mode 100644 gemfeed/examples/conf/frontends/var/nsd/etc/key.conf.tpl create mode 100644 gemfeed/examples/conf/frontends/var/nsd/etc/nsd.conf.master.tpl create mode 100644 gemfeed/examples/conf/frontends/var/nsd/etc/nsd.conf.slave.tpl create mode 100644 gemfeed/examples/conf/frontends/var/nsd/zones/master/buetow.org.zone.tpl create mode 100644 gemfeed/examples/conf/frontends/var/nsd/zones/master/dtail.dev.zone.tpl create mode 100644 gemfeed/examples/conf/frontends/var/nsd/zones/master/foo.zone.zone.tpl create mode 100644 gemfeed/examples/conf/frontends/var/nsd/zones/master/irregular.ninja.zone.tpl create mode 100644 gemfeed/examples/conf/frontends/var/nsd/zones/master/paul.cyou.zone.tpl create mode 100644 gemfeed/examples/conf/frontends/var/nsd/zones/master/snonux.foo.zone.tpl create mode 100644 gemfeed/examples/conf/frontends/var/www/htdocs/buetow.org/self/index.txt.tpl (limited to 'gemfeed/examples/conf/frontends') diff --git a/gemfeed/examples/conf/frontends/Rexfile b/gemfeed/examples/conf/frontends/Rexfile new file mode 100644 index 00000000..0079387e --- /dev/null +++ b/gemfeed/examples/conf/frontends/Rexfile @@ -0,0 +1,648 @@ +# How to use: +# +# rex commons +# +# Why use Rex to automate my servers? Because Rex is KISS, Puppet, SALT and Chef +# are not. So, why not use Ansible then? To use Ansible correctly you should also +# install Python on the target machines (not mandatory, though. But better). +# Rex is programmed in Perl and there is already Perl in the base system of OpenBSD. +# Also, I find Perl > Python (my personal opinion). + +use Rex -feature => [ '1.14', 'exec_autodie' ]; +use Rex::Logger; +use File::Slurp; + +# REX CONFIG SECTION + +group frontends => 'blowfish.buetow.org:2', 'fishfinger.buetow.org:2'; +our $ircbouncer_server = 'fishfinger.buetow.org:2'; +group ircbouncer => $ircbouncer_server; +group openbsd_canary => 'fishfinger.buetow.org:2'; + +user 'rex'; +sudo TRUE; + +parallelism 5; + +# CUSTOM (PERL-ish) CONFIG SECTION (what Rex can't do by itself) +# Note we using anonymous subs here. This is so we can pass the subs as +# Rex template variables too. + +our %ips = ( + 'fishfinger' => { + 'ipv4' => '46.23.94.99', + 'ipv6' => '2a03:6000:6f67:624::99', + }, + 'blowfish' => { + 'ipv4' => '23.88.35.144', + 'ipv6' => '2a01:4f8:c17:20f1::42', + }, + 'domain' => 'buetow.org', +); + +$ips{current_master} = $ips{fishfinger}; +$ips{current_master}{fqdn} = 'fishfinger.' . $ips{domain}; + +$ips{current_standby} = $ips{blowfish}; +$ips{current_standby}{fqdn} = 'blowfish.' . $ips{domain}; + +# Gather IPv6 addresses based on hostname. +our $ipv6address = sub { + my $hostname = shift; + my $ip = $ips{$hostname}{ipv6}; + unless ( defined $ip ) { + Rex::Logger::info( "Unable to determine IPv6 address for $hostname", 'error' ); + return '::1'; + } + return $ip; +}; + +# Bootstrapping the FQDN based on the server IP as the hostname and domain +# facts aren't set yet due to the myname file in the first place. +our $fqdns = sub { + my $ipv4 = shift; + while ( my ( $hostname, $ips ) = each %ips ) { + return "$hostname." . $ips{domain} if $ips->{ipv4} eq $ipv4; + } + Rex::Logger::info( "Unable to determine hostname for $ipv4", 'error' ); + return 'HOSTNAME-UNKNOWN.' . $ips{domain}; +}; + +# TODO: Rename rexfilesecrets.txt to confsecrets.txt?! Or wait for RCM migration. +# The secret store. Note to myself: "geheim cat rexfilesecrets.txt" +our $secrets = sub { read_file './secrets/' . shift }; + +our @dns_zones = qw/buetow.org dtail.dev foo.zone irregular.ninja snonux.foo paul.cyou/; +our @dns_zones_remove = qw//; + +# k3s cluster running on FreeBSD in my LAN +our @f3s_hosts = + qw/f3s.buetow.org anki.f3s.buetow.org bag.f3s.buetow.org flux.f3s.buetow.org audiobookshelf.f3s.buetow.org gpodder.f3s.buetow.org radicale.f3s.buetow.org vault.f3s.buetow.org syncthing.f3s.buetow.org uprecords.f3s.buetow.org/; + +# optionally, only enable manually for temp time, as no password protection yet +# push @f3s_hosts, 'registry.f3s.buetow.org'; + +our @acme_hosts = + qw/buetow.org git.buetow.org paul.buetow.org joern.buetow.org dory.buetow.org ecat.buetow.org blog.buetow.org fotos.buetow.org znc.buetow.org dtail.dev foo.zone stats.foo.zone irregular.ninja alt.irregular.ninja snonux.foo/; +push @acme_hosts, @f3s_hosts; + +# UTILITY TASKS + +task 'id', group => 'frontends', sub { say run 'id' }; +task 'dump_info', group => 'frontends', sub { dump_system_information }; + +# OPENBSD TASKS SECTION + +desc 'Install base stuff'; +task 'base', + group => 'frontends', + sub { + pkg 'figlet', ensure => present; + pkg 'tig', ensure => present; + pkg 'vger', ensure => present; + pkg 'zsh', ensure => present; + pkg 'bash', ensure => present; + pkg 'helix', ensure => present; + + my @pkg_scripts = qw/uptimed httpd dserver icinga2/; + push @pkg_scripts, 'znc' if connection->server eq $ircbouncer_server; + my $pkg_scripts = join ' ', @pkg_scripts; + append_if_no_such_line '/etc/rc.conf.local', "pkg_scripts=\"$pkg_scripts\""; + run 'touch /etc/rc.local'; + + file '/etc/myname', + content => template( './etc/myname.tpl', fqdns => $fqdns ), + owner => 'root', + group => 'wheel', + mode => '644'; + }; + +desc 'Setup uptimed'; +task 'uptimed', + group => 'frontends', + sub { + pkg 'uptimed', ensure => present; + service 'uptimed', ensure => 'started'; + }; + +desc 'Setup rsync'; +task 'rsync', + group => 'frontends', + sub { + pkg 'rsync', ensure => present; + + # Not required, as we use rsyncd via inetd + # append_if_no_such_line '/etc/rc.conf.local', 'rsyncd_flags='; + + file '/etc/rsyncd.conf', + content => template('./etc/rsyncd.conf.tpl'), + owner => 'root', + group => 'wheel', + mode => '644'; + + file '/usr/local/bin/rsync.sh', + content => template('./scripts/rsync.sh.tpl'), + owner => 'root', + group => 'wheel', + mode => '755'; + + file '/tmp/rsync.cron', + ensure => 'file', + content => "*/5\t*\t*\t*\t*\t-ns /usr/local/bin/rsync.sh", + mode => '600'; + + run '{ crontab -l -u root ; cat /tmp/rsync.cron; } | uniq | crontab -u root -'; + run 'rm /tmp/rsync.cron'; + }; + +desc 'Configure the gemtexter sites'; +task 'gemtexter', + group => 'frontends', + sub { + file '/usr/local/bin/gemtexter.sh', + content => template('./scripts/gemtexter.sh.tpl'), + owner => 'root', + group => 'wheel', + mode => '744'; + + file '/etc/daily.local', + ensure => 'present', + owner => 'root', + group => 'wheel', + mode => '644'; + + append_if_no_such_line '/etc/daily.local', '/usr/local/bin/gemtexter.sh'; + }; + +desc 'Configure taskwarrior reminder'; +task 'taskwarrior', + group => 'frontends', + sub { + pkg 'taskwarrior', ensure => present; + + file '/usr/local/bin/taskwarrior.sh', + content => template('./scripts/taskwarrior.sh.tpl'), + owner => 'root', + group => 'wheel', + mode => '500'; + + file '/etc/taskrc', + content => template('./etc/taskrc.tpl'), + owner => 'root', + group => 'wheel', + mode => '600'; + + append_if_no_such_line '/etc/daily.local', '/usr/local/bin/taskwarrior.sh'; + }; + +desc 'Configure ACME client'; +task 'acme', + group => 'frontends', + sub { + file '/etc/acme-client.conf', + content => template( './etc/acme-client.conf.tpl', acme_hosts => \@acme_hosts ), + owner => 'root', + group => 'wheel', + mode => '644'; + + file '/usr/local/bin/acme.sh', + content => template( './scripts/acme.sh.tpl', acme_hosts => \@acme_hosts ), + owner => 'root', + group => 'wheel', + mode => '744'; + + file '/etc/daily.local', + ensure => 'present', + owner => 'root', + group => 'wheel', + mode => '644'; + + append_if_no_such_line '/etc/daily.local', '/usr/local/bin/acme.sh'; + }; + +desc 'Invoke ACME client'; +task 'acme_invoke', + group => 'frontends', + sub { + say run '/usr/local/bin/acme.sh'; + }; + +desc 'Setup httpd'; +task 'httpd', + group => 'frontends', + sub { + append_if_no_such_line '/etc/rc.conf.local', 'httpd_flags='; + + file '/etc/httpd.conf', + content => template( './etc/httpd.conf.tpl', acme_hosts => \@acme_hosts ), + owner => 'root', + group => 'wheel', + mode => '644', + on_change => sub { service 'httpd' => 'restart' }; + + file '/var/www/htdocs/buetow.org', ensure => 'directory'; + file '/var/www/htdocs/buetow.org/self', ensure => 'directory'; + + # For failover health-check. + file '/var/www/htdocs/buetow.org/self/index.txt', + ensure => 'file', + content => template('./var/www/htdocs/buetow.org/self/index.txt.tpl'); + + service 'httpd', ensure => 'started'; + }; + +desc 'Setup inetd'; +task 'inetd', + group => 'frontends', + sub { + append_if_no_such_line '/etc/rc.conf.local', 'inetd_flags='; + + file '/etc/login.conf.d/inetd', + source => './etc/login.conf.d/inetd', + owner => 'root', + group => 'wheel', + mode => '644'; + + file '/etc/inetd.conf', + source => './etc/inetd.conf', + owner => 'root', + group => 'wheel', + mode => '644', + on_change => sub { service 'inetd' => 'restart' }; + + service 'inetd', ensure => 'started'; + }; + +desc 'Setup relayd'; +task 'relayd', + group => 'frontends', + sub { + append_if_no_such_line '/etc/rc.conf.local', 'relayd_flags='; + + file '/etc/relayd.conf', + content => template( + './etc/relayd.conf.tpl', + ipv6address => $ipv6address, + f3s_hosts => \@f3s_hosts, + acme_hosts => \@acme_hosts + ), + owner => 'root', + group => 'wheel', + mode => '600', + on_change => sub { service 'relayd' => 'restart' }; + + service 'relayd', ensure => 'started'; + append_if_no_such_line '/etc/daily.local', '/usr/sbin/rcctl start relayd'; + }; + +desc 'Setup OpenSMTPD'; +task 'smtpd', + group => 'frontends', + sub { + Rex::Logger::info('Dealing with mail aliases'); + file '/etc/mail/aliases', + source => './etc/mail/aliases', + owner => 'root', + group => 'wheel', + mode => '644', + on_change => sub { say run 'newaliases' }; + + Rex::Logger::info('Dealing with mail virtual domains'); + file '/etc/mail/virtualdomains', + source => './etc/mail/virtualdomains', + owner => 'root', + group => 'wheel', + mode => '644', + on_change => sub { service 'smtpd' => 'restart' }; + + Rex::Logger::info('Dealing with mail virtual users'); + file '/etc/mail/virtualusers', + source => './etc/mail/virtualusers', + owner => 'root', + group => 'wheel', + mode => '644', + on_change => sub { service 'smtpd' => 'restart' }; + + Rex::Logger::info('Dealing with smtpd.conf'); + file '/etc/mail/smtpd.conf', + content => template('./etc/mail/smtpd.conf.tpl'), + owner => 'root', + group => 'wheel', + mode => '644', + on_change => sub { service 'smtpd' => 'restart' }; + + service 'smtpd', ensure => 'started'; + }; + +desc 'Setup DNS server(s)'; +task 'nsd', + group => 'frontends', + sub { + my $restart = FALSE; + append_if_no_such_line '/etc/rc.conf.local', 'nsd_flags='; + + Rex::Logger::info('Dealing with master DNS key'); + file '/var/nsd/etc/key.conf', + content => template( './var/nsd/etc/key.conf.tpl', nsd_key => $secrets->('/var/nsd/etc/nsd_key.txt') ), + owner => 'root', + group => '_nsd', + mode => '640', + on_change => sub { $restart = TRUE }; + + Rex::Logger::info('Dealing with master DNS config'); + file '/var/nsd/etc/nsd.conf', + content => template( './var/nsd/etc/nsd.conf.master.tpl', dns_zones => \@dns_zones, ), + owner => 'root', + group => '_nsd', + mode => '640', + on_change => sub { $restart = TRUE }; + + for my $zone (@dns_zones) { + Rex::Logger::info("Dealing with DNS zone $zone"); + file "/var/nsd/zones/master/$zone.zone", + content => template( + "./var/nsd/zones/master/$zone.zone.tpl", + ips => \%ips, + f3s_hosts => \@f3s_hosts + ), + owner => 'root', + group => 'wheel', + mode => '644', + on_change => sub { $restart = TRUE }; + } + + for my $zone (@dns_zones_remove) { + Rex::Logger::info("Dealing with DNS zone removal $zone"); + file "/var/nsd/zones/master/$zone.zone", ensure => 'absent'; + } + + service 'nsd' => 'restart' if $restart; + service 'nsd', ensure => 'started'; + }; + +desc 'Setup DNS failover script(s)'; +task 'nsd_failover', + group => 'frontends', + sub { + file '/usr/local/bin/dns-failover.ksh', + source => './scripts/dns-failover.ksh', + owner => 'root', + group => 'wheel', + mode => '500'; + + file '/tmp/root.cron', + ensure => 'file', + content => "*\t*\t*\t*\t*\t-ns /usr/local/bin/dns-failover.ksh", + mode => '600'; + + run '{ crontab -l -u root ; cat /tmp/root.cron; } | uniq | crontab -u root -'; + run 'rm /tmp/root.cron'; + }; + +desc 'Setup DTail'; +task 'dtail', + group => 'frontends', + sub { + my $restart = FALSE; + + run 'adduser -class nologin -group _dserver -batch _dserver', unless => 'id _dserver'; + run 'usermod -d /var/run/dserver _dserver'; + + file '/etc/rc.d/dserver', + content => template('./etc/rc.d/dserver.tpl'), + owner => 'root', + group => 'wheel', + mode => '755', + on_change => sub { $restart = TRUE }; + + file '/etc/dserver', + ensure => 'directory', + owner => 'root', + group => 'wheel', + mode => '755'; + + file '/etc/dserver/dtail.json', + content => template('./etc/dserver/dtail.json.tpl'), + owner => 'root', + group => 'wheel', + mode => '755', + on_change => sub { $restart = TRUE }; + + file '/usr/local/bin/dserver-update-key-cache.sh', + content => template('./scripts/dserver-update-key-cache.sh.tpl'), + owner => 'root', + group => 'wheel', + mode => '500'; + + append_if_no_such_line '/etc/daily.local', '/usr/local/bin/dserver-update-key-cache.sh'; + + service 'dserver' => 'restart' if $restart; + service 'dserver', ensure => 'started'; + }; + +desc 'Installing Gogios binary'; +task 'gogios_install', + group => 'frontends', + sub { + file '/usr/local/bin/gogios', + source => 'usr/local/bin/gogios', + mode => '0755'; + owner => 'root', + group => 'root'; + }; + +desc 'Setup Gogios monitoring system'; +task 'gogios', + group => 'frontends', + sub { + pkg 'monitoring-plugins', ensure => present; + pkg 'nrpe', ensure => present; + + my $gogios_path = '/usr/local/bin/gogios'; + + unless ( is_file($gogios_path) ) { + Rex::Logger::info( "Gogios not installed to $gogios_path! Run task 'gogios_install'", 'error' ); + } + + run 'adduser -group _gogios -batch _gogios', unless => 'id _gogios'; + run 'usermod -d /var/run/gogios _gogios'; + + file '/etc/gogios.json', + content => template( './etc/gogios.json.tpl', acme_hosts => \@acme_hosts ), + owner => 'root', + group => 'wheel', + mode => '744'; + + file '/var/run/gogios', + ensure => 'directory', + owner => '_gogios', + group => '_gogios', + mode => '755'; + + file '/tmp/gogios.cron', + ensure => 'file', + content => template( './etc/gogios.cron.tpl', gogios_path => $gogios_path ), + mode => '600'; + + run 'cat /tmp/gogios.cron | crontab -u _gogios -'; + run 'rm /tmp/gogios.cron'; + + append_if_no_such_line '/etc/rc.local', 'if [ ! -d /var/run/gogios ]; then mkdir /var/run/gogios; fi'; + append_if_no_such_line '/etc/rc.local', 'chown _gogios /var/run/gogios'; + }; + +use Rex::Commands::Cron; + +desc 'Cron test'; +task 'cron_test', + group => 'openbsd_canary', + sub { + cron + add => '_gogios', + { + minute => '5', + hour => '*', + command => '/bin/ls', + }; + }; + +desc 'Installing Gorum binary'; +task 'gorum_install', + group => 'frontends', + sub { + file '/usr/local/bin/gorum', + source => 'usr/local/bin/gorum', + mode => '0755'; + owner => 'root', + group => 'root'; + }; + +desc 'Setup Gorum quorum system'; +task 'gorum', + group => 'frontends', + sub { + my $restart = FALSE; + my $gorum_path = '/usr/local/bin/gorum'; + + unless ( is_file($gorum_path) ) { + Rex::Logger::info( "gorum not installed to $gorum_path! Run task 'gorum_install'", 'error' ); + } + + run 'adduser -class nologin -group _gorum -batch _gorum', unless => 'id _gorum'; + run 'usermod -d /var/run/gorum _gorum'; + + file '/etc/gorum.json', + content => template('./etc/gorum.json.tpl'), + owner => 'root', + group => 'wheel', + mode => '744', + on_change => sub { $restart = TRUE }; + + file '/var/run/gorum', + ensure => 'directory', + owner => '_gorum', + group => '_gorum', + mode => '755'; + + file '/etc/rc.d/gorum', + content => template('./etc/rc.d/gorum.tpl'), + owner => 'root', + group => 'wheel', + mode => '755', + on_change => sub { $restart = TRUE }; + + service 'gorum' => 'restart' if $restart; + service 'gorum', ensure => 'started'; + }; + +desc 'Setup Foostats'; +task 'foostats', + group => 'frontends', + sub { + use File::Copy; + for my $file (qw/foostats.pl fooodds.txt/) { + Rex::Logger::info("Dealing with $file"); + my $git_script_path = $ENV{HOME} . '/git/foostats/' . $file; + copy( $git_script_path, './scripts/' . $file ) if -f $git_script_path; + } + + file '/usr/local/bin/foostats.pl', + source => './scripts/foostats.pl', + owner => 'root', + group => 'wheel', + mode => '500'; + + file '/var/www/htdocs/buetow.org/self/foostats/fooodds.txt', + source => './scripts/fooodds.txt', + owner => 'root', + group => 'wheel', + mode => '440'; + + file '/var/www/htdocs/gemtexter/stats.foo.zone', + ensure => 'directory', + owner => 'root', + group => 'wheel', + mode => '755'; + + file '/var/gemini/stats.foo.zone', + ensure => 'directory', + owner => 'root', + group => 'wheel', + mode => '755'; + + append_if_no_such_line '/etc/daily.local', 'perl /usr/local/bin/foostats.pl --parse-logs --replicate --report'; + + my @deps = qw(p5-Digest-SHA3 p5-PerlIO-gzip p5-JSON p5-String-Util p5-LWP-Protocol-https); + pkg $_, ensure => present for @deps; + + # For now, custom syslog config only required for foostats (to keep some logs for longer) + # Later, could move out to a separate task here in the Rexfile. + file '/etc/newsyslog.conf', + source => './etc/newsyslog.conf', + owner => 'root', + group => 'wheel', + mode => '644'; + }; + +desc 'Setup IRC bouncer'; +task 'ircbouncer', + group => 'ircbouncer', + sub { + pkg 'znc', ensure => present; + + # Requires runtime config in /var/znc before it can start. + # => geheim search znc.conf + service 'znc', ensure => 'started'; + }; + +# COMBINED TASKS SECTION + +desc 'Common configs of all hosts'; +task 'commons', + group => 'frontends', + sub { + run_task 'base'; + run_task 'nsd'; + run_task 'nsd_failover'; + run_task 'uptimed'; + run_task 'httpd'; + run_task 'gemtexter'; + run_task 'taskwarrior'; + run_task 'acme'; + run_task 'acme_invoke'; + run_task 'inetd'; + run_task 'relayd'; + run_task 'smtpd'; + run_task 'rsync'; + run_task 'gogios'; + + # run_task 'gorum'; + run_task 'foostats'; + + # Requires installing the binaries first! + #run_task 'dtail'; + }; + +1; + +# vim: syntax=perl diff --git a/gemfeed/examples/conf/frontends/etc/acme-client.conf.tpl b/gemfeed/examples/conf/frontends/etc/acme-client.conf.tpl new file mode 100644 index 00000000..b52f5b0e --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/acme-client.conf.tpl @@ -0,0 +1,41 @@ +# +# $OpenBSD: acme-client.conf,v 1.4 2020/09/17 09:13:06 florian Exp $ +# +authority letsencrypt { + api url "https://acme-v02.api.letsencrypt.org/directory" + account key "/etc/acme/letsencrypt-privkey.pem" +} + +authority letsencrypt-staging { + api url "https://acme-staging-v02.api.letsencrypt.org/directory" + account key "/etc/acme/letsencrypt-staging-privkey.pem" +} + +authority buypass { + api url "https://api.buypass.com/acme/directory" + account key "/etc/acme/buypass-privkey.pem" + contact "mailto:me@example.com" +} + +authority buypass-test { + api url "https://api.test4.buypass.no/acme/directory" + account key "/etc/acme/buypass-test-privkey.pem" + contact "mailto:me@example.com" +} + +<% for my $host (@$acme_hosts) { -%> +<% for my $prefix ('', 'www.', 'standby.') { -%> +domain <%= $prefix.$host %> { + domain key "/etc/ssl/private/<%= $prefix.$host %>.key" + domain full chain certificate "/etc/ssl/<%= $prefix.$host %>.fullchain.pem" + sign with letsencrypt +} +<% } -%> +<% } -%> + +# For the server itself (e.g. TLS, or monitoring) +domain <%= "$hostname.$domain" %> { + domain key "/etc/ssl/private/<%= "$hostname.$domain" %>.key" + domain full chain certificate "/etc/ssl/<%= "$hostname.$domain" %>.fullchain.pem" + sign with letsencrypt +} diff --git a/gemfeed/examples/conf/frontends/etc/dserver/dtail.json.tpl b/gemfeed/examples/conf/frontends/etc/dserver/dtail.json.tpl new file mode 100644 index 00000000..6b96fbad --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/dserver/dtail.json.tpl @@ -0,0 +1,127 @@ +{ + "Client": { + "TermColorsEnable": true, + "TermColors": { + "Remote": { + "DelimiterAttr": "Dim", + "DelimiterBg": "Blue", + "DelimiterFg": "Cyan", + "RemoteAttr": "Dim", + "RemoteBg": "Blue", + "RemoteFg": "White", + "CountAttr": "Dim", + "CountBg": "Blue", + "CountFg": "White", + "HostnameAttr": "Bold", + "HostnameBg": "Blue", + "HostnameFg": "White", + "IDAttr": "Dim", + "IDBg": "Blue", + "IDFg": "White", + "StatsOkAttr": "None", + "StatsOkBg": "Green", + "StatsOkFg": "Black", + "StatsWarnAttr": "None", + "StatsWarnBg": "Red", + "StatsWarnFg": "White", + "TextAttr": "None", + "TextBg": "Black", + "TextFg": "White" + }, + "Client": { + "DelimiterAttr": "Dim", + "DelimiterBg": "Yellow", + "DelimiterFg": "Black", + "ClientAttr": "Dim", + "ClientBg": "Yellow", + "ClientFg": "Black", + "HostnameAttr": "Dim", + "HostnameBg": "Yellow", + "HostnameFg": "Black", + "TextAttr": "None", + "TextBg": "Black", + "TextFg": "White" + }, + "Server": { + "DelimiterAttr": "AttrDim", + "DelimiterBg": "BgCyan", + "DelimiterFg": "FgBlack", + "ServerAttr": "AttrDim", + "ServerBg": "BgCyan", + "ServerFg": "FgBlack", + "HostnameAttr": "AttrBold", + "HostnameBg": "BgCyan", + "HostnameFg": "FgBlack", + "TextAttr": "AttrNone", + "TextBg": "BgBlack", + "TextFg": "FgWhite" + }, + "Common": { + "SeverityErrorAttr": "AttrBold", + "SeverityErrorBg": "BgRed", + "SeverityErrorFg": "FgWhite", + "SeverityFatalAttr": "AttrBold", + "SeverityFatalBg": "BgMagenta", + "SeverityFatalFg": "FgWhite", + "SeverityWarnAttr": "AttrBold", + "SeverityWarnBg": "BgBlack", + "SeverityWarnFg": "FgWhite" + }, + "MaprTable": { + "DataAttr": "AttrNone", + "DataBg": "BgBlue", + "DataFg": "FgWhite", + "DelimiterAttr": "AttrDim", + "DelimiterBg": "BgBlue", + "DelimiterFg": "FgWhite", + "HeaderAttr": "AttrBold", + "HeaderBg": "BgBlue", + "HeaderFg": "FgWhite", + "HeaderDelimiterAttr": "AttrDim", + "HeaderDelimiterBg": "BgBlue", + "HeaderDelimiterFg": "FgWhite", + "HeaderSortKeyAttr": "AttrUnderline", + "HeaderGroupKeyAttr": "AttrReverse", + "RawQueryAttr": "AttrDim", + "RawQueryBg": "BgBlack", + "RawQueryFg": "FgCyan" + } + } + }, + "Server": { + "SSHBindAddress": "0.0.0.0", + "HostKeyFile": "cache/ssh_host_key", + "HostKeyBits": 2048, + "MapreduceLogFormat": "default", + "MaxConcurrentCats": 2, + "MaxConcurrentTails": 50, + "MaxConnections": 50, + "MaxLineLength": 1048576, + "Permissions": { + "Default": [ + "readfiles:^/.*$" + ], + "Users": { + "paul": [ + "readfiles:^/.*$" + ], + "pbuetow": [ + "readfiles:^/.*$" + ], + "jamesblake": [ + "readfiles:^/tmp/foo.log$", + "readfiles:^/.*$", + "readfiles:!^/tmp/bar.log$" + ] + } + } + }, + "Common": { + "LogDir": "/var/log/dserver", + "Logger": "Fout", + "LogRotation": "Daily", + "CacheDir": "cache", + "SSHPort": 2222, + "LogLevel": "Info" + } +} diff --git a/gemfeed/examples/conf/frontends/etc/gogios.cron.tpl b/gemfeed/examples/conf/frontends/etc/gogios.cron.tpl new file mode 100644 index 00000000..fc6299c3 --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/gogios.cron.tpl @@ -0,0 +1,3 @@ +0 7 * * * <%= $gogios_path %> -renotify >/dev/null +*/5 8-22 * * * -s <%= $gogios_path %> >/dev/null +0 3 * * 0 <%= $gogios_path %> -force >/dev/null diff --git a/gemfeed/examples/conf/frontends/etc/gogios.json.tpl b/gemfeed/examples/conf/frontends/etc/gogios.json.tpl new file mode 100644 index 00000000..683f9de8 --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/gogios.json.tpl @@ -0,0 +1,98 @@ +<% our $plugin_dir = '/usr/local/libexec/nagios'; -%> +{ + "EmailTo": "paul", + "EmailFrom": "gogios@mx.buetow.org", + "CheckTimeoutS": 10, + "CheckConcurrency": 3, + "StateDir": "/var/run/gogios", + "Checks": { + <% for my $host (qw(master standby)) { -%> + <% for my $proto (4, 6) { -%> + "Check Ping<%= $proto %> <%= $host %>.buetow.org": { + "Plugin": "<%= $plugin_dir %>/check_ping", + "Args": ["-H", "<%= $host %>.buetow.org", "-<%= $proto %>", "-w", "100,10%", "-c", "200,15%"], + "Retries": 3, + "RetryInterval": 3 + }, + <% } -%> + <% } -%> + <% for my $host (qw(fishfinger blowfish)) { -%> + "Check DTail <%= $host %>.buetow.org": { + "Plugin": "/usr/local/bin/dtailhealth", + "Args": ["--server", "<%= $host %>.buetow.org:2222"], + "DependsOn": ["Check Ping4 <%= $host %>.buetow.org", "Check Ping6 <%= $host %>.buetow.org"] + }, + <% } -%> + <% for my $host (qw(fishfinger blowfish)) { -%> + <% for my $proto (4, 6) { -%> + "Check Ping<%= $proto %> <%= $host %>.buetow.org": { + "Plugin": "<%= $plugin_dir %>/check_ping", + "Args": ["-H", "<%= $host %>.buetow.org", "-<%= $proto %>", "-w", "100,10%", "-c", "200,15%"], + "Retries": 3, + "RetryInterval": 3 + }, + <% } -%> + "Check TLS Certificate <%= $host %>.buetow.org": { + "Plugin": "<%= $plugin_dir %>/check_http", + "Args": ["--sni", "-H", "<%= $host %>.buetow.org", "-C", "20" ], + "DependsOn": ["Check Ping4 <%= $host %>.buetow.org", "Check Ping6 <%= $host %>.buetow.org"] + }, + <% } -%> + <% for my $host (@$acme_hosts) { -%> + <% for my $prefix ('', 'standby.', 'www.') { -%> + <% my $depends_on = $prefix eq 'standby.' ? 'standby.buetow.org' : 'master.buetow.org'; -%> + "Check TLS Certificate <%= $prefix . $host %>": { + "Plugin": "<%= $plugin_dir %>/check_http", + "Args": ["--sni", "-H", "<%= $prefix . $host %>", "-C", "20" ], + "DependsOn": ["Check Ping4 <%= $depends_on %>", "Check Ping6 <%= $depends_on %>"] + }, + <% for my $proto (4, 6) { -%> + "Check HTTP IPv<%= $proto %> <%= $prefix . $host %>": { + "Plugin": "<%= $plugin_dir %>/check_http", + "Args": ["<%= $prefix . $host %>", "-<%= $proto %>"], + "DependsOn": ["Check Ping<%= $proto %> <%= $depends_on %>"] + }, + <% } -%> + <% } -%> + <% } -%> + <% for my $host (qw(fishfinger blowfish)) { -%> + <% for my $proto (4, 6) { -%> + "Check Dig <%= $host %>.buetow.org IPv<%= $proto %>": { + "Plugin": "<%= $plugin_dir %>/check_dig", + "Args": ["-H", "<%= $host %>.buetow.org", "-l", "buetow.org", "-<%= $proto %>"], + "DependsOn": ["Check Ping<%= $proto %> <%= $host %>.buetow.org"] + }, + "Check SMTP <%= $host %>.buetow.org IPv<%= $proto %>": { + "Plugin": "<%= $plugin_dir %>/check_smtp", + "Args": ["-H", "<%= $host %>.buetow.org", "-<%= $proto %>"], + "DependsOn": ["Check Ping<%= $proto %> <%= $host %>.buetow.org"] + }, + "Check Gemini TCP <%= $host %>.buetow.org IPv<%= $proto %>": { + "Plugin": "<%= $plugin_dir %>/check_tcp", + "Args": ["-H", "<%= $host %>.buetow.org", "-p", "1965", "-<%= $proto %>"], + "DependsOn": ["Check Ping<%= $proto %> <%= $host %>.buetow.org"] + }, + <% } -%> + <% } -%> + "Check Users <%= $hostname %>": { + "Plugin": "<%= $plugin_dir %>/check_users", + "Args": ["-w", "2", "-c", "3"] + }, + "Check SWAP <%= $hostname %>": { + "Plugin": "<%= $plugin_dir %>/check_swap", + "Args": ["-w", "95%", "-c", "90%"] + }, + "Check Procs <%= $hostname %>": { + "Plugin": "<%= $plugin_dir %>/check_procs", + "Args": ["-w", "80", "-c", "100"] + }, + "Check Disk <%= $hostname %>": { + "Plugin": "<%= $plugin_dir %>/check_disk", + "Args": ["-w", "30%", "-c", "10%"] + }, + "Check Load <%= $hostname %>": { + "Plugin": "<%= $plugin_dir %>/check_load", + "Args": ["-w", "2,1,1", "-c", "4,3,3"] + } + } +} diff --git a/gemfeed/examples/conf/frontends/etc/gorum.json.tpl b/gemfeed/examples/conf/frontends/etc/gorum.json.tpl new file mode 100644 index 00000000..247a9dbf --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/gorum.json.tpl @@ -0,0 +1,18 @@ +{ + "StateDir": "/var/run/gorum", + "Address": "<%= $hostname.'.'.$domain %>:4321", + "EmailTo": "", + "EmailFrom": "gorum@mx.buetow.org", + "Nodes": { + "Blowfish": { + "Hostname": "blowfish.buetow.org", + "Port": 4321, + "Priority": 100 + }, + "Fishfinger": { + "Hostname": "fishfinger.buetow.org", + "Port": 4321, + "Priority": 50 + } + } +} diff --git a/gemfeed/examples/conf/frontends/etc/httpd.conf.tpl b/gemfeed/examples/conf/frontends/etc/httpd.conf.tpl new file mode 100644 index 00000000..c3a2764e --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/httpd.conf.tpl @@ -0,0 +1,184 @@ +<% our @prefixes = ('', 'www.', 'standby.'); -%> +# Plain HTTP for ACME and HTTPS redirect +<% for my $host (@$acme_hosts) { for my $prefix (@prefixes) { -%> +server "<%= $prefix.$host %>" { + listen on * port 80 + log style forwarded + location "/.well-known/acme-challenge/*" { + root "/acme" + request strip 2 + } + location * { + block return 302 "https://$HTTP_HOST$REQUEST_URI" + } +} +<% } } -%> + +# Current server's FQDN (e.g. for mail server ACME cert requests) +server "<%= "$hostname.$domain" %>" { + listen on * port 80 + log style forwarded + location "/.well-known/acme-challenge/*" { + root "/acme" + request strip 2 + } + location * { + block return 302 "https://<%= "$hostname.$domain" %>" + } +} + +server "<%= "$hostname.$domain" %>" { + listen on * port 8080 + log style forwarded + location * { + root "/htdocs/buetow.org/self" + directory auto index + } +} + +# Gemtexter hosts +<% for my $host (qw/foo.zone stats.foo.zone/) { for my $prefix (@prefixes) { -%> +server "<%= $prefix.$host %>" { + listen on * port 8080 + log style forwarded + location "/.git*" { + block return 302 "https://<%= $prefix.$host %>" + } + location * { + <% if ($prefix eq 'www.') { -%> + block return 302 "https://<%= $host %>$REQUEST_URI" + <% } else { -%> + root "/htdocs/gemtexter/<%= $host %>" + directory auto index + <% } -%> + } +} +<% } } -%> + +# Redirect to paul.buetow.org +<% for my $prefix (@prefixes) { -%> +server "<%= $prefix %>buetow.org" { + listen on * port 8080 + log style forwarded + location * { + block return 302 "https://paul.buetow.org$REQUEST_URI" + } +} + +# Redirect blog to foo.zone +server "<%= $prefix %>blog.buetow.org" { + listen on * port 8080 + log style forwarded + location * { + block return 302 "https://foo.zone$REQUEST_URI" + } +} + +server "<%= $prefix %>snonux.foo" { + listen on * port 8080 + log style forwarded + location * { + block return 302 "https://foo.zone/about$REQUEST_URI" + } +} + +server "<%= $prefix %>paul.buetow.org" { + listen on * port 8080 + log style forwarded + location * { + block return 302 "https://foo.zone/about$REQUEST_URI" + } +} +<% } -%> + +# Redirect to gitub.dtail.dev +<% for my $prefix (@prefixes) { -%> +server "<%= $prefix %>dtail.dev" { + listen on * port 8080 + log style forwarded + location * { + block return 302 "https://github.dtail.dev$REQUEST_URI" + } +} +<% } -%> + +# Irregular Ninja special hosts +<% for my $prefix (@prefixes) { -%> +server "<%= $prefix %>irregular.ninja" { + listen on * port 8080 + log style forwarded + location * { + root "/htdocs/irregular.ninja" + directory auto index + } +} +<% } -%> + +<% for my $prefix (@prefixes) { -%> +server "<%= $prefix %>alt.irregular.ninja" { + listen on * port 8080 + log style forwarded + location * { + root "/htdocs/alt.irregular.ninja" + directory auto index + } +} +<% } -%> + +# joern special host +<% for my $prefix (@prefixes) { -%> +server "<%= $prefix %>joern.buetow.org" { + listen on * port 8080 + log style forwarded + location * { + root "/htdocs/joern/" + directory auto index + } +} +<% } -%> + +# Dory special host +<% for my $prefix (@prefixes) { -%> +server "<%= $prefix %>dory.buetow.org" { + listen on * port 8080 + log style forwarded + location * { + root "/htdocs/joern/dory.buetow.org" + directory auto index + } +} +<% } -%> + +# ecat special host +<% for my $prefix (@prefixes) { -%> +server "<%= $prefix %>ecat.buetow.org" { + listen on * port 8080 + log style forwarded + location * { + root "/htdocs/joern/ecat.buetow.org" + directory auto index + } +} +<% } -%> + +<% for my $prefix (@prefixes) { -%> +server "<%= $prefix %>fotos.buetow.org" { + listen on * port 8080 + log style forwarded + root "/htdocs/buetow.org/fotos" + directory auto index +} +<% } -%> + +# Defaults +server "default" { + listen on * port 80 + log style forwarded + block return 302 "https://foo.zone$REQUEST_URI" +} + +server "default" { + listen on * port 8080 + log style forwarded + block return 302 "https://foo.zone$REQUEST_URI" +} diff --git a/gemfeed/examples/conf/frontends/etc/inetd.conf b/gemfeed/examples/conf/frontends/etc/inetd.conf new file mode 100644 index 00000000..13163877 --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/inetd.conf @@ -0,0 +1,2 @@ +127.0.0.1:11965 stream tcp nowait www /usr/local/bin/vger vger -v +rsync stream tcp nowait root /usr/local/bin/rsync rsyncd --daemon diff --git a/gemfeed/examples/conf/frontends/etc/login.conf.d/inetd b/gemfeed/examples/conf/frontends/etc/login.conf.d/inetd new file mode 100644 index 00000000..c8620c41 --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/login.conf.d/inetd @@ -0,0 +1,3 @@ +inetd:\ + :maxproc=10:\ + :tc=daemon: diff --git a/gemfeed/examples/conf/frontends/etc/mail/aliases b/gemfeed/examples/conf/frontends/etc/mail/aliases new file mode 100644 index 00000000..91bf1d06 --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/mail/aliases @@ -0,0 +1,103 @@ +# +# $OpenBSD: aliases,v 1.68 2020/01/24 06:17:37 tedu Exp $ +# +# Aliases in this file will NOT be expanded in the header from +# Mail, but WILL be visible over networks or from /usr/libexec/mail.local. +# +# >>>>>>>>>> The program "newaliases" must be run after +# >> NOTE >> this file is updated for any changes to +# >>>>>>>>>> show through to smtpd. +# + +# Basic system aliases -- these MUST be present +MAILER-DAEMON: postmaster +postmaster: root + +# General redirections for important pseudo accounts +daemon: root +ftp-bugs: root +operator: root +www: root +admin: root + +# Redirections for pseudo accounts that should not receive mail +_bgpd: /dev/null +_dhcp: /dev/null +_dpb: /dev/null +_dvmrpd: /dev/null +_eigrpd: /dev/null +_file: /dev/null +_fingerd: /dev/null +_ftp: /dev/null +_hostapd: /dev/null +_identd: /dev/null +_iked: /dev/null +_isakmpd: /dev/null +_iscsid: /dev/null +_ldapd: /dev/null +_ldpd: /dev/null +_mopd: /dev/null +_nsd: /dev/null +_ntp: /dev/null +_ospfd: /dev/null +_ospf6d: /dev/null +_pbuild: /dev/null +_pfetch: /dev/null +_pflogd: /dev/null +_ping: /dev/null +_pkgfetch: /dev/null +_pkguntar: /dev/null +_portmap: /dev/null +_ppp: /dev/null +_rad: /dev/null +_radiusd: /dev/null +_rbootd: /dev/null +_relayd: /dev/null +_ripd: /dev/null +_rstatd: /dev/null +_rusersd: /dev/null +_rwalld: /dev/null +_smtpd: /dev/null +_smtpq: /dev/null +_sndio: /dev/null +_snmpd: /dev/null +_spamd: /dev/null +_switchd: /dev/null +_syslogd: /dev/null +_tcpdump: /dev/null +_traceroute: /dev/null +_tftpd: /dev/null +_unbound: /dev/null +_unwind: /dev/null +_vmd: /dev/null +_x11: /dev/null +_ypldap: /dev/null +bin: /dev/null +build: /dev/null +nobody: /dev/null +_tftp_proxy: /dev/null +_ftp_proxy: /dev/null +_sndiop: /dev/null +_syspatch: /dev/null +_slaacd: /dev/null +sshd: /dev/null + +# Well-known aliases -- these should be filled in! +root: paul +manager: root +dumper: root + +# RFC 2142: NETWORK OPERATIONS MAILBOX NAMES +abuse: root +noc: root +security: root + +# RFC 2142: SUPPORT MAILBOX NAMES FOR SPECIFIC INTERNET SERVICES +hostmaster: root +# usenet: root +# news: usenet +webmaster: root +# ftp: root + +paul: paul.buetow@protonmail.com +albena: albena.buetow@protonmail.com diff --git a/gemfeed/examples/conf/frontends/etc/mail/smtpd.conf.tpl b/gemfeed/examples/conf/frontends/etc/mail/smtpd.conf.tpl new file mode 100644 index 00000000..7764b345 --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/mail/smtpd.conf.tpl @@ -0,0 +1,23 @@ +# This is the smtpd server system-wide configuration file. +# See smtpd.conf(5) for more information. + +# I used https://www.checktls.com/TestReceiver for testing. + +pki "buetow_org_tls" cert "/etc/ssl/<%= "$hostname.$domain" %>.fullchain.pem" +pki "buetow_org_tls" key "/etc/ssl/private/<%= "$hostname.$domain" %>.key" + +table aliases file:/etc/mail/aliases +table virtualdomains file:/etc/mail/virtualdomains +table virtualusers file:/etc/mail/virtualusers + +listen on socket +listen on all tls pki "buetow_org_tls" hostname "<%= "$hostname.$domain" %>" +#listen on all + +action localmail mbox alias +action receive mbox virtual +action outbound relay + +match from any for domain action receive +match from local for local action localmail +match from local for any action outbound diff --git a/gemfeed/examples/conf/frontends/etc/mail/virtualdomains b/gemfeed/examples/conf/frontends/etc/mail/virtualdomains new file mode 100644 index 00000000..b59554ac --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/mail/virtualdomains @@ -0,0 +1,20 @@ +buetow.org +paul.buetow.org +mx.buetow.org +de.buetow.org +bg.buetow.org +uk.buetow.org +us.buetow.org +es.buetow.org +dev.buetow.org +oss.buetow.org +ex.buetow.org +xxx.buetow.org +newsletter.buetow.org +gadgets.buetow.org +orders.buetow.org +nospam.buetow.org +snonux.foo +dtail.dev +foo.zone +paul.cyou diff --git a/gemfeed/examples/conf/frontends/etc/mail/virtualusers b/gemfeed/examples/conf/frontends/etc/mail/virtualusers new file mode 100644 index 00000000..6cfac58b --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/mail/virtualusers @@ -0,0 +1,5 @@ +albena@buetow.org albena.buetow@protonmail.com +joern@buetow.org df2hbradio@gmail.com +dory@buetow.org df2hbradio@gmail.com +ecat@buetow.org df2hbradio@gmail.com +@ paul.buetow@protonmail.com diff --git a/gemfeed/examples/conf/frontends/etc/myname.tpl b/gemfeed/examples/conf/frontends/etc/myname.tpl new file mode 100644 index 00000000..dcd4ca04 --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/myname.tpl @@ -0,0 +1 @@ +<%= $fqdns->($vio0_ip) %> diff --git a/gemfeed/examples/conf/frontends/etc/newsyslog.conf b/gemfeed/examples/conf/frontends/etc/newsyslog.conf new file mode 100644 index 00000000..bbd1aa55 --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/newsyslog.conf @@ -0,0 +1,14 @@ +# logfile_name owner:group mode count size when flags +/var/cron/log root:wheel 600 3 10 * Z +/var/log/authlog root:wheel 640 7 * 168 Z +/var/log/daemon 640 14 300 * Z +/var/log/lpd-errs 640 7 10 * Z +/var/log/maillog 640 7 * 24 Z +/var/log/messages 644 5 300 * Z +/var/log/secure 600 7 * 168 Z +/var/log/wtmp 644 7 * $M1D4 B "" +/var/log/xferlog 640 7 250 * Z +/var/log/pflog 600 3 250 * ZB "pkill -HUP -u root -U root -t - -x pflogd" +/var/www/logs/access.log 644 14 * $W0 Z "pkill -USR1 -u root -U root -x httpd" +/var/www/logs/error.log 644 7 250 * Z "pkill -USR1 -u root -U root -x httpd" +/var/log/fooodds 640 7 300 * Z diff --git a/gemfeed/examples/conf/frontends/etc/rc.conf.local b/gemfeed/examples/conf/frontends/etc/rc.conf.local new file mode 100644 index 00000000..842f16d7 --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/rc.conf.local @@ -0,0 +1,5 @@ +httpd_flags= +inetd_flags= +nsd_flags= +pkg_scripts="uptimed httpd" +relayd_flags= diff --git a/gemfeed/examples/conf/frontends/etc/rc.d/dserver.tpl b/gemfeed/examples/conf/frontends/etc/rc.d/dserver.tpl new file mode 100755 index 00000000..aec80f54 --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/rc.d/dserver.tpl @@ -0,0 +1,16 @@ +#!/bin/ksh + +daemon="/usr/local/bin/dserver" +daemon_flags="-cfg /etc/dserver/dtail.json" +daemon_user="_dserver" + +. /etc/rc.d/rc.subr + +rc_reload=NO + +rc_pre() { + install -d -o _dserver /var/log/dserver + install -d -o _dserver /var/run/dserver/cache +} + +rc_cmd $1 & diff --git a/gemfeed/examples/conf/frontends/etc/rc.d/gorum.tpl b/gemfeed/examples/conf/frontends/etc/rc.d/gorum.tpl new file mode 100755 index 00000000..3b4f403d --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/rc.d/gorum.tpl @@ -0,0 +1,16 @@ +#!/bin/ksh + +daemon="/usr/local/bin/gorum" +daemon_flags="-cfg /etc/gorum.json" +daemon_user="_gorum" +daemon_logger="daemon.info" + +. /etc/rc.d/rc.subr + +rc_reload=NO + +rc_pre() { + install -d -o _gorum /var/log/gorum +} + +rc_cmd $1 & diff --git a/gemfeed/examples/conf/frontends/etc/relayd.conf.tpl b/gemfeed/examples/conf/frontends/etc/relayd.conf.tpl new file mode 100644 index 00000000..1900c0bf --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/relayd.conf.tpl @@ -0,0 +1,86 @@ +<% our @prefixes = ('', 'www.', 'standby.'); -%> +log connection + +# Wireguard endpoints of the k3s cluster nodes running in FreeBSD bhyve Linux VMs via Wireguard tunnels +table { + 192.168.2.120 + 192.168.2.121 + 192.168.2.122 +} + +# Same backends, separate table for registry service on port 30001 +table { + 192.168.2.120 + 192.168.2.121 + 192.168.2.122 +} + +# Local OpenBSD httpd +table { + 127.0.0.1 + ::1 +} + +http protocol "https" { + <% for my $host (@$acme_hosts) { for my $prefix (@prefixes) { -%> + tls keypair <%= $prefix.$host -%> + <% } } -%> + tls keypair <%= $hostname.'.'.$domain -%> + + match request header set "X-Forwarded-For" value "$REMOTE_ADDR" + match request header set "X-Forwarded-Proto" value "https" + + # WebSocket support for audiobookshelf + pass header "Connection" + pass header "Upgrade" + pass header "Sec-WebSocket-Key" + pass header "Sec-WebSocket-Version" + pass header "Sec-WebSocket-Extensions" + pass header "Sec-WebSocket-Protocol" + + <% for my $host (@$f3s_hosts) { for my $prefix (@prefixes) { -%> + <% if ($host eq 'registry.f3s.buetow.org') { -%> + match request quick header "Host" value "<%= $prefix.$host -%>" forward to + <% } else { -%> + match request quick header "Host" value "<%= $prefix.$host -%>" forward to + <% } } } -%> +} + +relay "https4" { + listen on <%= $vio0_ip %> port 443 tls + protocol "https" + forward to port 8080 + forward to port 30001 check tcp + forward to port 80 check tcp +} + +relay "https6" { + listen on <%= $ipv6address->($hostname) %> port 443 tls + protocol "https" + forward to port 8080 + forward to port 30001 check tcp + forward to port 80 check tcp +} + +tcp protocol "gemini" { + tls keypair foo.zone + tls keypair stats.foo.zone + tls keypair snonux.foo + tls keypair paul.buetow.org + tls keypair standby.foo.zone + tls keypair standby.stats.foo.zone + tls keypair standby.snonux.foo + tls keypair standby.paul.buetow.org +} + +relay "gemini4" { + listen on <%= $vio0_ip %> port 1965 tls + protocol "gemini" + forward to 127.0.0.1 port 11965 +} + +relay "gemini6" { + listen on <%= $ipv6address->($hostname) %> port 1965 tls + protocol "gemini" + forward to 127.0.0.1 port 11965 +} diff --git a/gemfeed/examples/conf/frontends/etc/rsyncd.conf.tpl b/gemfeed/examples/conf/frontends/etc/rsyncd.conf.tpl new file mode 100644 index 00000000..e9fe3cf8 --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/rsyncd.conf.tpl @@ -0,0 +1,28 @@ +<% my $allow = '*.wg0.wan.buetow.org,*.wg0,localhost'; %> +max connections = 5 +timeout = 300 + +[joernshtdocs] +comment = Joerns htdocs +path = /var/www/htdocs/joern +read only = yes +list = yes +uid = www +gid = www +hosts allow = <%= $allow %> + +# [publicgemini] +# comment = Public Gemini capsule content +# path = /var/gemini +# read only = yes +# list = yes +# uid = www +# gid = www +# hosts allow = <%= $allow %> + +# [sslcerts] +# comment = TLS certificates +# path = /etc/ssl +# read only = yes +# list = yes +# hosts allow = <%= $allow %> diff --git a/gemfeed/examples/conf/frontends/etc/taskrc.tpl b/gemfeed/examples/conf/frontends/etc/taskrc.tpl new file mode 100644 index 00000000..ed97d385 --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/taskrc.tpl @@ -0,0 +1,40 @@ +# [Created by task 2.6.2 7/9/2023 20:52:31] +# Taskwarrior program configuration file. +# For more documentation, see https://taskwarrior.org or try 'man task', 'man task-color', +# 'man task-sync' or 'man taskrc' + +# Here is an example of entries that use the default, override and blank values +# variable=foo -- By specifying a value, this overrides the default +# variable= -- By specifying no value, this means no default +# #variable=foo -- By commenting out the line, or deleting it, this uses the default + +# You can also refence environment variables: +# variable=$HOME/task +# variable=$VALUE + +# Use the command 'task show' to see all defaults and overrides + +# Files +data.location=/home/git/.task + +# To use the default location of the XDG directories, +# move this configuration file from ~/.taskrc to ~/.config/task/taskrc and uncomment below + +#data.location=~/.local/share/task +#hooks.location=~/.config/task/hooks + +# Color theme (uncomment one to use) +#include light-16.theme +#include light-256.theme +#include dark-16.theme +#include dark-256.theme +#include dark-red-256.theme +#include dark-green-256.theme +#include dark-blue-256.theme +#include dark-violets-256.theme +#include dark-yellow-green.theme +#include dark-gray-256.theme +#include dark-gray-blue-256.theme +#include solarized-dark-256.theme +#include solarized-light-256.theme +#include no-color.theme diff --git a/gemfeed/examples/conf/frontends/etc/tmux.conf b/gemfeed/examples/conf/frontends/etc/tmux.conf new file mode 100644 index 00000000..14493260 --- /dev/null +++ b/gemfeed/examples/conf/frontends/etc/tmux.conf @@ -0,0 +1,24 @@ +set-option -g allow-rename off +set-option -g default-terminal "screen-256color" +set-option -g history-limit 100000 +set-option -g status-bg '#444444' +set-option -g status-fg '#ffa500' + +set-window-option -g mode-keys vi + +bind-key h select-pane -L +bind-key j select-pane -D +bind-key k select-pane -U +bind-key l select-pane -R + +bind-key H resize-pane -L 5 +bind-key J resize-pane -D 5 +bind-key K resize-pane -U 5 +bind-key L resize-pane -R 5 + +bind-key b break-pane -d +bind-key c new-window -c '#{pane_current_path}' +bind-key p setw synchronize-panes off +bind-key P setw synchronize-panes on +bind-key r source-file ~/.tmux.conf \; display-message "~/.tmux.conf reloaded" +bind-key T choose-tree diff --git a/gemfeed/examples/conf/frontends/scripts/acme.sh.tpl b/gemfeed/examples/conf/frontends/scripts/acme.sh.tpl new file mode 100644 index 00000000..8d306092 --- /dev/null +++ b/gemfeed/examples/conf/frontends/scripts/acme.sh.tpl @@ -0,0 +1,68 @@ +#!/bin/sh + +MY_IP=`ifconfig vio0 | awk '$1 == "inet" { print $2 }'` + +# New hosts may not have a cert, just copy foo.zone as a +# placeholder, so that services can at least start proprely. +# cert will be updated with next acme-client runs! +ensure_placeholder_cert () { + host=$1 + copy_from=foo.zone + + if [ ! -f /etc/ssl/$host.crt ]; then + cp -v /etc/ssl/$copy_from.crt /etc/ssl/$host.crt + cp -v /etc/ssl/$copy_from.fullchain.pem /etc/ssl/$host.fullchain.pem + cp -v /etc/ssl/private/$copy_from.key /etc/ssl/private/$host.key + fi +} + +handle_cert () { + host=$1 + host_ip=`host $host | awk '/has address/ { print $(NF) }'` + + grep -q "^server \"$host\"" /etc/httpd.conf + if [ $? -ne 0 ]; then + echo "Host $host not configured in httpd, skipping..." + return + fi + ensure_placeholder_cert "$host" + + if [ "$MY_IP" != "$host_ip" ]; then + echo "Not serving $host, skipping..." + return + fi + + # Create symlink, so that relayd also can read it. + crt_path=/etc/ssl/$host + if [ -e $crt_path.crt ]; then + rm $crt_path.crt + fi + ln -s $crt_path.fullchain.pem $crt_path.crt + # Requesting and renewing certificate. + /usr/sbin/acme-client -v $host +} + +has_update=no +<% for my $host (@$acme_hosts) { -%> +<% for my $prefix ('', 'www.', 'standby.') { -%> +handle_cert <%= $prefix.$host %> +if [ $? -eq 0 ]; then + has_update=yes +fi +<% } -%> +<% } -%> + +# Current server's FQDN (e.g. for mail server certs) +handle_cert <%= "$hostname.$domain" %> +if [ $? -eq 0 ]; then + has_update=yes +fi + +# Pick up the new certs. +if [ $has_update = yes ]; then + # TLS offloading fully moved to relayd now + # /usr/sbin/rcctl reload httpd + + /usr/sbin/rcctl reload relayd + /usr/sbin/rcctl restart smtpd +fi diff --git a/gemfeed/examples/conf/frontends/scripts/dns-failover.ksh b/gemfeed/examples/conf/frontends/scripts/dns-failover.ksh new file mode 100644 index 00000000..dfc24ee3 --- /dev/null +++ b/gemfeed/examples/conf/frontends/scripts/dns-failover.ksh @@ -0,0 +1,133 @@ +#!/bin/ksh + +ZONES_DIR=/var/nsd/zones/master/ +DEFAULT_MASTER=fishfinger.buetow.org +DEFAULT_STANDBY=blowfish.buetow.org + +determine_master_and_standby () { + local master=$DEFAULT_MASTER + local standby=$DEFAULT_STANDBY + + # Weekly auto-failover for Let's Encrypt automation + local -i -r week_of_the_year=$(date +%U) + if [ $(( week_of_the_year % 2 )) -ne 0 ]; then + local tmp=$master + master=$standby + standby=$tmp + fi + + local -i health_ok=1 + if ! ftp -4 -o - https://$master/index.txt | grep -q "Welcome to $master"; then + echo "https://$master/index.txt IPv4 health check failed" + health_ok=0 + elif ! ftp -6 -o - https://$master/index.txt | grep -q "Welcome to $master"; then + echo "https://$master/index.txt IPv6 health check failed" + health_ok=0 + fi + + if [ $health_ok -eq 0 ]; then + local tmp=$master + master=$standby + standby=$tmp + fi + + echo "Master is $master, standby is $standby" + + host $master | awk '/has address/ { print $(NF) }' >/var/nsd/run/master_a + host $master | awk '/has IPv6 address/ { print $(NF) }' >/var/nsd/run/master_aaaa + host $standby | awk '/has address/ { print $(NF) }' >/var/nsd/run/standby_a + host $standby | awk '/has IPv6 address/ { print $(NF) }' >/var/nsd/run/standby_aaaa +} + +transform () { + sed -E ' + /IN A .*; Enable failover/ { + /^standby/! { + s/^(.*) 300 IN A (.*) ; (.*)/\1 300 IN A '$(cat /var/nsd/run/master_a)' ; \3/; + } + /^standby/ { + s/^(.*) 300 IN A (.*) ; (.*)/\1 300 IN A '$(cat /var/nsd/run/standby_a)' ; \3/; + } + } + /IN AAAA .*; Enable failover/ { + /^standby/! { + s/^(.*) 300 IN AAAA (.*) ; (.*)/\1 300 IN AAAA '$(cat /var/nsd/run/master_aaaa)' ; \3/; + } + /^standby/ { + s/^(.*) 300 IN AAAA (.*) ; (.*)/\1 300 IN AAAA '$(cat /var/nsd/run/standby_aaaa)' ; \3/; + } + } + / ; serial/ { + s/^( +) ([0-9]+) .*; (.*)/\1 '$(date +%s)' ; \3/; + } + ' +} + +zone_is_ok () { + local -r zone=$1 + local -r domain=${zone%.zone} + dig $domain @localhost | grep -q "$domain.*IN.*NS" +} + +failover_zone () { + local -r zone_file=$1 + local -r zone=$(basename $zone_file) + + # Race condition (e.g. script execution abored in the middle previous run) + if [ -f $zone_file.bak ]; then + mv $zone_file.bak $zone_file + fi + + cat $zone_file | transform > $zone_file.new.tmp + + grep -v ' ; serial' $zone_file.new.tmp > $zone_file.new.noserial.tmp + grep -v ' ; serial' $zone_file > $zone_file.old.noserial.tmp + + echo "Has zone $zone_file changed?" + if diff -u $zone_file.old.noserial.tmp $zone_file.new.noserial.tmp; then + echo "The zone $zone_file hasn't changed" + rm $zone_file.*.tmp + return 0 + fi + + cp $zone_file $zone_file.bak + mv $zone_file.new.tmp $zone_file + rm $zone_file.*.tmp + echo "Reloading nsd" + nsd-control reload + + if ! zone_is_ok $zone; then + echo "Rolling back $zone_file changes" + cp $zone_file $zone_file.invalid + mv $zone_file.bak $zone_file + echo "Reloading nsd" + nsd-control reload + zone_is_ok $zone + return 3 + fi + + for cleanup in invalid bak; do + if [ -f $zone_file.$cleanup ]; then + rm $zone_file.$cleanup + fi + done + + echo "Failover of zone $zone to $MASTER completed" + return 1 +} + +main () { + determine_master_and_standby + + local -i ec=0 + for zone_file in $ZONES_DIR/*.zone; do + if ! failover_zone $zone_file; then + ec=1 + fi + done + + # ec other than 0: CRON will send out an E-Mail. + exit $ec +} + +main diff --git a/gemfeed/examples/conf/frontends/scripts/dserver-update-key-cache.sh.tpl b/gemfeed/examples/conf/frontends/scripts/dserver-update-key-cache.sh.tpl new file mode 100644 index 00000000..86b5ecf9 --- /dev/null +++ b/gemfeed/examples/conf/frontends/scripts/dserver-update-key-cache.sh.tpl @@ -0,0 +1,34 @@ +#!/bin/ksh + +CACHEDIR=/var/run/dserver/cache +DSERVER_USER=_dserver +DSERVER_GROUP=_dserver + +echo 'Updating SSH key cache' + +ls /home/ | while read remoteuser; do + keysfile=/home/$remoteuser/.ssh/authorized_keys + + if [ -f $keysfile ]; then + cachefile=$CACHEDIR/$remoteuser.authorized_keys + echo "Caching $keysfile -> $cachefile" + + cp $keysfile $cachefile + chown $DSERVER_USER:$DSERVER_GROUP $cachefile + chmod 600 $cachefile + fi +done + +# Cleanup obsolete public SSH keys +find $CACHEDIR -name \*.authorized_keys -type f | +while read cachefile; do + remoteuser=$(basename $cachefile | cut -d. -f1) + keysfile=/home/$remoteuser/.ssh/authorized_keys + + if [ ! -f $keysfile ]; then + echo 'Deleting obsolete cache file $cachefile' + rm $cachefile + fi +done + +echo 'All set...' diff --git a/gemfeed/examples/conf/frontends/scripts/fooodds.txt b/gemfeed/examples/conf/frontends/scripts/fooodds.txt new file mode 100644 index 00000000..0e08bdd1 --- /dev/null +++ b/gemfeed/examples/conf/frontends/scripts/fooodds.txt @@ -0,0 +1,191 @@ +% ++ +.. +/actuator +/actuator/health +/admin +/ajax +alfacgiapi +/ALFA_DATA +/api +/apply.cgi +/ARest1.exe +.asp +/aspera +/assets +/audiobookshelf +/auth +/autodiscover +/.aws +/bac +/back +/backup +/bak +/base +/.bash_history +/bf +/bin +/bin/sh +/bk +/bkp +/blog +/blurs +/boaform +/boafrm +/.bod +/Br7q +/british-airways +/buetow.org.zip +/buetow.zip +/burodecredito +/c +/.cache +/ccaguardians +/cdn-cgi +/centralbankthailand +/cfdump.packetsdatabase.com +/charlesbridge +/check.txt +/cimtechsolutions +/.circleci +/c/k2 +/ckfinder +/client.zip +/cloud-config.yml +/cloudflare.com +/clssettlement +/cmd,/simZysh/register_main/setCookie +/cn/cmd +/codeberg +/CODE_OF_CONDUCT.md +/columbiagas +/common_page +/comp +/concerto +/config +/config.json +/config.xml +/Config.xml +/config.yaml +/config.yml +/connectivitycheck.gstatic.com +/connector.sds +/console +/contact-information.html +/contact-us +/containers +/CONTRIBUTING.md +/credentials.txt +/crivo +/current_config +/cwservices +/daAV +/dana-cached +/dana-na +/database_backup.sql +/.database.bak +/database.sql +/data.zip +/db +/debug +/debug.cgi +/decoherence-is-just-realizing-this +/demo +/developmentserver +/directory.gz +/directory.tar +/directory.zip +/dir.html +/DnHb +/dns-query +docker-compose +/docker-compose.yml +/?document=images +/Dorybau2.html +/Dorybau.html +/dory.buetow.org +/download +/DpbF +/druid +/dtail.dev.gz +/dtail.dev.sql +/dtail.dev.tar.gz +/dtail.dev.zip +/dtail.html +/dtail.zip +/dump.sql +/dvQ1 +/dvr/cmd +/edualy-shammin +/ekggho +.env +/epa +/etc +/eW9h +/ews +/F3to +/f3Yk +/fahrzeugtechnik.fh-joanneum.at +/failedbythefos +/features +/federalhomeloanbankofdesmoines +/fhir +/fhir-server +/file-manager +/files +/files.zip +/firstfinancial +/flash +/flower +/foostats +/footlocker +/foo.zip +/foo.zone.bz2 +/foozone.webp +/foo.zone.zip +/form.html +/freeze.na4u.ru +/frontend.zip +/ftpsync.settings +/full_backup.zip +/FvwmRearrange.png +/gdb.pdf +/geoserver +.git +/git-guides +/global-protect +/gm-donate.net +/GMUs +/goform +/google.com +/GoRU +/GponForm +/helpdesk +/high-noise-level-for-that-earth-day-with-colors-gay +/his-viewpoint-is-not-economics-until-they-harden +/hN6p +HNAP1 +/hp +/_ignition +jndi:ldap +.js +.lua +microsoft.exchange +/owa/ +.php +/phpinfo +phpunit +/portal/redlion +/_profiler +.rar +/RDWeb +robots.txt +/SDK +/sitemap.xml +/sites +.sql +/ueditor +/vendor +@vite +wordpress +/wp diff --git a/gemfeed/examples/conf/frontends/scripts/foostats.pl b/gemfeed/examples/conf/frontends/scripts/foostats.pl new file mode 100644 index 00000000..a440d941 --- /dev/null +++ b/gemfeed/examples/conf/frontends/scripts/foostats.pl @@ -0,0 +1,1910 @@ +#!/usr/bin/perl + +use v5.38; + +# Those are enabled automatically now w/ this version of Perl +# use strict; +# use warnings; + +use builtin qw(true false); +use experimental qw(builtin); + +use feature qw(refaliasing); +no warnings qw(experimental::refaliasing); + +# Debugging aids like diagnost