From 3bc8ff0104e413ebad99e61b6b9e1aa2415108fd Mon Sep 17 00:00:00 2001 From: Philipp Heckel Date: Sat, 25 Dec 2021 00:57:02 +0100 Subject: [PATCH] Docs --- client/client_test.go | 2 + cmd/serve.go | 2 +- docs/config.md | 65 +++++++++++++++++--------- docs/publish.md | 66 ++++++++++++++++++++------- docs/static/img/screenshot-email.png | Bin 0 -> 50070 bytes server/server.yml | 37 +++++++++++---- util/util.go | 2 +- util/util_test.go | 21 +++++++++ 8 files changed, 146 insertions(+), 49 deletions(-) create mode 100644 docs/static/img/screenshot-email.png diff --git a/client/client_test.go b/client/client_test.go index 5b589da..4ce0067 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -37,6 +37,8 @@ func TestClient_Publish_Subscribe(t *testing.T) { require.Equal(t, "some delayed message", msg.Message) require.True(t, time.Now().Add(24*time.Hour).Unix() < msg.Time) + time.Sleep(200 * time.Millisecond) + msg = nextMessage(c) require.NotNil(t, msg) require.Equal(t, "some message", msg.Message) diff --git a/cmd/serve.go b/cmd/serve.go index ddc2eed..550e26a 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -22,7 +22,7 @@ var flagsServe = []cli.Flag{ altsrc.NewDurationFlag(&cli.DurationFlag{Name: "cache-duration", Aliases: []string{"b"}, EnvVars: []string{"NTFY_CACHE_DURATION"}, Value: server.DefaultCacheDuration, Usage: "buffer messages for this time to allow `since` requests"}), altsrc.NewDurationFlag(&cli.DurationFlag{Name: "keepalive-interval", Aliases: []string{"k"}, EnvVars: []string{"NTFY_KEEPALIVE_INTERVAL"}, Value: server.DefaultKeepaliveInterval, Usage: "interval of keepalive messages"}), altsrc.NewDurationFlag(&cli.DurationFlag{Name: "manager-interval", Aliases: []string{"m"}, EnvVars: []string{"NTFY_MANAGER_INTERVAL"}, Value: server.DefaultManagerInterval, Usage: "interval of for message pruning and stats printing"}), - altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-addr", EnvVars: []string{"NTFY_SMTP_ADDR"}, Usage: "SMTP address (host:port) to allow email sending"}), + altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-addr", EnvVars: []string{"NTFY_SMTP_ADDR"}, Usage: "SMTP server address (host:port) to allow email sending"}), altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-user", EnvVars: []string{"NTFY_SMTP_USER"}, Usage: "SMTP user (if e-mail sending is enabled)"}), altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-pass", EnvVars: []string{"NTFY_SMTP_PASS"}, Usage: "SMTP password (if e-mail sending is enabled)"}), altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-from", EnvVars: []string{"NTFY_SMTP_FROM"}, Usage: "SMTP sender address (if e-mail sending is enabled)"}), diff --git a/docs/config.md b/docs/config.md index 3cd6cb4..f7cfe6b 100644 --- a/docs/config.md +++ b/docs/config.md @@ -300,6 +300,7 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`). | Config option | Env variable | Format | Default | Description | |---|---|---|---|---| +| `base-url` | `NTFY_BASE_URL` | *URL* | - | Public facing base URL of the service (e.g. `https://ntfy.sh`) | | `listen-http` | `NTFY_LISTEN_HTTP` | `[host]:port` | `:80` | Listen address for the HTTP web server | | `listen-https` | `NTFY_LISTEN_HTTPS` | `[host]:port` | - | Listen address for the HTTPS web server. If set, you also need to set `key-file` and `cert-file`. | | `key-file` | `NTFY_KEY_FILE` | *filename* | - | HTTPS/TLS private key file, only used if `listen-https` is set. | @@ -307,42 +308,64 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`). | `firebase-key-file` | `NTFY_FIREBASE_KEY_FILE` | *filename* | - | If set, also publish messages to a Firebase Cloud Messaging (FCM) topic for your app. This is optional and only required to save battery when using the Android app. See [Firebase (FCM](#firebase-fcm). | | `cache-file` | `NTFY_CACHE_FILE` | *filename* | - | If set, messages are cached in a local SQLite database instead of only in-memory. This allows for service restarts without losing messages in support of the since= parameter. See [message cache](#message-cache). | | `cache-duration` | `NTFY_CACHE_DURATION` | *duration* | 12h | Duration for which messages will be buffered before they are deleted. This is required to support the `since=...` and `poll=1` parameter. Set this to `0` to disable the cache entirely. | +| `behind-proxy` | `NTFY_BEHIND_PROXY` | *bool* | false | If set, the X-Forwarded-For header is used to determine the visitor IP address instead of the remote address of the connection. | +| `smtp-addr` | `NTFY_SMTP_ADDR` | `host:port` | - | SMTP server address to allow email sending | +| `smtp-user` | `NTFY_SMTP_USER` | *string* | - | SMTP user; only used if e-mail sending is enabled | +| `smtp-pass` | `NTFY_SMTP_PASS` | *string* | - | SMTP password; only used if e-mail sending is enabled | +| `smtp-from` | `NTFY_SMTP_FROM` | *e-mail address* | - | SMTP sender e-mail address; only used if e-mail sending is enabled | | `keepalive-interval` | `NTFY_KEEPALIVE_INTERVAL` | *duration* | 30s | Interval in which keepalive messages are sent to the client. This is to prevent intermediaries closing the connection for inactivity. Note that the Android app has a hardcoded timeout at 77s, so it should be less than that. | | `manager-interval` | `$NTFY_MANAGER_INTERVAL` | *duration* | 1m | Interval in which the manager prunes old messages, deletes topics and prints the stats. | | `global-topic-limit` | `NTFY_GLOBAL_TOPIC_LIMIT` | *number* | 5000 | Rate limiting: Total number of topics before the server rejects new topics. | | `visitor-subscription-limit` | `NTFY_VISITOR_SUBSCRIPTION_LIMIT` | *number* | 30 | Rate limiting: Number of subscriptions per visitor (IP address) | | `visitor-request-limit-burst` | `NTFY_VISITOR_REQUEST_LIMIT_BURST` | *number* | 60 | Allowed GET/PUT/POST requests per second, per visitor. This setting is the initial bucket of requests each visitor has | | `visitor-request-limit-replenish` | `NTFY_VISITOR_REQUEST_LIMIT_REPLENISH` | *duration* | 10s | Strongly related to `visitor-request-limit-burst`: The rate at which the bucket is refilled | -| `behind-proxy` | `NTFY_BEHIND_PROXY` | *bool* | false | If set, the X-Forwarded-For header is used to determine the visitor IP address instead of the remote address of the connection. | +| `visitor-email-limit-burst` | `NTFY_VISITOR_EMAIL_LIMIT_BURST` | *number* | 16 |Initial limit of e-mails per visitor | +| `visitor-email-limit-replenish` | `NTFY_VISITOR_EMAIL_LIMIT_REPLENISH` | *duration* | 1h | Strongly related to `visitor-email-limit-burst`: The rate at which the bucket is refilled | The format for a *duration* is: `(smh)`, e.g. 30s, 20m or 1h. ## Command line options ``` -$ ntfy --help +$ ntfy serve --help NAME: - ntfy - Simple pub-sub notification service + main serve - Run the ntfy server USAGE: - ntfy [OPTION..] + ntfy serve [OPTIONS..] -GLOBAL OPTIONS: - --config value, -c value config file (default: /etc/ntfy/server.yml) [$NTFY_CONFIG_FILE] - --listen-http value, -l value ip:port used to as listen address (default: ":80") [$NTFY_LISTEN_HTTP] - --firebase-key-file value, -F value Firebase credentials file; if set additionally publish to FCM topic [$NTFY_FIREBASE_KEY_FILE] - --cache-file value, -C value cache file used for message caching [$NTFY_CACHE_FILE] - --cache-duration since, -b since buffer messages for this time to allow since requests (default: 12h0m0s) [$NTFY_CACHE_DURATION] - --keepalive-interval value, -k value interval of keepalive messages (default: 30s) [$NTFY_KEEPALIVE_INTERVAL] - --manager-interval value, -m value interval of for message pruning and stats printing (default: 1m0s) [$NTFY_MANAGER_INTERVAL] - --global-topic-limit value, -T value total number of topics allowed (default: 5000) [$NTFY_GLOBAL_TOPIC_LIMIT] - --visitor-subscription-limit value, -V value number of subscriptions per visitor (default: 30) [$NTFY_VISITOR_SUBSCRIPTION_LIMIT] - --visitor-request-limit-burst value, -B value initial limit of requests per visitor (default: 60) [$NTFY_VISITOR_REQUEST_LIMIT_BURST] - --visitor-request-limit-replenish value, -R value interval at which burst limit is replenished (one per x) (default: 10s) [$NTFY_VISITOR_REQUEST_LIMIT_REPLENISH] - --behind-proxy, -P if set, use X-Forwarded-For header to determine visitor IP address (for rate limiting) (default: false) [$NTFY_BEHIND_PROXY] +DESCRIPTION: + Run the ntfy server and listen for incoming requests + + 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 -Try 'ntfy COMMAND --help' for more information. - -ntfy v1.4.8 (7b8185c), runtime go1.17, built at 1637872539 -Copyright (C) 2021 Philipp C. Heckel, distributed under the Apache License 2.0 +OPTIONS: + --config value, -c value config file (default: /etc/ntfy/server.yml) [$NTFY_CONFIG_FILE] + --base-url value, -B value externally visible base URL for this host (e.g. https://ntfy.sh) [$NTFY_BASE_URL] + --listen-http value, -l value ip:port used to as HTTP listen address (default: ":80") [$NTFY_LISTEN_HTTP] + --listen-https value, -L value ip:port used to as HTTPS listen address [$NTFY_LISTEN_HTTPS] + --key-file value, -K value private key file, if listen-https is set [$NTFY_KEY_FILE] + --cert-file value, -E value certificate file, if listen-https is set [$NTFY_CERT_FILE] + --firebase-key-file value, -F value Firebase credentials file; if set additionally publish to FCM topic [$NTFY_FIREBASE_KEY_FILE] + --cache-file value, -C value cache file used for message caching [$NTFY_CACHE_FILE] + --cache-duration since, -b since buffer messages for this time to allow since requests (default: 12h0m0s) [$NTFY_CACHE_DURATION] + --keepalive-interval value, -k value interval of keepalive messages (default: 30s) [$NTFY_KEEPALIVE_INTERVAL] + --manager-interval value, -m value interval of for message pruning and stats printing (default: 1m0s) [$NTFY_MANAGER_INTERVAL] + --smtp-addr value SMTP server address (host:port) to allow email sending [$NTFY_SMTP_ADDR] + --smtp-user value SMTP user (if e-mail sending is enabled) [$NTFY_SMTP_USER] + --smtp-pass value SMTP password (if e-mail sending is enabled) [$NTFY_SMTP_PASS] + --smtp-from value SMTP sender address (if e-mail sending is enabled) [$NTFY_SMTP_FROM] + --global-topic-limit value, -T value total number of topics allowed (default: 5000) [$NTFY_GLOBAL_TOPIC_LIMIT] + --visitor-subscription-limit value number of subscriptions per visitor (default: 30) [$NTFY_VISITOR_SUBSCRIPTION_LIMIT] + --visitor-request-limit-burst value initial limit of requests per visitor (default: 60) [$NTFY_VISITOR_REQUEST_LIMIT_BURST] + --visitor-request-limit-replenish value interval at which burst limit is replenished (one per x) (default: 10s) [$NTFY_VISITOR_REQUEST_LIMIT_REPLENISH] + --visitor-email-limit-burst value initial limit of e-mails per visitor (default: 16) [$NTFY_VISITOR_EMAIL_LIMIT_BURST] + --visitor-email-limit-replenish value interval at which burst limit is replenished (one per x) (default: 1h0m0s) [$NTFY_VISITOR_EMAIL_LIMIT_REPLENISH] + --behind-proxy, -P if set, use X-Forwarded-For header to determine visitor IP address (for rate limiting) (default: false) [$NTFY_BEHIND_PROXY] + --help, -h show help (default: false) ``` diff --git a/docs/publish.md b/docs/publish.md index 97bd7ac..85cfaf8 100644 --- a/docs/publish.md +++ b/docs/publish.md @@ -592,16 +592,26 @@ Here's an example with a custom message, tags and a priority: file_get_contents('https://ntfy.sh/mywebhook/publish?message=Webhook+triggered&priority=high&tags=warning,skull'); ``` -## Publish as e-mail +## E-mail notifications 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. Since ntfy does not provide auth, -the [rate limiting](#limitations) is pretty strict (see below). 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. +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 +that, your IP address appears in the e-mail body. This is to prevent abuse. === "Command line (curl)" ``` - curl -H "Email: phil@example.com" -d "You've Got Mail" ntfy.sh/alerts + curl \ + -H "Email: phil@example.com" \ + -H "Tags: warning,skull,backup-host,ssh-login" \ + -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 -d "You've Got Mail" "ntfy.sh/alerts?email=phil@example.com" ``` @@ -609,7 +619,9 @@ is to prevent abuse. ``` ntfy publish \ --email=phil@example.com \ - alerts "You've Got Mail" + --tags=warning,skull,backup-host,ssh-login \ + --priority=high \ + alerts "Unknown login from 5.31.23.83 to backups.example.com" ``` === "HTTP" @@ -617,31 +629,44 @@ is to prevent abuse. POST /alerts HTTP/1.1 Host: ntfy.sh Email: phil@example.com + Tags: warning,skull,backup-host,ssh-login + Priority: high - You've Got Mail + Unknown login from 5.31.23.83 to backups.example.com ``` === "JavaScript" ``` javascript fetch('https://ntfy.sh/alerts', { method: 'POST', - body: "You've Got Mail", - headers: { 'Email': 'phil@example.com' } + body: "Unknown login from 5.31.23.83 to backups.example.com", + headers: { + 'Email': 'phil@example.com', + 'Tags': 'warning,skull,backup-host,ssh-login', + 'Priority': 'high' + } }) ``` === "Go" ``` go - req, _ := http.NewRequest("POST", "https://ntfy.sh/alerts", strings.NewReader("You've Got Mail")) + 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") + req.Header.Set("Priority", "high") http.DefaultClient.Do(req) ``` === "Python" ``` python requests.post("https://ntfy.sh/alerts", - data="You've Got Mail", - headers={ "Email": "phil@example.com" }) + data="Unknown login from 5.31.23.83 to backups.example.com", + headers={ + "Email": "phil@example.com", + "Tags": "warning,skull,backup-host,ssh-login", + "Priority": "high" + }) ``` === "PHP" @@ -651,12 +676,21 @@ is to prevent abuse. 'method' => 'POST', 'header' => "Content-Type: text/plain\r\n" . - "Email: phil@example.com", - 'content' => 'You've Got Mail' + "Email: phil@example.com\r\n" . + "Tags: warning,skull,backup-host,ssh-login\r\n" . + "Priority: high", + 'content' => 'Unknown login from 5.31.23.83 to backups.example.com' ] ])); ``` +Here's what that looks like in Google Mail: + +
+ ![e-mail notification](static/img/screenshot-email.png){ width=600 } +
E-mail notification
+
+ ## Advanced features ### Message caching @@ -827,6 +861,6 @@ and can be passed as **HTTP headers** or **query parameters in the URL**. They a | `X-Priority` | `Priority`, `prio`, `p` | [Message priority](#message-priority) | | `X-Tags` | `Tags`, `Tag`, `ta` | [Tags and emojis](#tags-emojis) | | `X-Delay` | `Delay`, `X-At`, `At`, `X-In`, `In` | Timestamp or duration for [delayed delivery](#scheduled-delivery) | -| `X-Email` | `X-E-Mail`, `Email`, `E-Mail`, `mail`, `e` | E-mail address for [e-mail delivery](#publish-as-e-mail) | +| `X-Email` | `X-E-Mail`, `Email`, `E-Mail`, `mail`, `e` | E-mail address for [e-mail notifications](#e-mail-notifications) | | `X-Cache` | `Cache` | Allows disabling [message caching](#message-caching) | | `X-Firebase` | `Firebase` | Allows disabling [sending to Firebase](#disable-firebase) | diff --git a/docs/static/img/screenshot-email.png b/docs/static/img/screenshot-email.png new file mode 100644 index 0000000000000000000000000000000000000000..48c1f39217f6d0f4a07f2d9355c8442e525b50f8 GIT binary patch literal 50070 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: +# set "key-file" and "cert-file". Format: : # # listen-http: ":80" # listen-https: @@ -34,6 +38,27 @@ # # cache-duration: 12h +# If set, the X-Forwarded-For header is used to determine the visitor IP address +# instead of the remote address of the connection. +# +# WARNING: If you are behind a proxy, you must set this, otherwise all visitors are rate limited +# as if they are one. +# +# behind-proxy: false + +# If enabled, allow e-mail notifications via the 'X-Email' header. As of today, only SMTP servers +# with plain text auth and STARTLS are supported. Please also refer to the rate limiting settings +# below (visitor-email-limit-burst & visitor-email-limit-burst). +# +# - smtp-addr is the hostname:port of the SMTP server +# - smtp-user/smtp-pass are the username and password of the SMTP user +# - smtp-from is the e-mail address of the sender +# +# smtp-addr: +# smtp-user: +# smtp-pass: +# smtp-from: + # Interval in which keepalive messages are sent to the client. This is to prevent # intermediaries closing the connection for inactivity. # @@ -67,11 +92,3 @@ # # visitor-email-limit-burst: 16 # visitor-email-limit-replenish: 1h - -# If set, the X-Forwarded-For header is used to determine the visitor IP address -# instead of the remote address of the connection. -# -# WARNING: If you are behind a proxy, you must set this, otherwise all visitors are rate limited -# as if they are one. -# -# behind-proxy: false diff --git a/util/util.go b/util/util.go index 440b61e..38e28d5 100644 --- a/util/util.go +++ b/util/util.go @@ -148,7 +148,7 @@ func PriorityString(priority int) (string, error) { case 4: return "high", nil case 5: - return "urgent", nil + return "max", nil default: return "", errInvalidPriority } diff --git a/util/util_test.go b/util/util_test.go index 79f4fc6..c70e45c 100644 --- a/util/util_test.go +++ b/util/util_test.go @@ -100,3 +100,24 @@ func TestParsePriority_Invalid(t *testing.T) { require.Equal(t, errInvalidPriority, err) } } + +func TestPriorityString(t *testing.T) { + priorities := []int{0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 5} + expected := []string{"default", "min", "low", "default", "high", "max"} + for i, priority := range priorities { + actual, err := PriorityString(priority) + require.Nil(t, err) + require.Equal(t, expected[i], actual) + } +} + +func TestPriorityString_Invalid(t *testing.T) { + _, err := PriorityString(99) + require.Equal(t, err, errInvalidPriority) +} + +func TestShortTopicURL(t *testing.T) { + require.Equal(t, "ntfy.sh/mytopic", ShortTopicURL("https://ntfy.sh/mytopic")) + require.Equal(t, "ntfy.sh/mytopic", ShortTopicURL("http://ntfy.sh/mytopic")) + require.Equal(t, "lalala", ShortTopicURL("lalala")) +}