Cara paling stabil menginstal n8n di VPS Ubuntu adalah menggunakan Docker Compose dengan database PostgreSQL, file .env untuk secret, dan reverse proxy Nginx. Setup ini mengamankan credential enkripsi, mencegah database bloat, membatasi ukuran log, serta menyediakan fondasi production-ready untuk automation jangka panjang.
n8n Cloud vs Self-Hosted: Mana yang Tepat?
Sebelum menginstal, evaluasi kebutuhan Anda. Jika volume workflow masih rendah dan Anda tidak ingin repot mengelola server, n8n Cloud lebih praktis. Namun, ketika volume meningkat, Anda butuh kontrol penuh atas data, atau ingin menjalankan AI Agent dengan local LLM, self-hosted di VPS adalah pilihan yang jauh lebih ekonomis dan fleksibel.
| Faktor | n8n Cloud | Self-Hosted VPS |
|---|---|---|
| Biaya | Berbasis eksekusi (mahal di volume tinggi) | Fixed cost VPS ($5-$20/bulan) |
| Maintenance | Zero | Backup, update, monitoring |
| Data Control | Terbatas di server n8n | Penuh di server Anda |
| AI Flexibility | Hanya provider resmi | Bisa pakai local LLM (Ollama) |
Spesifikasi VPS & Struktur Folder
Memilih spesifikasi VPS yang tepat mencegah masalah Out of Memory (OOM) di kemudian hari.
| Use Case | CPU | RAM | Database |
|---|---|---|---|
| Personal / Testing | 1 vCPU | 1 GB | SQLite / Postgres |
| Small Business | 2 vCPU | 2 GB | PostgreSQL |
| Production | 2 vCPU | 4 GB | PostgreSQL |
| AI Agent / Heavy | 4+ vCPU | 8 GB+ | PostgreSQL |
Sebelum mulai, siapkan struktur folder yang rapi di VPS Anda agar mudah di-backup dan di-maintain:
~/n8n-docker/
├── .env # Menyimpan password & encryption key
├── docker-compose.yml # Konfigurasi container
├── backups/ # Direktori untuk script backup lokal
└── scripts/ # Script custom (backup, restore, dll)
Mengapa Docker Compose & PostgreSQL?
Instalasi via NPM (npm install n8n -g) sangat rapuh terhadap update sistem Ubuntu. Docker Compose mengisolasi environment, memudahkan migrasi, dan mencegah dependency hell.
Untuk database, default n8n menggunakan SQLite. SQLite masih acceptable untuk penggunaan pribadi dengan trafik rendah. Namun, untuk production, SQLite akan mengalami write-lock dan timeout saat menerima banyak webhook bersamaan. PostgreSQL menangani konkurensi dengan row-level locking, menjadikannya standar wajib untuk environment produksi.
Langkah 1: Setup Docker & File .env
Update sistem dan instal Docker resmi:
sudo apt update && sudo apt upgrade -y
sudo apt install ca-certificates curl gnupg -y
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
sudo usermod -aG docker $USER && newgrp docker
Buat direktori proyek dan file .env. Penting: Jangan taruh password langsung di docker-compose.yml.
mkdir -p ~/n8n-docker/{backups,scripts} && cd ~/n8n-docker
nano .env
Salin konfigurasi berikut. Generate string acak untuk N8N_ENCRYPTION_KEY menggunakan perintah openssl rand -base64 32 di terminal.
# Database Configuration
POSTGRES_USER=n8n
POSTGRES_PASSWORD=GantiDenganPasswordKuat123!
POSTGRES_DB=n8n
# n8n Encryption (WAJIB DISIMPAN AMAN)
# String ini mengenkripsi semua credential (API Key, OAuth) di n8n.
# Jika hilang, credential yang tersimpan tidak bisa dipulihkan.
N8N_ENCRYPTION_KEY=GantiDenganStringAcakPanjangDariOpenSSL1234567890
Langkah 2: Konfigurasi docker-compose.yml
Buat file docker-compose.yml di direktori yang sama.
version: "3.8"
services:
postgres:
image: postgres:15-alpine
restart: always
env_file:
- .env
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER}']
interval: 5s
timeout: 5s
retries: 10
logging:
options:
max-size: "10m"
max-file: "3"
n8n:
image: docker.n8n.io/n8nio/n8n:1.70.0 # Gunakan fixed version, hindari :latest
restart: always
env_file:
- .env
ports:
- "127.0.0.1:5678:5678" # Hanya izinkan akses lokal
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
- DB_POSTGRESDB_USER=${POSTGRES_USER}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
# Security & Encryption
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
# URL & Webhook (WAJIB SINKRON)
- N8N_HOST=otomasi.domainanda.com
- N8N_PORT=5678
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://otomasi.domainanda.com/
# Resource Optimization
- EXECUTIONS_DATA_PRUNE=true
- EXECUTIONS_DATA_MAX_AGE=168 # Hapus data > 7 hari
- EXECUTIONS_DATA_PRUNE_MAX_COUNT=10000
- NODE_OPTIONS=--max-old-space-size=1024 # Sesuaikan RAM (512 untuk 1GB, 2048 untuk 4GB)
- N8N_DEFAULT_BINARY_DATA_MODE=filesystem
volumes:
- n8n_data:/home/node/.n8n
- n8n_binaryData:/home/node/.n8n/binaryData
depends_on:
postgres:
condition: service_healthy
logging:
options:
max-size: "10m"
max-file: "3"
volumes:
postgres_data:
n8n_data:
n8n_binaryData:
Catatan Penting:
- Fixed Version (1.70.0): Mencegah Docker menarik versi mayor baru yang memiliki breaking changes saat container di-restart.
- Log Rotation: Blok
loggingmembatasi ukuran log container agar tidak memenuhi disk VPS. - Bind Localhost: Port
127.0.0.1:5678memastikan n8n hanya bisa diakses melalui reverse proxy, bukan langsung dari internet.
Langkah 3: Reverse Proxy Nginx & SSL
Install Nginx dan Certbot:
sudo apt install nginx certbot python3-certbot-nginx -y
Buat konfigurasi Nginx:
sudo nano /etc/nginx/sites-available/n8n
server {
listen 80;
server_name otomasi.domainanda.com;
location / {
proxy_pass http://127.0.0.1:5678;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900s;
}
}
Aktifkan dan dapatkan SSL gratis dari Let’s Encrypt:
sudo ln -s /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl restart nginx
sudo certbot --nginx -d otomasi.domainanda.com
Security Hardening: UFW, Fail2Ban, & 2FA
Jangan biarkan VPS Anda terbuka tanpa perlindungan.
1. Aktifkan Firewall (UFW):
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable
2. Install Fail2Ban:
Memblokir IP yang melakukan brute force SSH secara otomatis.
sudo apt install fail2ban -y
sudo systemctl enable fail2ban
3. Aktifkan 2FA di n8n:
Setelah container berjalan, akses domain Anda, buat akun Owner, dan wajib mengaktifkan Two-Factor Authentication (2FA) dari menu pengaturan profil.
Troubleshooting Error Paling Umum di Production
1. Webhook Mengembalikan Error 404 atau Timeout
Penyebab: Variabel WEBHOOK_URL tidak sinkron dengan N8N_HOST, atau Nginx tidak meneruskan header dengan benar.
Solusi: Pastikan WEBHOOK_URL diakhiri dengan trailing slash (/) dan gunakan protokol https. Pastikan proxy_set_header Host $host; dan X-Forwarded-Proto aktif di Nginx.
2. n8n Container Mengalami Restart Loop
Penyebab: Node.js kehabisan memori (OOM) atau PostgreSQL belum siap.
Solusi: Cek log dengan docker compose logs n8n. Jika OOM, naikkan nilai NODE_OPTIONS atau upgrade RAM VPS. Pastikan healthcheck PostgreSQL sudah dikonfigurasi.
3. PostgreSQL Authentication Failed
Penyebab: Password di .env diubah setelah volume database pertama kali dibuat.
Solusi: PostgreSQL hanya membaca password saat inisialisasi pertama. Jika Anda mengubah password, Anda harus menghapus volume PostgreSQL (docker volume rm n8n-docker_postgres_data) — peringatan: ini menghapus data. Selalu backup sebelum melakukan ini.
4. Credential Decryption Error
Penyebab: Variabel N8N_ENCRYPTION_KEY hilang atau berubah saat migrasi server.
Solusi: n8n mengenkripsi semua credential menggunakan key ini. Jika key hilang permanen, credential yang tersimpan tidak bisa dipulihkan dan harus diisi ulang. Selalu simpan key ini di password manager.
Strategi Backup, Restore, & Upgrade
Backup Otomatis:
Buat script di folder scripts/ yang menjalankan pg_dump untuk database dan menyalin volume n8n_data. Jadwalkan dengan cron job harian, dan gunakan rclone untuk mengirim hasil backup ke offsite storage (AWS S3/Backblaze B2).
Upgrade Strategy:
Karena menggunakan fixed version, proses upgrade sangat terkontrol:
- Backup database dan volume.
- Ubah angka versi di
docker-compose.yml(misal1.70.0ke1.71.0). - Jalankan
docker compose pulldandocker compose up -d. - Baca release notes di GitHub n8n untuk mengecek breaking changes.
Bonus: Monitoring & AI Agent
Untuk monitoring sederhana, tambahkan Uptime Kuma ke dalam docker-compose.yml Anda. Tool ini ringan, mudah di-setup, dan bisa mengirimkan notifikasi ke Telegram atau Email jika endpoint /healthz n8n mengalami downtime.
Di tahun 2026, n8n juga berevolusi menjadi platform orkestrasi AI Agent. Dengan native integration ke OpenAI, Claude, Gemini, dan Ollama (untuk local LLM), Anda dapat membangun pipeline RAG atau Telegram bot AI yang berjalan sepenuhnya di VPS Anda, menjaga kerahasiaan data perusahaan tanpa bergantung pada platform pihak ketiga.
FAQ
Mengapa webhook n8n terus mengembalikan error 404?
Penyebab utama adalah ketidakcocokan variabel WEBHOOK_URL dan N8N_HOST. URL di konfigurasi harus persis sama dengan URL publik, termasuk protokol https dan trailing slash (/) di akhir. Pastikan juga Nginx meneruskan header X-Forwarded-Proto.
Apa penyebab n8n container mengalami restart loop?
Biasanya disebabkan oleh Out of Memory (OOM) karena Node.js mengonsumsi seluruh RAM VPS, atau PostgreSQL belum siap saat n8n mencoba koneksi. Cek log dengan docker compose logs n8n. Jika OOM, batasi RAM dengan NODE_OPTIONS atau upgrade VPS.
Bagaimana cara mengatasi error “Credential could not be decrypted”?
Error ini terjadi karena variabel N8N_ENCRYPTION_KEY hilang, berubah, atau berbeda saat Anda memindahkan n8n ke server baru. Jika key ini hilang permanen, credential yang tersimpan tidak bisa dipulihkan dan harus diisi ulang.
Apakah saya harus menggunakan tag :latest untuk image Docker n8n?
Sangat disarankan menggunakan fixed version (contoh: 1.70.0) di production. Tag :latest bisa menarik versi mayor yang memiliki breaking changes dan merusak workflow Anda secara tiba-tiba saat container di-restart.
Bagaimana cara membackup n8n secara otomatis?
Gunakan cron job untuk menjalankan pg_dump bagi database PostgreSQL, dan backup direktori volume n8n_data. Simpan file backup ke offsite storage seperti AWS S3 menggunakan rclone untuk mencegah kehilangan data jika VPS mati total.
Berapa minimal spesifikasi RAM untuk VPS n8n?
Minimal 2GB RAM untuk setup dengan PostgreSQL. Untuk AI workflows atau high-volume production, 4GB+ direkomendasikan. Untuk penggunaan ringan dengan SQLite, 1GB masih bisa berjalan tapi berisiko crash saat payload besar.





