Promo Domain .biz.id hanya Rp2.500 Cek domain →
JowHost
Self-Hosting

Cara Install n8n di VPS dengan Docker Compose, PostgreSQL 17, dan HTTPS Otomatis

Panduan install n8n di VPS dengan Docker Compose, PostgreSQL 17, dan HTTPS otomatis dari Caddy. Diuji di Ubuntu 24.04: siap dipakai dalam kurang dari 2 menit.

Tim JowHost 7 menit baca
Terminal berisi docker compose up untuk n8n dan sertifikat HTTPS dari Let's Encrypt
Daftar isi
  1. Yang dibutuhkan untuk install n8n di VPS
  2. Gambaran susunannya
  3. Langkah 1: buka port 80 dan 443
  4. Langkah 2: buat folder dan file .env
  5. Langkah 3: buat compose.yaml
  6. Langkah 4: buat Caddyfile
  7. Langkah 5: jalankan
  8. Langkah 6: buat akun owner
  9. Uji: webhook pertama
  10. Kenapa PostgreSQL 17, bukan 16
  11. Perawatan setelah terpasang
  12. Kalau tidak berhasil
  13. Jalur cepat tanpa install manual

Panduan install n8n di VPS ini memasang tiga komponen sekaligus: n8n, database PostgreSQL 17, dan Caddy yang mengurus HTTPS otomatis. Di server uji kami, dari perintah docker compose up sampai n8n bisa dibuka lewat https:// hanya butuh 105 detik, termasuk mengunduh image dan menerbitkan sertifikat Let's Encrypt.

Diuji 5 November 2026 di Super Cloud Regular 1 vCPU · 2 GB, Ubuntu 24.04.5 LTS, Docker 29.9.3, n8n 2.47.2, PostgreSQL 17.11, Caddy 2. Semua keluaran di bawah adalah hasil asli dari server uji.

Yang dibutuhkan untuk install n8n di VPS

  • VPS dengan RAM minimal 2 GB. Di server uji, seluruh susunan ini memakai sekitar 870 MB RAM saat diam dan 1,05 GB saat menerima 1.000 request. Rincian angkanya ada di Spesifikasi VPS untuk n8n.
  • Docker dan Docker Compose sudah terpasang. Ikuti Install Docker di Ubuntu 24.04 bila belum.
  • Subdomain yang diarahkan ke IP VPS, misalnya n8n.domainanda.com dengan record A ke IP server. Cara mengatur DNS ada di panduan nameserver dan DNS. Caddy butuh nama ini untuk mendapatkan sertifikat HTTPS.
  • Sebaiknya login SSH sudah memakai kunci, bukan password. Lihat SSH key untuk VPS.

Gambaran susunannya

Container Tugas Port ke internet
caddy Menerima HTTPS, menerbitkan dan memperbarui sertifikat Let's Encrypt, meneruskan ke n8n 80 dan 443
n8n Aplikasi n8n (editor, webhook, eksekusi workflow) tidak ada
postgres Menyimpan workflow, kredensial, dan riwayat eksekusi tidak ada

Hanya Caddy yang membuka port. n8n dan PostgreSQL hanya bisa dihubungi dari dalam jaringan Docker. Ini penting, karena port yang dipublikasikan Docker melewati firewall UFW; kami sudah membuktikannya di artikel Docker bypass UFW. Di server uji, port 5678 milik n8n memang tidak bisa dijangkau dari luar.

Langkah 1: buka port 80 dan 443

Port 80 dipakai Caddy untuk verifikasi sertifikat, port 443 untuk HTTPS:

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Urutannya penting: izinkan OpenSSH sebelum ufw enable, supaya sesi SSH Anda tidak terputus.

Langkah 2: buat folder dan file .env

sudo mkdir -p /opt/n8n && cd /opt/n8n
sudo tee .env > /dev/null <<EOF
N8N_VERSION=2.47.2
N8N_HOST=n8n.domainanda.com
POSTGRES_PASSWORD=$(openssl rand -hex 24)
N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)
EOF
sudo chmod 600 .env

Ganti n8n.domainanda.com dengan subdomain Anda. openssl rand membuat password database dan kunci enkripsi acak secara otomatis, dan chmod 600 membuat file ini hanya bisa dibaca root.

