Self-hosting means running services on hardware you own instead of relying on someone else’s servers. Your photos on your machine instead of Google’s. Your notes in your house instead of Notion’s cloud. Your email, your media, your files — all under your control.

If that sounds appealing (it should), this guide covers everything you need to get started from absolute zero.

Why Self-Host?

Let’s get the “why” out of the way, because it matters. Self-hosting isn’t just a nerdy hobby — it solves real problems.

Privacy

Every cloud service you use has access to your data. Google reads your emails to serve ads. Notion can see every note you write. Dropbox can access every file you sync. Your data is their product.

When you self-host, your data lives on hardware in your house. No company can scan it, sell it, or hand it to a government without your knowledge. You decide who has access.

Cost (Long-Term)

Cloud subscriptions add up fast:

  • Google One (2TB): $100/year
  • iCloud+ (2TB): $120/year
  • Dropbox Plus: $120/year
  • Notion Plus: $96/year
  • 1Password: $36/year
  • Spotify: $132/year (okay, you can’t really self-host this one yet)

That’s $600+/year for services you could run yourself. A $150 mini PC and some free software replaces most of this forever. The hardware pays for itself within a year.

Control

Cloud services change their terms constantly. Google kills products regularly (RIP Google Reader, Google Play Music, Google+, Inbox, Stadia…). Prices go up. Features disappear. Storage limits shrink.

When you self-host, you decide when to update, what features to keep, and how long your data sticks around. No rug pulls.

Learning

Self-hosting teaches you Linux, networking, Docker, databases, DNS, reverse proxies, backup strategies, and security. These are real skills that transfer directly to IT careers. Many professional sysadmins and DevOps engineers started with a homelab.

It’s Actually Fun

There’s genuine satisfaction in having a tech stack that’s yours. Building it, maintaining it, customizing it — it scratches the same itch as building your own PC or tinkering with a car. The self-hosting community is friendly and enthusiastic, and there’s always something new to try.

What Can You Self-Host?

Almost everything. Here’s a sampling:

Photos & Media

  • Immich — Google Photos replacement (our favorite)
  • Jellyfin — Netflix/Plex alternative (fully free)
  • Navidrome — Spotify alternative for your own music library
  • Audiobookshelf — audiobook and podcast server

Files & Productivity

  • Nextcloud — Google Drive/Docs replacement
  • Paperless-ngx — document scanner and organizer
  • Vaultwarden — Bitwarden password manager (self-hosted)
  • Vikunja — Todoist/Trello alternative

Network & Security

  • Pi-hole or AdGuard Home — network-wide ad blocking
  • WireGuard — VPN to access your home network remotely
  • Nginx Proxy Manager — reverse proxy with free SSL certificates

Home Automation

  • Home Assistant — smart home control center
  • Frigate — AI-powered NVR for security cameras

Development

  • Gitea/Forgejo — self-hosted GitHub
  • Portainer — Docker management UI
  • Uptime Kuma — website/service monitoring

The awesome-selfhosted GitHub repo lists thousands more. It’s a rabbit hole.

What Hardware Do You Need?

You have several paths. Pick the one that matches your budget and ambitions.

Option 1: A Raspberry Pi ($50-100)

The cheapest entry point. A Raspberry Pi 4 (4GB) or Pi 5 can run Pi-hole, WireGuard, Home Assistant, and a few lightweight Docker containers.

Pros: Cheap, silent, sips power (5W) Cons: Limited to 8GB RAM, ARM architecture means some software doesn’t run, slow storage (unless you boot from USB SSD)

Good for: dipping your toes in. Not great for anything serious.

Option 2: A Mini PC ($150-500)

This is what most people should buy. A mini PC like the Beelink Mini S12 Pro (~$150) or a Ryzen-based system gives you:

  • Real x86_64 CPU (all software just works)
  • 16-64GB RAM
  • NVMe storage
  • 6-20W idle power consumption
  • Silent operation

