Ada kebiasaan kecil yang mudah terbawa: setiap kali satu server butuh kirim pesan ke ponsel kita, refleks pertama biasanya “bikin Telegram bot”. Padahal untuk keperluan sesederhana “disk hampir penuh”, “backup selesai”, atau “ada login SSH baru”, kita tidak butuh bot token, chat ID, dan library tambahan. Cukup satu alamat HTTP, dan pasang ntfy di VPS bisa mengirim semuanya ke ponsel lewat satu perintah curl. Oke, lanjuutt.. Artikel ini membahas seluruh jalurnya.
Apa itu ntfy dan kenapa cocok untuk VPS
ntfy (dibaca notify) adalah alat open-source sederhana: server kecil yang menerima pesan HTTP dan meneruskannya sebagai push notification ke aplikasi Android/iOS atau browser. Alurnya seperti kotak surat terbalik — VPS kita tinggal drop pesan ke alamat topik, dan semua perangkat yang berlangganan topik itu langsung dapat notifikasi.
Dibandingkan Telegram bot, ntfy punya beberapa kelebihan yang pas untuk pengelolaan server:
- Tanpa registrasi pihak ketiga. Server kita, datanya kita. Tidak ada token bot yang bisa dicabut orang lain.
- Topik berfungsi seperti password. Karena tidak ada sistem akun, nama topik yang sulit ditebak adalah pengaman utamanya — ntfy sendiri menyebut “the topic is essentially a password”.
- Push notification sungguhan. Aplikasi Android ntfy mendukung prioritas, tag/emoji, aksi tombol, bahkan panggilan telepon untuk pesan kritis.
- Satu perintah cukup.
curl -d "Disk 90% penuh" https://ntfy.contoh.com/alerts— selesai.
Sebelum mulai: yang perlu disiapkan
Sebelum masuk langkah, pastikan hal ini sudah ada:
- VPS dengan Docker dan Docker Compose (panduan instalasi Docker ada di banyak artikel kami sebelumnya).
- Domain atau subdomain, misalnya
ntfy.contoh.com. - Aplikasi ntfy di ponsel (Android dari F-Droid/Play Store, atau iOS dari App Store) — dipakai nanti untuk berlangganan topik.
- Reverse proxy (Nginx atau Caddy) yang sudah jalan, atau siapkan port publik langsung.
Langkah 1: Siapkan folder dan docker-compose.yml
ntfy bisa jalan cukup dengan satu baris docker run, tapi kita langsung pakai versi yang rapi — dengan cache pesan (agar pesan yang terkirim saat ponsel offline tetap bisa dibaca nanti) dan attachment cache (agar bisa kirim lampiran).
mkdir -p /opt/ntfy/data
cd /opt/ntfy
nano docker-compose.yml
Isi dengan konfigurasi berikut:
services:
ntfy:
image: binwiederhier/ntfy
container_name: ntfy
restart: unless-stopped
environment:
- TZ=Asia/Jakarta
volumes:
- ./data/cache:/var/cache/ntfy
- ./data/attachments:/var/cache/ntfy/attachments
ports:
- "2586:80"
command: serve
Dua hal penting dari berkas ini:
- Port 2586 dipilih supaya tidak bentrok dengan Nginx/Caddy atau aplikasi lain yang sudah memakai 80/443. Nanti reverse proxy kita yang menangani HTTPS.
- Volume
/var/cache/ntfydi-mount ke host supaya message cache tidak hilang saat container di-restart. Tanpa volume ini, pesan hanya hidup di memori dansince=/poll=1tidak berfungsi.
Langkah 2: Jalankan server ntfy
docker compose up -d
docker compose logs -f ntfy
Baris log yang muncul seharusnya mirip Listening on :80. Uji dari VPS itu sendiri:
curl -d "Halo dari VPS kita" http://localhost:2586/uji-pertama
Kalau tidak ada error, pesan sudah masuk ke topik uji-pertama. Buka juga http://IP-VPS:2586 di browser — itu adalah web UI ntfy tempat kita bisa berlangganan topik manual.
Langkah 3: Arahkan domain lewat reverse proxy
Untuk produksi, jangan buka port mentah. Arahkan subdomain ke ntfy lewat reverse proxy. Kalau pakai Nginx:
server {
listen 443 ssl;
server_name ntfy.contoh.com;
location / {
proxy_pass http://127.0.0.1:2586;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
}
Blok Upgrade dan Connection wajib ada karena ntfy memakai streaming untuk langganan real-time — tanpa itu, koneksi subscribe akan langsung terputus. Kalau pakai Caddy, konfigurasinya jauh lebih pendek:
ntfy.contoh.com {
reverse_proxy 127.0.0.1:2586
}
Sertifikat HTTPS diurus otomatis oleh Certbot (Nginx) atau Caddy. Jangan skip HTTPS: kalau nanti kita mengaktifkan autentikasi, password dikirim sebagai Basic auth yang hanya di-base64, jadi tanpa TLS password praktis terbaca siapa pun di jalan.
Langkah 4: Pasang aplikasi di ponsel dan berlangganan
- Instal aplikasi ntfy di ponsel (Android atau iOS).
- Di aplikasi, tekan + → Subscribe to topic.
- Isi alamat server:
https://ntfy.contoh.comdan nama topik, misalnyavps-alerts-d4f9a2. - Simpan, lalu kirim pesan uji dari VPS:
curl -H "Title: Uji notifikasi" -H "Priority: high" \
-d "Kalau notifikasi ini muncul, setup kita berhasil." \
https://ntfy.contoh.com/vps-alerts-d4f9a2
Notifikasi akan muncul di ponsel dalam hitungan detik. Perhatikan header yang dipakai: Title mengganti judul (tanpa itu judul hanya berupa URL topik), dan Priority: high membuat ponsel berbunyi dan menampilkan pop-over. Level prioritas ntfy ada lima: min, low, default, high, dan max/urgent.
Langkah 5: Amankan server dengan autentikasi
Ini bagian yang paling sering dilewatkan, padahal penting. Secara default ntfy tanpa autentikasi — siapa pun yang menebak nama topik bisa membaca maupun mengirim pesan ke sana. Untuk server produksi, kita aktifkan kontrol akses.
Pertama, tambahkan konfigurasi autentikasi ke docker-compose.yml:
environment:
- TZ=Asia/Jakarta
- NTFY_AUTH_FILE=/var/lib/ntfy/user.db
- NTFY_AUTH_DEFAULT_ACCESS=deny-all
- NTFY_BEHIND_PROXY=true
- NTFY_ENABLE_LOGIN=true
volumes:
- ./data/cache:/var/cache/ntfy
- ./data/attachments:/var/cache/ntfy/attachments
- ./data/auth:/var/lib/ntfy
Penjelasan tiap baris:
NTFY_AUTH_FILE— lokasi database user; nilainya menandakan autentikasi aktif.NTFY_AUTH_DEFAULT_ACCESS=deny-all— siapa pun yang tidak punya entri ACL ditolak. Untuk instance pribadi, dokumentasi ntfy sendiri menyarankan nilai ini.NTFY_BEHIND_PROXY=true— wajib kalau ada reverse proxy di depan. Tanpa ini, ntfy mengira semua pengunjung berasal dari satu IP (proxy kita), sehingga rate limit berlaku menyeluruh untuk semua orang — ini salah satu kesalahan konfigurasi paling umum.NTFY_ENABLE_LOGIN=true— mengizinkan login lewat web UI.
Restart container, lalu buat user dan ACL:
docker compose exec ntfy ntfy user list
docker compose exec ntfy ntfy user add --role=admin donny
docker compose exec ntfy ntfy access donny "vps-*" rw
Baris terakhir memberi user donny akses read-write ke semua topik berawalan vps- (pola wildcard * didukung). Pengguna biasa (bukan admin) perlu entri ACL seperti ini; role admin otomatis punya akses penuh ke semua topik.
Setelah itu, kirim pesan dengan kredensial:
curl -u donny:password-rahasia \
-H "Title: Login SSH baru" -H "Priority: urgent" -H "Tags: warning,skull" \
-d "Root login dari 203.0.113.10 pada $(date)" \
https://ntfy.contoh.com/vps-alerts-d4f9a2
Di ponsel, tambahkan kredensial yang sama di pengaturan langganan supaya bisa membaca topik terproteksi.
Langkah 6: Pakai access token untuk skrip otomatis
Menaruh password di setiap skrip adalah kebiasaan buruk. ntfy menyediakan access token khusus untuk ini:
docker compose exec ntfy ntfy token add --expires=365d --label=backup donny
Token yang dicetak (berformat tk_...) bisa dipakai sebagai ganti password:
curl -u :tk_xxxxxxxxxxxxxxxxxxxxxxxx \
-d "Backup selesai: 2,4 GB tersalin" \
https://ntfy.contoh.com/vps-backup
Keunggulan token: bisa dibuat satu token per skrip (backup, monitoring, deploy) dan dicabut satu per satu tanpa mengubah password utama. Satu catatan jujur dari dokumentasi ntfy: token saat ini memberikan akses penuh ke akun pemiliknya, belum granular per-topik.
Contoh nyata: notifikasi otomatis dari VPS
Kekuatan ntfy baru terasa saat dipakai bersama skrip. Tiga contoh yang langsung berguna:
1. Cek disk dalam cron. Tambahkan ke /etc/cron.daily/cek-disk:
#!/bin/bash
PAKAI=$(df / --output=pcent | tail -1 | tr -dc '0-9')
if [ "$PAKAI" -ge 85 ]; then
curl -u :tk_xxxxxxxxxxxxxxxxxxxxxxxx \
-H "Title: Disk hampir penuh" -H "Priority: urgent" -H "Tags: warning" \
-d "Partisi / sudah terpakai ${PAKAI}%" \
https://ntfy.contoh.com/vps-alerts-d4f9a2
fi
2. Notifikasi backup restic. Di akhir skrip backup (setelah restic snapshots sukses), satu curl lagi yang mengirim ringkasan hasil.
3. Alarm login SSH. Cukup tambahkan baris curl di akhir /etc/profile atau pakai modul PAM — pesan dikirim setiap ada sesi login baru.
Kenapa notifikasi saya tidak muncul? Pemecahan masalah umum
Beberapa kegagalan yang paling sering terjadi, lengkap dengan penyebabnya:
- Notifikasi tidak muncul sama sekali. Cek tiga hal berurutan: (a) nama topik di aplikasi ponsel sama persis dengan yang dikirim skrip — termasuk tanda hubung dan angka; (b) aplikasi ntfy diizinkan jalan di latar belakang oleh hemat-baterai Android; (c) pesan terkirim: jalankan ulang
curldengan-vuntuk melihat respons HTTP. - Semua notifikasi hilang setelah container restart. Volume cache belum di-mount, atau
cache-filetidak diatur. Pesan hanya hidup di memori tanpa penyimpanan persisten. - Rate limit error (HTTP 429) padahal lalu lintas kecil. Hampir selalu karena
behind-proxybelum diset. Semua pengunjung dihitung sebagai satu IP, jadi bucket limit habis cepat. - Pesan terkirim tapi ponsel tidak berbunyi. Prioritas masih
default. Naikkan kehighatauurgentuntuk alarm, dan sesuaikan setelan notifikasi per prioritas di aplikasi Android. - 401/403 di ponsel.
auth-default-access: deny-allaktif tetapi belum ada entri ACL untuk user tersebut, atau ponsel masih memakai kredensial lama. Periksa denganntfy accessdi server. - Judul notifikasi hanya berupa URL. Header
Title(atau aliast) tidak dikirim. Tambahkan-H "Title: ..."pada setiap perintah.
Tips supaya rapi dan aman
- Satu topik, satu maksud. Pisahkan
vps-alertsuntuk hal genting danvps-infountuk laporan biasa — dengan begitu kita bisa mematikan notifikasi topik info tanpa kehilangan alarm penting. - Nama topik panjang dan acak. Kombinasi huruf dan angka (misalnya
vps-alerts-d4f9a2) jauh lebih aman daripadaalerts. - Gunakan
Tagsuntuk emoji.Tags: warning,skullmembuat notifikasi jauh lebih cepat dikenali saat melintas di ponsel. - Perbarui image berkala.
docker compose pull && docker compose up -d, seperti layanan Docker lainnya. - Backup folder
data/. Di dalamnya ada database user, ACL, dan message cache — semuanya SQLite yang mudah disalin.
Kesimpulan
Notifikasi dari VPS tidak harus rumit. Dengan ntfy, satu alamat HTTPS plus satu baris curl sudah cukup untuk mengirim peringatan disk, laporan backup, atau alarm login SSH langsung ke ponsel — tanpa bot token, tanpa chat ID, dan tanpa bergantung pada layanan pihak ketiga. Kunci pengaturannya ada di dua tempat: cache persisten supaya pesan tidak hilang, dan autentikasi plus behind-proxy supaya server tidak terbuka untuk siapa saja.
Kalau server kita sudah punya cron, skrip backup, atau monitoring yang jalan, coba mulai dari satu skrip saja — misalnya cek disk harian — dan rasakan bedanya malam ini. Sisanya menyusul sendiri.

