Actually apply the pre-commit fixers to the codebase.
This can be redone manually with `pre-commit run --all` While the pre-commit hook could be merged to run locally, it is much cleaner to align all the files to best-practice syntax in a single commit. It is also required for server-side validation.
This commit is contained in:
parent
108ad3c7c3
commit
b218e62ffc
151 changed files with 42251 additions and 31034 deletions
227
docs/config.md
227
docs/config.md
|
@ -1,10 +1,10 @@
|
|||
# Configuring the ntfy server
|
||||
The ntfy server can be configured in three ways: using a config file (typically at `/etc/ntfy/server.yml`,
|
||||
see [server.yml](https://github.com/binwiederhier/ntfy/blob/main/server/server.yml)), via command line arguments
|
||||
The ntfy server can be configured in three ways: using a config file (typically at `/etc/ntfy/server.yml`,
|
||||
see [server.yml](https://github.com/binwiederhier/ntfy/blob/main/server/server.yml)), via command line arguments
|
||||
or using environment variables.
|
||||
|
||||
## Quick start
|
||||
By default, simply running `ntfy serve` will start the server at port 80. No configuration needed. Batteries included 😀.
|
||||
By default, simply running `ntfy serve` will start the server at port 80. No configuration needed. Batteries included 😀.
|
||||
If everything works as it should, you'll see something like this:
|
||||
```
|
||||
$ ntfy serve
|
||||
|
@ -12,7 +12,7 @@ $ ntfy serve
|
|||
```
|
||||
|
||||
You can immediately start [publishing messages](publish.md), or subscribe via the [Android app](subscribe/phone.md),
|
||||
[the web UI](subscribe/web.md), or simply via [curl or your favorite HTTP client](subscribe/api.md). To configure
|
||||
[the web UI](subscribe/web.md), or simply via [curl or your favorite HTTP client](subscribe/api.md). To configure
|
||||
the server further, check out the [config options table](#config-options) or simply type `ntfy serve --help` to
|
||||
get a list of [command line options](#command-line-options).
|
||||
|
||||
|
@ -46,7 +46,7 @@ Here are a few working sample configs:
|
|||
|
||||
=== "server.yml (ntfy.sh config)"
|
||||
``` yaml
|
||||
# All the things: Behind a proxy, Firebase, cache, attachments,
|
||||
# All the things: Behind a proxy, Firebase, cache, attachments,
|
||||
# SMTP publishing & receiving
|
||||
|
||||
base-url: "https://ntfy.sh"
|
||||
|
@ -68,14 +68,14 @@ Here are a few working sample configs:
|
|||
## Message cache
|
||||
If desired, ntfy can temporarily keep notifications in an in-memory or an on-disk cache. Caching messages for a short period
|
||||
of time is important to allow [phones](subscribe/phone.md) and other devices with brittle Internet connections to be able to retrieve
|
||||
notifications that they may have missed.
|
||||
notifications that they may have missed.
|
||||
|
||||
By default, ntfy keeps messages **in-memory for 12 hours**, which means that **cached messages do not survive an application
|
||||
restart**. You can override this behavior using the following config settings:
|
||||
|
||||
* `cache-file`: if set, ntfy will store messages in a SQLite based cache (default is empty, which means in-memory cache).
|
||||
**This is required if you'd like messages to be retained across restarts**.
|
||||
* `cache-duration`: defines the duration for which messages are stored in the cache (default is `12h`).
|
||||
* `cache-duration`: defines the duration for which messages are stored in the cache (default is `12h`).
|
||||
|
||||
You can also entirely disable the cache by setting `cache-duration` to `0`. When the cache is disabled, messages are only
|
||||
passed on to the connected subscribers, but never stored on disk or even kept in memory longer than is needed to forward
|
||||
|
@ -86,11 +86,11 @@ Subscribers can retrieve cached messaging using the [`poll=1` parameter](subscri
|
|||
|
||||
## Attachments
|
||||
If desired, you may allow users to upload and [attach files to notifications](publish.md#attachments). To enable
|
||||
this feature, you have to simply configure an attachment cache directory and a base URL (`attachment-cache-dir`, `base-url`).
|
||||
this feature, you have to simply configure an attachment cache directory and a base URL (`attachment-cache-dir`, `base-url`).
|
||||
Once these options are set and the directory is writable by the server user, you can upload attachments via PUT.
|
||||
|
||||
By default, attachments are stored in the disk-cache **for only 3 hours**. The main reason for this is to avoid legal issues
|
||||
and such when hosting user controlled content. Typically, this is more than enough time for the user (or the auto download
|
||||
and such when hosting user controlled content. Typically, this is more than enough time for the user (or the auto download
|
||||
feature) to download the file. The following config options are relevant to attachments:
|
||||
|
||||
* `base-url` is the root URL for the ntfy server; this is needed for the generated attachment URLs
|
||||
|
@ -99,7 +99,7 @@ feature) to download the file. The following config options are relevant to atta
|
|||
* `attachment-file-size-limit` is the per-file attachment size limit (e.g. 300k, 2M, 100M, default: 15M)
|
||||
* `attachment-expiry-duration` is the duration after which uploaded attachments will be deleted (e.g. 3h, 20h, default: 3h)
|
||||
|
||||
Here's an example config using mostly the defaults (except for the cache directory, which is empty by default):
|
||||
Here's an example config using mostly the defaults (except for the cache directory, which is empty by default):
|
||||
|
||||
=== "/etc/ntfy/server.yml (minimal)"
|
||||
``` yaml
|
||||
|
@ -123,27 +123,27 @@ and `visitor-attachment-daily-bandwidth-limit`. Setting these conservatively is
|
|||
|
||||
## Access control
|
||||
By default, the ntfy server is open for everyone, meaning **everyone can read and write to any topic** (this is how
|
||||
ntfy.sh is configured). To restrict access to your own server, you can optionally configure authentication and authorization.
|
||||
ntfy.sh is configured). To restrict access to your own server, you can optionally configure authentication and authorization.
|
||||
|
||||
ntfy's auth is implemented with a simple [SQLite](https://www.sqlite.org/)-based backend. It implements two roles
|
||||
(`user` and `admin`) and per-topic `read` and `write` permissions using an [access control list (ACL)](https://en.wikipedia.org/wiki/Access-control_list).
|
||||
Access control entries can be applied to users as well as the special everyone user (`*`), which represents anonymous API access.
|
||||
ntfy's auth is implemented with a simple [SQLite](https://www.sqlite.org/)-based backend. It implements two roles
|
||||
(`user` and `admin`) and per-topic `read` and `write` permissions using an [access control list (ACL)](https://en.wikipedia.org/wiki/Access-control_list).
|
||||
Access control entries can be applied to users as well as the special everyone user (`*`), which represents anonymous API access.
|
||||
|
||||
To set up auth, simply **configure the following two options**:
|
||||
|
||||
* `auth-file` is the user/access database; it is created automatically if it doesn't already exist; suggested
|
||||
* `auth-file` is the user/access database; it is created automatically if it doesn't already exist; suggested
|
||||
location `/var/lib/ntfy/user.db` (easiest if deb/rpm package is used)
|
||||
* `auth-default-access` defines the default/fallback access if no access control entry is found; it can be
|
||||
set to `read-write` (default), `read-only`, `write-only` or `deny-all`.
|
||||
|
||||
Once configured, you can use the `ntfy user` command to [add or modify users](#users-and-roles), and the `ntfy access` command
|
||||
lets you [modify the access control list](#access-control-list-acl) for specific users and topic patterns. Both of these
|
||||
commands **directly edit the auth database** (as defined in `auth-file`), so they only work on the server, and only if the user
|
||||
lets you [modify the access control list](#access-control-list-acl) for specific users and topic patterns. Both of these
|
||||
commands **directly edit the auth database** (as defined in `auth-file`), so they only work on the server, and only if the user
|
||||
accessing them has the right permissions.
|
||||
|
||||
### Users and roles
|
||||
The `ntfy user` command allows you to add/remove/change users in the ntfy user database, as well as change
|
||||
passwords or roles (`user` or `admin`). In practice, you'll often just create one admin
|
||||
passwords or roles (`user` or `admin`). In practice, you'll often just create one admin
|
||||
user with `ntfy user add --role=admin ...` and be done with all this (see [example below](#example-private-instance)).
|
||||
|
||||
**Roles:**
|
||||
|
@ -156,7 +156,7 @@ user with `ntfy user add --role=admin ...` and be done with all this (see [examp
|
|||
|
||||
```
|
||||
ntfy user list # Shows list of users (alias: 'ntfy access')
|
||||
ntfy user add phil # Add regular user phil
|
||||
ntfy user add phil # Add regular user phil
|
||||
ntfy user add --role=admin phil # Add admin user phil
|
||||
ntfy user del phil # Delete user phil
|
||||
ntfy user change-pass phil # Change password for user phil
|
||||
|
@ -165,7 +165,7 @@ ntfy user change-role phil admin # Make user phil an admin
|
|||
|
||||
### Access control list (ACL)
|
||||
The access control list (ACL) **manages access to topics for non-admin users, and for anonymous access (`everyone`/`*`)**.
|
||||
Each entry represents the access permissions for a user to a specific topic or topic pattern.
|
||||
Each entry represents the access permissions for a user to a specific topic or topic pattern.
|
||||
|
||||
The ACL can be displayed or modified with the `ntfy access` command:
|
||||
|
||||
|
@ -175,20 +175,20 @@ ntfy access USERNAME # Shows access control entries for USERNA
|
|||
ntfy access USERNAME TOPIC PERMISSION # Allow/deny access for USERNAME to TOPIC
|
||||
```
|
||||
|
||||
A `USERNAME` is an existing user, as created with `ntfy user add` (see [users and roles](#users-and-roles)), or the
|
||||
A `USERNAME` is an existing user, as created with `ntfy user add` (see [users and roles](#users-and-roles)), or the
|
||||
anonymous user `everyone` or `*`, which represents clients that access the API without username/password.
|
||||
|
||||
A `TOPIC` is either a specific topic name (e.g. `mytopic`, or `phil_alerts`), or a wildcard pattern that matches any
|
||||
number of topics (e.g. `alerts_*` or `ben-*`). Only the wildcard character `*` is supported. It stands for zero to any
|
||||
number of topics (e.g. `alerts_*` or `ben-*`). Only the wildcard character `*` is supported. It stands for zero to any
|
||||
number of characters.
|
||||
|
||||
A `PERMISSION` is any of the following supported permissions:
|
||||
|
||||
* `read-write` (alias: `rw`): Allows [publishing messages](publish.md) to the given topic, as well as
|
||||
* `read-write` (alias: `rw`): Allows [publishing messages](publish.md) to the given topic, as well as
|
||||
[subscribing](subscribe/api.md) and reading messages
|
||||
* `read-only` (aliases: `read`, `ro`): Allows only subscribing and reading messages, but not publishing to the topic
|
||||
* `write-only` (aliases: `write`, `wo`): Allows only publishing to the topic, but not subscribing to it
|
||||
* `deny` (alias: `none`): Allows neither publishing nor subscribing to a topic
|
||||
* `deny` (alias: `none`): Allows neither publishing nor subscribing to a topic
|
||||
|
||||
**Example commands** (type `ntfy access --help` for more details):
|
||||
```
|
||||
|
@ -237,10 +237,10 @@ After that, simply create an `admin` user:
|
|||
$ ntfy user add --role=admin phil
|
||||
password: mypass
|
||||
confirm: mypass
|
||||
user phil added with role admin
|
||||
user phil added with role admin
|
||||
```
|
||||
|
||||
Once you've done that, you can publish and subscribe using [Basic Auth](https://en.wikipedia.org/wiki/Basic_access_authentication)
|
||||
Once you've done that, you can publish and subscribe using [Basic Auth](https://en.wikipedia.org/wiki/Basic_access_authentication)
|
||||
with the given username/password. Be sure to use HTTPS to avoid eavesdropping and exposing your password. Here's a simple example:
|
||||
|
||||
=== "Command line (curl)"
|
||||
|
@ -301,7 +301,7 @@ with the given username/password. Be sure to use HTTPS to avoid eavesdropping an
|
|||
file_get_contents('https://ntfy.example.com/mysecrets', false, stream_context_create([
|
||||
'http' => [
|
||||
'method' => 'POST', // PUT also works
|
||||
'header' =>
|
||||
'header' =>
|
||||
'Content-Type: text/plain\r\n' .
|
||||
'Authorization: Basic cGhpbDpteXBhc3M=',
|
||||
'content' => 'Look ma, with auth'
|
||||
|
@ -310,12 +310,12 @@ with the given username/password. Be sure to use HTTPS to avoid eavesdropping an
|
|||
```
|
||||
|
||||
### Example: UnifiedPush
|
||||
[UnifiedPush](https://unifiedpush.org) requires that the [application server](https://unifiedpush.org/spec/definitions/#application-server) (e.g. Synapse, Fediverse Server, …)
|
||||
has anonymous write access to the [topic](https://unifiedpush.org/spec/definitions/#endpoint) used for push messages.
|
||||
The topic names used by UnifiedPush all start with the `up*` prefix. Please refer to the
|
||||
[UnifiedPush](https://unifiedpush.org) requires that the [application server](https://unifiedpush.org/spec/definitions/#application-server) (e.g. Synapse, Fediverse Server, …)
|
||||
has anonymous write access to the [topic](https://unifiedpush.org/spec/definitions/#endpoint) used for push messages.
|
||||
The topic names used by UnifiedPush all start with the `up*` prefix. Please refer to the
|
||||
**[UnifiedPush documentation](https://unifiedpush.org/users/distributors/ntfy/#limit-access-to-some-users)** for more details.
|
||||
|
||||
To enable support for UnifiedPush for private servers (i.e. `auth-default-access: "deny-all"`), you should either
|
||||
To enable support for UnifiedPush for private servers (i.e. `auth-default-access: "deny-all"`), you should either
|
||||
allow anonymous write access for the entire prefix or explicitly per topic:
|
||||
|
||||
=== "Prefix"
|
||||
|
@ -329,11 +329,11 @@ allow anonymous write access for the entire prefix or explicitly per topic:
|
|||
```
|
||||
|
||||
## E-mail notifications
|
||||
To allow forwarding messages via e-mail, you can configure an **SMTP server for outgoing messages**. Once configured,
|
||||
you can set the `X-Email` header to [send messages via e-mail](publish.md#e-mail-notifications) (e.g.
|
||||
To allow forwarding messages via e-mail, you can configure an **SMTP server for outgoing messages**. Once configured,
|
||||
you can set the `X-Email` header to [send messages via e-mail](publish.md#e-mail-notifications) (e.g.
|
||||
`curl -d "hi there" -H "X-Email: phil@example.com" ntfy.sh/mytopic`).
|
||||
|
||||
As of today, only SMTP servers with PLAIN auth and STARTLS are supported. To enable e-mail sending, you must set the
|
||||
As of today, only SMTP servers with PLAIN auth and STARTLS are supported. To enable e-mail sending, you must set the
|
||||
following settings:
|
||||
|
||||
* `base-url` is the root URL for the ntfy server; this is needed for e-mail footer
|
||||
|
@ -341,7 +341,7 @@ following settings:
|
|||
* `smtp-sender-user` and `smtp-sender-pass` are the username and password of the SMTP user
|
||||
* `smtp-sender-from` is the e-mail address of the sender
|
||||
|
||||
Here's an example config using [Amazon SES](https://aws.amazon.com/ses/) for outgoing mail (this is how it is
|
||||
Here's an example config using [Amazon SES](https://aws.amazon.com/ses/) for outgoing mail (this is how it is
|
||||
configured for `ntfy.sh`):
|
||||
|
||||
=== "/etc/ntfy/server.yml"
|
||||
|
@ -353,13 +353,13 @@ configured for `ntfy.sh`):
|
|||
smtp-sender-from: "ntfy@ntfy.sh"
|
||||
```
|
||||
|
||||
Please also refer to the [rate limiting](#rate-limiting) settings below, specifically `visitor-email-limit-burst`
|
||||
Please also refer to the [rate limiting](#rate-limiting) settings below, specifically `visitor-email-limit-burst`
|
||||
and `visitor-email-limit-burst`. Setting these conservatively is necessary to avoid abuse.
|
||||
|
||||
## E-mail publishing
|
||||
To allow publishing messages via e-mail, ntfy can run a lightweight **SMTP server for incoming messages**. Once configured,
|
||||
users can [send emails to a topic e-mail address](publish.md#e-mail-publishing) (e.g. `mytopic@ntfy.sh` or
|
||||
`myprefix-mytopic@ntfy.sh`) to publish messages to a topic. This is useful for e-mail based integrations such as for
|
||||
To allow publishing messages via e-mail, ntfy can run a lightweight **SMTP server for incoming messages**. Once configured,
|
||||
users can [send emails to a topic e-mail address](publish.md#e-mail-publishing) (e.g. `mytopic@ntfy.sh` or
|
||||
`myprefix-mytopic@ntfy.sh`) to publish messages to a topic. This is useful for e-mail based integrations such as for
|
||||
statuspage.io (though these days most services also support webhooks and HTTP calls).
|
||||
|
||||
To configure the SMTP server, you must at least set `smtp-server-listen` and `smtp-server-domain`:
|
||||
|
@ -379,8 +379,8 @@ Here's an example config (this is how it is configured for `ntfy.sh`):
|
|||
smtp-server-addr-prefix: "ntfy-"
|
||||
```
|
||||
|
||||
In addition to configuring the ntfy server, you have to create two DNS records (an [MX record](https://en.wikipedia.org/wiki/MX_record)
|
||||
and a corresponding A record), so incoming mail will find its way to your server. Here's an example of how `ntfy.sh` is
|
||||
In addition to configuring the ntfy server, you have to create two DNS records (an [MX record](https://en.wikipedia.org/wiki/MX_record)
|
||||
and a corresponding A record), so incoming mail will find its way to your server. Here's an example of how `ntfy.sh` is
|
||||
configured (in [Amazon Route 53](https://aws.amazon.com/route53/)):
|
||||
|
||||
<figure markdown>
|
||||
|
@ -388,7 +388,7 @@ configured (in [Amazon Route 53](https://aws.amazon.com/route53/)):
|
|||
<figcaption>DNS records for incoming mail</figcaption>
|
||||
</figure>
|
||||
|
||||
You can check if everything is working correctly by sending an email as raw SMTP via `nc`. Create a text file, e.g.
|
||||
You can check if everything is working correctly by sending an email as raw SMTP via `nc`. Create a text file, e.g.
|
||||
`email.txt`
|
||||
|
||||
```
|
||||
|
@ -403,7 +403,7 @@ Hello from 🇩🇪
|
|||
.
|
||||
```
|
||||
|
||||
And then send the mail via `nc` like this. If you see any lines starting with `451`, those are errors from the
|
||||
And then send the mail via `nc` like this. If you see any lines starting with `451`, those are errors from the
|
||||
ntfy server. Read them carefully.
|
||||
|
||||
```
|
||||
|
@ -418,9 +418,9 @@ $ cat email.txt | nc -N ntfy.sh 25
|
|||
As for the DNS setup, be sure to verify that `dig MX` and `dig A` are returning results similar to this:
|
||||
|
||||
```
|
||||
$ dig MX ntfy.sh +short
|
||||
$ dig MX ntfy.sh +short
|
||||
10 mx1.ntfy.sh.
|
||||
$ dig A mx1.ntfy.sh +short
|
||||
$ dig A mx1.ntfy.sh +short
|
||||
3.139.215.220
|
||||
```
|
||||
|
||||
|
@ -429,12 +429,12 @@ $ dig A mx1.ntfy.sh +short
|
|||
If you are running ntfy behind a proxy, you must set the `behind-proxy` flag. Otherwise, all visitors are
|
||||
[rate limited](#rate-limiting) as if they are one.
|
||||
|
||||
It may be desirable to run ntfy behind a proxy (e.g. nginx, HAproxy or Apache), so you can provide TLS certificates
|
||||
using Let's Encrypt using certbot, or simply because you'd like to share the ports (80/443) with other services.
|
||||
Whatever your reasons may be, there are a few things to consider.
|
||||
It may be desirable to run ntfy behind a proxy (e.g. nginx, HAproxy or Apache), so you can provide TLS certificates
|
||||
using Let's Encrypt using certbot, or simply because you'd like to share the ports (80/443) with other services.
|
||||
Whatever your reasons may be, there are a few things to consider.
|
||||
|
||||
If you are running ntfy behind a proxy, you should set the `behind-proxy` flag. This will instruct the
|
||||
[rate limiting](#rate-limiting) logic to use the `X-Forwarded-For` header as the primary identifier for a visitor,
|
||||
If you are running ntfy behind a proxy, you should set the `behind-proxy` flag. This will instruct the
|
||||
[rate limiting](#rate-limiting) logic to use the `X-Forwarded-For` header as the primary identifier for a visitor,
|
||||
as opposed to the remote IP address. If the `behind-proxy` flag is not set, all visitors will
|
||||
be counted as one, because from the perspective of the ntfy server, they all share the proxy's IP address.
|
||||
|
||||
|
@ -445,17 +445,17 @@ be counted as one, because from the perspective of the ntfy server, they all sha
|
|||
```
|
||||
|
||||
### TLS/SSL
|
||||
ntfy supports HTTPS/TLS by setting the `listen-https` [config option](#config-options). However, if you
|
||||
ntfy supports HTTPS/TLS by setting the `listen-https` [config option](#config-options). However, if you
|
||||
are behind a proxy, it is recommended that TLS/SSL termination is done by the proxy itself (see below).
|
||||
|
||||
I highly recommend using [certbot](https://certbot.eff.org/). I use it with the [dns-route53 plugin](https://certbot-dns-route53.readthedocs.io/en/stable/),
|
||||
I highly recommend using [certbot](https://certbot.eff.org/). I use it with the [dns-route53 plugin](https://certbot-dns-route53.readthedocs.io/en/stable/),
|
||||
which lets you use [AWS Route 53](https://aws.amazon.com/route53/) as the challenge. That's much easier than using the
|
||||
HTTP challenge. I've found [this guide](https://nandovieira.com/using-lets-encrypt-in-development-with-nginx-and-aws-route53) to
|
||||
be incredibly helpful.
|
||||
|
||||
### nginx/Apache2/caddy
|
||||
For your convenience, here's a working config that'll help configure things behind a proxy. Be sure to **enable WebSockets**
|
||||
by forwarding the `Connection` and `Upgrade` headers accordingly.
|
||||
by forwarding the `Connection` and `Upgrade` headers accordingly.
|
||||
|
||||
In this example, ntfy runs on `:2586` and we proxy traffic to it. We also redirect HTTP to HTTPS for GET requests against a topic
|
||||
or the root domain:
|
||||
|
@ -474,7 +474,7 @@ or the root domain:
|
|||
server_name ntfy.sh;
|
||||
|
||||
location / {
|
||||
# Redirect HTTP to HTTPS, but only for GET topic addresses, since we want
|
||||
# Redirect HTTP to HTTPS, but only for GET topic addresses, since we want
|
||||
# it to work with curl without the annoying https:// prefix
|
||||
set $redirect_https "";
|
||||
if ($request_method = GET) {
|
||||
|
@ -489,16 +489,16 @@ or the root domain:
|
|||
|
||||
proxy_pass http://127.0.0.1:2586;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
proxy_redirect off;
|
||||
|
||||
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
|
||||
proxy_connect_timeout 3m;
|
||||
proxy_send_timeout 3m;
|
||||
proxy_read_timeout 3m;
|
||||
|
@ -506,19 +506,19 @@ or the root domain:
|
|||
client_max_body_size 20m; # Must be >= attachment-file-size-limit in /etc/ntfy/server.yml
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name ntfy.sh;
|
||||
|
||||
|
||||
ssl_session_cache builtin:1000 shared:SSL:10m;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/ntfy.sh/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/ntfy.sh/privkey.pem;
|
||||
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:2586;
|
||||
proxy_http_version 1.1;
|
||||
|
@ -526,16 +526,16 @@ or the root domain:
|
|||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
proxy_redirect off;
|
||||
|
||||
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
|
||||
proxy_connect_timeout 3m;
|
||||
proxy_send_timeout 3m;
|
||||
proxy_read_timeout 3m;
|
||||
|
||||
|
||||
client_max_body_size 20m; # Must be >= attachment-file-size-limit in /etc/ntfy/server.yml
|
||||
}
|
||||
}
|
||||
|
@ -547,7 +547,7 @@ or the root domain:
|
|||
#
|
||||
# This config requires the use of the -L flag in curl to redirect to HTTPS, and it keeps nginx output buffering
|
||||
# enabled. While recommended, I have had issues with that in the past.
|
||||
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name ntfy.sh;
|
||||
|
@ -570,19 +570,19 @@ or the root domain:
|
|||
client_max_body_size 20m; # Must be >= attachment-file-size-limit in /etc/ntfy/server.yml
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name ntfy.sh;
|
||||
|
||||
|
||||
ssl_session_cache builtin:1000 shared:SSL:10m;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/ntfy.sh/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/ntfy.sh/privkey.pem;
|
||||
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:2586;
|
||||
proxy_http_version 1.1;
|
||||
|
@ -625,16 +625,16 @@ or the root domain:
|
|||
RewriteCond %{HTTP:Upgrade} websocket [NC]
|
||||
RewriteCond %{HTTP:Connection} upgrade [NC]
|
||||
RewriteRule ^/?(.*) "ws://127.0.0.1:2586/$1" [P,L]
|
||||
|
||||
# Redirect HTTP to HTTPS, but only for GET topic addresses, since we want
|
||||
# it to work with curl without the annoying https:// prefix
|
||||
|
||||
# Redirect HTTP to HTTPS, but only for GET topic addresses, since we want
|
||||
# it to work with curl without the annoying https:// prefix
|
||||
RewriteCond %{REQUEST_METHOD} GET
|
||||
RewriteRule ^/([-_A-Za-z0-9]{0,64})$ https://%{SERVER_NAME}/$1 [R,L]
|
||||
</VirtualHost>
|
||||
|
||||
|
||||
<VirtualHost *:443>
|
||||
ServerName ntfy.sh
|
||||
|
||||
|
||||
SSLEngine on
|
||||
SSLCertificateFile /etc/letsencrypt/live/ntfy.sh/fullchain.pem
|
||||
SSLCertificateKeyFile /etc/letsencrypt/live/ntfy.sh/privkey.pem
|
||||
|
@ -647,7 +647,7 @@ or the root domain:
|
|||
SetEnv proxy-nokeepalive 1
|
||||
SetEnv proxy-sendchunked 1
|
||||
|
||||
# Higher than the max message size of 4096 bytes
|
||||
# Higher than the max message size of 4096 bytes
|
||||
LimitRequestBody 102400
|
||||
|
||||
# Enable mod_rewrite (requires "a2enmod rewrite")
|
||||
|
@ -656,7 +656,7 @@ or the root domain:
|
|||
# WebSockets support (requires "a2enmod rewrite proxy_wstunnel")
|
||||
RewriteCond %{HTTP:Upgrade} websocket [NC]
|
||||
RewriteCond %{HTTP:Connection} upgrade [NC]
|
||||
RewriteRule ^/?(.*) "ws://127.0.0.1:2586/$1" [P,L]
|
||||
RewriteRule ^/?(.*) "ws://127.0.0.1:2586/$1" [P,L]
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
|
@ -707,10 +707,10 @@ firebase-key-file: "/etc/ntfy/ntfy-sh-firebase-adminsdk-ahnce-9f4d6f14b5.json"
|
|||
```
|
||||
|
||||
## iOS instant notifications
|
||||
Unlike Android, iOS heavily restricts background processing, which sadly makes it impossible to implement instant
|
||||
push notifications without a central server.
|
||||
Unlike Android, iOS heavily restricts background processing, which sadly makes it impossible to implement instant
|
||||
push notifications without a central server.
|
||||
|
||||
To still support instant notifications on iOS through your self-hosted ntfy server, you have to forward so called `poll_request`
|
||||
To still support instant notifications on iOS through your self-hosted ntfy server, you have to forward so called `poll_request`
|
||||
messages to the main ntfy.sh server (or any upstream server that's APNS/Firebase connected, if you build your own iOS app),
|
||||
which will then forward it to Firebase/APNS.
|
||||
|
||||
|
@ -726,12 +726,12 @@ the message ID of the original message, instructing the iOS app to poll this ser
|
|||
If `upstream-base-url` is not set, notifications will still eventually get to your device, but delivery can take hours,
|
||||
depending on the state of the phone. If you are using your phone, it shouldn't take more than 20-30 minutes though.
|
||||
|
||||
In case you're curious, here's an example of the entire flow:
|
||||
In case you're curious, here's an example of the entire flow:
|
||||
|
||||
- In the iOS app, you subscribe to `https://ntfy.example.com/mytopic`
|
||||
- The app subscribes to the Firebase topic `6de73be8dfb7d69e...` (the SHA256 of the topic URL)
|
||||
- When you publish a message to `https://ntfy.example.com/mytopic`, your ntfy server will publish a
|
||||
poll request to `https://ntfy.sh/6de73be8dfb7d69e...`. The request from your server to the upstream server
|
||||
- When you publish a message to `https://ntfy.example.com/mytopic`, your ntfy server will publish a
|
||||
poll request to `https://ntfy.sh/6de73be8dfb7d69e...`. The request from your server to the upstream server
|
||||
contains only the message ID (in the `X-Poll-ID` header), and the SHA256 checksum of the topic URL (as upstream topic).
|
||||
- The ntfy.sh server publishes the poll request message to Firebase, which forwards it to APNS, which forwards it to your iOS device
|
||||
- Your iOS device receives the poll request, and fetches the actual message from your server, and then displays it
|
||||
|
@ -743,21 +743,21 @@ curl -X POST -H "X-Poll-ID: s4PdJozxM8na" https://ntfy.sh/6de73be8dfb7d69e32fb2c
|
|||
{"id":"4HsClFEuCIcs","time":1654087955,"event":"poll_request","topic":"6de73be8dfb7d69e32fb2c00c23fe7adbd8b5504406e3068c273aa24cef4055b","message":"New message","poll_id":"s4PdJozxM8na"}
|
||||
```
|
||||
|
||||
Note that the self-hosted server literally sends the message `New message` for every message, even if your message
|
||||
may be `Some other message`. This is so that if iOS cannot talk to the self-hosted server (in time, or at all),
|
||||
Note that the self-hosted server literally sends the message `New message` for every message, even if your message
|
||||
may be `Some other message`. This is so that if iOS cannot talk to the self-hosted server (in time, or at all),
|
||||
it'll show `New message` as a popup.
|
||||
|
||||
## Rate limiting
|
||||
!!! info
|
||||
Be aware that if you are running ntfy behind a proxy, you must set the `behind-proxy` flag.
|
||||
Be aware that if you are running ntfy behind a proxy, you must set the `behind-proxy` flag.
|
||||
Otherwise, all visitors are rate limited as if they are one.
|
||||
|
||||
By default, ntfy runs without authentication, so it is vitally important that we protect the server from abuse or overload.
|
||||
There are various limits and rate limits in place that you can use to configure the server:
|
||||
|
||||
* **Global limit**: A global limit applies across all visitors (IPs, clients, users)
|
||||
* **Visitor limit**: A visitor limit only applies to a certain visitor. A **visitor** is identified by its IP address
|
||||
(or the `X-Forwarded-For` header if `behind-proxy` is set). All config options that start with the word `visitor` apply
|
||||
* **Visitor limit**: A visitor limit only applies to a certain visitor. A **visitor** is identified by its IP address
|
||||
(or the `X-Forwarded-For` header if `behind-proxy` is set). All config options that start with the word `visitor` apply
|
||||
only on a per-visitor basis.
|
||||
|
||||
During normal usage, you shouldn't encounter these limits at all, and even if you burst a few requests or emails
|
||||
|
@ -773,39 +773,39 @@ Let's do the easy limits first:
|
|||
In addition to the limits above, there is a requests/second limit per visitor for all sensitive GET/PUT/POST requests.
|
||||
This limit uses a [token bucket](https://en.wikipedia.org/wiki/Token_bucket) (using Go's [rate package](https://pkg.go.dev/golang.org/x/time/rate)):
|
||||
|
||||
Each visitor has a bucket of 60 requests they can fire against the server (defined by `visitor-request-limit-burst`).
|
||||
Each visitor has a bucket of 60 requests they can fire against the server (defined by `visitor-request-limit-burst`).
|
||||
After the 60, new requests will encounter a `429 Too Many Requests` response. The visitor request bucket is refilled at a rate of one
|
||||
request every 5s (defined by `visitor-request-limit-replenish`)
|
||||
|
||||
* `visitor-request-limit-burst` is the initial bucket of requests each visitor has. This defaults to 60.
|
||||
* `visitor-request-limit-replenish` is the rate at which the bucket is refilled (one request per x). Defaults to 5s.
|
||||
* `visitor-request-limit-exempt-hosts` is a comma-separated list of hostnames and IPs to be exempt from request rate
|
||||
* `visitor-request-limit-exempt-hosts` is a comma-separated list of hostnames and IPs to be exempt from request rate
|
||||
limiting; hostnames are resolved at the time the server is started. Defaults to an empty list.
|
||||
|
||||
|
||||
### Attachment limits
|
||||
Aside from the global file size and total attachment cache limits (see [above](#attachments)), there are two relevant
|
||||
Aside from the global file size and total attachment cache limits (see [above](#attachments)), there are two relevant
|
||||
per-visitor limits:
|
||||
|
||||
* `visitor-attachment-total-size-limit` is the total storage limit used for attachments per visitor. It defaults to 100M.
|
||||
The per-visitor storage is automatically decreased as attachments expire. External attachments (attached via `X-Attach`,
|
||||
see [publishing docs](publish.md#attachments)) do not count here.
|
||||
* `visitor-attachment-daily-bandwidth-limit` is the total daily attachment download/upload bandwidth limit per visitor,
|
||||
The per-visitor storage is automatically decreased as attachments expire. External attachments (attached via `X-Attach`,
|
||||
see [publishing docs](publish.md#attachments)) do not count here.
|
||||
* `visitor-attachment-daily-bandwidth-limit` is the total daily attachment download/upload bandwidth limit per visitor,
|
||||
including PUT and GET requests. This is to protect your precious bandwidth from abuse, since egress costs money in
|
||||
most cloud providers. This defaults to 500M.
|
||||
|
||||
### E-mail limits
|
||||
Similarly to the request limit, there is also an e-mail limit (only relevant if [e-mail notifications](#e-mail-notifications)
|
||||
Similarly to the request limit, there is also an e-mail limit (only relevant if [e-mail notifications](#e-mail-notifications)
|
||||
are enabled):
|
||||
|
||||
* `visitor-email-limit-burst` is the initial bucket of emails each visitor has. This defaults to 16.
|
||||
* `visitor-email-limit-replenish` is the rate at which the bucket is refilled (one email per x). Defaults to 1h.
|
||||
|
||||
### Firebase limits
|
||||
If [Firebase is configured](#firebase-fcm), all messages are also published to a Firebase topic (unless `Firebase: no`
|
||||
If [Firebase is configured](#firebase-fcm), all messages are also published to a Firebase topic (unless `Firebase: no`
|
||||
is set). Firebase enforces [its own limits](https://firebase.google.com/docs/cloud-messaging/concept-options#topics_throttling)
|
||||
on how many messages can be published. Unfortunately these limits are a little vague and can change depending on the time
|
||||
of day. In practice, I have only ever observed `429 Quota exceeded` responses from Firebase if **too many messages are published to
|
||||
the same topic**.
|
||||
on how many messages can be published. Unfortunately these limits are a little vague and can change depending on the time
|
||||
of day. In practice, I have only ever observed `429 Quota exceeded` responses from Firebase if **too many messages are published to
|
||||
the same topic**.
|
||||
|
||||
In ntfy, if Firebase responds with a 429 after publishing to a topic, the visitor (= IP address) who published the message
|
||||
is **banned from publishing to Firebase for 10 minutes** (not configurable). Because publishing to Firebase happens asynchronously,
|
||||
|
@ -828,7 +828,7 @@ Depending on *how you run it*, here are a few limits that are relevant:
|
|||
### Message cache
|
||||
By default, the [message cache](#message-cache) (defined by `cache-file`) uses the SQLite default settings, which means it
|
||||
syncs to disk on every write. For personal servers, this is perfectly adequate. For larger installations, such as ntfy.sh,
|
||||
the [write-ahead log (WAL)](https://sqlite.org/wal.html) should be enabled, and the sync mode should be adjusted.
|
||||
the [write-ahead log (WAL)](https://sqlite.org/wal.html) should be enabled, and the sync mode should be adjusted.
|
||||
See [this article](https://phiresky.github.io/blog/2020/sqlite-performance-tuning/) for details.
|
||||
|
||||
In addition to that, for very high load servers (such as ntfy.sh), it may be beneficial to write messages to the cache
|
||||
|
@ -900,7 +900,7 @@ If you put stuff on the Internet, bad actors will try to break them or break in.
|
|||
and nginx's [ngx_http_limit_req_module module](http://nginx.org/en/docs/http/ngx_http_limit_req_module.html) can be used
|
||||
to ban client IPs if they misbehave. This is on top of the [rate limiting](#rate-limiting) inside the ntfy server.
|
||||
|
||||
Here's an example for how ntfy.sh is configured, following the instructions from two tutorials ([here](https://easyengine.io/tutorials/nginx/fail2ban/)
|
||||
Here's an example for how ntfy.sh is configured, following the instructions from two tutorials ([here](https://easyengine.io/tutorials/nginx/fail2ban/)
|
||||
and [here](https://easyengine.io/tutorials/nginx/block-wp-login-php-bruteforce-attack/)):
|
||||
|
||||
=== "/etc/nginx/nginx.conf"
|
||||
|
@ -933,7 +933,7 @@ and [here](https://easyengine.io/tutorials/nginx/block-wp-login-php-bruteforce-a
|
|||
location / {
|
||||
limit_req zone=one burst=1000 nodelay;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
=== "/etc/fail2ban/filter.d/nginx-req-limit.conf"
|
||||
|
@ -957,15 +957,15 @@ and [here](https://easyengine.io/tutorials/nginx/block-wp-login-php-bruteforce-a
|
|||
|
||||
## Debugging/tracing
|
||||
If something's not working right, you can debug/trace through what the ntfy server is doing by setting the `log-level`
|
||||
to `DEBUG` or `TRACE`. The `DEBUG` setting will output information about each published message, but not the message
|
||||
contents. The `TRACE` setting will also print the message contents.
|
||||
to `DEBUG` or `TRACE`. The `DEBUG` setting will output information about each published message, but not the message
|
||||
contents. The `TRACE` setting will also print the message contents.
|
||||
|
||||
!!! warning
|
||||
Both options are very verbose and should only be enabled in production for short periods of time. Otherwise,
|
||||
Both options are very verbose and should only be enabled in production for short periods of time. Otherwise,
|
||||
you're going to run out of disk space pretty quickly.
|
||||
|
||||
You can also hot-reload the `log-level` by sending the `SIGHUP` signal to the process after editing the `server.yml` file.
|
||||
You can do so by calling `systemctl reload ntfy` (if ntfy is running inside systemd), or by calling `kill -HUP $(pidof ntfy)`.
|
||||
You can do so by calling `systemctl reload ntfy` (if ntfy is running inside systemd), or by calling `kill -HUP $(pidof ntfy)`.
|
||||
If successful, you'll see something like this:
|
||||
|
||||
```
|
||||
|
@ -981,8 +981,8 @@ CLI option (e.g. `--listen-http :80`. Here's a list of all available options. Al
|
|||
variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`).
|
||||
|
||||
!!! info
|
||||
All config options can also be defined in the `server.yml` file using underscores instead of dashes, e.g.
|
||||
`cache_duration` and `cache-duration` are both supported. This is to support stricter YAML parsers that do
|
||||
All config options can also be defined in the `server.yml` file using underscores instead of dashes, e.g.
|
||||
`cache_duration` and `cache-duration` are both supported. This is to support stricter YAML parsers that do
|
||||
not support dashes.
|
||||
|
||||
| Config option | Env variable | Format | Default | Description |
|
||||
|
@ -1028,7 +1028,7 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`).
|
|||
| `visitor-subscription-limit` | `NTFY_VISITOR_SUBSCRIPTION_LIMIT` | *number* | 30 | Rate limiting: Number of subscriptions per visitor (IP address) |
|
||||
| `web-root` | `NTFY_WEB_ROOT` | `app`, `home` or `disable` | `app` | Sets web root to landing page (home), web app (app) or disables the web app entirely (disable) |
|
||||
|
||||
The format for a *duration* is: `<number>(smh)`, e.g. 30s, 20m or 1h.
|
||||
The format for a *duration* is: `<number>(smh)`, e.g. 30s, 20m or 1h.
|
||||
The format for a *size* is: `<number>(GMK)`, e.g. 1G, 200M or 4000k.
|
||||
|
||||
## Command line options
|
||||
|
@ -1045,10 +1045,10 @@ CATEGORY:
|
|||
|
||||
DESCRIPTION:
|
||||
Run the ntfy server and listen for incoming requests
|
||||
|
||||
The command will load the configuration from /etc/ntfy/server.yml. Config options can
|
||||
|
||||
The command will load the configuration from /etc/ntfy/server.yml. Config options can
|
||||
be overridden using the command line options.
|
||||
|
||||
|
||||
Examples:
|
||||
ntfy serve # Starts server in the foreground (on port 80)
|
||||
ntfy serve --listen-http :8080 # Starts server with alternate port
|
||||
|
@ -1065,7 +1065,7 @@ OPTIONS:
|
|||
--cache-duration since, --cache_duration since, -b since buffer messages for this time to allow since requests (default: 12h0m0s) [$NTFY_CACHE_DURATION]
|
||||
--cache-file value, --cache_file value, -C value cache file used for message caching [$NTFY_CACHE_FILE]
|
||||
--cache-batch-size value, --cache_batch_size value max size of messages to batch together when writing to message cache (if zero, writes are synchronous) (default: 0) [$NTFY_BATCH_SIZE]
|
||||
--cache-batch-timeout value, --cache_batch_timeout value timeout for batched async writes to the message cache (if zero, writes are synchronous) (default: 0s) [$NTFY_CACHE_BATCH_TIMEOUT]
|
||||
--cache-batch-timeout value, --cache_batch_timeout value timeout for batched async writes to the message cache (if zero, writes are synchronous) (default: 0s) [$NTFY_CACHE_BATCH_TIMEOUT]
|
||||
--cache-startup-queries value, --cache_startup_queries value queries run when the cache database is initialized [$NTFY_CACHE_STARTUP_QUERIES]
|
||||
--cert-file value, --cert_file value, -E value certificate file, if listen-https is set [$NTFY_CERT_FILE]
|
||||
--config value, -c value config file (default: /etc/ntfy/server.yml) [$NTFY_CONFIG_FILE]
|
||||
|
@ -1099,4 +1099,3 @@ OPTIONS:
|
|||
--visitor-subscription-limit value, --visitor_subscription_limit value number of subscriptions per visitor (default: 30) [$NTFY_VISITOR_SUBSCRIPTION_LIMIT]
|
||||
--web-root value, --web_root value sets web root to landing page (home), web app (app) or disabled (disable) (default: "app") [$NTFY_WEB_ROOT]
|
||||
```
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Deprecation notices
|
||||
This page is used to list deprecation notices for ntfy. Deprecated commands and options will be
|
||||
This page is used to list deprecation notices for ntfy. Deprecated commands and options will be
|
||||
**removed after 1-3 months** from the time they were deprecated. How long the feature is deprecated
|
||||
before the behavior is changed depends on the severity of the change, and how prominent the feature is.
|
||||
|
||||
|
@ -34,7 +34,7 @@ and add a notice banner in the Android app instead.
|
|||
### Android app: Using `since=<timestamp>` instead of `since=<id>`
|
||||
> Active since 2022-02-27, behavior changed with v1.14.0
|
||||
|
||||
The Android app started using `since=<id>` instead of `since=<timestamp>`, which means as of Android app v1.14.0,
|
||||
The Android app started using `since=<id>` instead of `since=<timestamp>`, which means as of Android app v1.14.0,
|
||||
it will not work with servers older than v1.16.0 anymore. This is to simplify handling of deduplication in the Android app.
|
||||
|
||||
The `since=<timestamp>` endpoint will continue to work. This is merely a notice that the Android app behavior will change.
|
||||
|
@ -57,4 +57,3 @@ just the server.
|
|||
$ ntfy serve
|
||||
2021/12/17 08:16:01 Listening on :80/http
|
||||
```
|
||||
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
# Development
|
||||
Hurray 🥳 🎉, you are interested in writing code for ntfy! **That's awesome.** 😎
|
||||
|
||||
I tried my very best to write up detailed instructions, but if at any point in time you run into issues, don't
|
||||
I tried my very best to write up detailed instructions, but if at any point in time you run into issues, don't
|
||||
hesitate to **contact me on [Discord](https://discord.gg/cT7ECsZj9w) or [Matrix](https://matrix.to/#/#ntfy:matrix.org)**.
|
||||
|
||||
## ntfy server
|
||||
The ntfy server source code is available [on GitHub](https://github.com/binwiederhier/ntfy). The codebase for the
|
||||
server consists of three components:
|
||||
|
||||
* **The main server/client** is written in [Go](https://go.dev/) (so you'll need Go). Its main entrypoint is at
|
||||
[main.go](https://github.com/binwiederhier/ntfy/blob/main/main.go), and the meat you're likely interested in is
|
||||
in [server.go](https://github.com/binwiederhier/ntfy/blob/main/server/server.go). Notably, the server uses a
|
||||
[SQLite](https://sqlite.org) library called [go-sqlite3](https://github.com/mattn/go-sqlite3), which requires
|
||||
* **The main server/client** is written in [Go](https://go.dev/) (so you'll need Go). Its main entrypoint is at
|
||||
[main.go](https://github.com/binwiederhier/ntfy/blob/main/main.go), and the meat you're likely interested in is
|
||||
in [server.go](https://github.com/binwiederhier/ntfy/blob/main/server/server.go). Notably, the server uses a
|
||||
[SQLite](https://sqlite.org) library called [go-sqlite3](https://github.com/mattn/go-sqlite3), which requires
|
||||
[Cgo](https://go.dev/blog/cgo) and `CGO_ENABLED=1` to be set. Otherwise things will not work (see below).
|
||||
* **The documentation** is generated by [MkDocs](https://www.mkdocs.org/) and [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/),
|
||||
which is written in [Python](https://www.python.org/). You'll need Python and MkDocs (via `pip`) only if you want to
|
||||
build the docs.
|
||||
* **The web app** is written in [React](https://reactjs.org/), using [MUI](https://mui.com/). It uses [Create React App](https://create-react-app.dev/)
|
||||
to build the production build. If you want to modify the web app, you need [nodejs](https://nodejs.org/en/) (for `npm`)
|
||||
to build the production build. If you want to modify the web app, you need [nodejs](https://nodejs.org/en/) (for `npm`)
|
||||
and install all the 100,000 dependencies (*sigh*).
|
||||
|
||||
All of these components are built and then **baked into one binary**.
|
||||
All of these components are built and then **baked into one binary**.
|
||||
|
||||
### Navigating the code
|
||||
Code:
|
||||
|
@ -44,7 +44,7 @@ The `web/` and `docs/` folder are the sources for web app and documentation. Dur
|
|||
the generated output is copied to `server/site` (web app and landing page) and `server/docs` (documentation).
|
||||
|
||||
### Build/test on Gitpod
|
||||
To get a quick working development environment you can use [Gitpod](https://gitpod.io), an in-browser IDE
|
||||
To get a quick working development environment you can use [Gitpod](https://gitpod.io), an in-browser IDE
|
||||
that makes it easy to develop ntfy without having to set up a desktop IDE. For any real development,
|
||||
I do suggest a proper IDE like [IntelliJ IDEA](https://www.jetbrains.com/idea/).
|
||||
|
||||
|
@ -57,7 +57,7 @@ I do suggest a proper IDE like [IntelliJ IDEA](https://www.jetbrains.com/idea/).
|
|||
* [Make](https://www.gnu.org/software/make/) (required for convenience)
|
||||
* [libsqlite3/libsqlite3-dev](https://www.sqlite.org/) (required for main server, for SQLite cgo-based bindings)
|
||||
* [GoReleaser](https://goreleaser.com/) (required for a proper main server build)
|
||||
* [Python](https://www.python.org/) (for `pip`, only to build the docs)
|
||||
* [Python](https://www.python.org/) (for `pip`, only to build the docs)
|
||||
* [nodejs](https://nodejs.org/en/) (for `npm`, only to build the web app)
|
||||
|
||||
### Install dependencies
|
||||
|
@ -107,16 +107,16 @@ Now check out via git from the [GitHub repository](https://github.com/binwiederh
|
|||
|
||||
=== "via SSH"
|
||||
``` shell
|
||||
git clone git@github.com:binwiederhier/ntfy.git
|
||||
git clone git@github.com:binwiederhier/ntfy.git
|
||||
cd ntfy
|
||||
```
|
||||
|
||||
### Build all the things
|
||||
Now you can finally build everything. There are tons of `make` targets, so maybe just review what's there first
|
||||
Now you can finally build everything. There are tons of `make` targets, so maybe just review what's there first
|
||||
by typing `make`:
|
||||
|
||||
``` shell
|
||||
$ make
|
||||
$ make
|
||||
Typical commands (more see below):
|
||||
make build - Build web app, documentation and server/client (sloowwww)
|
||||
make cli-linux-amd64 - Build server/client binary (amd64, no web app or docs)
|
||||
|
@ -127,20 +127,20 @@ Typical commands (more see below):
|
|||
...
|
||||
```
|
||||
|
||||
If you want to build the **ntfy binary including web app and docs for all supported architectures** (amd64, armv7, and arm64),
|
||||
If you want to build the **ntfy binary including web app and docs for all supported architectures** (amd64, armv7, and arm64),
|
||||
you can simply run `make build`:
|
||||
|
||||
``` shell
|
||||
$ make build
|
||||
...
|
||||
# This builds web app, docs, and the ntfy binary (for amd64, armv7 and arm64).
|
||||
# This builds web app, docs, and the ntfy binary (for amd64, armv7 and arm64).
|
||||
# This will be SLOW (5+ minutes on my laptop on the first run). Maybe look at the other make targets?
|
||||
```
|
||||
|
||||
You'll see all the outputs in the `dist/` folder afterwards:
|
||||
|
||||
``` bash
|
||||
$ find dist
|
||||
$ find dist
|
||||
dist
|
||||
dist/metadata.json
|
||||
dist/ntfy_arm64_linux_arm64
|
||||
|
@ -153,7 +153,7 @@ dist/config.yaml
|
|||
dist/artifacts.json
|
||||
```
|
||||
|
||||
If you also want to build the **Debian/RPM packages and the Docker images for all supported architectures**, you can
|
||||
If you also want to build the **Debian/RPM packages and the Docker images for all supported architectures**, you can
|
||||
use the `make release-snapshot` target:
|
||||
|
||||
``` shell
|
||||
|
@ -188,7 +188,7 @@ $ make cli-linux-amd64 install-linux-amd64
|
|||
$ ntfy serve
|
||||
```
|
||||
|
||||
**During development of the main app, you can also just use `go run main.go`**, as long as you run
|
||||
**During development of the main app, you can also just use `go run main.go`**, as long as you run
|
||||
`make cli-deps-static-sites`at least once and `CGO_ENABLED=1`:
|
||||
|
||||
``` shell
|
||||
|
@ -209,11 +209,11 @@ This is because we use `go:embed` to embed the documentation and web app, so the
|
|||
present at `server/docs` and `server/site`. If they are not, you'll see the above error. The `cli-deps-static-sites`
|
||||
target creates dummy files that ensure that you'll be able to build.
|
||||
|
||||
While not officially supported (or released), you can build and run the server **on macOS** as well. Simply run
|
||||
While not officially supported (or released), you can build and run the server **on macOS** as well. Simply run
|
||||
`make cli-darwin-server` to build a binary, or `go run main.go serve` (see above) to run it.
|
||||
|
||||
### Build the web app
|
||||
The sources for the web app live in `web/`. As long as you have `npm` installed (see above), building the web app
|
||||
The sources for the web app live in `web/`. As long as you have `npm` installed (see above), building the web app
|
||||
is really simple. Just type `make web` and you're in business:
|
||||
|
||||
``` shell
|
||||
|
@ -221,11 +221,11 @@ $ make web
|
|||
...
|
||||
```
|
||||
|
||||
This will build the web app using Create React App and then **copy the production build to the `server/site` folder**, so
|
||||
This will build the web app using Create React App and then **copy the production build to the `server/site` folder**, so
|
||||
that when you `make cli` (or `make cli-linux-amd64`, ...), you will have the web app included in the `ntfy` binary.
|
||||
|
||||
If you're developing on the web app, it's best to just `cd web` and run `npm start` manually. This will open your browser
|
||||
at `http://127.0.0.1:3000` with the web app, and as you edit the source files, they will be recompiled and the browser
|
||||
at `http://127.0.0.1:3000` with the web app, and as you edit the source files, they will be recompiled and the browser
|
||||
will automatically refresh:
|
||||
|
||||
``` shell
|
||||
|
@ -234,7 +234,7 @@ $ npm start
|
|||
```
|
||||
|
||||
### Build the docs
|
||||
The sources for the docs live in `docs/`. Similarly to the web app, you can simply run `make docs` to build the
|
||||
The sources for the docs live in `docs/`. Similarly to the web app, you can simply run `make docs` to build the
|
||||
documentation. As long as you have `mkdocs` installed (see above), this should work fine:
|
||||
|
||||
``` shell
|
||||
|
@ -242,8 +242,8 @@ $ make docs
|
|||
...
|
||||
```
|
||||
|
||||
If you are changing the documentation, you should be running `mkdocs serve` directly. This will build the documentation,
|
||||
serve the files at `http://127.0.0.1:8000/`, and rebuild every time you save the source files:
|
||||
If you are changing the documentation, you should be running `mkdocs serve` directly. This will build the documentation,
|
||||
serve the files at `http://127.0.0.1:8000/`, and rebuild every time you save the source files:
|
||||
|
||||
```
|
||||
$ mkdocs serve
|
||||
|
@ -269,8 +269,8 @@ The Android app has two flavors:
|
|||
* [build.gradle](https://github.com/binwiederhier/ntfy-android/blob/main/app/build.gradle) - Main build file
|
||||
|
||||
### IDE/Environment
|
||||
You should download [Android Studio](https://developer.android.com/studio) (or [IntelliJ IDEA](https://www.jetbrains.com/idea/)
|
||||
with the relevant Android plugins). Everything else will just be a pain for you. Do yourself a favor. 😀
|
||||
You should download [Android Studio](https://developer.android.com/studio) (or [IntelliJ IDEA](https://www.jetbrains.com/idea/)
|
||||
with the relevant Android plugins). Everything else will just be a pain for you. Do yourself a favor. 😀
|
||||
|
||||
### Check out the code
|
||||
First check out the repository:
|
||||
|
|
|
@ -33,10 +33,10 @@ GitHub have been hopeless. In case it ever becomes available, I want to know imm
|
|||
|
||||
|
||||
## Low disk space alerts
|
||||
Here's a simple cronjob that I use to alert me when the disk space on the root disk is running low. It's simple, but
|
||||
effective.
|
||||
Here's a simple cronjob that I use to alert me when the disk space on the root disk is running low. It's simple, but
|
||||
effective.
|
||||
|
||||
``` bash
|
||||
``` bash
|
||||
#!/bin/bash
|
||||
|
||||
mingigs=10
|
||||
|
@ -78,7 +78,7 @@ to notify yourself on SSH login.
|
|||
|
||||
## Collect data from multiple machines
|
||||
The other day I was running tasks on 20 servers, and I wanted to collect the interim results
|
||||
as a CSV in one place. Each of the servers was publishing to a topic as the results completed (`publish-result.sh`),
|
||||
as a CSV in one place. Each of the servers was publishing to a topic as the results completed (`publish-result.sh`),
|
||||
and I had one central collector to grab the results as they came in (`collect-results.sh`).
|
||||
|
||||
It looked something like this:
|
||||
|
@ -89,10 +89,10 @@ It looked something like this:
|
|||
[ -n "$result" ] && echo "$result" >> results.csv
|
||||
done < <(stdbuf -i0 -o0 curl -s ntfy.sh/results/raw)
|
||||
```
|
||||
=== "publish-result.sh"
|
||||
=== "publish-result.sh"
|
||||
```bash
|
||||
// This script was run on each of the 20 servers. It was doing heavy processing ...
|
||||
|
||||
|
||||
// Publish script results
|
||||
curl -d "$(hostname),$count,$time" ntfy.sh/results
|
||||
```
|
||||
|
@ -136,7 +136,7 @@ You can send a message during a workflow run with curl. Here is an example sendi
|
|||
```
|
||||
|
||||
## Watchtower (shoutrrr)
|
||||
You can use [shoutrrr](https://github.com/containrrr/shoutrrr) generic webhook support to send
|
||||
You can use [shoutrrr](https://github.com/containrrr/shoutrrr) generic webhook support to send
|
||||
[Watchtower](https://github.com/containrrr/watchtower/) notifications to your ntfy topic.
|
||||
|
||||
Example docker-compose.yml:
|
||||
|
@ -156,7 +156,7 @@ shoutrrr send -u "generic+https://ntfy.sh/my_watchtower_topic?title=WatchtowerUp
|
|||
|
||||
## Sonarr, Radarr, Lidarr, Readarr, Prowlarr, SABnzbd
|
||||
It's possible to use custom scripts for all the *arr services, plus SABnzbd. Notifications for downloads, warnings, grabs etc.
|
||||
Some simple bash scripts to achieve this are kindly provided in [nickexyz's repository](https://github.com/nickexyz/ntfy-shellscripts).
|
||||
Some simple bash scripts to achieve this are kindly provided in [nickexyz's repository](https://github.com/nickexyz/ntfy-shellscripts).
|
||||
|
||||
## Node-RED
|
||||
You can use the HTTP request node to send messages with [Node-RED](https://nodered.org), some examples:
|
||||
|
@ -503,7 +503,7 @@ Select **Alert Contact Type** = Webhook. Then set your desired **Friendly Name**
|
|||
{
|
||||
"topic":"myTopic",
|
||||
"title": "*monitorFriendlyName* *alertTypeFriendlyName*",
|
||||
"message": "*alertDetails*",
|
||||
"message": "*alertDetails*",
|
||||
"tags": ["green_circle"],
|
||||
"priority": 3,
|
||||
"click": https://uptimerobot.com/dashboard#*monitorID*
|
||||
|
@ -515,7 +515,7 @@ You can create two Alert Contacts each with a different icon and priority, for e
|
|||
{
|
||||
"topic":"myTopic",
|
||||
"title": "*monitorFriendlyName* *alertTypeFriendlyName*",
|
||||
"message": "*alertDetails*",
|
||||
"message": "*alertDetails*",
|
||||
"tags": ["red_circle"],
|
||||
"priority": 3,
|
||||
"click": https://uptimerobot.com/dashboard#*monitorID*
|
||||
|
@ -529,7 +529,7 @@ You can now add the created Alerts Contact(s) to the monitor(s) and test the not
|
|||
|
||||
|
||||
## Apprise
|
||||
ntfy is integrated natively into [Apprise](https://github.com/caronc/apprise) (also check out the
|
||||
ntfy is integrated natively into [Apprise](https://github.com/caronc/apprise) (also check out the
|
||||
[Apprise/ntfy wiki page](https://github.com/caronc/apprise/wiki/Notify_ntfy)).
|
||||
|
||||
You can use it like this:
|
||||
|
@ -548,7 +548,7 @@ apprise -vv -t "Test Message Title" -b "Test Message Body" \
|
|||
|
||||
|
||||
## Rundeck
|
||||
Rundeck by default sends only HTML email which is not processed by ntfy SMTP server. Append following configurations to
|
||||
Rundeck by default sends only HTML email which is not processed by ntfy SMTP server. Append following configurations to
|
||||
[rundeck-config.properties](https://docs.rundeck.com/docs/administration/configuration/config-file-reference.html) :
|
||||
|
||||
```
|
||||
|
@ -570,5 +570,3 @@ Example `template.html`:
|
|||
|
||||
Add notification on Rundeck (attachment type must be: `Attached as file to email`):
|
||||

|
||||
|
||||
|
||||
|
|
24
docs/faq.md
24
docs/faq.md
|
@ -8,15 +8,15 @@ Yes. As long as you don't abuse it, it'll be available and free of charge. While
|
|||
server without signup and free of charge, I may also offer paid plans in the future.
|
||||
|
||||
## What are the uptime guarantees?
|
||||
Best effort.
|
||||
Best effort.
|
||||
|
||||
ntfy currently runs on a single DigitalOcean droplet, without any scale out strategy or redundancies. When the time comes,
|
||||
I'll add scale out features, but for now it is what it is.
|
||||
|
||||
In the first year of its life, and to this day (Dec'22), ntfy had **no outages** that I can remember. Other than short
|
||||
blips and some HTTP 500 spikes, it has been rock solid.
|
||||
In the first year of its life, and to this day (Dec'22), ntfy had **no outages** that I can remember. Other than short
|
||||
blips and some HTTP 500 spikes, it has been rock solid.
|
||||
|
||||
There is a [status page](https://ntfy.statuspage.io/) which is updated based on some automated checks via the amazingly
|
||||
There is a [status page](https://ntfy.statuspage.io/) which is updated based on some automated checks via the amazingly
|
||||
awesome [healthchecks.io](https://healthchecks.io/) (_no affiliation, just a fan_).
|
||||
|
||||
## What happens if there are multiple subscribers to the same topic?
|
||||
|
@ -25,7 +25,7 @@ As per usual with pub-sub, all subscribers receive notifications if they are sub
|
|||
## Will you know what topics exist, can you spy on me?
|
||||
If you don't trust me or your messages are sensitive, run your own server. It's open source.
|
||||
That said, the logs do contain topic names and IP addresses, but I don't use them for anything other than
|
||||
troubleshooting and rate limiting. Messages are cached for the duration configured in `server.yml` (12h by default)
|
||||
troubleshooting and rate limiting. Messages are cached for the duration configured in `server.yml` (12h by default)
|
||||
to facilitate service restarts, message polling and to overcome client network disruptions.
|
||||
|
||||
## Can I self-host it?
|
||||
|
@ -35,16 +35,16 @@ your own server as well. Check out the [install instructions](install.md).
|
|||
## Is Firebase used?
|
||||
In addition to caching messages locally and delivering them to long-polling subscribers, all messages are also
|
||||
published to Firebase Cloud Messaging (FCM) (if `FirebaseKeyFile` is set, which it is on ntfy.sh). This
|
||||
is to facilitate notifications on Android.
|
||||
is to facilitate notifications on Android.
|
||||
|
||||
If you do not care for Firebase, I suggest you install the [F-Droid version](https://f-droid.org/en/packages/io.heckel.ntfy/)
|
||||
of the app and [self-host your own ntfy server](install.md).
|
||||
|
||||
## How much battery does the Android app use?
|
||||
If you use the ntfy.sh server, and you don't use the [instant delivery](subscribe/phone.md#instant-delivery) feature,
|
||||
the Android/iOS app uses no additional battery, since Firebase Cloud Messaging (FCM) is used. If you use your own server,
|
||||
or you use *instant delivery* (Android only), the app has to maintain a constant connection to the server, which consumes
|
||||
about 0-1% of battery in 17h of use (on my phone). There has been a ton of testing and improvement around this. I think it's pretty
|
||||
If you use the ntfy.sh server, and you don't use the [instant delivery](subscribe/phone.md#instant-delivery) feature,
|
||||
the Android/iOS app uses no additional battery, since Firebase Cloud Messaging (FCM) is used. If you use your own server,
|
||||
or you use *instant delivery* (Android only), the app has to maintain a constant connection to the server, which consumes
|
||||
about 0-1% of battery in 17h of use (on my phone). There has been a ton of testing and improvement around this. I think it's pretty
|
||||
decent now.
|
||||
|
||||
## What is instant delivery?
|
||||
|
@ -63,10 +63,10 @@ it, or hopefully, somebody else will come along and help out. Please review the
|
|||
|
||||
## Can I disable the web app? Can I protect it with a login screen?
|
||||
The web app is a static website without a backend (other than the ntfy API). All data is stored locally in the browser
|
||||
cache and local storage. That means it does not need to be protected with a login screen, and it poses no additional
|
||||
cache and local storage. That means it does not need to be protected with a login screen, and it poses no additional
|
||||
security risk. So technically, it does not need to be disabled.
|
||||
|
||||
However, if you still want to disable it, you can do so with the `web-root: disable` option in the `server.yml` file.
|
||||
However, if you still want to disable it, you can do so with the `web-root: disable` option in the `server.yml` file.
|
||||
|
||||
Think of the ntfy web app like an Android/iOS app. It is freely available and accessible to anyone, yet useless without
|
||||
a proper backend. So as long as you secure your backend with ACLs, exposing the ntfy web app to the Internet is harmless.
|
||||
|
|
|
@ -9,8 +9,8 @@ or POST requests. I use it to notify myself when scripts fail, or long-running c
|
|||
|
||||
To [receive notifications on your phone](subscribe/phone.md), install the app, either via Google Play or F-Droid.
|
||||
Once installed, open it and subscribe to a topic of your choosing. Topics don't have to explicitly be created, so just
|
||||
pick a name and use it later when you [publish a message](publish.md). Note that **topic names are public, so it's wise
|
||||
to choose something that cannot be guessed easily.**
|
||||
pick a name and use it later when you [publish a message](publish.md). Note that **topic names are public, so it's wise
|
||||
to choose something that cannot be guessed easily.**
|
||||
|
||||
For this guide, we'll just use `mytopic` as our topic name:
|
||||
|
||||
|
@ -23,7 +23,7 @@ That's it. After you tap "Subscribe", the app is listening for new messages on t
|
|||
|
||||
## Step 2: Send a message
|
||||
Now let's [send a message](publish.md) to our topic. It's easy in every language, since we're just using HTTP PUT/POST,
|
||||
or with the [ntfy CLI](install.md). The message is in the request body. Here's an example showing how to publish a
|
||||
or with the [ntfy CLI](install.md). The message is in the request body. Here's an example showing how to publish a
|
||||
simple message using a POST request:
|
||||
|
||||
=== "Command line (curl)"
|
||||
|
@ -40,7 +40,7 @@ simple message using a POST request:
|
|||
``` http
|
||||
POST /mytopic HTTP/1.1
|
||||
Host: ntfy.sh
|
||||
|
||||
|
||||
Backup successful 😀
|
||||
```
|
||||
|
||||
|
@ -91,5 +91,3 @@ Here's another video showing the entire process:
|
|||
<video controls muted autoplay loop width="650" src="static/img/android-video-overview.mp4"></video>
|
||||
<figcaption>Sending push notifications to your Android phone</figcaption>
|
||||
</figure>
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Installing ntfy
|
||||
The `ntfy` CLI allows you to [publish messages](publish.md), [subscribe to topics](subscribe/cli.md) as well as to
|
||||
self-host your own ntfy server. It's all pretty straight forward. Just install the binary, package or Docker image,
|
||||
configure it and run it. Just like any other software. No fuzz.
|
||||
self-host your own ntfy server. It's all pretty straight forward. Just install the binary, package or Docker image,
|
||||
configure it and run it. Just like any other software. No fuzz.
|
||||
|
||||
!!! info
|
||||
The following steps are only required if you want to **self-host your own ntfy server or you want to use the ntfy CLI**.
|
||||
|
@ -18,7 +18,7 @@ We support amd64, armv7 and arm64.
|
|||
|
||||
To run the ntfy server, then just run `ntfy serve` (or `systemctl start ntfy` when using the deb/rpm).
|
||||
To send messages, use `ntfy publish`. To subscribe to topics, use `ntfy subscribe` (see [subscribing via CLI](subscribe/cli.md)
|
||||
for details).
|
||||
for details).
|
||||
|
||||
## Linux binaries
|
||||
Please check out the [releases page](https://github.com/binwiederhier/ntfy/releases) for binaries and
|
||||
|
@ -69,7 +69,7 @@ Installation via Debian repository:
|
|||
curl -fsSL https://archive.heckel.io/apt/pubkey.txt | sudo gpg --dearmor -o /etc/apt/keyrings/archive.heckel.io.gpg
|
||||
sudo apt install apt-transport-https
|
||||
sudo sh -c "echo 'deb [arch=amd64 signed-by=/etc/apt/keyrings/archive.heckel.io.gpg] https://archive.heckel.io/apt debian main' \
|
||||
> /etc/apt/sources.list.d/archive.heckel.io.list"
|
||||
> /etc/apt/sources.list.d/archive.heckel.io.list"
|
||||
sudo apt update
|
||||
sudo apt install ntfy
|
||||
sudo systemctl enable ntfy
|
||||
|
@ -141,7 +141,7 @@ Manually installing the .deb file:
|
|||
=== "x86_64/amd64"
|
||||
```bash
|
||||
sudo rpm -ivh https://github.com/binwiederhier/ntfy/releases/download/v1.29.1/ntfy_1.29.1_linux_amd64.rpm
|
||||
sudo systemctl enable ntfy
|
||||
sudo systemctl enable ntfy
|
||||
sudo systemctl start ntfy
|
||||
```
|
||||
|
||||
|
@ -155,14 +155,14 @@ Manually installing the .deb file:
|
|||
=== "armv7/armhf"
|
||||
```bash
|
||||
sudo rpm -ivh https://github.com/binwiederhier/ntfy/releases/download/v1.29.1/ntfy_1.29.1_linux_armv7.rpm
|
||||
sudo systemctl enable ntfy
|
||||
sudo systemctl enable ntfy
|
||||
sudo systemctl start ntfy
|
||||
```
|
||||
|
||||
=== "arm64"
|
||||
```bash
|
||||
sudo rpm -ivh https://github.com/binwiederhier/ntfy/releases/download/v1.29.1/ntfy_1.29.1_linux_arm64.rpm
|
||||
sudo systemctl enable ntfy
|
||||
sudo systemctl enable ntfy
|
||||
sudo systemctl start ntfy
|
||||
```
|
||||
|
||||
|
@ -185,35 +185,35 @@ ntfy is packaged in nixpkgs as `ntfy-sh`. It can be installed by adding the pack
|
|||
nix-env -iA ntfy-sh
|
||||
```
|
||||
|
||||
NixOS also supports [declarative setup of the ntfy server](https://search.nixos.org/options?channel=unstable&show=services.ntfy-sh.enable&from=0&size=50&sort=relevance&type=packages&query=ntfy).
|
||||
NixOS also supports [declarative setup of the ntfy server](https://search.nixos.org/options?channel=unstable&show=services.ntfy-sh.enable&from=0&size=50&sort=relevance&type=packages&query=ntfy).
|
||||
|
||||
## macOS
|
||||
The [ntfy CLI](subscribe/cli.md) (`ntfy publish` and `ntfy subscribe` only) is supported on macOS as well.
|
||||
To install, please [download the tarball](https://github.com/binwiederhier/ntfy/releases/download/v1.29.1/ntfy_1.29.1_macOS_all.tar.gz),
|
||||
extract it and place it somewhere in your `PATH` (e.g. `/usr/local/bin/ntfy`).
|
||||
The [ntfy CLI](subscribe/cli.md) (`ntfy publish` and `ntfy subscribe` only) is supported on macOS as well.
|
||||
To install, please [download the tarball](https://github.com/binwiederhier/ntfy/releases/download/v1.29.1/ntfy_1.29.1_macOS_all.tar.gz),
|
||||
extract it and place it somewhere in your `PATH` (e.g. `/usr/local/bin/ntfy`).
|
||||
|
||||
If run as `root`, ntfy will look for its config at `/etc/ntfy/client.yml`. For all other users, it'll look for it at
|
||||
If run as `root`, ntfy will look for its config at `/etc/ntfy/client.yml`. For all other users, it'll look for it at
|
||||
`~/Library/Application Support/ntfy/client.yml` (sample included in the tarball).
|
||||
|
||||
```bash
|
||||
curl -L https://github.com/binwiederhier/ntfy/releases/download/v1.29.1/ntfy_1.29.1_macOS_all.tar.gz > ntfy_1.29.1_macOS_all.tar.gz
|
||||
tar zxvf ntfy_1.29.1_macOS_all.tar.gz
|
||||
sudo cp -a ntfy_1.29.1_macOS_all/ntfy /usr/local/bin/ntfy
|
||||
mkdir ~/Library/Application\ Support/ntfy
|
||||
mkdir ~/Library/Application\ Support/ntfy
|
||||
cp ntfy_1.29.1_macOS_all/client/client.yml ~/Library/Application\ Support/ntfy/client.yml
|
||||
ntfy --help
|
||||
```
|
||||
|
||||
!!! info
|
||||
There is a [GitHub issue](https://github.com/binwiederhier/ntfy/issues/286) about making ntfy installable via
|
||||
[Homebrew](https://brew.sh/). I'll eventually get to that, but I'd also love if somebody else stepped up to do it.
|
||||
Also, you can build and run the ntfy server on macOS as well, though I don't officially support that.
|
||||
[Homebrew](https://brew.sh/). I'll eventually get to that, but I'd also love if somebody else stepped up to do it.
|
||||
Also, you can build and run the ntfy server on macOS as well, though I don't officially support that.
|
||||
Check out the [build instructions](develop.md) for details.
|
||||
|
||||
## Windows
|
||||
The [ntfy CLI](subscribe/cli.md) (`ntfy publish` and `ntfy subscribe` only) is supported on Windows as well.
|
||||
To install, please [download the latest ZIP](https://github.com/binwiederhier/ntfy/releases/download/v1.29.1/ntfy_1.29.1_windows_x86_64.zip),
|
||||
extract it and place the `ntfy.exe` binary somewhere in your `%Path%`.
|
||||
extract it and place the `ntfy.exe` binary somewhere in your `%Path%`.
|
||||
|
||||
The default path for the client config file is at `%AppData%\ntfy\client.yml` (not created automatically, sample in the ZIP file).
|
||||
|
||||
|
@ -226,15 +226,15 @@ Also available in [Scoop's](https://scoop.sh) Main repository:
|
|||
[GitHub issue](https://github.com/binwiederhier/ntfy/issues) to let me know.
|
||||
|
||||
## Docker
|
||||
The [ntfy image](https://hub.docker.com/r/binwiederhier/ntfy) is available for amd64, armv6, armv7 and arm64. It should
|
||||
The [ntfy image](https://hub.docker.com/r/binwiederhier/ntfy) is available for amd64, armv6, armv7 and arm64. It should
|
||||
be pretty straight forward to use.
|
||||
|
||||
The server exposes its web UI and the API on port 80, so you need to expose that in Docker. To use the persistent
|
||||
[message cache](config.md#message-cache), you also need to map a volume to `/var/cache/ntfy`. To change other settings,
|
||||
The server exposes its web UI and the API on port 80, so you need to expose that in Docker. To use the persistent
|
||||
[message cache](config.md#message-cache), you also need to map a volume to `/var/cache/ntfy`. To change other settings,
|
||||
you should map `/etc/ntfy`, so you can edit `/etc/ntfy/server.yml`.
|
||||
|
||||
!!! info
|
||||
Note that the Docker image **does not contain a `/etc/ntfy/server.yml` file**. If you'd like to use a config file,
|
||||
Note that the Docker image **does not contain a `/etc/ntfy/server.yml` file**. If you'd like to use a config file,
|
||||
please manually create one outside the image and map it as a volume, e.g. via `-v /etc/ntfy:/etc/ntfy`. You may
|
||||
use the [`server.yml` file on GitHub](https://github.com/binwiederhier/ntfy/blob/main/server/server.yml) as a template.
|
||||
|
||||
|
@ -438,7 +438,7 @@ Configuration is relatively straightforward. As an example, a minimal configurat
|
|||
|
||||
=== "from-file"
|
||||
```bash
|
||||
kubectl create configmap ntfy --from-file=server.yml
|
||||
kubectl create configmap ntfy --from-file=server.yml
|
||||
```
|
||||
|
||||
## Kustomize
|
||||
|
@ -447,16 +447,16 @@ ntfy can be deployed in a Kubernetes cluster with [Kustomize](https://github.com
|
|||
to customize Kubernetes objects using a `kustomization.yaml` file.
|
||||
|
||||
1. Create new folder - `ntfy`
|
||||
2. Add all files listed below
|
||||
2. Add all files listed below
|
||||
1. `kustomization.yaml` - stores all configmaps and resources used in a deployment
|
||||
2. `ntfy-deployment.yaml` - define deployment type and its parameters
|
||||
3. `ntfy-pvc.yaml` - describes how [persistent volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) will be created
|
||||
3. `ntfy-pvc.yaml` - describes how [persistent volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) will be created
|
||||
4. `ntfy-svc.yaml` - expose application to the internal kubernetes network
|
||||
5. `ntfy-ingress.yaml` - expose service to outside the network using [ingress controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/)
|
||||
6. `server.yaml` - simple server configuration
|
||||
3. Replace **TESTNAMESPACE** within `kustomization.yaml` with designated namespace
|
||||
3. Replace **TESTNAMESPACE** within `kustomization.yaml` with designated namespace
|
||||
4. Replace **ntfy.test** within `ntfy-ingress.yaml` with desired DNS name
|
||||
5. Apply configuration to cluster set in current context:
|
||||
5. Apply configuration to cluster set in current context:
|
||||
|
||||
```bash
|
||||
kubectl apply -k /ntfy
|
||||
|
@ -473,9 +473,9 @@ kubectl apply -k /ntfy
|
|||
- ntfy-ingress.yaml # ingress definition
|
||||
configMapGenerator: # will parse config from raw config to configmap,it allows for dynamic reload of application if additional app is deployed ie https://github.com/stakater/Reloader
|
||||
- name: server-config
|
||||
files:
|
||||
files:
|
||||
- server.yml
|
||||
namespace: TESTNAMESPACE # select namespace for whole application
|
||||
namespace: TESTNAMESPACE # select namespace for whole application
|
||||
```
|
||||
=== "ntfy-deployment.yaml"
|
||||
```yaml
|
||||
|
@ -497,7 +497,7 @@ kubectl apply -k /ntfy
|
|||
app: ntfy-pod
|
||||
spec:
|
||||
containers:
|
||||
- name: ntfy
|
||||
- name: ntfy
|
||||
image: binwiederhier/ntfy:v1.28.0 # set deployed version
|
||||
args: ["serve"]
|
||||
env: #example of adjustments made in environmental variables
|
||||
|
@ -508,8 +508,8 @@ kubectl apply -k /ntfy
|
|||
- name: NTFY_LOG_LEVEL # adjust log level
|
||||
value: INFO
|
||||
- name: NTFY_BASE_URL # add base url
|
||||
value: XXXXXXXXXX
|
||||
ports:
|
||||
value: XXXXXXXXXX
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http-ntfy
|
||||
resources:
|
||||
|
@ -533,7 +533,7 @@ kubectl apply -k /ntfy
|
|||
persistentVolumeClaim: # stores /cache/ntfy in defined pv
|
||||
claimName: ntfy-pvc
|
||||
```
|
||||
|
||||
|
||||
=== "ntfy-pvc.yaml"
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
|
@ -554,7 +554,7 @@ kubectl apply -k /ntfy
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: ntfy-svc
|
||||
name: ntfy-svc
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
|
|
|
@ -6,7 +6,7 @@ I've added a ⭐ to projects or posts that have a significant following, or had
|
|||
|
||||
## Public ntfy servers
|
||||
|
||||
Here's a list of public ntfy servers. As of right now, there is only one official server. The others are provided by the
|
||||
Here's a list of public ntfy servers. As of right now, there is only one official server. The others are provided by the
|
||||
ntfy community. Thanks to everyone running a public server. **You guys rock!**
|
||||
|
||||
| URL | Country |
|
||||
|
@ -43,7 +43,7 @@ and uptime of third party servers, so use of each server is **at your own discre
|
|||
- [FindMyDevice](https://gitlab.com/Nulide/findmydevice/) - Find your Device with an SMS or online with the help of FMDServer
|
||||
- [Tox Push Message App](https://github.com/zoff99/tox_push_msg_app) - Tox Push Message App
|
||||
|
||||
## Libraries
|
||||
## Libraries
|
||||
|
||||
- [ntfy-php-library](https://github.com/VerifiedJoseph/ntfy-php-library) - PHP library for sending messages using a ntfy server (PHP)
|
||||
- [ntfy-notifier](https://github.com/DAcodedBEAT/ntfy-notifier) - Symfony Notifier integration for ntfy (PHP)
|
||||
|
@ -65,7 +65,7 @@ and uptime of third party servers, so use of each server is **at your own discre
|
|||
- [ntfyr](https://github.com/haxwithaxe/ntfyr) - A simple commandline tool to send notifications to ntfy
|
||||
- [ntfy.py](https://github.com/ioqy/ntfy-client-python) - ntfy.py is a simple nfty.sh client for sending notifications
|
||||
|
||||
## Projects + scripts
|
||||
## Projects + scripts
|
||||
|
||||
- [Grafana-to-ntfy](https://github.com/kittyandrew/grafana-to-ntfy) - Grafana-to-ntfy alerts channel (Rust)
|
||||
- [ntfy-long-zsh-command](https://github.com/robfox92/ntfy-long-zsh-command) - Notifies you once a long-running command completes (zsh)
|
||||
|
@ -97,16 +97,16 @@ and uptime of third party servers, so use of each server is **at your own discre
|
|||
- [ntfy-notification-channel](https://github.com/wijourdil/ntfy-notification-channel) - Laravel Notification channel for ntfy (PHP)
|
||||
- [ntfy_on_a_chip](https://github.com/gergepalfi/ntfy_on_a_chip) - ESP8266 and ESP32 client code to communicate with ntfy
|
||||
- [ntfy-sdk](https://github.com/yukibtc/ntfy-sdk) - ntfy client library to send notifications (Rust)
|
||||
- [ntfy_ynh](https://github.com/YunoHost-Apps/ntfy_ynh) - ntfy app for YunoHost
|
||||
- [ntfy_ynh](https://github.com/YunoHost-Apps/ntfy_ynh) - ntfy app for YunoHost
|
||||
- [drone-ntfy](https://github.com/Clortox/drone-ntfy) - Drone.io plugin for sending ntfy notifications from a pipeline
|
||||
|
||||
## Blog + forum posts
|
||||
|
||||
- [ntfy setup instructions](https://docs.benjamin-altpeter.de/network/vms/1001029-ntfy/) - benjamin-altpeter.de - 12/2022
|
||||
- [Ntfy Self-Hosted Push Notifications](https://lachlanlife.net/posts/2022-12-ntfy/) - lachlanlife.net - 12/2022
|
||||
- [Ntfy Self-Hosted Push Notifications](https://lachlanlife.net/posts/2022-12-ntfy/) - lachlanlife.net - 12/2022
|
||||
- [ntfy.sh](https://paramdeo.com/til/ntfy-sh) - paramdeo.com - 11/2022
|
||||
- [Using ntfy to warn me when my computer is discharging](https://ulysseszh.github.io/programming/2022/11/28/ntfy-warn-discharge.html) - ulysseszh.github.io - 11/2022
|
||||
- [ntfy - Push Notification Service](https://dizzytech.de/posts/ntfy/) - dizzytech.de - 11/2022
|
||||
- [ntfy - Push Notification Service](https://dizzytech.de/posts/ntfy/) - dizzytech.de - 11/2022
|
||||
- [Console #132](https://console.substack.com/p/console-132) ⭐ - console.substack.com - 11/2022
|
||||
- [MeshCentral - Ntfy Push Notifications ](https://www.youtube.com/watch?v=wyE4rtUd4Bg) - youtube.com - 11/2022
|
||||
- [Changelog | Tracking layoffs, tech worker demand still high, ntfy, ...](https://changelog.com/news/tracking-layoffs-tech-worker-demand-still-high-ntfy-devenv-markdoc-mike-bifulco-Y1jW) ⭐ - changelog.com - 11/2022
|
||||
|
@ -118,11 +118,11 @@ and uptime of third party servers, so use of each server is **at your own discre
|
|||
- [Ntfy et Jeedom : un plugin](https://lunarok-domotique.com/2022/11/ntfy-et-jeedom/) - lunarok-domotique.com - 11/2022
|
||||
- [Crea tu propio servidor de notificaciones con Ntfy](https://blog.parravidales.es/crea-tu-propio-servidor-de-notificaciones-con-ntfy/) - blog.parravidales.es - 11/2022
|
||||
- [Zero-cost push notifications to your phone or desktop via PUT/POST ](https://lobste.rs/s/41dq13/zero_cost_push_notifications_your_phone) - lobste.rs - 10/2022
|
||||
- [A nifty push notification system: ntfy](https://jpmens.net/2022/10/30/a-nifty-push-notification-system-ntfy/) - jpmens.net - 10/2022
|
||||
- [A nifty push notification system: ntfy](https://jpmens.net/2022/10/30/a-nifty-push-notification-system-ntfy/) - jpmens.net - 10/2022
|
||||
- [Alarmanlage der dritten Art (YouTube video)](https://www.youtube.com/watch?v=altb5QLHbaU&feature=youtu.be) - youtube.com - 10/2022
|
||||
- [Neue Services: Ntfy, TikTok und RustDesk](https://adminforge.de/tools/neue-services-ntfy-tiktok-und-rustdesk/) - adminforge.de - 9/2022
|
||||
- [Ntfy, le service de notifications qu’il vous faut](https://www.cachem.fr/ntfy-le-service-de-notifications-quil-vous-faut/) - cachem.fr - 9/2022
|
||||
- [NAS Synology et notifications avec ntfy](https://www.cachem.fr/synology-notifications-ntfy/) - cachem.fr - 9/2022
|
||||
- [NAS Synology et notifications avec ntfy](https://www.cachem.fr/synology-notifications-ntfy/) - cachem.fr - 9/2022
|
||||
- [Self hosted Mobile Push Notifications using NTFY | Thejesh GN](https://thejeshgn.com/2022/08/23/self-hosted-mobile-push-notifications-using-ntfy/) - thejeshgn.com - 8/2022
|
||||
- [Fedora Magazine | 4 cool new projects to try in Copr](https://fedoramagazine.org/4-cool-new-projects-to-try-in-copr-for-august-2022/) - fedoramagazine.org - 8/2022
|
||||
- [Docker로 오픈소스 푸시알람 프로젝트 ntfy.sh 설치 및 사용하기.(Feat. Uptimekuma)](https://svrforum.com/svr/398979) - svrforum.com - 8/2022
|
||||
|
@ -131,7 +131,7 @@ and uptime of third party servers, so use of each server is **at your own discre
|
|||
- [Install guide (with Docker)](https://chowdera.com/2022/150/202205301257379077.html) - chowdera.com - 5/2022
|
||||
- [无需注册的通知服务ntfy](https://blog.csdn.net/wbsu2004/article/details/125040247) - blog.csdn.net - 5/2022
|
||||
- [Updated review post (Jan-Lukas Else)](https://jlelse.blog/thoughts/2022/04/ntfy) - jlelse.blog - 4/2022
|
||||
- [Using ntfy and Tasker together](https://lachlanlife.net/posts/2022-04-tasker-ntfy/) - lachlanlife.net - 4/2022
|
||||
- [Using ntfy and Tasker together](https://lachlanlife.net/posts/2022-04-tasker-ntfy/) - lachlanlife.net - 4/2022
|
||||
- [Reddit feature update post](https://www.reddit.com/r/selfhosted/comments/uetlso/ntfy_is_a_tool_to_send_push_notifications_to_your/) ⭐ - reddit.com - 4/2022
|
||||
- [無料で簡単に通知の送受信ができつつオープンソースでセルフホストも可能な「ntfy」を使ってみた](https://gigazine.net/news/20220404-ntfy-push-notification/) - gigazine.net - 4/2022
|
||||
- [Pocketmags ntfy review](https://pocketmags.com/us/linux-format-magazine/march-2022/articles/1104187/ntfy) - pocketmags.com - 3/2022
|
||||
|
|
|
@ -15,14 +15,14 @@ Please send experienced iOS developers my way to help me figure this out.
|
|||
## iOS app not receiving notifications (anymore)
|
||||
If notifications do not show up at all anymore, there are a few causes for it (that I know of):
|
||||
|
||||
**Firebase+APNS are being weird and buggy**:
|
||||
If this is the case, usually it helps to **remove the topic/subscription and re-add it**. That will force Firebase to
|
||||
**Firebase+APNS are being weird and buggy**:
|
||||
If this is the case, usually it helps to **remove the topic/subscription and re-add it**. That will force Firebase to
|
||||
re-subscribe to the Firebase topic.
|
||||
|
||||
**Self-hosted only: No `upstream-base-url` set, or `base-url` mismatch**:
|
||||
**Self-hosted only: No `upstream-base-url` set, or `base-url` mismatch**:
|
||||
To make self-hosted servers work with the iOS
|
||||
app, I had to do some horrible things (see [iOS instant notifications](config.md#ios-instant-notifications) for details).
|
||||
Be sure that in your selfhosted server:
|
||||
|
||||
* Set `upstream-base-url: "https://ntfy.sh"` (**not your own hostname!**)
|
||||
* Ensure that the URL you set in `base-url` **matches exactly** what you set the Default Server in iOS to
|
||||
* Ensure that the URL you set in `base-url` **matches exactly** what you set the Default Server in iOS to
|
||||
|
|
|
@ -8,5 +8,5 @@ any outside service. All data is exclusively used to make the service function p
|
|||
I use is Firebase Cloud Messaging (FCM) service, which is required to provide instant Android notifications (see
|
||||
[FAQ](faq.md) for details). To avoid FCM altogether, download the F-Droid version.
|
||||
|
||||
For debugging purposes, the ntfy server may temporarily log request paths, remote IP addresses or even topics
|
||||
For debugging purposes, the ntfy server may temporarily log request paths, remote IP addresses or even topics
|
||||
or messages, though typically this is turned off.
|
||||
|
|
278
docs/publish.md
278
docs/publish.md
|
@ -1,6 +1,6 @@
|
|||
# Publishing
|
||||
Publishing messages can be done via HTTP PUT/POST or via the [ntfy CLI](install.md). Topics are created on the fly by
|
||||
subscribing or publishing to them. Because there is no sign-up, **the topic is essentially a password**, so pick
|
||||
Publishing messages can be done via HTTP PUT/POST or via the [ntfy CLI](install.md). Topics are created on the fly by
|
||||
subscribing or publishing to them. Because there is no sign-up, **the topic is essentially a password**, so pick
|
||||
something that's not easily guessable.
|
||||
|
||||
Here's an example showing how to publish a simple message using a POST request:
|
||||
|
@ -43,7 +43,7 @@ Here's an example showing how to publish a simple message using a POST request:
|
|||
|
||||
=== "Python"
|
||||
``` python
|
||||
requests.post("https://ntfy.sh/mytopic",
|
||||
requests.post("https://ntfy.sh/mytopic",
|
||||
data="Backup successful 😀".encode(encoding='utf-8'))
|
||||
```
|
||||
|
||||
|
@ -65,7 +65,7 @@ If you have the [Android app](subscribe/phone.md) installed on your phone, this
|
|||
<figcaption>Android notification</figcaption>
|
||||
</figure>
|
||||
|
||||
There are more features related to publishing messages: You can set a [notification priority](#message-priority),
|
||||
There are more features related to publishing messages: You can set a [notification priority](#message-priority),
|
||||
a [title](#message-title), and [tag messages](#tags-emojis) 🥳 🎉. Here's an example that uses some of them at together:
|
||||
|
||||
=== "Command line (curl)"
|
||||
|
@ -95,7 +95,7 @@ a [title](#message-title), and [tag messages](#tags-emojis) 🥳 🎉. Here's an
|
|||
Title: Unauthorized access detected
|
||||
Priority: urgent
|
||||
Tags: warning,skull
|
||||
|
||||
|
||||
Remote access to phils-laptop detected. Act right away.
|
||||
```
|
||||
|
||||
|
@ -128,10 +128,10 @@ a [title](#message-title), and [tag messages](#tags-emojis) 🥳 🎉. Here's an
|
|||
$headers = @{ Title="Unauthorized access detected"
|
||||
Priority="urgent"
|
||||
Tags="warning,skull" }
|
||||
$body = "Remote access to phils-laptop detected. Act right away."
|
||||
$body = "Remote access to phils-laptop detected. Act right away."
|
||||
Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $headers -Body $body -UseBasicParsing
|
||||
```
|
||||
|
||||
|
||||
=== "Python"
|
||||
``` python
|
||||
requests.post("https://ntfy.sh/phil_alerts",
|
||||
|
@ -174,8 +174,8 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
|
|||
-H "Actions: http, Open door, https://api.nest.com/open/yAxkasd, clear=true" \
|
||||
-H "Email: phil@example.com" \
|
||||
-d "There's someone at the door. 🐶
|
||||
|
||||
Please check if it's a good boy or a hooman.
|
||||
|
||||
Please check if it's a good boy or a hooman.
|
||||
Doggies have been known to ring the doorbell." \
|
||||
ntfy.sh/mydoorbell
|
||||
```
|
||||
|
@ -189,8 +189,8 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
|
|||
--email="phil@example.com" \
|
||||
mydoorbell \
|
||||
"There's someone at the door. 🐶
|
||||
|
||||
Please check if it's a good boy or a hooman.
|
||||
|
||||
Please check if it's a good boy or a hooman.
|
||||
Doggies have been known to ring the doorbell."
|
||||
```
|
||||
|
||||
|
@ -202,13 +202,13 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
|
|||
Attach: https://nest.com/view/yAxkasd.jpg
|
||||
Actions: http, Open door, https://api.nest.com/open/yAxkasd, clear=true
|
||||
Email: phil@example.com
|
||||
|
||||
|
||||
There's someone at the door. 🐶
|
||||
|
||||
Please check if it's a good boy or a hooman.
|
||||
|
||||
Please check if it's a good boy or a hooman.
|
||||
Doggies have been known to ring the doorbell.
|
||||
```
|
||||
|
||||
|
||||
=== "JavaScript"
|
||||
``` javascript
|
||||
fetch('https://ntfy.sh/mydoorbell', {
|
||||
|
@ -220,8 +220,8 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
|
|||
'Email': 'phil@example.com'
|
||||
},
|
||||
body: `There's someone at the door. 🐶
|
||||
|
||||
Please check if it's a good boy or a hooman.
|
||||
|
||||
Please check if it's a good boy or a hooman.
|
||||
Doggies have been known to ring the doorbell.`,
|
||||
})
|
||||
```
|
||||
|
@ -230,8 +230,8 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
|
|||
``` go
|
||||
req, _ := http.NewRequest("POST", "https://ntfy.sh/mydoorbell",
|
||||
strings.NewReader(`There's someone at the door. 🐶
|
||||
|
||||
Please check if it's a good boy or a hooman.
|
||||
|
||||
Please check if it's a good boy or a hooman.
|
||||
Doggies have been known to ring the doorbell.`))
|
||||
req.Header.Set("Click", "https://home.nest.com/")
|
||||
req.Header.Set("Attach", "https://nest.com/view/yAxkasd.jpg")
|
||||
|
@ -249,7 +249,7 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
|
|||
Email="phil@example.com" }
|
||||
$body = @'
|
||||
There's someone at the door. 🐶
|
||||
|
||||
|
||||
Please check if it's a good boy or a hooman.
|
||||
Doggies have been known to ring the doorbell.
|
||||
'@
|
||||
|
@ -283,7 +283,7 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
|
|||
"Actions": "http, Open door, https://api.nest.com/open/yAxkasd, clear=true\r\n" .
|
||||
"Email": "phil@example.com\r\n",
|
||||
'content' => 'There\'s someone at the door. 🐶
|
||||
|
||||
|
||||
Please check if it\'s a good boy or a hooman.
|
||||
Doggies have been known to ring the doorbell.'
|
||||
]
|
||||
|
@ -298,7 +298,7 @@ an [external image attachment](#attach-file-from-a-url) and [email publishing](#
|
|||
## Message title
|
||||
_Supported on:_ :material-android: :material-apple: :material-firefox:
|
||||
|
||||
The notification title is typically set to the topic short URL (e.g. `ntfy.sh/mytopic`). To override the title,
|
||||
The notification title is typically set to the topic short URL (e.g. `ntfy.sh/mytopic`). To override the title,
|
||||
you can set the `X-Title` header (or any of its aliases: `Title`, `ti`, or `t`).
|
||||
|
||||
=== "Command line (curl)"
|
||||
|
@ -320,7 +320,7 @@ you can set the `X-Title` header (or any of its aliases: `Title`, `ti`, or `t`).
|
|||
POST /controversial HTTP/1.1
|
||||
Host: ntfy.sh
|
||||
Title: Dogs are better than cats
|
||||
|
||||
|
||||
Oh my ...
|
||||
```
|
||||
|
||||
|
@ -400,7 +400,7 @@ You can set the priority with the header `X-Priority` (or any of its aliases: `P
|
|||
|
||||
=== "ntfy CLI"
|
||||
```
|
||||
ntfy publish \
|
||||
ntfy publish \
|
||||
-p 5 \
|
||||
phil_alerts An urgent message
|
||||
```
|
||||
|
@ -437,7 +437,7 @@ You can set the priority with the header `X-Priority` (or any of its aliases: `P
|
|||
$body = "An urgent message"
|
||||
Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $headers -Body $body -UseBasicParsing
|
||||
```
|
||||
|
||||
|
||||
=== "Python"
|
||||
``` python
|
||||
requests.post("https://ntfy.sh/phil_alerts",
|
||||
|
@ -468,12 +468,12 @@ _Supported on:_ :material-android: :material-apple: :material-firefox:
|
|||
|
||||
You can tag messages with emojis and other relevant strings:
|
||||
|
||||
* **Emojis**: If a tag matches an [emoji short code](emojis.md), it'll be converted to an emoji and prepended
|
||||
* **Emojis**: If a tag matches an [emoji short code](emojis.md), it'll be converted to an emoji and prepended
|
||||
to title or message.
|
||||
* **Other tags:** If a tag doesn't match, it will be listed below the notification.
|
||||
* **Other tags:** If a tag doesn't match, it will be listed below the notification.
|
||||
|
||||
This feature is useful for things like warnings (⚠️, ️🚨, or 🚩), but also to simply tag messages otherwise (e.g. script
|
||||
names, hostnames, etc.). Use [the emoji short code list](emojis.md) to figure out what tags can be converted to emojis.
|
||||
This feature is useful for things like warnings (⚠️, ️🚨, or 🚩), but also to simply tag messages otherwise (e.g. script
|
||||
names, hostnames, etc.). Use [the emoji short code list](emojis.md) to figure out what tags can be converted to emojis.
|
||||
Here's an **excerpt of emojis** I've found very useful in alert messages:
|
||||
|
||||
<table class="remove-md-box"><tr>
|
||||
|
@ -488,7 +488,7 @@ Here's an **excerpt of emojis** I've found very useful in alert messages:
|
|||
</tbody></table>
|
||||
</td>
|
||||
<td>
|
||||
<table><thead><tr><th>Tag</th><th>Emoji</th></tr></thead><tbody>
|
||||
<table><thead><tr><th>Tag</th><th>Emoji</th></tr></thead><tbody>
|
||||
<tr><td><code>-1</code></td><td>👎️</td></tr>
|
||||
<tr><td><code>warning</code></td><td>⚠️</td></tr>
|
||||
<tr><td><code>rotating_light</code></td><td>️🚨</td></tr>
|
||||
|
@ -502,7 +502,7 @@ Here's an **excerpt of emojis** I've found very useful in alert messages:
|
|||
<tr><td><code>facepalm</code></td><td>🤦</td></tr>
|
||||
<tr><td><code>no_entry</code></td><td>⛔</td></tr>
|
||||
<tr><td><code>no_entry_sign</code></td><td>🚫</td></tr>
|
||||
<tr><td><code>cd</code></td><td>💿</td></tr>
|
||||
<tr><td><code>cd</code></td><td>💿</td></tr>
|
||||
<tr><td><code>computer</code></td><td>💻</td></tr>
|
||||
<tr><td>...</td><td>...</td></tr>
|
||||
</tbody></table>
|
||||
|
@ -531,7 +531,7 @@ them with a comma, e.g. `tag1,tag2,tag3`.
|
|||
POST /backups HTTP/1.1
|
||||
Host: ntfy.sh
|
||||
Tags: warning,mailsrv13,daily-backup
|
||||
|
||||
|
||||
Backup of mailsrv13 failed
|
||||
```
|
||||
|
||||
|
@ -587,22 +587,22 @@ them with a comma, e.g. `tag1,tag2,tag3`.
|
|||
## Scheduled delivery
|
||||
_Supported on:_ :material-android: :material-apple: :material-firefox:
|
||||
|
||||
You can delay the delivery of messages and let ntfy send them at a later date. This can be used to send yourself
|
||||
You can delay the delivery of messages and let ntfy send them at a later date. This can be used to send yourself
|
||||
reminders or even to execute commands at a later date (if your subscriber acts on messages).
|
||||
|
||||
Usage is pretty straight forward. You can set the delivery time using the `X-Delay` header (or any of its aliases: `Delay`,
|
||||
`X-At`, `At`, `X-In` or `In`), either by specifying a Unix timestamp (e.g. `1639194738`), a duration (e.g. `30m`,
|
||||
`3h`, `2 days`), or a natural language time string (e.g. `10am`, `8:30pm`, `tomorrow, 3pm`, `Tuesday, 7am`,
|
||||
[and more](https://github.com/olebedev/when)).
|
||||
Usage is pretty straight forward. You can set the delivery time using the `X-Delay` header (or any of its aliases: `Delay`,
|
||||
`X-At`, `At`, `X-In` or `In`), either by specifying a Unix timestamp (e.g. `1639194738`), a duration (e.g. `30m`,
|
||||
`3h`, `2 days`), or a natural language time string (e.g. `10am`, `8:30pm`, `tomorrow, 3pm`, `Tuesday, 7am`,
|
||||
[and more](https://github.com/olebedev/when)).
|
||||
|
||||
As of today, the minimum delay you can set is **10 seconds** and the maximum delay is **3 days**. This can currently
|
||||
not be configured otherwise ([let me know](https://github.com/binwiederhier/ntfy/issues) if you'd like to change
|
||||
not be configured otherwise ([let me know](https://github.com/binwiederhier/ntfy/issues) if you'd like to change
|
||||
these limits).
|
||||
|
||||
For the purposes of [message caching](config.md#message-cache), scheduled messages are kept in the cache until 12 hours
|
||||
For the purposes of [message caching](config.md#message-cache), scheduled messages are kept in the cache until 12 hours
|
||||
after they were delivered (or whatever the server-side cache duration is set to). For instance, if a message is scheduled
|
||||
to be delivered in 3 days, it'll remain in the cache for 3 days and 12 hours. Also note that naturally,
|
||||
[turning off server-side caching](#message-caching) is not possible in combination with this feature.
|
||||
to be delivered in 3 days, it'll remain in the cache for 3 days and 12 hours. Also note that naturally,
|
||||
[turning off server-side caching](#message-caching) is not possible in combination with this feature.
|
||||
|
||||
=== "Command line (curl)"
|
||||
```
|
||||
|
@ -650,7 +650,7 @@ to be delivered in 3 days, it'll remain in the cache for 3 days and 12 hours. Al
|
|||
$body = "Good morning"
|
||||
Invoke-RestMethod -Method 'Post' -Uri $uri -Headers $headers -Body $body -UseBasicParsing
|
||||
```
|
||||
|
||||
|
||||
=== "Python"
|
||||
``` python
|
||||
requests.post("https://ntfy.sh/hello",
|
||||
|
@ -686,19 +686,19 @@ Here are a few examples (assuming today's date is **12/10/2021, 9am, Eastern Tim
|
|||
</td>
|
||||
</tr></table>
|
||||
|
||||
## Webhooks (publish via GET)
|
||||
## Webhooks (publish via GET)
|
||||
_Supported on:_ :material-android: :material-apple: :material-firefox:
|
||||
|
||||
In addition to using PUT/POST, you can also send to topics via simple HTTP GET requests. This makes it easy to use
|
||||
In addition to using PUT/POST, you can also send to topics via simple HTTP GET requests. This makes it easy to use
|
||||
a ntfy topic as a [webhook](https://en.wikipedia.org/wiki/Webhook), or if your client has limited HTTP support (e.g.
|
||||
like the [MacroDroid](https://play.google.com/store/apps/details?id=com.arlosoft.macrodroid) Android app).
|
||||
|
||||
To send messages via HTTP GET, simply call the `/publish` endpoint (or its aliases `/send` and `/trigger`). Without
|
||||
any arguments, this will send the message `triggered` to the topic. However, you can provide all arguments that are
|
||||
also supported as HTTP headers as URL-encoded arguments. Be sure to check the list of all
|
||||
To send messages via HTTP GET, simply call the `/publish` endpoint (or its aliases `/send` and `/trigger`). Without
|
||||
any arguments, this will send the message `triggered` to the topic. However, you can provide all arguments that are
|
||||
also supported as HTTP headers as URL-encoded arguments. Be sure to check the list of all
|
||||
[supported parameters and headers](#list-of-all-parameters) for details.
|
||||
|
||||
For instance, assuming your topic is `mywebhook`, you can simply call `/mywebhook/trigger` to send a message
|
||||
For instance, assuming your topic is `mywebhook`, you can simply call `/mywebhook/trigger` to send a message
|
||||
(aka trigger the webhook):
|
||||
|
||||
=== "Command line (curl)"
|
||||
|
@ -730,7 +730,7 @@ For instance, assuming your topic is `mywebhook`, you can simply call `/mywebhoo
|
|||
=== "PowerShell"
|
||||
``` powershell
|
||||
Invoke-RestMethod -Method 'Get' -Uri "ntfy.sh/mywebhook/trigger"
|
||||
```
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
``` python
|
||||
|
@ -742,8 +742,8 @@ For instance, assuming your topic is `mywebhook`, you can simply call `/mywebhoo
|
|||
file_get_contents('https://ntfy.sh/mywebhook/trigger');
|
||||
```
|
||||
|
||||
To add a custom message, simply append the `message=` URL parameter. And of course you can set the
|
||||
[message priority](#message-priority), the [message title](#message-title), and [tags](#tags-emojis) as well.
|
||||
To add a custom message, simply append the `message=` URL parameter. And of course you can set the
|
||||
[message priority](#message-priority), the [message title](#message-title), and [tags](#tags-emojis) as well.
|
||||
For a full list of possible parameters, check the list of [supported parameters and headers](#list-of-all-parameters).
|
||||
|
||||
Here's an example with a custom message, tags and a priority:
|
||||
|
@ -794,8 +794,8 @@ Here's an example with a custom message, tags and a priority:
|
|||
## Publish as JSON
|
||||
_Supported on:_ :material-android: :material-apple: :material-firefox:
|
||||
|
||||
For some integrations with other tools (e.g. [Jellyfin](https://jellyfin.org/), [overseerr](https://overseerr.dev/)),
|
||||
adding custom headers to HTTP requests may be tricky or impossible, so ntfy also allows publishing the entire message
|
||||
For some integrations with other tools (e.g. [Jellyfin](https://jellyfin.org/), [overseerr](https://overseerr.dev/)),
|
||||
adding custom headers to HTTP requests may be tricky or impossible, so ntfy also allows publishing the entire message
|
||||
as JSON in the request body.
|
||||
|
||||
To publish as JSON, simple PUT/POST the JSON object directly to the ntfy root URL. The message format is described below
|
||||
|
@ -803,9 +803,9 @@ the example.
|
|||
|
||||
!!! info
|
||||
To publish as JSON, you must **PUT/POST to the ntfy root URL**, not to the topic URL. Be sure to check that you're
|
||||
POST-ing to `https://ntfy.sh/` (correct), and not to `https://ntfy.sh/mytopic` (incorrect).
|
||||
POST-ing to `https://ntfy.sh/` (correct), and not to `https://ntfy.sh/mytopic` (incorrect).
|
||||
|
||||
Here's an example using most supported parameters. Check the table below for a complete list. The `topic` parameter
|
||||
Here's an example using most supported parameters. Check the table below for a complete list. The `topic` parameter
|
||||
is the only required one:
|
||||
|
||||
=== "Command line (curl)"
|
||||
|
@ -863,9 +863,9 @@ is the only required one:
|
|||
=== "Go"
|
||||
``` go
|
||||
// You should probably use json.Marshal() instead and make a proper struct,
|
||||
// or even just use req.Header.Set() like in the other examples, but for the
|
||||
// or even just use req.Header.Set() like in the other examples, but for the
|
||||
// sake of the example, this is easier.
|
||||
|
||||
|
||||
body := `{
|
||||
"topic": "mytopic",
|
||||
"message": "Disk space is low at 5.1 GB",
|
||||
|
@ -894,7 +894,7 @@ is the only required one:
|
|||
tags = @("warning", "cd")
|
||||
click = "https://homecamera.lan/xasds1h2xsSsa/"
|
||||
actions = @(
|
||||
@{
|
||||
@{
|
||||
action = "view"
|
||||
label = "Admin panel"
|
||||
url = "https://filesrv.lan/admin"
|
||||
|
@ -942,7 +942,7 @@ is the only required one:
|
|||
]));
|
||||
```
|
||||
|
||||
The JSON message format closely mirrors the format of the message you can consume when you [subscribe via the API](subscribe/api.md)
|
||||
The JSON message format closely mirrors the format of the message you can consume when you [subscribe via the API](subscribe/api.md)
|
||||
(see [JSON message format](subscribe/api.md#json-message-format) for details), but is not exactly identical. Here's an overview of
|
||||
all the supported fields:
|
||||
|
||||
|
@ -964,9 +964,9 @@ all the supported fields:
|
|||
_Supported on:_ :material-android: :material-apple: :material-firefox:
|
||||
|
||||
You can add action buttons to notifications to allow yourself to react to a notification directly. This is incredibly
|
||||
useful and has countless applications.
|
||||
useful and has countless applications.
|
||||
|
||||
You can control your home appliances (open/close garage door, change temperature on thermostat, ...), react to common
|
||||
You can control your home appliances (open/close garage door, change temperature on thermostat, ...), react to common
|
||||
monitoring alerts (clear logs when disk is full, ...), and many other things. The sky is the limit.
|
||||
|
||||
As of today, the following actions are supported:
|
||||
|
@ -987,7 +987,7 @@ Here's an example of what that a notification with actions can look like:
|
|||
You can define **up to three user actions** in your notifications, using either of the following methods:
|
||||
|
||||
* In the [`X-Actions` header](#using-a-header), using a simple comma-separated format
|
||||
* As a [JSON array](#using-a-json-array) in the `actions` key, when [publishing as JSON](#publish-as-json)
|
||||
* As a [JSON array](#using-a-json-array) in the `actions` key, when [publishing as JSON](#publish-as-json)
|
||||
|
||||
#### Using a header
|
||||
To define actions using the `X-Actions` header (or any of its aliases: `Actions`, `Action`), use the following format:
|
||||
|
@ -1002,14 +1002,14 @@ To define actions using the `X-Actions` header (or any of its aliases: `Actions`
|
|||
<action1>, <label1>, paramN=... [; <action2>, <label2>, ...]
|
||||
```
|
||||
|
||||
Multiple actions are separated by a semicolon (`;`), and key/value pairs are separated by commas (`,`). Values may be
|
||||
quoted with double quotes (`"`) or single quotes (`'`) if the value itself contains commas or semicolons.
|
||||
Multiple actions are separated by a semicolon (`;`), and key/value pairs are separated by commas (`,`). Values may be
|
||||
quoted with double quotes (`"`) or single quotes (`'`) if the value itself contains commas or semicolons.
|
||||
|
||||
The `action=` and `label=` prefix are optional in all actions, and the `url=` prefix is optional in the `view` and
|
||||
`http` action. The only limitation of this format is that depending on your language/library, UTF-8 characters may not
|
||||
The `action=` and `label=` prefix are optional in all actions, and the `url=` prefix is optional in the `view` and
|
||||
`http` action. The only limitation of this format is that depending on your language/library, UTF-8 characters may not
|
||||
work. If they don't, use the [JSON array format](#using-a-json-array) instead.
|
||||
|
||||
As an example, here's how you can create the above notification using this format. Refer to the [`view` action](#open-websiteapp) and
|
||||
As an example, here's how you can create the above notification using this format. Refer to the [`view` action](#open-websiteapp) and
|
||||
[`http` action](#send-http-request) section for details on the specific actions:
|
||||
|
||||
=== "Command line (curl)"
|
||||
|
@ -1046,8 +1046,8 @@ As an example, here's how you can create the above notification using this forma
|
|||
fetch('https://ntfy.sh/myhome', {
|
||||
method: 'POST',
|
||||
body: 'You left the house. Turn down the A/C?',
|
||||
headers: {
|
||||
'Actions': 'view, Open portal, https://home.nest.com/, clear=true; http, Turn down, https://api.nest.com/, body=\'{"temperature": 65}\''
|
||||
headers: {
|
||||
'Actions': 'view, Open portal, https://home.nest.com/, clear=true; http, Turn down, https://api.nest.com/, body=\'{"temperature": 65}\''
|
||||
}
|
||||
})
|
||||
```
|
||||
|
@ -1086,9 +1086,9 @@ As an example, here's how you can create the above notification using this forma
|
|||
]
|
||||
]));
|
||||
```
|
||||
|
||||
|
||||
#### Using a JSON array
|
||||
Alternatively, the same actions can be defined as **JSON array**, if the notification is defined as part of the JSON body
|
||||
Alternatively, the same actions can be defined as **JSON array**, if the notification is defined as part of the JSON body
|
||||
(see [publish as JSON](#publish-as-json)):
|
||||
|
||||
=== "Command line (curl)"
|
||||
|
@ -1189,7 +1189,7 @@ Alternatively, the same actions can be defined as **JSON array**, if the notific
|
|||
``` go
|
||||
// You should probably use json.Marshal() instead and make a proper struct,
|
||||
// but for the sake of the example, this is easier.
|
||||
|
||||
|
||||
body := `{
|
||||
"topic": "myhome",
|
||||
"message": "You left the house. Turn down the A/C?",
|
||||
|
@ -1291,16 +1291,16 @@ Alternatively, the same actions can be defined as **JSON array**, if the notific
|
|||
]));
|
||||
```
|
||||
|
||||
The required/optional fields for each action depend on the type of the action itself. Please refer to
|
||||
[`view` action](#open-websiteapp), [`broadcasst` action](#send-android-broadcast), and [`http` action](#send-http-request)
|
||||
The required/optional fields for each action depend on the type of the action itself. Please refer to
|
||||
[`view` action](#open-websiteapp), [`broadcasst` action](#send-android-broadcast), and [`http` action](#send-http-request)
|
||||
for details.
|
||||
|
||||
### Open website/app
|
||||
_Supported on:_ :material-android: :material-apple: :material-firefox:
|
||||
|
||||
The `view` action **opens a website or app when the action button is tapped**, e.g. a browser, a Google Maps location, or
|
||||
even a deep link into Twitter or a show ntfy topic. How exactly the action is handled depends on how Android and your
|
||||
desktop browser treat the links. Normally it'll just open a link in the browser.
|
||||
even a deep link into Twitter or a show ntfy topic. How exactly the action is handled depends on how Android and your
|
||||
desktop browser treat the links. Normally it'll just open a link in the browser.
|
||||
|
||||
Examples:
|
||||
|
||||
|
@ -1343,8 +1343,8 @@ Here's an example using the [`X-Actions` header](#using-a-header):
|
|||
fetch('https://ntfy.sh/myhome', {
|
||||
method: 'POST',
|
||||
body: 'Somebody retweeted your tweet.',
|
||||
headers: {
|
||||
'Actions': 'view, Open Twitter, https://twitter.com/binwiederhier/status/1467633927951163392'
|
||||
headers: {
|
||||
'Actions': 'view, Open Twitter, https://twitter.com/binwiederhier/status/1467633927951163392'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
@ -1456,7 +1456,7 @@ And the same example using [JSON publishing](#publish-as-json):
|
|||
``` go
|
||||
// You should probably use json.Marshal() instead and make a proper struct,
|
||||
// but for the sake of the example, this is easier.
|
||||
|
||||
|
||||
body := `{
|
||||
"topic": "myhome",
|
||||
"message": "Somebody retweeted your tweet.",
|
||||
|
@ -1585,8 +1585,8 @@ Here's an example using the [`X-Actions` header](#using-a-header):
|
|||
fetch('https://ntfy.sh/wifey', {
|
||||
method: 'POST',
|
||||
body: 'Your wife requested you send a picture of yourself.',
|
||||
headers: {
|
||||
'Actions': 'broadcast, Take picture, extras.cmd=pic, extras.camera=front'
|
||||
headers: {
|
||||
'Actions': 'broadcast, Take picture, extras.cmd=pic, extras.camera=front'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
@ -1710,7 +1710,7 @@ And the same example using [JSON publishing](#publish-as-json):
|
|||
``` go
|
||||
// You should probably use json.Marshal() instead and make a proper struct,
|
||||
// but for the sake of the example, this is easier.
|
||||
|
||||
|
||||
body := `{
|
||||
"topic": "wifey",
|
||||
"message": "Your wife requested you send a picture of yourself.",
|
||||
|
@ -1812,7 +1812,7 @@ The `http` action **sends a HTTP request when the action button is tapped**. You
|
|||
for whatever systems you have, e.g. opening the garage door, or turning on/off lights.
|
||||
|
||||
By default, this action sends a **POST request** (not GET!), though this can be changed with the `method` parameter.
|
||||
The only required parameter is `url`. Headers can be passed along using the `headers` parameter.
|
||||
The only required parameter is `url`. Headers can be passed along using the `headers` parameter.
|
||||
|
||||
Here's an example using the [`X-Actions` header](#using-a-header):
|
||||
|
||||
|
@ -1846,8 +1846,8 @@ Here's an example using the [`X-Actions` header](#using-a-header):
|
|||
fetch('https://ntfy.sh/myhome', {
|
||||
method: 'POST',
|
||||
body: 'Garage door has been open for 15 minutes. Close it?',
|
||||
headers: {
|
||||
'Actions': 'http, Close door, https://api.mygarage.lan/, method=PUT, headers.Authorization=Bearer zAzsx1sk.., body={\"action\": \"close\"}'
|
||||
headers: {
|
||||
'Actions': 'http, Close door, https://api.mygarage.lan/, method=PUT, headers.Authorization=Bearer zAzsx1sk.., body={\"action\": \"close\"}'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
@ -1979,7 +1979,7 @@ And the same example using [JSON publishing](#publish-as-json):
|
|||
``` go
|
||||
// You should probably use json.Marshal() instead and make a proper struct,
|
||||
// but for the sake of the example, this is easier.
|
||||
|
||||
|
||||
body := `{
|
||||
"topic": "myhome",
|
||||
"message": "Garage door has been open for 15 minutes. Close it?",
|
||||
|
@ -2002,7 +2002,7 @@ And the same example using [JSON publishing](#publish-as-json):
|
|||
|
||||
=== "PowerShell"
|
||||
``` powershell
|
||||
# Powershell requires the 'Depth' argument to equal 3 here to expand 'headers',
|
||||
# Powershell requires the 'Depth' argument to equal 3 here to expand 'headers',
|
||||
# otherwise it will read System.Collections.Hashtable in the returned JSON
|
||||
|
||||
$uri = "https://ntfy.sh"
|
||||
|
@ -2088,13 +2088,13 @@ The `http` action supports the following fields:
|
|||
## Click action
|
||||
_Supported on:_ :material-android: :material-apple: :material-firefox:
|
||||
|
||||
You can define which URL to open when a notification is clicked. This may be useful if your notification is related
|
||||
You can define which URL to open when a notification is clicked. This may be useful if your notification is related
|
||||
to a Zabbix alert or a transaction that you'd like to provide the deep-link for. Tapping the notification will open
|
||||
the web browser (or the app) and open the website.
|
||||
|
||||
To define a click action for the notification, pass a URL as the value of the `X-Click` header (or its aliase `Click`).
|
||||
If you pass a website URL (`http://` or `https://`) the web browser will open. If you pass another URI that can be handled
|
||||
by another app, the responsible app may open.
|
||||
by another app, the responsible app may open.
|
||||
|
||||
Examples:
|
||||
|
||||
|
@ -2126,7 +2126,7 @@ Here's an example that will open Reddit when the notification is clicked:
|
|||
``` http
|
||||
POST /reddit_alerts HTTP/1.1
|
||||
Host: ntfy.sh
|
||||
Click: https://www.reddit.com/message/messages
|
||||
Click: https://www.reddit.com/message/messages
|
||||
|
||||
New messages on Reddit
|
||||
```
|
||||
|
@ -2181,19 +2181,19 @@ _Supported on:_ :material-android: :material-firefox:
|
|||
You can **send images and other files to your phone** as attachments to a notification. The attachments are then downloaded
|
||||
onto your phone (depending on size and setting automatically), and can be used from the Downloads folder.
|
||||
|
||||
There are two different ways to send attachments:
|
||||
There are two different ways to send attachments:
|
||||
|
||||
* sending [a local file](#attach-local-file) via PUT, e.g. from `~/Flowers/flower.jpg` or `ringtone.mp3`
|
||||
* or by [passing an external URL](#attach-file-from-a-url) as an attachment, e.g. `https://f-droid.org/F-Droid.apk`
|
||||
* or by [passing an external URL](#attach-file-from-a-url) as an attachment, e.g. `https://f-droid.org/F-Droid.apk`
|
||||
|
||||
### Attach local file
|
||||
To **send a file from your computer** as an attachment, you can send it as the PUT request body. If a message is greater
|
||||
than the maximum message size (4,096 bytes) or consists of non UTF-8 characters, the ntfy server will automatically
|
||||
detect the mime type and size, and send the message as an attachment file. To send smaller text-only messages or files
|
||||
as attachments, you must pass a filename by passing the `X-Filename` header or query parameter (or any of its aliases
|
||||
`Filename`, `File` or `f`).
|
||||
To **send a file from your computer** as an attachment, you can send it as the PUT request body. If a message is greater
|
||||
than the maximum message size (4,096 bytes) or consists of non UTF-8 characters, the ntfy server will automatically
|
||||
detect the mime type and size, and send the message as an attachment file. To send smaller text-only messages or files
|
||||
as attachments, you must pass a filename by passing the `X-Filename` header or query parameter (or any of its aliases
|
||||
`Filename`, `File` or `f`).
|
||||
|
||||
By default, and how ntfy.sh is configured, the **max attachment size is 15 MB** (with 100 MB total per visitor).
|
||||
By default, and how ntfy.sh is configured, the **max attachment size is 15 MB** (with 100 MB total per visitor).
|
||||
Attachments **expire after 3 hours**, which typically is plenty of time for the user to download it, or for the Android app
|
||||
to auto-download it. Please also check out the [other limits below](#limitations).
|
||||
|
||||
|
@ -2220,7 +2220,7 @@ Here's an example showing how to upload an image:
|
|||
Host: ntfy.sh
|
||||
Filename: flower.jpg
|
||||
Content-Type: 52312
|
||||
|
||||
|
||||
(binary JPEG data)
|
||||
```
|
||||
|
||||
|
@ -2256,7 +2256,7 @@ Here's an example showing how to upload an image:
|
|||
'header' =>
|
||||
"Content-Type: application/octet-stream\r\n" . // Does not matter
|
||||
"Filename: flower.jpg",
|
||||
'content' => file_get_contents('flower.jpg') // Dangerous for large files
|
||||
'content' => file_get_contents('flower.jpg') // Dangerous for large files
|
||||
]
|
||||
]));
|
||||
```
|
||||
|
@ -2270,13 +2270,13 @@ Here's what that looks like on Android:
|
|||
|
||||
### Attach file from a URL
|
||||
Instead of sending a local file to your phone, you can use **an external URL** to specify where the attachment is hosted.
|
||||
This could be a Dropbox link, a file from social media, or any other publicly available URL. Since the files are
|
||||
This could be a Dropbox link, a file from social media, or any other publicly available URL. Since the files are
|
||||
externally hosted, the expiration or size limits from above do not apply here.
|
||||
|
||||
To attach an external file, simple pass the `X-Attach` header or query parameter (or any of its aliases `Attach` or `a`)
|
||||
to specify the attachment URL. It can be any type of file.
|
||||
to specify the attachment URL. It can be any type of file.
|
||||
|
||||
ntfy will automatically try to derive the file name from the URL (e.g `https://example.com/flower.jpg` will yield a
|
||||
ntfy will automatically try to derive the file name from the URL (e.g `https://example.com/flower.jpg` will yield a
|
||||
filename `flower.jpg`). To override this filename, you may send the `X-Filename` header or query parameter (or any of its
|
||||
aliases `Filename`, `File` or `f`).
|
||||
|
||||
|
@ -2354,7 +2354,7 @@ _Supported on:_ :material-android:
|
|||
|
||||
You can include an icon that will appear next to the text of the notification. Simply pass the `X-Icon` header or query
|
||||
parameter (or its alias `Icon`) to specify the URL that the icon is located at. The client will automatically download
|
||||
the icon (unless it is already cached locally, and less than 24 hours old), and show it in the notification. Icons are
|
||||
the icon (unless it is already cached locally, and less than 24 hours old), and show it in the notification. Icons are
|
||||
cached locally in the client until the notification is deleted. **Only JPEG and PNG images are supported at this time**.
|
||||
|
||||
Here's an example showing how to include an icon:
|
||||
|
@ -2394,7 +2394,7 @@ Here's an example showing how to include an icon:
|
|||
``` javascript
|
||||
fetch('https://ntfy.sh/tvshows', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
headers: {
|
||||
'Icon': 'https://styles.redditmedia.com/t5_32uhe/styles/communityIcon_xnt6chtnr2j21.png',
|
||||
'Title': 'Kodi: Resuming Playback',
|
||||
'Tags': 'arrow_forward'
|
||||
|
@ -2458,14 +2458,14 @@ Here's an example of how it will look on Android:
|
|||
## E-mail notifications
|
||||
_Supported on:_ :material-android: :material-apple: :material-firefox:
|
||||
|
||||
You can forward messages to e-mail by specifying an address in the header. This can be useful for messages that
|
||||
you'd like to persist longer, or to blast-notify yourself on all possible channels.
|
||||
You can forward messages to e-mail by specifying an address in the header. This can be useful for messages that
|
||||
you'd like to persist longer, or to blast-notify yourself on all possible channels.
|
||||
|
||||
Usage is easy: Simply pass the `X-Email` header (or any of its aliases: `X-E-mail`, `Email`, `E-mail`, `Mail`, or `e`).
|
||||
Only one e-mail address is supported.
|
||||
|
||||
Since ntfy does not provide auth (yet), the rate limiting is pretty strict (see [limitations](#limitations)). In the
|
||||
default configuration, you get **16 e-mails per visitor** (IP address) and then after that one per hour. On top of
|
||||
Since ntfy does not provide auth (yet), the rate limiting is pretty strict (see [limitations](#limitations)). In the
|
||||
default configuration, you get **16 e-mails per visitor** (IP address) and then after that one per hour. On top of
|
||||
that, your IP address appears in the e-mail body. This is to prevent abuse.
|
||||
|
||||
=== "Command line (curl)"
|
||||
|
@ -2476,7 +2476,7 @@ that, your IP address appears in the e-mail body. This is to prevent abuse.
|
|||
-H "Priority: high" \
|
||||
-d "Unknown login from 5.31.23.83 to backups.example.com" \
|
||||
ntfy.sh/alerts
|
||||
curl -H "Email: phil@example.com" -d "You've Got Mail"
|
||||
curl -H "Email: phil@example.com" -d "You've Got Mail"
|
||||
curl -d "You've Got Mail" "ntfy.sh/alerts?email=phil@example.com"
|
||||
```
|
||||
|
||||
|
@ -2505,7 +2505,7 @@ that, your IP address appears in the e-mail body. This is to prevent abuse.
|
|||
fetch('https://ntfy.sh/alerts', {
|
||||
method: 'POST',
|
||||
body: "Unknown login from 5.31.23.83 to backups.example.com",
|
||||
headers: {
|
||||
headers: {
|
||||
'Email': 'phil@example.com',
|
||||
'Tags': 'warning,skull,backup-host,ssh-login',
|
||||
'Priority': 'high'
|
||||
|
@ -2515,7 +2515,7 @@ that, your IP address appears in the e-mail body. This is to prevent abuse.
|
|||
|
||||
=== "Go"
|
||||
``` go
|
||||
req, _ := http.NewRequest("POST", "https://ntfy.sh/alerts",
|
||||
req, _ := http.NewRequest("POST", "https://ntfy.sh/alerts",
|
||||
strings.NewReader("Unknown login from 5.31.23.83 to backups.example.com"))
|
||||
req.Header.Set("Email", "phil@example.com")
|
||||
req.Header.Set("Tags", "warning,skull,backup-host,ssh-login")
|
||||
|
@ -2538,7 +2538,7 @@ that, your IP address appears in the e-mail body. This is to prevent abuse.
|
|||
``` python
|
||||
requests.post("https://ntfy.sh/alerts",
|
||||
data="Unknown login from 5.31.23.83 to backups.example.com",
|
||||
headers={
|
||||
headers={
|
||||
"Email": "phil@example.com",
|
||||
"Tags": "warning,skull,backup-host,ssh-login",
|
||||
"Priority": "high"
|
||||
|
@ -2571,11 +2571,11 @@ Here's what that looks like in Google Mail:
|
|||
_Supported on:_ :material-android: :material-apple: :material-firefox:
|
||||
|
||||
You can publish messages to a topic via e-mail, i.e. by sending an email to a specific address. For instance, you can
|
||||
publish a message to the topic `sometopic` by sending an e-mail to `ntfy-sometopic@ntfy.sh`. This is useful for e-mail
|
||||
publish a message to the topic `sometopic` by sending an e-mail to `ntfy-sometopic@ntfy.sh`. This is useful for e-mail
|
||||
based integrations such as for statuspage.io (though these days most services also support webhooks and HTTP calls).
|
||||
|
||||
Depending on the [server configuration](config.md#e-mail-publishing), the e-mail address format can have a prefix to
|
||||
prevent spam on topics. For ntfy.sh, the prefix is configured to `ntfy-`, meaning that the general e-mail address
|
||||
Depending on the [server configuration](config.md#e-mail-publishing), the e-mail address format can have a prefix to
|
||||
prevent spam on topics. For ntfy.sh, the prefix is configured to `ntfy-`, meaning that the general e-mail address
|
||||
format is:
|
||||
|
||||
```
|
||||
|
@ -2583,7 +2583,7 @@ ntfy-$topic@ntfy.sh
|
|||
```
|
||||
|
||||
As of today, e-mail publishing only supports adding a [message title](#message-title) (the e-mail subject). Tags, priority,
|
||||
delay and other features are not supported (yet). Here's an example that will publish a message with the
|
||||
delay and other features are not supported (yet). Here's an example that will publish a message with the
|
||||
title `You've Got Mail` to topic `sometopic` (see [ntfy.sh/sometopic](https://ntfy.sh/sometopic)):
|
||||
|
||||
<figure markdown>
|
||||
|
@ -2596,17 +2596,17 @@ title `You've Got Mail` to topic `sometopic` (see [ntfy.sh/sometopic](https://nt
|
|||
### Authentication
|
||||
Depending on whether the server is configured to support [access control](config.md#access-control), some topics
|
||||
may be read/write protected so that only users with the correct credentials can subscribe or publish to them.
|
||||
To publish/subscribe to protected topics, you can:
|
||||
To publish/subscribe to protected topics, you can:
|
||||
|
||||
* Use [basic auth](#basic-auth), e.g. `Authorization: Basic dGVzdHVzZXI6ZmFrZXBhc3N3b3Jk`
|
||||
* or use the [`auth` query parameter](#query-param), e.g. `?auth=QmFzaWMgZEdWemRIVnpaWEk2Wm1GclpYQmhjM04zYjNKaw`
|
||||
|
||||
!!! warning
|
||||
Base64 only encodes username and password. It **is not encrypting it**. For your self-hosted server,
|
||||
**be sure to use HTTPS to avoid eavesdropping** and exposing your password.
|
||||
Base64 only encodes username and password. It **is not encrypting it**. For your self-hosted server,
|
||||
**be sure to use HTTPS to avoid eavesdropping** and exposing your password.
|
||||
|
||||
#### Basic auth
|
||||
Here's an example using [Basic auth](https://en.wikipedia.org/wiki/Basic_access_authentication), with a user `testuser`
|
||||
Here's an example using [Basic auth](https://en.wikipedia.org/wiki/Basic_access_authentication), with a user `testuser`
|
||||
and password `fakepassword`:
|
||||
|
||||
=== "Command line (curl)"
|
||||
|
@ -2685,8 +2685,8 @@ and password `fakepassword`:
|
|||
]));
|
||||
```
|
||||
|
||||
To generate the `Authorization` header, use **standard base64** to encode the colon-separated `<username>:<password>`
|
||||
and prepend the word `Basic`, i.e. `Authorization: Basic base64(<username>:<password>)`. Here's some pseudo-code that
|
||||
To generate the `Authorization` header, use **standard base64** to encode the colon-separated `<username>:<password>`
|
||||
and prepend the word `Basic`, i.e. `Authorization: Basic base64(<username>:<password>)`. Here's some pseudo-code that
|
||||
hopefully explains it better:
|
||||
|
||||
```
|
||||
|
@ -2766,8 +2766,8 @@ Here's an example using the `auth` query parameter:
|
|||
]));
|
||||
```
|
||||
|
||||
To generate the value of the `auth` parameter, encode the value of the `Authorization` header (see anove) using
|
||||
**raw base64 encoding** (like base64, but strip any trailing `=`). Here's some pseudo-code that hopefully
|
||||
To generate the value of the `auth` parameter, encode the value of the `Authorization` header (see anove) using
|
||||
**raw base64 encoding** (like base64, but strip any trailing `=`). Here's some pseudo-code that hopefully
|
||||
explains it better:
|
||||
|
||||
```
|
||||
|
@ -2777,7 +2777,7 @@ authHeader = "Basic " + base64(username + ":" + password) // -> Basic dGVzdHVzZX
|
|||
authParam = base64_raw(authHeader) // -> QmFzaWMgZEdWemRIVnpaWEk2Wm1GclpYQmhjM04zYjNKaw (no trailing =)
|
||||
|
||||
// If your language does not have a function to encode raw base64, simply use normal base64
|
||||
// and REMOVE TRAILING "=" characters.
|
||||
// and REMOVE TRAILING "=" characters.
|
||||
```
|
||||
|
||||
The following command will generate the appropriate value for you on *nix systems:
|
||||
|
@ -2788,17 +2788,17 @@ echo -n "Basic `echo -n 'testuser:fakepassword' | base64`" | base64 | tr -d '='
|
|||
|
||||
### Message caching
|
||||
!!! info
|
||||
If `Cache: no` is used, messages will only be delivered to connected subscribers, and won't be re-delivered if a
|
||||
client re-connects. If a subscriber has (temporary) network issues or is reconnecting momentarily,
|
||||
If `Cache: no` is used, messages will only be delivered to connected subscribers, and won't be re-delivered if a
|
||||
client re-connects. If a subscriber has (temporary) network issues or is reconnecting momentarily,
|
||||
**messages might be missed**.
|
||||
|
||||
By default, the ntfy server caches messages on disk for 12 hours (see [message caching](config.md#message-cache)), so
|
||||
all messages you publish are stored server-side for a little while. The reason for this is to overcome temporary
|
||||
all messages you publish are stored server-side for a little while. The reason for this is to overcome temporary
|
||||
client-side network disruptions, but arguably this feature also may raise privacy concerns.
|
||||
|
||||
To avoid messages being cached server-side entirely, you can set `X-Cache` header (or its alias: `Cache`) to `no`.
|
||||
To avoid messages being cached server-side entirely, you can set `X-Cache` header (or its alias: `Cache`) to `no`.
|
||||
This will make sure that your message is not cached on the server, even if server-side caching is enabled. Messages
|
||||
are still delivered to connected subscribers, but [`since=`](subscribe/api.md#fetch-cached-messages) and
|
||||
are still delivered to connected subscribers, but [`since=`](subscribe/api.md#fetch-cached-messages) and
|
||||
[`poll=1`](subscribe/api.md#poll-for-messages) won't return the message anymore.
|
||||
|
||||
=== "Command line (curl)"
|
||||
|
@ -2869,12 +2869,12 @@ are still delivered to connected subscribers, but [`since=`](subscribe/api.md#fe
|
|||
|
||||
### Disable Firebase
|
||||
!!! info
|
||||
If `Firebase: no` is used and [instant delivery](subscribe/phone.md#instant-delivery) isn't enabled in the Android
|
||||
app (Google Play variant only), **message delivery will be significantly delayed (up to 15 minutes)**. To overcome
|
||||
If `Firebase: no` is used and [instant delivery](subscribe/phone.md#instant-delivery) isn't enabled in the Android
|
||||
app (Google Play variant only), **message delivery will be significantly delayed (up to 15 minutes)**. To overcome
|
||||
this delay, simply enable instant delivery.
|
||||
|
||||
The ntfy server can be configured to use [Firebase Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging)
|
||||
(see [Firebase config](config.md#firebase-fcm)) for message delivery on Android (to minimize the app's battery footprint).
|
||||
(see [Firebase config](config.md#firebase-fcm)) for message delivery on Android (to minimize the app's battery footprint).
|
||||
The ntfy.sh server is configured this way, meaning that all messages published to ntfy.sh are also published to corresponding
|
||||
FCM topics.
|
||||
|
||||
|
@ -2949,7 +2949,7 @@ to `no`. This will instruct the server not to forward messages to Firebase.
|
|||
|
||||
### UnifiedPush
|
||||
!!! info
|
||||
This setting is not relevant to users, only to app developers and people interested in [UnifiedPush](https://unifiedpush.org).
|
||||
This setting is not relevant to users, only to app developers and people interested in [UnifiedPush](https://unifiedpush.org).
|
||||
|
||||
[UnifiedPush](https://unifiedpush.org) is a standard for receiving push notifications without using the Google-owned
|
||||
[Firebase Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging) service. It puts push notifications
|
||||
|
@ -2957,16 +2957,16 @@ in the control of the user. ntfy can act as a **UnifiedPush distributor**, forwa
|
|||
|
||||
When publishing messages to a topic, apps using ntfy as a UnifiedPush distributor can set the `X-UnifiedPush` header or query
|
||||
parameter (or any of its aliases `unifiedpush` or `up`) to `1` to [disable Firebase](#disable-firebase). As of today, this
|
||||
option is mostly equivalent to `Firebase: no`, but was introduced to allow future flexibility. The flag additionally
|
||||
option is mostly equivalent to `Firebase: no`, but was introduced to allow future flexibility. The flag additionally
|
||||
enables auto-detection of the message encoding. If the message is binary, it'll be encoded as base64.
|
||||
|
||||
### Matrix Gateway
|
||||
The ntfy server implements a [Matrix Push Gateway](https://spec.matrix.org/v1.2/push-gateway-api/) (in combination with
|
||||
[UnifiedPush](https://unifiedpush.org) as the [Provider Push Protocol](https://unifiedpush.org/developers/gateway/)). This makes it easier to integrate
|
||||
with self-hosted [Matrix](https://matrix.org/) servers (such as [synapse](https://github.com/matrix-org/synapse)), since
|
||||
with self-hosted [Matrix](https://matrix.org/) servers (such as [synapse](https://github.com/matrix-org/synapse)), since
|
||||
you don't have to set up a separate push proxy (such as [common-proxies](https://github.com/UnifiedPush/common-proxies)).
|
||||
|
||||
In short, ntfy accepts Matrix messages on the `/_matrix/push/v1/notify` endpoint (see [Push Gateway API](https://spec.matrix.org/v1.2/push-gateway-api/)),
|
||||
In short, ntfy accepts Matrix messages on the `/_matrix/push/v1/notify` endpoint (see [Push Gateway API](https://spec.matrix.org/v1.2/push-gateway-api/)),
|
||||
and forwards them to the ntfy topic defined in the `pushkey` of the message. The message will then be forwarded to the
|
||||
ntfy Android app, and passed on to the Matrix client there.
|
||||
|
||||
|
@ -2989,7 +2989,7 @@ that you can use to try out what [authentication and access control](#authentica
|
|||
| [mytopic-wo](https://ntfy.sh/mytopic-wo) | `testuser` (password: `testuser`) | Write-only for `testuser`, no access for anyone else | Test topic |
|
||||
|
||||
## Limitations
|
||||
There are a few limitations to the API to prevent abuse and to keep the server healthy. Almost all of these settings
|
||||
There are a few limitations to the API to prevent abuse and to keep the server healthy. Almost all of these settings
|
||||
are configurable via the server side [rate limiting settings](config.md#rate-limiting). Most of these limits you won't run into,
|
||||
but just in case, let's list them all:
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
|
|||
**Features:**
|
||||
|
||||
* Web: Generate random topic name button ([#453](https://github.com/binwiederhier/ntfy/issues/453), thanks to [@yardenshoham](https://github.com/yardenshoham))
|
||||
* Add [Gitpod config](https://github.com/binwiederhier/ntfy/blob/main/.gitpod.yml) ([#540](https://github.com/binwiederhier/ntfy/pull/540), thanks to [@yardenshoham](https://github.com/yardenshoham))
|
||||
* Add [Gitpod config](https://github.com/binwiederhier/ntfy/blob/main/.gitpod.yml) ([#540](https://github.com/binwiederhier/ntfy/pull/540), thanks to [@yardenshoham](https://github.com/yardenshoham))
|
||||
|
||||
**Bug fixes + maintenance:**
|
||||
|
||||
|
@ -67,7 +67,7 @@ requests.
|
|||
**Documentation:**
|
||||
|
||||
* GitHub Actions example ([#492](https://github.com/binwiederhier/ntfy/pull/492), thanks to [@ksurl](https://github.com/ksurl))
|
||||
* UnifiedPush ACL clarification ([#497](https://github.com/binwiederhier/ntfy/issues/497), thanks to [@bt90](https://github.com/bt90))
|
||||
* UnifiedPush ACL clarification ([#497](https://github.com/binwiederhier/ntfy/issues/497), thanks to [@bt90](https://github.com/bt90))
|
||||
* Install instructions for Kustomize ([#463](https://github.com/binwiederhier/ntfy/pull/463), thanks to [@l-maciej](https://github.com/l-maciej))
|
||||
|
||||
**Other things:**
|
||||
|
@ -78,11 +78,11 @@ requests.
|
|||
## ntfy server v1.29.0
|
||||
Released November 12, 2022
|
||||
|
||||
This release adds the ability to add rate limit exemptions for IP ranges instead of just specific IP addresses. It also fixes
|
||||
This release adds the ability to add rate limit exemptions for IP ranges instead of just specific IP addresses. It also fixes
|
||||
a few bugs in the web app and the CLI and adds lots of new examples and install instructions.
|
||||
|
||||
Thanks to [some love on HN](https://news.ycombinator.com/item?id=33517944), we got so many new ntfy users trying out ntfy
|
||||
and joining the [chat rooms](https://github.com/binwiederhier/ntfy#chat--forum). **Welcome to the ntfy community to all of you!**
|
||||
and joining the [chat rooms](https://github.com/binwiederhier/ntfy#chat--forum). **Welcome to the ntfy community to all of you!**
|
||||
We also got a ton of new **[sponsors and donations](https://github.com/sponsors/binwiederhier)** 💸, which is amazing. I'd like to thank
|
||||
all of you for believing in the project, and for helping me pay the server cost. The HN spike increased the AWS cost quite a bit.
|
||||
|
||||
|
@ -120,13 +120,13 @@ all of you for believing in the project, and for helping me pay the server cost.
|
|||
|
||||
**Sponsorships:**:
|
||||
|
||||
Thank you to the amazing folks who decided to [sponsor ntfy](https://github.com/sponsors/binwiederhier). Thank you for
|
||||
helping carry the cost of the public server and developer licenses, and more importantly: Thank you for believing in ntfy!
|
||||
You guys rock!
|
||||
Thank you to the amazing folks who decided to [sponsor ntfy](https://github.com/sponsors/binwiederhier). Thank you for
|
||||
helping carry the cost of the public server and developer licenses, and more importantly: Thank you for believing in ntfy!
|
||||
You guys rock!
|
||||
|
||||
A list of all the sponsors can be found in the [README](https://github.com/binwiederhier/ntfy/blob/main/README.md).
|
||||
|
||||
## ntfy Android app v1.14.0
|
||||
## ntfy Android app v1.14.0
|
||||
Released September 27, 2022
|
||||
|
||||
This release adds the ability to set a custom icon to each notification, as well as a display name to subscriptions. We
|
||||
|
@ -164,7 +164,7 @@ This release primarily adds icon support for the Android app, and adds a display
|
|||
Aside from that, we fixed a few random bugs, most importantly the `Priority` header bug that allows the use behind
|
||||
Cloudflare. We also added a ton of documentation. Most prominently, an [integrations + projects page](https://ntfy.sh/docs/integrations/).
|
||||
|
||||
As of now, I also have started accepting **[donations and sponsorships](https://github.com/sponsors/binwiederhier)** 💸.
|
||||
As of now, I also have started accepting **[donations and sponsorships](https://github.com/sponsors/binwiederhier)** 💸.
|
||||
I would be very humbled if you consider donating.
|
||||
|
||||
**Features:**
|
||||
|
@ -200,8 +200,8 @@ I would be very humbled if you consider donating.
|
|||
Released June 23, 2022
|
||||
|
||||
This release brings two new CLI options to wait for a command to finish, or for a PID to exit. It also adds more detail
|
||||
to trace debug output. Aside from other bugs, it fixes a performance issue that occurred in large installations every
|
||||
minute or so, due to competing stats gathering (personal installations will likely be unaffected by this).
|
||||
to trace debug output. Aside from other bugs, it fixes a performance issue that occurred in large installations every
|
||||
minute or so, due to competing stats gathering (personal installations will likely be unaffected by this).
|
||||
|
||||
**Features:**
|
||||
|
||||
|
@ -226,7 +226,7 @@ minute or so, due to competing stats gathering (personal installations will like
|
|||
Released June 16, 2022
|
||||
|
||||
This release adds a Matrix Push Gateway directly into ntfy, to make self-hosting a Matrix server easier. The Windows
|
||||
CLI is now available via Scoop, and ntfy is now natively supported in Uptime Kuma.
|
||||
CLI is now available via Scoop, and ntfy is now natively supported in Uptime Kuma.
|
||||
|
||||
**Features:**
|
||||
|
||||
|
@ -265,8 +265,8 @@ set your server as the default server for new topics.
|
|||
## ntfy server v1.25.2
|
||||
Released June 2, 2022
|
||||
|
||||
This release adds the ability to set a log level to facilitate easier debugging of live systems. It also solves a
|
||||
production problem with a few over-users that resulted in Firebase quota problems (only applying to the over-users).
|
||||
This release adds the ability to set a log level to facilitate easier debugging of live systems. It also solves a
|
||||
production problem with a few over-users that resulted in Firebase quota problems (only applying to the over-users).
|
||||
We now block visitors from using Firebase if they trigger a quota exceeded response.
|
||||
|
||||
On top of that, we updated the Firebase SDK and are now building the release in GitHub Actions. We've also got two
|
||||
|
@ -279,7 +279,7 @@ more translations: Chinese/Simplified and Dutch.
|
|||
**Bugs**:
|
||||
|
||||
* Respect Firebase "quota exceeded" response for topics, block Firebase publishing for user for 10min ([#289](https://github.com/binwiederhier/ntfy/issues/289))
|
||||
* Fix documentation header blue header due to mkdocs-material theme update (no ticket)
|
||||
* Fix documentation header blue header due to mkdocs-material theme update (no ticket)
|
||||
|
||||
**Maintenance:**
|
||||
|
||||
|
@ -367,7 +367,7 @@ The app is now available in the [App Store](https://apps.apple.com/us/app/ntfy/i
|
|||
## ntfy server v1.23.0
|
||||
Released May 21, 2022
|
||||
|
||||
This release ships a CLI for Windows and macOS, as well as the ability to disable the web app entirely. On top of that,
|
||||
This release ships a CLI for Windows and macOS, as well as the ability to disable the web app entirely. On top of that,
|
||||
it adds support for APNs, the iOS messaging service. This is needed for the (soon to be released) iOS app.
|
||||
|
||||
**Features:**
|
||||
|
@ -391,7 +391,7 @@ it adds support for APNs, the iOS messaging service. This is needed for the (soo
|
|||
|
||||
* Portuguese/Brazil (thanks to [@tiagotriques](https://hosted.weblate.org/user/tiagotriques/) and [@pireshenrique22](https://hosted.weblate.org/user/pireshenrique22/))
|
||||
|
||||
Thank you to the many translators, who helped translate the new strings so quickly. I am humbled and amazed by your help.
|
||||
Thank you to the many translators, who helped translate the new strings so quickly. I am humbled and amazed by your help.
|
||||
|
||||
## ntfy Android app v1.13.0
|
||||
Released May 11, 2022
|
||||
|
@ -465,10 +465,10 @@ Released Apr 25, 2022
|
|||
|
||||
The main feature in this Android release is [Action Buttons](https://ntfy.sh/docs/publish/#action-buttons), a feature
|
||||
that allows users to add actions to the notifications. Actions can be to view a website or app, send a broadcast, or
|
||||
send a HTTP request.
|
||||
send a HTTP request.
|
||||
|
||||
We also added support for [ntfy:// deep links](https://ntfy.sh/docs/subscribe/phone/#ntfy-links), added three more
|
||||
languages and fixed a ton of bugs.
|
||||
We also added support for [ntfy:// deep links](https://ntfy.sh/docs/subscribe/phone/#ntfy-links), added three more
|
||||
languages and fixed a ton of bugs.
|
||||
|
||||
**Features:**
|
||||
|
||||
|
@ -509,9 +509,9 @@ Thanks to [@s-h-a-r-d](https://github.com/s-h-a-r-d) (aka @Shard), [@cmeis](http
|
|||
## ntfy server v1.21.2
|
||||
Released Apr 24, 2022
|
||||
|
||||
In this release, the web app got translation support and was translated into 9 languages already 🇧🇬 🇩🇪 🇺🇸 🌎.
|
||||
In this release, the web app got translation support and was translated into 9 languages already 🇧🇬 🇩🇪 🇺🇸 🌎.
|
||||
It also re-adds support for ARMv6, and adds server-side support for Action Buttons. [Action Buttons](https://ntfy.sh/docs/publish/#action-buttons)
|
||||
is a feature that will be released in the Android app soon. It allows users to add actions to the notifications.
|
||||
is a feature that will be released in the Android app soon. It allows users to add actions to the notifications.
|
||||
Limited support is available in the web app.
|
||||
|
||||
**Features:**
|
||||
|
@ -543,7 +543,7 @@ Limited support is available in the web app.
|
|||
**Integrations:**
|
||||
|
||||
[Apprise](https://github.com/caronc/apprise) support was fully released in [v0.9.8.2](https://github.com/caronc/apprise/releases/tag/v0.9.8.2)
|
||||
of Apprise. Thanks to [@particledecay](https://github.com/particledecay) and [@caronc](https://github.com/caronc) for their fantastic work.
|
||||
of Apprise. Thanks to [@particledecay](https://github.com/particledecay) and [@caronc](https://github.com/caronc) for their fantastic work.
|
||||
You can try it yourself like this (detailed usage in the [Apprise wiki](https://github.com/caronc/apprise/wiki/Notify_ntfy)):
|
||||
|
||||
```
|
||||
|
@ -593,7 +593,7 @@ Released Apr 6, 2022
|
|||
|
||||
**Features:**:
|
||||
|
||||
* Added message bar and publish dialog ([#196](https://github.com/binwiederhier/ntfy/issues/196))
|
||||
* Added message bar and publish dialog ([#196](https://github.com/binwiederhier/ntfy/issues/196))
|
||||
|
||||
**Bug fixes:**
|
||||
|
||||
|
@ -624,7 +624,7 @@ Released Mar 30, 2022
|
|||
* Improved [e-mail publishing](config.md#e-mail-publishing) documentation
|
||||
|
||||
## ntfy server v1.18.1
|
||||
Released Mar 21, 2022
|
||||
Released Mar 21, 2022
|
||||
_This release ships no features or bug fixes. It's merely a documentation update._
|
||||
|
||||
**Documentation:**
|
||||
|
@ -653,8 +653,8 @@ Released Mar 16, 2022
|
|||
|
||||
**Features:**
|
||||
|
||||
* [Publish messages as JSON](https://ntfy.sh/docs/publish/#publish-as-json) ([#133](https://github.com/binwiederhier/ntfy/issues/133),
|
||||
thanks [@cmeis](https://github.com/cmeis) for reporting, thanks to [@Joeharrison94](https://github.com/Joeharrison94) and
|
||||
* [Publish messages as JSON](https://ntfy.sh/docs/publish/#publish-as-json) ([#133](https://github.com/binwiederhier/ntfy/issues/133),
|
||||
thanks [@cmeis](https://github.com/cmeis) for reporting, thanks to [@Joeharrison94](https://github.com/Joeharrison94) and
|
||||
[@Fallenbagel](https://github.com/Fallenbagel) for testing)
|
||||
|
||||
**Bug fixes:**
|
||||
|
@ -682,7 +682,7 @@ Released Mar 11, 2022
|
|||
* Replace [web app](https://ntfy.sh/app) with a React/MUI-based web app from the 21st century (#111)
|
||||
* Web UI broken with auth (#132, thanks for reporting @arminus)
|
||||
* Send static web resources as `Content-Encoding: gzip`, i.e. docs and web app (no ticket)
|
||||
* Add support for auth via `?auth=...` query param, used by WebSocket in web app (no ticket)
|
||||
* Add support for auth via `?auth=...` query param, used by WebSocket in web app (no ticket)
|
||||
|
||||
## ntfy server v1.16.0
|
||||
Released Feb 27, 2022
|
||||
|
@ -699,7 +699,7 @@ Released Feb 27, 2022
|
|||
|
||||
**Technical notes:**
|
||||
|
||||
* As of this release, message IDs will be 12 characters long (as opposed to 10 characters). This is to be able to
|
||||
* As of this release, message IDs will be 12 characters long (as opposed to 10 characters). This is to be able to
|
||||
distinguish them from Unix timestamps for #151.
|
||||
|
||||
## ntfy Android app v1.9.1
|
||||
|
@ -746,7 +746,7 @@ Released Feb 6, 2022
|
|||
|
||||
**Features:**
|
||||
|
||||
* Support [auth / access control](https://ntfy.sh/docs/config/#access-control) (#19, thanks to @cmeis, @drsprite/@poblabs,
|
||||
* Support [auth / access control](https://ntfy.sh/docs/config/#access-control) (#19, thanks to @cmeis, @drsprite/@poblabs,
|
||||
@gedw99, @karmanyaahm, @Mek101, @gc-ss, @julianfoad, @nmoseman, Jakob, PeterCxy, Techlosopher)
|
||||
* Export/upload log now allows censored/uncensored logs (no ticket)
|
||||
* Removed wake lock (except for notification dispatching, no ticket)
|
||||
|
|
131
docs/static/css/extra.css
vendored
131
docs/static/css/extra.css
vendored
|
@ -1,130 +1,133 @@
|
|||
:root > * {
|
||||
--md-primary-fg-color: #338574;
|
||||
--md-primary-fg-color--light: #338574;
|
||||
--md-primary-fg-color--dark: #338574;
|
||||
--md-primary-fg-color: #338574;
|
||||
--md-primary-fg-color--light: #338574;
|
||||
--md-primary-fg-color--dark: #338574;
|
||||
}
|
||||
|
||||
.md-header__button.md-logo :is(img, svg) {
|
||||
width: unset !important;
|
||||
width: unset !important;
|
||||
}
|
||||
|
||||
.md-header__topic:first-child {
|
||||
font-weight: 400;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.md-typeset h4 {
|
||||
font-weight: 500 !important;
|
||||
margin: 0 !important;
|
||||
font-size: 1.1em !important;
|
||||
font-weight: 500 !important;
|
||||
margin: 0 !important;
|
||||
font-size: 1.1em !important;
|
||||
}
|
||||
|
||||
.admonition {
|
||||
font-size: .74rem !important;
|
||||
font-size: 0.74rem !important;
|
||||
}
|
||||
|
||||
article {
|
||||
padding-bottom: 50px;
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
figure img, figure video {
|
||||
border-radius: 7px;
|
||||
figure img,
|
||||
figure video {
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
body[data-md-color-scheme="default"] figure img, body[data-md-color-scheme="default"] figure video {
|
||||
filter: drop-shadow(3px 3px 3px #ccc);
|
||||
body[data-md-color-scheme="default"] figure img,
|
||||
body[data-md-color-scheme="default"] figure video {
|
||||
filter: drop-shadow(3px 3px 3px #ccc);
|
||||
}
|
||||
|
||||
body[data-md-color-scheme="slate"] figure img, body[data-md-color-scheme="slate"] figure video {
|
||||
filter: drop-shadow(3px 3px 3px #1a1313);
|
||||
body[data-md-color-scheme="slate"] figure img,
|
||||
body[data-md-color-scheme="slate"] figure video {
|
||||
filter: drop-shadow(3px 3px 3px #1a1313);
|
||||
}
|
||||
|
||||
figure video {
|
||||
width: 100%;
|
||||
max-height: 450px;
|
||||
width: 100%;
|
||||
max-height: 450px;
|
||||
}
|
||||
|
||||
.remove-md-box {
|
||||
background: none;
|
||||
border: none;
|
||||
margin: 0 auto;
|
||||
background: none;
|
||||
border: none;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.remove-md-box td {
|
||||
padding: 0 10px
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
/* Lightbox; thanks to https://yossiabramov.com/blog/vanilla-js-lightbox */
|
||||
|
||||
.screenshots {
|
||||
text-align: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.screenshots img {
|
||||
max-height: 230px;
|
||||
max-width: 300px;
|
||||
margin: 3px;
|
||||
border-radius: 5px;
|
||||
filter: drop-shadow(2px 2px 2px #ddd);
|
||||
max-height: 230px;
|
||||
max-width: 300px;
|
||||
margin: 3px;
|
||||
border-radius: 5px;
|
||||
filter: drop-shadow(2px 2px 2px #ddd);
|
||||
}
|
||||
|
||||
.screenshots .nowrap {
|
||||
white-space: nowrap;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.lightbox {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
position: fixed;
|
||||
left:0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: -1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.15s ease-in;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: -1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.15s ease-in;
|
||||
}
|
||||
|
||||
.lightbox.show {
|
||||
background-color: rgba(0,0,0, 0.75);
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
z-index: 1000;
|
||||
background-color: rgba(0, 0, 0, 0.75);
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.lightbox img {
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
filter: drop-shadow(5px 5px 10px #222);
|
||||
border-radius: 5px;
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
filter: drop-shadow(5px 5px 10px #222);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.lightbox .close-lightbox {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
right: 30px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
right: 30px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.lightbox .close-lightbox::after,
|
||||
.lightbox .close-lightbox::before {
|
||||
content: '';
|
||||
width: 3px;
|
||||
height: 20px;
|
||||
background-color: #ddd;
|
||||
position: absolute;
|
||||
border-radius: 5px;
|
||||
transform: rotate(45deg);
|
||||
content: "";
|
||||
width: 3px;
|
||||
height: 20px;
|
||||
background-color: #ddd;
|
||||
position: absolute;
|
||||
border-radius: 5px;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.lightbox .close-lightbox::before {
|
||||
transform: rotate(-45deg);
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.lightbox .close-lightbox:hover::after,
|
||||
.lightbox .close-lightbox:hover::before {
|
||||
background-color: #fff;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
|
136
docs/static/js/extra.js
vendored
136
docs/static/js/extra.js
vendored
|
@ -1,99 +1,109 @@
|
|||
// Link tabs, as per https://facelessuser.github.io/pymdown-extensions/extensions/tabbed/#linked-tabs
|
||||
|
||||
const savedCodeTab = localStorage.getItem('savedTab')
|
||||
const codeTabs = document.querySelectorAll(".tabbed-set > input")
|
||||
const savedCodeTab = localStorage.getItem("savedTab");
|
||||
const codeTabs = document.querySelectorAll(".tabbed-set > input");
|
||||
for (const tab of codeTabs) {
|
||||
tab.addEventListener("click", () => {
|
||||
const current = document.querySelector(`label[for=${tab.id}]`)
|
||||
const pos = current.getBoundingClientRect().top
|
||||
const labelContent = current.innerHTML
|
||||
const labels = document.querySelectorAll('.tabbed-set > label, .tabbed-alternate > .tabbed-labels > label')
|
||||
for (const label of labels) {
|
||||
if (label.innerHTML === labelContent) {
|
||||
document.querySelector(`input[id=${label.getAttribute('for')}]`).checked = true
|
||||
}
|
||||
}
|
||||
|
||||
// Preserve scroll position
|
||||
const delta = (current.getBoundingClientRect().top) - pos
|
||||
window.scrollBy(0, delta)
|
||||
|
||||
// Save
|
||||
localStorage.setItem('savedTab', labelContent)
|
||||
})
|
||||
|
||||
// Select saved tab
|
||||
const current = document.querySelector(`label[for=${tab.id}]`)
|
||||
const labelContent = current.innerHTML
|
||||
if (savedCodeTab === labelContent) {
|
||||
tab.checked = true
|
||||
tab.addEventListener("click", () => {
|
||||
const current = document.querySelector(`label[for=${tab.id}]`);
|
||||
const pos = current.getBoundingClientRect().top;
|
||||
const labelContent = current.innerHTML;
|
||||
const labels = document.querySelectorAll(
|
||||
".tabbed-set > label, .tabbed-alternate > .tabbed-labels > label",
|
||||
);
|
||||
for (const label of labels) {
|
||||
if (label.innerHTML === labelContent) {
|
||||
document.querySelector(
|
||||
`input[id=${label.getAttribute("for")}]`,
|
||||
).checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Preserve scroll position
|
||||
const delta = current.getBoundingClientRect().top - pos;
|
||||
window.scrollBy(0, delta);
|
||||
|
||||
// Save
|
||||
localStorage.setItem("savedTab", labelContent);
|
||||
});
|
||||
|
||||
// Select saved tab
|
||||
const current = document.querySelector(`label[for=${tab.id}]`);
|
||||
const labelContent = current.innerHTML;
|
||||
if (savedCodeTab === labelContent) {
|
||||
tab.checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Lightbox for screenshot
|
||||
|
||||
const lightbox = document.createElement('div');
|
||||
lightbox.classList.add('lightbox');
|
||||
const lightbox = document.createElement("div");
|
||||
lightbox.classList.add("lightbox");
|
||||
document.body.appendChild(lightbox);
|
||||
|
||||
const showScreenshotOverlay = (e, el, group, index) => {
|
||||
lightbox.classList.add('show');
|
||||
document.addEventListener('keydown', nextScreenshotKeyboardListener);
|
||||
return showScreenshot(e, group, index);
|
||||
lightbox.classList.add("show");
|
||||
document.addEventListener("keydown", nextScreenshotKeyboardListener);
|
||||
return showScreenshot(e, group, index);
|
||||
};
|
||||
|
||||
const showScreenshot = (e, group, index) => {
|
||||
const actualIndex = resolveScreenshotIndex(group, index);
|
||||
lightbox.innerHTML = '<div class="close-lightbox"></div>' + screenshots[group][actualIndex].innerHTML;
|
||||
lightbox.querySelector('img').onclick = (e) => { return showScreenshot(e, group, actualIndex+1); };
|
||||
currentScreenshotGroup = group;
|
||||
currentScreenshotIndex = actualIndex;
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
const actualIndex = resolveScreenshotIndex(group, index);
|
||||
lightbox.innerHTML =
|
||||
'<div class="close-lightbox"></div>' +
|
||||
screenshots[group][actualIndex].innerHTML;
|
||||
lightbox.querySelector("img").onclick = (e) => {
|
||||
return showScreenshot(e, group, actualIndex + 1);
|
||||
};
|
||||
currentScreenshotGroup = group;
|
||||
currentScreenshotIndex = actualIndex;
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
|
||||
const nextScreenshot = (e) => {
|
||||
return showScreenshot(e, currentScreenshotGroup, currentScreenshotIndex+1);
|
||||
return showScreenshot(e, currentScreenshotGroup, currentScreenshotIndex + 1);
|
||||
};
|
||||
|
||||
const previousScreenshot = (e) => {
|
||||
return showScreenshot(e, currentScreenshotGroup, currentScreenshotIndex-1);
|
||||
return showScreenshot(e, currentScreenshotGroup, currentScreenshotIndex - 1);
|
||||
};
|
||||
|
||||
const resolveScreenshotIndex = (group, index) => {
|
||||
if (index < 0) {
|
||||
return screenshots[group].length - 1;
|
||||
} else if (index > screenshots[group].length - 1) {
|
||||
return 0;
|
||||
}
|
||||
return index;
|
||||
if (index < 0) {
|
||||
return screenshots[group].length - 1;
|
||||
} else if (index > screenshots[group].length - 1) {
|
||||
return 0;
|
||||
}
|
||||
return index;
|
||||
};
|
||||
|
||||
const hideScreenshotOverlay = (e) => {
|
||||
lightbox.classList.remove('show');
|
||||
document.removeEventListener('keydown', nextScreenshotKeyboardListener);
|
||||
lightbox.classList.remove("show");
|
||||
document.removeEventListener("keydown", nextScreenshotKeyboardListener);
|
||||
};
|
||||
|
||||
const nextScreenshotKeyboardListener = (e) => {
|
||||
switch (e.keyCode) {
|
||||
case 37:
|
||||
previousScreenshot(e);
|
||||
break;
|
||||
case 39:
|
||||
nextScreenshot(e);
|
||||
break;
|
||||
}
|
||||
switch (e.keyCode) {
|
||||
case 37:
|
||||
previousScreenshot(e);
|
||||
break;
|
||||
case 39:
|
||||
nextScreenshot(e);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
let currentScreenshotGroup = '';
|
||||
let currentScreenshotGroup = "";
|
||||
let currentScreenshotIndex = 0;
|
||||
let screenshots = {};
|
||||
Array.from(document.getElementsByClassName('screenshots')).forEach((sg) => {
|
||||
const group = sg.id;
|
||||
screenshots[group] = [...sg.querySelectorAll('a')];
|
||||
screenshots[group].forEach((el, index) => {
|
||||
el.onclick = (e) => { return showScreenshotOverlay(e, el, group, index); };
|
||||
});
|
||||
Array.from(document.getElementsByClassName("screenshots")).forEach((sg) => {
|
||||
const group = sg.id;
|
||||
screenshots[group] = [...sg.querySelectorAll("a")];
|
||||
screenshots[group].forEach((el, index) => {
|
||||
el.onclick = (e) => {
|
||||
return showScreenshotOverlay(e, el, group, index);
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
lightbox.onclick = hideScreenshotOverlay;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
# Subscribe via API
|
||||
You can create and subscribe to a topic in the [web UI](web.md), via the [phone app](phone.md), via the [ntfy CLI](cli.md),
|
||||
or in your own app or script by subscribing the API. This page describes how to subscribe via API. You may also want to
|
||||
or in your own app or script by subscribing the API. This page describes how to subscribe via API. You may also want to
|
||||
check out the page that describes how to [publish messages](../publish.md).
|
||||
|
||||
You can consume the subscription API as either a **[simple HTTP stream (JSON, SSE or raw)](#http-stream)**, or
|
||||
You can consume the subscription API as either a **[simple HTTP stream (JSON, SSE or raw)](#http-stream)**, or
|
||||
**[via WebSockets](#websockets)**. Both are incredibly simple to use.
|
||||
|
||||
## HTTP stream
|
||||
The HTTP stream-based API relies on a simple GET request with a streaming HTTP response, i.e **you open a GET request and
|
||||
the connection stays open forever**, sending messages back as they come in. There are three different API endpoints, which
|
||||
the connection stays open forever**, sending messages back as they come in. There are three different API endpoints, which
|
||||
only differ in the response format:
|
||||
|
||||
* [JSON stream](#subscribe-as-json-stream): `<topic>/json` returns a JSON stream, with one JSON message object per line
|
||||
|
@ -17,8 +17,8 @@ only differ in the response format:
|
|||
* [Raw stream](#subscribe-as-raw-stream): `<topic>/raw` returns messages as raw text, with one line per message
|
||||
|
||||
### Subscribe as JSON stream
|
||||
Here are a few examples of how to consume the JSON endpoint (`<topic>/json`). For almost all languages, **this is the
|
||||
recommended way to subscribe to a topic**. The notable exception is JavaScript, for which the
|
||||
Here are a few examples of how to consume the JSON endpoint (`<topic>/json`). For almost all languages, **this is the
|
||||
recommended way to subscribe to a topic**. The notable exception is JavaScript, for which the
|
||||
[SSE/EventSource stream](#subscribe-as-sse-stream) is much easier to work with.
|
||||
|
||||
=== "Command line (curl)"
|
||||
|
@ -45,7 +45,7 @@ recommended way to subscribe to a topic**. The notable exception is JavaScript,
|
|||
HTTP/1.1 200 OK
|
||||
Content-Type: application/x-ndjson; charset=utf-8
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
|
||||
{"id":"SLiKI64DOt","time":1635528757,"event":"open","topic":"mytopic"}
|
||||
{"id":"hwQ2YpKdmg","time":1635528741,"event":"message","topic":"mytopic","message":"Disk full"}
|
||||
{"id":"DGUDShMCsc","time":1635528787,"event":"keepalive","topic":"mytopic"}
|
||||
|
@ -86,7 +86,7 @@ recommended way to subscribe to a topic**. The notable exception is JavaScript,
|
|||
|
||||
### Subscribe as SSE stream
|
||||
Using [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) in JavaScript, you can consume
|
||||
notifications via a [Server-Sent Events (SSE)](https://en.wikipedia.org/wiki/Server-sent_events) stream. It's incredibly
|
||||
notifications via a [Server-Sent Events (SSE)](https://en.wikipedia.org/wiki/Server-sent_events) stream. It's incredibly
|
||||
easy to use. Here's what it looks like. You may also want to check out the [full example on GitHub](https://github.com/binwiederhier/ntfy/tree/main/examples/web-example-eventsource).
|
||||
|
||||
=== "Command line (curl)"
|
||||
|
@ -94,9 +94,9 @@ easy to use. Here's what it looks like. You may also want to check out the [full
|
|||
$ curl -s ntfy.sh/mytopic/sse
|
||||
event: open
|
||||
data: {"id":"weSj9RtNkj","time":1635528898,"event":"open","topic":"mytopic"}
|
||||
|
||||
|
||||
data: {"id":"p0M5y6gcCY","time":1635528909,"event":"message","topic":"mytopic","message":"Hi!"}
|
||||
|
||||
|
||||
event: keepalive
|
||||
data: {"id":"VNxNIg5fpt","time":1635528928,"event":"keepalive","topic":"test"}
|
||||
...
|
||||
|
@ -113,9 +113,9 @@ easy to use. Here's what it looks like. You may also want to check out the [full
|
|||
|
||||
event: open
|
||||
data: {"id":"weSj9RtNkj","time":1635528898,"event":"open","topic":"mytopic"}
|
||||
|
||||
|
||||
data: {"id":"p0M5y6gcCY","time":1635528909,"event":"message","topic":"mytopic","message":"Hi!"}
|
||||
|
||||
|
||||
event: keepalive
|
||||
data: {"id":"VNxNIg5fpt","time":1635528928,"event":"keepalive","topic":"test"}
|
||||
...
|
||||
|
@ -131,14 +131,14 @@ easy to use. Here's what it looks like. You may also want to check out the [full
|
|||
|
||||
### Subscribe as raw stream
|
||||
The `/raw` endpoint will output one line per message, and **will only include the message body**. It's useful for extremely
|
||||
simple scripts, and doesn't include all the data. Additional fields such as [priority](../publish.md#message-priority),
|
||||
[tags](../publish.md#tags--emojis--) or [message title](../publish.md#message-title) are not included in this output
|
||||
simple scripts, and doesn't include all the data. Additional fields such as [priority](../publish.md#message-priority),
|
||||
[tags](../publish.md#tags--emojis--) or [message title](../publish.md#message-title) are not included in this output
|
||||
format. Keepalive messages are sent as empty lines.
|
||||
|
||||
=== "Command line (curl)"
|
||||
```
|
||||
$ curl -s ntfy.sh/disk-alerts/raw
|
||||
|
||||
|
||||
Disk full
|
||||
...
|
||||
```
|
||||
|
@ -170,7 +170,7 @@ format. Keepalive messages are sent as empty lines.
|
|||
```
|
||||
|
||||
=== "Python"
|
||||
``` python
|
||||
``` python
|
||||
resp = requests.get("https://ntfy.sh/disk-alerts/raw", stream=True)
|
||||
for line in resp.iter_lines():
|
||||
if line:
|
||||
|
@ -189,13 +189,13 @@ format. Keepalive messages are sent as empty lines.
|
|||
```
|
||||
|
||||
## WebSockets
|
||||
You may also subscribe to topics via [WebSockets](https://en.wikipedia.org/wiki/WebSocket), which is also widely
|
||||
supported in many languages. Most notably, WebSockets are natively supported in JavaScript. On the command line,
|
||||
You may also subscribe to topics via [WebSockets](https://en.wikipedia.org/wiki/WebSocket), which is also widely
|
||||
supported in many languages. Most notably, WebSockets are natively supported in JavaScript. On the command line,
|
||||
I recommend [websocat](https://github.com/vi/websocat), a fantastic tool similar to `socat` or `curl`, but specifically
|
||||
for WebSockets.
|
||||
for WebSockets.
|
||||
|
||||
The WebSockets endpoint is available at `<topic>/ws` and returns messages as JSON objects similar to the
|
||||
[JSON stream endpoint](#subscribe-as-json-stream).
|
||||
The WebSockets endpoint is available at `<topic>/ws` and returns messages as JSON objects similar to the
|
||||
[JSON stream endpoint](#subscribe-as-json-stream).
|
||||
|
||||
=== "Command line (websocat)"
|
||||
```
|
||||
|
@ -246,7 +246,7 @@ curl -s "ntfy.sh/mytopic/json?poll=1"
|
|||
|
||||
### Fetch cached messages
|
||||
Messages may be cached for a couple of hours (see [message caching](../config.md#message-cache)) to account for network
|
||||
interruptions of subscribers. If the server has configured message caching, you can read back what you missed by using
|
||||
interruptions of subscribers. If the server has configured message caching, you can read back what you missed by using
|
||||
the `since=` query parameter. It takes a duration (e.g. `10m` or `30s`), a Unix timestamp (e.g. `1635528757`),
|
||||
a message ID (e.g. `nFS3knfcQ1xe`), or `all` (all cached messages).
|
||||
|
||||
|
@ -257,9 +257,9 @@ curl -s "ntfy.sh/mytopic/json?since=nFS3knfcQ1xe"
|
|||
```
|
||||
|
||||
### Fetch scheduled messages
|
||||
Messages that are [scheduled to be delivered](../publish.md#scheduled-delivery) at a later date are not typically
|
||||
returned when subscribing via the API, which makes sense, because after all, the messages have technically not been
|
||||
delivered yet. To also return scheduled messages from the API, you can use the `scheduled=1` (alias: `sched=1`)
|
||||
Messages that are [scheduled to be delivered](../publish.md#scheduled-delivery) at a later date are not typically
|
||||
returned when subscribing via the API, which makes sense, because after all, the messages have technically not been
|
||||
delivered yet. To also return scheduled messages from the API, you can use the `scheduled=1` (alias: `sched=1`)
|
||||
parameter (makes most sense with the `poll=1` parameter):
|
||||
|
||||
```
|
||||
|
@ -268,8 +268,8 @@ curl -s "ntfy.sh/mytopic/json?poll=1&sched=1"
|
|||
|
||||
### Filter messages
|
||||
You can filter which messages are returned based on the well-known message fields `id`, `message`, `title`, `priority` and
|
||||
`tags`. Here's an example that only returns messages of high or urgent priority that contains the both tags
|
||||
"zfs-error" and "error". Note that the `priority` filter is a logical OR and the `tags` filter is a logical AND.
|
||||
`tags`. Here's an example that only returns messages of high or urgent priority that contains the both tags
|
||||
"zfs-error" and "error". Note that the `priority` filter is a logical OR and the `tags` filter is a logical AND.
|
||||
|
||||
```
|
||||
$ curl "ntfy.sh/alerts/json?priority=high&tags=zfs-error"
|
||||
|
@ -289,7 +289,7 @@ Available filters (all case-insensitive):
|
|||
| `tags` | `X-Tags`, `tag`, `ta` | `ntfy.sh/mytopic?/jsontags=error,alert` | Only return messages that match *all listed tags* (comma-separated) |
|
||||
|
||||
### Subscribe to multiple topics
|
||||
It's possible to subscribe to multiple topics in one HTTP call by providing a comma-separated list of topics
|
||||
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:
|
||||
|
||||
```
|
||||
|
@ -318,7 +318,7 @@ format of the message. It's very straight forward:
|
|||
| Field | Required | Type | Example | Description |
|
||||
|--------------|----------|---------------------------------------------------|-------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `id` | ✔️ | *string* | `hwQ2YpKdmg` | Randomly chosen message identifier |
|
||||
| `time` | ✔️ | *number* | `1635528741` | Message date time, as Unix time stamp |
|
||||
| `time` | ✔️ | *number* | `1635528741` | Message date time, as Unix time stamp |
|
||||
| `event` | ✔️ | `open`, `keepalive`, `message`, or `poll_request` | `message` | Message type, typically you'd be only interested in `message` |
|
||||
| `topic` | ✔️ | *string* | `topic1,topic2` | Comma-separated list of topics the message is associated with; only one for all `message` events, but may be a list in `open` events |
|
||||
| `message` | - | *string* | `Some message` | Message body; always present in `message` events |
|
||||
|
@ -334,7 +334,7 @@ format of the message. It's very straight forward:
|
|||
| Field | Required | Type | Example | Description |
|
||||
|-----------|----------|-------------|--------------------------------|-----------------------------------------------------------------------------------------------------------|
|
||||
| `name` | ✔️ | *string* | `attachment.jpg` | Name of the attachment, can be overridden with `X-Filename`, see [attachments](../publish.md#attachments) |
|
||||
| `url` | ✔️ | *URL* | `https://example.com/file.jpg` | URL of the attachment |
|
||||
| `url` | ✔️ | *URL* | `https://example.com/file.jpg` | URL of the attachment |
|
||||
| `type` | -️ | *mime type* | `image/jpeg` | Mime type of the attachment, only defined if attachment was uploaded to ntfy server |
|
||||
| `size` | -️ | *number* | `33848` | Size of the attachment in bytes, only defined if attachment was uploaded to ntfy server |
|
||||
| `expires` | -️ | *number* | `1635528741` | Attachment expiry date as Unix time stamp, only defined if attachment was uploaded to ntfy server |
|
||||
|
@ -396,7 +396,7 @@ Here's an example for each message type:
|
|||
"event": "keepalive",
|
||||
"topic": "phil_alerts"
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
=== "Poll request message"
|
||||
``` json
|
||||
|
|
|
@ -4,14 +4,14 @@ to topics via the ntfy CLI. The CLI is included in the same `ntfy` binary that c
|
|||
|
||||
!!! info
|
||||
The **ntfy CLI is not required to send or receive messages**. You can instead [send messages with curl](../publish.md),
|
||||
and even use it to [subscribe to topics](api.md). It may be a little more convenient to use the ntfy CLI than writing
|
||||
and even use it to [subscribe to topics](api.md). It may be a little more convenient to use the ntfy CLI than writing
|
||||
your own script. It all depends on the use case. 😀
|
||||
|
||||
## Install + configure
|
||||
To install the ntfy CLI, simply **follow the steps outlined on the [install page](../install.md)**. The ntfy server and
|
||||
client are the same binary, so it's all very convenient. After installing, you can (optionally) configure the client
|
||||
by creating `~/.config/ntfy/client.yml` (for the non-root user), or `/etc/ntfy/client.yml` (for the root user). You
|
||||
can find a [skeleton config](https://github.com/binwiederhier/ntfy/blob/main/client/client.yml) on GitHub.
|
||||
To install the ntfy CLI, simply **follow the steps outlined on the [install page](../install.md)**. The ntfy server and
|
||||
client are the same binary, so it's all very convenient. After installing, you can (optionally) configure the client
|
||||
by creating `~/.config/ntfy/client.yml` (for the non-root user), or `/etc/ntfy/client.yml` (for the root user). You
|
||||
can find a [skeleton config](https://github.com/binwiederhier/ntfy/blob/main/client/client.yml) on GitHub.
|
||||
|
||||
If you just want to use [ntfy.sh](https://ntfy.sh), you don't have to change anything. If you **self-host your own server**,
|
||||
you may want to edit the `default-host` option:
|
||||
|
@ -24,7 +24,7 @@ default-host: https://ntfy.myhost.com
|
|||
```
|
||||
|
||||
## Publish messages
|
||||
You can send messages with the ntfy CLI using the `ntfy publish` command (or any of its aliases `pub`, `send` or
|
||||
You can send messages with the ntfy CLI using the `ntfy publish` command (or any of its aliases `pub`, `send` or
|
||||
`trigger`). There are a lot of examples on the page about [publishing messages](../publish.md), but here are a few
|
||||
quick ones:
|
||||
|
||||
|
@ -32,7 +32,7 @@ quick ones:
|
|||
```
|
||||
ntfy publish mytopic This is a message
|
||||
ntfy publish mytopic "This is a message"
|
||||
ntfy pub mytopic "This is a message"
|
||||
ntfy pub mytopic "This is a message"
|
||||
```
|
||||
|
||||
=== "Send with title, priority, and tags"
|
||||
|
@ -78,7 +78,7 @@ $ ntfy pub --file README.md mytopic | jq .
|
|||
```
|
||||
|
||||
### Wait for PID/command
|
||||
If you have a long-running command and want to **publish a notification when the command completes**,
|
||||
If you have a long-running command and want to **publish a notification when the command completes**,
|
||||
you may wrap it with `ntfy publish --wait-cmd` (aliases: `--cmd`, `--done`). Or, if you forgot to wrap it, and the
|
||||
command is already running, you can wait for the process to complete with `ntfy publish --wait-pid` (alias: `--pid`).
|
||||
|
||||
|
@ -123,15 +123,15 @@ Or, if you already started the long-running process and want to wait for it usin
|
|||
|
||||
## Subscribe to topics
|
||||
You can subscribe to topics using `ntfy subscribe`. Depending on how it is called, this command
|
||||
will either print or execute a command for every arriving message. There are a few different ways
|
||||
will either print or execute a command for every arriving message. There are a few different ways
|
||||
in which the command can be run:
|
||||
|
||||
### Stream messages as JSON
|
||||
```
|
||||
ntfy subscribe TOPIC
|
||||
```
|
||||
If you run the command like this, it prints the JSON representation of every incoming message. This is useful
|
||||
when you have a command that wants to stream-read incoming JSON messages. Unless `--poll` is passed, this command
|
||||
If you run the command like this, it prints the JSON representation of every incoming message. This is useful
|
||||
when you have a command that wants to stream-read incoming JSON messages. Unless `--poll` is passed, this command
|
||||
stays open forever.
|
||||
|
||||
```
|
||||
|
@ -152,7 +152,7 @@ ntfy subscribe TOPIC COMMAND
|
|||
```
|
||||
If you run it like this, a COMMAND is executed for every incoming messages. Scroll down to see a list of available
|
||||
environment variables. Here are a few examples:
|
||||
|
||||
|
||||
```
|
||||
ntfy sub mytopic 'notify-send "$m"'
|
||||
ntfy sub topic1 /my/script.sh
|
||||
|
@ -164,7 +164,7 @@ ntfy sub topic1 'echo "Message $m was received. Its title was $t and it had prio
|
|||
<figcaption>Execute command on incoming messages</figcaption>
|
||||
</figure>
|
||||
|
||||
The message fields are passed to the command as environment variables and can be used in scripts. Note that since
|
||||
The message fields are passed to the command as environment variables and can be used in scripts. Note that since
|
||||
these are environment variables, you typically don't have to worry about quoting too much, as long as you enclose them
|
||||
in double-quotes, you should be fine:
|
||||
|
||||
|
@ -178,7 +178,7 @@ in double-quotes, you should be fine:
|
|||
| `$NTFY_PRIORITY` | `$priority`, `$prio`, `$p` | Message priority (1=min, 5=max) |
|
||||
| `$NTFY_TAGS` | `$tags`, `$tag`, `$ta` | Message tags (comma separated list) |
|
||||
| `$NTFY_RAW` | `$raw` | Raw JSON message |
|
||||
|
||||
|
||||
### Subscribe to multiple topics
|
||||
```
|
||||
ntfy subscribe --from-config
|
||||
|
@ -242,8 +242,8 @@ Here's an example config file that subscribes to three different topics, executi
|
|||
In this example, when `ntfy subscribe --from-config` is executed:
|
||||
|
||||
* Messages to `echo-this` simply echos to standard out
|
||||
* Messages to `alerts` display as desktop notification for high priority messages using [notify-send](https://manpages.ubuntu.com/manpages/focal/man1/notify-send.1.html) (Linux),
|
||||
[notifu](https://www.paralint.com/projects/notifu/) (Windows) or `osascript` (macOS)
|
||||
* Messages to `alerts` display as desktop notification for high priority messages using [notify-send](https://manpages.ubuntu.com/manpages/focal/man1/notify-send.1.html) (Linux),
|
||||
[notifu](https://www.paralint.com/projects/notifu/) (Windows) or `osascript` (macOS)
|
||||
* Messages to `calc` open the calculator 😀 (*because, why not*)
|
||||
* Messages to `print-temp` execute an inline script and print the CPU temperature (Linux version only)
|
||||
|
||||
|
@ -271,8 +271,8 @@ if you install the deb/rpm package. To configure it, simply edit `/etc/ntfy/clie
|
|||
The `ntfy-client.service` runs as user `ntfy`, meaning that typical Linux permission restrictions apply. See below
|
||||
for how to fix this.
|
||||
|
||||
If the service runs on your personal desktop machine, you may want to override the service user/group (`User=` and `Group=`), and
|
||||
adjust the `DISPLAY` and `DBUS_SESSION_BUS_ADDRESS` environment variables. This will allow you to run commands in your X session
|
||||
If the service runs on your personal desktop machine, you may want to override the service user/group (`User=` and `Group=`), and
|
||||
adjust the `DISPLAY` and `DBUS_SESSION_BUS_ADDRESS` environment variables. This will allow you to run commands in your X session
|
||||
as the primary machine user.
|
||||
|
||||
You can either manually override these systemd service entries with `sudo systemctl edit ntfy-client`, and add this
|
||||
|
@ -306,7 +306,7 @@ Depending on whether the server is configured to support [access control](../con
|
|||
may be read/write protected so that only users with the correct credentials can subscribe or publish to them.
|
||||
To publish/subscribe to protected topics, you can use [Basic Auth](https://en.wikipedia.org/wiki/Basic_access_authentication)
|
||||
with a valid username/password. For your self-hosted server, **be sure to use HTTPS to avoid eavesdropping** and exposing
|
||||
your password.
|
||||
your password.
|
||||
|
||||
You can either add your username and password to the configuration file:
|
||||
=== "~/.config/ntfy/client.yml"
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
# Subscribe from your phone
|
||||
You can use the ntfy [Android App](https://play.google.com/store/apps/details?id=io.heckel.ntfy) or [iOS app](https://apps.apple.com/us/app/ntfy/id1625396347)
|
||||
to receive notifications directly on your phone. Just like the server, this app is also open source, and the code is available
|
||||
on GitHub ([Android](https://github.com/binwiederhier/ntfy-android), [iOS](https://github.com/binwiederhier/ntfy-ios)). Feel free to
|
||||
on GitHub ([Android](https://github.com/binwiederhier/ntfy-android), [iOS](https://github.com/binwiederhier/ntfy-ios)). Feel free to
|
||||
contribute, or [build your own](../develop.md).
|
||||
|
||||
<a href="https://play.google.com/store/apps/details?id=io.heckel.ntfy"><img src="../../static/img/badge-googleplay.png"></a>
|
||||
<a href="https://f-droid.org/en/packages/io.heckel.ntfy/"><img src="../../static/img/badge-fdroid.png"></a>
|
||||
<a href="https://apps.apple.com/us/app/ntfy/id1625396347"><img src="../../static/img/badge-appstore.png"></a>
|
||||
|
||||
You can get the Android app from both [Google Play](https://play.google.com/store/apps/details?id=io.heckel.ntfy) and
|
||||
You can get the Android app from both [Google Play](https://play.google.com/store/apps/details?id=io.heckel.ntfy) and
|
||||
from [F-Droid](https://f-droid.org/en/packages/io.heckel.ntfy/). Both are largely identical, with the one exception that
|
||||
the F-Droid flavor does not use Firebase. The iOS app can be downloaded from the [App Store](https://apps.apple.com/us/app/ntfy/id1625396347).
|
||||
|
||||
|
@ -65,8 +65,8 @@ setting, and other settings such as popover or notification dot:
|
|||
## Instant delivery
|
||||
_Supported on:_ :material-android:
|
||||
|
||||
Instant delivery allows you to receive messages on your phone instantly, **even when your phone is in doze mode**, i.e.
|
||||
when the screen turns off, and you leave it on the desk for a while. This is achieved with a foreground service, which
|
||||
Instant delivery allows you to receive messages on your phone instantly, **even when your phone is in doze mode**, i.e.
|
||||
when the screen turns off, and you leave it on the desk for a while. This is achieved with a foreground service, which
|
||||
you'll see as a permanent notification that looks like this:
|
||||
|
||||
<figure markdown>
|
||||
|
@ -75,7 +75,7 @@ you'll see as a permanent notification that looks like this:
|
|||
</figure>
|
||||
|
||||
Android does not allow you to dismiss this notification, unless you turn off the notification channel in the settings.
|
||||
To do so, long-press on the foreground notification (screenshot above) and navigate to the settings. Then toggle the
|
||||
To do so, long-press on the foreground notification (screenshot above) and navigate to the settings. Then toggle the
|
||||
"Subscription Service" off:
|
||||
|
||||
<figure markdown>
|
||||
|
@ -83,12 +83,12 @@ To do so, long-press on the foreground notification (screenshot above) and navig
|
|||
<figcaption>Turning off the persistent instant delivery notification</figcaption>
|
||||
</figure>
|
||||
|
||||
**Limitations without instant delivery**: Without instant delivery, **messages may arrive with a significant delay**
|
||||
(sometimes many minutes, or even hours later). If you've ever picked up your phone and
|
||||
**Limitations without instant delivery**: Without instant delivery, **messages may arrive with a significant delay**
|
||||
(sometimes many minutes, or even hours later). If you've ever picked up your phone and
|
||||
suddenly had 10 messages that were sent long before you know what I'm talking about.
|
||||
|
||||
The reason for this is [Firebase Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging). FCM is the
|
||||
*only* Google approved way to send push messages to Android devices, and it's what pretty much all apps use to deliver push
|
||||
The reason for this is [Firebase Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging). FCM is the
|
||||
*only* Google approved way to send push messages to Android devices, and it's what pretty much all apps use to deliver push
|
||||
notifications. Firebase is overall pretty bad at delivering messages in time, but on Android, most apps are stuck with it.
|
||||
|
||||
The ntfy Android app uses Firebase only for the main host `ntfy.sh`, and only in the Google Play flavor of the app.
|
||||
|
@ -113,10 +113,10 @@ _Supported on:_ :material-android:
|
|||
|
||||
The ntfy Android app supports deep linking directly to topics. This is useful when integrating with [automation apps](#automation-apps)
|
||||
such as [MacroDroid](https://play.google.com/store/apps/details?id=com.arlosoft.macrodroid) or [Tasker](https://play.google.com/store/apps/details?id=net.dinglisch.android.taskerm),
|
||||
or to simply directly link to a topic from a mobile website.
|
||||
or to simply directly link to a topic from a mobile website.
|
||||
|
||||
!!! info
|
||||
Android deep linking of http/https links is very brittle and limited, which is why something like `https://<host>/<topic>/subscribe` is
|
||||
Android deep linking of http/https links is very brittle and limited, which is why something like `https://<host>/<topic>/subscribe` is
|
||||
**not possible**, and instead `ntfy://` links have to be used. More details in [issue #20](https://github.com/binwiederhier/ntfy/issues/20).
|
||||
|
||||
**Supported link formats:**
|
||||
|
@ -132,10 +132,10 @@ or to simply directly link to a topic from a mobile website.
|
|||
_Supported on:_ :material-android:
|
||||
|
||||
[UnifiedPush](https://unifiedpush.org) is a standard for receiving push notifications without using the Google-owned
|
||||
[Firebase Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging) service. It puts push notifications
|
||||
in the control of the user. ntfy can act as a **UnifiedPush distributor**, forwarding messages to apps that support it.
|
||||
[Firebase Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging) service. It puts push notifications
|
||||
in the control of the user. ntfy can act as a **UnifiedPush distributor**, forwarding messages to apps that support it.
|
||||
|
||||
To use ntfy as a distributor, simply select it in one of the [supported apps](https://unifiedpush.org/users/apps/).
|
||||
To use ntfy as a distributor, simply select it in one of the [supported apps](https://unifiedpush.org/users/apps/).
|
||||
That's it. It's a one-step installation 😀. If desired, you can select your own [selfhosted ntfy server](../install.md)
|
||||
to handle messages. Here's an example with [FluffyChat](https://fluffychat.im/):
|
||||
|
||||
|
@ -156,7 +156,7 @@ or [Tasker](https://play.google.com/store/apps/details?id=net.dinglisch.android.
|
|||
To react on incoming notifications, you have to register to intents with the `io.heckel.ntfy.MESSAGE_RECEIVED` action (see
|
||||
[code for details](https://github.com/binwiederhier/ntfy-android/blob/main/app/src/main/java/io/heckel/ntfy/msg/BroadcastService.kt)).
|
||||
Here's an example using [MacroDroid](https://play.google.com/store/apps/details?id=com.arlosoft.macrodroid)
|
||||
and [Tasker](https://play.google.com/store/apps/details?id=net.dinglisch.android.taskerm), but any app that can catch
|
||||
and [Tasker](https://play.google.com/store/apps/details?id=net.dinglisch.android.taskerm), but any app that can catch
|
||||
broadcasts is supported:
|
||||
|
||||
<div id="integration-screenshots-receive" class="screenshots">
|
||||
|
@ -170,7 +170,7 @@ broadcasts is supported:
|
|||
</div>
|
||||
|
||||
For MacroDroid, be sure to type in the package name `io.heckel.ntfy`, otherwise intents may be silently swallowed.
|
||||
If you're using topics to drive automation, you'll likely want to mute the topic in the ntfy app. This will prevent
|
||||
If you're using topics to drive automation, you'll likely want to mute the topic in the ntfy app. This will prevent
|
||||
notification popups:
|
||||
|
||||
<figure markdown>
|
||||
|
@ -204,10 +204,10 @@ Here's a list of extras you can access. Most likely, you'll want to filter for `
|
|||
|
||||
#### Send messages using intents
|
||||
To send messages from other apps (such as [MacroDroid](https://play.google.com/store/apps/details?id=com.arlosoft.macrodroid)
|
||||
and [Tasker](https://play.google.com/store/apps/details?id=net.dinglisch.android.taskerm)), you can
|
||||
and [Tasker](https://play.google.com/store/apps/details?id=net.dinglisch.android.taskerm)), you can
|
||||
broadcast an intent with the `io.heckel.ntfy.SEND_MESSAGE` action. The ntfy Android app will forward the intent as a HTTP
|
||||
POST request to [publish a message](../publish.md). This is primarily useful for apps that do not support HTTP POST/PUT
|
||||
(like MacroDroid). In Tasker, you can simply use the "HTTP Request" action, which is a little easier and also works if
|
||||
(like MacroDroid). In Tasker, you can simply use the "HTTP Request" action, which is a little easier and also works if
|
||||
ntfy is not installed.
|
||||
|
||||
Here's what that looks like:
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# Subscribe from the Web UI
|
||||
You can use the Web UI to subscribe to topics as well. If you do, and you keep the website open, **notifications will
|
||||
pop up as desktop notifications**. Simply type in the topic name and click the *Subscribe* button. The browser will
|
||||
pop up as desktop notifications**. Simply type in the topic name and click the *Subscribe* button. The browser will
|
||||
keep a connection open and listen for incoming notifications.
|
||||
|
||||
To learn how to send messages, check out the [publishing page](../publish.md).
|
||||
|
||||
<div id="web-screenshots" class="screenshots">
|
||||
<a href="../../static/img/web-detail.png"><img src="../../static/img/web-detail.png"/></a>
|
||||
<a href="../../static/img/web-detail.png"><img src="../../static/img/web-detail.png"/></a>
|
||||
<a href="../../static/img/web-notification.png"><img src="../../static/img/web-notification.png"/></a>
|
||||
<a href="../../static/img/web-subscribe.png"><img src="../../static/img/web-subscribe.png"/></a>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue