Back to blog
5 min read

Why I Ditched Cloud Services and Built My Own Home Server

Tired of monthly subscriptions and privacy violations? I built my own home server to replace Google, Spotify, and 10+ other services. Here's why you should too.

HomelabPrivacySelf-HostedTutorial

The Problem: You’re Renting Everything

Think about it: you pay $10-20/month for Spotify, Netflix, Google Drive, iCloud, and a dozen other services. That’s easily $150+/month or $1,800/year.

What do you get in return?

  • Your photos and emails scanned for ads
  • Price hikes whenever they want
  • Services that shut down randomly (RIP Google Reader)
  • Your data sold to advertisers
  • No control over YOUR files

Real-world example: Remember when Google Photos was free unlimited storage? Then they changed it. Or when Netflix password sharing was fine? Until it wasn’t.

The Solution: Build Your Own Home Server

Imagine having your own personal cloud that:

  • Costs $400 once (not $1,800/year forever)
  • Stores ALL your data privately
  • Runs your own Spotify, Gmail, Google Drive
  • Never raises prices or changes rules
  • You own it completely

Think of it like this: Renting vs Owning a house, but for your digital life.

What I Built (And What It Replaced)

1. My Own Email Server

Replaces: Gmail ($6/month for custom domain)

Instead of Google reading your emails for ads, you have your own you@yourdomain.com that:

  • Nobody can scan
  • Never gets shut down
  • Has unlimited storage (your hard drive size)
  • Costs $0/month

2. My Own Music Server (Navidrome)

Replaces: Spotify Premium ($11/month)

Upload your music collection once. Stream it anywhere like Spotify, but:

  • No ads
  • No missing songs
  • Works offline automatically
  • Your playlists never disappear

3. My Own Cloud Storage (Nextcloud)

Replaces: Google Drive ($10/month for 2TB)

Think “Google Drive” but you own it:

  • Upload photos from your phone automatically
  • Share files with anyone
  • Edit documents online
  • Calendar, contacts, notes - all synced
  • 2TB costs you $50 (one-time hard drive cost) vs $120/year to Google

4. My Own Password Manager (Vaultwarden)

Replaces: 1Password ($3/month)

Store all your passwords securely without trusting a company.

5. My Own Media Server (Jellyfin)

Replaces: Netflix, Disney+ ($20/month combined)

Stream your movie/TV collection from anywhere. Like having your own Netflix.

6. My Own Smart Home Hub (Home Assistant)

Replaces: Google Home, Alexa

Control smart lights, thermostats, cameras without sending data to Google/Amazon.

The Numbers: Why This Makes Sense

Monthly Costs (Before Homelab)

ServiceMonthly Cost
Spotify$11
Netflix$15
Google Drive (2TB)$10
Gmail Custom Domain$6
1Password$3
iCloud Storage$3
TOTAL$48/month
Per Year$576/year

One-Time Homelab Cost

ItemCost
Mini PC (Used Dell OptiPlex)$200
2TB Hard Drive$50
Domain Name$12/year
TOTAL FIRST YEAR$262

Break-even point: About 5 months. After that, you save $500+ every single year.

Over 5 years:

  • Cloud services: $2,880
  • Homelab: $262 + ($12 × 4) = $310

You save $2,570 over 5 years. And you get MORE privacy and control.

”But Isn’t This Complicated?”

Honest answer: A little, at first. But think about it like building IKEA furniture.

The first time? Confusing and frustrating.
The second piece? Way easier.
After a few? You’re a pro.

Same with a homelab. Start with ONE service (I recommend Nextcloud for cloud storage). Get that working. Then add more when you’re ready.

How I Actually Set This Up

The Hardware (The Easy Part)

You don’t need much:

Option 1: Use an old laptop
Got an old laptop collecting dust? Install Linux on it. Done.

Option 2: Buy a used mini PC ($150-250)
Search eBay for “Dell OptiPlex 7040” or “HP EliteDesk 800 G3”. These are office computers companies throw away. They’re perfect.

What you need:

  • At least 8GB RAM
  • 250GB storage (or add a hard drive)
  • Modern-ish Intel CPU (i5 6th gen or newer)

