[GH-ISSUE #1018] Self Hosted ntfy Server with Basic Auth (via Nginx Reverse Proxy) not supported via Mobile App #714

Closed
opened 2026-05-07 00:26:49 +02:00 by BreizhHardware · 8 comments

Originally created by @caronc on GitHub (Feb 7, 2024).
Original GitHub issue: https://github.com/binwiederhier/ntfy/issues/1018

🐞 Describe the bug
I could be doing something wrong I'm sure, but I've got a ntfy deployed on my home server and it works great because I've set up the Nginx basic auth to not be applied from requests from my local network.

However when I leave my home and my IP is now one from a nearby tower (or any external one), basic auth doesn't appear to work correctly using the mobile app, but I can easily point to my hosted service through the browser and authenticate without any issue (so configuration wise, i feel as though i'm good).

I was hoping the logic would simply be: https://user:pass@my.ntfy.server
imag1

But this just turns into a Reconnecting... setup until i return back into my local network.
imag2

How can the mobile app recognize Basic Auth?

💻 Components impacted
Android App

💡 Screenshots and/or logs
Screenshots shown above

🔮 Additional context
n/a

Originally created by @caronc on GitHub (Feb 7, 2024). Original GitHub issue: https://github.com/binwiederhier/ntfy/issues/1018 :lady_beetle: **Describe the bug** I could be doing something wrong I'm sure, but I've got a ntfy deployed on my home server and it works great because I've set up the Nginx `basic auth` to not be applied from requests from my local network. However when I leave my home and my IP is now one from a nearby tower (or any external one), basic auth doesn't appear to work correctly using the mobile app, but I can easily point to my hosted service through the browser and authenticate without any issue (so configuration wise, i feel as though i'm good). I was hoping the logic would simply be: `https://user:pass@my.ntfy.server` ![imag1](https://github.com/binwiederhier/ntfy/assets/850374/2eb76e9e-206f-4ac8-8df1-f13f934b90d8) But this just turns into a `Reconnecting...` setup until i return back into my local network. ![imag2](https://github.com/binwiederhier/ntfy/assets/850374/4bca13a7-04b8-42f8-8635-003fb34bc711) How can the mobile app recognize Basic Auth? :computer: **Components impacted** Android App :bulb: **Screenshots and/or logs** Screenshots shown above :crystal_ball: **Additional context** n/a
BreizhHardware 2026-05-07 00:26:49 +02:00
  • closed this issue
  • added the
    🪲 bug
    label
Author
Owner

@Torxgewinde commented on GitHub (Feb 24, 2024):

Just my two cents:

AFAIK for HTTP-Basic-Auth the credentials go in a separate menu, this should be similar to this screenshot:
signal-2024-02-24-102603_002

Please also note, that the endpoint "/file/" must not have HTTP-basic-auth enforced by the reverse-proxy: https://github.com/binwiederhier/ntfy/issues/893#issuecomment-1731314679

