Self-Host Apps on a VPS: Architecture, RAM Usage, and What to Deploy First

12 min read·Matthieu·PrivacyDocker ComposeVPSSelf-hostingDocker|

A decision guide for self-hosting apps on a VPS with Docker. Includes real memory footprint data for 10+ apps, stacking combos for 4GB and 8GB plans, and a framework for choosing your first app.

You have a VPS. Maybe you just got it, or maybe you have been running a few things and want to do more. Either way, the question is the same: what should I run on it, and will it fit?

This guide covers the architecture of a self-hosted app stack, gives real memory footprint numbers measured on a 4vCPU/8GB VPS, and provides a decision matrix to help you pick your first (or next) app.

Prerequisites: This guide assumes you already have Docker and a reverse proxy running. If not, start with Docker in Production on a VPS: What Breaks and How to Fix It to set up Docker, Docker Compose, and Caddy or Traefik on Debian 12 or Ubuntu 24.04. For Docker Compose fundamentals, see Docker Compose for Multi-Service VPS Deployments.

Why self-host on a VPS instead of a homelab?

A VPS gives you always-on hosting with a public IPv4 address, no CGNAT, no electricity bill, and no hardware to maintain. Provider-managed snapshots handle disaster recovery. A 4vCPU/8GB VPS runs 5-8 Docker apps comfortably for a few euros per month. Your home internet goes down; your VPS does not.

Factor VPS Homelab
Public IP Included, static Often behind CGNAT. Requires tunnel workarounds.
Uptime 99.9%+ SLA, redundant power Depends on your ISP and power grid
Bandwidth Symmetric, typically 1 Gbps+ Asymmetric. Upload is the bottleneck.
Hardware maintenance Provider's problem Your problem. Disk failures, fan noise, heat.
Electricity Included in the price 20-60 EUR/year for a small server running 24/7
Snapshots/backups One click, provider-managed You build and test the backup pipeline yourself
Initial cost From ~4 EUR/mo 200-500+ EUR for a Mini PC or NAS
Physical access None. SSH only. Full access. Good for USB devices, ZFS arrays.

A homelab makes sense if you need local storage (ZFS arrays, NAS), USB hardware (Zigbee sticks, SDR dongles), or you want to learn bare-metal administration. For everything else, a VPS is simpler and cheaper to start with.

Most residential ISPs now use Carrier-Grade NAT (CGNAT), meaning you share a public IP with dozens of other customers. You cannot port-forward. Your self-hosted apps are invisible to the internet. Workarounds exist (Cloudflare Tunnels, WireGuard relays), but they add complexity. A VPS sidesteps the problem: you get a dedicated public IPv4, you control DNS, and inbound traffic just works.

If you want both, use a VPS as your public edge and a WireGuard tunnel back to your homelab for private services.

What does a self-hosted app stack look like?

A self-hosted stack on a VPS follows a layered architecture: a reverse proxy sits in front, routing HTTPS traffic to application containers. Each app connects to its own database (or uses embedded SQLite). A backup layer snapshots data on a schedule.

Internet
  │
  ▼
┌─────────────────────────────┐
│  Reverse Proxy (Caddy)      │  Port 443 ← only public port
│  TLS termination + routing  │
└──────┬──────┬──────┬────────┘
       │      │      │
       ▼      ▼      ▼
    ┌─────┐ ┌─────┐ ┌─────┐
    │App 1│ │App 2│ │App 3│    Docker containers
    └──┬──┘ └──┬──┘ └──┬──┘
       │      │      │
       ▼      ▼      ▼
    ┌─────┐ ┌─────┐ ┌─────┐
    │ DB  │ │ DB  │ │SQLite│   PostgreSQL, Redis, or embedded
    └─────┘ └─────┘ └─────┘
              │
              ▼
    ┌─────────────────┐
    │  Backup Layer   │        Restic, borgmatic, or provider snapshots
    │  (scheduled)    │
    └─────────────────┘

Key decisions:

  • Reverse proxy: Caddy auto-provisions TLS certificates with zero config. Traefik integrates with Docker labels for auto-discovery. Both work. Caddy is simpler for beginners.
  • Database: Many lightweight apps (Vaultwarden, Uptime Kuma, Beszel) use embedded SQLite. Heavier apps (Immich, Plausible, Gitea) need PostgreSQL.
  • Backup: Provider snapshots cover the full disk. For app-level backups, use Restic or borgmatic to an offsite target (S3-compatible storage or a second VPS).
  • Networking: All app containers sit on an internal Docker network. Only the reverse proxy exposes ports 80 and 443. Apps never bind to public interfaces directly.

This architecture is covered in detail at Docker in Production on a VPS: What Breaks and How to Fix It.

How much RAM do self-hosted apps actually use?

Not as much as you think. Most popular self-hosted apps idle under 200MB. The exceptions are apps with machine learning features (Immich) or embedded analytics engines (Plausible with ClickHouse).

The numbers below are idle/light-use RSS memory from docker stats, measured on a Virtua Cloud 4vCPU/8GB VPS running Debian 12. Peak values represent typical spikes during active use (photo upload, document OCR, workflow execution).

