SSD Nodes Learn 🎉 VPS dari $5.50/bln
Panduan Matt ConnorOleh Matt Connor

Cara Host Sendiri Pelayan ntfy dengan Docker Compose

Ketahui cara memasang ntfy pada VPS anda sendiri menggunakan Docker Compose dan TLS. Lindungi topik dengan ACL serta hantar amaran automatik melalui cron dan systemd.

Fungsi pelayan ntfy yang dihoskan sendiri

Pelayan ntfy yang dihoskan sendiri menukarkan HTTP POST kepada pemberitahuan tolak (push notification) pada telefon anda. Anda menerbitkan mesej menggunakan curl, dan mesej tersebut akan sampai ke aplikasi Android, aplikasi iOS, tab pelayar, atau mana-mana peranti yang boleh mengekalkan sambungan HTTP. Tiada pustaka klien yang perlu dipasang dan tiada broker mesej yang perlu dijalankan.

ntfy mengalamatkan mesej mengikut topik. Topik ialah nama dalam path URL, seperti https://ntfy.example.com/alerts, dan ia wujud sebaik sahaja seseorang menerbitkan mesej kepadanya. Dalam pemasangan lalai, sesiapa sahaja yang mengetahui nama tersebut boleh membaca dan menulis pada topik itu, itulah sebabnya dokumentasi projek itu sendiri menyamakan nama topik dengan kata laluan. Model tersebut sesuai untuk perkhidmatan awam ntfy.sh. Ia tidak sesuai untuk pelayan yang membawa maklumat kegagalan sandaran anda, jadi panduan ini akan mengaktifkan pengesahan sebelum mesej pertama dihantar.

Keperluan sebelum bermula

Anda memerlukan VPS yang menjalankan Ubuntu 24.04 atau Debian 13 dengan Docker Engine dan pemalam Compose, nama domain, serta RAM yang sangat sedikit. Cipta rekod A DNS (domain name system) yang menghala ntfy.example.com ke alamat IP awam pelayan, kemudian sahkan ia selesai diselesaikan (resolve) sebelum anda menyentuh perkara lain.

dig +short ntfy.example.com
sudo ufw allow 80,443/tcp
sudo ufw status

dig mesti memaparkan IP pelayan anda. Pengeluaran sijil gagal jika ia tidak memaparkan apa-apa, kerana pihak berkuasa sijil menyemak nama tersebut dari luar. Port 80 kekal terbuka kerana ACME (automatic certificate management environment), iaitu protokol di sebalik Let's Encrypt, menggunakannya untuk cabaran HTTP. Kontena ntfy itu sendiri tidak akan mendapat port awam.

Imej Docker tidak mengandungi fail konfigurasi, jadi anda perlu menciptanya. Setiap arahan dalam panduan ini akan membacanya. Mula-mula, cari ID pengguna dan ID kumpulan yang akan digunakan oleh kontena tersebut.

id -u
id -g
sudo install -d -o "$(id -u)" -g "$(id -g)" /etc/ntfy /var/cache/ntfy /var/lib/ntfy
sudo nano /etc/ntfy/server.yml
base-url: "https://ntfy.example.com"
listen-http: ":2586"
behind-proxy: true
cache-file: "/var/cache/ntfy/cache.db"
cache-duration: "12h"
auth-file: "/var/lib/ntfy/user.db"
auth-default-access: "deny-all"
enable-login: true
enable-signup: false

Empat daripada baris tersebut adalah sangat penting. base-url mestilah alamat HTTPS awam yang tepat, kerana ntfy membina pautan lampiran dan permintaan aplikasi web itu sendiri daripadanya; nilai yang salah akan menyebabkan aplikasi web dimuatkan tetapi gagal melakukan sebarang tindakan. listen-http: ":2586" mengikat kepada semua antara muka di dalam kontena, yang kelihatan tidak selamat tetapi sebenarnya betul: kontena mempunyai ruang nama rangkaiannya sendiri, jadi mengikat kepada 127.0.0.1 di sana akan menyebabkan port tidak dapat dicapai dari hos dan port yang diterbitkan oleh Docker tidak akan dapat disambungkan. auth-default-access: "deny-all" adalah keseluruhan postur keselamatan, kerana ia menolak baca dan tulis kepada sesiapa sahaja tanpa kebenaran yang jelas. behind-proxy: true memberitahu ntfy untuk mengambil alamat klien daripada pengepala X-Forwarded-For, supaya had kadar mengira pelawat sebenar dan bukannya mengira proksi terbalik sebagai satu klien yang sangat sibuk.

