From 76667ffcf9937cb4dd0428b5858710c218ee9f71 Mon Sep 17 00:00:00 2001
From: nisbet-hubbard <87453615+nisbet-hubbard@users.noreply.github.com>
Date: Wed, 12 Jul 2023 18:18:48 +0800
Subject: [PATCH 1/5] Use mod_proxy_http for websocket upgrade
mod_proxy_wstunnel is deprecated as of httpd 2.4.47. It also uses more resources since it relies on mod_rewrite.
See https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#protoupgrade.
---
docs/config.md | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/docs/config.md b/docs/config.md
index 9af79992..3577bb48 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -649,8 +649,8 @@ or the root domain:
ServerName ntfy.sh
- # Proxy connections to ntfy (requires "a2enmod proxy")
- ProxyPass / http://127.0.0.1:2586/
+ # Proxy connections to ntfy (requires "a2enmod proxy proxy_http")
+ ProxyPass / http://127.0.0.1:2586/ upgrade=websocket
ProxyPassReverse / http://127.0.0.1:2586/
SetEnv proxy-nokeepalive 1
@@ -661,11 +661,6 @@ or the root domain:
# Enable mod_rewrite (requires "a2enmod rewrite")
RewriteEngine on
-
- # 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]
# Redirect HTTP to HTTPS, but only for GET topic addresses, since we want
# it to work with curl without the annoying https:// prefix
@@ -681,8 +676,8 @@ or the root domain:
SSLCertificateKeyFile /etc/letsencrypt/live/ntfy.sh/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
- # Proxy connections to ntfy (requires "a2enmod proxy")
- ProxyPass / http://127.0.0.1:2586/
+ # Proxy connections to ntfy (requires "a2enmod proxy proxy_http")
+ ProxyPass / http://127.0.0.1:2586/ upgrade=websocket
ProxyPassReverse / http://127.0.0.1:2586/
SetEnv proxy-nokeepalive 1
@@ -693,11 +688,7 @@ or the root domain:
# Enable mod_rewrite (requires "a2enmod rewrite")
RewriteEngine on
-
- # 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]
+
```
From e52132c85b1297a53911f97302546aab227097eb Mon Sep 17 00:00:00 2001
From: nisbet-hubbard <87453615+nisbet-hubbard@users.noreply.github.com>
Date: Wed, 12 Jul 2023 19:48:51 +0800
Subject: [PATCH 2/5] Use mod_alias for redirection
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
It’s a less resource-intensive alternative to mod_rewrite.
---
docs/config.md | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/docs/config.md b/docs/config.md
index 3577bb48..af84dae9 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -658,14 +658,13 @@ or the root domain:
# Higher than the max message size of 4096 bytes
LimitRequestBody 102400
-
- # Enable mod_rewrite (requires "a2enmod rewrite")
- RewriteEngine on
# 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]
+ # it to work with curl without the annoying https:// prefix (requires "a2enmod alias")
+
+ RedirectMatch permanent "^/([-_A-Za-z0-9]{0,64})$" "https://%{SERVER_NAME}/$1"
+
+
@@ -685,9 +684,6 @@ or the root domain:
# Higher than the max message size of 4096 bytes
LimitRequestBody 102400
-
- # Enable mod_rewrite (requires "a2enmod rewrite")
- RewriteEngine on
```
From a534cc9ecacb5985c1de4b503ae435fe9973c768 Mon Sep 17 00:00:00 2001
From: nisbet-hubbard <87453615+nisbet-hubbard@users.noreply.github.com>
Date: Wed, 12 Jul 2023 20:00:48 +0800
Subject: [PATCH 3/5] Add server.yml ex. when using proxy
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This would help inexperienced sysadmins who may not realise that since TLS terminates at proxy, ntfy is actually listening on a TCP socket that’s using http rather than https.
---
docs/config.md | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/docs/config.md b/docs/config.md
index af84dae9..bb7f7e1b 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -44,6 +44,14 @@ Here are a few working sample configs:
attachment-cache-dir: "/var/cache/ntfy/attachments"
```
+=== "server.yml (behind proxy, with cache + attachments)"
+ ``` yaml
+ base-url: "http://ntfy.example.com"
+ listen-http: ":2586"
+ cache-file: "/var/cache/ntfy/cache.db"
+ attachment-cache-dir: "/var/cache/ntfy/attachments"
+ ```
+
=== "server.yml (ntfy.sh config)"
``` yaml
# All the things: Behind a proxy, Firebase, cache, attachments,
From 4e9eeb1fa168e0d27d6df013242aefc6e172fe5a Mon Sep 17 00:00:00 2001
From: nisbet-hubbard <87453615+nisbet-hubbard@users.noreply.github.com>
Date: Wed, 12 Jul 2023 20:24:57 +0800
Subject: [PATCH 4/5] Add missing note on log file permissions
---
server/server.yml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/server/server.yml b/server/server.yml
index 6b2fc989..b044a914 100644
--- a/server/server.yml
+++ b/server/server.yml
@@ -342,6 +342,10 @@
# - "field -> level" to match any value, e.g. "time_taken_ms -> debug"
# Warning: Using log-level-overrides has a performance penalty. Only use it for temporary debugging.
#
+# Check your permissions:
+# If you are running ntfy with systemd, make sure this log file is owned by the
+# ntfy user and group by running: chown ntfy.ntfy .
+#
# Example (good for production):
# log-level: info
# log-format: json
From 384cabede52dc61ca57c1033bf6d4d27554d4ee2 Mon Sep 17 00:00:00 2001
From: Nihal Gonsalves
Date: Fri, 14 Jul 2023 13:10:24 +0200
Subject: [PATCH 5/5] feat: check extension to display external images
---
web/src/app/notificationUtils.js | 2 +-
web/src/components/Notifications.jsx | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/web/src/app/notificationUtils.js b/web/src/app/notificationUtils.js
index 35c85ce6..0bd5136d 100644
--- a/web/src/app/notificationUtils.js
+++ b/web/src/app/notificationUtils.js
@@ -35,7 +35,7 @@ export const formatMessage = (m) => {
};
const imageRegex = /\.(png|jpe?g|gif|webp)$/i;
-const isImage = (attachment) => {
+export const isImage = (attachment) => {
if (!attachment) return false;
// if there's a type, only take that into account
diff --git a/web/src/components/Notifications.jsx b/web/src/components/Notifications.jsx
index d1cce0e8..0b8b2e7d 100644
--- a/web/src/components/Notifications.jsx
+++ b/web/src/components/Notifications.jsx
@@ -27,7 +27,7 @@ import { useOutletContext } from "react-router-dom";
import { useRemark } from "react-remark";
import styled from "@emotion/styled";
import { formatBytes, formatShortDateTime, maybeActionErrors, openUrl, shortUrl, topicShortUrl, unmatchedTags } from "../app/utils";
-import { formatMessage, formatTitle } from "../app/notificationUtils";
+import { formatMessage, formatTitle, isImage } from "../app/notificationUtils";
import { LightboxBackdrop, Paragraph, VerticallyCenteredContainer } from "./styles";
import subscriptionManager from "../app/SubscriptionManager";
import priority1 from "../img/priority-1.svg";
@@ -346,7 +346,7 @@ const Attachment = (props) => {
const { attachment } = props;
const expired = attachment.expires && attachment.expires < Date.now() / 1000;
const expires = attachment.expires && attachment.expires > Date.now() / 1000;
- const displayableImage = !expired && attachment.type && attachment.type.startsWith("image/");
+ const displayableImage = !expired && isImage(attachment);
// Unexpired image
if (displayableImage) {