The Software (The “Magic”)

I use Docker because it makes everything stupidly simple. Think of Docker like this:

Without Docker: Installing software is like building a house from scratch - you need to lay foundation, frame walls, run plumbing…

With Docker: It’s like buying a prefab tiny home that just drops onto your lot. Everything’s already built. You just plug it in.

Installing Docker (Literally 3 Commands)

On Ubuntu, setting up Docker is ridiculously easy:

# Update package list sudo apt update # Install Docker curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh # Add your user to docker group (so you don't need sudo) sudo usermod -aG docker $USER # Install Docker Compose sudo apt install docker-compose -y

Restart your terminal, and you’re ready to go. That’s it. No PhD required.

My First Steps (What I Wish I Knew)

Week 1: Install Ubuntu on my old laptop. Set up Docker. Felt like a hacker.

Week 2: Installed Nextcloud (cloud storage). Uploaded my phone photos. Mind blown when they appeared on my laptop.

Here’s the entire docker-compose file I used for Nextcloud. Create a file called docker-compose.yml:

version: '3' services: nextcloud: image: nextcloud:latest container_name: nextcloud restart: unless-stopped ports: - 8080:80 volumes: - ./nextcloud:/var/www/html - ./data:/var/www/html/data environment: - MYSQL_HOST=db - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud - MYSQL_PASSWORD=secure_password_here depends_on: - db db: image: mariadb:10.6 container_name: nextcloud-db restart: unless-stopped volumes: - ./db:/var/lib/mysql environment: - MYSQL_ROOT_PASSWORD=root_password_here - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud - MYSQL_PASSWORD=secure_password_here

Then just run:

docker-compose up -d

That’s it. Visit http://your-server-ip:8080 and boom - you have your own cloud storage running.

Week 3: Added Navidrome (music server). Uploaded my Spotify playlists. Deleted Spotify.

Navidrome was even easier. Another docker-compose.yml:

version: '3' services: navidrome: image: deluan/navidrome:latest container_name: navidrome restart: unless-stopped ports: - 4533:4533 environment: ND_SCANSCHEDULE: 1h ND_LOGLEVEL: info ND_BASEURL: "" volumes: - ./data:/data - ./music:/music:ro

Drop your MP3s in the music folder, run docker-compose up -d, and you’ve got your own Spotify at http://your-server-ip:4533.

Week 4: Set up remote access so I could use everything from my phone anywhere.

Month 2: Went crazy adding services - email, password manager, media server, smart home.

Now: Running 15+ services. Paying $1/month (domain name). Zero regrets.

The Real Benefits Nobody Talks About

1. You Learn Real Skills

You’ll learn Linux, networking, security, and Docker. These are actual job skills worth $80k+/year in tech.

2. It’s Actually Fun

There’s something satisfying about typing docker run and having your own Spotify appear. It’s like magic, but you made the magic happen.

3. You Stop Worrying About Shutdowns

Remember when Google Reader died? When Microsoft Groove shut down? When Yahoo Mail lost emails?

With your homelab, you decide what stays and what goes. No company can rug-pull you.

4. Privacy Peace of Mind

Your photos aren’t being scanned for ad targeting. Your emails aren’t being read. Your files aren’t being mined for data. It’s just… yours.

The “What If” Questions

“What if my server dies?”
You have backups (automated with Docker). Buy another $200 PC, restore from backup, you’re back in 30 minutes.

“What about electricity costs?”
A mini PC uses about 20 watts. That’s $2/month in electricity. Way less than $48/month in subscriptions.

“Can I access it from my phone when I’m away?”
Yes! Use a VPN (Wireguard) or Cloudflare Tunnel. Takes 10 minutes to set up.

“What if I break something?”
Docker makes it impossible to truly break things. Delete a container, create a new one. All your data stays safe.

“Isn’t internet upload speed too slow?”
For streaming music/photos, 5-10 Mbps upload is plenty. Most people have 10-20 Mbps.

Start Simple: Your First Weekend Project

Don’t try to replace everything at once. Start here:

Step 1: Get Hardware (Weekend 1)

  • Find an old laptop/PC, or buy a used mini PC on eBay ($150-250)
  • Install Ubuntu (there are YouTube tutorials - it’s easier than you think)

Step 2: Install Docker (Weekend 1)

  • Copy-paste 3 commands from Docker’s website
  • You’re done

Here are those 3 commands:

# 1. Download and run Docker install script curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh # 2. Add yourself to docker group sudo usermod -aG docker $USER # 3. Install Docker Compose sudo apt install docker-compose -y

Log out and back in. Done. You’re now a Docker expert.

Step 3: Run Your First Service (Weekend 2)

  • Try Nextcloud (cloud storage) or Navidrome (music)
  • Use a docker-compose guide (literally copy-paste)
  • Upload files. See the magic happen.

Create a folder and a docker-compose.yml file:

mkdir ~/nextcloud cd ~/nextcloud nano docker-compose.yml

Paste this:

version: '3' services: nextcloud: image: nextcloud:latest restart: unless-stopped ports: - 8080:80 volumes: - ./data:/var/www/html

Save it (Ctrl+X, Y, Enter), then run:

docker-compose up -d

Visit http://your-server-ip:8080. Congratulations, you just deployed your first self-hosted service!

Step 4: Make It Accessible (Weekend 3)

  • Set up Wireguard VPN or Cloudflare Tunnel
  • Access your server from your phone
  • Show it to friends. Enjoy their amazement.

Quick Cloudflare Tunnel setup:

# Install cloudflared wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb sudo dpkg -i cloudflared-linux-amd64.deb # Login cloudflared tunnel login # Create tunnel cloudflared tunnel create homelab # Route traffic cloudflared tunnel route dns homelab cloud.yourdomain.com # Run it cloudflared tunnel run homelab

Now cloud.yourdomain.com works from anywhere in the world. You can access your Nextcloud from your phone, laptop, friend’s house - anywhere!

Step 5: Expand (As Wanted)

  • Add one service per month
  • No rush. No pressure.
  • Enjoy the savings.

Tools That Make Everything Easy

Here are the actual tools I use (all free and open-source):

For Managing Services:

  • Portainer - Visual dashboard for Docker (like a control panel)
  • Homepage - Beautiful dashboard showing all your services

For Remote Access:

  • Wireguard - VPN to access everything securely
  • Cloudflare Tunnel - Access without opening ports (safer)

Setting Up Wireguard VPN

Wireguard is the easiest VPN to set up. Here’s how:

# Install Wireguard sudo apt install wireguard -y # Generate server keys wg genkey | sudo tee /etc/wireguard/privatekey | wg pubkey | sudo tee /etc/wireguard/publickey

Create /etc/wireguard/wg0.conf:

[Interface] Address = 10.0.0.1/24 ListenPort = 51820 PrivateKey = YOUR_PRIVATE_KEY_HERE PostUp = iptables -A FORWARD -i wg0 -j ACCEPT PostDown = iptables -D FORWARD -i wg0 -j ACCEPT [Peer] # Your phone or laptop PublicKey = CLIENT_PUBLIC_KEY_HERE AllowedIPs = 10.0.0.2/32

Enable it:

sudo systemctl enable wg-quick@wg0 sudo systemctl start wg-quick@wg0

Now you can access your homelab from anywhere securely!

Using Cloudflare Tunnel (Even Easier)

Don’t want to deal with VPNs? Cloudflare Tunnel is magical:

# Install cloudflared wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb sudo dpkg -i cloudflared-linux-amd64.deb # Login to Cloudflare cloudflared tunnel login # Create a tunnel cloudflared tunnel create homelab # Create config cat > ~/.cloudflared/config.yml << EOF tunnel: YOUR_TUNNEL_ID credentials-file: /home/$USER/.cloudflared/YOUR_TUNNEL_ID.json ingress: - hostname: nextcloud.yourdomain.com service: http://localhost:8080 - hostname: music.yourdomain.com service: http://localhost:4533 - service: http_status:404 EOF # Run it cloudflared tunnel run homelab

Now nextcloud.yourdomain.com works from anywhere - no ports, no VPN needed!