enable-login: true membolehkan aplikasi web dan aplikasi telefon mendaftar masuk dengan kata laluan. enable-signup kekal false, kerana penciptaan akaun layan diri pada pelayan peribadi adalah pintu terbuka dengan langkah tambahan.

sudo chown "$(id -u):$(id -g)" /etc/ntfy/server.yml
sudo chmod 600 /etc/ntfy/server.yml

Jalankan ntfy dengan Docker Compose

Masukkan ini ke dalam /opt/ntfy/compose.yaml, dengan menggantikan 1000:1000 menggunakan dua nombor id -u dan id -g yang dipaparkan di atas.

services:
  ntfy:
    image: binwiederhier/ntfy:v2.27.0
    container_name: ntfy
    command: serve
    user: "1000:1000"
    environment:
      - TZ=UTC
    volumes:
      - /etc/ntfy:/etc/ntfy
      - /var/cache/ntfy:/var/cache/ntfy
      - /var/lib/ntfy:/var/lib/ntfy
    ports:
      - "127.0.0.1:2586:2586"
    restart: unless-stopped
cd /opt/ntfy
sudo docker compose up -d
sudo docker compose logs ntfy
curl -s http://127.0.0.1:2586/v1/health

Pelayan yang sihat akan menjawab {"healthy":true}. Terdapat dua perincian dalam fail compose tersebut yang dibuat secara sengaja. Imej tersebut dikunci pada v2.27.0, iaitu keluaran semasa setakat Ogos 2026, bukannya latest, kerana dengan latest, docker compose pull seterusnya akan menukar versi pelayan anda dan anda hanya akan mengetahuinya melalui changelog selepas itu. Port diterbitkan sebagai 127.0.0.1:2586:2586, supaya kontena hanya boleh dicapai daripada alamat loopback hos. Jika anda menulis 2586:2586 sebaliknya, Docker akan memasukkan peraturan firewallnya sendiri mendahului peraturan anda, yang bermaksud port tersebut akan menjawab daripada internet walaupun ufw status menyatakan port tersebut ditutup.

Jika curl memaparkan Connection refused, baca log kontena. Ralat kebenaran (permission error) pada /var/lib/ntfy/user.db bermaksud baris user: tidak sepadan dengan pemilik direktori tersebut, jadi proses tidak dapat mencipta pangkalan datanya sendiri lalu ditamatkan. Panduan asas Docker Compose untuk VPS membincangkan pemilikan volum dan polisi mulakan semula dengan lebih terperinci.

Gunakan TLS dengan Caddy

Caddy meminta dan memperbaharui sijil secara automatik, yang merupakan cara paling pantas untuk mendapatkan TLS (transport layer security) yang berfungsi.

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy

Gantikan kandungan /etc/caddy/Caddyfile dengan tiga baris berikut.

ntfy.example.com {
    reverse_proxy 127.0.0.1:2586
}
sudo systemctl reload caddy
curl -s https://ntfy.example.com/v1/health

{"healthy":true} yang sama melalui HTTPS bermakna keseluruhan laluan berfungsi. 502 daripada Caddy bermakna ntfy tidak mendengar pada port tersebut: semak dengan sudo ss -lntp | grep 2586. Ralat sijil biasanya bermakna rekod DNS salah atau port 80 disekat, dan sudo journalctl -u caddy -n 50 akan menamakan punca masalah tersebut.