We have a full best mini PCs for homelab guide with specific recommendations for every budget.

Option 3: An Old Laptop or Desktop ($0)

Got an old laptop sitting in a drawer? Install Linux on it, plug in an Ethernet cable, and you have a server. The battery even acts as a built-in UPS.

Pros: Free Cons: Higher power draw, noisy, no ECC RAM, may be underpowered

Perfectly fine for learning and running a few services. Just don’t rely on it for critical data without backups.

Option 4: A Used Enterprise Server ($100-300)

Used Dell PowerEdge or HP ProLiant servers are dirt cheap on eBay. A Dell R720 with dual Xeons and 128GB RAM might cost $150.

Pros: Tons of RAM, ECC memory, IPMI remote management, redundant power supplies Cons: Loud (jet engine noise), power-hungry (100-300W idle), large, heavy, hot

Only choose this if you have a basement, garage, or dedicated room for it. The noise and power cost are significant.

My Recommendation

Start with a mini PC. Specifically, an Intel N100-based system if you’re on a budget, or a Ryzen 7 system if you want room to grow. The power efficiency means you can leave it running 24/7 without worrying about your electricity bill.

Choosing an Operating System

Proxmox VE is a free, open-source virtualization platform. Install it on bare metal and then create virtual machines and containers for everything else.

Why Proxmox is the right starting point:

  • Web-based management — no need to SSH in for basic tasks
  • Snapshots — take a snapshot before making changes, roll back if something breaks
  • Isolation — each service runs in its own VM or container, so a broken service doesn’t take everything down
  • Learning — you’ll learn virtualization, Linux, networking, and storage management all at once
  • Future-proof — as your homelab grows, Proxmox scales with you (clustering, HA, Ceph)

Ubuntu Server / Debian

If you just want to run Docker containers and don’t need VMs, a plain Ubuntu Server or Debian install works great. Less overhead, simpler to manage, but you lose the snapshot and VM capabilities of Proxmox.

TrueNAS Scale

If your primary goal is a NAS (Network Attached Storage) with some app-running capability, TrueNAS Scale combines ZFS storage management with a Docker-based app ecosystem. Not ideal as a general-purpose server, but excellent for storage-first setups.

Docker: The Foundation of Self-Hosting

Docker is the technology that makes self-hosting accessible. Without it, installing software meant compiling from source, managing dependencies, and dealing with conflicts. Docker packages everything into containers — isolated, reproducible, and easy to manage.

What Is Docker?

Think of Docker containers like shipping containers. Each one packages an application with everything it needs to run — the code, runtime, libraries, and configuration. Containers are isolated from each other and from the host system.

Key Concepts

Image: A template for creating containers. Like a recipe. Container: A running instance of an image. Like a dish made from the recipe. Volume: Persistent storage that survives container restarts. Where your data lives. Docker Compose: A YAML file that defines multiple containers as a single application. This is what you’ll use 90% of the time.

Installing Docker

On Ubuntu or Debian:

1
2
3
4
5
6
7
8
9
# Install Docker
curl -fsSL https://get.docker.com | sudo sh

# Let your user run Docker without sudo
sudo usermod -aG docker $USER

# Log out and back in, then verify
docker --version
docker compose version

Your First Docker Compose File

Let’s install something useful: Uptime Kuma, a monitoring tool that watches your services and alerts you when something goes down.

Create a directory and compose file:

1
2
mkdir -p ~/docker/uptime-kuma
cd ~/docker/uptime-kuma

Create docker-compose.yml:

1
2
3
4
5
6
7
8
9
services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    container_name: uptime-kuma
    volumes:
      - ./data:/app/data
    ports:
      - "3001:3001"
    restart: unless-stopped

Launch it:

1
docker compose up -d

Open http://YOUR_SERVER_IP:3001 in your browser. That’s it — you just self-hosted your first application.

Understanding the Compose File

Let’s break down what each line does:

