Catatan transparansi: Studi kasus di artikel ini adalah VPS pribadi saya untuk dev tools + dogfooding (terpisah dari VPS produksi klien). Domain pribadi saya samarkan ke
example.devuntuk privasi. Angka biaya SaaS adalah harga real yang saya bayar di plan saya per November 2024, tarif Anda bisa berbeda tergantung plan tier, region pajak, dan promo aktif.
Akhir 2024 saya audit billing bulanan: 7 SaaS langganan = $107/bulan = $1.284/tahun. Trigger-nya simpel, 1Password naikkan harga family plan 33%, Sentry team push notif “upgrade ke $26”, Zapier task limit di plan saya makin sering kena. Saat saya jumlahkan semuanya, saya sadar bayar harga sebuah laptop setiap tahun untuk software yang versi self-host-nya open source dan gratis.
6 bulan kemudian, sekarang: semua 7 layanan jalan di 1 VPS $8.40/bulan. Stack: Contabo VPS Singapore (6 vCPU, 12 GB RAM, 100 GB NVMe), Ubuntu 24.04 LTS, Docker Compose, Caddy reverse proxy, Restic untuk backup. Saving net $98/bulan = $1.176/tahun. ROI break-even dalam 1 minggu dibanding harga SaaS sebelumnya.
Tapi saya tidak akan jualan “self-host = pasti hemat untuk semua”. Ada 5 hal yang sebaiknya tetap pakai SaaS (Section 13), email transactional untuk e-commerce klien saya, payment gateway, CDN global heavy traffic, di antaranya. Self-host adalah trade-off control vs maintenance time. Untuk freelance/agency kecil/personal stack, trade-off ini sangat worth-it. Untuk team enterprise dengan compliance audit + butuh SLA 99.99%, SaaS tetap rasional.
Artikel ini saya tulis untuk Anda yang tagihan SaaS bulanan terasa berat, atau yang ingin own your data, bukan vendor lock-in. Setup keseluruhan ~3 jam kalau Anda familiar Docker. Pertama kali bisa 1 weekend (8-12 jam) sambil belajar. Saya cover dari picking VPS sampai backup strategy, lengkap, no skip.
1. Kenapa Self-Hosting Worth It (dan Kapan Tidak)
Tiga alasan kuat self-host worth-it untuk profile saya (freelance + agency kecil):
1.1. Cost predictability.
SaaS pricing naik berkala 1Password naik 33% Q3 2024, Notion naik 100% saat ada AI feature, Zapier limit task makin agresif tiap tahun. VPS Contabo saya lock di $8.40/bulan kontrak 1 tahun, dan Hetzner saya pakai untuk klien Eropa juga harga static 3 tahun.
1.2. Data ownership + portability.
Kalau Mailgun matikan akun saya besok karena suspicion fraud, semua email transactional klien Berhenti, saya tidak punya leverage. Self-host: data ada di disk saya, backup ada di Backblaze saya. Pindah provider VPS = 2 jam rsync.
1.3. No vendor lock-in.
Vaultwarden = drop-in compatible dengan Bitwarden client. n8n workflow JSON portable. Plausible export semua data via UI. Anda kapan-kapan migrasi balik ke SaaS = bisa. Anda lock-in Notion saat mereka deprecate feature = data export-nya pain.
Tapi self-host TIDAK worth-it kalau Anda di kondisi berikut:
| Kondisi | Saran |
|---|---|
| Team >5 orang butuh enterprise SSO (Okta/Azure AD/Google Workspace SAML) | Pakai SaaS, SSO self-host bisa, tapi maintenance overhead besar |
| Compliance SOC2 / HIPAA / PCI-DSS audit | SaaS dengan audit certification existing |
| 24/7 dedicated support mission-critical | SaaS dengan enterprise SLA |
| Tim non-technical harus admin sendiri | SaaS, UI/UX lebih friendly |
| Traffic spike unpredictable >100k req/jam | SaaS dengan auto-scale, atau managed Kubernetes |
Hidden cost realitas yang sering di-skip oleh blog “self-host hemat”:
- VPS uptime tanggung jawab Anda. Provider down, app Anda down. Saya monitor 4 region VPS dari Uptime Kuma sendiri + UptimeRobot external untuk catch monitoring’s own failure.
- Security patch tanggung jawab Anda. Watchtower auto-update Docker image membantu, tapi major version upgrade (Postgres 14→15, Nextcloud 28→29) tetap manual + risk.
- Backup strategy harus Anda design. Tidak ada “Restore from backup” tombol di SaaS dashboard. Section 11 di artikel ini saya cover detail strateginya.
Ringkasnya: kalau Anda technical, comfortable dengan SSH+Docker, dan bisa sediakan 30-60 menit/minggu untuk maintenance, self-host worth banget. Selain itu, SaaS tetap rasional.
2. Pre-requisite Stack: VPS + Domain + Docker Compose
Hardware minimum yang saya rekomendasikan untuk run 7 app ini secara nyaman:
- CPU: 4 vCPU (6 lebih napas)
- RAM: 8 GB (12 lebih napas; Sentry + Mailcow makan banyak)
- Storage: 50 GB SSD (100 GB untuk Nextcloud files + backup staging)
- Bandwidth: 5 TB/bulan unmetered (sebagian besar provider EU/Asia kasih unlimited 1 Gbps)
VPS provider yang saya rekomendasikan (per pengalaman saya kelola 14+ VPS klien):
| Provider | Spec | Harga | Region | Notes |
|---|---|---|---|---|
| Contabo VPS S | 4 vCPU / 8 GB / 50 GB NVMe | $5.50/bulan | EU, US, SG, JP | Cheapest, IO sedang |
| Contabo VPS M | 6 vCPU / 12 GB / 100 GB NVMe | $8.40/bulanAAA | EU, US, SG, JP | Pilihan saya, best price/performance |
| Hetzner CX22 | 2 vCPU / 4 GB / 40 GB SSD | $5.6/bulan | EU, US | Performa top, latency EU bagus |
| Hetzner CX32 | 4 vCPU / 8 GB / 80 GB SSD | $7.5/bulan | EU, US | Hetzner middle tier |
| DigitalOcean Premium | 4 vCPU / 8 GB / 160 GB SSD | $48/bulan | Global | Mahal tapi API + integrasi developer juara |
Saya pakai Contabo VPS M untuk dev stack pribadi. Untuk klien produksi, saya mix Hetzner + Contabo tergantung region target audience.
Software stack yang saya install di provision Day 1:
# Base OS
apt update && apt upgrade -y
# Docker + Compose
curl -fsSL https://get.docker.com | sh
apt install -y docker-compose-plugin
# Caddy (reverse proxy auto-SSL)
apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt update && apt install -y caddy
# Restic (backup)
apt install -y restic
# Watchtower (auto-update Docker container)
docker run -d --name watchtower \
-v /var/run/docker.sock:/var/run/docker.sock \
--restart unless-stopped \
containrrr/watchtower --cleanup --schedule "0 4 * * *"
DNS setup di Cloudflare dashboard:
- Wildcard A record:
*.example.dev→ IP VPS, Proxied OFF (kalau pakai Cloudflare Tunnel atau langsung) - Atau 7 individual A record per subdomain:
vault.example.dev, cloud.example.dev, dll
💡 Pro tip #1: Pakai domain
.devatau.app($12-15/tahun di Namecheap/Cloudflare Registrar) untuk self-host stack. Kedua TLD ini HSTS preloaded by default, browser modern (Chrome, Firefox, Safari) wajib SSL, auto-redirect HTTP→HTTPS bahkan tanpa cert valid. Bonus security gratis.
Struktur folder yang saya pakai untuk seluruh stack:
/srv/
├── caddy/
│ └── Caddyfile
├── data/
│ ├── vaultwarden/
│ ├── nextcloud/
│ ├── plausible/
│ ├── uptime-kuma/
│ ├── mailcow/
│ ├── sentry/
│ └── n8n/
└── compose/
├── vaultwarden/docker-compose.yml
├── nextcloud/docker-compose.yml
└── ...
1 folder per app, masing-masing dengan compose file + data folder. Mudah backup selektif + maintenance.
3. App #1: Vaultwarden — Ganti 1Password / LastPass
Saving: $5/bulan (1Password Family $4.99 → Vaultwarden free)
Vaultwarden adalah implementasi server Bitwarden dalam Rust (lebih lightweight dari official server Node.js, ~28 MB RAM idle vs 350+ MB official). 100% compatible dengan client Bitwarden official: browser extension, mobile app iOS/Android, desktop app, CLI.
Use case yang saya pakai:
- Password vault personal + family share (5 collection)
- TOTP 2FA codes (ganti Google Authenticator)
- SSH private key + secure note untuk credential
- Browser auto-fill di Chrome/Firefox/Safari
Docker compose (/srv/compose/vaultwarden/docker-compose.yml):
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
DOMAIN: "https://vault.example.dev"
SIGNUPS_ALLOWED: "false"
ADMIN_TOKEN: "${VW_ADMIN_TOKEN}"
SMTP_HOST: "mail.example.dev"
SMTP_FROM: "[email protected]"
SMTP_USERNAME: "[email protected]"
SMTP_PASSWORD: "${VW_SMTP_PASS}"
SMTP_SECURITY: "starttls"
SMTP_PORT: 587
volumes:
- /srv/data/vaultwarden:/data
ports:
- "127.0.0.1:8081:80"
Initial setup workflow:
- Sementara set
SIGNUPS_ALLOWED: "true"→ register akun pertama dihttps://vault.example.dev - Set kembali ke
"false"→ restart container → tidak ada lagi yang bisa register - Generate ADMIN_TOKEN panjang (saya pakai
openssl rand -base64 48) → akses panel admin di /admin - Setup SMTP supaya 2FA recovery + email reminder berfungsi (saya pakai Mailcow saya sendiri, jadi 100% self-hosted)
Migrasi dari 1Password:
1Password app → File menu → Export → All Items → CSV
Vaultwarden web vault → Tools → Import data → Format: 1Password 1pif/csv
Verify: 487 item dari 1Password masuk semua, share 5 family collection terbentuk ulang dengan permission.
⚠️ Catatan #1: Setelah register akun pertama, WAJIB set
SIGNUPS_ALLOWED=falsedan restart container. Default true berarti siapapun yang nemu subdomain Vaultwarden Anda bisa register sendiri — itu bukan threat besar (mereka tidak akses vault Anda), tapi spam DB + risk brute force lebih tinggi.
Resource footprint di steady state: 28 MB RAM, <1% CPU. Aplikasi paling ringan di seluruh stack ini.
4. App #2: Nextcloud — Ganti Google Drive / Dropbox
Saving: $2-15/bulan (Google Drive 100 GB $1.99 → Dropbox 2 TB $12 → Nextcloud free di VPS)
Nextcloud adalah full ecosystem self-host: file sync + collaboration + Office docs via Collabora + calendar + contacts + tasks + Talk (video call). Saya pakai 60% untuk file sync (replace Dropbox), 30% untuk Office docs (replace Google Docs), 10% untuk calendar (replace Google Calendar).
Storage strategy yang saya pakai:
- 80 GB di VPS NVMe untuk hot files (project aktif, gambar working, doc kolaborasi)
- 1 TB di Backblaze B2 ($6/bulan) sebagai external storage Nextcloud untuk archive
Total cost: $8.40 (VPS) + $6 (B2 archive) = $14.40 untuk 1.08 TB usable, vs Dropbox 2 TB $12 = lebih murah Dropbox kalau Anda butuh full 2 TB. Tapi untuk <200 GB working files + archive di B2, self-host menang dan Anda dapat fitur Office collaboration + calendar gratis.
Docker compose (simplified, 4 service):
services:
nextcloud-app:
image: nextcloud:29-apache
container_name: nextcloud-app
restart: unless-stopped
environment:
MYSQL_HOST: nextcloud-db
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_PASSWORD: "${NC_DB_PASS}"
REDIS_HOST: nextcloud-redis
NEXTCLOUD_TRUSTED_DOMAINS: "cloud.example.dev"
OVERWRITEPROTOCOL: "https"
PHP_MEMORY_LIMIT: "1024M"
PHP_UPLOAD_LIMIT: "10G"
volumes:
- /srv/data/nextcloud/app:/var/www/html
ports:
- "127.0.0.1:8082:80"
depends_on:
- nextcloud-db
- nextcloud-redis
nextcloud-db:
image: mariadb:10.11
container_name: nextcloud-db
restart: unless-stopped
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
environment:
MYSQL_ROOT_PASSWORD: "${NC_DB_ROOT}"
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_PASSWORD: "${NC_DB_PASS}"
volumes:
- /srv/data/nextcloud/db:/var/lib/mysql
nextcloud-redis:
image: redis:7-alpine
container_name: nextcloud-redis
restart: unless-stopped
volumes:
- /srv/data/nextcloud/redis:/data
nextcloud-cron:
image: nextcloud:29-apache
container_name: nextcloud-cron
restart: unless-stopped
volumes:
- /srv/data/nextcloud/app:/var/www/html
entrypoint: /cron.sh
depends_on:
- nextcloud-db
- nextcloud-redis
Performance tuning yang biasanya skipped tapi penting (di config.php setelah install):
'memcache.local' => '\\OC\\Memcache\\APCu',
'memcache.distributed' => '\\OC\\Memcache\\Redis',
'memcache.locking' => '\\OC\\Memcache\\Redis',
'redis' => [
'host' => 'nextcloud-redis',
'port' => 6379,
],
'preview_max_x' => 2048,
'preview_max_y' => 2048,
'enabledPreviewProviders' => ['OC\\Preview\\PNG', 'OC\\Preview\\JPEG', 'OC\\Preview\\PDF'],
💡 Pro tip #2: Nextcloud bukan untuk team backup besar (>500 GB). Untuk itu pakai object storage langsung (MinIO atau B2). Nextcloud cocok untuk collaboration + sync 50-200 GB working files dengan UI yang familiar untuk user non-technical.
Initial setup: 25 menit (lebih lama dari Vaultwarden karena perlu setup DB + Redis + trusted domain + first user + apps preferred).
Resource footprint: 480 MB RAM (idle), 1.2 GB (peak saat preview generation atau OnlyOffice doc edit).
5. App #3: Plausible Analytics — Ganti Google Analytics + Mixpanel
Saving: $9-20/bulan (Mixpanel Growth $20 → Plausible self-host free)
Plausible adalah privacy-friendly web analytics: no cookies, GDPR-compliant by default, dashboard clean, script tag <1 KB (vs GA4 script 50 KB+). Saya pakai untuk monitor traffic blog larhtech.com + 4 site klien yang opt-in privacy.
Plausible bukan replacement enterprise BI (Mode, Looker, Metabase). Tapi cukup untuk 95% use case product/marketing: pageviews, bounce rate, conversion funnel, source/medium, device breakdown, custom event.
Docker compose (3 service):
services:
plausible:
image: plausible/analytics:v2.1.0
container_name: plausible
restart: unless-stopped
command: sh -c "/entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
environment:
BASE_URL: "https://analytics.example.dev"
SECRET_KEY_BASE: "${PL_SECRET_KEY}"
DATABASE_URL: "postgres://plausible:${PL_DB_PASS}@plausible-db:5432/plausible_db"
CLICKHOUSE_DATABASE_URL: "http://plausible-clickhouse:8123/plausible_events_db"
MAILER_EMAIL: "[email protected]"
SMTP_HOST_ADDR: "mail.example.dev"
SMTP_HOST_PORT: 587
SMTP_USER_NAME: "[email protected]"
SMTP_USER_PWD: "${PL_SMTP_PASS}"
ports:
- "127.0.0.1:8083:8000"
depends_on:
- plausible-db
- plausible-clickhouse
plausible-db:
image: postgres:15-alpine
container_name: plausible-db
restart: unless-stopped
environment:
POSTGRES_PASSWORD: "${PL_DB_PASS}"
POSTGRES_USER: plausible
POSTGRES_DB: plausible_db
volumes:
- /srv/data/plausible/db:/var/lib/postgresql/data
plausible-clickhouse:
image: clickhouse/clickhouse-server:24.3-alpine
container_name: plausible-clickhouse
restart: unless-stopped
volumes:
- /srv/data/plausible/clickhouse:/var/lib/clickhouse
ulimits:
nofile:
soft: 262144
hard: 262144
Clickhouse = analytics DB column-oriented yang paling resource-heavy di stack ini (~600 MB RAM idle, spike sampai 1.4 GB saat ada heavy query dashboard).
Initial setup (15 menit):
- Register admin user via web UI
- Add first site (
larhtech.com) → dapat snippet script:
<script defer data-domain="larhtech.com" src="https://analytics.example.dev/js/script.js"></script>
- Paste ke
<head>semua page (WordPress: pakai plugin “Header and Footer Scripts”) - Optional: enable shared dashboard URL untuk klien
Migrasi dari Google Analytics: tidak ada native importer. Saya parallel-run 2 minggu (script GA + Plausible aktif bersamaan), bandingkan data, lalu cut over GA tag. Plausible juga tidak punya cohort/funnel kompleks seperti Mixpanel, kalau Anda butuh funnel multi-step, tambah PostHog (juga open source) di stack ini.
⚠️ Catatan #2: Plausible self-host tidak kirim data sama sekali ke pihak ketiga, beda dengan Plausible Cloud (yang host di EU server mereka, tetap GDPR-compliant tapi data Anda di server mereka). Untuk privacy purist atau compliance yang ketat (HIPAA, sektor finance), self-host adalah pilihan.
6. App #4: Uptime Kuma — Ganti UptimeRobot / StatusCake
Saving: $7/bulan (UptimeRobot Pro $7 → Uptime Kuma free)
Uptime Kuma adalah monitoring dashboard self-host paling populer di 2024-2025 (35k+ GitHub star). UI Tailwind yang clean, 90+ notification channel, support monitor HTTP, TCP, Ping, DNS, Docker container, Steam server, RADIUS, gRPC, dll.
Saya monitor 47 endpoint dari Uptime Kuma sendiri: 14 site klien produksi + 7 self-host app + 12 SSL cert expiry + 14 internal API endpoint.
Docker compose (super simple, 1 service):
services:
uptime-kuma:
image: louislam/uptime-kuma:1
container_name: uptime-kuma
restart: unless-stopped
volumes:
- /srv/data/uptime-kuma:/app/data
ports:
- "127.0.0.1:8084:3001"
Initial setup (5 menit):
- Akses
https://status.example.dev→ register admin user - Add first monitor: HTTP(s) check ke
larhtech.com, interval 60 detik, timeout 30 detik - Add notification channel: Telegram bot (saya pakai bot pribadi, BotFather setup 2 menit)
- Setup public status page:
https://status.example.dev/status/mainuntuk share ke klien/team
Notification channel yang saya pakai aktif:
- Telegram untuk alert pribadi (push instant)
- Email ke
[email protected]untuk archive - Discord webhook untuk team channel (kalau ada team)
- Apprise untuk multi-channel fan-out
💡 Pro tip #3: Set up Uptime Kuma ITU SENDIRI monitored dari service external, UptimeRobot free tier 50 monitor cukup, atau VPS ke-2 dengan Uptime Kuma juga. Kalau Anda monitor Uptime Kuma dari Uptime Kuma yang sama yang down, Anda tidak akan dapat alert kalau monitoring service down. Saya pernah miss outage 3 jam karena ini di awal.
Resource footprint: 92 MB RAM. Hampir nol di CPU. App paling cost-effective dari semua stack ini ($7/bulan saved untuk 92 MB RAM).
7. App #5: Mailcow — Ganti Google Workspace Email
Saving: $6-12/user/bulan (Google Workspace Business $12/user/bulan → Mailcow free)
Mailcow adalah full email server stack: Postfix (SMTP), Dovecot (IMAP/POP3), Rspamd (spam filter), ClamAV (antivirus), SOGo (webmail), DKIM/SPF/DMARC auto, web admin panel. Saya pindah email pribadi + 2 domain agency kecil ke sini. Saving 3 user × $12 = $36/bulan.
PENTING, Mailcow adalah app paling complicated di stack ini. Saya tidak akan mengelabuhi, self-host email butuh effort, knowledge DNS, dan patience. Yang bisa salah:
- Reverse DNS PTR harus match domain Anda (request via Contabo support panel, 24-48 jam)
- IP reputation, Contabo IP shared block kadang ada di RBL (Spamhaus, Barracuda). Cek di MXToolbox sebelum commit.
- SPF/DKIM/DMARC harus perfect, atau email Anda masuk spam folder Gmail/Outlook
- IP warming 2-4 minggu kirim email volume rendah dulu, baru ramp-up
Karena Mailcow tidak pakai docker-compose.yml standard (mereka punya install.sh sendiri), workflow setup:
cd /srv
git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
./generate_config.sh
# Input: hostname mail.example.dev, timezone Asia/Jakarta
docker compose pull
docker compose up -d
Setelah container up (~5 menit), akses https://mail.example.dev → admin/moohoo (ganti password segera).
DNS records yang perlu Anda tambah di Cloudflare/Namecheap:
mail.example.dev A [VPS_IP]
example.dev MX 10 mail.example.dev
example.dev TXT "v=spf1 mx ~all"
default._domainkey TXT "v=DKIM1; k=rsa; p=[DKIM_PUBLIC_KEY]" (dapat dari panel Mailcow)
_dmarc TXT "v=DMARC1; p=quarantine; rua=mailto:[email protected]"
Verify deliverability ke major provider:
- Kirim email test ke
[email protected]→ balas dengan laporan SPF/DKIM/DMARC pass/fail - Kirim ke
mail-tester.com→ dapat score 0-10. Target >9/10 sebelum production - Test masuk Gmail, Outlook, ProtonMail, semua harus masuk Inbox, bukan Spam
⚠️ Catatan #3: JANGAN pindah email klien produksi e-commerce tanpa minimum 2 minggu testing. Saya pindah email pribadi dulu, monitor deliverability 30 hari (pakai mail-tester.com weekly), baru pindah 2 domain agency kecil. Untuk klien e-commerce dengan email transactional kritikal (order confirmation, password reset, invoice), tetap rekomendasi pakai Postmark/Mailgun/SendGrid, bukan self-host. Resiko 1 email order tidak sampai = customer complaint = reputational damage. SaaS email cost $10-30/bulan worth-it dibanding risk.
Resource footprint Mailcow: paling berat di stack ini, 1.8 GB RAM idle, 2.4 GB peak. 11 container running simultan (Postfix, Dovecot, Rspamd, ClamAV, MySQL, Redis, Nginx, SOGo, ACMe, Watchdog, dst). Setup time pertama kali: 60 menit termasuk DNS propagation wait + deliverability test.
8. App #6: Sentry Self-Hosted — Ganti Sentry SaaS
Saving: $26/bulan (Sentry Team plan 50k events $26 → Sentry self-hosted free)
Sentry adalah error tracking + performance monitoring untuk web app, mobile, backend. Saya integrate ke 8 project: 4 Next.js (klien e-commerce), 2 Laravel (klien CMS), 1 React Native, 1 Node.js worker.
Self-host edition full feature parity dengan SaaS Team plan: issue tracking, performance monitoring, session replay, profiling, cron monitoring, release tracking. Yang TIDAK ada: 24/7 dedicated support + audit log enterprise.
Setup Sentry beda dengan app lain, pakai install script official, bukan compose file standalone:
cd /srv
git clone https://github.com/getsentry/self-hosted sentry
cd sentry
./install.sh
# Interactive prompts: skip user creation untuk sekarang, terima default
Install script auto-generate docker-compose untuk 8+ service: sentry-web, sentry-worker, sentry-cron, postgres, redis, kafka, snuba, smtp, nginx. Butuh minimum 8 GB RAM untuk Sentry stack alone, karena Sentry pakai Kafka untuk queue ingest event, dan Snuba (clickhouse-based search engine).
Initial setup (45 menit):
- Setelah install script selesai, akses
https://errors.example.dev→ create admin user (email + password) - Create organization → create first project → pilih platform (Next.js)
- Copy DSN URL:
https://[KEY]@errors.example.dev/[PROJECT_ID] - Install Sentry SDK di app:
pnpm add @sentry/nextjs
npx @sentry/wizard@latest -i nextjs
- Set environment variable di app:
NEXT_PUBLIC_SENTRY_DSN=... - Deploy → trigger error test → verify error masuk dashboard Sentry
Per project ada DSN unique. Saya manage 8 project di 1 Sentry instance, ~12k event/bulan total.
Resource footprint: 1.6 GB RAM idle, 2.8 GB peak saat ada worker spike (incident besar = ratusan event/menit ingest).
💡 Pro tip #4: Kalau Anda solo dev atau proyek kecil <2.000 event/bulan, tetap pakai Sentry SaaS free tier (5.000 event/bulan gratis). Self-host Sentry worth-it kalau Anda multi-project >5 aplikasi atau team butuh >50k event/bulan (skip Team plan $26). Resource VPS untuk Sentry tidak murah, 8 GB RAM dedikasi adalah investment.
9. App #7: n8n — Ganti Zapier / Make
Saving: $20-30/bulan (Zapier Professional $29.99 → n8n self-host free)
n8n adalah workflow automation visual node-based, dengan 400+ integration built-in. Use case: webhook → trigger → multi-step action chain. Mirip Zapier/Make tapi self-host.
Saingan utama: di Zapier $29 plan = 2.000 task/bulan limit. Di n8n self-host = task unlimited (terbatas CPU VPS Anda). Untuk power user dengan workflow heavy, ini saving besar.
Use case real yang saya jalankan:
- Cloudflare webhook → Telegram alert — saat traffic spike >5× baseline di klien, notif instant ke saya
- Sentry webhook → Linear ticket auto-create — error baru di production = ticket di backlog
- Cron daily 04:00 → Restic backup verify report — backup verify run, hasil masuk Discord channel
- Form submit larhtech.com → SQLite logger + Email response — contact form tanpa pakai Mailgun
Docker compose (n8n + Postgres backing):
services:
n8n:
image: n8nio/n8n:latest
container_name: n8n
restart: unless-stopped
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: n8n-db
DB_POSTGRESDB_DATABASE: n8n
DB_POSTGRESDB_USER: n8n
DB_POSTGRESDB_PASSWORD: "${N8N_DB_PASS}"
N8N_HOST: "flow.example.dev"
N8N_PROTOCOL: https
WEBHOOK_URL: "https://flow.example.dev"
N8N_BASIC_AUTH_ACTIVE: "true"
N8N_BASIC_AUTH_USER: admin
N8N_BASIC_AUTH_PASSWORD: "${N8N_AUTH_PASS}"
EXECUTIONS_MODE: queue
QUEUE_BULL_REDIS_HOST: n8n-redis
TZ: Asia/Jakarta
volumes:
- /srv/data/n8n:/home/node/.n8n
ports:
- "127.0.0.1:5678:5678"
depends_on:
- n8n-db
- n8n-redis
n8n-db:
image: postgres:15-alpine
container_name: n8n-db
restart: unless-stopped
environment:
POSTGRES_DB: n8n
POSTGRES_USER: n8n
POSTGRES_PASSWORD: "${N8N_DB_PASS}"
volumes:
- /srv/data/n8n/db:/var/lib/postgresql/data
n8n-redis:
image: redis:7-alpine
container_name: n8n-redis
restart: unless-stopped
volumes:
- /srv/data/n8n/redis:/data
⚠️ Catatan #4: JANGAN pakai default SQLite storage untuk production n8n. Workflow data + execution log tumbuh cepat — SQLite akan kena lock contention saat >100 execution/jam. Postgres backing store wajib. Mode “queue” + Redis juga wajib untuk concurrent execution.
Initial setup (15 menit): akses https://flow.example.dev, set basic auth password, create first workflow drag-and-drop, test webhook trigger dengan curl.
Resource footprint: 380 MB RAM (idle), 640 MB peak. Tergantung jumlah workflow + frekuensi execution.
10. Reverse Proxy + SSL: Caddy Auto-SSL untuk 7 Subdomain
Setelah 7 app jalan dengan port bind ke 127.0.0.1 (bukan 0.0.0.0 — penting untuk security), satukan semua di Caddy reverse proxy dengan auto-SSL Let’s Encrypt.
/etc/caddy/Caddyfile:
{
email [email protected]
}
vault.example.dev {
reverse_proxy localhost:8081
encode gzip zstd
}
cloud.example.dev {
reverse_proxy localhost:8082
encode gzip zstd
request_body {
max_size 10GB
}
}
analytics.example.dev {
reverse_proxy localhost:8083
encode gzip zstd
}
status.example.dev {
reverse_proxy localhost:8084
encode gzip zstd
}
mail.example.dev {
reverse_proxy localhost:8085
encode gzip zstd
}
errors.example.dev {
reverse_proxy localhost:9000
encode gzip zstd
request_body {
max_size 50MB
}
}
flow.example.dev {
reverse_proxy localhost:5678
encode gzip zstd
}
Apply config dan reload:
caddy validate --config /etc/caddy/Caddyfile
systemctl reload caddy
Caddy auto-issue cert dari Let’s Encrypt untuk semua 7 subdomain dalam 60 detik (kalau DNS A record sudah propagated). Auto-renew tiap 60 hari. Zero config certbot drama.
💡 Pro tip #5: Kalau VPS Anda di belakang NAT atau home server tanpa public IP, pakai Cloudflare Tunnel (free unlimited): traffic terenkripsi via Cloudflare edge, skip port forwarding 80/443. Tinggal install cloudflared di VPS, daftar tunnel di Cloudflare dashboard, map subdomain → service localhost. Mengurangi 1 attack surface (no exposed public port).