Jika anda sudah menjalankan nginx, salin tetapan proksi yang didokumentasikan oleh ntfy: proxy_http_version 1.1, proxy_buffering off, proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for, serta tetapkan timeout baca dan hantar sekurang-kurangnya tiga minit. Pelanggan (subscriber) membiarkan satu sambungan HTTP terbuka selagi ia mendengar, manakala nginx akan menutup sambungan upstream yang melahu selepas 60 saat secara lalai. Ini menyebabkan pelanggan menyambung semula secara berulang dan mesej yang dihantar semasa tempoh terputus itu akan hilang.

Cipta pengguna dan kunci topik

Pengesahan telah diaktifkan dan tiada sesiapa yang mempunyai akses kepada apa-apa lagi, itulah tujuannya. Cipta satu akaun pentadbir untuk diri anda dan satu akaun mesin untuk skrip. Perintah ini membaca /etc/ntfy/server.yml dari dalam kontena, itulah sebabnya fail konfigurasi dipasang sebagai volume.

sudo docker compose exec ntfy ntfy user add --role=admin admin
sudo docker compose exec ntfy ntfy user add robot
sudo docker compose exec ntfy ntfy user list

Setiap satu akan meminta kata laluan. Seorang pentadbir mengabaikan senarai akses dan boleh membaca serta menulis setiap topik, jadi simpan akaun itu untuk diri anda dan aplikasi telefon. robot ialah pengguna biasa tanpa sebarang akses sehingga anda memberikannya.

sudo docker compose exec ntfy ntfy access robot alerts write
sudo docker compose exec ntfy ntfy access robot "alerts_*" write
sudo docker compose exec ntfy ntfy access

Entri ACL (access control list) terdiri daripada pengguna, topik dan kebenaran. Topik sama ada nama literal atau corak di mana * memadankan apa sahaja, jadi alerts_* meliputi alerts_backup dan alerts_db tanpa perlu satu perintah bagi setiap hos. Kebenaran write bermaksud terbitkan sahaja, jadi token yang dicuri daripada cron job tidak boleh melanggan dan membaca semula apa yang telah dihantar. Nama pengguna khas everyone menetapkan apa yang boleh dilakukan oleh pelawat tanpa pengesahan, dan anda hanya akan menggunakannya untuk membuka sesuatu yang sengaja dijadikan awam, seperti ntfy access everyone status read.

Skrip harus membawa token, bukan kata laluan anda.

sudo docker compose exec ntfy ntfy token add robot

Perintah ini mencetak token yang bermula dengan tk_. Token mewarisi akses yang tepat seperti pengguna pemiliknya, jadi token ini boleh menerbitkan ke topik alerts dan tidak boleh melakukan perkara lain. ntfy token list menunjukkan apa yang wujud, dan ntfy token remove membatalkan token tanpa menjejaskan kata laluan pengguna.

Hantar mesej pertama anda dan buktikan kunci berfungsi

Mulakan dengan memeriksa sama ada pintu ditutup.

curl -s -o /dev/null -w '%{http_code}\n' -d "hello" https://ntfy.example.com/alerts

Perintah tersebut mencetak 403, dan 403 ialah jawapan yang betul: auth-default-access: "deny-all" menolak penerbitan tanpa nama. Sekarang, hantar mesej yang sebenar.

curl -H "Authorization: Bearer tk_REPLACE_WITH_YOUR_TOKEN" \
  -H "Title: Nightly backup finished" \
  -H "Priority: default" \
  -H "Tags: white_check_mark" \
  -d "42 GB copied in 11 minutes" \
  https://ntfy.example.com/alerts

Pelayan membalas dengan mesej yang disimpan dalam format JSON, yang menunjukkan bahawa mesej tersebut telah diterima dan bukannya diabaikan. Title ialah baris pertama yang ditebalkan. Priority berjalan dari 1 hingga 5, atau mengikut nama daripada min hingga urgent, dan ia menentukan sama ada telefon akan mengeluarkan bunyi. Tags akan menjadi emoji pada pemberitahuan apabila nama tersebut sepadan dengan kod pendek emoji yang dikenali, dan kekal sebagai teks biasa jika tidak sepadan.

Untuk memantau topik daripada terminal, strim topik tersebut:

