Revert "Listen for clients without TCP keep-alive probes" (#2152)

Without the probes and without an http.Server IdleTimeout, an idle keep-alive connection from a client that silently went away (a phone switching networks) stays open until ntfy restarts. The probes come back as they were; a version with probe timing above the keepalive interval follows in a separate PR.

Claude-Session: https://claude.ai/code/session_01DeXuhSjq5Gta5qPJgSceFe
This commit is contained in:
binwiederhier committed 2026-11-03 23:04:56 +00:00
1 parent 75857d28bb
commit 6db70ed568
3 files changed
+2 -23

No files matched your search

-1
View File
@@ -2355,7 +2355,6 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
**Bug fixes + maintenance:**
* Do not send TCP keep-alive probes on the client listeners (`listen-http`, `listen-https`): Go sends one every 15 seconds on an idle connection by default, which, without a proxy in front of ntfy, woke phones holding a stream three times as often as ntfy's own keepalive event ([#2152](https://github.com/binwiederhier/ntfy/pull/2152))
* `ntfy cluster status` lists the node itself as the first row of the table (marked "this node", and "leader" if it leads) instead of a line above it ([#2153](https://github.com/binwiederhier/ntfy/pull/2153))
* The cluster and admin socket options lost their `experimental-` prefix, e.g. `cluster-listen` instead of `experimental-cluster-listen` (and `NTFY_CLUSTER_LISTEN`); the old names still work ([#2154](https://github.com/binwiederhier/ntfy/pull/2154))
* Send read-only queries to the least busy read replica instead of round-robin, so a replica that stalls stops getting new reads; the new `ntfy_db_ping_seconds` metric shows how long each database takes to answer its health check ([#2156](https://github.com/binwiederhier/ntfy/pull/2156))
+2 -12
View File
@@ -505,23 +505,13 @@ func (s *Server) Run() error {
httpServer := &http.Server{Addr: addr, Handler: mux}
s.httpServers = append(s.httpServers, httpServer)
go func() {
listener, err := listenTCP(addr)
if err != nil {
errChan <- err
return
}
errChan <- httpServer.Serve(listener)
errChan <- httpServer.ListenAndServe()
}()
}
if s.config.ListenHTTPS != "" {
s.httpsServer = &http.Server{Addr: s.config.ListenHTTPS, Handler: mux}
go func() {
listener, err := listenTCP(s.config.ListenHTTPS)
if err != nil {
errChan <- err
return
}
errChan <- s.httpsServer.ServeTLS(listener, s.config.CertFile, s.config.KeyFile)
errChan <- s.httpsServer.ListenAndServeTLS(s.config.CertFile, s.config.KeyFile)
}()
}
if s.config.ListenUnix != "" {
-10
View File
@@ -6,7 +6,6 @@ import (
"fmt"
"io"
"mime"
"net"
"net/http"
"net/netip"
"regexp"
@@ -207,12 +206,3 @@ func isMarkdownContentType(contentType string) bool {
}
return strings.ToLower(mediaType) == "text/markdown"
}
// listenTCP listens for the clients (listen-http, listen-https) without TCP keep-alive probes. Go
// sends them every 15s on an idle accepted connection by default; to a phone holding a stream, each
// is a radio wake-up, on top of ntfy's own keepalive event (keepalive-interval, 45s), which already
// keeps the connection alive and finds dead ones.
func listenTCP(addr string) (net.Listener, error) {
lc := &net.ListenConfig{KeepAlive: -1}
return lc.Listen(context.Background(), "tcp", addr)
}