commit e7d332a40477730be99b006f59413b3a18958d5b (patch)
parent 539d947ef2d8f39cee6f0743be7ba549353f3df8
Author: alex <alex@garbash.com>
Date: Thu, 28 Apr 2022 21:49:55 -0400
notes: Add note on a wildcard cert
Diffstat:
3 files changed, 97 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
@@ -23,7 +23,9 @@ BUILT = index.html \
notes/011-backups.html \
notes/011-backups.txt \
notes/012-mailing-lists.html \
- notes/012-mailing-lists.txt
+ notes/012-mailing-lists.txt \
+ notes/013-wildcard-cert.html \
+ notes/013-wildcard-cert.txt
build: $(BUILT)
diff --git a/index.md b/index.md
@@ -17,7 +17,6 @@ Game Plan
---------
### TODO:
-* Wildcard cert for internal services
* Start inviting people
* Automate account creation
* Homepage
@@ -40,3 +39,4 @@ Game Plan
* [Set up IRC bouncer](notes/010-irc-bouncer.html)
* [Basic backup solution](notes/011-backups.html)
* [Primitive Mailing Lists and Archive](notes/012-mailing-lists.html)
+* [Wildcard certificate for internal services](notes/013-wildcard-cert.html)
diff --git a/notes/013-wildcard-cert.md b/notes/013-wildcard-cert.md
@@ -0,0 +1,93 @@
+---
+title: 013-wildcard-cert
+---
+
+# 013-wildcard-cert
+
+Thur Apr 28, 2022
+
+I've been running two internal services for a while:
+
+* lists.garbash.com -- mailing list archive
+* irc.garbash.com -- [soju](https://soju.im) IRC client
+
+Because we're not using split DNS (hosting our own DNS server for
+clients on the VPN), these are kept internal only by having the public
+DNS have the internal IP addresses:
+
+ $ host irc.garbash.com
+ irc.garbash.com has address 10.6.6.1
+
+This works great, except it becomes harder to obtain a TLS certificate.
+My favorite way to get a TLS certificate on OpenBSD is acme-client(8),
+which is in base and works out of the box but does not support dns-01
+ACME challenges required for wildcard certs. As such, all sites requiring
+certs need to be publicly accessible for HTTP challenges.
+
+It would have been OK to serve over plain HTTP (in the sense that the
+services are served over a wireguard tunnel, so they're already encrypted),
+but browsers only allow desktop notifications for HTTPS sites, so to get
+notifications for `soju`, I needed a wildcard cert.
+
+The wildcard cert turned out to be not too hard. For a couple months I
+used [`uacme`](https://github.com/ndilieto/uacme) because it was in ports,
+but getting the client to update our DNS in Linode wasn't supported in
+the upstream project (as far I can tell). So for a couple times I actually
+ran the tool with manual DNS mode--updating the TXT records by hand myself.
+
+This clearly isn't sustainable (mostly because it requires remembering every
+couple months to redo it), so I moved to [`acme.sh`](https://github.com/acmesh-official/acme.sh),
+which, despite not being in ports, was super easy to install and use.
+
+To get the new certs, I created a new user:
+
+ # adduser
+ ... acmesh, nologin, daemon, etc ...
+
+Then I created a `certs` group so that all the services that need the certs
+can read the certificates:
+
+ # addgroup certs
+ # usermod -G _soju certs
+ # usermod -G acmesh certs
+
+I had to manually `chmod` some of the directories of `acme.sh` to allow
+group-writable, and `chown` those directories to `acmesh:certs`.
+
+Finally, installing the cert was as simple as:
+
+ $ export LINODE_V4_API_KEY=...
+ $ ./acme.sh --install -m alex@garbash.com # one time
+ $ ./acme.sh --issue --dns dns_linode_v4 --dnssleep 300 -d *.garbash.com
+
+This installed the certs to `/home/acmesh/.acme.sh`. `httpd(8)` needs the
+fullchain and private key:
+
+
+ server "lists.garbash.com" {
+ listen on * tls port 443
+ directory auto index
+ root "/htdocs/lists"
+ tls {
+ certificate "/home/acmesh/.acme.sh/*.garbash.com/fullchain.cer"
+ key "/home/acmesh/.acme.sh/*.garbash.com/*.garbash.com.key"
+ }
+ location "/.well-known/acme-challenge/*" {
+ root "/acme"
+ request strip 2
+ }
+ }
+
+
+The final step is to modify the crontab to restart the services
+when it runs successfully! Since this is running as the `acmesh`
+user, I needed to give it permission to run the `rcctl` command
+passwordless by adding the following to doas.conf:
+
+ permit nopass acmesh as root cmd /usr/sbin/rcctl args restart httpd
+
+Adding the following to the crontab will cause it to run on success:
+
+ -reloadcmd '/usr/sbin/rcctl restart httpd'
+
+Hopefully I won't need to think about this for a while!