curl -s -u admin https://ntfy.example.com/alerts/raw

curl akan meminta kata laluan. Setiap mesej tiba sebagai satu baris, dan baris kosong yang muncul sekali-sekala adalah isyarat keepalive. Membuka https://ntfy.example.com dalam pelayar dan melog masuk dengan akaun yang sama akan memberikan anda versi aplikasi web bagi strim yang sama.

Tetapkan had kadar supaya satu skrip tidak membanjiri pelayan

Secara lalai, setiap pelawat mendapat baldi sebanyak 60 permintaan, yang diisi semula pada kadar satu permintaan setiap 5 saat. Ini adalah jumlah yang banyak untuk pelayan peribadi, dan skrip yang terperangkap dalam gelung cuba semula akan menghabiskan kesemuanya. Tambahkan had pada server.yml.

visitor-request-limit-burst: 30
visitor-request-limit-replenish: "10s"
visitor-message-daily-limit: 500
sudo docker compose restart ntfy

Pelawat yang melebihi had akan menerima HTTP 429 dan bukannya mesej yang dihantar. Had ini dikira berdasarkan alamat pelawat, itulah sebabnya behind-proxy: true sangat penting: tanpanya, ntfy hanya melihat alamat Caddy, setiap klien dikira sebagai pelawat yang sama, dan satu skrip yang bising akan menghabiskan baldi yang dikongsi oleh telefon anda dan pelayan anda yang lain.

Makluman daripada cron job yang gagal

Jangan letakkan token pada baris perintah. ps aux memaparkan baris perintah penuh bagi setiap proses yang sedang berjalan kepada semua pengguna pada sistem, jadi token yang dihantar dengan -H boleh dibaca oleh mana-mana akaun tempatan selagi curl berjalan. Fail konfigurasi curl dapat mengelakkan perkara ini.

sudo install -d -m 700 /etc/ntfy-alert
printf 'header = "Authorization: Bearer tk_REPLACE_WITH_YOUR_TOKEN"\n' | sudo tee /etc/ntfy-alert/curlrc
sudo chmod 600 /etc/ntfy-alert/curlrc

Sekarang, balutkan tugasan tersebut. Simpan ini sebagai /usr/local/bin/backup-with-alert.sh dan chmod 750 fail tersebut.

#!/bin/bash
out=$(/usr/local/bin/backup.sh 2>&1)
code=$?
if [ "$code" -ne 0 ]; then
  printf '%s' "$out" | tail -c 1000 | curl -K /etc/ntfy-alert/curlrc \
    -H "Title: backup.sh failed with exit $code" \
    -H "Priority: high" \
    -H "Tags: warning" \
    --data-binary @- \
    https://ntfy.example.com/alerts
fi
exit "$code"
17 3 * * * /usr/local/bin/backup-with-alert.sh >> /var/log/backup-alert.log 2>&1

$? ditangkap pada baris tepat selepas perintah tersebut, kerana perintah seterusnya yang dijalankan akan menulis ganti output tersebut. Output tersebut melalui tail -c 1000 kerana ntfy menguatkuasakan saiz mesej maksimum dan pemberitahuan bukanlah pemapar log. exit "$code" penutup mengekalkan status asal, supaya apa-apa proses lain yang memantau tugasan ini masih dapat melihat kegagalan. Uji keseluruhan proses dengan menghalakan skrip ke /bin/false untuk satu kali pelaksanaan.

Cawangan kegagalan yang tidak pernah dilaksanakan adalah lebih buruk daripada tiada makluman, kerana ia memberi tanggapan bahawa kesunyian bermaksud kejayaan. Cron memberikan tugasan anda persekitaran yang hampir kosong dan PATH yang jauh lebih pendek daripada shell log masuk anda, jadi skrip yang berfungsi apabila anda menjalankannya secara manual boleh terhenti sebelum ia sempat mencapai baris curl. Panduan tentang sebab cron job tidak berjalan merangkumi perangkap persekitaran tersebut. Gunakan laluan mutlak (absolute paths) di mana-mana, dan baca fail log selepas pelaksanaan berjadual yang pertama dan bukannya membuat andaian.

