SSD Nodes Learn Hosting plans →
Panduan Matt ConnorOleh Matt Connor · Diperbarui 2026-08-07

Cara Instal Listmonk di VPS Ubuntu 24.04

Pelajari instalasi Listmonk v6.2.0 di Ubuntu 24.04 dengan PostgreSQL, config.toml, systemd, TLS, dan SMTP, serta biaya nyata untuk menjaga keterkiriman email.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, July 30, 2026.

Kebutuhan untuk newsletter yang di-hosting sendiri dengan Listmonk

Listmonk adalah pengelola newsletter dan mailing list yang di-hosting sendiri: satu biner Go, satu database PostgreSQL, satu file konfigurasi, dan satu unit systemd. VPS kecil dapat menjalankannya tanpa kesulitan karena Listmonk menyimpan subscriber dan mengantrekan campaign, tetapi tidak pernah mengirim email itu sendiri. Listmonk meneruskan setiap pesan ke server SMTP (simple mail transfer protocol), sehingga tingkat keterkiriman ditentukan oleh reputasi server tersebut, bukan oleh software ini.

Panduan ini menginstal Listmonk v6.2.0, rilis terbaru per Juli 2026, pada Ubuntu 24.04. Anda memerlukan VPS dengan alamat IP publik, nama domain yang Anda kendalikan, dan PostgreSQL 12 atau yang lebih baru. Instalasi memerlukan waktu sekitar satu jam. Reputasi pengiriman memerlukan waktu beberapa minggu, dan bagian tersebut dibahas menjelang akhir panduan.

Instal PostgreSQL dan buat database

Ubuntu 24.04 merilis PostgreSQL 16 di repositorinya sendiri, jauh lebih baru daripada versi yang dibutuhkan Listmonk.

sudo apt update
sudo apt install -y postgresql curl
sudo systemctl enable --now postgresql

Buat role dan database dalam satu sesi psql. -v ON_ERROR_STOP=1 membuat psql keluar saat pernyataan pertama gagal, sehingga kesalahan pengetikan tidak meninggalkan konfigurasi setengah jadi yang terlihat seolah-olah sudah selesai.

sudo -u postgres psql -v ON_ERROR_STOP=1 <<'SQL'
CREATE USER listmonk WITH PASSWORD 'pick-a-long-random-password';
CREATE DATABASE listmonk OWNER listmonk;
SQL

OWNER listmonk bukan sekadar hiasan. Instalasi skema membuat tabel, tipe, indeks, dan fungsi, sehingga role harus memiliki database tersebut. Jika Listmonk diarahkan ke database yang dimiliki role lain, instalasi berhenti dengan permission denied, bahkan setelah Anda menjalankan GRANT CONNECT.

Pastikan database sudah ada sebelum melanjutkan.

sudo -u postgres psql -tAc "SELECT datname FROM pg_database WHERE datname='listmonk';"

Perintah tersebut mencetak listmonk. Baris kosong berarti pernyataan CREATE tidak pernah dijalankan, jadi baca kembali output psql.

Instal binary Listmonk

Listmonk merilis binary statis untuk setiap arsitektur. Periksa arsitektur server Anda terlebih dahulu karena binary amd64 pada VPS ARM akan ditolak kernel saat dieksekusi.

dpkg --print-architecture
cd /tmp
curl -fsSLO https://github.com/knadh/listmonk/releases/download/v6.2.0/listmonk_6.2.0_linux_amd64.tar.gz
tar -xzf listmonk_6.2.0_linux_amd64.tar.gz
sudo install -m 755 listmonk /usr/bin/listmonk
listmonk --version

Pada VPS ARM, ganti amd64 dengan arm64 pada nama file. listmonk --version yang menampilkan string versi merupakan bukti pertama bahwa binary tersebut sesuai dengan mesin.

Buat config.toml dan batasi aksesnya

--new-config menulis config.toml ke direktori kerja saat ini. Karena itu, cd berada di dalam sh -c, bukan sebelum sudo.

