I’ve always liked playing around with web stuff, and I’m also getting into self-hosting services strictly on my private network. I’ve got a bit of a funky setup that helps me do that. Let’s say I want to deploy a notes app onto a server I call tombombadil.
tombombadil.home.arpa -> 192.168.0.100.tombombadil via Docker, exposing the port it exposes as 42024. But who wants to remember all those ports? I’d rather have friendly names, especially in a browser.notes.home.arpa -> tombombadil.home.arpa.tombombadil to reverse proxy, e.g., notes.home.arpa:80 -> localhost:42024.This is all well and good, except that I can only access with HTTP, not HTTPS. That would prevent the hosted service from using fancy features like service workers, web bluetooth, or even accessing the clipboard. The solution would be to configure nginx to use an appropriate SSL certificate, and there are plenty of references for how to do that if you have a certificate. I’m documenting here how to get a good certificate.
There are three main options:
For my use case above, if only tombombadil runs a reverse proxy, then I only need one SSL certificate. However, Chrome will not trust an SSL certificate for *.home.arpa, so each service will need to be individually named in the certificate. (Could I use a wildcard for something like *.c.home.arpa? Not sure, but I want to avoid the typing…) In that case, the third option seems like the right one for me.
To generate an appropriate root certificate:
# Private key
openssl genrsa -out MyHomeCA.key 4096
# Root certificate
openssl req -x509 -new -nodes -key MyHomeCA.key -sha256 -days 3650 \
-out MyHomeCA.pem \
-subj "/CN=My Home Root CA/O=Home Lab/C=US"
MyHomeCA.pem is the file you’ll want to add to your trusted root certificates. Note that Windows doesn’t recognize the .pem extension, but if you select it anyway then Windows will accept it.
Here’s the script I used to generate a signed SSL cert; this is what you configure nginx to use.
CA_KEY="MyHomeCA.key"
CA_CERT="MyHomeCA.pem"
# "canonical" host listed first
HOSTS=(tombombadil adminer git links notes paste)
printf -v SAN_LIST 'DNS:%s.home.arpa,' "${HOSTS[@]}"
SAN_LIST=${SAN_LIST%,}
openssl x509 -req \
-in <( openssl req -new -nodes -newkey rsa:2048 \
-keyout homearpa.key \
-subj "/CN=${HOSTS[0]}.home.arpa"
) \
-CA "$CA_CERT" -CAkey "$CA_KEY" -CAcreateserial \
-out homearpa.crt -days 398 -sha256 \
-extfile <(cat <<EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = $SAN_LIST
EOF
)
If I weren’t using a CA, the openssl command could have been simpler:
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
-keyout homearpa.key -out homearpa.crt -subj "/CN=${HOSTS[0]}.home.arpa" \
-addext "subjectAltName=${names%,}"