11. Backup Strategy: 1 Restic Repository untuk Semua Service
Backup adalah assumed disaster. VPS hilang besok, Anda harus bisa restore ke VPS baru dalam <2 jam. Tanpa backup strategy, semua effort 6 bulan sebelumnya bisa hilang.
Tools yang saya pakai:
- Restic 0.16, backup tool encrypted (AES-256), incremental, deduplication
- Backblaze B2, cheap S3-compatible object storage ($6/TB/bulan, $0.01/GB egress)
- cron, daily 03:00 WIB (off-peak)
Script /srv/scripts/backup.sh:
#!/bin/bash
set -euo pipefail
export RESTIC_REPOSITORY="b2:my-bucket-name:/selfhost"
export RESTIC_PASSWORD_FILE="/root/.restic_pass"
export B2_ACCOUNT_ID="${B2_KEY_ID}"
export B2_ACCOUNT_KEY="${B2_APP_KEY}"
# Stop services yang punya DB writer aktif (untuk consistent backup)
docker compose -f /srv/compose/nextcloud/docker-compose.yml stop nextcloud-app
docker compose -f /srv/compose/plausible/docker-compose.yml stop plausible
docker compose -f /srv/compose/sentry/docker-compose.yml stop sentry-worker
# Backup volume data + compose file
restic backup \
--tag "daily-$(date +%Y-%m-%d)" \
--exclude '*.tmp' \
--exclude 'cache/*' \
/srv/data \
/srv/compose \
/etc/caddy
# Restart services
docker compose -f /srv/compose/nextcloud/docker-compose.yml start nextcloud-app
docker compose -f /srv/compose/plausible/docker-compose.yml start plausible
docker compose -f /srv/compose/sentry/docker-compose.yml start sentry-worker
# Retention policy: 7 daily + 4 weekly + 6 monthly + 2 yearly
restic forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 6 \
--keep-yearly 2 \
--prune
# Verify (cepat - subset random)
restic check --read-data-subset=5%
Cron entry:
echo "0 3 * * * root /srv/scripts/backup.sh >> /var/log/restic-backup.log 2>&1" > /etc/cron.d/restic-backup
⚠️ Catatan #5: Backup yang tidak pernah di-restore = backup yang tidak ada. Test restore minimum 1× setelah setup awal, dan 1× per kuartal. Jangan asumsikan backup berfungsi sampai Anda terbukti bisa restore. Saya
restic restoreke folder/tmp/restore_test/quarterly, verify file count + sample diff, lalu delete.
Backup size after 6 bulan running: 18 GB encrypted di B2 = $0.11/bulan storage. Total backup cost annualized: ~$1.5/bulan termasuk egress untuk test restore. Margin error besar untuk insurance.
12. Total Cost Comparison + Resource Headroom
BEFORE (7 SaaS subscription) – Tahun 2024:
| Layanan | Plan | $/bulan |
|---|---|---|
| 1Password Family | Family 5 user | $4.99 |
| Google Drive | 100 GB Standard | $1.99 |
| Mixpanel | Growth 100k MTU | $20.00 |
| UptimeRobot | Pro 50 monitor | $7.00 |
| Google Workspace | Business 1 user | $12.00 |
| Sentry | Team 50k events | $26.00 |
| Zapier | Professional 2k task | $29.99 |
| Total SaaS | $101.96 |
AFTER (1 VPS + storage backup) – Tahun 2025:
| Item | $/bulan |
|---|---|
| Contabo VPS M (6 vCPU / 12 GB / 100 GB NVMe) | $8.40 |
| Backblaze B2 backup (~20 GB encrypted) | $0.12 |
| Backblaze B2 Nextcloud archive storage (~1 TB) | $6.00 |
| Domain .dev renewal | $1.17 (annualized) |
| Total Self-Host | $15.69 |
Net saving: $86.27/bulan = $1.035/tahun. Dengan pricing yang lebih konservatif (kalau Anda skip B2 archive 1 TB, $9.69/bulan total) → saving $92.27/bulan = $1.107/tahun.
ROI break-even: <1 minggu.
5-year saving (asumsi SaaS pricing flat, padahal biasa naik 5-10%/tahun): $5.176.
Resource utilization steady state setelah 6 bulan running:
| Metrik | Idle (jam 02-06 WIB) | Peak (jam 14-17 WIB) |
|---|---|---|
| CPU usage | 4-8% | 18-25% |
| RAM used | 4.2 GB / 12 GB (35%) | 6.8 GB / 12 GB (57%) |
| Disk used | 38 GB / 100 GB (38%) | (data growth 1-2 GB/bulan) |
| Network in | 12 MB/jam | 180 MB/jam |
| Network out | 24 MB/jam | 340 MB/jam |
Headroom 5.2 GB RAM + 62 GB disk untuk tambah app ke-8/9/10 di future (Headscale, Vikunja, Outline ada di roadmap saya).