Simpan N8N_ENCRYPTION_KEY di tempat aman. Kunci ini mengenkripsi semua kredensial (token API, password) di dalam n8n. Kalau hilang, kredensial yang tersimpan tidak bisa dibaca lagi, walau database-nya masih ada.

Versi n8n sengaja ditulis jelas (2.47.2), bukan latest. Dengan begitu n8n tidak berganti versi diam-diam saat container dibuat ulang, dan Anda yang menentukan kapan update. Caranya ada di Update n8n di Docker tanpa kehilangan workflow.

Langkah 3: buat compose.yaml

services:
  postgres:
    image: postgres:17-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: n8n
    volumes:
      - postgres17_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n -d n8n"]
      interval: 10s
      timeout: 5s
      retries: 5

  n8n:
    image: docker.n8n.io/n8nio/n8n:${N8N_VERSION}
    restart: unless-stopped
    environment:
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
      DB_POSTGRESDB_DATABASE: n8n
      DB_POSTGRESDB_USER: n8n
      DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
      N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
      N8N_HOST: ${N8N_HOST}
      N8N_PROTOCOL: https
      N8N_PROXY_HOPS: 1
      WEBHOOK_URL: https://${N8N_HOST}/
      GENERIC_TIMEZONE: Asia/Jakarta
      TZ: Asia/Jakarta
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy

  caddy:
    image: caddy:2-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    environment:
      N8N_HOST: ${N8N_HOST}
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - n8n

volumes:
  postgres17_data:
  n8n_data:
  caddy_data:
  caddy_config:

Beberapa baris yang sering terlewat di tutorial lain:

  • WEBHOOK_URL: tanpa ini, n8n menampilkan alamat webhook http://localhost:5678/... yang tidak bisa dipanggil dari luar.
  • N8N_PROXY_HOPS: 1: memberi tahu n8n bahwa ada satu reverse proxy (Caddy) di depannya, sehingga alamat IP pengunjung terbaca dengan benar.
  • GENERIC_TIMEZONE: jadwal di node Schedule mengikuti jam WIB, bukan UTC.
  • depends_on dengan service_healthy: n8n baru menyala setelah PostgreSQL siap menerima koneksi.
  • Tidak ada ports: di n8n dan postgres: keduanya sengaja tidak dibuka ke internet.

Langkah 4: buat Caddyfile

{$N8N_HOST} {
    reverse_proxy n8n:5678
}

Tiga baris ini sudah cukup. Caddy membaca nama domain dari .env, meminta sertifikat ke Let's Encrypt, mengalihkan HTTP ke HTTPS, dan memperbarui sertifikat sebelum kedaluwarsa.

Langkah 5: jalankan

cd /opt/n8n
sudo docker compose up -d
sudo docker compose ps

Hasil di server uji (kolom dipersingkat):

SERVICE    STATUS          PORTS
caddy      Up              0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp
n8n        Up              5678/tcp
postgres   Up (healthy)    5432/tcp

Hanya caddy yang terhubung ke 0.0.0.0 (internet). 5678/tcp dan 5432/tcp tanpa tanda panah berarti port itu hanya berlaku di dalam jaringan Docker.

Perintah up -d selesai dalam 91 detik, sebagian besar untuk mengunduh image n8n yang ukurannya ±1,9 GB. Sekitar 14 detik kemudian https://n8n.domainanda.com/healthz sudah membalas 200 dengan sertifikat dari Let's Encrypt:

issuer=C = US, O = Let's Encrypt, CN = YE1

Langkah 6: buat akun owner

Buka https://n8n.domainanda.com di browser. n8n meminta Anda membuat akun owner (email, nama, dan password minimal 8 karakter dengan angka dan huruf besar):

Halaman Set up owner account di n8n yang baru terpasang

Segera isi halaman ini begitu n8n menyala. Selama akun owner belum dibuat, siapa pun yang membuka alamat itu lebih dulu bisa mengisinya.

Uji: webhook pertama

Di server uji kami membuat workflow sederhana: node Webhook (path uji) yang diteruskan ke node Edit Fields berisi pesan dan waktu, lalu menerbitkannya. Hasil pemanggilan dari komputer lain:

curl https://n8n.domainanda.com/webhook/uji
{"pesan":"Halo dari n8n di VPS JowHost","waktu":"2026-11-05T12:40:41.712+07:00"}

