diff --git a/docs/config.md b/docs/config.md
index b15b8022..1893f491 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -1333,7 +1333,6 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`).
| `stripe-secret-key` | `NTFY_STRIPE_SECRET_KEY` | *string* | - | Payments: Key used for the Stripe API communication, this enables payments |
| `stripe-webhook-key` | `NTFY_STRIPE_WEBHOOK_KEY` | *string* | - | Payments: Key required to validate the authenticity of incoming webhooks from Stripe |
| `billing-contact` | `NTFY_BILLING_CONTACT` | *email address* or *website* | - | Payments: Email or website displayed in Upgrade dialog as a billing contact |
-| `web-push-enabled` | `NTFY_WEB_PUSH_ENABLED` | *boolean* (`true` or `false`) | - | Web Push: Enable/disable (requires private and public key below). |
| `web-push-public-key` | `NTFY_WEB_PUSH_PUBLIC_KEY` | *string* | - | Web Push: Public Key. Run `ntfy webpush generate-keys` to generate |
| `web-push-private-key` | `NTFY_WEB_PUSH_PRIVATE_KEY` | *string* | - | Web Push: Private Key. Run `ntfy webpush generate-keys` to generate |
| `web-push-subscriptions-file` | `NTFY_WEB_PUSH_SUBSCRIPTIONS_FILE` | *string* | - | Web Push: Subscriptions file |
@@ -1430,7 +1429,6 @@ OPTIONS:
--enable-metrics, --enable_metrics if set, Prometheus metrics are exposed via the /metrics endpoint (default: false) [$NTFY_ENABLE_METRICS]
--metrics-listen-http value, --metrics_listen_http value ip:port used to expose the metrics endpoint (implicitly enables metrics) [$NTFY_METRICS_LISTEN_HTTP]
--profile-listen-http value, --profile_listen_http value ip:port used to expose the profiling endpoints (implicitly enables profiling) [$NTFY_PROFILE_LISTEN_HTTP]
- --web-push-enabled, --web_push_enabled enable web push (requires public and private key) (default: false) [$NTFY_WEB_PUSH_ENABLED]
--web-push-public-key value, --web_push_public_key value public key used for web push notifications [$NTFY_WEB_PUSH_PUBLIC_KEY]
--web-push-private-key value, --web_push_private_key value private key used for web push notifications [$NTFY_WEB_PUSH_PRIVATE_KEY]
--web-push-subscriptions-file value, --web_push_subscriptions_file value file used to store web push subscriptions [$NTFY_WEB_PUSH_SUBSCRIPTIONS_FILE]
diff --git a/docs/static/img/web-push-settings.png b/docs/static/img/web-push-settings.png
deleted file mode 100644
index 905d7c3c..00000000
Binary files a/docs/static/img/web-push-settings.png and /dev/null differ
diff --git a/docs/static/img/web-subscribe.png b/docs/static/img/web-subscribe.png
index 50db6763..ccbd0493 100644
Binary files a/docs/static/img/web-subscribe.png and b/docs/static/img/web-subscribe.png differ
diff --git a/docs/subscribe/desktop.md b/docs/subscribe/desktop.md
index b9ba02d9..fd9a9297 100644
--- a/docs/subscribe/desktop.md
+++ b/docs/subscribe/desktop.md
@@ -1,20 +1,17 @@
# Using the web app as an installed web app
-While ntfy doesn't have a native desktop app, it is built as a [progressive web app](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps)
-and thus can be installed on both desktop and mobile.
+While ntfy doesn't have a native desktop app, it is built as a [progressive web app](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps) (PWA)
+and thus can be installed on both desktop and mobile. This gives it its own launcher (e.g. shortcut on Windows, app on
+macOS, launcher shortcut on Linux) own window, push notifications, and an app badge with the unread notification count.
-This gives it its own launcher (e.g. shortcut on Windows, app on macOS, launcher shortcut on Linux) own window,
-push notifications, and an app badge with the unread notification count.
-
-To receive background notifications, either the browser or the installed web app must be open.
+To install and register the web app in your operating system, click the "install app" icon in your browser (usually next to the
+address bar). To receive background notifications, **either the browser or the installed web app must be open**.
Web app installation is supported on Chrome and Edge on desktop, as well as Chrome on Android and Safari on iOS.
Look at the [compatibility table](https://caniuse.com/web-app-manifest) for more info.
-
-
diff --git a/docs/subscribe/web.md b/docs/subscribe/web.md
index 465a53ee..1508e99f 100644
--- a/docs/subscribe/web.md
+++ b/docs/subscribe/web.md
@@ -1,49 +1,21 @@
-# Subscribe from the Web UI
+# Subscribe from the web app
+The web app lets you subscribe and publish messages to ntfy topics. For ntfy.sh, the web app is available at [ntfy.sh/app](https://ntfy.sh/app).
+To subscribe, simply type in the topic name and click the *Subscribe* button. **After subscribing, messages published to the topic
+will appear in the web app, and pop up as a notification.**
-You can use the Web UI to subscribe to topics as well. Simply type in the topic name and click the *Subscribe* button.
-
-While subscribing, you have the option to enable background notifications on supported browsers.
-
-- If background notifications are off:
-
- This requires an active ntfy tab to be open to receive notifications. These are typically instantaneous, and will
- appear as a system notification. If you don't see these, check that your browser is allowed to show notifications
- (for example in System Settings on macOS).
-
- If you don't want to enable background notifications, pinning the ntfy tab on your browser is a good solution to leave
- it running.
-
-- If background notifications are on:
-
- This uses the [Web Push API](https://caniuse.com/push-api). You don't need an active ntfy tab open, but in some
- cases you may need to keep your browser open.
-
- Background notifications are only supported on the same server hosting the web app. You cannot use another server,
- but can instead subscribe on the other server itself.
-
- If the ntfy app is not opened for more than a week, background notifications will be paused. You can resume them
- by opening the app again, and will get a warning notification before they are paused.
-
- | Browser | Platform | Browser Running | Browser Not Running | Restrictions |
- | ------- | -------- | --------------- | ------------------- | ------------------------------------------------------- |
- | Chrome | Desktop | ✅ | ❌ | |
- | Firefox | Desktop | ✅ | ❌ | |
- | Edge | Desktop | ✅ | ❌ | |
- | Opera | Desktop | ✅ | ❌ | |
- | Safari | Desktop | ✅ | ✅ | requires Safari 16.1, macOS 13 Ventura |
- | Chrome | Android | ✅ | ✅ | |
- | Safari | iOS | ⚠️ | ⚠️ | requires iOS 16.4, only when app is added to homescreen |
-
- (Browsers below 1% usage not shown, look at the [Push API](https://caniuse.com/push-api) for more info)
+
+
+
+## Publish messages
To learn how to send messages, check out the [publishing page](../publish.md).
+## Topic reservations
If topic reservations are enabled, you can claim ownership over topics and define access to it:
@@ -51,9 +23,29 @@ If topic reservations are enabled, you can claim ownership over topics and defin
-You can set your default choice for new subscriptions (for example synced account subscriptions and the default toggle state)
-in the settings page:
+## Background notifications
+While subscribing, you have the option to enable background notifications on supported browsers (see "Settings" tab).
-
-
-
+**If background notifications are off (default):** This requires an active ntfy tab to be open to receive notifications.
+These are typically instantaneous, and will appear as a system notification. If you don't see these, check that your browser
+is allowed to show notifications (for example in System Settings on macOS). If you don't want to enable background notifications,
+**pinning the ntfy tab on your browser** is a good solution to leave it running.
+
+**If background notifications are on:** This uses the [Web Push API](https://caniuse.com/push-api). You don't need an active
+ntfy tab open, but in some cases you may need to keep your browser open. Background notifications are only supported on the
+same server hosting the web app. You cannot use another server, but can instead subscribe on the other server itself.
+
+If the ntfy app is not opened for more than a week, background notifications will be paused. You can resume them
+by opening the app again, and will get a warning notification before they are paused.
+
+| Browser | Platform | Browser Running | Browser Not Running | Restrictions |
+|---------|----------|-----------------|---------------------|---------------------------------------------------------|
+| Chrome | Desktop | ✅ | ❌ | |
+| Firefox | Desktop | ✅ | ❌ | |
+| Edge | Desktop | ✅ | ❌ | |
+| Opera | Desktop | ✅ | ❌ | |
+| Safari | Desktop | ✅ | ✅ | requires Safari 16.1, macOS 13 Ventura |
+| Chrome | Android | ✅ | ✅ | |
+| Safari | iOS | ⚠️ | ⚠️ | requires iOS 16.4, only when app is added to homescreen |
+
+(Browsers below 1% usage not shown, look at the [Push API](https://caniuse.com/push-api) for more info)
diff --git a/server/server_web_push.go b/server/server_web_push.go
index dee88f4f..0875b94f 100644
--- a/server/server_web_push.go
+++ b/server/server_web_push.go
@@ -79,18 +79,18 @@ func (s *Server) handleWebPushDelete(w http.ResponseWriter, r *http.Request, _ *
func (s *Server) publishToWebPushEndpoints(v *visitor, m *message) {
subscriptions, err := s.webPush.SubscriptionsForTopic(m.Topic)
if err != nil {
- logvm(v, m).Err(err).Warn("Unable to publish web push messages")
+ logvm(v, m).Err(err).With(v, m).Warn("Unable to publish web push messages")
return
}
+ log.Tag(tagWebPush).With(v, m).Debug("Publishing web push message to %d subscribers", len(subscriptions))
payload, err := json.Marshal(newWebPushPayload(fmt.Sprintf("%s/%s", s.config.BaseURL, m.Topic), m))
if err != nil {
- log.Tag(tagWebPush).Err(err).Warn("Unable to marshal expiring payload")
+ log.Tag(tagWebPush).Err(err).With(v, m).Warn("Unable to marshal expiring payload")
return
}
for _, subscription := range subscriptions {
- ctx := log.Context{"endpoint": subscription.Endpoint, "username": subscription.UserID, "topic": m.Topic, "message_id": m.ID}
- if err := s.sendWebPushNotification(payload, subscription, &ctx); err != nil {
- log.Tag(tagWebPush).Err(err).Fields(ctx).Warn("Unable to publish web push message")
+ if err := s.sendWebPushNotification(subscription, payload, v, m); err != nil {
+ log.Tag(tagWebPush).Err(err).With(v, m, subscription).Warn("Unable to publish web push message")
}
}
}
@@ -125,9 +125,8 @@ func (s *Server) pruneAndNotifyWebPushSubscriptionsInternal() error {
}
warningSent := make([]*webPushSubscription, 0)
for _, subscription := range subscriptions {
- ctx := log.Context{"endpoint": subscription.Endpoint}
- if err := s.sendWebPushNotification(payload, subscription, &ctx); err != nil {
- log.Tag(tagWebPush).Err(err).Fields(ctx).Warn("Unable to publish expiry imminent warning")
+ if err := s.sendWebPushNotification(subscription, payload); err != nil {
+ log.Tag(tagWebPush).Err(err).With(subscription).Warn("Unable to publish expiry imminent warning")
continue
}
warningSent = append(warningSent, subscription)
@@ -139,7 +138,8 @@ func (s *Server) pruneAndNotifyWebPushSubscriptionsInternal() error {
return nil
}
-func (s *Server) sendWebPushNotification(message []byte, sub *webPushSubscription, ctx *log.Context) error {
+func (s *Server) sendWebPushNotification(sub *webPushSubscription, message []byte, contexters ...log.Contexter) error {
+ log.Tag(tagWebPush).With(sub).With(contexters...).Debug("Sending web push message")
resp, err := webpush.SendNotification(message, sub.ToSubscription(), &webpush.Options{
Subscriber: s.config.WebPushEmailAddress,
VAPIDPublicKey: s.config.WebPushPublicKey,
@@ -148,18 +148,18 @@ func (s *Server) sendWebPushNotification(message []byte, sub *webPushSubscriptio
TTL: int(s.config.CacheDuration.Seconds()),
})
if err != nil {
- log.Tag(tagWebPush).Err(err).Fields(*ctx).Debug("Unable to publish web push message, removing endpoint")
+ log.Tag(tagWebPush).With(sub).With(contexters...).Err(err).Debug("Unable to publish web push message, removing endpoint")
if err := s.webPush.RemoveSubscriptionsByEndpoint(sub.Endpoint); err != nil {
return err
}
return err
}
if (resp.StatusCode < 200 || resp.StatusCode > 299) && resp.StatusCode != 429 {
- log.Tag(tagWebPush).Fields(*ctx).Field("response_code", resp.StatusCode).Debug("Unable to publish web push message, unexpected response")
+ log.Tag(tagWebPush).With(sub).With(contexters...).Field("response_code", resp.StatusCode).Debug("Unable to publish web push message, unexpected response")
if err := s.webPush.RemoveSubscriptionsByEndpoint(sub.Endpoint); err != nil {
return err
}
- return errHTTPInternalErrorWebPushUnableToPublish.Fields(*ctx)
+ return errHTTPInternalErrorWebPushUnableToPublish.With(sub).With(contexters...)
}
return nil
}
diff --git a/server/types.go b/server/types.go
index ba00b690..c2ac7bd4 100644
--- a/server/types.go
+++ b/server/types.go
@@ -521,3 +521,11 @@ func (w *webPushSubscription) ToSubscription() *webpush.Subscription {
},
}
}
+
+func (w *webPushSubscription) Context() log.Context {
+ return map[string]any{
+ "web_push_subscription_id": w.ID,
+ "web_push_subscription_user_id": w.UserID,
+ "web_push_subscription_endpoint": w.Endpoint,
+ }
+}