For Backups:

  • Duplicati - Automated backups to USB drive or cloud
  • Kopia - Even better backup tool (what I use now)

Automated Backups with Kopia

CRITICAL: Set up backups BEFORE you get attached to your data. Here’s my Kopia setup:

# Install Kopia curl -s https://kopia.io/signing-key | sudo apt-key add - echo "deb https://packages.kopia.io/apt/ stable main" | sudo tee /etc/apt/sources.list.d/kopia.list sudo apt update sudo apt install kopia -y # Create backup repository (to external USB drive) kopia repository create filesystem --path=/mnt/backup # Create backup policy kopia policy set --global \ --keep-latest 7 \ --keep-hourly 24 \ --keep-daily 7 \ --keep-weekly 4 \ --keep-monthly 6 \ --keep-annual 2 # Backup your Docker data kopia snapshot create /home/youruser/docker-data # Schedule automatic backups (add to crontab) echo "0 */6 * * * kopia snapshot create /home/youruser/docker-data" | crontab -

This backs up every 6 hours and keeps:

  • 7 latest snapshots
  • 24 hourly backups
  • 7 daily backups
  • 4 weekly backups
  • 6 monthly backups
  • 2 yearly backups

Sleep peacefully knowing your data is safe.

For Monitoring:

  • Uptime Kuma - Shows which services are running
  • Grafana - Pretty graphs of CPU, RAM, storage

Monitoring Everything with Uptime Kuma

Uptime Kuma is like a dashboard showing which services are alive. Super simple Docker setup:

version: '3' services: uptime-kuma: image: louislam/uptime-kuma:latest container_name: uptime-kuma restart: unless-stopped ports: - 3001:3001 volumes: - ./uptime-kuma:/app/data

Run it:

docker-compose up -d

Visit http://your-server-ip:3001, add all your services, and get notifications on your phone if anything goes down.

Pro Monitoring with Grafana + Prometheus

For the real deal, combine Grafana with Prometheus:

version: '3' services: prometheus: image: prom/prometheus:latest container_name: prometheus restart: unless-stopped ports: - 9090:9090 volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - ./prometheus-data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' grafana: image: grafana/grafana:latest container_name: grafana restart: unless-stopped ports: - 3000:3000 volumes: - ./grafana-data:/var/lib/grafana environment: - GF_SECURITY_ADMIN_PASSWORD=admin

Create prometheus.yml:

global: scrape_interval: 15s scrape_configs: - job_name: 'node' static_configs: - targets: ['localhost:9100']

Now you get beautiful graphs showing CPU, RAM, disk usage, network traffic - everything!

Common Mistakes (And How to Avoid Them)

Mistake #1: Trying to do everything at once

Fix: Start with ONE service. Master it. Then add more.

Mistake #2: Not doing backups

Fix: Set up automated backups on day 1. Use Kopia or Duplicati.

Mistake #3: Using WiFi instead of Ethernet

Fix: Plug your server into your router with a cable. WiFi is unreliable for servers.

Mistake #4: Exposing services directly to internet

Fix: Use a VPN (Wireguard) or Cloudflare Tunnel. Never open ports directly.

Mistake #5: Not updating regularly

Fix: Update Docker containers once a month. Takes 5 minutes with Watchtower (automates it).

Here’s how to set up Watchtower to auto-update everything:

version: '3' services: watchtower: image: containrrr/watchtower:latest container_name: watchtower restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - WATCHTOWER_CLEANUP=true # Remove old images - WATCHTOWER_SCHEDULE=0 0 4 * * * # Run at 4 AM daily - WATCHTOWER_NOTIFICATIONS=email - WATCHTOWER_NOTIFICATION_EMAIL_TO=you@email.com

Run it:

docker-compose up -d

Now your containers auto-update every night. You wake up to fresh, secure software. Zero effort.

Manual updates are also easy:

# Update all containers cd ~/docker docker-compose pull docker-compose up -d # Or update specific service docker-compose pull nextcloud docker-compose up -d nextcloud

Security Best Practices (Don’t Skip This!)

Your homelab is exposed to the internet. Here’s how to NOT get hacked:

