SSL Certificaten in een homelab omgeving
Het gebeurt regelmatig dat ik in mijn homelab een webservice open en dat de Brave-browser aangeeft dat de verbinding onveilig is. De oorzaak is meestal eenvoudig: de dienst is alleen bereikbaar via HTTP in plaats van HTTPS. In dat geval kan de browser niet verifiëren of de website daadwerkelijk is wie hij zegt te zijn, en wordt er geen versleutelde verbinding opgezet. De inhoud is daardoor vatbaar voor afluisteren of manipulatie.
Het nut van versleuteling binnen een homelab valt te bediscussiëren. Het netwerk is immers afgeschermd en wordt alleen door vertrouwde apparaten gebruikt. Toch zijn er voor mij twee goede redenen om ook intern HTTPS te gebruiken. Ten eerste wil ik af van de storende waarschuwingen in de adresbalk. Ten tweede geeft het geheel een professionelere uitstraling, ook al ben ik voorlopig de enige gebruiker.
Van betaalde certificaten naar Let’s Encrypt
Tot enkele jaren geleden waren SSL-certificaten doorgaans betaald. In 2015, mede naar aanleiding van de Snowden-onthullingen, ontstond binnen de techwereld een sterke drang om encryptie standaard en laagdrempelig te maken. Vanuit die gedachte werd Let’s Encrypt opgericht: een Certificate Authority (CA) die gratis TLS-certificaten uitgeeft en het aanvraagproces sterk automatiseert.
Wat doet HTTPS precies?
Wanneer een gebruiker een HTTPS-website bezoekt, stuurt de server een certificaat mee. Dat certificaat is uitgegeven door een vertrouwde Certificate Authority en bewijst dat de server daadwerkelijk hoort bij het domein dat in de adresbalk staat. Daarnaast zorgt HTTPS ervoor dat het verkeer tussen client en server versleuteld is, zodat derden niet kunnen meekijken of ingrijpen.
Services in mijn homelab
Binnen mijn homelab draaien verschillende diensten die ik graag van een geldig certificaat wil voorzien, waaronder:
- Nextcloud
- Vaultwarden
- Portainer
- TrueNAS
- Proxmox
Niet al deze diensten mogen publiek toegankelijk zijn. Managementinterfaces zoals die van TrueNAS en Proxmox wil ik bewust alleen intern beschikbaar houden. Diensten als Vaultwarden (wachtwoordmanager) en Nextcloud (private cloud) moeten daarentegen wel via het internet bereikbaar zijn.
DNS, NAT en een reverse proxy
Voor de publiek toegankelijke diensten heb ik subdomeinen aangemaakt bij mijn DNS-provider Strato. Zo verwijst bijvoorbeeld nextcloud.lionel.wtf naar mijn publieke IP-adres. Inkomend verkeer komt daar binnen, passeert NAT op de router en wordt vervolgens doorgestuurd naar een reverse proxy.
Die reverse proxy fungeert als tussenlaag en routeert het verkeer op basis van het subdomein naar een intern IP-adres en poort. Hierdoor kan ik meerdere webservices hosten zonder dat ze allemaal rechtstreeks op poort 80 of 443 hoeven te luisteren.
Als reverse proxy gebruik ik Nginx, beheerd via Nginx Proxy Manager (NPM), een gebruiksvriendelijke wrapper met een webinterface. Dit draait in een LXC-container met één vCPU en 512 MiB RAM. Geen krachtpatser, maar voor deze taak meer dan voldoende.

Certificaten aanvragen: HTTP-01 en DNS-01
Binnen Nginx Proxy Manager is het mogelijk om direct SSL-certificaten aan te vragen via Let’s Encrypt. Dit kan op twee manieren: via een HTTP-challenge of een DNS-challenge.
Het principe is vergelijkbaar met wat je soms ziet op online marktplaatsen: de koper vraagt de verkoper om een foto te maken van het product met een specifieke tekst erbij. Daarmee bewijst de verkoper dat hij daadwerkelijk controle heeft over het product. Bij Let’s Encrypt werkt het net zo: je moet aantonen dat je controle hebt over een domein.
Voor publiek toegankelijke subdomeinen is de HTTP-challenge de meest eenvoudige optie. Let’s Encrypt controleert of er via HTTP een specifiek bestand bereikbaar is op het domein. Dat werkt alleen als de service tijdelijk vanaf het internet bereikbaar is.
Lastiger wordt het bij diensten zoals de Proxmox-webinterface, die ik om veiligheidsredenen niet publiek wil blootstellen. Hiervoor bestaat de DNS-challenge. Daarbij wordt geen webserver gecontroleerd, maar vraagt Let’s Encrypt of er een specifieke TXT-record aanwezig is in de DNS-zone van het domein.
Het aanpassen van die TXT-record gebeurt bij de DNS-provider. Omdat dit losstaat van het IP-adres waar het subdomein naartoe wijst, is het op deze manier toch mogelijk om ook volledig interne services van een geldig SSL-certificaat te voorzien, zonder ze ooit aan het internet bloot te stellen.