<!-- gh-comment-id:1962322725 --> @Torxgewinde commented on GitHub (Feb 24, 2024): Just my two cents: AFAIK for HTTP-Basic-Auth the credentials go in a separate menu, this should be similar to this screenshot: ![signal-2024-02-24-102603_002](https://github.com/binwiederhier/ntfy/assets/12876583/fa9d43af-af77-405a-abce-27fb3adce521) Please also note, that the endpoint "/file/" must not have HTTP-basic-auth enforced by the reverse-proxy: https://github.com/binwiederhier/ntfy/issues/893#issuecomment-1731314679
Author
Owner

@caronc commented on GitHub (Feb 24, 2024):

Thanks for your post, unfortunately That didn't work. 😔

I would additionally upgrade this bug to include http-auth for files too then. Exposing ntfy to the internet with file upload access wide open is not ideal under any circumstance.

<!-- gh-comment-id:1962331740 --> @caronc commented on GitHub (Feb 24, 2024): Thanks for your post, unfortunately That didn't work. 😔 I would additionally upgrade this bug to include http-auth for files too then. Exposing ntfy to the internet with file upload access wide open is not ideal under any circumstance.
Author
Owner

@Torxgewinde commented on GitHub (Feb 24, 2024):

I add the server.yml and the haproxy.conf config i am using. In my setup it works well and indeed blocks/redirects unauthenticated users. The /file/ endpoint is not used for uploading, just for downloading AFAIK and the filename is changed to same random string which serves the same purpose as a token or additional Authentication: header.

In addition i also configured the same user in NTFY, so both (Reverse-Proxy and also in addition NTFY) check if the user is valid.

HTH

haproxy.conf

########################################################################
#
# Configuration file for HAProxy in front of NTFY
#
# Docu:
#  https://www.haproxy.com/documentation/hapee/latest/onepage/
#  https://www.haproxy.com/blog/websockets-load-balancing-with-haproxy
#  https://delta.blue/blog/haproxy-timeouts/
#  https://www.haproxy.com/documentation/haproxy-configuration-tutorials/authentication/basic-authentication/
#  https://www.haproxy.com/documentation/haproxy-configuration-tutorials/client-ip-preservation/add-x-forward-for-header/
#
# Testing the config:
#  haproxy -f /etc/haproxy/haproxy.cfg -d
# Restarting the service:
#  service haproxy restart
########################################################################

global
	maxconn 100
	user nobody
	group nogroup
	daemon
	nosplice

#default settings:
defaults
	mode http
	timeout connect 1s
	timeout client 60s
	timeout http-request 10s
	timeout http-keep-alive 10s
	timeout server 60s
	timeout server-fin 10s
	timeout tunnel 120s
	timeout client-fin 10s
	retries 2

# List of username and passwords we accept:
#  Plaintext Passwords: user myUsername insecure-password myPassword
#  Hash only with mkpasswd from packet "whois":
#   - Generate: mkpasswd -m sha-256 myPassword
#   - Add entry: user myUsername password myPasswordHashFromAbove
userlist mycredentials
	user Torxgewinde password $HASH_abcdefghijklmnopqrstuvwxyz_HASH$

# TCP frontend with TLS/SSL
frontend frontend_ntfy_proxy
	#
	# create combined_certs with this command:
	# cat server-cert.pem server-key.pem > combined_certs
	#
	bind [::]:443,:443 ssl crt /etc/haproxy/example.quicksrv.de.combined ssl-min-ver TLSv1.3

	# add header X-Forwarded-For:
	# This is needed or otherwise to NTFY all interactions count as a single interaction
	option forwardfor

	# try to push everything to https/wss encrypted connections:
	http-request redirect scheme https unless { ssl_fc }
	http-request redirect code 301 location https://%[hdr(host)]%[capture.req.uri] unless { ssl_fc }
	http-request deny unless { ssl_fc }

	# Everything must be authenticated except for /file/ endpoint
	# See: https://github.com/binwiederhier/ntfy/issues/893#issuecomment-1731314679
	http-request auth unless { http_auth(mycredentials) } or { path_beg /file/ }

	#is it a websocket?
	acl for_websocket hdr(Upgrade) -i websocket
	acl for_websocket hdr(Connection) -i upgrade
	use_backend backend_ntfy_ws if for_websocket

	#everything else is handled as HTTP request
	default_backend backend_ntfy_http

# Default backend to contact NTFY
backend backend_ntfy_http
	#add header to signal which backend handled the request
	http-response set-header X-Torxgewinde "backend_ntfy_http"

	#forward request to this server, this is where FHEMWEB listens
	server NTFY_SERVER_HTTP 127.0.0.1:8080

# NTFY websocket backend
backend backend_ntfy_ws
	#add header to signal which backend handled the request
	http-response set-header X-Torxgewinde "backend_ntfy_ws"

	#reject/deny if the following checks do not match
	acl hdr_connection_upgrade hdr(Connection) -i upgrade
	acl hdr_upgrade_websocket hdr(Upgrade) -i websocket
	acl hdr_websocket_key hdr_cnt(Sec-WebSocket-Key) eq 1
	acl hdr_websocket_version hdr_cnt(Sec-WebSocket-Version) eq 1
	http-request deny if !hdr_connection_upgrade !hdr_upgrade_websocket !hdr_websocket_key !hdr_websocket_version

	server NTFY_SERVER_WS 127.0.0.1:8080
# ntfy server config file
#
# Please refer to the documentation at https://ntfy.sh/docs/config/ for details.
# All options also support underscores (_) instead of dashes (-) to comply with the YAML spec.

# Public facing base URL of the service (e.g. https://ntfy.sh or https://ntfy.example.com)
#
# This setting is required for any of the following features:
# - attachments (to return a download URL)
# - e-mail sending (for the topic URL in the email footer)
# - iOS push notifications for self-hosted servers (to calculate the Firebase poll_request topic)
# - Matrix Push Gateway (to validate that the pushkey is correct)
#
base-url: "https://example.quicksrv.de"

# Listen address for the HTTP & HTTPS web server. If "listen-https" is set, you must also
# set "key-file" and "cert-file". Format: [<ip>]:<port>, e.g. "1.2.3.4:8080".
#
# To listen on all interfaces, you may omit the IP address, e.g. ":443".
# To disable HTTP, set "listen-http" to "-".
#
listen-http: "127.0.0.1:8080"
# listen-https:

# Listen on a Unix socket, e.g. /var/lib/ntfy/ntfy.sock
# This can be useful to avoid port issues on local systems, and to simplify permissions.
#
# listen-unix: <socket-path>
# listen-unix-mode: <linux permissions, e.g. 0700>

# Path to the private key & cert file for the HTTPS web server. Not used if "listen-https" is not set.
#
# key-file: <filename>
# cert-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.
#
# firebase-key-file: <filename>

# If "cache-file" is 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.
#
# The "cache-duration" parameter defines the duration for which messages will be buffered
# before they are deleted. This is required to support the "since=..." and "poll=1" parameter.
# To disable the cache entirely (on-disk/in-memory), set "cache-duration" to 0.
# The cache file is created automatically, provided that the correct permissions are set.
#
# The "cache-startup-queries" parameter allows you to run commands when the database is initialized,
# e.g. to enable WAL mode (see https://phiresky.github.io/blog/2020/sqlite-performance-tuning/)).
# Example:
#    cache-startup-queries: |
#       pragma journal_mode = WAL;
#       pragma synchronous = normal;
#       pragma temp_store = memory;
#       pragma busy_timeout = 15000;
#       vacuum;
#
# The "cache-batch-size" and "cache-batch-timeout" parameter allow enabling async batch writing
# of messages. If set, messages will be queued and written to the database in batches of the given
# size, or after the given timeout. This is only required for high volume servers.
#
# Debian/RPM package users:
#   Use /var/cache/ntfy/cache.db as cache file to avoid permission issues. The package
#   creates this folder for you.
#
# Check your permissions:
#   If you are running ntfy with systemd, make sure this cache file is owned by the
#   ntfy user and group by running: chown ntfy.ntfy <filename>.
#
cache-file: "/var/cache/ntfy/cache.db"
cache-duration: "720h"
# cache-startup-queries:
# cache-batch-size: 0
# cache-batch-timeout: "0ms"

# If set, access to the ntfy server and API can be controlled on a granular level using
# the 'ntfy user' and 'ntfy access' commands. See the --help pages for details, or check the docs.
#
# - auth-file is the SQLite user/access database; it is created automatically if it doesn't already exist
# - 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".
# - auth-startup-queries allows you to run commands when the database is initialized, e.g. to enable
#   WAL mode. This is similar to cache-startup-queries. See above for details.
#
# Debian/RPM package users:
#   Use /var/lib/ntfy/user.db as user database to avoid permission issues. The package
#   creates this folder for you.
#
# Check your permissions:
#   If you are running ntfy with systemd, make sure this user database file is owned by the
#   ntfy user and group by running: chown ntfy.ntfy <filename>.
#
# auth-file: <filename>
# auth-default-access: "read-write"
# auth-startup-queries:
auth-file: "/var/lib/ntfy/user.db"
auth-default-access: "deny-all"


# 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: true

# If enabled, clients can attach files to notifications as attachments. Minimum settings to enable attachments
# are "attachment-cache-dir" and "base-url".
#
# - attachment-cache-dir is the cache directory for attached files
# - attachment-total-size-limit is the limit of the on-disk attachment cache directory (total size)
# - attachment-file-size-limit is the per-file attachment size limit (e.g. 300k, 2M, 100M)
# - attachment-expiry-duration is the duration after which uploaded attachments will be deleted (e.g. 3h, 20h)
#
attachment-cache-dir: "/var/cache/ntfy/attachments"
attachment-total-size-limit: "10G"
attachment-file-size-limit: "1G"
attachment-expiry-duration: "720h"

# If enabled, allow outgoing e-mail notifications via the 'X-Email' header. If this header is set,
# messages will additionally be sent out as e-mail using an external SMTP server.
#
# As of today, only SMTP servers with plain text auth (or no auth at all), and STARTLS are supported.
# Please also refer to the rate limiting settings below (visitor-email-limit-burst & visitor-email-limit-burst).
#
# - smtp-sender-addr is the hostname:port of the SMTP server
# - smtp-sender-from is the e-mail address of the sender
# - smtp-sender-user/smtp-sender-pass are the username and password of the SMTP user (leave blank for no auth)
#
# smtp-sender-addr:
# smtp-sender-from:
# smtp-sender-user:
# smtp-sender-pass:

# If enabled, ntfy will launch a lightweight SMTP server for incoming messages. Once configured, users can send
# emails to a topic e-mail address to publish messages to a topic.
#
# - smtp-server-listen defines the IP address and port the SMTP server will listen on, e.g. :25 or 1.2.3.4:25
# - smtp-server-domain is the e-mail domain, e.g. ntfy.sh
# - smtp-server-addr-prefix is an optional prefix for the e-mail addresses to prevent spam. If set to "ntfy-",
#   for instance, only e-mails to ntfy-$topic@ntfy.sh will be accepted. If this is not set, all emails to
#   $topic@ntfy.sh will be accepted (which may obviously be a spam problem).
#
# smtp-server-listen:
# smtp-server-domain:
# smtp-server-addr-prefix:

# Web Push support (background notifications for browsers)
#
# If enabled, allows ntfy to receive push notifications, even when the ntfy web app is closed. When enabled, users
# can enable background notifications in the web app. Once enabled, ntfy will forward published messages to the push
# endpoint, which will then forward it to the browser.
#
# You must configure web-push-public/private key, web-push-file, and web-push-email-address below to enable Web Push.
# Run "ntfy webpush keys" to generate the keys.
#
# - web-push-public-key is the generated VAPID public key, e.g. AA1234BBCCddvveekaabcdfqwertyuiopasdfghjklzxcvbnm1234567890
# - web-push-private-key is the generated VAPID private key, e.g. AA2BB1234567890abcdefzxcvbnm1234567890
# - web-push-file is a database file to keep track of browser subscription endpoints, e.g. `/var/cache/ntfy/webpush.db`
# - web-push-email-address is the admin email address send to the push provider, e.g. `sysadmin@example.com`
# - web-push-startup-queries is an optional list of queries to run on startup`
#
# web-push-public-key:
# web-push-private-key:
# web-push-file:
# web-push-email-address:
# web-push-startup-queries:

# If enabled, ntfy can perform voice calls via Twilio via the "X-Call" header.
#
# - twilio-account is the Twilio account SID, e.g. AC12345beefbeef67890beefbeef122586
# - twilio-auth-token is the Twilio auth token, e.g. affebeef258625862586258625862586
# - twilio-phone-number is the outgoing phone number you purchased, e.g. +18775132586
# - twilio-verify-service is the Twilio Verify service SID, e.g. VA12345beefbeef67890beefbeef122586
#
# twilio-account:
# twilio-auth-token:
# twilio-phone-number:
# twilio-verify-service:

# 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.
#
# keepalive-interval: "45s"

# Interval in which the manager prunes old messages, deletes topics
# and prints the stats.
#
# manager-interval: "1m"

# Defines topic names that are not allowed, because they are otherwise used. There are a few default topics
# that cannot be used (e.g. app, account, settings, ...). To extend the default list, define them here.
#
# Example:
#   disallowed-topics:
#     - about
#     - pricing
#     - contact
#
# disallowed-topics:

# Defines the root path of the web app, or disables the web app entirely.
#
# Can be any simple path, e.g. "/", "/app", or "/ntfy". For backwards-compatibility reasons,
# the values "app" (maps to "/"), "home" (maps to "/app"), or "disable" (maps to "") to disable
# the web app entirely.
#
#web-root: "/"
web-root: disable

# Various feature flags used to control the web app, and API access, mainly around user and
# account management.
#
# - enable-signup allows users to sign up via the web app, or API
# - enable-login allows users to log in via the web app, or API
# - enable-reservations allows users to reserve topics (if their tier allows it)
#
enable-signup: false
enable-login: false
# enable-reservations: false

# Server URL of a Firebase/APNS-connected ntfy server (likely "https://ntfy.sh").
#
# iOS users:
#   If you use the iOS ntfy app, you MUST configure this to receive timely notifications. You'll like want this:
#   upstream-base-url: "https://ntfy.sh"
#
# If set, all incoming messages will publish a "poll_request" message to the configured upstream server, containing
# the message ID of the original message, instructing the iOS app to poll this server for the actual message contents.
# This is to prevent the upstream server and Firebase/APNS from being able to read the message.
#
# - upstream-base-url is the base URL of the upstream server. Should be "https://ntfy.sh".
# - upstream-access-token is the token used to authenticate with the upstream server. This is only required
#   if you exceed the upstream rate limits, or the uptream server requires authentication.
#
# upstream-base-url:
# upstream-access-token:

# Rate limiting: Total number of topics before the server rejects new topics.
#
# global-topic-limit: 15000

# Rate limiting: Number of subscriptions per visitor (IP address)
#
# visitor-subscription-limit: 30

# Rate limiting: Allowed GET/PUT/POST requests per second, per visitor:
# - visitor-request-limit-burst is the initial bucket of requests each visitor has
# - visitor-request-limit-replenish is the rate at which the bucket is refilled
# - visitor-request-limit-exempt-hosts is a comma-separated list of hostnames, IPs or CIDRs to be
#   exempt from request rate limiting. Hostnames are resolved at the time the server is started.
#   Example: "1.2.3.4,ntfy.example.com,8.7.6.0/24"
#
visitor-request-limit-burst: 60
visitor-request-limit-replenish: "5s"
# visitor-request-limit-exempt-hosts: ""

# Rate limiting: Hard daily limit of messages per visitor and day. The limit is reset
# every day at midnight UTC. If the limit is not set (or set to zero), the request
# limit (see above) governs the upper limit.
#
visitor-message-daily-limit: 1000

# Rate limiting: Allowed emails per visitor:
# - visitor-email-limit-burst is the initial bucket of emails each visitor has
# - visitor-email-limit-replenish is the rate at which the bucket is refilled
#
# visitor-email-limit-burst: 16
# visitor-email-limit-replenish: "1h"

# Rate limiting: Attachment size and bandwidth limits per visitor:
# - visitor-attachment-total-size-limit is the total storage limit used for attachments per visitor
# - visitor-attachment-daily-bandwidth-limit is the total daily attachment download/upload traffic limit per visitor
#
# visitor-attachment-total-size-limit: "100M"
# visitor-attachment-daily-bandwidth-limit: "500M"

# Rate limiting: Enable subscriber-based rate limiting (mostly used for UnifiedPush)
#
# If enabled, subscribers may opt to have published messages counted against their own rate limits, as opposed
# to the publisher's rate limits. This is especially useful to increase the amount of messages that high-volume
# publishers (e.g. Matrix/Mastodon servers) are allowed to send.
#
# Once enabled, a client may send a "Rate-Topics: <topic1>,<topic2>,..." header when subscribing to topics via
# HTTP stream, or websockets, thereby registering itself as the "rate visitor", i.e. the visitor whose rate limits
# to use when publishing on this topic. Note: Setting the rate visitor requires READ-WRITE permission on the topic.
#
# UnifiedPush only: If this setting is enabled, publishing to UnifiedPush topics will lead to a HTTP 507 response if
# no "rate visitor" has been previously registered. This is to avoid burning the publisher's "visitor-message-daily-limit".
#
# visitor-subscriber-rate-limiting: false

# Payments integration via Stripe
#
# - stripe-secret-key is the key used for the Stripe API communication. Setting this values
#   enables payments in the ntfy web app (e.g. Upgrade dialog). See https://dashboard.stripe.com/apikeys.
# - stripe-webhook-key is the key required to validate the authenticity of incoming webhooks from Stripe.
#   Webhooks are essential up keep the local database in sync with the payment provider. See https://dashboard.stripe.com/webhooks.
# - billing-contact is an email address or website displayed in the "Upgrade tier" dialog to let people reach
#   out with billing questions. If unset, nothing will be displayed.
#
# stripe-secret-key:
# stripe-webhook-key:
# billing-contact:

# Metrics
#
# ntfy can expose Prometheus-style metrics via a /metrics endpoint, or on a dedicated listen IP/port.
# Metrics may be considered sensitive information, so before you enable them, be sure you know what you are
# doing, and/or secure access to the endpoint in your reverse proxy.
#
# - enable-metrics enables the /metrics endpoint for the default ntfy server (i.e. HTTP, HTTPS and/or Unix socket)
# - metrics-listen-http exposes the metrics endpoint via a dedicated [IP]:port. If set, this option implicitly
#   enables metrics as well, e.g. "10.0.1.1:9090" or ":9090"
#
# enable-metrics: false
# metrics-listen-http:

# Profiling
#
# ntfy can expose Go's net/http/pprof endpoints to support profiling of the ntfy server. If enabled, ntfy will listen
# on a dedicated listen IP/port, which can be accessed via the web browser on http://<ip>:<port>/debug/pprof/.
# This can be helpful to expose bottlenecks, and visualize call flows. See https://pkg.go.dev/net/http/pprof for details.
#
# profile-listen-http:

# Logging options
#
# By default, ntfy logs to the console (stderr), with an "info" log level, and in a human-readable text format.
# ntfy supports five different log levels, can also write to a file, log as JSON, and even supports granular
# log level overrides for easier debugging. Some options (log-level and log-level-overrides) can be hot reloaded
# by calling "kill -HUP $pid" or "systemctl reload ntfy".
#
# - log-format defines the output format, can be "text" (default) or "json"
# - log-file is a filename to write logs to. If this is not set, ntfy logs to stderr.
# - log-level defines the default log level, can be one of "trace", "debug", "info" (default), "warn" or "error".
#   Be aware that "debug" (and particularly "trace") can be VERY CHATTY. Only turn them on briefly for debugging purposes.
# - log-level-overrides lets you override the log level if certain fields match. This is incredibly powerful
#   for debugging certain parts of the system (e.g. only the account management, or only a certain visitor).
#   This is an array of strings in the format:
#      - "field=value -> level" to match a value exactly, e.g. "tag=manager -> trace"
#      - "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 <filename>.
#
# Example (good for production):
#   log-level: info
#   log-format: json
#   log-file: /var/log/ntfy.log
#
# Example level overrides (for debugging, only use temporarily):
#   log-level-overrides:
#      - "tag=manager -> trace"
#      - "visitor_ip=1.2.3.4 -> debug"
#      - "time_taken_ms -> debug"
#
# log-level: info
# log-level-overrides:
# log-format: text
# log-file:
<!-- gh-comment-id:1962347307 --> @Torxgewinde commented on GitHub (Feb 24, 2024): I add the `server.yml` and the `haproxy.conf` config i am using. In my setup it works well and indeed blocks/redirects unauthenticated users. The `/file/` endpoint is not used for uploading, just for downloading AFAIK and the filename is changed to same random string which serves the same purpose as a token or additional `Authentication:` header. In addition i also configured the same user in NTFY, so both (Reverse-Proxy and also in addition NTFY) check if the user is valid. HTH haproxy.conf ``` ######################################################################## # # Configuration file for HAProxy in front of NTFY # # Docu: # https://www.haproxy.com/documentation/hapee/latest/onepage/ # https://www.haproxy.com/blog/websockets-load-balancing-with-haproxy # https://delta.blue/blog/haproxy-timeouts/ # https://www.haproxy.com/documentation/haproxy-configuration-tutorials/authentication/basic-authentication/ # https://www.haproxy.com/documentation/haproxy-configuration-tutorials/client-ip-preservation/add-x-forward-for-header/ # # Testing the config: # haproxy -f /etc/haproxy/haproxy.cfg -d # Restarting the service: # service haproxy restart ######################################################################## global maxconn 100 user nobody group nogroup daemon nosplice #default settings: defaults mode http timeout connect 1s timeout client 60s timeout http-request 10s timeout http-keep-alive 10s timeout server 60s timeout server-fin 10s timeout tunnel 120s timeout client-fin 10s retries 2 # List of username and passwords we accept: # Plaintext Passwords: user myUsername insecure-password myPassword # Hash only with mkpasswd from packet "whois": # - Generate: mkpasswd -m sha-256 myPassword # - Add entry: user myUsername password myPasswordHashFromAbove userlist mycredentials user Torxgewinde password $HASH_abcdefghijklmnopqrstuvwxyz_HASH$ # TCP frontend with TLS/SSL frontend frontend_ntfy_proxy # # create combined_certs with this command: # cat server-cert.pem server-key.pem > combined_certs # bind [::]:443,:443 ssl crt /etc/haproxy/example.quicksrv.de.combined ssl-min-ver TLSv1.3 # add header X-Forwarded-For: # This is needed or otherwise to NTFY all interactions count as a single interaction option forwardfor # try to push everything to https/wss encrypted connections: http-request redirect scheme https unless { ssl_fc } http-request redirect code 301 location https://%[hdr(host)]%[capture.req.uri] unless { ssl_fc } http-request deny unless { ssl_fc } # Everything must be authenticated except for /file/ endpoint # See: https://github.com/binwiederhier/ntfy/issues/893#issuecomment-1731314679 http-request auth unless { http_auth(mycredentials) } or { path_beg /file/ } #is it a websocket? acl for_websocket hdr(Upgrade) -i websocket acl for_websocket hdr(Connection) -i upgrade use_backend backend_ntfy_ws if for_websocket #everything else is handled as HTTP request default_backend backend_ntfy_http # Default backend to contact NTFY backend backend_ntfy_http #add header to signal which backend handled the request http-response set-header X-Torxgewinde "backend_ntfy_http" #forward request to this server, this is where FHEMWEB listens server NTFY_SERVER_HTTP 127.0.0.1:8080 # NTFY websocket backend backend backend_ntfy_ws #add header to signal which backend handled the request http-response set-header X-Torxgewinde "backend_ntfy_ws" #reject/deny if the following checks do not match acl hdr_connection_upgrade hdr(Connection) -i upgrade acl hdr_upgrade_websocket hdr(Upgrade) -i websocket acl hdr_websocket_key hdr_cnt(Sec-WebSocket-Key) eq 1 acl hdr_websocket_version hdr_cnt(Sec-WebSocket-Version) eq 1 http-request deny if !hdr_connection_upgrade !hdr_upgrade_websocket !hdr_websocket_key !hdr_websocket_version server NTFY_SERVER_WS 127.0.0.1:8080 ``` ``` # ntfy server config file # # Please refer to the documentation at https://ntfy.sh/docs/config/ for details. # All options also support underscores (_) instead of dashes (-) to comply with the YAML spec. # Public facing base URL of the service (e.g. https://ntfy.sh or https://ntfy.example.com) # # This setting is required for any of the following features: # - attachments (to return a download URL) # - e-mail sending (for the topic URL in the email footer) # - iOS push notifications for self-hosted servers (to calculate the Firebase poll_request topic) # - Matrix Push Gateway (to validate that the pushkey is correct) # base-url: "https://example.quicksrv.de" # Listen address for the HTTP & HTTPS web server. If "listen-https" is set, you must also # set "key-file" and "cert-file". Format: [<ip>]:<port>, e.g. "1.2.3.4:8080". # # To listen on all interfaces, you may omit the IP address, e.g. ":443". # To disable HTTP, set "listen-http" to "-". # listen-http: "127.0.0.1:8080" # listen-https: # Listen on a Unix socket, e.g. /var/lib/ntfy/ntfy.sock # This can be useful to avoid port issues on local systems, and to simplify permissions. # # listen-unix: <socket-path> # listen-unix-mode: <linux permissions, e.g. 0700> # Path to the private key & cert file for the HTTPS web server. Not used if "listen-https" is not set. # # key-file: <filename> # cert-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. # # firebase-key-file: <filename> # If "cache-file" is 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. # # The "cache-duration" parameter defines the duration for which messages will be buffered # before they are deleted. This is required to support the "since=..." and "poll=1" parameter. # To disable the cache entirely (on-disk/in-memory), set "cache-duration" to 0. # The cache file is created automatically, provided that the correct permissions are set. # # The "cache-startup-queries" parameter allows you to run commands when the database is initialized, # e.g. to enable WAL mode (see https://phiresky.github.io/blog/2020/sqlite-performance-tuning/)). # Example: # cache-startup-queries: | # pragma journal_mode = WAL; # pragma synchronous = normal; # pragma temp_store = memory; # pragma busy_timeout = 15000; # vacuum; # # The "cache-batch-size" and "cache-batch-timeout" parameter allow enabling async batch writing # of messages. If set, messages will be queued and written to the database in batches of the given # size, or after the given timeout. This is only required for high volume servers. # # Debian/RPM package users: # Use /var/cache/ntfy/cache.db as cache file to avoid permission issues. The package # creates this folder for you. # # Check your permissions: # If you are running ntfy with systemd, make sure this cache file is owned by the # ntfy user and group by running: chown ntfy.ntfy <filename>. # cache-file: "/var/cache/ntfy/cache.db" cache-duration: "720h" # cache-startup-queries: # cache-batch-size: 0 # cache-batch-timeout: "0ms" # If set, access to the ntfy server and API can be controlled on a granular level using # the 'ntfy user' and 'ntfy access' commands. See the --help pages for details, or check the docs. # # - auth-file is the SQLite user/access database; it is created automatically if it doesn't already exist # - 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". # - auth-startup-queries allows you to run commands when the database is initialized, e.g. to enable # WAL mode. This is similar to cache-startup-queries. See above for details. # # Debian/RPM package users: # Use /var/lib/ntfy/user.db as user database to avoid permission issues. The package # creates this folder for you. # # Check your permissions: # If you are running ntfy with systemd, make sure this user database file is owned by the # ntfy user and group by running: chown ntfy.ntfy <filename>. # # auth-file: <filename> # auth-default-access: "read-write" # auth-startup-queries: auth-file: "/var/lib/ntfy/user.db" auth-default-access: "deny-all" # 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: true # If enabled, clients can attach files to notifications as attachments. Minimum settings to enable attachments # are "attachment-cache-dir" and "base-url". # # - attachment-cache-dir is the cache directory for attached files # - attachment-total-size-limit is the limit of the on-disk attachment cache directory (total size) # - attachment-file-size-limit is the per-file attachment size limit (e.g. 300k, 2M, 100M) # - attachment-expiry-duration is the duration after which uploaded attachments will be deleted (e.g. 3h, 20h) # attachment-cache-dir: "/var/cache/ntfy/attachments" attachment-total-size-limit: "10G" attachment-file-size-limit: "1G" attachment-expiry-duration: "720h" # If enabled, allow outgoing e-mail notifications via the 'X-Email' header. If this header is set, # messages will additionally be sent out as e-mail using an external SMTP server. # # As of today, only SMTP servers with plain text auth (or no auth at all), and STARTLS are supported. # Please also refer to the rate limiting settings below (visitor-email-limit-burst & visitor-email-limit-burst). # # - smtp-sender-addr is the hostname:port of the SMTP server # - smtp-sender-from is the e-mail address of the sender # - smtp-sender-user/smtp-sender-pass are the username and password of the SMTP user (leave blank for no auth) # # smtp-sender-addr: # smtp-sender-from: # smtp-sender-user: # smtp-sender-pass: # If enabled, ntfy will launch a lightweight SMTP server for incoming messages. Once configured, users can send # emails to a topic e-mail address to publish messages to a topic. # # - smtp-server-listen defines the IP address and port the SMTP server will listen on, e.g. :25 or 1.2.3.4:25 # - smtp-server-domain is the e-mail domain, e.g. ntfy.sh # - smtp-server-addr-prefix is an optional prefix for the e-mail addresses to prevent spam. If set to "ntfy-", # for instance, only e-mails to ntfy-$topic@ntfy.sh will be accepted. If this is not set, all emails to # $topic@ntfy.sh will be accepted (which may obviously be a spam problem). # # smtp-server-listen: # smtp-server-domain: # smtp-server-addr-prefix: # Web Push support (background notifications for browsers) # # If enabled, allows ntfy to receive push notifications, even when the ntfy web app is closed. When enabled, users # can enable background notifications in the web app. Once enabled, ntfy will forward published messages to the push # endpoint, which will then forward it to the browser. # # You must configure web-push-public/private key, web-push-file, and web-push-email-address below to enable Web Push. # Run "ntfy webpush keys" to generate the keys. # # - web-push-public-key is the generated VAPID public key, e.g. AA1234BBCCddvveekaabcdfqwertyuiopasdfghjklzxcvbnm1234567890 # - web-push-private-key is the generated VAPID private key, e.g. AA2BB1234567890abcdefzxcvbnm1234567890 # - web-push-file is a database file to keep track of browser subscription endpoints, e.g. `/var/cache/ntfy/webpush.db` # - web-push-email-address is the admin email address send to the push provider, e.g. `sysadmin@example.com` # - web-push-startup-queries is an optional list of queries to run on startup` # # web-push-public-key: # web-push-private-key: # web-push-file: # web-push-email-address: # web-push-startup-queries: # If enabled, ntfy can perform voice calls via Twilio via the "X-Call" header. # # - twilio-account is the Twilio account SID, e.g. AC12345beefbeef67890beefbeef122586 # - twilio-auth-token is the Twilio auth token, e.g. affebeef258625862586258625862586 # - twilio-phone-number is the outgoing phone number you purchased, e.g. +18775132586 # - twilio-verify-service is the Twilio Verify service SID, e.g. VA12345beefbeef67890beefbeef122586 # # twilio-account: # twilio-auth-token: # twilio-phone-number: # twilio-verify-service: # 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. # # keepalive-interval: "45s" # Interval in which the manager prunes old messages, deletes topics # and prints the stats. # # manager-interval: "1m" # Defines topic names that are not allowed, because they are otherwise used. There are a few default topics # that cannot be used (e.g. app, account, settings, ...). To extend the default list, define them here. # # Example: # disallowed-topics: # - about # - pricing # - contact # # disallowed-topics: # Defines the root path of the web app, or disables the web app entirely. # # Can be any simple path, e.g. "/", "/app", or "/ntfy". For backwards-compatibility reasons, # the values "app" (maps to "/"), "home" (maps to "/app"), or "disable" (maps to "") to disable # the web app entirely. # #web-root: "/" web-root: disable # Various feature flags used to control the web app, and API access, mainly around user and # account management. # # - enable-signup allows users to sign up via the web app, or API # - enable-login allows users to log in via the web app, or API # - enable-reservations allows users to reserve topics (if their tier allows it) # enable-signup: false enable-login: false # enable-reservations: false # Server URL of a Firebase/APNS-connected ntfy server (likely "https://ntfy.sh"). # # iOS users: # If you use the iOS ntfy app, you MUST configure this to receive timely notifications. You'll like want this: # upstream-base-url: "https://ntfy.sh" # # If set, all incoming messages will publish a "poll_request" message to the configured upstream server, containing # the message ID of the original message, instructing the iOS app to poll this server for the actual message contents. # This is to prevent the upstream server and Firebase/APNS from being able to read the message. # # - upstream-base-url is the base URL of the upstream server. Should be "https://ntfy.sh". # - upstream-access-token is the token used to authenticate with the upstream server. This is only required # if you exceed the upstream rate limits, or the uptream server requires authentication. # # upstream-base-url: # upstream-access-token: # Rate limiting: Total number of topics before the server rejects new topics. # # global-topic-limit: 15000 # Rate limiting: Number of subscriptions per visitor (IP address) # # visitor-subscription-limit: 30 # Rate limiting: Allowed GET/PUT/POST requests per second, per visitor: # - visitor-request-limit-burst is the initial bucket of requests each visitor has # - visitor-request-limit-replenish is the rate at which the bucket is refilled # - visitor-request-limit-exempt-hosts is a comma-separated list of hostnames, IPs or CIDRs to be # exempt from request rate limiting. Hostnames are resolved at the time the server is started. # Example: "1.2.3.4,ntfy.example.com,8.7.6.0/24" # visitor-request-limit-burst: 60 visitor-request-limit-replenish: "5s" # visitor-request-limit-exempt-hosts: "" # Rate limiting: Hard daily limit of messages per visitor and day. The limit is reset # every day at midnight UTC. If the limit is not set (or set to zero), the request # limit (see above) governs the upper limit. # visitor-message-daily-limit: 1000 # Rate limiting: Allowed emails per visitor: # - visitor-email-limit-burst is the initial bucket of emails each visitor has # - visitor-email-limit-replenish is the rate at which the bucket is refilled # # visitor-email-limit-burst: 16 # visitor-email-limit-replenish: "1h" # Rate limiting: Attachment size and bandwidth limits per visitor: # - visitor-attachment-total-size-limit is the total storage limit used for attachments per visitor # - visitor-attachment-daily-bandwidth-limit is the total daily attachment download/upload traffic limit per visitor # # visitor-attachment-total-size-limit: "100M" # visitor-attachment-daily-bandwidth-limit: "500M" # Rate limiting: Enable subscriber-based rate limiting (mostly used for UnifiedPush) # # If enabled, subscribers may opt to have published messages counted against their own rate limits, as opposed # to the publisher's rate limits. This is especially useful to increase the amount of messages that high-volume # publishers (e.g. Matrix/Mastodon servers) are allowed to send. # # Once enabled, a client may send a "Rate-Topics: <topic1>,<topic2>,..." header when subscribing to topics via # HTTP stream, or websockets, thereby registering itself as the "rate visitor", i.e. the visitor whose rate limits # to use when publishing on this topic. Note: Setting the rate visitor requires READ-WRITE permission on the topic. # # UnifiedPush only: If this setting is enabled, publishing to UnifiedPush topics will lead to a HTTP 507 response if # no "rate visitor" has been previously registered. This is to avoid burning the publisher's "visitor-message-daily-limit". # # visitor-subscriber-rate-limiting: false # Payments integration via Stripe # # - stripe-secret-key is the key used for the Stripe API communication. Setting this values # enables payments in the ntfy web app (e.g. Upgrade dialog). See https://dashboard.stripe.com/apikeys. # - stripe-webhook-key is the key required to validate the authenticity of incoming webhooks from Stripe. # Webhooks are essential up keep the local database in sync with the payment provider. See https://dashboard.stripe.com/webhooks. # - billing-contact is an email address or website displayed in the "Upgrade tier" dialog to let people reach # out with billing questions. If unset, nothing will be displayed. # # stripe-secret-key: # stripe-webhook-key: # billing-contact: # Metrics # # ntfy can expose Prometheus-style metrics via a /metrics endpoint, or on a dedicated listen IP/port. # Metrics may be considered sensitive information, so before you enable them, be sure you know what you are # doing, and/or secure access to the endpoint in your reverse proxy. # # - enable-metrics enables the /metrics endpoint for the default ntfy server (i.e. HTTP, HTTPS and/or Unix socket) # - metrics-listen-http exposes the metrics endpoint via a dedicated [IP]:port. If set, this option implicitly # enables metrics as well, e.g. "10.0.1.1:9090" or ":9090" # # enable-metrics: false # metrics-listen-http: # Profiling # # ntfy can expose Go's net/http/pprof endpoints to support profiling of the ntfy server. If enabled, ntfy will listen # on a dedicated listen IP/port, which can be accessed via the web browser on http://<ip>:<port>/debug/pprof/. # This can be helpful to expose bottlenecks, and visualize call flows. See https://pkg.go.dev/net/http/pprof for details. # # profile-listen-http: # Logging options # # By default, ntfy logs to the console (stderr), with an "info" log level, and in a human-readable text format. # ntfy supports five different log levels, can also write to a file, log as JSON, and even supports granular # log level overrides for easier debugging. Some options (log-level and log-level-overrides) can be hot reloaded # by calling "kill -HUP $pid" or "systemctl reload ntfy". # # - log-format defines the output format, can be "text" (default) or "json" # - log-file is a filename to write logs to. If this is not set, ntfy logs to stderr. # - log-level defines the default log level, can be one of "trace", "debug", "info" (default), "warn" or "error". # Be aware that "debug" (and particularly "trace") can be VERY CHATTY. Only turn them on briefly for debugging purposes. # - log-level-overrides lets you override the log level if certain fields match. This is incredibly powerful # for debugging certain parts of the system (e.g. only the account management, or only a certain visitor). # This is an array of strings in the format: # - "field=value -> level" to match a value exactly, e.g. "tag=manager -> trace" # - "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 <filename>. # # Example (good for production): # log-level: info # log-format: json # log-file: /var/log/ntfy.log # # Example level overrides (for debugging, only use temporarily): # log-level-overrides: # - "tag=manager -> trace" # - "visitor_ip=1.2.3.4 -> debug" # - "time_taken_ms -> debug" # # log-level: info # log-level-overrides: # log-format: text # log-file: ```
Author
Owner

@caronc commented on GitHub (Mar 10, 2024):

My request is to support basic auth at a global level. This allows users who want to add their own security around their self hosted version of ntfy.sh to do so.

I'm just trying to park my instance behind a secure reverse proxy i manage. I want to store the basic auth credentials in the connection info just like other platforms allow.

I get that there are individual topics built in with an internal user list controlled through ntfy, but that restricts me from leveraging PAM or other amazing centralized solutions you get from keeping auth outside of ntfy and one layer back.

My request: please just support basic auth in the connection string. All requests should just include the header from that point forward (including files)

Authorization: Basic <base64>
<!-- gh-comment-id:1987229569 --> @caronc commented on GitHub (Mar 10, 2024): My request is to support `basic auth` at a global level. This allows users who want to add their own security around their self hosted version of ntfy.sh to do so. I'm just trying to park my instance behind a secure reverse proxy i manage. I want to store the basic auth credentials in the connection info just like other platforms allow. I get that there are individual topics built in with an internal user list controlled through ntfy, but that restricts me from leveraging PAM or other amazing centralized solutions you get from keeping auth outside of ntfy and one layer back. My request: please just support [basic auth](https://en.m.wikipedia.org/wiki/Basic_access_authentication) in the connection string. All requests should just include the header from that point forward (including files) ``` Authorization: Basic <base64> ```
Author
Owner

@gitterspec commented on GitHub (Apr 2, 2024):

I agree that auth should additionally be supported through the URL (i.e. https://user:pass@host). UnifiedPush apps create a random topic anonymously, so the current auth implementation can't be used, but auth through the URL would allow adding protection if desired.

<!-- gh-comment-id:2031080640 --> @gitterspec commented on GitHub (Apr 2, 2024): I agree that auth should additionally be supported through the URL (i.e. https://user:pass@host). UnifiedPush apps create a random topic anonymously, so the current auth implementation can't be used, but auth through the URL would allow adding protection if desired.
Author
Owner

@kkarhan commented on GitHub (Nov 20, 2024):

I agree with @caronc since things like basic, server-wide auth is desireable and supporting that even rudimentary is quite useful.

  • The backend could thus be transparent (espechally when done via a reverse proxy) so any kind of SSO / PAM could be leveraged without requiring ntfy to support them directly.
<!-- gh-comment-id:2489699675 --> @kkarhan commented on GitHub (Nov 20, 2024): I agree with @caronc since things like basic, server-wide auth is desireable and supporting that even rudimentary is quite useful. - The backend could thus be transparent (espechally when done via a reverse proxy) so any kind of SSO / PAM could be leveraged without requiring ntfy to support them directly.
Author
Owner

@kkarhan commented on GitHub (Nov 20, 2024):

This is espechally important since the App doesn't support proxy configurations so one can't simply use i.e. Orbot and do Cookie Auth on Tor...

<!-- gh-comment-id:2489701204 --> @kkarhan commented on GitHub (Nov 20, 2024): This is espechally important since the App [doesn't support proxy configurations](https://github.com/binwiederhier/ntfy/issues/1047) so one [can't simply use i.e. Orbot](https://github.com/binwiederhier/ntfy/issues/1047#issuecomment-2489695399) and do Cookie Auth on Tor...
Author
Owner

@binwiederhier commented on GitHub (Dec 29, 2025):

Custom HTTP headers will be supported in the 1.21.x release. See https://github.com/binwiederhier/ntfy-android/pull/146 for screenshots.

<!-- gh-comment-id:3697497978 --> @binwiederhier commented on GitHub (Dec 29, 2025): Custom HTTP headers will be supported in the 1.21.x release. See https://github.com/binwiederhier/ntfy-android/pull/146 for screenshots.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/ntfy#714
No description provided.