How to Reduce Costs by Self-Hosting Common SaaS Applications

How to Reduce Costs by Self-Hosting Common SaaS Applications

We earn commissions when you shop through the links on this page, at no additional cost to you. Learn more.

I stopped paying $10–15 per month for scattered SaaS apps and got tired of managing login credentials across twelve different vendors. In the past two years, I've self-hosted everything from file storage to password management on a budget VPS, and I've cut my software costs from around $180 per year to roughly $50. The math is compelling, and the setup is simpler than you'd think.

Self-hosting common applications like Nextcloud, Vaultwarden, Gitea, and Jellyfin isn't just cheaper—it gives you genuine control, privacy, and the satisfaction of owning your own infrastructure. If you're already paying for cloud storage, password managers, git hosting, or media servers separately, self-hosting can pay for itself within weeks.

The Real Cost Comparison: SaaS vs. Self-Hosted

Let me lay out actual numbers. Here's what a typical knowledge worker, small team, or homelab enthusiast might spend annually on common SaaS apps:

Now here's my actual spend:

That's a 90% cost reduction. Over five years, you save $3,200. Over ten years, $6,300. Even accounting for the 8–10 hours of initial setup and ongoing maintenance (which is honestly enjoyable if you like this stuff), the ROI is staggering.

Which Applications Make Sense to Self-Host?

Not every SaaS is worth self-hosting. I prioritize applications where:

I don't self-host analytics (Plausible, Fathom are too good and cheap), email (too complex, too prone to blacklisting), or communication (Slack is worth the cost for a team). Self-hosting is a precision tool, not a religion.

Getting Started: The Infrastructure Foundation

You need three things: a server, a domain, and Docker Compose.

Pick Your VPS

I use RackNerd (around $40/year for 2 vCore, 4GB RAM, 100GB NVMe SSD). RackNerd frequently runs promotions at year-end and during sales events, and their support is reliable. Other solid options include Hetzner (€3.99/month in EU, ~€48/year), Contabo (€4/month, ~€48/year), and OVH (€5.99/month, €72/year).

For a single person running Nextcloud, Vaultwarden, and Gitea simultaneously, 2 vCore and 4GB RAM is plenty. If you add Jellyfin (which transcodes video), bump to 4 vCore / 8GB.

Domain Registration

Use Namecheap or Porkbun. I spend $12/year on a .com. You'll point this to your VPS via an A record. Later, you'll request free SSL certificates from Let's Encrypt.

Install Docker and Docker Compose

SSH into your VPS and run:

#!/bin/bash
# Update system
sudo apt update && sudo apt upgrade -y

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Add your user to the docker group
sudo usermod -aG docker $USER
newgrp docker

# Install Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# Verify
docker --version
docker-compose --version
Tip: After adding your user to the docker group, log out and back in so the group membership takes effect. Don't use sudo docker unless you have to—it causes permission headaches with mounted volumes.

Building Your Docker Compose Stack

Here's a minimal but production-ready Docker Compose file that runs Nextcloud, Vaultwarden, and Gitea behind Caddy (my preferred reverse proxy). I use this on my RackNerd VPS and it uses about 2.8GB of RAM under normal load.

version: '3.8'

services:
  caddy:
    image: caddy:latest
    container_name: caddy-reverse-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - internal
    restart: unless-stopped
    environment:
      - DOMAIN=yourdomain.com

  nextcloud:
    image: nextcloud:latest
    container_name: nextcloud
    depends_on:
      - nextcloud_db
    volumes:
      - nextcloud_data:/var/www/html
      - nextcloud_apps:/var/www/html/custom_apps
    environment:
      - MYSQL_HOST=nextcloud_db
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud_user
      - MYSQL_PASSWORD=securepassword123
      - NEXTCLOUD_TRUSTED_DOMAINS=yourdomain.com
      - OVERWRITEPROTOCOL=https
    networks:
      - internal
    restart: unless-stopped

  nextcloud_db:
    image: mariadb:11
    container_name: nextcloud_db
    volumes:
      - nextcloud_db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=rootpassword456
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud_user
      - MYSQL_PASSWORD=securepassword123
    networks:
      - internal
    restart: unless-stopped

  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    volumes:
      - vaultwarden_data:/data
    environment:
      - DOMAIN=https://vault.yourdomain.com
      - SIGNUPS_ALLOWED=false
      - INVITATIONS_ORG_INVITE_EXPIRATION_HOURS=24
      - LOG_LEVEL=info
    networks:
      - internal
    restart: unless-stopped

  gitea:
    image: gitea/gitea:latest
    container_name: gitea
    volumes:
      - gitea_data:/data
    environment:
      - ROOT_URL=https://git.yourdomain.com
      - SSH_DOMAIN=git.yourdomain.com
      - DB_TYPE=sqlite3
      - DISABLE_REGISTRATION=true
    ports:
      - "2222:22"
    networks:
      - internal
    restart: unless-stopped

volumes:
  caddy_data:
  caddy_config:
  nextcloud_data:
  nextcloud_apps:
  nextcloud_db:
  vaultwarden_data:
  gitea_data:

networks:
  internal:
    driver: bridge

Create a Caddyfile in the same directory:

{
  email [email protected]
}

yourdomain.com {
  reverse_proxy nextcloud:80
}

vault.yourdomain.com {
  reverse_proxy vaultwarden:80
}

git.yourdomain.com {
  reverse_proxy gitea:3000
}

Save both files, then run:

docker-compose up -d

Caddy will automatically request and renew Let's Encrypt certificates. You'll have three applications running with TLS in under 2 minutes.

Watch out: Never commit docker-compose.yml with real passwords to version control. Use .env files or a secrets management tool. Also, change the default MySQL/database passwords immediately—the ones above are examples only.

Ongoing Costs and Maintenance

Self-hosting isn't entirely free. Here's what to budget:

The time investment is the honest variable. You'll handle minor updates, occasional troubleshooting, and monitoring. If you're already managing a homelab or VPS, this is negligible. If you're not technical at all, self-hosting might frustrate you. But if you're reading CompactHost, you probably enjoy this work anyway.

Security Considerations

Self-hosting means you're responsible for security. At minimum:

We've written extensively on hardening VPS security and Docker best practices elsewhere on CompactHost—refer to those if you're new to self-hosting infrastructure.

The Hidden Benefits Beyond Cost

I've saved money, yes, but I've also gained:

That's harder to quantify on a spreadsheet, but it's real.

What's Next?

If you're convinced self-hosting is for you, start small. Pick one application—Nextcloud for file storage or Vaultwarden for passwords—and deploy it. Get comfortable with Docker Compose, then add more services. You don't have to migrate everything on day one.

And if you're still on the fence? Run the numbers for your own situation. If you're paying more than $100/year for SaaS, self-hosting will pay for itself before the year ends. After that, it's pure savings.

Discussion