Het begon simpel: ik wilde niet meer betalen voor Google Foto's. Twee maanden later heb ik een klein serverrack thuis staan met daarin een mini-pc, een nas, een switch, een patchpaneel en een Raspberry Pi als back-upsysteem. Het homelab is mijn nieuwe hobby en het is een beetje duur, maar vooral heel erg leuk.
Het homelab begon met het grote aantal foto's en video's dat ik in Google had staan. Toen ik in 2023 een kind kreeg, begon ik er daar natuurlijk heel erg veel van te maken. Ik zette ze in Google Foto's: deels vanwege de gunstige prijs, maar vooral omdat dat het wel erg eenvoudig maakte om het album te delen met familie en vrienden. De ethische afwegingen daarvoor besprak ik al eens in onze podcast.
Tweeënhalf jaar later blijkt dat geen duurzame oplossing. Ik moest betalen: eerst 2,99 euro per maand en inmiddels 3,99 euro per maand omdat ik over de 100GB opslag heen ben. Er zijn andere overwegingen; ons artikel uit 2021 over de machteloosheid wanneer je Google- of Microsoft-account wordt afgesloten zat altijd ergens in mijn achterhoofd. Ik besloot daarom een nas te kopen, onder andere nadat een collega me wees op een opensourcealternatief voor Google Foto's.
Docker op de nas
Toen ik de nas kreeg, begon ik direct met allemaal zaken die niets te maken hadden met foto's of Google. Ik ontdekte Docker en zette er naast Immich ook maar meteen Pi-Hole, Home Assistant, Nextcloud en allerlei andere diensten op. Ik kwam er snel achter dat een nas, met een schamele 10GB geheugen en een niet al te krachtige processor, niet gemaakt is voor al die diensten. Toen het vakantiegeld binnenkwam, was het idee voor een homelab dan ook snel geboren.
Met mijn nieuwe beste vriend Claude ben ik een paar avonden goed aan het brainstormen geslagen over de beste apparatuur en software. Inmiddels draait het hele cluster grotendeels stabiel en nu is het vooral optimaliseren en documenteren geblazen.
Leren over racks en U's
Ik leerde eerst alles over racks, ofwel de behuizingen. Daarnaast verdiepte ik me in de U's, de standaardmaat voor de hoogte van een schapje in een rack. Ik leerde ook dat de Cisco-switch die ik al had, niet bedoeld is voor gebruik in dit soort racks. Ik ben voor een GeeekPi Rackmate T1 gegaan, een rack van 10" breed met ruimte voor 8U. Dat is genoeg voor een schapje voor de switch, de pc's en voor de nas onderin. Die dient nu namelijk als de opslag voor de server.
Patchpanelen aansluiten
Ik heb ook alles moeten leren over patchpanelen aansluiten. Een patchpaneel is waar aan de achterkant alle ethernetkabels binnenkomen, die je vervolgens vanaf de voorkant naar de switch leidt. Voor zover ik dat begrijp is dat voornamelijk vanwege de esthetiek: die korte kabeltjes aan de voorkant zien er veel cooler uit dan de kabelbrij aan de achterkant. En vooruit, het helpt ook dat acht kabels mappen veel eenvoudiger is.
Een patchpaneel aansluiten is een kunst op zich. Daarvoor heb je een zogeheten LSA- of punchdowntool nodig – ik had er nog nooit van gehoord. Vervolgens strip je de ethernetkabel en plaats je alle individuele kleurkabels in kleine gleufjes in het patchpaneel, die je dan weer met een LSA-tool vastzet. Het werkte snel toen ik eenmaal doorhad hoe dit moest, maar daarvoor zijn heel wat meters kabel gesneuveld.
Dat gebeurt ook als je acht ethernetkabels aan de voorkant aan beide kanten en dan nog eens acht kabels aan de achterkant moet voorzien van RJ45-connectors. Ik ben blij dat ik de tegenwoordigheid van geest had om connectors met doorsteek te kopen, want dat rotwerk gun je niemand ...
Een 24GB-Beelink als hart
Het hart van het homelab is een Beelink-mini-pc, de Beelink SER 8 om precies te zijn. Die heeft 24GB geheugen (ik had op 32GB gehoopt, maar Amazon had de specificaties verkeerd online gezet), een terabyte opslag en een AMD Ryzen 7 8845HS-processor. Alle diensten draaien op deze mini-pc. Die gebruikt het besturingssysteem Proxmox, waarmee je containers kunt maken. Zo kan ik iedere dienst in een aparte container zetten. Proxmox lijkt het beste OS te zijn voor dit soort homelabs, als ik subreddits als /r/Homelab en /r/selfhosted mag geloven.
Onder de streep ben ik bij dit soort keuzes ook vaak van mening dat wat je gewend bent, meer – of op z'n minst net zoveel – meespeelt dan feitelijke afwegingen. Ik heb op gevoel gekozen voor Proxmox en blijf daar nu bij. Net zoals ik nu nog steeds een Android-toestel heb omdat mijn eerste smartphone de HTC Hero was en ik nog steeds op een PlayStation game omdat ik die al sinds de PS1 heb. Althans, tot nu toe dan.
Voor wie Proxmox niet kent: het is serversoftware waarmee je containers of virtuele machines kunt maken die je dan lekker kunt compartimentaliseren. Daar houd ik van. Iedere container of VM krijgt een eigen IP-adres en ik kan precies toewijzen hoeveel geheugen en cpu-cores die container mag gebruiken. Toen ik de eerste paar containers had staan en ik wist hoe ik die moest opzetten, draaide de rest na een paar avondjes buffelen al snel.
Inmiddels draait mijn server:
| Dienst | Wat is het? |
| Nginx Proxy Manager | Maakt het mogelijk om websites te hosten, maar regelt ook reverse proxy's richting diensten, zodat ze van buiten het netwerk beschikbaar zijn. |
| Webserver, MariaDB, PHPmyadmin | Diensten die nodig zijn om websites met een backend, zoals blogs, te hosten. |
| Immich | Opensource foto-opslagdienst, een goed alternatief voor Google Foto's. Hiermee begon het hele project. |
| GitLab | GitHub-alternatief om zelf repo's te hosten van websites. Enorme overkill voor mijn singlepagesites, maar wel mooi. |
| Home Assistant | Smarthomeplatform |
| P1 Monitor | Tool van Ztatz om mijn slimme meter uit te lezen. Ik heb een draadloze P1-lezer moeten kopen en eigenlijk kan Home Assistant deze tool overnemen. Maar ik heb zes jaar historische P1 Monitor-data die ik wil kunnen blijven verzamelen. |
| Nextcloud | Om documenten te hosten en te maken. Mogelijk ook overkill, dus ook hiervoor zoek ik nog een alternatief. |
| Vaultwarden | Een opensourcealternatief voor Bitwarden dat je zelf kunt hosten. |
| Pi-Hole | Netwerkbrede adblocker. |
| Jellyfin | Om films en series te streamen. |
| WebDAV | Server om files zoals van Joplin te synchroniseren. |
| Grafana | Om dashboards weer te geven met statistieken over de server én bepaalde containers. |
| Grimmory | Een tooltje om e-boeken overzichtelijk te ordenen. Ik heb deze uit de Meuktracker gehaald als tip. |
| GoToSocial | Een eigen fediverse-installatie, zodat ik via social.tijshofmans.nl/@tijs kan posten en je dat met Mastodon kunt lezen. |
| Planka | Een to-doapp met kanbanweergave, vergelijkbaar met Trello. |
| Mealie | Een tooltje om recepten in op te slaan en je weekmenu te plannen. |
| Authentik | Extra authenticatielaag om op diensten in te loggen. |
| Tailscale | Vpn om van buiten het netwerk toegang te krijgen. |
Ik heb een paar diensten moeten migreren. Immich, GitLab en Nextcloud draaiden bijvoorbeeld al in Docker op mijn nas. Dat overzetten ging opvallend eenvoudig: bij geen enkele dienst had ik last van downtime.
Overkill
De meeste diensten zijn klein en vragen niet veel, behalve Immich, dat een gezichtsherkenningsmodule heeft die ramintensief is. GitLab is ook veel te zwaar. Ook dat is, net als Proxmox, net wat je gewend bent. Ik gebruik GitLab voor een ander hobbyproject met twee vrienden, maar op mijn eigen server is het enorme overkill, aangezien ik er alleen de broncode van tijshofmans.nl op host. Inmiddels staan daar overigens ook de Docker-configuratiebestanden op die de verschillende containers gebruiken. Ik onderzoek nog alternatieven, zoals Gitea of Forgejo.
Back-updiensten
Naast de Beelink staat ook een Raspberry Pi. Daarvan had ik er nog veel liggen. Tot voor kort had ik in mijn meterkast vijf Raspberry's hangen. Ze hadden allemaal een eigen functie, omdat ik Docker nog niet goed kende. Die Pi's heb ik langzaam maar zeker kunnen uitfaseren door diensten als Home Assistant naar containers te migreren.
Toch heb ik nog één Pi in het homelab zitten. Die dient voornamelijk als back-up voor essentiële systemen. Er draait een tweede Pi-Hole op als secundaire DNS-provider, maar ook een kopie van Home Assistant en Immich, voor het geval die eruit knallen vanaf de Beelink-server.
Nadenken over de 'paf'
Eigenlijk ben ik nog het meest bezig met de partner acceptance factor en specifieker de manier waarop ik de diensten beschikbaar maak voor mijn vrouw. Veel diensten zoals GitLab gebruikt ze niet, maar een receptendienst als Mealie is voor ons samen en Home Assistant moet ook gewoon werken zonder gedoe.
Een van de manieren om diensten extern beschikbaar te maken waar je het meest over hoort, is Tailscale of alternatieven zoals Twingate. Dat zijn een soort vpn-diensten waarmee je op afstand bij je lokale netwerk kunt komen. Dan kun je via Tailscale naar een lokaal IP-adres. Als je dat configureert als subnet, kun je zelfs bij alle diensten binnen dat subnet.
Ik wil niet van mijn vrouw vragen een vpn te installeren om de lampen te kunnen bedienen.
Daaraan zit alleen een grote 'maar'. Ik ga niet van mijn partner vragen om een vpn te installeren. Er is geen snellere en efficiëntere manier om weerstand tegen een thuisserver te creëren dan te eisen dat iemand eerst een app installeert, inlogt en die app vervolgens elke keer moet aanslingeren om een dienst te gebruiken.
Reverse proxy's
Daar zit een belangrijke afweging. De meeste diensten heb ik via een reverse proxy beschikbaar gemaakt. Nginx Proxy Manager regelt nu de proxy naar verschillende subdomeinen, zodat de diensten overal beschikbaar zijn. Iets minder veilig, maar voor mij een acceptabel risico.
Verder gebruik ik nu Authentik. Dat is een opensource authenticatiedienst die het mogelijk maakt om een extra authenticatielaag over bestaande apps heen te zetten. Dat is dan weer niet veiliger, want het vervangt bestaande logins niet. Het zet er alleen een laag bovenop. Wel is het, opnieuw voor mijn vrouw, makkelijker. Zij kan dan via single sign-on inloggen met ons gezamenlijke Google-account.
Documenteren en dashboards
De volgende stap is nu alles goed documenteren en beschikbaar maken. Dat laatste doe ik met een dashboard. Er zijn diensten die automatisch dashboards kunnen maken van alle diensten op de server, maar ik koos ervoor om een dashboardje te vibecoden. Dat is net zo snel, geeft me meer flexibiliteit en heeft bovendien dezelfde styling die ik ook voor mijn persoonlijke website gebruik.
Nu nog zorgen dat mijn vrouw straks begrijpt hoe alles werkt. Ik werk nog aan documentatie, maar heb een interessant idee. Ik wil een chatbot: een chatvenster in het dashboard met een custom instructie voor Claude, die alle documentatie straks gebruikt voor probleemoplossing of andere vragen. Maar dat is weer een heel eigen blog waard.
:strip_exif()/i/2008241156.jpeg?f=imagenormal)
/i/2008241162.png?f=imagenormal)
/i/2008240670.png?f=imagenormal)
/i/2008242310.png?f=imagemedium)
/i/2008242312.png?f=imagemedium)
/u/204872/crop65a1d5f52b87f.png?f=community)
/u/211309/crop61b0ff95cd8ef.png?f=community)
:strip_icc():strip_exif()/u/1597840/crop69ed231feaa91_cropped.jpg?f=community)
/u/62337/firewirelogo.png?f=community)
/u/1853590/crop686665a2ef9c2_cropped.png?f=community)
:strip_icc():strip_exif()/u/510323/crop5c49c55cb1a09_cropped.jpeg?f=community)
:strip_icc():strip_exif()/u/92809/crop577f58c1b8795.jpeg?f=community)
:strip_icc():strip_exif()/u/312772/crop63d3a8d18ee78_cropped.jpg?f=community)
:strip_icc():strip_exif()/u/184733/crop675f042292542.jpg?f=community)
:strip_icc():strip_exif()/u/140051/BSOD.jpg?f=community)
/u/298857/crop6471d9676d431.png?f=community)
/u/281364/crop6a1c5ee499300.png?f=community)
:strip_exif()/u/8077/jerney.gif?f=community)
:strip_icc():strip_exif()/u/142042/_igp0404-60.jpg?f=community)
:strip_icc():strip_exif()/u/157485/ava.jpg?f=community)
:strip_icc():strip_exif()/u/80211/crop625154a54bd09_cropped.jpg?f=community)
/u/94596/crop643fb12fd4e6d.png?f=community)
:strip_icc():strip_exif()/u/261029/crop641b08d1a7b6f_cropped.jpg?f=community)
/u/341812/crop6a4c5b6b221a9_cropped.png?f=community)
/u/34186/crop62e07d174532d_cropped.png?f=community)
:strip_icc():strip_exif()/u/448966/crop62a741840cd69_cropped.jpg?f=community)
:strip_exif()/u/435804/crop5f679f2864b1d_cropped.gif?f=community)
/u/115333/crop5f45784fcadad_cropped.png?f=community)
:strip_icc():strip_exif()/u/145751/check-in-minion-small2.jpg?f=community)
:strip_icc():strip_exif()/u/78991/Image2.jpg?f=community)
:strip_icc():strip_exif()/u/88719/crop624ccd84437db_cropped.jpg?f=community)
:strip_icc():strip_exif()/u/11631/tentacle.jpg?f=community)
/u/590416/crop5d8a8f12228ba_cropped.png?f=community)
:strip_exif()/u/44466/0115455001290429971.gif?f=community)
:strip_icc():strip_exif()/u/364924/crop651c5ddadde89_cropped.jpg?f=community)
/u/217510/crop660db19c1cf7b_cropped.png?f=community)
:strip_icc():strip_exif()/u/397705/crop608ff931a9e77_cropped.jpg?f=community)
:strip_icc():strip_exif()/u/320289/crop59885e9c557f6_cropped.jpeg?f=community)
:strip_icc():strip_exif()/u/219282/crop65bfaacd66e4c_cropped.jpg?f=community)
/u/1906/crop5dfd46928e003.png?f=community)
:strip_icc():strip_exif()/u/6764/cergorach.jpg?f=community)
/u/381607/have%2520a%2520nice%2520day%2520-%2520small.png?f=community)
:strip_icc():strip_exif()/u/476420/crop5623d9ad036cf_cropped.jpeg?f=community)
:strip_icc():strip_exif()/u/371214/crop5890a3fb73f78_cropped.jpeg?f=community)
:strip_icc():strip_exif()/u/473568/60x60.jpg?f=community)
:strip_icc():strip_exif()/u/46692/wiegel.jpg?f=community)
/u/243953/crop56f55a7bcf291.png?f=community)
:strip_icc():strip_exif()/u/420672/crop5cef95d7a6a08_cropped.jpeg?f=community)
/u/1982/crop5a048313062a4_cropped.png?f=community)
:strip_exif()/u/86638/crop66742fa02feea.webp?f=community)
/u/18479/crop6962247f917ee_cropped.png?f=community)
/u/456646/crop67dc8333af5d9_cropped.png?f=community)
:strip_icc():strip_exif()/u/856/crop58b5845e39c29_cropped.jpeg?f=community)
:strip_exif()/u/117880/911_gt3rs_60.gif?f=community)
:strip_icc():strip_exif()/u/1318532/crop5f6baa8470c0d_cropped.jpeg?f=community)
:strip_icc():strip_exif()/u/133312/poppetje.jpg?f=community)
/u/127261/crop5dcd39ec2f45d_cropped.png?f=community)
/u/270298/crop5db1fdd995966.png?f=community)
:strip_exif()/u/305786/crop583d93254a881_cropped.gif?f=community)
/u/257022/crop629738e7a7bae_cropped.png?f=community)
/u/9258/killbill.png?f=community)
:strip_icc():strip_exif()/u/60260/mr-t-obama-UI.jpg?f=community)
/u/175440/crop5b5f0d899a5e8_cropped.png?f=community)