1. Enable UFW Firewall

Ubuntu’s firewall is dead simple:

# Enable firewall sudo ufw enable # Allow SSH (so you don't lock yourself out!) sudo ufw allow 22/tcp # Allow Wireguard VPN sudo ufw allow 51820/udp # Block everything else by default sudo ufw default deny incoming sudo ufw default allow outgoing # Check status sudo ufw status

Now only SSH and your VPN can access the server. Everything else is blocked.

2. Set Up Fail2Ban (Auto-Ban Attackers)

Fail2Ban watches your logs and bans IPs trying to brute-force:

# Install sudo apt install fail2ban -y # Configure sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local sudo nano /etc/fail2ban/jail.local

Edit these settings:

[DEFAULT] bantime = 3600 # Ban for 1 hour findtime = 600 # 10 minute window maxretry = 5 # 5 failed attempts = ban [sshd] enabled = true port = 22 logpath = /var/log/auth.log

Start it:

sudo systemctl enable fail2ban sudo systemctl start fail2ban

Check who’s banned:

sudo fail2ban-client status sshd

Hackers trying to guess your password? Auto-banned. You’re welcome.

3. Use Strong Passwords (Or Better: SSH Keys)

Never use passwords for SSH. Use keys instead:

# On your laptop (not the server), generate a key ssh-keygen -t ed25519 -C "your_email@example.com" # Copy it to your server ssh-copy-id user@your-server-ip # Now disable password login on server sudo nano /etc/ssh/sshd_config

Change these lines:

PasswordAuthentication no PubkeyAuthentication yes PermitRootLogin no

Restart SSH:

sudo systemctl restart sshd

Now only YOU can access the server. No password = no brute force attacks possible.

4. Use Environment Variables for Secrets

NEVER put passwords in docker-compose.yml. Use a .env file:

Create .env:

# Database passwords NEXTCLOUD_DB_PASSWORD=super_secure_random_password_here NEXTCLOUD_DB_ROOT_PASSWORD=another_random_password IMMICH_DB_PASSWORD=yet_another_random_password PAPERLESS_DB_PASSWORD=you_get_the_idea # Service passwords PIHOLE_PASSWORD=strong_password

Generate random passwords:

openssl rand -base64 32

Then reference them in docker-compose.yml:

environment: - MYSQL_PASSWORD=${NEXTCLOUD_DB_PASSWORD}

Keep .env secure:

chmod 600 .env

Never commit it to git! Add to .gitignore:

echo ".env" >> .gitignore

5. Enable HTTPS Everywhere

Use Nginx Proxy Manager (super easy GUI) or Caddy (auto-HTTPS):

Caddy example - the easiest reverse proxy ever:

version: '3' services: caddy: image: caddy:latest container_name: caddy restart: unless-stopped ports: - 80:80 - 443:443 volumes: - ./Caddyfile:/etc/caddy/Caddyfile - ./caddy-data:/data - ./caddy-config:/config

Create Caddyfile:

nextcloud.yourdomain.com { reverse_proxy nextcloud:80 } music.yourdomain.com { reverse_proxy navidrome:4533 } jellyfin.yourdomain.com { reverse_proxy jellyfin:8096 }

That’s it. Caddy automatically gets SSL certificates from Let’s Encrypt. HTTPS everywhere, zero config.

Troubleshooting Common Issues

Things will break. Here’s how to fix them:

Container Won’t Start

Check the logs:

# View logs docker-compose logs nextcloud # Follow logs in real-time docker-compose logs -f nextcloud # Last 100 lines docker-compose logs --tail=100 nextcloud

Usually the error is obvious in the logs.

Out of Disk Space

Find what’s eating your disk:

# Check disk usage df -h # Find large directories du -sh /* | sort -hr | head -10 # Docker disk usage docker system df # Clean up old containers/images docker system prune -a

Container Using Too Much RAM/CPU

Check resource usage:

# Live resource monitor docker stats # See all running containers docker ps # Stop a container docker-compose stop nextcloud # Restart a container docker-compose restart nextcloud

Can’t Access from Phone

Check your network:

