add homelab post
Some checks failed
Deploy Blog / deploy (push) Has been cancelled

This commit is contained in:
jawhng
2025-12-22 22:59:47 +00:00
parent 218a6b50dd
commit 6b9595be22

View File

@@ -0,0 +1,113 @@
---
title: "How It's Made - The Homelab (if I can call it that)"
date: "2025-12-22"
excerpt: "How I bought an office PC at a protest and turned it into t h e c l o u d over the course of a weekend."
---
## Set And Setting
I just turned 30. My beard's filling in. It's time to make a homelab. I looked online for something a step above a Raspberry Pi but in the same price range. I found it. I went to a protest. I bought a little computer off some middle-aged dude on the steps of the Sofia National Theatre. **The government resigned the next day.**
## The Machine
An honest-to-god HP ProDesk G2 600 with an Intel i5, 16GB of DDR4 RAM and a 500GB SSD. Running Ubuntu Server 24.04. Not impressive by any standards, but sufficient for what amounts to a personal "cloud infrastructure". The machine sits above my TV and behind my ISP's gateway, creating a networking topology that would later cause me to sneak out of bed in the middle of the night to shuffle LAN cables while trying not to wake up my girlfriend.
## The Vision
Self-host everything. Own your data. Control your infrastructure. Give a corporation the finger (not the one that pays me, it's the only good one). The typical motivations that drive people to spend weekends configuring servers instead of using managed services.
The requirements:
- Photo backup with mobile access and scripted regular backups to an external drive
- Git hosting for personal projects and showing off.
- A blog platform - you're **here**
- Infrastructure monitoring
- Global accessibility via HTTPS
- Automated deployments
## The Plumbing
I bought this domain for 2 years at the very likeable price of 5 dollars. I ran it through CloudFlare for the added security tools and better analytics on traffic. I'm behind 2 NATs on any end device of my home network. I have an ISP gateway and a router. I took turns placing my server behind each and now it's stuck right behind the gateway.
## The Services - containers all the way
Everything runs in Docker containers, each with its own compose file for isolation and maintainability. I really like the whale logo.
- **Immich:** Self-hosted photo backup with a mobile app. Deploying it went first and I only had one issue - port mappings changed between versions, requiring adjustments after some googling.
- **Gitea:** Git hosting with a web interface, issue tracking, and webhook support. Backed by PostgreSQL for reliability. SSH access configured on a non-standard port to avoid conflicts.
- **Nginx Proxy Manager:** Handles reverse proxying and SSL certificate management. The interface makes it trivial to add new services and request Let's Encrypt certificates. Initially attempted HTTP-01 challenges for SSL validation, but DNS propagation delays caused failures. Switched to DNS-01 challenges using Cloudflare's API, which proved more reliable.
- **Portainer:** Web-based Docker management. Useful for quick container inspection without SSH access. I might keep it, I might not.
- **Uptime Kuma:** Kind of unnecessary but I was having fun. Monitors all services and tracks uptime statistics. Provides notifications when services become unavailable.
- **DDNS Updater:** Synchronizes dynamic IP addresses with Cloudflare DNS records. This proved essential given that I don't have a static IP but ended up causing me a lot of issues when I forgot to make it update the correct place.
- **Tailscale:** Mesh VPN providing secure access to internal services without port forwarding. Also serves as a workaround for NAT loopback limitations.
- **This Blog:** Built with SvelteKit, served via nginx, deployed automatically via webhooks. The entire deployment pipeline runs on the same server.
## The Networking Problems
### Two NATs For the Price of One
The initial topology placed the server behind both the ISP gateway and a personal router, creating double NAT. Port forwarding rules existed on both devices. Services worked from the local network but were unreachable from external connections.
The solution involved eliminating the router layer entirely and connecting the server directly to the gateway.
### The Changing IP Mystery
Services remained accessible from the local network but failed from external networks. Cloudflare returned errors 520 and 522. Investigation revealed a discrepancy between the actual public IP and what DNS records pointed to.
The root cause: the DDNS updater was configured for Namecheap (where I bought the domain), but DNS had been migrated to Cloudflare for the free API access. When the public IP changed, the actual DNS records never updated. Reconfiguring the DDNS updater with Cloudflare credentials fixed it.
### NAT Loop-de-loop(back)
The gateway doesn't support NAT hairpinning, preventing access to services via their public domains from the internal network. For the time being I've resorted to editing the hosts files on local machines.
### Not killing my old external HDDs - only one I haven't solved
Automated daily backups run via systemd timer, mounting an external USB drive, backing up critical data, maintaining seven days of history, and unmounting the drive to allow spindown. The spindown doesn't work quite right so at the time of writing this I'm still working on it.
## AI-Assisted Development
This entire setup was built with assistance from Claude Code. Every configuration file, troubleshooting session, and architectural decision involved AI collaboration. The workflow combined AI-suggested solutions with human judgment on implementation.
The AI handled error interpretation, suggested fixes, and generated documentation. Human oversight provided context, made final decisions, and occasionally overruled suggestions (with mixed results). **This gives me a fully-working setup that is both working for me and teaching me about its working**
## Key Takeaways
**Network topology matters.** NATs (yes, multiple), forwarding ports, proxying DNS, etc. Crouching over LAN cables in your underwear on a freezing night. I have a lot to learn.
**Dynamic DNS isn't optional.** I'm sure ISPs change IP addresses just to mess with you. Automated DDNS definitely saved me a couple times.
**Comprehensive logging pays dividends.** Both systemd journal and file-based logs provide different perspectives on service behavior. Even better when you have AI read them for you.
**Container orchestration simplifies management.** Docker Compose provides clear service definitions, easy updates, and straightforward rollbacks. I know absolutely none of that but I'll learn in time.
**VPN access solves edge cases.** Tailscale addresses NAT loopback issues, provides secure remote access, and simplifies network architecture. Wireguard on its own eliminates the need of a 3rd party service so it's on the table.
## Let's Crunch The Numbers
I didn't do this to save money. I did it as a testament to my love for technology and upcycling redundant machines. But it **actually saves money**:
**Annual Costs:**
- Domain registration: ~€2.50/year
- Electricity: ~€5/month (€60/year)
- Hardware: €50 one-time (amortized over 5 years: €10/year)
- Total: ~€72.50/year
**Equivalent Services:**
- Google Photos: €10/month
- GitHub Pro: €4/month
- Static site hosting: €5-20/month
- Total: ~€228-408/year
The financial case is especially strong when you include the lessened time investment with AI assistance. The educational benefits will later appear on my bank balance.
## So What Now?
The homelab runs continuously. Services remain accessible anywhere. SSL certificates renew automatically. Backups execute daily. IP address changes propagate to DNS without intervention. Deployments trigger on git push for this blog (read the article on it to learn more).
It's cheaper than the sum of its parts. It's a lot more complicated than clicking "buy" and drag and dropping files around but to become a gandalf-level nerd you gotta walk a certain path and I feel I'm going in the right direction.
itaintmuchbutitshonestwork.jpg
Also the server is called lucien after the librarian of the dream world from The Sandman (graphic novel, not the slop show). If you really got this far, thanks <3.
---