1
2
3
4
5
6
7
8
9
services:                      # Define the services (containers) to run
  uptime-kuma:                 # Service name (you choose this)
    image: louislam/uptime-kuma:1  # Docker image to use (from Docker Hub)
    container_name: uptime-kuma    # Name for the running container
    volumes:
      - ./data:/app/data       # Map local ./data folder to /app/data inside container
    ports:
      - "3001:3001"            # Map host port 3001 to container port 3001
    restart: unless-stopped    # Auto-restart unless you manually stop it

Every self-hosted application follows this same pattern. Change the image, adjust the ports and volumes, and you’re running a new service. It really is that simple.

Essential Docker Commands

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# Start services defined in docker-compose.yml
docker compose up -d

# Stop services
docker compose down

# View running containers
docker ps

# View logs
docker compose logs -f

# Update to latest image version
docker compose pull
docker compose up -d

# Restart a service
docker compose restart

Your First Five Self-Hosted Apps

Here’s the starter pack I recommend for everyone. These five cover the most common needs and teach you the fundamentals.

1. Pi-hole — Ad Blocking for Your Whole Network

Pi-hole blocks ads and trackers at the DNS level. Every device on your network — phones, tablets, smart TVs, IoT devices — gets ad-free browsing without installing anything on each device.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "8080:80/tcp"
    environment:
      TZ: "Europe/Amsterdam"
      WEBPASSWORD: "your_password_here"
    volumes:
      - ./etc-pihole:/etc/pihole
      - ./etc-dnsmasq.d:/etc/dnsmasq.d
    restart: unless-stopped

After starting, set your router’s DNS server to your server’s IP address. Done — whole-network ad blocking.

2. Vaultwarden — Password Manager

Vaultwarden is a lightweight, self-hosted implementation of the Bitwarden password manager. It’s compatible with all official Bitwarden apps and browser extensions.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
services:
  vaultwarden:
    container_name: vaultwarden
    image: vaultwarden/server:latest
    volumes:
      - ./data:/data
    ports:
      - "8081:80"
    environment:
      SIGNUPS_ALLOWED: "true"    # Set to false after creating your account
    restart: unless-stopped

Create your account, install the Bitwarden browser extension, point it to your server, and import your passwords. Now your passwords live on your hardware.

Important: Set SIGNUPS_ALLOWED to false after creating your account, and put this behind HTTPS before using it seriously.

3. Immich — Photo Management

Your Google Photos replacement. We have a complete setup guide for this one, but here’s the quick version:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
services:
  immich-server:
    image: ghcr.io/immich-app/immich-server:release
    volumes:
      - /path/to/photos:/usr/src/app/upload
    env_file: .env
    ports:
      - "2283:2283"
    depends_on:
      - redis
      - database
    restart: always

  immich-machine-learning:
    image: ghcr.io/immich-app/immich-machine-learning:release
    volumes:
      - model-cache:/cache
    env_file: .env
    restart: always

  redis:
    image: redis:6.2-alpine
    restart: always

  database:
    image: tensorchord/pgvecto-rs:pg14-v0.2.0
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_DB: ${DB_DATABASE_NAME}
    volumes:
      - pgdata:/var/lib/postgresql/data
    restart: always

volumes:
  pgdata:
  model-cache:

4. Jellyfin — Media Streaming

Jellyfin is a free media server — think Netflix for your own movie and TV collection. It handles transcoding, subtitles, metadata, and has apps for every platform.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
services:
  jellyfin:
    container_name: jellyfin
    image: jellyfin/jellyfin:latest
    ports:
      - "8096:8096"
    volumes:
      - ./config:/config
      - ./cache:/cache
      - /path/to/movies:/media/movies
      - /path/to/tvshows:/media/tvshows
    environment:
      - TZ=Europe/Amsterdam
    restart: unless-stopped

5. Homepage — Your Dashboard

