chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.33.1 #22

Open
renovate-bot wants to merge 1 commit from renovate/docker.io-binwiederhier-ntfy-2.x into main
Member

This PR contains the following updates:

Package Update Change
docker.io/binwiederhier/ntfy (source) minor v2.17.0 → v2.33.1

Release Notes

binwiederhier/ntfy (docker.io/binwiederhier/ntfy)

v2.33.1

Compare Source

This release builds ntfy with Go 1.27.3 (security fixes, including rejecting the compromised eMudhra intermediate CAs), and adds monitoring for the experimental cluster: each node's view of its peers, per-peer and database connection pool metrics.

The v2.33.0 release had an issue that made it crash on older CPU architectures. The v2.33.1 release fixes that (see #​2092).

Features:

  • Show each cluster node's view of its peers with ntfy cluster status, /v1/cluster/status on the cluster listener, and per-peer metrics, so a link that only works in one direction is visible (experimental clustering, see cluster status)
  • Export PostgreSQL connection pool metrics (ntfy_db_pool_*: connections in use, and queries that waited for a free connection, per pool), to size pool_max_conns (see PostgreSQL)

Security:

  • Build with Go 1.27.3, which includes the security fixes of Go 1.27.2 (crypto/tls, net/http, html/template and others) and 1.27.3 (crypto/x509: certificate chains through the compromised eMudhra intermediate CAs are rejected)
  • Reject phone number verification unless Twilio confirms the code as approved, instead of accepting any successful response
  • Ignore duplicate topics in a subscription and limit a subscription to 150 topics, so a single request cannot replay the same topic's cache over and over

Bug fixes + maintenance:

  • Count published messages from every cluster node: each node adds its own publishes to the stored total instead of the leader overwriting it with its own count (experimental clustering)
  • Fix "Illegal instruction" crash of the amd64 binaries on CPUs without x86-64-v3 (AVX2/BMI2), by building releases on Ubuntu 24.04 again (#​2092, thanks to @​frank-bg for reporting)

v2.33.0

Compare Source

v2.32.0

Compare Source

This release prepares ntfy.sh for a passive cluster node: jobs that write to the shared database run only on the cluster leader, and each database store now records the oldest schema version it works with. Streaming subscriptions also tell proxies not to buffer them.

Features:

  • Set the Incremental: ?1 header (RFC 10036) on streaming subscriptions, so proxies that support it forward messages without buffering (#​2056, thanks to @​bt90 for the suggestion)

Bug fixes + maintenance:

  • Fix template files (?tpl=<name>) ignoring the priority sent with the request when the file has no priority key (#​2045, thanks to @​6801318d8d for reporting)
  • Return HTTP 409 instead of 500 when deleting or changing the password of a user provisioned via auth-users through the admin API (#​2062, thanks to @​daniloamiranda for reporting)
  • Run the shared-database housekeeping (pruning expired messages, attachments and tokens, web push expiry warnings, writing the published-messages total) on the cluster leader only, so a passive node no longer overwrites the total with its own count (experimental clustering)
  • Record the oldest schema version each database store still works with, so an older ntfy refuses to start on a database that a newer version migrated in a breaking way, instead of misreading it; none of today's migrations are breaking (#​2060)

v2.31.1

Compare Source

This release fixes the database load that made us roll back ntfy.sh from v2.31.0: reconnecting with since=<message ID> read every message of the topic from the database. A new index makes these reconnects cheap, cheaper than in v2.30.0. It also lets ntfy start with a warning on a newer database schema, so later rollbacks need no manual step.

Bug fixes + maintenance:

  • Fix reconnects with since=<message ID> reading every message of the topic from the database, which overloaded ntfy.sh's database right after the v2.31.0 upgrade; the message cache gets a new index: (topic, published, id) on PostgreSQL, (topic, published, time) on SQLite (#​2058)
  • Start with a warning instead of failing when the database schema is newer than this version of ntfy supports, so a rollback or a rolling cluster upgrade needs no manual schema change (#​2059)
  • Web app: Fix the wrong topic opening when subscribed to the same topic on two different servers (#​858)
  • Web app: Fix the "Upgrade to ntfy Pro" banner covering the bottom of a long topic list (#​1007)
  • Web app: The "Notifications are disabled" and "Notifications are blocked" warnings can now be closed (#​1220)
  • Web app: Fix a crash when opening the subscribe dialog before the topic list has loaded, e.g. while another tab holds the browser database (#​2014, #​1881)

Upgrade notes:

  • This release changes the message database schema (version 16 to 17: an index for since=<message ID> reconnects). Downgrading to v2.31.0 or earlier afterwards requires setting the version back by hand first: UPDATE schema_version SET version = 16 WHERE store = 'message' on PostgreSQL, or UPDATE schemaVersion SET version = 16 WHERE id = 1 in the SQLite cache-file. From this release on, a newer schema only logs a warning (#​2059)

v2.31.0

Compare Source

This release fixes messages that could be lost when a client reconnects, e.g. a phone switching networks, right when messages are published: every server now reads newly written messages from its message cache once a second and sends them to the subscribers that missed them. In load tests with server restarts and crashes, this brought lost messages down from 465 to 2 out of about 615,000. It also adds a /v1/ready endpoint for load balancers, and continues the experimental clustering work with node roles.

Features:

  • Add /v1/ready for load balancers, and the node's role to /v1/health; with clustering, a node with no other active node leads right away instead of after a one-minute hold-off (#​2050)
  • Experimental clustering: add experimental-cluster-role to run a passive node that never leads and never takes over another node's subscribers, e.g. one that is not behind the load balancer (#​2049)

Bug fixes + maintenance:

  • Fix messages lost when a client reconnects before they are written to the message cache, or when a cluster node's fan-out is lost: every node now reads newly written messages once a second and sends them to the subscribers that missed them (#​2040)
  • Write user stats (messages, emails, calls) as increments, so servers sharing one database add up instead of overwriting each other's counts (#​1989)
  • Don't add a visitor's anonymous usage to an account's stats when the account takes over that visitor, e.g. right after upgrading (#​2041)

Upgrade notes:

  • A reconnect with since=<message ID> now also returns the messages published in the same second as that message, so none are skipped when several servers write out of order. The ntfy apps and web app drop these by ID; your own scripts may see a few duplicates (#​2040)
  • Experimental clustering only: this release changes the cluster's node registry schema (version 1 to 2). Downgrading a clustered server to v2.30.0 afterwards requires setting the version back by hand first: UPDATE schema_version SET version = 1 WHERE store = 'node_registry' (#​2049)

v2.30.0

Compare Source

This release links attachments in email notifications, adds SMTP LOGIN auth (e.g. for OVH and Outlook), and fixes the PostgreSQL memory growth that came with v2.29.0. It also ships the first experimental version of clustering: several ntfy servers sharing one PostgreSQL database. Clustering is not ready for production yet.

Features:

  • Link attachments in email notifications, including the file name and when the link expires (#​672, thanks to @​merspieler for suggesting)
  • Support SMTP servers that only offer LOGIN auth (e.g. OVH, Outlook) for sending emails (#​930/#​1530, thanks to @​wunter8 for reporting and @​santanoce for the initial implementation)
  • Experimental: run several ntfy servers as one cluster that shares a PostgreSQL database, enabled with experimental-cluster-listen; this is not ready for production yet (#​2005, #​2008, #​2012, #​2013)

Bug fixes + maintenance:

  • Fix Dockerfile-build failing to build: use Go 1.26 and add the cluster package (#​1962, thanks to @​ElectricTea for reporting)
  • Set the org.opencontainers.image.version label on release Docker images (#​1921/#​1936, thanks to @​Plazzmex for reporting and @​w1977-0 for the fix)
  • Warn at startup if attachment-expiry-duration is longer than cache-duration, since attachments never outlive their message (#​1053, thanks to @​ctschach for reporting)
  • Fix PostgreSQL memory growth after v2.29.0: write message batches with one fixed INSERT for any batch size (#​2011)
  • CLI: fix ntfy publish failing with "invalid header field value" when sending a multi-line message or title along with a file (#​1808, thanks to @​quantenzitrone for reporting)
  • Web app: fix an updated message showing next to its old version when the update arrived via the background poll instead of live (#​2010)

Documentation:

  • Document recommended PostgreSQL pool settings for busy servers (#​2011)

v2.29.0

Compare Source

This release fixes cache writes under load. On ntfy.sh, hourly cron bursts overwhelmed the batch writer: messages took up to 40s to reach the database (so poll=1 and since= missed them) and publishes stalled. Batches are now written in one statement, publishes no longer wait on the writer, and PostgreSQL connections stay idle instead of reconnecting.

Features:

  • Timezone support for delayed notifications via X-Timezone header, timezone query param or JSON field; the web app sends the browser's timezone (#​1967/#​1924, thanks @​beemines)
  • RFC 3339 timestamps for delayed notifications, e.g. At: 2026-12-10T11:00:00-05:00 (#​1931, thanks @​ALPHACOM-Brehmer)

Bug fixes + maintenance:

  • Fix delayed message visibility and stalled publishes under bursts: multi-row INSERT per batch, non-blocking publishes (100-batch buffer), and no scheduled-message lookup unless a sequence ID is set (#​2006)
  • Fix a panic in the account token-update endpoint caused by a concurrent anonymous request racing on the shared visitor; now returns HTTP 401
  • Fix messages lost on shutdown: the write queue is flushed and ntfy serve handles SIGTERM/SIGINT gracefully
  • pool_max_idle_conns now defaults to pool_max_conns, so PostgreSQL connections are reused instead of re-opened
  • Fix since=<message-id> replaying a topic's full history when the ID wasn't on the read replica yet; it's now resolved on the primary
  • Use the PostgreSQL row estimate for messages_cached instead of a COUNT(*) every minute
  • Detect Markdown when Content-Type has parameters or is uppercase (#​1995, thanks @​cipherprofessor)
  • Fix the Alertmanager template's bogus 0001-01-01 end time and merged start/end lines (#​1946/#​1940, thanks @​justadityaraj and @​deferred)
  • Embed the time zone database (time/tzdata) so named time zones work on ARM Docker images and minimal runtimes
  • Build with Go 1.27; minimum Go version to build is now 1.26
  • Groundwork for clustering (node registry, util primitives, reserved config options); not usable yet (#​1991, #​1997, #​2001, #​2003)

v2.28.0

Compare Source

This is a hardening release. A single topic on ntfy.sh was polled continuously with poll=1 and no since cursor, which replays a topic's entire cache on every request. The changes below bound what one replay can cost, close two fields that had no size limit at all, and fix an ordering bug found while digging into it.

Bug fixes + maintenance:

  • Fix messages being returned out of publish order when polling or replaying several topics at once (/topic1,topic2/json?poll=1, #​1297)
  • Limit the message title to 1 KB and all tags combined to 512 bytes, rejecting larger requests with HTTP 400 (error codes 40057 and 40058). Neither field had a size limit before, unlike the message body; on ntfy.sh the 99.9th percentile is 212 bytes for titles and 244 for tags
  • Cap a single cache replay at 10 MB of messages per topic. A poll without a since cursor returns a topic's entire cache, which was previously unbounded and could reach tens of megabytes on a busy topic, so one request could allocate that much on the server. The newest messages that fit are kept and a truncated response carries an X-Messages-Truncated: 1 header
  • visitor-attachment-daily-bandwidth-limit now also covers messages replayed from the message cache by poll requests, not just attachment traffic. A poll without a since cursor returns a topic's entire cache, so a topic that is cheap to fill can be re-read for many times its own size; polls beyond the budget are rejected with HTTP 429 (error code 42905) before anything is written. Note that heavy pollers now consume the same budget as attachment downloads, so operators serving both may want to raise the limit

v2.27.0

Compare Source

This release lets you sign in with your verified email address instead of your username, which should help if you ever signed up with an email and then forgot which username you picked. It also hardens the message templating engine against a few ways a small template could eat a lot of memory, and it drops the "experimental" label from PostgreSQL support, which has been running ntfy.sh for a while now.

I also did a bunch of refactoring in, mostly in preparation for being able to cluster ntfy nodes and scale the service horizontally. It'll be a while until then, ... baby steps.

Security:

  • Limit message templates (Template: yes) to 32 KB, limit printf widths and precisions to below 1000, and limit indent/nindent to 100 spaces, preventing excessive memory use from a single small template
  • Exclude secrets from the config hash served to the web app, preventing a rather theoretical information leak

Features:

  • Allow logging in with your verified primary email address (in addition to your username), so a password reset no longer leaves you unable to sign in when you only remember the email you signed up with

Bug fixes + maintenance:

  • Fix Twilio phone calls and phone number verifications failing silently when Twilio rejected the request, and move the Twilio integration into its own twilio package
  • Move the Prometheus metrics into a dedicated metrics package
  • Message cache databases from ntfy older than v1.10.0 (November 2021) can no longer be migrated; upgrade via an older ntfy version first, or delete the cache database
  • Fix user_phone table in the SQLite user database referencing a dropped table after the v2.14 schema migration; repaired automatically by a new migration

v2.26.3

Compare Source

This is a hotfix release, useful pretty much only for ntfy.sh. It was adds the ability to track abusive IPs mor efficiently, reducing the load on the IP banning services and preventing them from falling behind and leaving abusers unbanned for too long. It works by tracking HTTP errors, and writing out a ban file that fail2ban can read and ban offenders instantly. See ban-feed for details.

Features:

  • Add an abuse ban-feed: when enabled via ban-file, ntfy tracks a weighted strike budget per visitor and appends abusive IPs to a file that fail2ban can tail and ban on sight (ban-file, ban-window, ban-threshold, ban-weights; see ban-feed)

v2.26.0

Compare Source

This release hardens message templates, which are now executed with a hard-capped execution timeout. This closes
a denial-of-service hole.

On the web app side, it adds configurable date and time formats, a smoother loading and page-transition experience,
and a fix that strips unsafe URL protocols from rendered Markdown.

Security:

  • Prevent a CPU denial of service via message templates (Template: yes), #​1826, thanks to @​alanturing881 for reporting)

Features:

  • Web app: Add "Date format" and "Time format" settings (Settings -> Appearance), with ISO 8601, day/month/year (slash or dot) and month/day/year date options and a 12-/24-hour clock option, and base the default format on your browser/system locale rather than the selected display language. When logged in, both settings sync across devices via your account (#​1647, thanks to @​wsw70 for reporting)

Bug fixes + maintenance:

  • Web app: Smooth transitions and loading animation, remove flickering
  • Web app: GET /account now reads from the primary database instead of a read replica, so the account view no longer shows stale data right after a change when replicas lag behind
  • Docs: Document the third-party HelmForge Helm chart as a Kubernetes installation option (#​1727, thanks to @​mberlofa)
  • Web app: Strip unsafe URL protocols (javascript:, data:, ...) from links and images in Markdown-rendered messages, so they no longer trigger an uncaught "React has blocked a javascript: URL" error (thanks to @​jvoisin for reporting)

v2.25.0

Compare Source

This release adds password reset via email, and reworks email verification to use durable, link-based magic links (replacing the old in-memory 6-digit codes). Email stays optional at signup; a user can reset their password only once they have a verified "primary" (recovery)email.

All of this work is probably not useful for self-hosters, but it hopefully will be useful for me, since I do have to reset accounts on a regular basis.

Security issues:

  • Generate access tokens, IDs, and magic-link tokens with a cryptographically secure RNG (crypto/rand) instead of a clock-seeded PRNG

Features:

  • Add password reset via emailed magic link, with a "Forgot password" link on the login page and a ntfy user reset-pass CLI command for admins
  • Rework email verification to use durable, single-use, expiring magic links instead of in-memory 6-digit codes, and add a "primary" email (used for account recovery and as the X-Email: yes target) with verified/unverified state in the account UI
  • You can now clear/read messages and delete messages with a GET request (#​1771, thanks to @​lemmi for reporting and to @​wunter8 for implementing)
  • Add a reload button to the web app's action bar when running as an installed PWA, which clears the service worker caches and hard-refreshes the app
  • Add a "Back to app" link to the web app's login, signup, and password-reset pages (alongside the existing links), which previously had no way back to the app

Bug fixes + maintenance:

  • X-Email: yes (also true/1) now sends to your primary verified email regardless of the smtp-sender-verify setting (previously it was rejected unless verification was enabled); it requires being logged in with a verified address
  • Grant users full access to their own sync topic (st_...) so cross-device subscription sync works under auth-default-access: deny-all (#​733, #​1795, thanks to @​lmorchard for the contribution)
  • Support HTTP (non-TLS) S3-compatible endpoints by preserving the endpoint scheme, e.g. for a local MinIO instance (#​1794, #​1734, thanks to @​sskender for the contribution, and @​Kernald for reporting)
  • Stop silently stripping spaces from passwords while typing in the web app's login, signup, and password-reset forms (#​1246, thanks to @​aldem for reporting)
  • Update web app dependencies, including major-version upgrades to Vite (6 -> 8, now Rolldown-based), Material UI (5 -> 9), and Dexie (3 -> 4) (#​1800, #​1764, #​1767, #​1762, #​1766, #​1765, thanks Dependabot)
  • Play notification sounds in the web app even when the Notification API is unavailable, e.g. over plain HTTP or in browsers without notification support (#​1772, thanks to @​mitya12342 for the contribution)
  • Stop escaping <, >, and & as \u003c/\u003e/\u0026 in JSON responses (#​1511, #​1512, thanks to @​wunter8 for the contribution)
  • Fix the web app navbar not reflecting a topic reservation (lock icon, and "Reserve topic" -> "Change reservation"/"Remove reservation" menu) until a page reload, by persisting reservation and display-name changes onto already-subscribed topics during account sync
  • Reduce the web app's initial bundle size by ~300 KB (~50 KB gzipped) by lazy-loading the emoji picker dataset and the Markdown renderer, and by importing Material UI icons individually

v2.24.0

Compare Source

The main feature for this release is an in-memory ACL cache (auth-access-cache) that can help bring down the read load on the production database. The topic authorization queries are consistently the highest ranking queries on the database, so this will help quite a bit. The current database load is quite low, but I'm expecting it to increase as more users join and use ntfy.

Security issues:

  • Fix case-insensitive ACL topic matching on SQLite: an access control rule for secret no longer also matches a request for SECRET. SQLite's LIKE is case-insensitive for ASCII by default. PostgreSQL was unaffected. It's honestly incredible that this issue remained undetected for so long, especially while ntfy.sh was running on SQLite (it now runs on PostgreSQL).

Features:

  • Add opt-in in-memory ACL cache (auth-access-cache) that serves topic authorization without a database round-trip; off by default, intended for high-volume servers
  • Add ntfy --version flag to the CLI (#​1722, #​1748, thanks to @​sskender for the contribution, and @​Saucy9607 for reporting)

Bug fixes + maintenance:

v2.23.0

Compare Source

Features:

  • Add per-visitor rate limit on new topic creations (visitor-topic-creation-limit-burst / visitor-topic-creation-limit-replenish, defaults 100 burst / 1m replenish) to mitigate topic-enumeration / squatting attacks that inflate the in-memory topic map

Bug fixes + maintenance:

  • Remove stacktrace-js, stacktrace-gps, humanize-duration, and js-base64 from the web app to reduce dependency and security footprint
  • Restrict the publish dialog's local file preview to safe image types (png/jpg/gif/webp) to prevent same-origin script execution from blob URLs when previewing a crafted SVG (GHSA-j8hr-p342-xrmh, thanks to @​Venukamatchi for reporting)

v2.22.0

Compare Source

Bug fixes + maintenance:

v2.21.0

Compare Source

This release adds the ability to verify email addresses using the smtp-sender-verify flag. This is a change that is required because ntfy.sh was used to send unsolicited emails and the AWS SES account was suspended. Going forward, ntfy.sh won't be able to send emails unless the email address was verified ahead of time.

Features:

  • Add verified email recipients feature with smtp-sender-verify config flag, allowing server admins to require email
    address verification before sending email notifications (#​1681)

v2.20.1

Compare Source

This is a small bugfix release that only affects high volume S3 backends that struggle with HTTP/2.

Bug fixes + maintenance:

  • Attachments: Add disable_http2=true S3 URL option to work around HTTP/2 stream errors with DigitalOcean Spaces and other S3-compatible providers (#​1678/#​1679)

v2.20.0

Compare Source

This release is another step towards making it possible to help scale ntfy up and out 🔥! With this release, you can store attachments in an S3-compatible object store as an alterative to the directory. See attachment store for details.

⚠️ Important note: With this release, ntfy will take full control over the attachment directory or S3 bucket. Files/objects in the configured attachment-cache-dir that match the message ID format (12 chars, matching ^[A-Za-z0-9]{12}$), and have no entries in the message database will be deleted. Do not use a directory or S3 bucket as attachment-cache-dir that is also used for something else.

This is a small behavioral change that was necessary because the old logic often left attachments behind and would not clean them up. Unless you have re-used the attachment directory for anything else (which is hopefully never done), this should not affect you at all.

Features:

Bug fixes + maintenance:

  • Reject invalid e-mail addresses (e.g. multiple comma-separated recipients) with HTTP 400
  • Add OpenRC init service file (#​1650, thanks to @​ageru for the contribution)

v2.19.2

Compare Source

This is another small bugfix release for PostgreSQL, avoiding races between primary and read replica, as well as to further reduce primary load.

Bug fixes + maintenance:

  • Fix race condition in web push subscription causing FK constraint violation when concurrent requests hit the same endpoint
  • Route authorization query to read-only database replica to reduce primary database load

v2.19.1

Compare Source

This is a bugfix release to avoid PostgreSQL insert failures due to invalid UTF-8 messages. It also fixes database-url validation incorrectly rejecting postgresql:// connection strings.

Bug fixes + maintenance:

  • Fix invalid UTF-8 in HTTP headers (e.g. Latin-1 encoded text) causing PostgreSQL insert failures and dropping entire message batches
  • Fix database-url validation rejecting postgresql:// connection strings (#​1657/#​1658)

v2.19.0

Compare Source

This is a fast-follow release that enables Postgres read replica support.

To offload read-heavy queries from the primary database, you can optionally configure one or more read replicas using the database-replica-urls option. When configured, non-critical read-only queries (e.g. fetching messages, checking access permissions, etc) are distributed across the replicas using round-robin, while all writes and correctness-critical reads continue to go to the primary. If a replica becomes unhealthy, ntfy automatically falls back to the primary until the replica recovers.

Features:

Bug fixes + maintenance:

  • Web: Throttle notification sound in web app to play at most once every 2 seconds (similar to #​1550, thanks to @​jlaffaye for reporting)
  • Web: Add hover tooltips to icon buttons in web app account and preferences pages (#​1565, thanks to @​jermanuts for reporting)

v2.18.0

Compare Source

This is the biggest release I've ever done on the server. It's 14,997 added lines of code, and 10,202 lines removed, all from one pull request that adds PostgreSQL support.

The code was written by Cursor and Claude, but reviewed and heavily tested over 2-3 weeks by me. I created comparison documents, went through all queries multiple times and reviewed the logic over and over again. I also did load tests and manual regression tests, which took lots of evenings.

ntfy.sh was successfully upgraded to 2.18.0 (though not with Postgres backend yet, as per the rollout plan).

I'm kindly asking the community to test the Postgres support and report back to me if things are working (or not working). There is a one-off migration tool (entirely written by AI) that you can use to migrate.

Features:

Bug fixes + maintenance:


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate.

This PR contains the following updates: | Package | Update | Change | |---|---|---| | [docker.io/binwiederhier/ntfy](https://ntfy.sh/) ([source](https://github.com/binwiederhier/ntfy)) | minor | `v2.17.0` → `v2.33.1` | --- ### Release Notes <details> <summary>binwiederhier/ntfy (docker.io/binwiederhier/ntfy)</summary> ### [`v2.33.1`](https://github.com/binwiederhier/ntfy/releases/tag/v2.33.1) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.33.0...v2.33.1) This release builds ntfy with Go 1.27.3 (security fixes, including rejecting the compromised eMudhra intermediate CAs), and adds monitoring for the experimental cluster: each node's view of its peers, per-peer and database connection pool metrics. *The v2.33.0 release had an issue that made it crash on older CPU architectures. The v2.33.1 release fixes that (see [#&#8203;2092](https://github.com/binwiederhier/ntfy/issues/2092)).* **Features:** - Show each cluster node's view of its peers with `ntfy cluster status`, `/v1/cluster/status` on the cluster listener, and per-peer metrics, so a link that only works in one direction is visible (experimental clustering, see [cluster status](https://docs.ntfy.sh/config/#cluster-status)) - Export PostgreSQL connection pool metrics (`ntfy_db_pool_*`: connections in use, and queries that waited for a free connection, per pool), to size `pool_max_conns` (see [PostgreSQL](https://docs.ntfy.sh/config/#postgresql)) **Security:** - Build with Go 1.27.3, which includes the security fixes of Go 1.27.2 (`crypto/tls`, `net/http`, `html/template` and others) and 1.27.3 (`crypto/x509`: certificate chains through the compromised eMudhra intermediate CAs are rejected) - Reject phone number verification unless Twilio confirms the code as approved, instead of accepting any successful response - Ignore duplicate topics in a subscription and limit a subscription to 150 topics, so a single request cannot replay the same topic's cache over and over **Bug fixes + maintenance:** - Count published messages from every cluster node: each node adds its own publishes to the stored total instead of the leader overwriting it with its own count (experimental clustering) - Fix "Illegal instruction" crash of the amd64 binaries on CPUs without x86-64-v3 (AVX2/BMI2), by building releases on Ubuntu 24.04 again ([#&#8203;2092](https://github.com/binwiederhier/ntfy/issues/2092), thanks to [@&#8203;frank-bg](https://github.com/frank-bg) for reporting) ### [`v2.33.0`](https://github.com/binwiederhier/ntfy/compare/v2.32.0...v2.33.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.32.0...v2.33.0) ### [`v2.32.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.32.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.31.1...v2.32.0) This release prepares ntfy.sh for a passive cluster node: jobs that write to the shared database run only on the cluster leader, and each database store now records the oldest schema version it works with. Streaming subscriptions also tell proxies not to buffer them. **Features:** - Set the `Incremental: ?1` header ([RFC 10036](https://www.rfc-editor.org/info/rfc10036/)) on streaming subscriptions, so proxies that support it forward messages without buffering ([#&#8203;2056](https://github.com/binwiederhier/ntfy/issues/2056), thanks to [@&#8203;bt90](https://github.com/bt90) for the suggestion) **Bug fixes + maintenance:** - Fix template files (`?tpl=<name>`) ignoring the priority sent with the request when the file has no `priority` key ([#&#8203;2045](https://github.com/binwiederhier/ntfy/issues/2045), thanks to [@&#8203;6801318d8d](https://github.com/6801318d8d) for reporting) - Return HTTP 409 instead of 500 when deleting or changing the password of a user provisioned via `auth-users` through the admin API ([#&#8203;2062](https://github.com/binwiederhier/ntfy/issues/2062), thanks to [@&#8203;daniloamiranda](https://github.com/daniloamiranda) for reporting) - Run the shared-database housekeeping (pruning expired messages, attachments and tokens, web push expiry warnings, writing the published-messages total) on the cluster leader only, so a passive node no longer overwrites the total with its own count (experimental clustering) - Record the oldest schema version each database store still works with, so an older ntfy refuses to start on a database that a newer version migrated in a breaking way, instead of misreading it; none of today's migrations are breaking ([#&#8203;2060](https://github.com/binwiederhier/ntfy/pull/2060)) ### [`v2.31.1`](https://github.com/binwiederhier/ntfy/releases/tag/v2.31.1) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.31.0...v2.31.1) This release fixes the database load that made us roll back ntfy.sh from v2.31.0: reconnecting with `since=<message ID>` read every message of the topic from the database. A new index makes these reconnects cheap, cheaper than in v2.30.0. It also lets ntfy start with a warning on a newer database schema, so later rollbacks need no manual step. **Bug fixes + maintenance:** - Fix reconnects with `since=<message ID>` reading every message of the topic from the database, which overloaded ntfy.sh's database right after the v2.31.0 upgrade; the message cache gets a new index: (topic, published, id) on PostgreSQL, (topic, published, time) on SQLite ([#&#8203;2058](https://github.com/binwiederhier/ntfy/pull/2058)) - Start with a warning instead of failing when the database schema is newer than this version of ntfy supports, so a rollback or a rolling cluster upgrade needs no manual schema change ([#&#8203;2059](https://github.com/binwiederhier/ntfy/pull/2059)) - Web app: Fix the wrong topic opening when subscribed to the same topic on two different servers ([#&#8203;858](https://github.com/binwiederhier/ntfy/issues/858)) - Web app: Fix the "Upgrade to ntfy Pro" banner covering the bottom of a long topic list ([#&#8203;1007](https://github.com/binwiederhier/ntfy/issues/1007)) - Web app: The "Notifications are disabled" and "Notifications are blocked" warnings can now be closed ([#&#8203;1220](https://github.com/binwiederhier/ntfy/issues/1220)) - Web app: Fix a crash when opening the subscribe dialog before the topic list has loaded, e.g. while another tab holds the browser database ([#&#8203;2014](https://github.com/binwiederhier/ntfy/issues/2014), [#&#8203;1881](https://github.com/binwiederhier/ntfy/issues/1881)) **Upgrade notes:** - This release changes the message database schema (version 16 to 17: an index for `since=<message ID>` reconnects). Downgrading to v2.31.0 or earlier afterwards requires setting the version back by hand first: `UPDATE schema_version SET version = 16 WHERE store = 'message'` on PostgreSQL, or `UPDATE schemaVersion SET version = 16 WHERE id = 1` in the SQLite `cache-file`. From this release on, a newer schema only logs a warning ([#&#8203;2059](https://github.com/binwiederhier/ntfy/pull/2059)) ### [`v2.31.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.31.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.30.0...v2.31.0) This release fixes messages that could be lost when a client reconnects, e.g. a phone switching networks, right when messages are published: every server now reads newly written messages from its message cache once a second and sends them to the subscribers that missed them. In load tests with server restarts and crashes, this brought lost messages down from 465 to 2 out of about 615,000. It also adds a `/v1/ready` endpoint for load balancers, and continues the experimental clustering work with node roles. **Features:** - Add `/v1/ready` for load balancers, and the node's role to `/v1/health`; with clustering, a node with no other active node leads right away instead of after a one-minute hold-off ([#&#8203;2050](https://github.com/binwiederhier/ntfy/pull/2050)) - Experimental clustering: add `experimental-cluster-role` to run a `passive` node that never leads and never takes over another node's subscribers, e.g. one that is not behind the load balancer ([#&#8203;2049](https://github.com/binwiederhier/ntfy/pull/2049)) **Bug fixes + maintenance:** - Fix messages lost when a client reconnects before they are written to the message cache, or when a cluster node's fan-out is lost: every node now reads newly written messages once a second and sends them to the subscribers that missed them ([#&#8203;2040](https://github.com/binwiederhier/ntfy/pull/2040)) - Write user stats (messages, emails, calls) as increments, so servers sharing one database add up instead of overwriting each other's counts ([#&#8203;1989](https://github.com/binwiederhier/ntfy/pull/1989)) - Don't add a visitor's anonymous usage to an account's stats when the account takes over that visitor, e.g. right after upgrading ([#&#8203;2041](https://github.com/binwiederhier/ntfy/pull/2041)) **Upgrade notes:** - A reconnect with `since=<message ID>` now also returns the messages published in the same second as that message, so none are skipped when several servers write out of order. The ntfy apps and web app drop these by ID; your own scripts may see a few duplicates ([#&#8203;2040](https://github.com/binwiederhier/ntfy/pull/2040)) - Experimental clustering only: this release changes the cluster's node registry schema (version 1 to 2). Downgrading a clustered server to v2.30.0 afterwards requires setting the version back by hand first: `UPDATE schema_version SET version = 1 WHERE store = 'node_registry'` ([#&#8203;2049](https://github.com/binwiederhier/ntfy/pull/2049)) ### [`v2.30.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.30.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.29.0...v2.30.0) This release links attachments in email notifications, adds SMTP LOGIN auth (e.g. for OVH and Outlook), and fixes the PostgreSQL memory growth that came with v2.29.0. It also ships the first experimental version of clustering: several ntfy servers sharing one PostgreSQL database. Clustering is not ready for production yet. **Features:** - Link attachments in email notifications, including the file name and when the link expires ([#&#8203;672](https://github.com/binwiederhier/ntfy/issues/672), thanks to [@&#8203;merspieler](https://github.com/merspieler) for suggesting) - Support SMTP servers that only offer LOGIN auth (e.g. OVH, Outlook) for sending emails ([#&#8203;930](https://github.com/binwiederhier/ntfy/issues/930)/[#&#8203;1530](https://github.com/binwiederhier/ntfy/pull/1530), thanks to [@&#8203;wunter8](https://github.com/wunter8) for reporting and [@&#8203;santanoce](https://github.com/santanoce) for the initial implementation) - Experimental: run several ntfy servers as one cluster that shares a PostgreSQL database, enabled with `experimental-cluster-listen`; this is not ready for production yet ([#&#8203;2005](https://github.com/binwiederhier/ntfy/pull/2005), [#&#8203;2008](https://github.com/binwiederhier/ntfy/pull/2008), [#&#8203;2012](https://github.com/binwiederhier/ntfy/pull/2012), [#&#8203;2013](https://github.com/binwiederhier/ntfy/pull/2013)) **Bug fixes + maintenance:** - Fix `Dockerfile-build` failing to build: use Go 1.26 and add the `cluster` package ([#&#8203;1962](https://github.com/binwiederhier/ntfy/issues/1962), thanks to [@&#8203;ElectricTea](https://github.com/ElectricTea) for reporting) - Set the `org.opencontainers.image.version` label on release Docker images ([#&#8203;1921](https://github.com/binwiederhier/ntfy/issues/1921)/[#&#8203;1936](https://github.com/binwiederhier/ntfy/pull/1936), thanks to [@&#8203;Plazzmex](https://github.com/Plazzmex) for reporting and [@&#8203;w1977-0](https://github.com/w1977-0) for the fix) - Warn at startup if `attachment-expiry-duration` is longer than `cache-duration`, since attachments never outlive their message ([#&#8203;1053](https://github.com/binwiederhier/ntfy/issues/1053), thanks to [@&#8203;ctschach](https://github.com/ctschach) for reporting) - Fix PostgreSQL memory growth after v2.29.0: write message batches with one fixed `INSERT` for any batch size ([#&#8203;2011](https://github.com/binwiederhier/ntfy/pull/2011)) - CLI: fix `ntfy publish` failing with "invalid header field value" when sending a multi-line message or title along with a file ([#&#8203;1808](https://github.com/binwiederhier/ntfy/issues/1808), thanks to [@&#8203;quantenzitrone](https://github.com/quantenzitrone) for reporting) - Web app: fix an updated message showing next to its old version when the update arrived via the background poll instead of live ([#&#8203;2010](https://github.com/binwiederhier/ntfy/pull/2010)) **Documentation:** - Document recommended PostgreSQL pool settings for busy servers ([#&#8203;2011](https://github.com/binwiederhier/ntfy/pull/2011)) ### [`v2.29.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.29.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.28.0...v2.29.0) This release fixes cache writes under load. On ntfy.sh, hourly cron bursts overwhelmed the batch writer: messages took up to 40s to reach the database (so `poll=1` and `since=` missed them) and publishes stalled. Batches are now written in one statement, publishes no longer wait on the writer, and PostgreSQL connections stay idle instead of reconnecting. **Features:** - Timezone support for delayed notifications via `X-Timezone` header, `timezone` query param or JSON field; the web app sends the browser's timezone ([#&#8203;1967](https://github.com/binwiederhier/ntfy/pull/1967)/[#&#8203;1924](https://github.com/binwiederhier/ntfy/issues/1924), thanks [@&#8203;beemines](https://github.com/beemines)) - RFC 3339 timestamps for delayed notifications, e.g. `At: 2026-12-10T11:00:00-05:00` ([#&#8203;1931](https://github.com/binwiederhier/ntfy/pull/1931), thanks [@&#8203;ALPHACOM-Brehmer](https://github.com/ALPHACOM-Brehmer)) **Bug fixes + maintenance:** - Fix delayed message visibility and stalled publishes under bursts: multi-row `INSERT` per batch, non-blocking publishes (100-batch buffer), and no scheduled-message lookup unless a sequence ID is set ([#&#8203;2006](https://github.com/binwiederhier/ntfy/pull/2006)) - Fix a panic in the account token-update endpoint caused by a concurrent anonymous request racing on the shared visitor; now returns HTTP 401 - Fix messages lost on shutdown: the write queue is flushed and `ntfy serve` handles `SIGTERM`/`SIGINT` gracefully - `pool_max_idle_conns` now defaults to `pool_max_conns`, so PostgreSQL connections are reused instead of re-opened - Fix `since=<message-id>` replaying a topic's full history when the ID wasn't on the read replica yet; it's now resolved on the primary - Use the PostgreSQL row estimate for `messages_cached` instead of a `COUNT(*)` every minute - Detect Markdown when `Content-Type` has parameters or is uppercase ([#&#8203;1995](https://github.com/binwiederhier/ntfy/pull/1995), thanks [@&#8203;cipherprofessor](https://github.com/cipherprofessor)) - Fix the Alertmanager template's bogus `0001-01-01` end time and merged start/end lines ([#&#8203;1946](https://github.com/binwiederhier/ntfy/pull/1946)/[#&#8203;1940](https://github.com/binwiederhier/ntfy/issues/1940), thanks [@&#8203;justadityaraj](https://github.com/justadityaraj) and [@&#8203;deferred](https://github.com/deferred)) - Embed the time zone database (`time/tzdata`) so named time zones work on ARM Docker images and minimal runtimes - Build with Go 1.27; minimum Go version to build is now 1.26 - Groundwork for clustering (node registry, util primitives, reserved config options); not usable yet ([#&#8203;1991](https://github.com/binwiederhier/ntfy/pull/1991), [#&#8203;1997](https://github.com/binwiederhier/ntfy/pull/1997), [#&#8203;2001](https://github.com/binwiederhier/ntfy/pull/2001), [#&#8203;2003](https://github.com/binwiederhier/ntfy/pull/2003)) ### [`v2.28.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.28.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.27.0...v2.28.0) This is a hardening release. A single topic on ntfy.sh was polled continuously with `poll=1` and no `since` cursor, which replays a topic's entire cache on every request. The changes below bound what one replay can cost, close two fields that had no size limit at all, and fix an ordering bug found while digging into it. **Bug fixes + maintenance:** - Fix messages being returned out of publish order when polling or replaying **several topics at once** (`/topic1,topic2/json?poll=1`, [#&#8203;1297](https://github.com/binwiederhier/ntfy/issues/1297)) - Limit the message title to 1 KB and all tags combined to 512 bytes, rejecting larger requests with HTTP 400 (error codes `40057` and `40058`). Neither field had a size limit before, unlike the message body; on ntfy.sh the 99.9th percentile is 212 bytes for titles and 244 for tags - Cap a single cache replay at 10 MB of messages per topic. A poll without a `since` cursor returns a topic's entire cache, which was previously unbounded and could reach tens of megabytes on a busy topic, so one request could allocate that much on the server. The newest messages that fit are kept and a truncated response carries an `X-Messages-Truncated: 1` header - `visitor-attachment-daily-bandwidth-limit` now also covers messages replayed from the message cache by poll requests, not just attachment traffic. A poll without a `since` cursor returns a topic's entire cache, so a topic that is cheap to fill can be re-read for many times its own size; polls beyond the budget are rejected with HTTP 429 (error code 42905) before anything is written. **Note that heavy pollers now consume the same budget as attachment downloads**, so operators serving both may want to raise the limit ### [`v2.27.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.27.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.26.3...v2.27.0) This release lets you sign in with your verified email address instead of your username, which should help if you ever signed up with an email and then forgot which username you picked. It also hardens the message templating engine against a few ways a small template could eat a lot of memory, and it drops the "experimental" label from PostgreSQL support, which has been running ntfy.sh for a while now. I also did a bunch of refactoring in, mostly in preparation for being able to cluster ntfy nodes and scale the service horizontally. It'll be a while until then, ... baby steps. **Security:** - Limit message templates (`Template: yes`) to 32 KB, limit `printf` widths and precisions to below 1000, and limit `indent`/`nindent` to 100 spaces, preventing excessive memory use from a single small template - Exclude secrets from the config hash served to the web app, preventing a rather theoretical information leak **Features:** - Allow logging in with your verified primary email address (in addition to your username), so a password reset no longer leaves you unable to sign in when you only remember the email you signed up with **Bug fixes + maintenance:** - Fix Twilio phone calls and phone number verifications failing silently when Twilio rejected the request, and move the Twilio integration into its own `twilio` package - Move the Prometheus metrics into a dedicated `metrics` package - Message cache databases from ntfy older than v1.10.0 (November 2021) can no longer be migrated; upgrade via an older ntfy version first, or delete the cache database - Fix `user_phone` table in the SQLite user database referencing a dropped table after the v2.14 schema migration; repaired automatically by a new migration ### [`v2.26.3`](https://github.com/binwiederhier/ntfy/releases/tag/v2.26.3) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.26.0...v2.26.3) This is a hotfix release, useful pretty much only for ntfy.sh. It was adds the ability to track abusive IPs mor efficiently, reducing the load on the IP banning services and preventing them from falling behind and leaving abusers unbanned for too long. It works by tracking HTTP errors, and writing out a ban file that fail2ban can read and ban offenders instantly. See [ban-feed](https://docs.ntfy.sh/config/#ban-feed) for details. **Features:** - Add an abuse ban-feed: when enabled via `ban-file`, ntfy tracks a weighted strike budget per visitor and appends abusive IPs to a file that fail2ban can tail and ban on sight (`ban-file`, `ban-window`, `ban-threshold`, `ban-weights`; see [ban-feed](https://docs.ntfy.sh/config/#ban-feed)) ### [`v2.26.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.26.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.25.0...v2.26.0) This release hardens **message templates**, which are now executed with a hard-capped execution timeout. This closes a denial-of-service hole. On the web app side, it adds configurable **date and time formats**, a smoother loading and page-transition experience, and a fix that strips unsafe URL protocols from rendered Markdown. **Security:** - Prevent a CPU denial of service via message templates (`Template: yes`), [#&#8203;1826](https://github.com/binwiederhier/ntfy/pull/1826), thanks to [@&#8203;alanturing881](https://github.com/alanturing881) for reporting) **Features:** - Web app: Add "Date format" and "Time format" settings (Settings -> Appearance), with ISO 8601, day/month/year (slash or dot) and month/day/year date options and a 12-/24-hour clock option, and base the default format on your browser/system locale rather than the selected display language. When logged in, both settings sync across devices via your account ([#&#8203;1647](https://github.com/binwiederhier/ntfy/issues/1647), thanks to [@&#8203;wsw70](https://github.com/wsw70) for reporting) **Bug fixes + maintenance:** - Web app: Smooth transitions and loading animation, remove flickering - Web app: `GET /account` now reads from the primary database instead of a read replica, so the account view no longer shows stale data right after a change when replicas lag behind - Docs: Document the third-party HelmForge Helm chart as a Kubernetes installation option ([#&#8203;1727](https://github.com/binwiederhier/ntfy/issues/1727), thanks to [@&#8203;mberlofa](https://github.com/mberlofa)) - Web app: Strip unsafe URL protocols (`javascript:`, `data:`, ...) from links and images in Markdown-rendered messages, so they no longer trigger an uncaught "React has blocked a javascript: URL" error (thanks to [@&#8203;jvoisin](https://github.com/jvoisin) for reporting) ### [`v2.25.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.25.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.24.0...v2.25.0) This release adds **password reset** via email, and reworks email verification to use durable, link-based magic links (replacing the old in-memory 6-digit codes). Email stays optional at signup; a user can reset their password only once they have a verified "primary" (recovery)email. All of this work is probably not useful for self-hosters, but it hopefully will be useful for me, since I do have to reset accounts on a regular basis. **Security issues:** - Generate access tokens, IDs, and magic-link tokens with a cryptographically secure RNG (`crypto/rand`) instead of a clock-seeded PRNG **Features:** - Add password reset via emailed magic link, with a "Forgot password" link on the login page and a `ntfy user reset-pass` CLI command for admins - Rework email verification to use durable, single-use, expiring magic links instead of in-memory 6-digit codes, and add a "primary" email (used for account recovery and as the `X-Email: yes` target) with verified/unverified state in the account UI - You can now clear/read messages and delete messages with a GET request ([#&#8203;1771](https://github.com/binwiederhier/ntfy/issues/1771), thanks to [@&#8203;lemmi](https://github.com/lemmi) for reporting and to [@&#8203;wunter8](https://github.com/wunter8) for implementing) - Add a reload button to the web app's action bar when running as an installed PWA, which clears the service worker caches and hard-refreshes the app - Add a "Back to app" link to the web app's login, signup, and password-reset pages (alongside the existing links), which previously had no way back to the app **Bug fixes + maintenance:** - `X-Email: yes` (also `true`/`1`) now sends to your primary verified email regardless of the `smtp-sender-verify` setting (previously it was rejected unless verification was enabled); it requires being logged in with a verified address - Grant users full access to their own sync topic (`st_...`) so cross-device subscription sync works under `auth-default-access: deny-all` ([#&#8203;733](https://github.com/binwiederhier/ntfy/issues/733), [#&#8203;1795](https://github.com/binwiederhier/ntfy/pull/1795), thanks to [@&#8203;lmorchard](https://github.com/lmorchard) for the contribution) - Support HTTP (non-TLS) S3-compatible endpoints by preserving the endpoint scheme, e.g. for a local MinIO instance ([#&#8203;1794](https://github.com/binwiederhier/ntfy/pull/1794), [#&#8203;1734](https://github.com/binwiederhier/ntfy/issues/1734), thanks to [@&#8203;sskender](https://github.com/sskender) for the contribution, and [@&#8203;Kernald](https://github.com/Kernald) for reporting) - Stop silently stripping spaces from passwords while typing in the web app's login, signup, and password-reset forms ([#&#8203;1246](https://github.com/binwiederhier/ntfy/issues/1246), thanks to [@&#8203;aldem](https://github.com/aldem) for reporting) - Update web app dependencies, including major-version upgrades to Vite (6 -> 8, now Rolldown-based), Material UI (5 -> 9), and Dexie (3 -> 4) ([#&#8203;1800](https://github.com/binwiederhier/ntfy/pull/1800), [#&#8203;1764](https://github.com/binwiederhier/ntfy/pull/1764), [#&#8203;1767](https://github.com/binwiederhier/ntfy/pull/1767), [#&#8203;1762](https://github.com/binwiederhier/ntfy/pull/1762), [#&#8203;1766](https://github.com/binwiederhier/ntfy/pull/1766), [#&#8203;1765](https://github.com/binwiederhier/ntfy/pull/1765), thanks Dependabot) - Play notification sounds in the web app even when the Notification API is unavailable, e.g. over plain HTTP or in browsers without notification support ([#&#8203;1772](https://github.com/binwiederhier/ntfy/pull/1772), thanks to [@&#8203;mitya12342](https://github.com/mitya12342) for the contribution) - Stop escaping `<`, `>`, and `&` as `\u003c`/`\u003e`/`\u0026` in JSON responses ([#&#8203;1511](https://github.com/binwiederhier/ntfy/issues/1511), [#&#8203;1512](https://github.com/binwiederhier/ntfy/pull/1512), thanks to [@&#8203;wunter8](https://github.com/wunter8) for the contribution) - Fix the web app navbar not reflecting a topic reservation (lock icon, and "Reserve topic" -> "Change reservation"/"Remove reservation" menu) until a page reload, by persisting reservation and display-name changes onto already-subscribed topics during account sync - Reduce the web app's initial bundle size by \~300 KB (\~50 KB gzipped) by lazy-loading the emoji picker dataset and the Markdown renderer, and by importing Material UI icons individually ### [`v2.24.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.24.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.23.0...v2.24.0) The main feature for this release is an in-memory ACL cache (`auth-access-cache`) that can help bring down the read load on the production database. The topic authorization queries are consistently the highest ranking queries on the database, so this will help quite a bit. The current database load is quite low, but I'm expecting it to increase as more users join and use ntfy. **Security issues:** - Fix case-insensitive ACL topic matching on SQLite: an access control rule for `secret` no longer also matches a request for `SECRET`. SQLite's `LIKE` is case-insensitive for ASCII by default. PostgreSQL was unaffected. It's honestly incredible that this issue remained undetected for so long, especially while ntfy.sh was running on SQLite (it now runs on PostgreSQL). **Features:** - Add opt-in in-memory ACL cache (`auth-access-cache`) that serves topic authorization without a database round-trip; off by default, intended for high-volume servers - Add `ntfy --version` flag to the CLI ([#&#8203;1722](https://github.com/binwiederhier/ntfy/issues/1722), [#&#8203;1748](https://github.com/binwiederhier/ntfy/pull/1748), thanks to [@&#8203;sskender](https://github.com/sskender) for the contribution, and [@&#8203;Saucy9607](https://github.com/Saucy9607) for reporting) **Bug fixes + maintenance:** - Extend account token automatically from the PWA service worker, so installed PWAs don't get logged out ([#&#8203;1669](https://github.com/binwiederhier/ntfy/pull/1669), [#&#8203;1203](https://github.com/binwiederhier/ntfy/issues/1203), [#&#8203;1533](https://github.com/binwiederhier/ntfy/issues/1533), thanks to [@&#8203;nihalgonsalves](https://github.com/nihalgonsalves) for the contribution) - Fix `rel` attribute on auto-linked notification URLs so `noreferrer`/`noopener` are actually applied ([#&#8203;1720](https://github.com/binwiederhier/ntfy/pull/1720), thanks to [@&#8203;dmitrylyzo](https://github.com/dmitrylyzo) for the contribution) - Add systemd sandboxing/hardening to the `ntfy.service` unit ([#&#8203;1467](https://github.com/binwiederhier/ntfy/pull/1467), thanks to [@&#8203;Velocifyer](https://github.com/Velocifyer) for the contribution) - Fix `cmd` package build on macOS (darwin) so the server compiles from source ([#&#8203;1631](https://github.com/binwiederhier/ntfy/issues/1631), [#&#8203;1696](https://github.com/binwiederhier/ntfy/pull/1696), thanks to [@&#8203;ShipItAndPray](https://github.com/ShipItAndPray) for the contribution, and [@&#8203;XYenon](https://github.com/XYenon) for reporting) ### [`v2.23.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.23.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.22.0...v2.23.0) **Features:** - Add per-visitor rate limit on new topic creations (`visitor-topic-creation-limit-burst` / `visitor-topic-creation-limit-replenish`, defaults 100 burst / 1m replenish) to mitigate topic-enumeration / squatting attacks that inflate the in-memory topic map **Bug fixes + maintenance:** - Remove `stacktrace-js`, `stacktrace-gps`, `humanize-duration`, and `js-base64` from the web app to reduce dependency and security footprint - Restrict the publish dialog's local file preview to safe image types (png/jpg/gif/webp) to prevent same-origin script execution from blob URLs when previewing a crafted SVG ([GHSA-j8hr-p342-xrmh](https://github.com/binwiederhier/ntfy/security/advisories/GHSA-j8hr-p342-xrmh), thanks to [@&#8203;Venukamatchi](https://github.com/Venukamatchi) for reporting) ### [`v2.22.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.22.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.21.0...v2.22.0) **Bug fixes + maintenance:** - Tighten web push endpoint allow-list regex to prevent SSRF via unanchored pattern matching ([GHSA-w9hq-5jg7-q4j7](https://github.com/binwiederhier/ntfy/security/advisories/GHSA-w9hq-5jg7-q4j7), thanks to [@&#8203;MightyNawaf](https://github.com/MightyNawaf) for reporting) - Fix web app not allowing access tokens to be changed to never expire ([#&#8203;1693](https://github.com/binwiederhier/ntfy/issues/1693)/[#&#8203;1694](https://github.com/binwiederhier/ntfy/pull/1694), thanks to [@&#8203;lastsamurai26](https://github.com/lastsamurai26) for reporting and to [@&#8203;ShipItAndPray](https://github.com/ShipItAndPray) for fixing) - Fix web app crashing on account page for tokens without a last access time ([#&#8203;1651](https://github.com/binwiederhier/ntfy/issues/1651), [#&#8203;1684](https://github.com/binwiederhier/ntfy/issues/1684), thanks to [@&#8203;Pulsar7](https://github.com/Pulsar7) and [@&#8203;rzhli](https://github.com/rzhli) for reporting) ### [`v2.21.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.21.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.20.1...v2.21.0) This release adds the ability to verify email addresses using the `smtp-sender-verify` flag. This is a change that is required because ntfy.sh was used to send unsolicited emails and the AWS SES account was suspended. Going forward, ntfy.sh won't be able to send emails unless the email address was verified ahead of time. **Features:** - Add verified email recipients feature with `smtp-sender-verify` config flag, allowing server admins to require email address verification before sending email notifications ([#&#8203;1681](https://github.com/binwiederhier/ntfy/pull/1681)) ### [`v2.20.1`](https://github.com/binwiederhier/ntfy/releases/tag/v2.20.1) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.20.0...v2.20.1) This is a small bugfix release that only affects high volume S3 backends that struggle with HTTP/2. **Bug fixes + maintenance:** - [Attachments](https://docs.ntfy.sh/config/#attachments): Add `disable_http2=true` S3 URL option to work around HTTP/2 stream errors with DigitalOcean Spaces and other S3-compatible providers ([#&#8203;1678](https://github.com/binwiederhier/ntfy/issues/1678)/[#&#8203;1679](https://github.com/binwiederhier/ntfy/pull/1679)) ### [`v2.20.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.20.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.19.2...v2.20.0) This release is another step towards making it possible to help scale ntfy up and out 🔥! With this release, you can store attachments in an S3-compatible object store as an alterative to the directory. See [attachment store](https://docs.ntfy.sh/config/#attachments) for details. > :warning: **Important note:** With this release, ntfy will take full control over the attachment directory or S3 bucket. Files/objects in the configured `attachment-cache-dir` that match the message ID format (12 chars, matching `^[A-Za-z0-9]{12}$`), and have no entries in the message database will be deleted. **Do not use a directory or S3 bucket as `attachment-cache-dir` that is also used for something else.** > > This is a small behavioral change that was necessary because the old logic often left attachments behind and would not clean them up. Unless you have re-used the attachment directory for anything else (which is hopefully never done), this should not affect you at all. **Features:** - Add S3-compatible object storage as an alternative [attachment store](https://docs.ntfy.sh/config/#attachments) via `attachment-cache-dir` config option ([#&#8203;1656](https://github.com/binwiederhier/ntfy/pull/1656)/[#&#8203;1672](https://github.com/binwiederhier/ntfy/pull/1672)) **Bug fixes + maintenance:** - Reject invalid e-mail addresses (e.g. multiple comma-separated recipients) with HTTP 400 - Add OpenRC init service file ([#&#8203;1650](https://github.com/binwiederhier/ntfy/pull/1650), thanks to [@&#8203;ageru](https://github.com/ageru) for the contribution) ### [`v2.19.2`](https://github.com/binwiederhier/ntfy/releases/tag/v2.19.2) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.19.1...v2.19.2) This is another small bugfix release for PostgreSQL, avoiding races between primary and read replica, as well as to further reduce primary load. **Bug fixes + maintenance:** - Fix race condition in web push subscription causing FK constraint violation when concurrent requests hit the same endpoint - Route authorization query to read-only database replica to reduce primary database load ### [`v2.19.1`](https://github.com/binwiederhier/ntfy/releases/tag/v2.19.1) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.19.0...v2.19.1) This is a bugfix release to avoid PostgreSQL insert failures due to invalid UTF-8 messages. It also fixes `database-url` validation incorrectly rejecting `postgresql://` connection strings. **Bug fixes + maintenance:** - Fix invalid UTF-8 in HTTP headers (e.g. Latin-1 encoded text) causing PostgreSQL insert failures and dropping entire message batches - Fix `database-url` validation rejecting `postgresql://` connection strings ([#&#8203;1657](https://github.com/binwiederhier/ntfy/issues/1657)/[#&#8203;1658](https://github.com/binwiederhier/ntfy/pull/1658)) ### [`v2.19.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.19.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.18.0...v2.19.0) This is a fast-follow release that enables Postgres read replica support. To offload read-heavy queries from the primary database, you can optionally configure one or more read replicas using the `database-replica-urls` option. When configured, non-critical read-only queries (e.g. fetching messages, checking access permissions, etc) are distributed across the replicas using round-robin, while all writes and correctness-critical reads continue to go to the primary. If a replica becomes unhealthy, ntfy automatically falls back to the primary until the replica recovers. **Features:** - Support [PostgreSQL read replicas](https://docs.ntfy.sh/config/#postgresql-experimental) for offloading non-critical read queries via `database-replica-urls` config option ([#&#8203;1648](https://github.com/binwiederhier/ntfy/pull/1648)) - Add interactive [config generator](https://docs.ntfy.sh/config/#config-generator) to the documentation to help create server configuration files ([#&#8203;1654](https://github.com/binwiederhier/ntfy/pull/1654)) **Bug fixes + maintenance:** - Web: Throttle notification sound in web app to play at most once every 2 seconds (similar to [#&#8203;1550](https://github.com/binwiederhier/ntfy/issues/1550), thanks to [@&#8203;jlaffaye](https://github.com/jlaffaye) for reporting) - Web: Add hover tooltips to icon buttons in web app account and preferences pages ([#&#8203;1565](https://github.com/binwiederhier/ntfy/issues/1565), thanks to [@&#8203;jermanuts](https://github.com/jermanuts) for reporting) ### [`v2.18.0`](https://github.com/binwiederhier/ntfy/releases/tag/v2.18.0) [Compare Source](https://github.com/binwiederhier/ntfy/compare/v2.17.0...v2.18.0) This is the biggest release I've ever done on the server. It's 14,997 added lines of code, and 10,202 lines removed, all from one [pull request](https://github.com/binwiederhier/ntfy/pull/1619) that adds [PostgreSQL support](https://docs.ntfy.sh/config/#postgresql-experimental). The code was written by Cursor and Claude, but reviewed and heavily tested over 2-3 weeks by me. I created comparison documents, went through all queries multiple times and reviewed the logic over and over again. I also did load tests and manual regression tests, which took lots of evenings. ntfy.sh was successfully upgraded to 2.18.0 (though not with Postgres backend yet, as per the [rollout plan](https://github.com/binwiederhier/ntfy/issues/1114#issuecomment-3991245185)). I'm kindly asking the community to test the Postgres support and report back to me if things are working (or not working). There is a [one-off migration tool](https://github.com/binwiederhier/ntfy/tree/main/tools/pgimport) (entirely written by AI) that you can use to migrate. **Features:** - Add experimental [PostgreSQL support](https://docs.ntfy.sh/config/#postgresql-experimental) as an alternative database backend (message cache, user manager, web push subscriptions) via `database-url` config option ([#&#8203;1114](https://github.com/binwiederhier/ntfy/issues/1114)/[#&#8203;1619](https://github.com/binwiederhier/ntfy/pull/1619), thanks to [@&#8203;brettinternet](https://github.com/brettinternet) for reporting) **Bug fixes + maintenance:** - Preserve `<br>` line breaks in HTML-only emails received via SMTP ([#&#8203;690](https://github.com/binwiederhier/ntfy/issues/690), [#&#8203;1620](https://github.com/binwiederhier/ntfy/pull/1620), thanks to [@&#8203;uzkikh](https://github.com/uzkikh) for the fix and to [@&#8203;teastrainer](https://github.com/teastrainer) for reporting) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNTMuMSIsInVwZGF0ZWRJblZlciI6IjQzLjI1My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
renovate-bot force-pushed renovate/docker.io-binwiederhier-ntfy-2.x from 29342b4645 to 1ec7e0de29 2026-07-09 19:10:00 +00:00 Compare
renovate-bot changed title from Update docker.io/binwiederhier/ntfy Docker tag to v2.25.0 to Update docker.io/binwiederhier/ntfy Docker tag to v2.26.0 2026-07-09 19:10:04 +00:00
renovate-bot changed title from Update docker.io/binwiederhier/ntfy Docker tag to v2.26.0 to chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.26.0 2026-07-17 23:10:22 +00:00
renovate-bot force-pushed renovate/docker.io-binwiederhier-ntfy-2.x from 1ec7e0de29 to 0e7bf27b63
All checks were successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
ci/crow/push/tanka-test Pipeline was successful
2026-07-20 22:07:09 +00:00
Compare
renovate-bot changed title from chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.26.0 to chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.26.3 2026-07-20 22:07:12 +00:00
renovate-bot changed title from chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.26.3 to Update docker.io/binwiederhier/ntfy Docker tag to v2.26.3 2026-07-21 01:07:43 +00:00
renovate-bot changed title from Update docker.io/binwiederhier/ntfy Docker tag to v2.26.3 to chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.26.3 2026-07-21 02:07:50 +00:00
renovate-bot changed title from chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.26.3 to chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.27.0 2026-08-04 23:13:30 +00:00
renovate-bot force-pushed renovate/docker.io-binwiederhier-ntfy-2.x from e8ff908420 to 9095c44202 2026-09-21 19:15:14 +00:00 Compare
renovate-bot changed title from chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.27.0 to chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.28.0 2026-09-21 19:15:18 +00:00
renovate-bot force-pushed renovate/docker.io-binwiederhier-ntfy-2.x from 9095c44202 to 8900ac780c
All checks were successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/push/tanka-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
2026-10-07 16:09:28 +00:00
Compare
renovate-bot changed title from chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.28.0 to chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.29.0 2026-10-07 16:09:30 +00:00
renovate-bot force-pushed renovate/docker.io-binwiederhier-ntfy-2.x from 8900ac780c
All checks were successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/push/tanka-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
to 52db22b81f
All checks were successful
ci/crow/push/tanka-test Pipeline was successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
2026-10-12 14:07:24 +00:00
Compare
renovate-bot changed title from chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.29.0 to chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.30.0 2026-10-12 14:07:27 +00:00
renovate-bot force-pushed renovate/docker.io-binwiederhier-ntfy-2.x from 52db22b81f
All checks were successful
ci/crow/push/tanka-test Pipeline was successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
to ca9c56c6e2
All checks were successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/push/tanka-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
2026-10-15 20:07:26 +00:00
Compare
renovate-bot changed title from chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.30.0 to chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.31.0 2026-10-15 20:07:28 +00:00
renovate-bot force-pushed renovate/docker.io-binwiederhier-ntfy-2.x from ca9c56c6e2
All checks were successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/push/tanka-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
to ddaec1a8ea
All checks were successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/push/tanka-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
2026-10-17 01:07:17 +00:00
Compare
renovate-bot changed title from chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.31.0 to chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.31.1 2026-10-17 01:07:22 +00:00
renovate-bot force-pushed renovate/docker.io-binwiederhier-ntfy-2.x from ddaec1a8ea
All checks were successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/push/tanka-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
to 35ec5fec44
All checks were successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/push/tanka-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
2026-10-19 20:08:18 +00:00
Compare
renovate-bot changed title from chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.31.1 to chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.32.0 2026-10-19 20:08:22 +00:00
renovate-bot force-pushed renovate/docker.io-binwiederhier-ntfy-2.x from 35ec5fec44
All checks were successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/push/tanka-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
to e6dbc89c3e
All checks were successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/push/tanka-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
2026-10-23 02:07:55 +00:00
Compare
renovate-bot changed title from chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.32.0 to chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.33.0 2026-10-23 02:08:00 +00:00
renovate-bot force-pushed renovate/docker.io-binwiederhier-ntfy-2.x from e6dbc89c3e
All checks were successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/push/tanka-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
to 3dd67ed178
All checks were successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/push/tanka-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
2026-10-23 03:07:41 +00:00
Compare
renovate-bot changed title from chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.33.0 to chore(deps): update docker.io/binwiederhier/ntfy docker tag to v2.33.1 2026-10-23 03:07:45 +00:00
All checks were successful
ci/crow/pr/tanka-test Pipeline was successful
ci/crow/push/tanka-test Pipeline was successful
ci/crow/push/dns-test Pipeline was successful
ci/crow/pr/dns-test Pipeline was successful
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin renovate/docker.io-binwiederhier-ntfy-2.x:renovate/docker.io-binwiederhier-ntfy-2.x
git switch renovate/docker.io-binwiederhier-ntfy-2.x

Merge

Merge the changes and update on Forgejo.
git switch main
git merge --no-ff renovate/docker.io-binwiederhier-ntfy-2.x
git switch renovate/docker.io-binwiederhier-ntfy-2.x
git rebase main
git switch main
git merge --ff-only renovate/docker.io-binwiederhier-ntfy-2.x
git switch renovate/docker.io-binwiederhier-ntfy-2.x
git rebase main
git switch main
git merge --no-ff renovate/docker.io-binwiederhier-ntfy-2.x
git switch main
git merge --squash renovate/docker.io-binwiederhier-ntfy-2.x
git switch main
git merge --ff-only renovate/docker.io-binwiederhier-ntfy-2.x
git switch main
git merge renovate/docker.io-binwiederhier-ntfy-2.x
git push origin main
Sign in to join this conversation.
No reviewers
No labels
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
ops/homelab!22
No description provided.