From 0f841977cfa1f2b934f433ac4239e612b44e5dcf Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Wed, 13 Jul 2022 13:09:16 +0100 Subject: Use ACME --- frontends/Rexfile | 83 ++++++---- frontends/etc/acme-client.conf.tpl | 37 +++++ frontends/etc/httpd.conf | 181 --------------------- frontends/etc/httpd.conf.tpl | 149 +++++++++++++++++ frontends/etc/relayd.conf.tpl | 11 +- frontends/scripts/acme.sh.tpl | 22 +++ frontends/var/nsd/zones/master/buetow.org.zone.tpl | 1 + frontends/var/nsd/zones/master/dtail.dev.zone.tpl | 1 + 8 files changed, 268 insertions(+), 217 deletions(-) create mode 100644 frontends/etc/acme-client.conf.tpl delete mode 100644 frontends/etc/httpd.conf create mode 100644 frontends/etc/httpd.conf.tpl create mode 100644 frontends/scripts/acme.sh.tpl diff --git a/frontends/Rexfile b/frontends/Rexfile index 6ffd55a..5eeda02 100644 --- a/frontends/Rexfile +++ b/frontends/Rexfile @@ -40,12 +40,18 @@ our $ipv6address = sub { # facts aren't set yet due to the myname file in the first place. our $fqdns = sub { my $ipv4 = shift; - return 'blowfish.buetow.org' if $ipv4 eq '23.88.35.144'; + return 'blowfish.buetow.org' if $ipv4 eq '23.88.35.144'; return 'twofish.buetow.org' if $ipv4 eq '108.160.134.135'; Rex::Logger::info("Unable to determine hostname for $ipv4", 'error'); return 'HOSTNAME-UNKNOWN.buetow.org'; }; +# To determine whether te server is te primary or the secondary. +our $is_primary = sub { + my $ipv4 = shift; + $fqdns->($ipv4) eq 'blowfish.buetow.org'; +}; + our $filewalk; our $filewalk = sub { my $dir = shift; @@ -71,6 +77,7 @@ our $filewalk = sub { our $secrets = sub { read_file './secrets/' . shift }; our @dns_zones = qw/buetow.org dtail.dev foo.surf foo.zone irregular.ninja sidewalk.ninja snonux.de snonux.me snonux.land/; +our @acme_hosts = qw/paul.buetow.org buetow.org dtail.dev foo.zone irregular.ninja snonux.land/; # UTILITY TASKS @@ -79,35 +86,6 @@ task 'dump_info', group => 'frontends', sub { dump_system_information }; # OPENBSD TASKS SECTION -desc 'Install certificates from the secret store'; -task 'certs', group => 'frontends', - sub { - my $restart_services = FALSE; - - for my $source ($filewalk->('./secrets/etc/ssl')) { - my $dest = $source; - $dest =~ s/.*secrets//; - my $mode = $dest =~ /private/ ? '440' : '644'; - - Rex::Logger::info("Dealing with $dest"); - file $dest, - source => $source, - owner => 'root', - group => 'www', - mode => $mode, - on_change => sub { - Rex::Logger::info("$dest changed, scheduling services restart"); - $restart_services = TRUE; - }; - } - - if ($restart_services) { - service 'httpd' => 'restart'; - service 'relayd' => 'restart'; - service 'smtpd' => 'restart'; - } - }; - desc 'Install base stuff'; task 'base', group => 'frontends', sub { @@ -132,6 +110,40 @@ task 'uptimed', group => 'frontends', service 'uptimed', ensure => 'started'; }; +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, + is_primary => $is_primary), + owner => 'root', + group => 'wheel', + mode => '644'; + + file '/usr/local/bin/acme.sh', + content => template('./scripts/acme.sh.tpl', + acme_hosts => \@acme_hosts, + is_primary => $is_primary), + owner => 'root', + group => 'wheel', + mode => '744'; + + file '/etc/daily.local', + ensure => 'present', + owner => 'root', + group => 'wheel', + mode => '744'; + + 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 { @@ -139,7 +151,9 @@ task 'httpd', group => 'frontends', #delete_lines_according_to qr{httpd_flags}, '/etc/rc.conf.local'; file '/etc/httpd.conf', - source => './etc/httpd.conf', + content => template('./etc/httpd.conf.tpl', + acme_hosts => \@acme_hosts, + is_primary => $is_primary), owner => 'root', group => 'wheel', mode => '644', @@ -169,7 +183,9 @@ task 'relayd', group => 'frontends', append_if_no_such_line '/etc/rc.conf.local', 'relayd_flags='; file '/etc/relayd.conf', - content => template('./etc/relayd.conf.tpl', ipv6address => $ipv6address), + content => template('./etc/relayd.conf.tpl', + ipv6address => $ipv6address, + is_primary => $is_primary), owner => 'root', group => 'wheel', mode => '600', @@ -297,10 +313,11 @@ task 'failunderd', group => 'frontends', desc 'Common configs of all hosts'; task 'commons', group => 'frontends', sub { - certs(); base(); uptimed(); httpd(); + acme(); + acme_invoke(); inetd(); relayd(); smtpd(); diff --git a/frontends/etc/acme-client.conf.tpl b/frontends/etc/acme-client.conf.tpl new file mode 100644 index 0000000..681f357 --- /dev/null +++ b/frontends/etc/acme-client.conf.tpl @@ -0,0 +1,37 @@ +# +# $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" +} + +<% + our $primary = $is_primary->($vio0_ip); + our $prefix = $primary ? '' : 'www.'; +%> + +<% for my $host (@$acme_hosts) { %> +domain <%= $prefix.$host %> { + domain key "/etc/ssl/private/<%= $prefix.$host %>.key" + domain full chain certificate "/etc/ssl/<%= $prefix.$host %>.fullchain.pem" + sign with letsencrypt +} +<% } %> diff --git a/frontends/etc/httpd.conf b/frontends/etc/httpd.conf deleted file mode 100644 index 044849e..0000000 --- a/frontends/etc/httpd.conf +++ /dev/null @@ -1,181 +0,0 @@ -server "foo.zone" { - listen on * port 80 - block return 302 "https://foo.zone" -} - -server "www.foo.zone" { - listen on * port 80 - block return 302 "https://www.foo.zone" -} - -server "foo.zone" { - alias "www.foo.zone" - listen on * tls port 443 - tls { - certificate "/etc/ssl/foo.zone.fullchain.pem" - key "/etc/ssl/private/foo.zone.key" - } - location "/*" { - root "/htdocs/gemtexter/foo.zone" - directory auto index - } -} - -server "snonux.land" { - listen on * port 80 - block return 302 "https://snonux.land" -} - -server "www.snonux.land" { - listen on * port 80 - block return 302 "https://www.snonux.land" -} - -server "snonux.land" { - alias "www.snonux.land" - listen on * tls port 443 - tls { - certificate "/etc/ssl/foo.zone.fullchain.pem" - key "/etc/ssl/private/foo.zone.key" - } - location "/*" { - root "/htdocs/gemtexter/foo.zone/notes" - directory auto index - } -} - -server "irregular.ninja" { - listen on * port 80 - block return 302 "https://irregular.ninja" -} - -server "www.irregular.ninja" { - listen on * port 80 - block return 302 "https://www.irregular.ninja" -} - -server "irregular.ninja" { - alias "www.irregular.ninja" - listen on * tls port 443 - tls { - certificate "/etc/ssl/irregular.ninja.fullchain.pem" - key "/etc/ssl/private/irregular.ninja.key" - } - location "/*" { - root "/htdocs/irregular.ninja" - directory auto index - } -} - -server "snonux.de" { - alias "www.snonux.de" - listen on * port 80 - block return 302 "https://foo.zone$REQUEST_URI" -} - -server "snonux.de" { - alias "www.snonux.de" - listen on * tls port 443 - tls { - certificate "/etc/ssl/snonux.de.fullchain.pem" - key "/etc/ssl/private/snonux.de.key" - } - block return 302 "https://foo.zone$REQUEST_URI" -} - -server "foo.surf" { - alias "www.foo.surf" - listen on * port 80 - block return 302 "https://foo.zone$REQUEST_URI" -} - -server "foo.surf" { - alias "www.foo.surf" - listen on * tls port 443 - tls { - certificate "/etc/ssl/foo.surf.fullchain.pem" - key "/etc/ssl/private/foo.surf.key" - } - block return 302 "https://foo.zone$REQUEST_URI" -} - -server "sidewalk.ninja" { - alias "www.sidewalk.ninja" - listen on * port 80 - block return 302 "https://irregular.ninja$REQUEST_URI" -} - -server "sidewalk.ninja" { - alias "www.sidewalk.ninja" - listen on * tls port 443 - tls { - certificate "/etc/ssl/sidewalk.ninja.fullchain.pem" - key "/etc/ssl/private/sidewalk.ninja.key" - } - block return 302 "https://irregular.ninja$REQUEST_URI" -} - -server "buetow.org" { - alias "www.buetow.org" - listen on * port 80 - block return 302 "https://foo.zone$REQUEST_URI" -} - -server "paul.buetow.org" { - alias "contact.buetow.org" - listen on * port 80 - block return 302 "https://foo.zone/contact-information.html" -} - -server "tmp.buetow.org" { - listen on * port 80 - block return 302 "https://buetow.org/tmp/" -} - -server "buetow.org" { - alias "www.buetow.org" - listen on * tls port 443 - tls { - certificate "/etc/ssl/buetow.org.fullchain.pem" - key "/etc/ssl/private/buetow.org.key" - } - root "/htdocs/buetow.org" - location match "/tmp/.*" { - directory auto index - } - location match "/.*" { - block return 302 "https://foo.zone$REQUEST_URI" - } -} - -server "dtail.dev" { - alias "www.dtail.dev" - listen on * port 80 - block return 302 "https://dail.dev" -} - -server "dtail.dev" { - alias "www.dtail.dev" - listen on * tls port 443 - tls { - certificate "/etc/ssl/dtail.dev.fullchain.pem" - key "/etc/ssl/private/dtail.dev.key" - } - location * { - block return 302 "https://github.dtail.dev" - } -} - -server "default" { - listen on * port 80 - block return 302 "https://foo.zone$REQUEST_URI" -} - -server "default" { - listen on * tls port 443 - tls { - certificate "/etc/ssl/foo.zone.fullchain.pem" - key "/etc/ssl/private/foo.zone.key" - } - block return 302 "https://foo.zone$REQUEST_URI" -} diff --git a/frontends/etc/httpd.conf.tpl b/frontends/etc/httpd.conf.tpl new file mode 100644 index 0000000..c536766 --- /dev/null +++ b/frontends/etc/httpd.conf.tpl @@ -0,0 +1,149 @@ +<% + our $primary = $is_primary->($vio0_ip); + our $prefix = $primary ? '' : 'www.'; +%> + +# Plain HTTP for ACME and HTTPS redirect +<% for my $host (@$acme_hosts) { %> +server "<%= $prefix.$host %>" { + listen on * port 80 + location "/.well-known/acme-challenge/*" { + root "/acme" + request strip 2 + } + location * { + block return 302 "https://$HTTP_HOST$REQUEST_URI" + } +} +<% } %> + +# Gemtexter hosts +<% for my $host (qw/foo.zone snonux.land/) { %> +server "<%= $prefix.$host %>" { + listen on * tls port 443 + tls { + certificate "/etc/ssl/<%= $prefix.$host %>.fullchain.pem" + key "/etc/ssl/private/<%= $prefix.$host %>.key" + } + location * { + root "/htdocs/gemtexter/<%= $host %>" + directory auto index + } +} +<% } %> + +# DTail special host +server "<%= $prefix %>dtail.dev" { + listen on * tls port 443 + tls { + certificate "/etc/ssl/<%= $prefix %>dtail.dev.fullchain.pem" + key "/etc/ssl/private/<%= $prefix %>dtail.dev.key" + } + location * { + block return 302 "https://github.dtail.dev$REQUEST_URI" + } +} + +# Irregular Ninja special host +server "<%= $prefix %>irregular.ninja" { + listen on * tls port 443 + tls { + certificate "/etc/ssl/<%= $prefix %>irregular.ninja.fullchain.pem" + key "/etc/ssl/private/<%= $prefix %>irregular.ninja.key" + } + location * { + root "/htdocs/irregular.ninja" + directory auto index + } +} + +# buetow.org special host. +server "<%= $prefix %>buetow.org" { + listen on * tls port 443 + tls { + certificate "/etc/ssl/<%= $prefix %>buetow.org.fullchain.pem" + key "/etc/ssl/private/<%= $prefix %>buetow.org.key" + } + root "/htdocs/buetow.org" + location match "/tmp/.*" { + directory auto index + } + location match "/.*" { + block return 302 "https://paul.buetow.org" + } +} + +<% if ($primary) { %> +server "paul.buetow.org" { + listen on * tls port 443 + tls { + certificate "/etc/ssl/paul.buetow.org.fullchain.pem" + key "/etc/ssl/private/paul.buetow.org.key" + } + block return 302 "https://foo.zone/contact-information.html" +} +<% } %> + +# Legacy hosts +server "snonux.de" { + alias "www.snonux.de" + listen on * port 80 + block return 302 "https://foo.zone$REQUEST_URI" +} + +server "snonux.de" { + alias "www.snonux.de" + listen on * tls port 443 + tls { + certificate "/etc/ssl/snonux.de.fullchain.pem" + key "/etc/ssl/private/snonux.de.key" + } + block return 302 "https://foo.zone$REQUEST_URI" +} + +server "foo.surf" { + alias "www.foo.surf" + listen on * port 80 + block return 302 "https://foo.zone$REQUEST_URI" +} + +server "foo.surf" { + alias "www.foo.surf" + listen on * tls port 443 + tls { + certificate "/etc/ssl/foo.surf.fullchain.pem" + key "/etc/ssl/private/foo.surf.key" + } + block return 302 "https://foo.zone$REQUEST_URI" +} + +server "sidewalk.ninja" { + alias "www.sidewalk.ninja" + listen on * port 80 + block return 302 "https://irregular.ninja$REQUEST_URI" +} + +server "sidewalk.ninja" { + alias "www.sidewalk.ninja" + listen on * tls port 443 + tls { + certificate "/etc/ssl/sidewalk.ninja.fullchain.pem" + key "/etc/ssl/private/sidewalk.ninja.key" + } + block return 302 "https://irregular.ninja$REQUEST_URI" +} + +# Defaults +server "default" { + listen on * port 80 + block return 302 "https://foo.zone$REQUEST_URI" +} + +server "default" { + listen on * tls port 443 + tls { + certificate "/etc/ssl/foo.zone.fullchain.pem" + key "/etc/ssl/private/foo.zone.key" + } + block return 302 "https://foo.zone$REQUEST_URI" +} diff --git a/frontends/etc/relayd.conf.tpl b/frontends/etc/relayd.conf.tpl index d8553b2..4d702be 100644 --- a/frontends/etc/relayd.conf.tpl +++ b/frontends/etc/relayd.conf.tpl @@ -1,10 +1,15 @@ +<% + our $primary = $is_primary->($vio0_ip); + our $prefix = $primary ? '' : 'www.'; +%> + log connection tcp protocol "gemini" { - tls keypair buetow.org + tls keypair <%= $prefix %>foo.zone + tls keypair <%= $prefix %>buetow.org + tls keypair <%= $prefix %>snonux.land tls keypair snonux.de - tls keypair foo.zone - tls keypair irregular.ninja } relay "gemini4" { diff --git a/frontends/scripts/acme.sh.tpl b/frontends/scripts/acme.sh.tpl new file mode 100644 index 0000000..8039168 --- /dev/null +++ b/frontends/scripts/acme.sh.tpl @@ -0,0 +1,22 @@ +#!/bin/sh + +<% + our $primary = $is_primary->($vio0_ip); + our $prefix = $primary ? '' : 'www.'; +-%> + +<% for my $host (@$acme_hosts) { -%> +# Requesting and renewing certificate. +/usr/sbin/acme-client -v <%= $prefix.$host %> +# Create symlink, so that relayd also can read it. +crt_path=/etc/ssl/<%= $prefix.$host %> +if [ -e $crt_path.crt ]; then + rm $crt_path.crt +fi +ln -s $crt_path.fullchain.pem $crt_path.crt + +<% } -%> + +# Pick up the new certs. +/usr/sbin/rcctl reload httpd +/usr/sbin/rcctl reload relayd diff --git a/frontends/var/nsd/zones/master/buetow.org.zone.tpl b/frontends/var/nsd/zones/master/buetow.org.zone.tpl index 42bff2d..df35a53 100644 --- a/frontends/var/nsd/zones/master/buetow.org.zone.tpl +++ b/frontends/var/nsd/zones/master/buetow.org.zone.tpl @@ -27,6 +27,7 @@ twofish 86400 IN A 108.160.134.135 twofish 86400 IN AAAA 2401:c080:1000:45af:5400:3ff:fec6:ca1d git2 3600 IN CNAME twofish www 3600 IN CNAME twofish +www.paul 3600 IN CNAME twofish vulcan 86400 IN A 95.216.174.192 vulcan 86400 IN AAAA 2a01:4f9:c010:250e::1 diff --git a/frontends/var/nsd/zones/master/dtail.dev.zone.tpl b/frontends/var/nsd/zones/master/dtail.dev.zone.tpl index 0d67272..72e531b 100644 --- a/frontends/var/nsd/zones/master/dtail.dev.zone.tpl +++ b/frontends/var/nsd/zones/master/dtail.dev.zone.tpl @@ -12,5 +12,6 @@ $TTL 4h 86400 IN A 23.88.35.144 86400 IN AAAA 2a01:4f8:c17:20f1::4 * 86400 IN CNAME blowfish.buetow.org. +www 86400 IN CNAME twofish.buetow.org. github 86400 IN CNAME mimecast.github.io. -- cgit v1.2.3