Homepage is a modern dashboard that shows all your services in one place. It integrates with dozens of self-hosted apps to show live statistics.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
services:
  homepage:
    image: ghcr.io/gethomepage/homepage:latest
    container_name: homepage
    ports:
      - "3000:3000"
    volumes:
      - ./config:/app/config
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: unless-stopped

After starting, edit the YAML config files in the ./config directory to add your services. Now you have a clean dashboard showing everything you’re running.

Networking Basics

Accessing Services Locally

Every service runs on a port. From devices on your home network, access them at http://YOUR_SERVER_IP:PORT. Bookmark these or use Homepage as your central dashboard.

Remote Access with WireGuard

Want to access your self-hosted services from outside your home? WireGuard is the simplest and most secure option.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
services:
  wireguard:
    image: lscr.io/linuxserver/wireguard:latest
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Amsterdam
      - SERVERURL=your.dynamic.dns.com
      - PEERS=phone,laptop
    volumes:
      - ./config:/config
      - /lib/modules:/lib/modules
    ports:
      - "51820:51820/udp"
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    restart: unless-stopped

Forward UDP port 51820 on your router to your server, install the WireGuard app on your phone, scan the QR code from ./config/peer_phone/peer_phone.png, and you have secure remote access to your entire home network.

Reverse Proxy with Nginx Proxy Manager

If you want to access services via nice domain names (like photos.yourdomain.com) with HTTPS, use Nginx Proxy Manager:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
services:
  nginx-proxy-manager:
    image: jc21/nginx-proxy-manager:latest
    container_name: nginx-proxy-manager
    ports:
      - "80:80"
      - "443:443"
      - "81:81"      # Admin panel
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    restart: unless-stopped

The web UI at port 81 makes it point-and-click to set up reverse proxies with free Let’s Encrypt SSL certificates.

Backups: The Non-Negotiable

If your data isn’t backed up, it doesn’t exist. This is the one thing beginners skip and later regret.

The 3-2-1 rule:

  • 3 copies of your data
  • 2 different storage media
  • 1 offsite copy

At minimum:

  1. Your server’s storage — the original copy
  2. An external USB drive — automated rsync backups
  3. An offsite location — a backup to a friend’s server, a cheap cloud storage (Backblaze B2 at $6/TB/month), or a second physical location

Tools like restic or borgbackup handle encrypted, deduplicated, incremental backups efficiently. Set them up early and automate them. Future you will be grateful.

Security Basics

A few things to do immediately:

  • Keep software updateddocker compose pull && docker compose up -d regularly
  • Use strong, unique passwords (you have Vaultwarden now — use it)
  • Don’t expose services directly to the internet without a reverse proxy and HTTPS
  • Use WireGuard for remote access instead of opening ports for each service
  • Enable automatic security updates on your server OS: sudo apt install unattended-upgrades
  • Set up a firewall: ufw allow ssh && ufw allow 80 && ufw allow 443 && ufw enable

Common Beginner Mistakes

  1. Not backing up — mentioned it twice because it’s that important
  2. Exposing everything to the internet — use a VPN, not port forwarding for every service
  3. Using root for everything — create a normal user account with sudo access
  4. Not using Docker volumes — storing data inside containers means losing it on updates
  5. Running on Wi-Fi — use Ethernet for your server. Wi-Fi is unreliable for always-on services.
  6. Overcomplicating the setup — start with 2-3 services and add more as you learn. Don’t try to self-host everything on day one.

Where to Go From Here

Once you have the basics running:

  1. Add more services gradually. The awesome-selfhosted list is your shopping catalog.
  2. Learn about reverse proxies and set up proper HTTPS for your services.
  3. Set up monitoring with Uptime Kuma and Grafana so you know when things break.
  4. Automate updates with Watchtower or manual pull-and-restart scripts.
  5. Join the community — r/selfhosted on Reddit, the self-hosted podcast, and various Discord servers are full of friendly people willing to help.

Self-hosting is a journey. You don’t need to have everything figured out on day one. Start small, learn as you go, and build something you’re proud of.

Your data, your rules. Welcome to self-hosting.