sudo install -d -m 750 /etc/listmonk
sudo sh -c 'cd /etc/listmonk && listmonk --new-config'

File yang dibuat berukuran kecil. Di bawah [app], address = "localhost:9000" mengikat server HTTP hanya ke loopback. Dengan demikian, panel admin tidak dapat diakses dari Internet sampai Anda menempatkan reverse proxy di depannya. Jangan mengubah baris tersebut. Di bawah [db] terdapat host = "localhost", port = 5432, user = "listmonk", database = "listmonk", dan ssl_mode = "disable". Nilai default tersebut sudah sesuai dengan database yang Anda buat. Jadi, satu-satunya baris yang harus diubah adalah baris kata sandi.

ssl_mode = "disable" sudah benar selama Postgres mendengarkan pada loopback di mesin yang sama, karena trafik tersebut tidak pernah meninggalkan mesin. Jika database dipindahkan ke host lain, ubah nilainya menjadi require. Jika tidak, kata sandi dikirim melalui jaringan dalam teks biasa.

Edit baris kata sandi di bawah [db] agar sesuai dengan role, lalu buat akun service dan batasi akses file tersebut dari login lain.

sudo useradd --system --home-dir /var/lib/listmonk --create-home --shell /usr/sbin/nologin listmonk
sudo chown -R root:listmonk /etc/listmonk
sudo chmod 640 /etc/listmonk/config.toml

Sekarang akun service dapat membaca file tersebut, sedangkan akun lain tidak dapat membacanya.

sudo -u listmonk cat /etc/listmonk/config.toml > /dev/null && echo readable
stat -c '%U:%G %a' /etc/listmonk/config.toml

Perintah pertama mencetak readable. Perintah kedua mencetak root:listmonk 640. Akun lain tanpa hak istimewa yang mencoba cat akan mendapatkan Permission denied. Inilah tujuannya: file ini menyimpan kata sandi database dalam teks biasa, dan server biasanya memiliki lebih dari satu login. Prinsip yang sama berlaku untuk setiap service yang Anda jalankan. Karena itu, baca akun service dengan hak akses minimum sekali, lalu terapkan prinsip tersebut di semua tempat.

Buat skema dengan --install

--install membuat tabel dan mengisi pengaturan default. Tetapkan login admin pertama melalui variabel lingkungan agar akun sudah tersedia sebelum panel dapat diakses.

sudo -u listmonk env LISTMONK_ADMIN_USER=admin \
  LISTMONK_ADMIN_PASSWORD='another-long-random-password' \
  listmonk --config /etc/listmonk/config.toml --install --yes

--yes menjawab prompt konfirmasi. Baca prompt tersebut sekali sebelum mengotomatiskannya, karena --install adalah installer pertama dan menghapus skema Listmonk yang sudah ada. Menjalankannya untuk kedua kali pada database aktif akan menghapus subscriber Anda. Dalam skrip apa pun yang mungkin dijalankan dua kali, gunakan --install --idempotent --yes. Perintah ini tidak melakukan apa pun jika tabel sudah tersedia. Perubahan skema yang dirilis dalam versi baru diterapkan dengan --upgrade, bukan dengan --install.

Periksa hasilnya dari sisi database, bukan melalui browser.

sudo -u postgres psql -d listmonk -c '\dt'
sudo -u postgres psql -d listmonk -tAc "SELECT username FROM users;"

Perintah pertama menampilkan tabel Listmonk, termasuk subscribers, lists, campaigns, templates, dan bounces. Perintah kedua menampilkan admin. Hasil kosong dari perintah kedua berarti variabel lingkungan tidak pernah diteruskan ke proses, sehingga panel akan meminta Anda membuat pengguna pertama melalui browser.

Jalankan Listmonk dengan systemd

Tulis /etc/systemd/system/listmonk.service.

[Unit]
Description=Listmonk newsletter and mailing list manager
After=network-online.target postgresql.service
Wants=network-online.target

[Service]
Type=simple
User=listmonk
Group=listmonk
WorkingDirectory=/var/lib/listmonk
ExecStart=/usr/bin/listmonk --config /etc/listmonk/config.toml
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true