# Is the container running? docker ps | grep nextcloud # Is the port open? sudo netstat -tulpn | grep 8080 # Test from server itself curl http://localhost:8080 # Check firewall sudo ufw status

Database Corruption

Always have backups! Restore from backup:

# Stop the service docker-compose stop nextcloud # Restore from Kopia backup kopia snapshot restore latest-snapshot-id /path/to/restore # Start the service docker-compose start nextcloud

Forgot Admin Password

Most services store passwords in a database or config file:

# Nextcloud - reset admin password docker exec -it nextcloud php occ user:resetpassword admin # Vaultwarden - check the container logs for the admin token docker-compose logs vaultwarden | grep "admin_token"

Useful Docker Commands Cheat Sheet

# List all containers (running and stopped) docker ps -a # View container logs docker logs container_name # Execute command in container docker exec -it container_name bash # Restart all containers docker-compose restart # Stop all containers docker-compose down # Update and restart all containers docker-compose pull && docker-compose up -d # Remove stopped containers docker container prune # Remove unused images docker image prune -a # See container resource usage docker stats # Backup a container's volume docker run --rm -v container_data:/data -v $(pwd):/backup ubuntu tar czf /backup/backup.tar.gz /data

My Actual Setup Today

Hardware:

  • HP EliteDesk 800 G4 Mini ($220 on eBay)
  • 16GB RAM (upgraded from 8GB for $30)
  • 500GB SSD (came with it)
  • 4TB external HDD for media ($80)

Services Running (15 total):

  • Nextcloud (files, photos, calendar)
  • Vaultwarden (passwords)
  • Navidrome (music)
  • Jellyfin (movies/TV)
  • Paperless-ngx (document management)
  • Immich (photo backup - better than Google Photos)
  • Home Assistant (smart home)
  • Wireguard (VPN)
  • Uptime Kuma (monitoring)
  • Nginx Proxy Manager (routes everything)
  • Portainer (Docker management)
  • Pi-hole (network-wide ad blocking)
  • Mealie (recipe manager)
  • Audiobookshelf (audiobooks)
  • Tandoor (recipes)

Monthly cost: $1 (domain name)
Monthly savings vs cloud: $47
Yearly savings: $564

My Complete Docker Compose Stack

Here’s my actual production docker-compose.yml running all these services:

version: '3.8' services: # Reverse Proxy - Routes all traffic nginx-proxy-manager: image: jc21/nginx-proxy-manager:latest container_name: nginx-proxy-manager restart: unless-stopped ports: - 80:80 - 443:443 - 81:81 volumes: - ./nginx/data:/data - ./nginx/letsencrypt:/etc/letsencrypt # Nextcloud - My personal cloud nextcloud: image: nextcloud:latest container_name: nextcloud restart: unless-stopped volumes: - ./nextcloud:/var/www/html - ./nextcloud-data:/var/www/html/data environment: - MYSQL_HOST=nextcloud-db - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud - MYSQL_PASSWORD=${NEXTCLOUD_DB_PASSWORD} depends_on: - nextcloud-db nextcloud-db: image: mariadb:10.6 container_name: nextcloud-db restart: unless-stopped volumes: - ./nextcloud-db:/var/lib/mysql environment: - MYSQL_ROOT_PASSWORD=${NEXTCLOUD_DB_ROOT_PASSWORD} - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud - MYSQL_PASSWORD=${NEXTCLOUD_DB_PASSWORD} # Vaultwarden - Password manager vaultwarden: image: vaultwarden/server:latest container_name: vaultwarden restart: unless-stopped volumes: - ./vaultwarden:/data environment: - WEBSOCKET_ENABLED=true - SIGNUPS_ALLOWED=false # Navidrome - Music streaming navidrome: image: deluan/navidrome:latest container_name: navidrome restart: unless-stopped volumes: - ./navidrome:/data - /mnt/media/music:/music:ro environment: - ND_LOGLEVEL=info # Jellyfin - Media server jellyfin: image: jellyfin/jellyfin:latest container_name: jellyfin restart: unless-stopped volumes: - ./jellyfin:/config - /mnt/media/movies:/movies:ro - /mnt/media/tv:/tv:ro environment: - JELLYFIN_PublishedServerUrl=https://jellyfin.yourdomain.com # Immich - Photo backup (Google Photos replacement) immich: image: ghcr.io/immich-app/immich-server:release container_name: immich restart: unless-stopped volumes: - ./immich:/usr/src/app/upload environment: - DB_HOSTNAME=immich-db - DB_DATABASE_NAME=immich - DB_USERNAME=immich - DB_PASSWORD=${IMMICH_DB_PASSWORD} depends_on: - immich-db - immich-redis immich-db: image: postgres:14 container_name: immich-db restart: unless-stopped volumes: - ./immich-db:/var/lib/postgresql/data environment: - POSTGRES_USER=immich - POSTGRES_PASSWORD=${IMMICH_DB_PASSWORD} - POSTGRES_DB=immich immich-redis: image: redis:7 container_name: immich-redis restart: unless-stopped # Uptime Kuma - Monitoring uptime-kuma: image: louislam/uptime-kuma:latest container_name: uptime-kuma restart: unless-stopped volumes: - ./uptime-kuma:/app/data # Portainer - Docker management portainer: image: portainer/portainer-ce:latest container_name: portainer restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock - ./portainer:/data # Pi-hole - Network-wide ad blocking pihole: image: pihole/pihole:latest container_name: pihole restart: unless-stopped ports: - 53:53/tcp - 53:53/udp volumes: - ./pihole:/etc/pihole - ./dnsmasq:/etc/dnsmasq.d environment: - TZ=America/New_York - WEBPASSWORD=${PIHOLE_PASSWORD} # Home Assistant - Smart home homeassistant: image: homeassistant/home-assistant:latest container_name: homeassistant restart: unless-stopped network_mode: host volumes: - ./homeassistant:/config environment: - TZ=America/New_York # Paperless-ngx - Document management paperless: image: ghcr.io/paperless-ngx/paperless-ngx:latest container_name: paperless restart: unless-stopped volumes: - ./paperless/data:/usr/src/paperless/data - ./paperless/media:/usr/src/paperless/media - ./paperless/export:/usr/src/paperless/export - ./paperless/consume:/usr/src/paperless/consume environment: - PAPERLESS_REDIS=redis://paperless-redis:6379 - PAPERLESS_DBHOST=paperless-db depends_on: - paperless-db - paperless-redis paperless-db: image: postgres:14 container_name: paperless-db restart: unless-stopped volumes: - ./paperless-db:/var/lib/postgresql/data environment: - POSTGRES_DB=paperless - POSTGRES_USER=paperless - POSTGRES_PASSWORD=${PAPERLESS_DB_PASSWORD} paperless-redis: image: redis:7 container_name: paperless-redis restart: unless-stopped # Watchtower - Auto-update containers watchtower: image: containrrr/watchtower:latest container_name: watchtower restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - WATCHTOWER_CLEANUP=true - WATCHTOWER_SCHEDULE=0 0 4 * * * # 4 AM daily

This single file manages 15+ services. Start them all with:

docker-compose up -d

Update them all with:

docker-compose pull docker-compose up -d

That’s the power of Docker!

The Bottom Line

Cloud services want you to rent forever. Netflix, Spotify, Google - they’re all landlords. You’re paying rent, and at any moment they can:

  • Raise prices
  • Change the rules
  • Shut down
  • Scan your data
  • Kick you out

A homelab is buying your own house. Upfront cost, but then it’s YOURS:

  • No monthly bills
  • You make the rules
  • Can’t be shut down
  • Your data is private
  • You’re in complete control

The setup takes a weekend or two. The savings last forever. The skills are valuable. The privacy is priceless.

Is it for everyone? No. If you’re happy paying $50/month forever and don’t care about privacy, stick with cloud.

But if you:

  • Want to save $500+/year
  • Value your privacy
  • Like learning new things
  • Want control over your data
  • Enjoy tinkering

Then a homelab might be the best weekend project you’ve ever done.

Start small. One service. One weekend. See how it feels. You can always go back to the cloud.

But I bet you won’t. Once you taste digital independence, it’s hard to go back to renting. 🚀