ntfy/server/index.gohtml
2021-11-29 09:34:43 -05:00

418 lines
22 KiB
Plaintext

{{- /*gotype: heckel.io/ntfy/server.indexPage*/ -}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ntfy.sh | simple HTTP-based pub-sub</title>
<link rel="stylesheet" href="static/css/app.css" type="text/css">
<!-- Mobile view -->
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="HandheldFriendly" content="true">
<!-- Mobile browsers, background color -->
<meta name="theme-color" content="#317f6f">
<meta name="msapplication-navbutton-color" content="#317f6f">
<meta name="apple-mobile-web-app-status-bar-style" content="#317f6f">
<!-- Favicon, see favicon.io -->
<link rel="icon" type="image/png" href="static/img/favicon.png">
<!-- Previews in Google, Slack, WhatsApp, etc. -->
<meta property="og:type" content="website" />
<meta property="og:locale" content="en_US" />
<meta property="og:site_name" content="ntfy.sh" />
<meta property="og:title" content="ntfy.sh | simple HTTP-based pub-sub" />
<meta property="og:description" content="ntfy is a simple HTTP-based pub-sub notification service. It allows you to send desktop notifications via scripts from any computer, entirely without signup or cost. Made with ❤ by Philipp C. Heckel, Apache License 2.0, source at https://heckel.io/ntfy." />
<meta property="og:image" content="/static/img/ntfy.png" />
<meta property="og:url" content="https://ntfy.sh" />
{{if .Topic}}
<!-- Never index topic page -->
<meta name="robots" content="noindex, nofollow" />
{{end}}
</head>
<body>
<div id="header"><div id="headerBox"><img src="static/img/ntfy.png" alt="ntfy"/></div></div>
<div id="main"{{if .Topic}} style="display: none"{{end}}>
<h1>ntfy.sh | simple HTTP-based pub-sub</h1>
<p>
<b>ntfy</b> (pronounce: <i>notify</i>) is a simple HTTP-based <a href="https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern">pub-sub</a> notification service.
It allows you to send notifications to your phone or desktop via scripts from any computer,
entirely <b>without signup, cost or setup</b>. It's also <a href="https://github.com/binwiederhier/ntfy">open source</a> if you want to run your own.
</p>
<div id="screenshots">
<a href="static/img/screenshot-curl.png"><img src="static/img/screenshot-curl.png"/></a>
<a href="static/img/screenshot-web-detail.png"><img src="static/img/screenshot-web-detail.png"/></a>
<span class="nowrap">
<a href="static/img/screenshot-phone-main.jpg"><img src="static/img/screenshot-phone-main.jpg"/></a>
<a href="static/img/screenshot-phone-detail.jpg"><img src="static/img/screenshot-phone-detail.jpg"/></a>
<a href="static/img/screenshot-phone-notification.jpg"><img src="static/img/screenshot-phone-notification.jpg"/></a>
</span>
</div>
<p>
There are many ways to use it: Notify yourself when a build finishes, when an rsync is done or a backup fails,
or know when somebody logs into your server. There are <a href="#examples">many more examples</a>, endless possibilities 😀.
</p>
<h2 id="publish" class="anchor">Publishing messages</h2>
<p>
Publishing messages can be done via PUT or POST. Topics are created on the fly by subscribing or publishing to them.
Because there is no sign-up, <b>the topic is essentially a password</b>, so pick something that's not easily guessable.
</p>
<p class="smallMarginBottom">
Here's an example showing how to publish a message using a POST request (via <tt>curl -d</tt>):
</p>
<code>
curl -d "Backup successful 😀" <span class="ntfyUrl">ntfy.sh</span>/mytopic
</code>
<p class="smallMarginBottom">
Here's an example in JS with <tt>fetch()</tt> (see <a href="https://github.com/binwiederhier/ntfy/tree/main/examples">full example</a>):
</p>
<code>
fetch('https://<span class="ntfyUrl">ntfy.sh</span>/mytopic', {<br/>
&nbsp;&nbsp;method: 'POST', // PUT works too<br/>
&nbsp;&nbsp;body: 'Hello from the other side.'<br/>
})
</code>
<p class="smallMarginBottom">
There are <a href="#other-features">more features</a> related to publishing messages: You can set a
<a href="#priority">notification priority</a>, a <a href="#title">title</a>, and <a href="#tags">tag messages</a>.
Here's an example using all of them:
</p>
<code>
curl \<br/>
&nbsp;&nbsp;-H "Title: Unauthorized access detected" \<br/>
&nbsp;&nbsp;-H "Priority: urgent" \<br/>
&nbsp;&nbsp;-H "Tags: warning,skull" \<br/>
&nbsp;&nbsp;-d "Remote access to $(hostname) detected. Act right away." \<br/>
&nbsp;&nbsp;<span class="ntfyUrl">ntfy.sh</span>/mytopic
</code>
<h2 id="subscribe" class="anchor">Subscribe to a topic</h2>
<p>
You can create and subscribe to a topic either in this web UI, or in your own app by subscribing to an
<a href="https://developer.mozilla.org/en-US/docs/Web/API/EventSource">EventSource</a>, a JSON feed, or raw feed.
</p>
<div id="subscribeBox">
<h3 id="subscribe-web" class="anchor">Subscribe in this Web UI</h3>
<p id="error"></p>
<p>
Subscribe to topics here and receive messages as <b>desktop notification</b>. Topics are not password-protected,
so choose a name that's not easy to guess. Once subscribed, you can publish messages via PUT/POST.
</p>
<form id="subscribeForm">
<p>
<b>Topic:</b><br/>
<input type="text" id="topicField" autocomplete="off" placeholder="Topic name, e.g. phil_alerts" maxlength="64" pattern="[-_A-Za-z0-9]{1,64}" />
<button id="subscribeButton">Subscribe</button>
</p>
<p id="topicsHeader"><b>Subscribed topics:</b></p>
<ul id="topicsList"></ul>
</form>
<audio id="notifySound" src="static/sound/mixkit-message-pop-alert-2354.mp3"></audio>
</div>
<h3 id="subscribe-phone" class="anchor">Subscribe from your phone</h3>
<p>
You can use the <a href="https://play.google.com/store/apps/details?id=io.heckel.ntfy">Ntfy Android App</a>
to receive notifications directly on your phone. Just like the server, this app is also <a href="https://github.com/binwiederhier/ntfy-android">open source</a>.
Since I don't have an iPhone or a Mac, I didn't make an iOS app yet. I'd be awesome if <a href="https://github.com/binwiederhier/ntfy/issues/4">someone else could help out</a>.
</p>
<p>
<a href="https://play.google.com/store/apps/details?id=io.heckel.ntfy"><img src="static/img/badge-googleplay.png"></a>
<a href="https://github.com/binwiederhier/ntfy/issues/4"><img src="static/img/badge-appstore.png"></a>
</p>
<h3 id="subscribe-api" class="anchor">Subscribe via your app, or via the CLI</h3>
<p class="smallMarginBottom">
Using <a href="https://developer.mozilla.org/en-US/docs/Web/API/EventSource">EventSource</a> in JS, you can consume
notifications like this (see <a href="example.html">live example</a>):
</p>
<code>
const eventSource = new EventSource('<span class="ntfyProtocol">https://</span><span class="ntfyUrl">ntfy.sh</span>/mytopic/sse');<br/>
eventSource.onmessage = (e) => {<br/>
&nbsp;&nbsp;// Do something with e.data<br/>
};
</code>
<p class="smallMarginBottom">
You can also use the same <tt>/sse</tt> endpoint via <tt>curl</tt> or any other HTTP library:
</p>
<code>
$ curl -s <span class="ntfyUrl">ntfy.sh</span>/mytopic/sse<br/>
event: open<br/>
data: {"id":"weSj9RtNkj","time":1635528898,"event":"open","topic":"mytopic"}<br/><br/>
data: {"id":"p0M5y6gcCY","time":1635528909,"event":"message","topic":"mytopic","message":"Hi!"}<br/><br/>
event: keepalive<br/>
data: {"id":"VNxNIg5fpt","time":1635528928,"event":"keepalive","topic":"test"}
</code>
<p class="smallMarginBottom">
To consume JSON instead, use the <tt>/json</tt> endpoint, which prints one message per line:
</p>
<code>
$ curl -s <span class="ntfyUrl">ntfy.sh</span>/mytopic/json<br/>
{"id":"SLiKI64DOt","time":1635528757,"event":"open","topic":"mytopic"}<br/>
{"id":"hwQ2YpKdmg","time":1635528741,"event":"message","topic":"mytopic","message":"Hi!"}<br/>
{"id":"DGUDShMCsc","time":1635528787,"event":"keepalive","topic":"mytopic"}
</code>
<p class="smallMarginBottom">
Or use the <tt>/raw</tt> endpoint if you need something super simple (empty lines are keepalive messages):
</p>
<code>
$ curl -s <span class="ntfyUrl">ntfy.sh</span>/mytopic/raw<br/>
<br/>
This is a notification<br/>
And another one with a smiley face 😀
</code>
<h2 id="other-features" class="anchor">Other features</h2>
<h3 id="fetching-cached-messages" class="anchor">Fetching cached messages (<tt>since=</tt>)</h3>
<p class="smallMarginBottom">
Messages are cached on disk for {{.CacheDuration}} to account for network interruptions of subscribers.
You can read back what you missed by using the <tt>since=</tt> query parameter. It takes either a
duration (e.g. <tt>10m</tt> or <tt>30s</tt>), a Unix timestamp (e.g. <tt>1635528757</tt>) or <tt>all</tt> (all
cached messages).
</p>
<code>
curl -s "<span class="ntfyUrl">ntfy.sh</span>/mytopic/json?since=10m"
</code>
<h3 id="polling" class="anchor">Polling (<tt>poll=1</tt>)</h3>
<p class="smallMarginBottom">
You can also just poll for messages if you don't like the long-standing connection using the <tt>poll=1</tt>
query parameter. The connection will end after all available messages have been read. This parameter can be
combined with <tt>since=</tt> (defaults to <tt>since=all</tt>).
</p>
<code>
curl -s "<span class="ntfyUrl">ntfy.sh</span>/mytopic/json?poll=1"
</code>
<h3 id="multiple-topics" class="anchor">Subscribing to multiple topics (<tt>topic1,topic2,...</tt>)</h3>
<p class="smallMarginBottom">
It's possible to subscribe to multiple topics in one HTTP call by providing a
comma-separated list of topics in the URL. This allows you to reduce the number of connections you have to maintain:
</p>
<code>
$ curl -s <span class="ntfyUrl">ntfy.sh</span>/mytopic1,mytopic2/json<br/>
{"id":"0OkXIryH3H","time":1637182619,"event":"open","topic":"mytopic1,mytopic2,mytopic3"}<br/>
{"id":"dzJJm7BCWs","time":1637182634,"event":"message","topic":"mytopic1","message":"for topic 1"}<br/>
{"id":"Cm02DsxUHb","time":1637182643,"event":"message","topic":"mytopic2","message":"for topic 2"}
</code>
<h3 id="priority" class="anchor">Message priority (<tt>X-Priority</tt>, <tt>Priority</tt>, <tt>prio</tt>, or <tt>p</tt>)</h3>
<p>
All messages have a priority, which defines how your urgently your phone notifies you. You can set custom
notification sounds and vibration patterns on your phone to map to these priorities.
</p>
<p class="smallMarginBottom">
The following priorities exist: <tt>1</tt> (<tt>min</tt>), <tt>2</tt> (<tt>low</tt>), <tt>3</tt> (<tt>default</tt>),
<tt>4</tt> (<tt>high</tt>), and <tt>5</tt> (<tt>max</tt>/<tt>urgent</tt>). You can set the priority with the
header <tt>X-Priority</tt> (or any of its aliases: <tt>Priority</tt>, <tt>prio</tt>, or <tt>p</tt>). Here are a few examples:
</p>
<code>
curl -H "X-Priority: urgent" -d "An urgent message" <span class="ntfyUrl">ntfy.sh</span>/mytopic<br/>
curl -H "Priority: 2" -d "Low priority message" <span class="ntfyUrl">ntfy.sh</span>/mytopic<br/>
curl -H p:4 -d "A high priority message" <span class="ntfyUrl">ntfy.sh</span>/mytopic
</code>
<h3 id="title" class="anchor">Notification title (<tt>X-Title</tt>, <tt>Title</tt>, <tt>ti</tt>, or <tt>t</tt>)</h3>
<p class="smallMarginBottom">
The notification title is typically set to the topic short URL (e.g. <tt><span class="ntfyUrl">ntfy.sh</span>/mytopic</tt>.
To override it, you can set the <tt>X-Title</tt> header (or any of its aliases: <tt>Title</tt>, <tt>ti</tt>, or <tt>t</tt>).
</p>
<code>
curl -H "Title: Dogs are better than cats" -d "Oh my ..." <span class="ntfyUrl">ntfy.sh</span>/mytopic<br/>
</code>
<h3 id="tags" class="anchor">Tags &amp; emojis 🥳 🎉 (<tt>X-Tags</tt>, <tt>Tags</tt>, or <tt>ta</tt>)</h3>
<p>
You can tag messages with emojis (or other relevant strings). If a tag matches a <a href="https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json">known emoji short code</a>,
it will be converted to an emoji. If it doesn't match, it will be listed below the notification. This is useful
for things like warnings and such (⚠️, ️🚨, or 🚩), but also to simply tag messages otherwise (e.g. which script the
message came from, ...).
</p>
<p class="smallMarginBottom">
You can set tags with the <tt>X-Tags</tt> header (or any of its aliases: <tt>Tags</tt>, or <tt>ta</tt>).
Use <a href="https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json">this reference</a>
to figure out what tags can be converted to emojis. In the example below, the tag "warning" matches the emoji ⚠️,
the tag "ssh-login" doesn't match and will be displayed below the message.
</p>
<code>
$ curl -H "Tags: warning,ssh-login" -d "Unauthorized SSH access" <span class="ntfyUrl">ntfy.sh</span>/mytopic<br/>
{"id":"ZEIwjfHlSS",...,"tags":["warning","ssh-login"],"message":"Unauthorized SSH access"}
</code>
<h2 id="examples" class="anchor">Examples</h2>
<p>
There are a million ways to use ntfy, but here are some inspirations. I try to collect
<a href="https://github.com/binwiederhier/ntfy/tree/main/examples">examples on GitHub</a>, so be sure to check
those out, too.
</p>
<h3 id="example-alerts" class="anchor">Example: A long process is done: backups, copying data, pipelines, ...</h3>
<p class="smallMarginBottom">
I started adding notifications pretty much all of my scripts. Typically, I just chain the <tt>curl</tt> call
directly to the command I'm running. The following example will either send <i>Laptop backup succeeded</i>
or ⚠️ <i>Laptop backup failed</i> directly to my phone:
</p>
<code>
rsync -a root@laptop /backups/laptop \<br/>
&nbsp;&nbsp;&& zfs snapshot ... \<br/>
&nbsp;&nbsp;&& curl -d "Laptop backup succeeded" <span class="ntfyUrl">ntfy.sh</span>/backups \<br/>
&nbsp;&nbsp;|| curl -H tags:warning -H prio:high -d "Laptop backup failed" <span class="ntfyUrl">ntfy.sh</span>/backups
</code>
<h3 id="example-web" class="anchor">Example: Server-sent messages in your web app</h3>
<p>
Just as you can <a href="#subscribe-web">subscribe to topics in this Web UI</a>, you can use ntfy in your own
web application. Check out the <a href="example.html">live example</a> or just look the source of this page.
</p>
<h3 id="example-notify-ssh" class="anchor">Example: Notify on SSH login</h3>
<p>
Years ago my home server was broken into. That shook me hard, so every time someone logs into any machine that I
own, I now message myself. Here's an example of how to use <a href="https://en.wikipedia.org/wiki/Linux_PAM">PAM</a>
to notify yourself on SSH login.
</p>
<p class="smallMarginBottom">
<b>/etc/pam.d/sshd</b> (at the end of the file):
</p>
<code>
session optional pam_exec.so /usr/local/bin/ntfy-ssh-login.sh
</code>
<p class="smallMarginBottom">
<b>/usr/local/bin/ntfy-ssh-login.sh</b>:
</p>
<code>
#!/bin/bash<br/>
if [ "${PAM_TYPE}" = "open_session" ]; then<br/>
&nbsp;&nbsp;curl -H tags:warning -d "SSH login: ${PAM_USER} from ${PAM_RHOST}" <span class="ntfyUrl">ntfy.sh</span>/alerts<br/>
fi
</code>
<h3 id="example-collect-data" class="anchor">Example: Collect data from multiple machines</h3>
<p>
The other day I was running tasks on 20 servers and I wanted to collect the interim results
as a CSV in one place. Here's the script I wrote:
</p>
<code>
while read result; do<br/>
&nbsp;&nbsp;[ -n "$result" ] && echo "$result" >> results.csv<br/>
done < <(stdbuf -i0 -o0 curl -s <span class="ntfyUrl">ntfy.sh</span>/results/raw)
</code>
<h2 id="faq" class="anchor">FAQ</h2>
<p>
<b id="isnt-this-like" class="anchor">Isn't this like ...?</b><br/>
Who knows. I didn't do a lot of research before making this. It was fun making it.
</p>
<p>
<b id="is-it-free" class="anchor">Can I use this in my app? Will it stay free?</b><br/>
Yes. As long as you don't abuse it, it'll be available and free of charge. I do not plan on monetizing
the service.
</p>
<p>
<b id="uptime-guarantees" class="anchor">What are the uptime guarantees?</b><br/>
Best effort.
</p>
<p>
<b id="multiple-subscribers" class="anchor">What happens if there are multiple subscribers to the same topic?</b><br/>
As per usual with pub-sub, all subscribers receive notifications if they are
subscribed to a topic.
</p>
<p>
<b id="can-you-spy-on-me" class="anchor">Will you know what topics exist, can you spy on me?</b><br/>
If you don't trust me or your messages are sensitive, run your own server. It's <a href="https://github.com/binwiederhier/ntfy">open source</a>.
That said, the logs do not contain any topic names or other details about you.
Messages are cached for {{.CacheDuration}} to facilitate service restarts, message polling and to overcome
client network disruptions.
</p>
<p>
<b id="selfhosted" class="anchor">Can I self-host it?</b><br/>
Yes. The server (including this Web UI) can be self-hosted, and the Android app supports adding topics from
your own server as well. There are <a href="https://github.com/binwiederhier/ntfy#installation">install instructions</a>
on GitHub.
</p>
<p>
<b id="why-firebase" class="anchor">Why is Firebase used?</b><br/>
In addition to caching messages locally and delivering them to long-polling subscribers, all messages are also
published to Firebase Cloud Messaging (FCM) (if <tt>FirebaseKeyFile</tt> is set, which it is on ntfy.sh). This
is to facilitate instant notifications on Android.
</p>
<p>
<b id="battery-usage" class="anchor">How much battery does the Android app use?</b><br/>
If you use the ntfy.sh server and you don't use the <i>instant delivery</i> feature, the Android app uses no
additional battery, since Firebase Cloud Messaging (FCM) is used. If you use your own server, or you use
<i>instant delivery</i>, the app has to maintain a constant connection to the server, which consumes about 4% of
battery in 17h of use (on my phone). I use it and it makes no difference to me.
</p>
<p>
<b id="instant-delivery" class="anchor">What is instant delivery?</b><br/>
Instant delivery is a feature in the Android app. If turned on, the app maintains a constant connection to the
server and listens for incoming notifications. This consumes <a href="#battery-usage">additional battery</a>,
but delivers notifications instantly.
</p>
<p>
<b id="why-no-ios" class="anchor">Why is there no iOS app (yet)?</b><br/>
I don't have an iPhone or a Mac, so I didn't make an iOS app yet. It'd be awesome if
<a href="https://github.com/binwiederhier/ntfy/issues/4">someone else could help out</a>.
</p>
<h2 id="privacy" class="anchor">Privacy policy</h2>
<p>
Neither the server nor the app record any personal information, or share any of the messages and topics with
any outside service. All data is exclusively used to make the service function properly. The one exception
is the Firebase Cloud Messaging (FCM) service, which is required to provide instant Android notifications (see
FAQ for details).
</p>
<p>
The web server does not log or otherwise store request paths, remote IP addresses or even topics or messages,
aside from a short on-disk cache (for {{.CacheDuration}}) to support service restarts.
</p>
<center id="ironicCenterTagDontFreakOut"><i>Made with ❤️ by <a href="https://heckel.io">Philipp C. Heckel</a></i></center>
</div>
<div id="detail"{{if not .Topic}} style="display: none"{{end}}>
<div id="detailMain">
<button id="detailCloseButton"><img src="static/img/close.svg"/></button>
<h1><span id="detailTitle"></span></h1>
<p class="smallMarginBottom">
<b>ntfy</b> is a simple HTTP-based pub-sub notification service. This is a ntfy topic.
To send notifications to it, simply PUT or POST to the topic URL. Here's an example using <tt>curl</tt>:
</p>
<code>
curl -d "Backup failed" <span id="detailTopicUrl">ntfy.sh/topic</span>
</code>
<p id="detailNotificationsDisallowed">
If you'd like to receive desktop notifications when new messages arrive on this topic, you have
<a href="#" onclick="return requestPermission()">grant the browser permission</a> to show notifications.
Click the link to do so.
</p>
<p class="smallMarginBottom">
<b>Recent notifications</b> (cached for {{.CacheDuration}}):
</p>
<p id="detailNoNotifications">
<i>You haven't received any notifications for this topic yet.</i>
</p>
<div id="detailEventsList"></div>
</div>
</div>
<div id="lightbox" class="lightbox"></div>
<script src="static/js/emoji.js"></script>
<script src="static/js/app.js"></script>
</body>
</html>