App What it replaces Idle RAM Peak RAM Storage/month Database
Vaultwarden Bitwarden, 1Password ~25 MB ~50 MB Minimal SQLite
Uptime Kuma UptimeRobot, Pingdom ~100 MB ~170 MB Minimal SQLite
Beszel Datadog (basic) ~50 MB ~80 MB Minimal Embedded
Gitea GitHub (private repos) ~150 MB ~300 MB ~50 MB/repo PostgreSQL or SQLite
n8n Zapier, Make ~100 MB ~500 MB+ Varies by workflows PostgreSQL
Paperless-ngx Filing cabinet ~300 MB ~1 GB ~5 MB/document PostgreSQL + Redis
Nextcloud Google Drive, Dropbox ~250 MB ~512 MB Varies by files PostgreSQL + Redis
Coolify Vercel, Railway ~500 MB ~1.2 GB Varies by deploys PostgreSQL (bundled)
Plausible Google Analytics ~400 MB ~1.5 GB ~100 MB/1M pageviews PostgreSQL + ClickHouse
Immich Google Photos ~800 MB ~2.5 GB ~3 GB/1000 photos PostgreSQL + Redis

A few notes on these numbers:

  • Immich with machine learning (face/object detection) enabled needs 4-6 GB total. During a large photo import, expect 3-4 GB. You can disable ML to drop memory to ~400 MB, but you lose smart search and face recognition.
  • Plausible RAM depends on traffic volume. ClickHouse loves memory. For a site with under 100k pageviews/month, the numbers above hold. High-traffic sites need more.
  • n8n at idle is light, but complex workflows with large JSON payloads or AI integrations spike hard. AI agent workflows can consume 200 MB+ per execution.
  • Paperless-ngx spikes during OCR. Set PAPERLESS_WEBSERVER_WORKERS=1 in Docker to save ~150 MB if you are the only user.

Which app should I self-host first on my VPS?

Start with Vaultwarden. It uses 25 MB of RAM, deploys in under 10 minutes, replaces a paid password manager you use every day, and forces you to set up TLS properly. That TLS setup (reverse proxy + DNS + certificates) is the foundation every other self-hosted app needs. One app, three wins: privacy, cost savings, and infrastructure you will reuse.

App Privacy impact Setup complexity SaaS it replaces Min RAM
Vaultwarden Very high (passwords) Low (10 min) Bitwarden/1Password 128 MB
Immich High (personal photos) Medium (30 min) Google Photos 2 GB (4 GB with ML)
Paperless-ngx High (documents, IDs) Medium (20 min) Filing cabinet + scanner apps 512 MB
Plausible Medium (visitor analytics) Medium-high (25 min) Google Analytics 1 GB
Uptime Kuma + Beszel Low (infra monitoring) Low (10 min) UptimeRobot + Datadog 256 MB
Gitea Medium (source code) Low (15 min) GitHub private repos 256 MB
n8n Medium (workflow data) Medium (20 min) Zapier, Make 512 MB
Coolify Low (deployment tool) Medium (20 min) Vercel, Railway 1 GB

Privacy impact is the strongest reason to self-host. Your passwords, photos, and scanned documents are the most sensitive data you handle daily. On your own VPS in Europe, that data stays under your control and under GDPR.

For tutorials on each app, follow the links at the end of this guide.

What can I run on a 4GB VPS vs an 8GB VPS?

A 4GB VPS runs a solid personal stack. An 8GB VPS handles everything a solo developer or small team needs. The numbers below account for the reverse proxy (~30 MB), Docker overhead, and the OS itself (~300-400 MB used).

4 GB VPS (~3.2 GB available for apps)

Stack combo Total idle RAM Headroom
Vaultwarden + Uptime Kuma + Beszel + Gitea ~325 MB ~2.9 GB
Vaultwarden + Paperless-ngx + Uptime Kuma ~425 MB ~2.8 GB
Vaultwarden + n8n + Beszel + Gitea ~325 MB ~2.9 GB
Vaultwarden + Nextcloud + Uptime Kuma ~375 MB ~2.8 GB

These combos leave plenty of headroom for peak usage. Even when Paperless-ngx spikes to 1 GB during OCR, you still have room. Avoid Immich with ML or Plausible on 4 GB unless they are the only app running.

8 GB VPS (~7 GB available for apps)

Stack combo Total idle RAM Headroom
Vaultwarden + Immich + Uptime Kuma + Beszel ~975 MB ~6 GB
Vaultwarden + Plausible + Gitea + Paperless-ngx + Beszel ~925 MB ~6 GB
Vaultwarden + Coolify + Uptime Kuma + n8n ~725 MB ~6.3 GB
All lightweight (Vaultwarden + Gitea + Uptime Kuma + Beszel + n8n + Paperless-ngx) ~725 MB ~6.3 GB

On 8 GB, you can comfortably run Immich with ML alongside three or four lightweight apps. Plausible with ClickHouse also fits without memory pressure. This is the sweet spot for a personal self-hosting setup.