Perhatikan zona waktunya +07:00: GENERIC_TIMEZONE dan TZ sudah bekerja. Alamat yang tampil di node Webhook juga sudah https://n8n.domainanda.com/webhook/uji, bukan localhost, berkat WEBHOOK_URL.

Kami lalu mengirim 1.000 request ke webhook ini (10 sekaligus). Semuanya berhasil (200) dalam 149 detik, sekitar 6,7 request per detik di VPS 1 vCPU. Pemakaian CPU dan RAM selama uji itu kami bahas di Spesifikasi VPS untuk n8n.

Kenapa PostgreSQL 17, bukan 16

Banyak tutorial masih memakai postgres:16. Saat kami mencobanya, n8n 2.45.7 menulis peringatan ini di log saat menyala:

Postgres 16 is outside the supported range and receives compatibility support only. Upgrade to Postgres 17 or newer.

Dengan postgres:17-alpine peringatan itu hilang. Kalau Anda sudah terlanjur memakai PostgreSQL 16, cara memindahkan datanya (backup lalu restore ke PostgreSQL 17) sudah kami uji di artikel update n8n.

Kenapa tidak memakai SQLite bawaan n8n saja? Bisa, untuk coba-coba. Tetapi PostgreSQL lebih tahan menghadapi banyak eksekusi bersamaan, dan backup-nya cukup satu perintah pg_dump yang konsisten walau n8n sedang berjalan.

Perawatan setelah terpasang

  • Backup rutin: database (pg_dump), volume n8n_data, dan file .env. Di server uji, dump database berukuran 203 KB dan arsip volume 265 KB, jadi backup harian hampir tidak memakan ruang. Perintah lengkap dan uji restore-nya ada di Update n8n di Docker tanpa kehilangan workflow.
  • Riwayat eksekusi ikut disimpan. Setelah uji 1.000 request, tabel eksekusi kami berisi 1.001 baris. n8n otomatis menghapus riwayat yang lebih tua dari 14 hari (EXECUTIONS_DATA_MAX_AGE, bawaan 336 jam) atau melebihi 10.000 eksekusi (EXECUTIONS_DATA_PRUNE_MAX_COUNT). Kalau workflow Anda berjalan ribuan kali sehari, kecilkan angka itu di bagian environment n8n agar database tetap ramping.
  • Ruang disk untuk update: setiap versi image n8n berukuran ±1,9 GB. Sisakan beberapa GB kosong, lalu bersihkan image lama setelah update terbukti lancar.

Kalau tidak berhasil

  • Halaman tidak bisa dibuka atau sertifikat tidak terbit: pastikan record A subdomain sudah mengarah ke IP VPS (dig +short n8n.domainanda.com harus menampilkan IP server) dan port 80 terbuka. Lihat pesan dari Caddy dengan sudo docker compose logs caddy. Perubahan DNS kadang butuh beberapa menit sampai terbaca.
  • Muncul 502 Bad Gateway: wajar beberapa detik setelah up -d atau update, karena n8n masih menyala dan menjalankan migrasi database. Di server uji, jeda ini sekitar 11 detik. Kalau lebih dari semenit, cek sudo docker compose logs n8n.
  • Alamat webhook masih localhost: WEBHOOK_URL belum terisi atau .env tidak terbaca. Pastikan perintah dijalankan dari folder /opt/n8n, lalu ulangi sudo docker compose up -d.
  • n8n tidak mau menyala setelah .env diganti: kemungkinan N8N_ENCRYPTION_KEY berubah. n8n menyimpan salinan kunci di volume n8n_data dan menolak kunci yang berbeda. Kembalikan kunci lama dari backup .env.

Jalur cepat tanpa install manual

Kalau ingin langsung mencoba tanpa menulis file konfigurasi, saat memesan Super Cloud pilih aplikasi one-click n8n, dan n8n terpasang otomatis saat VPS pertama kali menyala. Super Cloud juga bisa dibayar per jam dari saldo, cocok untuk mencoba dulu sebelum memutuskan memakai n8n untuk pekerjaan sungguhan: server uji untuk artikel ini aktif 22 menit dan langsung kami hapus setelah selesai.

Cara manual di atas tetap berguna untuk dipahami. Kalau suatu saat n8n bermasalah, Anda tahu persis di mana file konfigurasi, volume data, dan log-nya.

Self-Hosting

Ditulis oleh

Tim JowHost

Server Specialist.

Artikel lainnya