Tagihan Vercel, GitHub, Jira, dan Sentry datang bareng di akhir bulan — totalnya bisa bikin kamu nangis. Gue pernah di titik itu: $180/bulan cuma buat tooling, padahal proyeknya belum profit. Solusinya? Self-host semua yang bisa di-self-host.
Artikel ini bukan daftar random. Semua tool di bawah sudah gue pakai sendiri di VPS Ubuntu 22.04 dengan RAM 4GB dan 2 vCPU. Biaya VPS-nya? Sekitar Rp 120 ribu/bulan. Jauh lebih masuk akal.
Kenapa Self-Hosted Lebih Masuk Akal untuk Indie Dev
SaaS itu nyaman, tapi model harga-nya dirancang supaya kamu terus bayar. Makin produktif, makin banyak seat, makin mahal. Untuk solo dev atau tim kecil, ini tidak adil.
Dengan self-hosted:
- Kamu kontrol data sendiri
- Biaya flat, nggak naik tiba-tiba
- Bisa kustomisasi sesuai kebutuhan
- Nggak ada vendor lock-in
Gotcha-nya: kamu yang handle maintenance, update, dan backup. Tapi kalau kamu sudah terbiasa manage server, ini bukan masalah besar.
Gitea — Pengganti GitHub yang Ringan
Gitea adalah Git hosting yang bisa jalan di VPS paling murah sekalipun. Binary-nya kecil, resource usage-nya rendah, dan fiturnya cukup untuk kebutuhan sehari-hari: pull request, issue tracker, CI/CD via Gitea Actions.
Install via Docker Compose:
# docker-compose.yml
version: "3"
services:
gitea:
image: gitea/gitea:1.21
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=gitea_secret
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
depends_on:
- db
restart: unless-stopped
db:
image: postgres:15
container_name: gitea_db
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=gitea_secret
- POSTGRES_DB=gitea
volumes:
- ./postgres:/var/lib/postgresql/data
restart: unless-stopped
Jalankan dengan:
docker compose up -d
Akses di http://IP_VPS:3000, lalu setup lewat web UI. Selesai.
Gotcha: Kalau kamu mau pakai SSH clone (git clone git@...), pastikan port 222 di VPS kamu tidak diblokir firewall. Tambahkan rule UFW:
sudo ufw allow 222/tcp
Dan tambahkan ini ke ~/.ssh/config di laptop kamu:
Host gitea.domain.kamu
HostName gitea.domain.kamu
User git
Port 222
Drone CI — CI/CD Pipeline Tanpa Konfigurasi Ribet
Drone CI connect langsung ke Gitea (atau GitHub, Forgejo). Pipeline-nya didefinisikan lewat file .drone.yml di root repo — mirip GitHub Actions tapi jauh lebih ringan.
Setup Drone dengan Gitea:
Pertama, buat OAuth Application di Gitea: Settings → Applications → Manage OAuth2 Applications. Catat Client ID dan Client Secret.
# tambahkan ke docker-compose.yml yang sama
drone:
image: drone/drone:2
container_name: drone
environment:
- DRONE_GITEA_SERVER=http://gitea:3000
- DRONE_GITEA_CLIENT_ID=CLIENT_ID_KAMU
- DRONE_GITEA_CLIENT_SECRET=CLIENT_SECRET_KAMU
- DRONE_RPC_SECRET=random_secret_panjang
- DRONE_SERVER_HOST=drone.domain.kamu
- DRONE_SERVER_PROTO=https
ports:
- "3001:80"
volumes:
- ./drone:/data
restart: unless-stopped
drone-runner:
image: drone/drone-runner-docker:1
container_name: drone_runner
environment:
- DRONE_RPC_PROTO=http
- DRONE_RPC_HOST=drone
- DRONE_RPC_SECRET=random_secret_panjang
- DRONE_RUNNER_CAPACITY=2
volumes:
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
- drone
restart: unless-stopped
Contoh .drone.yml untuk project Node.js:
kind: pipeline
type: docker
name: default
steps:
- name: install
image: node:20-alpine
commands:
- npm ci
- name: test
image: node:20-alpine
commands:
- npm test
- name: build
image: node:20-alpine
commands:
- npm run build
when:
branch:
- main
Gotcha: DRONE_RPC_SECRET di server dan runner harus sama persis. Kalau beda, runner nggak akan connect dan kamu akan debug selama satu jam seperti yang gue pernah alami.
Plausible Analytics — Ganti Google Analytics, Privacy-First
Kalau kamu punya side project atau blog, kamu butuh analytics. Google Analytics itu gratis tapi datanya milik Google dan bikin website kamu lebih lambat karena script besar.
Plausible ringan (script < 1KB), tidak pakai cookie, dan GDPR-compliant. Self-hosted version-nya gratis sepenuhnya.
# plausible docker-compose.yml
version: "3.3"
services:
mail:
image: bytemark/smtp
restart: unless-stopped
plausible_db:
image: postgres:14-alpine
restart: unless-stopped
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=postgres
plausible_events_db:
image: clickhouse/clickhouse-server:23.3.7.5-alpine
restart: unless-stopped
volumes:
- event-data:/var/lib/clickhouse
- ./clickhouse/clickhouse-config.xml:/etc/clickhouse-server/config.d/logging.xml:ro
- ./clickhouse/clickhouse-user-config.xml:/etc/clickhouse-server/users.d/logging.xml:ro
ulimits:
nofile:
soft: 262144
hard: 262144
plausible:
image: plausible/analytics:v2.0
restart: unless-stopped
command: sh -c "sleep 10 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
depends_on:
- plausible_db
- plausible_events_db
- mail
ports:
- 8000:8000
environment:
- BASE_URL=https://analytics.domain.kamu
- SECRET_KEY_BASE=GENERATE_DENGAN_openssl_rand_-base64_48
volumes:
db-data:
event-data:
Generate SECRET_KEY_BASE:
openssl rand -base64 48
Tambahkan script tracking ke website kamu:
<script defer data-domain="domain.kamu" src="https://analytics.domain.kamu/js/script.js"></script>
Gotcha: Plausible butuh ClickHouse yang lumayan rakus memory di awal. Di VPS 2GB RAM, kadang container-nya crash saat startup. Solusinya: tambahkan swap 2GB di VPS.
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Sentry Self-Hosted — Error Tracking Tanpa Bayar Per Event
Sentry cloud itu mahal kalau event-mu banyak. Self-hosted Sentry gratis dan unlimited. Tapi ini yang paling berat di list ini — butuh minimal 4GB RAM.
# Clone repo resmi
git clone https://github.com/getsentry/self-hosted.git
cd self-hosted
# Jalankan installer
./install.sh
Installer akan setup semua dependency otomatis. Setelah selesai:
docker compose up -d
Akses di port 9000. Buat akun admin saat pertama kali buka.
Integrasi ke project Python/Django:
import sentry_sdk
sentry_sdk.init(
dsn="https://KEY@sentry.domain.kamu/PROJECT_ID",
traces_sample_rate=1.0,
)
Integrasi ke project Node.js:
import * as Sentry from "@sentry/node";
Sentry.init({
dsn: "https://KEY@sentry.domain.kamu/PROJECT_ID",
tracesSampleRate: 1.0,
});
Gotcha: Self-hosted Sentry update-nya agak tertinggal dari versi cloud. Sebelum update, selalu baca CHANGELOG-nya dulu. Beberapa versi punya breaking migration yang bisa bikin data hilang kalau nggak hati-hati.
Nginx Proxy Manager — Reverse Proxy dengan UI
Semua service di atas jalan di port berbeda. Supaya bisa diakses via domain (bukan IP:port) dan dapat SSL otomatis, kamu butuh reverse proxy. Nginx Proxy Manager punya UI yang bersih — nggak perlu edit config Nginx manual.
# nginx-proxy-manager docker-compose.yml
version: '3'
services:
npm:
image: jc21/nginx-proxy-manager:latest
restart: unless-stopped
ports:
- '80:80'
- '443:443'
- '81:81' # UI admin
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
Setelah jalan, akses UI di port 81. Login default:
- Email:
admin@example.com - Password:
changeme
Langsung ganti password setelah login pertama. Tambahkan Proxy Host untuk setiap service, aktifkan SSL dengan Let's Encrypt — tinggal klik.
Gotcha: Port 80 dan 443 harus bebas di VPS kamu. Kalau ada Apache atau Nginx lain yang jalan, matikan dulu:
sudo systemctl stop nginx
sudo systemctl disable nginx
Stack Lengkap di Satu VPS
Berikut gambaran resource usage stack ini di VPS 4GB RAM:
| Service | RAM (idle) |
|---|---|
| Gitea + Postgres | ~300MB |
| Drone CI + Runner | ~200MB |
| Plausible + ClickHouse | ~800MB |
| Sentry (self-hosted) | ~2GB |
| Nginx Proxy Manager | ~50MB |
Total sekitar 3.3GB. Pas-pasan di VPS 4GB, tapi dengan swap 2GB masih aman. Kalau budget ada, ambil VPS 8GB supaya lebih leluasa.
Untuk backup, gue pakai script sederhana yang jalan via cron tiap malam:
#!/bin/bash
# backup.sh
BACKUP_DIR="/backups/$(date +%Y-%m-%d)"
mkdir -p "$BACKUP_DIR"
# Backup semua volume Docker
docker run --rm \
-v gitea_data:/data \
-v "$BACKUP_DIR":/backup \
alpine tar czf /backup/gitea.tar.gz /data
# Backup database Gitea
docker exec gitea_db pg_dump -U gitea gitea | gzip > "$BACKUP_DIR/gitea_db.sql.gz"
# Hapus backup lebih dari 7 hari
find /backups -type d -mtime +7 -exec rm -rf {} +
echo "Backup selesai: $BACKUP_DIR"
Tambahkan ke crontab:
crontab -e
# Tambahkan:
0 2 * * * /home/ubuntu/backup.sh >> /var/log/backup.log 2>&1
Yang Gue Lakukan Setelah Setup Ini
Setelah semua service jalan, gue migrate semua repo private dari GitHub ke Gitea. GitHub masih gue pakai untuk open source project supaya tetap visible ke publik.
Drone CI gue connect ke Gitea untuk semua project internal. Pipeline-nya deploy ke server yang sama via SSH — sederhana tapi cukup.
Plausible gue pasang di semua side project. Sekarang gue tahu berapa pengunjung per hari tanpa khawatir data bocor ke Google.
Sentry gue aktifkan untuk project yang sudah production. Error langsung masuk ke Telegram via webhook — satu integrasi kecil yang sangat membantu.
Total penghematan dibanding SaaS: sekitar $120/bulan. Dalam setahun itu Rp 22 juta lebih. Cukup buat bayar VPS 15 tahun ke depan.
Kalau kamu mau mulai, jangan setup semuanya sekaligus. Mulai dari Gitea dulu, stabilkan, baru tambah service berikutnya satu per satu. Open source development tools self-hosted gratis ini butuh sedikit waktu di awal, tapi hasilnya worth it.