Self-Hosting Guide for Beginners: Start Here

by David Park

Most people discover self-hosting the same way: they get a SaaS bill that makes them wince. $49/month for a simple form backend. $79/month for a basic analytics tool. $120/month for a database that's mostly idle. At some point you do the math and realize you're paying enterprise prices for indie hacker workloads.

This self-hosting guide for beginners won't sugarcoat the tradeoffs. You'll trade some convenience for control — and that's a good deal, if you go in with the right expectations. I've been running production services on cheap VPS boxes for nine years. Most of what I know came from breaking things at 2am. This guide is the shortcut I wish I'd had.

Here's what we'll cover: picking a server, locking it down, getting apps running with Docker, and keeping things alive without a dedicated ops team. Let's move.

Why Self-Host at All?

Let me be blunt: self-hosting isn't for everyone. If you're non-technical and just need a landing page, use Netlify and move on. But if you're an indie hacker running a SaaS, a side project with real users, or a small team that processes sensitive data — self-hosting starts making serious financial and operational sense.

The economics are stark. A $6/month Hetzner CAX11 (2 vCPU ARM, 4GB RAM, as of 2024) can comfortably run Plausible Analytics, a small Postgres database, and a Node.js API simultaneously. That same stack on managed services would run you $60–120/month easy. Over a year, that's $650–$1,400 back in your pocket.

Beyond cost, you own the data. No vendor lock-in. No surprise deprecations. No "we're sunsetting the free tier" emails.

Choosing Your First Server

Don't overthink this. For a first server, you want:

  • A reputable VPS provider with hourly billing so you can kill it if you mess up
  • At least 2GB RAM — 1GB sounds fine until you run Docker
  • A data center close to your users — latency matters more than you think
  • Linux — specifically Ubuntu 24.04 LTS or Debian 12

My current go-to is Hetzner. Their CAX21 (4 vCPU ARM, 8GB RAM) is €7.49/month and genuinely fast. DigitalOcean and Vultr are solid alternatives if you need US-based infrastructure. Avoid any provider that makes you call sales to get pricing — that's not for us.

Once you've picked a provider, spin up an Ubuntu 24.04 instance. Don't add anything fancy yet. Just get SSH access working.

Securing the Box Before Anything Else

I see beginners skip this step constantly. Don't. An unsecured VPS gets compromised within hours — there are bots scanning for default credentials around the clock.

Here's the minimal hardening checklist:

1. Create a non-root user

adduser deploy
usermod -aG sudo deploy

2. Copy your SSH key to the new user

rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy

3. Disable password auth and root login

Edit /etc/ssh/sshd_config:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

Then restart SSH: systemctl restart sshd

4. Set up a basic firewall with UFW

ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

That's it for now. You're not Fort Knox, but you're not a sitting duck either. If you want to go deeper on hardening, this guide on how to harden SSH on Linux covers the topic in detail.

Docker Is Your Best Friend Here

If there's one tool that makes self-hosting actually manageable for a one-person operation, it's Docker. Not Kubernetes — that's overkill until you're running dozens of services and have a team. Docker Compose is the sweet spot.

Install Docker on Ubuntu 24.04:

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker deploy

Log out and back in for the group change to take effect.

Now here's a real example. Say you want to run Plausible Analytics — a privacy-friendly Google Analytics alternative — on your own server. Their self-hosted setup uses Docker Compose. You clone their repo, edit a .env file with your domain and a few secrets, and run:

docker compose up -d

That's genuinely it. Plausible, Postgres, and Clickhouse all spin up and talk to each other. No manual database setup. No dependency hell.

This pattern repeats across almost every self-hosted app worth running: Gitea, Umami, Miniflux, Listmonk, n8n. They all ship with a docker-compose.yml. The ecosystem has matured a lot in the last three years.

Getting a Domain and HTTPS Working

A server without a domain and HTTPS is a half-finished project. Here's the fast path.

Domain: Buy from Cloudflare Registrar or Namecheap. Point an A record at your server's IP. Wait 5 minutes (or up to an hour if you're unlucky).

Reverse proxy: You need something to sit in front of your Docker containers and route traffic. I use Caddy — it handles HTTPS certificates automatically via Let's Encrypt, the config is human-readable, and it doesn't require a PhD to operate.

Install Caddy:

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install caddy

A basic Caddyfile to proxy your app:

