Sertifikaatit palomuurin taakse
Jatkoa Raspberry Pi Homelabille.
Tämänhetkinen tilanne: Raspberry Pi, joka pyörittää muutamaa sovellusta (home assistant, pi-hole ja portainer) ja tarve ssl/tls sertifikaateille jokaisen sovelluksen http-yhteyden salaamiseksi. Sertifikaattien hakeminen, hallinnointi ja hyödyntäminen mieluiten mahdollisimman yksinkertaista. Tarkoitus myös pitää laite ja sovellukset eristettynä ulkoverkosta.
Tätä tarvetta varten päädyin käänteisproxy ratkaisuun. Ajaisin käänteisproxya kontissa ja sen kautta yhdistäisin muihin kontteihin, jotka ajavat itse sovelluksia. Tällöin vain proxylle tarvitsee hakea sertifikaatti ja usein se osaakin sen itse tehdä. Yksi käänteisproxy, joka osaa sertifikaatteja itse hallita on Caddy, ja sitä päätin tähä ratkaisuun käyttää. Tämän lisäksi käytän paikallista DNS palvelinta uuden paikallisen alidomainin määrittämiseksi omalle päädomainilleni (lassihirvonen.com). Julkinen päädomain mahdollistaa sen, että Caddy pystyy hakemaan sertifikaatin Let’s Encryptiltä (https://letsencrypt.org/), eikä minun tarvitse säätää itse kirjattujen sertifikaattien kanssa, joista myöskään selaimet eivät pidä.
Jotta ratkaisu saadaan toimimaan täytyy hieman ymmärtää kuinka sertifikaattien myöntäminen toimii. Sertifikaattien myöntämiseen liittyy keskeisesti ACME (Automatic Certificate Management Environment) -haaste. Haasteen avulla palvelinagentti (tässä tapauksessa Caddy) todistaa varmenteen myöntäjälle eli CA:lle (tässä tapauksessa Let’s Encrypt), että se omistaa domainin. Yleisin tapa tänä päivänä suorittaa ACME-haaste on käyttäen HTTP-01 -haastetta. HTTP-01 -haaste vaatii, että agentilla on julkinen IP-osoite, joka on määritetty domain-nimeen. CA ottaa palvelimeen yhteyttä antaakseen sille tunnisteen, joka palvelinagentin tulee sijoittaa ennaltamäärättyyn hakemistopolkuun todistaakseen omistavansa domainin. Tämä ei omassa tilanteessani ole mieluinen vaihtoehto, sillä se linkittää domain-nimeni kotini IP-osoitteeseen, sekä vaatisi Caddyn yhdistämisen suoraan internettiin. Päätin siis käyttää DNS-01 -haastetta, joka perustuu siihen, että palvelinagentti lisää tietyn arvon domainin TXT-tietueeseen. Tällöin tarvitse antaa omaa IP-oisoitetta tai avata portteja ulkoverkkoon, sillä Caddy aloittaa yhteyden Let’s Encryptin kanssa, joka ilmoittaa TXT-tietueeseen sijoitettavan arvon.
Testiympäristöön
Ennen live-ympäristöön viemistä testasin, että saan järjestelmät toimimaan testiympäristössä. Testiympäristönä käytin Caddya ja Apachea.
Seurasin sivun https://github.com/CaddyBuilds/caddy-cloudflare ohjeita, hieman niitä soveltaen omaan tarpeeseeni.
Loin uuden kansion, jonne voi tarpeelliset tiedostot lisätä.
mkdir -p ~/containers/caddy
Siirryin uuteen kansioon ja hain caddy-cloudflare docker imagen.
docker pull ghcr.io/caddybuilds/caddy-cloudflare:latest
Seuraavaksi loin docker-compose.yml tiedoston, joka määrittää kontit ja niiden asetukset.
micro docker-compose.yml
Kävin docker-compose.yml-tiedoston luonnin yhteydessä tekemässä itselleni Cloudflaren API avaimen, jonka lisäsin tiedostoon.
Loin Caddyfilen, jolla Caddy määritetään.
micro Caddyfile
Asetin Caddyn ohjaamaan osoitteseen home.lassihirvonen.com tulleet pyynnöt apacheen "httpd:80". Sen lisäksi määritin tässä Caddyn käyttämään DNS-01 haastetta Cloudflaren kautta.
Tein Apachelle index.html-tiedoston docker-compose.yml-tiedostossa määrittelemääni website-kansioon. Tämä auttaa myöhemmin tunnistamaan oman sivuni.
echo "moi" > ~/containers/caddy/website/index.html
Tämä jälkeen kävin luomassa paikallisen DNS-tietueen Pi-Holella osoitteelle home.lassihirvonen.com, joka osoittaa raspin IP-osoitteeseen.
Käynnistin docker-compose.yml-tiedostossa määrittelemäni kontit.
docker compose up -d
Optio -d
käynnistää kontit taustalla.
Siirryin selaimella osoitteeseen home.lassihirvonen.com.
Näin sivulla luomani index.html-tiedoston sisällön. Sivu myös aukesi ilman minkäänlaista varoitusta sertifikaateista ja salatulla yhteydellä.
Varmenteen tarkemmat tiedot:
Onnistuin siis luomaan testiympäristössä luotettavan sertifikaatin palomuurin taakse sisäverkkoon.
Rehelissyyden nimissä troubleshoottasin tätä ratkaisua noin 3-4 tuntia ja alunperin ajatus oli raportoida kaikki ongelmat, mutta luovutin tämän suhteen jo aika alkumetreillä, sillä se olisi vienyt aivan liikaa aikaa. Helposti eniten vaikeutta aiheuttivat docker-compose.yml ja Caddyfile tiedostot.
Live-ympäristöön
Teoriassa tämän pitäisi olla niinkin yksinkertaista, kuin liittää kontit caddyn verkkoon, päivittää Caddyfile ja luoda paikalliset DNS-tietueet.
Kävin luomassa DNS-tietueet etukäteen jokaiselle palvelulle.
Portainer
Aloitin portainerista, sillä se vaikutti helpoimmalta muuttaa.
Avasin portainerin ja siirryin portainer-kontin asetuksiin. Aivan sivun pohjalta liitin kontin verkkoon caddy_caddy.
Muokkasin seuraavaksi Caddyfileä, micro Caddyfile
ja lisäsin sinne alla olevan kuvan rivit.
Käynnistin caddyn uudelleen, docker compose restart caddy
.
Siirryin selaimella osoitteeseen portainer.lassihirvonen.com ja sivu aukesi käyttäen https-yhteyttä.
Pi-Hole
Avasin portainerin ja pi-hole -kontin asetukset, josta lisäsin sen caddy_caddy verkkoon. Jätin Pi-Holen myös alkuperäiseen bridge-adapteriin, sillä en kokenut, että DNS liikenteen olisi pakollista kulkea käänteisproxyn kautta.
Lisäsin alla olevat rivit Caddyfileen.
Käynnistin caddyn uudelleen docker compose restart caddy
. Siirryin selaimella sivulle pi-hole.lassihirvonen.com/admin ja sivu aukesi käyttäen https-yhteyttä.
Home Assistant
Tässä kohtaa kaava on jo tuttu. Viimeinen palvelu, eli Home Assistant huolestutti ehkä eniten, sillä se on helposti monimutkaisin, enkä haluaisi rikkoa sitä.
Avasin portainerin ja siirryin home assistant -kontin asetuksiin. Yritettyäni lisätä home assistantin verkkoon caddy_caddy, sain seuraavan ilmoituksen.
Päivittyy ajallaan...