Idle RAM is what you plan around, but peaks are what crash your server. Paperless-ngx spikes during OCR. Immich spikes during photo imports with ML classification. n8n spikes when executing workflows with large payloads. The headroom column above is your safety margin. If headroom drops below 1 GB, the Linux OOM killer may terminate a container at the worst possible time. Keep at least 1.5 GB of headroom for any stack that includes Immich or Plausible.

For a Virtua Cloud VPS with 4vCPU and 8 GB RAM on NVMe storage, check the current plans. The Frankfurt location puts your data in the EU under German data protection law.

Which self-hosted apps need European hosting?

Any app that stores personal data benefits from European hosting under GDPR. But some apps handle data that makes the jurisdiction question urgent.

High priority for EU hosting:

  • Vaultwarden stores every password you own. A breach here is catastrophic. European hosting means GDPR breach notification requirements apply.
  • Immich holds personal photos, often including faces of family members. Face recognition data is biometric data under GDPR Article 9. Special category. Extra protections apply.
  • Paperless-ngx stores scanned IDs, tax documents, contracts. Some of the most sensitive personal data you have.

Medium priority:

  • Plausible collects visitor analytics. Privacy-focused by design (no cookies, no personal data), but the data still belongs to your site visitors.
  • Gitea may contain proprietary source code. Not personal data per se, but IP you want to control.
  • n8n workflows often process data from multiple services. The automation layer sees everything.

Lower priority:

  • Uptime Kuma / Beszel store monitoring data. No personal data unless you are monitoring endpoints that contain it.
  • Coolify is a deployment tool. It handles your code but does not store end-user data.

If you are a European business or handle EU citizen data, hosting these apps on a VPS in Germany (or another EU country) simplifies your GDPR compliance story. You control the data. You know where it is. You choose who has access.

How do I keep my self-hosted apps secure and updated?

Self-hosting means you are the sysadmin. That is the trade-off for control.

Firewall first. Before deploying any app, configure ufw to allow only SSH (port 22) and HTTPS (port 443). Block everything else. This is covered in Docker in Production on a VPS: What Breaks and How to Fix It.

TLS everywhere. Your reverse proxy (Caddy or Traefik) handles TLS termination. Every app gets HTTPS. No exceptions. Caddy provisions Let's Encrypt certificates automatically.

Updates. Check for container image updates weekly. Pull new images, recreate containers:

docker compose pull
docker compose up -d

For critical security updates (Vaultwarden, any internet-facing app), subscribe to the project's GitHub releases or RSS feed. Vaultwarden releases and Immich releases are good examples.

Backups. Test them. A backup you have never restored is not a backup. Use provider snapshots for full-disk recovery and Restic or borgmatic for app-level offsite backups. Schedule them with cron or a systemd timer. Verify them monthly.

Secrets management. Never hardcode passwords in docker-compose.yml. Use a .env file with chmod 600:

openssl rand -base64 32 > /dev/null  # example: generate a strong password
# docker-compose.yml
services:
  app:
    env_file: .env
# .env (chmod 600, owned by root)
DB_PASSWORD=<generated-password>
SECRET_KEY=<generated-key>

Monitoring. Run Uptime Kuma for external endpoint checks and Beszel for container-level metrics (CPU, RAM, disk per container). Both are lightweight and give you visibility before problems become outages. See Self-Host Uptime Kuma and Beszel on a VPS with Docker Compose.

Log awareness. Docker containers log to stdout by default:

docker compose logs -f --tail=50 <service-name>

For system-level services (the reverse proxy if running natively, SSH, firewall), use journalctl:

journalctl -u caddy -f

When something breaks, logs are your first stop. Not Stack Overflow. Not Reddit. Logs.

Where to go next?

Each app in the decision matrix above has a dedicated tutorial with full Docker Compose configs, reverse proxy setup, backups, and hardening:

App Tutorial
Vaultwarden (passwords) Self-Host Vaultwarden on a VPS with Docker Compose
Immich (photos) Self-Host Immich on a VPS with Docker Compose
Plausible (analytics) Self-Host Plausible Analytics on a VPS with Docker Compose
Uptime Kuma + Beszel (monitoring) Self-Host Uptime Kuma and Beszel on a VPS with Docker Compose
Coolify vs Dokploy (PaaS) Coolify vs Dokploy: Which Self-Hosted PaaS for Your VPS?
Paperless-ngx (documents) Self-Host Paperless-ngx on a VPS with Docker Compose
Gitea (Git hosting) Self-Host Gitea on a VPS with Docker Compose

If you haven't set up Docker and a reverse proxy yet, start here: Docker in Production on a VPS: What Breaks and How to Fix It. That guide covers Debian 12 and Ubuntu 24.04, installs Docker with Compose, configures Caddy as a reverse proxy with automatic TLS, sets up a firewall, and creates a non-root deploy user. Everything in this guide builds on that foundation.


Copyright 2026 Virtua.Cloud. All rights reserved. This content is original work by the Virtua.Cloud team. Reproduction, republication, or redistribution without written permission is prohibited.