[Install]
WantedBy=multi-user.target

WorkingDirectory penting karena Listmonk menyelesaikan path relatif, termasuk path upload media pada filesystem, terhadap direktori tersebut. After=postgresql.service hanya mengatur urutan start. Perintah ini tidak menunggu hingga Postgres menerima koneksi. Karena itu, Restart=on-failure menangani kondisi ketika Listmonk start terlalu cepat dan tidak dapat terhubung.

sudo systemctl daemon-reload
sudo systemctl enable --now listmonk
ss -ltnp | grep 9000
curl -sI http://127.0.0.1:9000/

ss harus menampilkan 127.0.0.1:9000 dalam status LISTEN. curl yang mengembalikan baris status HTTP apa pun berarti server merespons. Jika curl gagal dengan Connection refused, berarti proses berhenti selama startup. journalctl -u listmonk -n 50 --no-pager akan menjelaskan penyebabnya. Perhatikan bahwa enable --now adalah bagian yang tetap berjalan setelah reboot. Proses yang dijalankan secara manual akan berhenti setelah upgrade kernel berikutnya.

Pasang nginx dan TLS di depan

Listmonk menggunakan HTTP biasa pada loopback. Karena itu, nginx menangani terminasi TLS (transport layer security) dan meneruskan permintaan.

server {
    listen 443 ssl;
    server_name lists.example.com;

    client_max_body_size 25m;

    location / {
        proxy_pass http://127.0.0.1:9000;
        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;
    }
}

client_max_body_size harus dinaikkan karena impor pelanggan dan unggahan media merupakan pengiriman file. Secara default, nginx menolak file berukuran lebih dari 1 MB dengan 413 Request Entity Too Large. Terbitkan sertifikat menggunakan certbot. certbot juga menulis baris listen 443 ssl dan pengalihan dari port 80 untuk Anda. Langkah-langkahnya tersedia dalam panduan sertifikat Let's Encrypt untuk nginx. Buka port 80 dan 443, tetapi biarkan port 9000 tetap tertutup karena proxy mengaksesnya melalui loopback. Jika firewall belum dikonfigurasi, mulai dengan dasar-dasar firewall ufw.

Selanjutnya, buka panel admin dan tetapkan URL root pada Settings menjadi https://lists.example.com. Instalasi baru menggunakan http://localhost:9000. Listmonk menulis nilai tersebut ke setiap tautan berhenti berlangganan dan URL media yang disertakan dalam email. Jika Anda mengirim kampanye sebelum mengubahnya, setiap penerima akan menerima tautan yang mengarah ke mesin mereka sendiri. Tautan tersebut tidak berfungsi bagi penerima. Bagi filter spam, tautan itu menunjukkan bahwa pengirim tidak dapat mengonfigurasi domainnya sendiri.

Hubungkan SMTP yang tidak terdapat dalam config.toml

Cari bagian SMTP di config.toml. Anda tidak akan menemukannya. Pengaturan email disimpan dalam database, pada tabel settings, dan dapat diedit di panel admin melalui Settings dan SMTP. Karena itu, file yang dihasilkan tetap singkat. Perubahan SMTP juga tidak memerlukan restart.

Ada dua pilihan yang realistis untuk server SMTP itu sendiri. Jalankan server Anda sendiri. Dengan demikian, reputasi sepenuhnya menjadi tanggung jawab Anda, dan pengelolaannya merupakan proyek tersendiri: menjalankan server email sendiri dengan Mailcow menjelaskan hal-hal yang diperlukan. Atau arahkan Listmonk ke relay transaksional dan serahkan pengelolaan reputasi IP kepada penyedia tersebut.

Apa pun pilihannya, gunakan port 587 dengan STARTTLS atau port 465 dengan TLS implisit. Jangan mengandalkan port keluar 25. Sebagian besar penyedia VPS memblokirnya secara default pada akun baru. Port 25 yang diblokir tampak seperti koneksi yang macet karena paket dibuang, bukan ditolak. Akibatnya, klien menunggu hingga timeout, bukan gagal dengan cepat.

