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.
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)
| Service | Monthly 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
| Item | Cost |
|---|---|
| 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 -yRestart 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_hereThen just run:
docker-compose up -dThat’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:roDrop 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 -yLog 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.ymlPaste this:
version: '3'
services:
nextcloud:
image: nextcloud:latest
restart: unless-stopped
ports:
- 8080:80
volumes:
- ./data:/var/www/htmlSave it (Ctrl+X, Y, Enter), then run:
docker-compose up -dVisit 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 homelabNow 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/publickeyCreate /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/32Enable it:
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0Now 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 homelabNow 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/dataRun it:
docker-compose up -dVisit 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=adminCreate 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.comRun it:
docker-compose up -dNow 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 nextcloudSecurity 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 statusNow 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.localEdit 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.logStart it:
sudo systemctl enable fail2ban
sudo systemctl start fail2banCheck who’s banned:
sudo fail2ban-client status sshdHackers 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_configChange these lines:
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin noRestart SSH:
sudo systemctl restart sshdNow 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_passwordGenerate random passwords:
openssl rand -base64 32Then reference them in docker-compose.yml:
environment:
- MYSQL_PASSWORD=${NEXTCLOUD_DB_PASSWORD}Keep .env secure:
chmod 600 .envNever commit it to git! Add to .gitignore:
echo ".env" >> .gitignore5. 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:/configCreate 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 nextcloudUsually 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 -aContainer 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 nextcloudCan’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 statusDatabase 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 nextcloudForgot 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 /dataMy 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 dailyThis single file manages 15+ services. Start them all with:
docker-compose up -dUpdate them all with:
docker-compose pull
docker-compose up -dThat’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. 🚀