13. Anti-Pattern: 5 Hal yang TIDAK Worth Self-Host
Self-host hemat bukan universal. Berikut 5 hal yang saya TETAP pakai SaaS, dan alasan teknis:
| # | Kategori | Kenapa SaaS lebih rasional |
|---|---|---|
| 1 | Email transactional e-commerce klien (order confirmation, password reset, invoice) | Deliverability 99%+ butuh IP reputation matang + monitoring blacklist + DKIM rotation. Pakai Postmark ($15/bulan) / Mailgun / SendGrid. Risk 1 email tidak sampai = customer complaint. |
| 2 | Database analytics 100 GB+ dengan query paralel | Clickhouse self-host bisa, tapi managed (ClickHouse Cloud, BigQuery, Snowflake) handle scaling otomatis. ROI break-even lebih tinggi. |
| 3 | CDN untuk traffic global >10k req/menit | Cloudflare free + Pro ($20/bulan) atau Bunny.net ($0.01/GB) jauh lebih efektif daripada DIY caching layer di VPS dengan latency variable. |
| 4 | Customer support helpdesk | Intercom/Crisp punya widget mobile + auto-translate yang susah re-implement self-host. Untuk SaaS B2C, integrasi mobile push notification = kritis. |
| 5 | Payment gateway | JANGAN PERNAH self-host. PCI-DSS compliance audit = 6 bulan effort + $10k-50k cost. Pakai Stripe/Midtrans/Xendit — mereka audit, Anda fokus produk. |
Saya juga tetap bayar Cloudflare Pro ($20/bulan) untuk klien produksi dengan traffic harian >100k pageview. WAF + Argo Smart Routing + image optimization tidak bisa di-DIY dengan biaya wajar.
14. FAQ
Berapa VPS spec minimum untuk run 7 app ini?
Minimum 4 vCPU / 8 GB RAM / 50 GB SSD cukup, tapi tight. Saya rekomendasi 6 vCPU / 12 GB / 100 GB untuk napas. Contabo VPS M ($8.40/bulan) atau Hetzner CX32 ($7.5/bulan) — pilih sesuai region target audience Anda.
aultwarden aman untuk team agency 10 user dengan data sensitive?
Secara crypto aman (server-side encrypted, client-side decrypt, server tidak pernah lihat plaintext). Tapi untuk compliance audit / SOC2 / HIPAA, susah lewat — Anda butuh certified audit log + access policy enforcement. Untuk 10 user financial/healthcare, pakai 1Password Business dengan SSO Okta/Azure AD.
Mailcow self-host bisa kompete dengan Gmail deliverability?
Bisa, tapi butuh effort: reverse DNS PTR setup via VPS provider support, IP warming 2-4 minggu (kirim email volume kecil dulu naik bertahap), SPF/DKIM/DMARC strict, monitor blacklist via MXToolbox weekly. Untuk email kritikal bisnis (transactional e-commerce), pakai hybrid: SaaS untuk transactional, self-host untuk internal team.
Backup strategy kalau VPS provider hilang besok?
3-2-1 rule: 3 copy data, 2 different media, 1 offsite. Saya pakai VPS NVMe (primary) + Backblaze B2 ($1.50/bulan untuk ~20 GB encrypted Restic) + occasional download ke local NAS (cold archive 3 bulan). Test restic restore minimum quarterly.
Berapa lama maintenance overhead per minggu?
Steady-state 30-60 menit/minggu: update Docker image via Watchtower (auto), backup verify (manual check log), dashboard monitor (5 menit). Pertama 2 bulan lebih (2-3 jam/minggu) karena learning curve Docker + DNS + reverse proxy.
Self-host vs PaaS murah (Coolify, Dokploy, CapRover)?
PaaS murah punya UI bagus seperti Heroku tapi tetap pakai VPS Anda di belakang. Cocok untuk reduce learning curve Docker Compose. Saya rekomendasi mulai dari Coolify (open source, free self-host) kalau Anda first-time. Setelah comfortable, migrasi ke pure Docker Compose untuk control penuh.
15. Penutup
Recap singkat:
- 7 app self-host: Vaultwarden, Nextcloud, Plausible, Uptime Kuma, Mailcow, Sentry, n8n
- Stack: VPS $8.40 + Caddy auto-SSL + Restic backup encrypted ke B
- Setup time total: ~3 jam untuk Anda yang familiar Docker, 8-12 jam untuk first-timer
- Saving net: $86/bulan = $1.035/tahun dengan plan saya
- Resource headroom: 5 GB RAM + 62 GB disk untuk tambah app future
- Maintenance overhead: 30-60 menit/minggu steady-state
Pesan utama: self-host = trade-off control vs maintenance time. Untuk freelancer/agency kecil/personal stack, ROI gampang dicapai. Tapi untuk team enterprise butuh SLA hard, SaaS tetap juara, saya tidak ragu rekomendasi Postmark untuk klien e-commerce, Stripe untuk payment, Cloudflare Pro untuk traffic kritis. Pilih tools yang tepat per use case, bukan ideological “anti-SaaS”.
Roadmap saya berikutnya kalau VPS masih napas: Headscale (Tailscale self-host untuk private network), Vikunja (todo app ganti Notion), Outline (team wiki). Bisa tambah 3 app lagi tanpa upgrade VPS — total saving bisa naik ke $120-150/bulan.
Untuk stack lengkap dengan deep-dive per topik:
- Setup VPS Ubuntu 24.04 dari Nol untuk WordPress — base stack provision (Docker, firewall, SSH hardening)
- Migrasi WordPress dari Shared Hosting ke VPS dalam 90 Menit — kalau Anda masih shared hosting
- Setup VPS Anti-DDoS dengan Cloudflare Free + Nginx Rate Limit + fail2ban — security layer untuk public service
- Database Query Slow di WordPress: Optimize 5 Query Tersering — performance tuning relevan
- VPS CPU 100% Padahal Idle: Trace dengan strace + lsof — forensic VPS kalau ada incident

Last Updated on Mei 27, 2026 by larhtechBro