Uji konfigurasi sebelum menggunakannya. Buat sebuah list, tambahkan alamat Anda sendiri sebagai subscriber, lalu kirim campaign kepada satu penerima. Buka pesan yang diterima dan baca seluruh header. Header Authentication-Results yang ditambahkan oleh sisi penerima menunjukkan apakah SPF dan DKIM berhasil.

Deliverability adalah seluruh proses

Listmonk menyusun pesan, mengelola daftar, lalu menyerahkan email untuk dikirim. Semua keputusan tentang apakah email tersebut masuk ke kotak masuk dibuat oleh provider penerima, berdasarkan alamat IP pengirim dan domain pengirim. IP VPS baru belum memiliki riwayat sama sekali, dan setiap provider kotak surat besar menganggap tidak adanya riwayat sebagai indikasi yang agak mencurigakan.

Empat hal berikut wajib tersedia:

  • Record TXT SPF (sender policy framework) yang mencantumkan host yang diizinkan mengirim untuk domain Anda.
  • Kunci DKIM (domainkeys identified mail) yang dipublikasikan sebagai record TXT, dengan proses penandatanganan dilakukan oleh mail server, bukan oleh Listmonk.
  • Record DMARC (domain based message authentication, reporting and conformance), yang memberi tahu penerima tindakan yang harus dilakukan jika dua mekanisme pertama gagal.
  • Mailbox bounce yang dibaca Listmonk, sehingga alamat yang menolak email dihapus dari daftar dan tidak terus-menerus dicoba ulang.

Setelah itu, kirim email secara perlahan pada tahap awal. Domain yang belum pernah mengirim email lalu tiba-tiba mengirimkan sepuluh ribu pesan dalam satu jam memiliki pola yang sama persis dengan akun yang telah disusupi, sehingga emailnya difilter seperti itu. Mulailah dari subscriber yang paling aktif, lalu tingkatkan volumenya selama beberapa hari.

Setiap template juga memerlukan link berhenti berlangganan yang berfungsi. Dalam template Listmonk, link tersebut adalah {{ UnsubscribeURL }}, sedangkan isi campaign ditempatkan pada posisi {{ template "content" . }}, yang harus muncul tepat satu kali dalam setiap template. Campaign tanpa link berhenti berlangganan akan menghasilkan laporan spam, bukan permintaan berhenti berlangganan. Laporan spam adalah cara tercepat untuk kehilangan reputasi pengiriman yang Anda bangun selama berminggu-minggu.

Cadangan, dan kebutuhan sebenarnya untuk pemulihan

Dua hal harus disimpan di luar server: dump database dan config.toml. Tambahkan direktori media jika Anda mengunggah gambar ke dalam kampanye.

sudo -u postgres pg_dump -Fc listmonk > listmonk-$(date +%F).dump

Dump tersebut menyimpan subscriber, kampanye, template, dan semua pengaturan, termasuk kredensial SMTP. Karena itu, enkripsi dump tersebut dan simpan di luar server ini. Penjadwalan proses tersebut sudah memiliki solusi yang matang: lihat cadangan restic terenkripsi ke penyimpanan jarak jauh. config.toml hanya terdiri dari beberapa baris, tetapi menyimpan kata sandi database. Perlakukan file tersebut dengan cara yang sama.

Lakukan upgrade dalam urutan berikut. Hentikan service, buat dump, ganti binary di /usr/bin, jalankan listmonk --config /etc/listmonk/config.toml --upgrade, lalu mulai service. Migrasi skema hanya berjalan maju. Karena itu, dump tersebut adalah satu-satunya cara untuk kembali ke kondisi sebelumnya.

Mengapa Listmonk gagal dimulai?

Baca journal terlebih dahulu dengan journalctl -u listmonk -n 50 --no-pager. Hampir setiap kegagalan saat dimulai tercatat dalam satu baris pada blok [db].

