Home Server - Part 1: The Inspiration

I was watching one of PewDiePie’s videos where he opens with saying “I’m not a tech guy”, then casually shows off his perfectly riced Arch Linux setup and a workflow that would make most developers jealous. Here I am, also running Arch (BTW), but with barely any rice and feeling pretty average about my setup.

His whole degoogling journey and approach to self-hosting got me thinking - if Felix can build his own privacy-focused infrastructure, maybe I should stop being lazy about it too.

The Hardware Sitting There, Judging Me

I had a gaming PC collecting dust in the corner:

  • AMD Ryzen 5 3600X (12 threads)
  • 32GB RAM
  • RX 5700 XT
  • 1TB NVMe + 3TB storage

The poor thing was just sitting there, occasionally running a game I’d never finish. Those 12 cores were basically wasted on my Steam backlog anxiety. Time to put that hardware to work doing something actually useful.

Looking at the specs, I realized I had serious horsepower just sitting there. Letting it idle felt wasteful when I could be running my own services instead of funneling everything through big tech.

Famous Last Words: “I’ll Just Try Nextcloud”

“I’ll just try Nextcloud,” I told myself. “Simple file sync, replace Google Drive, nothing fancy.”

Famous. Last. Words.

Within a week, I had convinced myself that if I’m already running one container, I might as well add a few more. Photo management would be nice. And hey, network-wide ad blocking sounds useful. Before I knew it, I was deep in YAML files and researching PostgreSQL tuning at 2 AM.

Here’s what the “simple Nextcloud setup” eventually became:

Core Services:

  • Nextcloud - Finally ditched Google Drive (mostly)
  • Immich - AI-powered photo management that actually runs on my hardware
  • Paperless-NGX - OCR document management with Swedish and English support
  • AdGuard Home - Network-wide ad blocking that makes browsing tolerable again

Infrastructure Services:

  • PostgreSQL with vector extensions because apparently I needed AI features
  • Redis for caching everything
  • Prometheus + Grafana for monitoring everything else
  • Cloudflare Tunnels for secure access without port forwarding nightmares
graph TB
    %% External Layer
    Internet["🌐 Internet"] --> Cloudflare["Cloudflare Tunnel"]

    %% Application Layer
    subgraph "Web Applications"
        Nextcloud["Nextcloud<br/>:8080"]
        Immich["Immich Server<br/>:2283"]
        AdGuard["AdGuard Home<br/>:3000"]
        Paperless["Paperless-ngx<br/>:8000"]
    end

    %% Infrastructure Layer
    subgraph "Database & Cache"
        PostgreSQL[("PostgreSQL<br/>Vector DB")]
        Redis[("Redis<br/>Cache")]
    end

    %% Monitoring Layer
    subgraph "Monitoring Stack"
        Grafana["Grafana<br/>:3001"]
        Prometheus["Prometheus<br/>:9090"]
        NodeExporter["Node Exporter"]
        RedisExporter["Redis Exporter"]
        PostgresExporter["Postgres Exporter"]
        BackupValidator["Backup Validator"]
    end

    %% Support Services
    subgraph "Background Services"
        NextcloudCron["Nextcloud Cron"]
        ImmichML["Immich ML"]
    end

    %% External connections
    Cloudflare --> Nextcloud
    Cloudflare --> Immich
    Cloudflare --> AdGuard
    Cloudflare --> Paperless
    Cloudflare --> Grafana

    %% Database connections
    Nextcloud --> PostgreSQL
    Nextcloud --> Redis
    Immich --> PostgreSQL
    Immich --> Redis
    Paperless --> PostgreSQL
    Paperless --> Redis

    %% Support service connections
    Nextcloud -.-> NextcloudCron
    Immich -.-> ImmichML

    %% Monitoring connections
    Prometheus --> Grafana
    NodeExporter --> Prometheus
    RedisExporter --> Prometheus
    PostgresExporter --> Prometheus
    BackupValidator --> Prometheus
Drag to pan • Scroll to zoom View only

Yeah. That escalated quickly.

The Container Rabbit Hole

Everything runs in containers, which turned out to be a good decision. What started as “just Docker Compose for Nextcloud” became managing 15+ services, each with their own quirks and requirements.

I found out the hard way that just because a service says it’s ā€œrunningā€ doesn’t mean it’s actually working. That’s why proper health checks are a must. There’s nothing like going to pull up your files and realizing the database has quietly died. Nobody likes surprises like that.

The photo management service alone became this beautiful, resource-hungry beast that needed careful tuning. AI-powered facial recognition, object detection, duplicate finding - all running on my hardware instead of some company’s servers scanning my personal photos.

The Moment It Clicked

Somewhere between setting up the fifth service and realizing I needed monitoring to keep track of it all, something clicked. This wasn’t just about replacing Google Drive anymore. I was building actual infrastructure. My own little data center in a closet.

The hardware that was collecting dust suddenly had purpose. Those 12 threads were crunching through machine learning models, the 32GB of RAM was caching everything for snappy performance, and that big storage drive was finally earning its keep.

More importantly, my data was becoming mine again. No ads, no tracking, no wondering what some algorithm was doing with my information behind the scenes.

But there was another huge benefit I hadn’t anticipated: I now had my own personal playground. Need to test a new application stack? Spin up containers and have a production-like environment running in minutes. Want to experiment with a database migration? Do it locally first without worrying about cloud costs or service limits.

This became invaluable for development work. Instead of relying on cloud services for every experiment - with their setup overhead, billing concerns, and rate limits - I could prototype, break things, and iterate freely on my own hardware. It’s like having a private AWS in your closet, but without the surprise bills or the need to authenticate with three different services just to spin up a test environment.

The psychological freedom of being able to experiment without external dependencies or costs is massive. “Let me just test this real quick” actually means real quick, not “let me set up another cloud account and figure out their networking first.”

Where This Is Going

This is where things started spiraling - and I realized I needed real infrastructure practices. What began as a weekend experiment was turning into something that needed proper management, monitoring, and backup strategies.

In the next post, I’ll dive into the Docker reality check: how my simple docker-compose.yml grew from 20 lines to managing 15+ services, complete with resource limits, health checks, and the kind of configuration that makes you feel like you’re running a real data center.

It gets interesting when you’re trying to prevent a machine learning service from eating all your RAM at 3 AM.

Next up: The Docker Spiral - From Simple Compose to 15+ Services

COMMENTS