For ages every service in the homelab had its own self-signed cert, which meant every browser visit started with a warning and every curl needed -k. It works, but it trains you to click through certificate warnings, which is a bad habit to build. So I put one nginx box in front of everything and let it terminate TLS.
The trick that makes this pleasant at home is the Let's Encrypt DNS-01 challenge rather than HTTP-01. None of these services are exposed to the internet, so there's nothing for the ACME server to reach over HTTP. With the DNS challenge, the client proves control of the domain by writing a TXT record, and my domain is parked on a provider with an API. So I can issue a wildcard-ish set of certs for *.home.example.com (well, per-host in 2016 terms, since wildcards via ACME aren't here yet) without opening a single port inbound.
server {
listen 443 ssl;
server_name grafana.home.example.com;
ssl_certificate /etc/letsencrypt/live/grafana.home/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/grafana.home/privkey.pem;
location / { proxy_pass http://10.0.0.21:3000; }
}
The renewal runs from cron on the proxy and reloads nginx on success. The result is that everything on the LAN is now https://thing.home.example.com with a green padlock, the internal CA wrangling is gone, and I no longer reflexively trust broken certs. Small change, disproportionate improvement to daily life.