summaryrefslogtreecommitdiff
path: root/gemfeed/examples/conf/frontends/Rexfile
diff options
context:
space:
mode:
Diffstat (limited to 'gemfeed/examples/conf/frontends/Rexfile')
-rw-r--r--gemfeed/examples/conf/frontends/Rexfile648
1 files changed, 648 insertions, 0 deletions
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