pq: password authentication failed for user "listmonk" berarti kata sandi dalam [db] tidak cocok dengan role Postgres. Prefix pq menunjukkan bahwa driver Postgres melaporkan penolakan dari server. Ini berarti konfigurasi berhasil dibaca, tetapi kredensialnya salah. Reset role dengan sudo -u postgres psql -c "ALTER USER listmonk WITH PASSWORD 'new-password';", lalu masukkan string yang sama persis ke dalam file.

pq: database "listmonk" does not exist berarti nilai database dalam [db] tidak menunjuk ke database yang benar-benar ada. sudo -u postgres psql -l mencantumkan database yang tersedia di server, termasuk ejaan yang keliru Anda gunakan.

permission denied selama --install berarti role dapat terhubung, tetapi bukan pemilik database tersebut sehingga tidak dapat membuat tabel di dalamnya. Perbaiki dengan sudo -u postgres psql -c "ALTER DATABASE listmonk OWNER TO listmonk;", lalu jalankan kembali proses instalasi.

Service tidak pernah dimulai dan journal menyebutkan file konfigurasi. Proses yang berjalan sebagai listmonk tidak dapat membuka config.toml yang memiliki pemilik root:root dengan mode 600. stat -c '%U:%G %a' /etc/listmonk/config.toml seharusnya menampilkan root:listmonk 640, dan direktori di atasnya seharusnya memiliki root:listmonk 750.

Panel berfungsi, tetapi tidak ada email yang masuk. Ini bukan masalah saat service dimulai. Periksa Settings dan SMTP terlebih dahulu, lalu periksa log kampanye di panel admin. Log tersebut mencatat error yang dikembalikan server email untuk setiap percobaan.

FAQ

Apakah saya memerlukan mail server sendiri untuk menggunakan Listmonk?

Tidak. Listmonk bukan mail server. Listmonk memerlukan kredensial SMTP untuk server yang menerima email Anda dan mengirimkannya, baik transactional relay maupun mail server yang Anda kelola sendiri. Tetapkan kredensial tersebut pada Settings dan SMTP di panel admin, bukan di config.toml, karena pengaturan email disimpan dalam database. Gunakan port 587 dengan STARTTLS atau port 465 dengan implicit TLS, karena sebagian besar penyedia VPS memblokir port keluar 25 pada akun baru.

Mengapa tautan dalam campaign saya mengarah ke localhost:9000?

Pengaturan root URL masih menggunakan nilai default saat instalasi, yaitu http://localhost:9000. Listmonk menulis nilai tersebut ke dalam tautan unsubscribe dan URL media saat campaign dikirim. Buka Settings di panel admin, tetapkan root URL ke alamat HTTPS Anda yang sebenarnya, lalu simpan. Pesan yang sudah terkirim tidak dapat diperbaiki, jadi kirim campaign percobaan kepada diri sendiri dan klik tautan unsubscribe di dalamnya sebelum mengirim email ke daftar penerima yang sebenarnya.

Apakah menjalankan --install lagi akan menghapus subscriber saya?

Ya. --install adalah installer pada proses pertama dan menghapus schema Listmonk yang sudah ada, sedangkan --yes menghapus prompt yang seharusnya memperingatkan Anda. Dalam script yang mungkin dijalankan dua kali, gunakan --install --idempotent --yes, yang tidak melakukan apa pun jika tabel sudah ada. Untuk menerapkan perubahan schema pada release baru, hentikan service, buat pg_dump, lalu jalankan --upgrade.

Mengapa Listmonk menampilkan pesan password authentication failed for user listmonk?

Password dalam blok [db] pada /etc/listmonk/config.toml tidak cocok dengan role Postgres yang memiliki nama sama. Baris journal tersebut adalah pq: password authentication failed for user "listmonk", sedangkan pq adalah driver Postgres yang meneruskan penolakan dari server. Artinya, file konfigurasi berhasil ditemukan dan dibaca. Reset password role tersebut dengan sudo -u postgres psql -c "ALTER USER listmonk WITH PASSWORD 'new-password';", tulis string yang sama persis ke dalam file konfigurasi, lalu jalankan sudo systemctl restart listmonk.