analytics.yourdomain.com {
    reverse_proxy localhost:8000
}

Run systemctl reload caddy and Caddy will automatically get a TLS certificate. HTTPS, done. No Certbot juggling, no cron jobs renewing certificates at 3am.

Nginx with Certbot works too, but honestly Caddy's automatic HTTPS alone makes it worth learning first. I switched everything over about two years ago and haven't thought about certificate renewal since.

Keeping Things Running: Backups and Monitoring

This is where most beginners drop the ball. They get the app running, feel great, and then six months later a disk fills up or a Docker volume gets accidentally pruned. No backup. RIP.

Two tools. That's all you need to start.

Backups with restic

restic is a fast, encrypted backup tool that works with S3-compatible storage. Hetzner Object Storage is €0.023/GB/month — cheap enough that there's no excuse.

sudo apt install restic
export RESTIC_REPOSITORY="s3:https://your-bucket-endpoint/backups"
export RESTIC_PASSWORD="a-strong-passphrase"
export AWS_ACCESS_KEY_ID="your-key"
export AWS_SECRET_ACCESS_KEY="your-secret"

restic init
restic backup /home/deploy/apps

Set this up as a daily cron job:

crontab -e
# Add:
0 3 * * * /usr/bin/restic backup /home/deploy/apps --quiet

Test restoring before you need it. Seriously. An untested backup is just a false sense of security.

Monitoring with UptimeRobot

UptimeRobot's free tier monitors 50 URLs at 5-minute intervals and sends you an email when something goes down. That's enough for most indie hackers. Set it up, point it at your domain, done. You'll know within 5 minutes if your server is dead.

For more detailed server metrics — CPU, RAM, disk — Netdata has a free self-hosted agent that gives you a real-time dashboard with zero configuration. wget -O /tmp/netdata-kickstart.sh https://my-netdata.io/kickstart.sh && sh /tmp/netdata-kickstart.sh and you're up.

A Realistic Stack for Your First Self-Hosted Setup

Here's what I'd actually run on a fresh $7/month Hetzner box as a starting point:

Tool Purpose Monthly Cost (SaaS equivalent)
Plausible (self-hosted) Analytics $9–19/month saved
Listmonk Email newsletters $29–99/month saved
Umami Secondary analytics $9/month saved
Miniflux RSS reader $3/month saved
Gitea Private Git repos $4–21/month saved

All five run comfortably on 4GB RAM. Total self-hosted cost: your $7 server plus maybe $1/month in storage. Total SaaS equivalent: $54–$151/month. The math isn't subtle.

You don't have to run all five on day one. Pick one app that solves a real pain point — probably analytics or email — and get that working first. Build confidence before adding complexity.

Common Beginner Mistakes (And How to Avoid Them)

Running everything as root. Don't. Use the deploy user we set up earlier. If something gets compromised, blast radius matters.

No swap space. If your app spikes memory and you have no swap, the OOM killer starts shooting processes. Add 2GB swap on any server with less than 4GB RAM:

fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab

Ignoring logs. docker compose logs -f your-service-name is your first debugging tool. Check it before assuming the server is broken.

Upgrading in production without testing. Docker makes this easier — pull the new image, test with docker compose up on a staging copy, then switch. Don't just docker pull and restart on live without knowing what changed.

Not setting resource limits. One misbehaving container can starve everything else. Add mem_limit: 512m to your Docker Compose services as a sanity check.

The Self-Hosting Learning Curve Is Real, But Short

The first time you set up a server, it'll take you a weekend. The second time, maybe two hours. By the fifth time, you'll do it in under an hour from memory. The skills compound fast because the underlying concepts don't change much — Linux, Docker, DNS, reverse proxy. Learn those four things and you can run almost anything.

This self-hosting guide for beginners is deliberately opinionated. I'm not covering every possible tool or every edge case. I'm telling you what I'd do if I were starting over today, on a budget, trying to get something real running without a DevOps team.

There's more to learn — setting up automated Docker updates and managing multiple apps on one server are good next steps once you've got the basics down.

Your action for tomorrow: spin up a Hetzner CAX11 (€3.79/month), harden it with the steps above, and deploy one self-hosted app using Docker Compose. Pick Plausible or Umami if you want analytics, Listmonk if you need email. Get one thing working. That's it. The rest follows naturally.