Makluman apabila unit systemd gagal

Cron mengendalikan tugasan berjadual. Servis yang berjalan lama memerlukan OnFailure=, yang dijalankan oleh systemd setiap kali unit memasuki keadaan failed. Cipta satu unit templat dan gunakannya semula untuk setiap servis pada pelayan. Simpan fail ini sebagai /etc/systemd/system/ntfy-unit-failed@.service.

[Unit]
Description=Send an ntfy alert because %i failed

[Service]
Type=oneshot
ExecStart=/usr/local/bin/ntfy-unit-failed %i

Kemudian /usr/local/bin/ntfy-unit-failed, dengan mod 750:

#!/bin/bash
unit="$1"
journalctl -u "$unit" -n 15 --no-pager -o cat | tail -c 1000 | curl -K /etc/ntfy-alert/curlrc \
  -H "Title: $unit failed on $(hostname -s)" \
  -H "Priority: urgent" \
  -H "Tags: rotating_light" \
  --data-binary @- \
  https://ntfy.example.com/alerts

Lampirkan ia pada servis menggunakan drop-in, supaya naik taraf pakej tidak menimpa suntingan anda.

sudo systemctl edit myapp.service
[Unit]
OnFailure=ntfy-unit-failed@%n.service

%n dikembangkan kepada nama unit penuh, jadi instans tersebut menjadi ntfy-unit-failed@myapp.service, dan %i di dalam templat menghantar myapp.service kepada skrip sebagai argumen pertamanya. Inilah yang membolehkan satu templat melayani setiap unit. Buktikan ia berfungsi dengan unit yang sengaja digagalkan, disimpan sebagai /etc/systemd/system/ntfy-selftest.service.

[Unit]
Description=Deliberately failing unit
OnFailure=ntfy-unit-failed@%n.service

[Service]
Type=oneshot
ExecStart=/bin/false
sudo systemctl daemon-reload
sudo systemctl start ntfy-selftest.service

Perintah mula keluar dengan nilai bukan sifar dan mencetak Job for ntfy-selftest.service failed because the control process exited with error code, dan telefon anda sepatutnya bergetar kira-kira sesaat kemudian. Padamkan unit ujian tersebut selepas itu.

Satu perangkap perlu diberi perhatian. OnFailure= hanya berjalan apabila unit mencapai keadaan failed, dan servis dengan Restart=always mungkin tidak akan mencapainya, kerana systemd terus memulakannya semula. Unit hanya dianggap gagal setelah ia melebihi StartLimitBurst percubaan mula semula dalam tempoh StartLimitIntervalSec. Tetapkan kedua-dua nilai tersebut pada mana-mana servis yang anda ingin pantau, atau gelung ranap akan berlaku secara senyap selama berhari-hari. Timer adalah pengganti yang lebih bersih untuk corak cron di atas, memandangkan unit servis timer mendapat OnFailure= secara automatik, dan panduan mengenai servis dan timer systemd pada VPS menerangkan langkah-langkah penukarannya.

Sambungkan pemantau masa aktif ke topik yang sama

Uptime Kuma, pemantau status yang dihoskan sendiri, menyertakan jenis pemberitahuan ntfy. Buka Settings, kemudian Notifications, seterusnya Setup Notification, pilih Ntfy, tetapkan URL pelayan kepada https://ntfy.example.com dan topik kepada alerts, pilih keutamaan, dan tampal token akses robot. Hantar pemberitahuan ujian sebelum anda menyimpan, kerana nama topik yang salah akan gagal secara senyap pada pemberian write yang tidak meliputinya.

Had sebenar aturan ini: pemantau yang berjalan pada VPS yang sama tidak dapat memberitahu anda bahawa VPS tersebut tergendala, dan ntfy tidak dapat menyampaikan berita bahawa ntfy sendiri tergendala. Jalankan pemantau pada mesin yang berbeza, dan berikan saluran pemberitahuan kedua, seperti e-mel, untuk pemantau yang memerhati ntfy itu sendiri. Jenis pemantau Push pada Uptime Kuma meliputi titik buta yang lain: tugas cron anda memanggil URL push selepas pelaksanaan yang berjaya, dan Kuma memberi amaran apabila panggilan tersebut berhenti diterima. Cawangan kegagalan hanya dicetuskan apabila tugas dijalankan, jadi ia tidak memberikan maklumat tentang tugas yang tidak pernah bermula.

