diff --git a/README.md b/README.md
index 0b95c2dd..88aecf0b 100644
--- a/README.md
+++ b/README.md
@@ -109,6 +109,7 @@ Zerobyte can be customized using environment variables. Below are the available
| `TZ` | Timezone for the container (e.g., `Europe/Zurich`). **Crucial for accurate backup scheduling.** | `UTC` |
| `TRUST_PROXY` | When `true`, trust an existing `X-Forwarded-For` header from your reverse proxy. Leave `false` for direct deployments. | `false` |
| `TRUSTED_ORIGINS` | Comma-separated list of extra trusted origins for CORS (e.g., `http://localhost:3000,http://example.com`). | (none) |
+| `WEBHOOK_ALLOWED_ORIGINS` | Comma-separated list of HTTP origins allowed for backup webhooks and outbound HTTP notification destinations. | (none) |
| `LOG_LEVEL` | Logging verbosity. Options: `debug`, `info`, `warn`, `error`. | `info` |
| `SERVER_IDLE_TIMEOUT` | Idle timeout for the server in seconds. | `60` |
| `RCLONE_CONFIG_DIR` | Path to the directory containing `rclone.conf` inside the container. Change this if running as a non-root user. | `/root/.config/rclone` |
diff --git a/apps/docs/content/docs/configuration.mdx b/apps/docs/content/docs/configuration.mdx
index fada487f..13204f34 100644
--- a/apps/docs/content/docs/configuration.mdx
+++ b/apps/docs/content/docs/configuration.mdx
@@ -37,6 +37,7 @@ Zerobyte is configured through environment variables and Docker Compose settings
| `RESTIC_HOSTNAME` | Hostname used by Restic when creating snapshots. Automatically detected if a custom hostname is set in Docker. | `zerobyte` |
| `TRUST_PROXY` | Set to `true` to trust `X-Forwarded-For` headers from a reverse proxy. | `false` |
| `TRUSTED_ORIGINS` | Comma-separated list of additional trusted origins for CORS. | (none) |
+| `WEBHOOK_ALLOWED_ORIGINS` | Comma-separated list of HTTP origins allowed for backup webhooks and outbound HTTP notification destinations. | (none) |
| `LOG_LEVEL` | Logging verbosity: `debug`, `info`, `warn`, `error`. | `info` |
| `SERVER_IDLE_TIMEOUT` | Server idle timeout in seconds. | `60` |
| `RCLONE_CONFIG_DIR` | Path to the rclone config directory inside the container. | `/root/.config/rclone` |
diff --git a/apps/docs/content/docs/guides/notifications.mdx b/apps/docs/content/docs/guides/notifications.mdx
index 4f26d667..2aaf0f5b 100644
--- a/apps/docs/content/docs/guides/notifications.mdx
+++ b/apps/docs/content/docs/guides/notifications.mdx
@@ -36,6 +36,10 @@ You create destinations under **Notifications**. You route them per backup sched
| `Generic Webhook` | Arbitrary HTTP endpoints and automation systems | URL, method, headers, content type, optional JSON template keys |
| `Custom (Shoutrrr URL)` | Power users or services not exposed by the built-in forms | Raw Shoutrrr URL |
+
+ Outbound HTTP notification destinations must use an origin listed in `WEBHOOK_ALLOWED_ORIGINS`. This applies to Generic Webhook, Gotify, self-hosted ntfy servers, and Custom Shoutrrr URLs that resolve to a custom HTTP endpoint.
+
+
## Which type should I use?
- Choose **Email** when you already trust an SMTP relay and want easy fan-out to multiple recipients.
@@ -163,6 +167,10 @@ Each assignment is independent. One schedule can send failures to Email, warning
- `App Token`
- `Priority` from `0` to `10`
- `Path` (optional)
+
+ **Notes**
+
+ - Add the Gotify server origin, such as `https://gotify.example.com`, to `WEBHOOK_ALLOWED_ORIGINS`.
@@ -178,6 +186,8 @@ Each assignment is independent. One schedule can send failures to Email, warning
**Notes**
+ - Leave `Server URL` empty to use `ntfy.sh`.
+ - Add self-hosted ntfy origins, such as `https://ntfy.example.com`, to `WEBHOOK_ALLOWED_ORIGINS`.
- If you set an access token, it takes precedence over username and password.
- Priority values are `max`, `high`, `default`, `low`, and `min`.
@@ -236,6 +246,7 @@ Each assignment is independent. One schedule can send failures to Email, warning
**Notes**
+ - Add the webhook origin, such as `https://hooks.example.com`, to `WEBHOOK_ALLOWED_ORIGINS`.
- Headers are entered one per line as `Key: Value`.
- With JSON mode enabled, Zerobyte sends a body shaped like `{titleKey: "...", messageKey: "..."}`.
- With JSON mode disabled, the request body is plain notification text.
@@ -261,6 +272,8 @@ Each assignment is independent. One schedule can send failures to Email, warning
See the [Shoutrrr documentation](https://shoutrrr.nickfedor.com/services/overview) for the supported URL formats and service-specific options.
+ If the Shoutrrr URL targets a custom HTTP endpoint, add that endpoint origin to `WEBHOOK_ALLOWED_ORIGINS`.
+
**Fields**
- `Shoutrrr URL`