Adakah ntfy yang dihoskan sendiri berfungsi pada Android dan iPhone?

Pada Android, ya, tanpa syarat. Pasang aplikasi daripada Google Play atau F-Droid, buka Settings, tetapkan pelayan lalai kepada https://ntfy.example.com, tambah akaun anda di bawah skrin pengurusan pengguna, kemudian langgan alerts. Penghantaran segera (instant delivery) memastikan perkhidmatan latar depan berjalan supaya mesej sampai walaupun telefon berada dalam mod doze, dan pemberitahuan kekal yang disertakan adalah keperluan Android untuk perkhidmatan latar depan, bukannya pepijat. Binaan F-Droid tidak mengandungi kod Firebase langsung, jadi setiap langganan menggunakan penghantaran segera. ntfy juga boleh bertindak sebagai pengedar UnifiedPush, pengganti terbuka untuk perkhidmatan push Google, supaya aplikasi lain yang menyokong UnifiedPush boleh menghantar melalui pelayan anda juga.

Pada iOS, ia berfungsi dengan satu kebergantungan yang tidak boleh anda alih keluar. Apple hanya mengejutkan aplikasi di latar belakang melalui APNs (Apple push notification service), dan hanya pihak yang memegang kelayakan penandatangan aplikasi boleh menghantar kepadanya, jadi pelayan anda tidak mempunyai cara untuk mencapai aplikasi secara terus. ntfy menyelesaikan perkara ini dengan geganti (relay): pelayan anda menghantar poll_request yang mengandungi ID mesej kepada ntfy.sh, yang kemudiannya memajukan mesej tersebut melalui Firebase dan APNs untuk mengejutkan aplikasi, dan aplikasi tersebut kemudiannya mengambil kandungan mesej daripada pelayan anda.

upstream-base-url: "https://ntfy.sh"

Fahami kos yang terlibat. Kandungan mesej kekal pada pelayan anda, tetapi fakta bahawa mesej telah sampai, serta ID mesej tersebut, melalui infrastruktur yang tidak anda kendalikan. Tanpa tetapan ini, pemberitahuan pada iPhone daripada pelayan yang dihoskan sendiri akan sampai lewat atau tidak sampai langsung, kerana tiada apa yang mengejutkan aplikasi tersebut. Satu-satunya cara untuk membuang geganti tersebut adalah dengan membina dan mengedarkan aplikasi iOS sendiri menggunakan akaun pembangun Apple anda sendiri dan kunci APNs anda sendiri, yang bermaksud yuran tahunan dan pembinaan semula untuk setiap kemas kini. Jika geganti tersebut tidak boleh diterima untuk kegunaan anda, kekalkan makluman pada Android atau aplikasi web desktop.

Sandaran, naik taraf dan menetapkan versi imej

Dua laluan tidak boleh dijana semula: /etc/ntfy/server.yml dan /var/lib/ntfy/user.db. Fail kedua mengandungi setiap pengguna, hash kata laluan, entri ACL dan token, jadi kendalikannya seperti kunci peribadi.

sudo tar czf ntfy-backup.tgz -C / etc/ntfy var/lib/ntfy
sudo chmod 600 ntfy-backup.tgz

Salin fail tersebut keluar dari pelayan. cache.db hanya menyimpan mesej terkini, iaitu 12 jam mesej dengan cache-duration di atas, jadi kehilangannya tidak menjejaskan apa-apa yang perlu dilindungi. Proses naik taraf bermaksud menyunting tag dalam fail compose dan melakukan pull.

sudo docker compose pull
sudo docker compose up -d
curl -s https://ntfy.example.com/v1/health

Baca nota keluaran terlebih dahulu. Pangkalan data SQLite akan berhijrah semasa permulaan, jadi kembali kepada tag lama selepas perubahan skema adalah tidak selamat. Simpan sandaran yang baru anda buat sehingga versi baharu telah berjalan selama satu hari.

Gotify dan Apprise

Gotify ialah pilihan yang lebih kecil: satu binari dengan UI web dan aplikasi Android, tiada wildcard topik dan tiada klien iOS rasmi, yang sesuai untuk pelayan peribadi di mana Android menjadi satu-satunya sasaran. Apprise ialah pustaka Python dan alat baris perintah dan bukannya pelayan, dan ia menyebarkan satu mesej kepada lebih daripada seratus perkhidmatan termasuk ntfy, yang sesuai untuk skrip yang perlu mencapai beberapa tempat serentak. ntfy ialah perkhidmatan yang menyediakan pelayan, API HTTP dan aplikasi pada kedua-dua platform mudah alih, itulah sebabnya ia merupakan jawapan biasa untuk pemberitahuan daripada pelayan sewaan.

FAQ

Mengapakah penerbitan ke pelayan ntfy saya menghasilkan ralat 403?

Dengan auth-default-access: "deny-all" dalam server.yml, penerbitan tanpa nama akan ditolak, dan itu adalah tingkah laku yang sepatutnya. Hantar kelayakan dengan -u user:pass atau -H "Authorization: Bearer tk_...". Jika anda sudah menghantar token dan masih menerima 403, pengguna di sebalik token tersebut tidak mempunyai entri ACL yang sepadan untuk topik berkenaan. Jalankan ntfy access untuk mencetak senarai penuh. Ingat bahawa kebenaran write tidak membenarkan langganan, jadi akaun yang boleh menerbitkan mesej dengan baik masih akan ditolak apabila ia cuba membaca topik yang sama.

Adakah pemberitahuan berfungsi pada iPhone dengan pelayan ntfy yang dihoskan sendiri?

Ia berfungsi melalui geganti (relay) yang tidak dapat dielakkan. Apple hanya mengejutkan aplikasi melalui APNs (Apple push notification service), dan hanya penerbit aplikasi yang boleh menghantar kepadanya, jadi ntfy memajukan poll_request yang mengandungi ID mesej ke ntfy.sh, yang kemudiannya menyampaikannya ke peranti. Tetapkan upstream-base-url: "https://ntfy.sh" dalam server.yml dan mulakan semula kontena. Kandungan mesej itu sendiri masih diambil daripada pelayan anda. Tanpa tetapan tersebut, pemberitahuan iOS akan tertangguh atau tidak muncul langsung.

Mengapakah makluman ntfy daripada cron job saya tidak pernah sampai?

Jalankan baris curl secara berasingan terlebih dahulu untuk membuktikan bahawa token dan topik adalah betul. Jika ia berfungsi secara manual tetapi tidak daripada cron, kegagalan tersebut berlaku sebelum makluman dihantar: cron menjalankan tugas dengan persekitaran minimum dan PATH yang singkat, jadi skrip yang memanggil arahan dengan nama ringkas boleh terhenti sebelum sampai ke baris curl. Gunakan laluan mutlak (absolute paths), alihkan output tugas ke fail log, dan baca fail tersebut selepas pelaksanaan seterusnya. Respons 429 dan bukannya penghantaran bermakna had kadar (rate limit) sedang berfungsi dan skrip anda mencuba semula terlalu pantas.

Patutkah saya mendedahkan ntfy pada internet awam?

Aplikasi telefon perlu mencapainya daripada rangkaian mudah alih, jadi titik akhir HTTPS awam dengan auth-default-access: "deny-all" dan ACL setiap topik adalah persediaan biasa, dan ia selamat selagi tiada topik yang boleh dibaca oleh everyone. Instans yang hanya melalui VPN adalah munasabah apabila setiap pelanggan adalah mesin yang anda kawal. Ia kurang sesuai untuk telefon, kerana aplikasi hanya menerima data semasa terowong aktif, jadi makluman akan beratur sehingga telefon menyambung semula.