Global HTTP timeouts vs per-request context cancellation for long Git operations in Forgejo
0 reputation · 18 Oct 2025, 04:38 UTC
0 reputation · 18 Oct 2025, 04:38 UTC
I'm running a Forgejo instance (v1.21-era configuration) that regularly serves large repository pushes and LFS transfers, and I need to decide how to protect the server without breaking legitimate long-running operations.
From the documentation, the [server] section in app.ini exposes ReadTimeout, ReadHeaderTimeout, and WriteTimeout, enforced globally by Go's net/http server. Setting these aggressively guards against slowloris-style attacks and stuck connections, but my understanding is they would also abort slow but healthy pushes from clients on poor connections.
The alternative I've seen discussed is propagating the incoming HTTP request's context down to the spawned git subprocesses, so a client disconnect or deadline cancels the underlying command. My concern is that this appears not to be the current default behavior — the git process may keep running after the client goes away — and that adding it raises questions about orphaned processes and signal forwarding to process groups.
Which approach is more appropriate for a public-facing instance with frequent multi-GB pushes: tight global HTTP timeouts, or per-request context propagation to git commands? If I enable per-request cancellation, what guarantees exist that interrupted git processes are fully reaped rather than left as orphans? And is there a documented way to verify on a test instance which behavior my build actually exhibits?
34775 reputation · 18 Oct 2025, 14:48 UTC
For a public‑facing Forgejo instance that regularly handles multi‑GB pushes, enable per‑request context cancellation for the git subprocess and keep a relatively high global HTTP timeout as a backup safeguard. This lets legitimate long pushes finish while still aborting connections when the client disconnects or exceeds the deadline.
ReadTimeout, ReadHeaderTimeout and WriteTimeout are enforced by Go's net/http server before any application code runs, so they abort a push solely based on elapsed wall‑clock time, regardless of the client's uplink speed.exec.Command used for git receives the incoming request’s context.Context (e.g., gitCmd.Context = ctx or via exec.CommandContext).SIGTERM and the parent waits for its exit (e.g., cmd.Wait() after cmd.Start()). This prevents orphaned git processes.app.ini to values comfortably above the expected maximum push duration (e.g., ReadTimeout = 10m, WriteTimeout = 10m) to retain protection against slowloris attacks without interfering with normal large pushes.trickle -s -u 50 git push).ps -ef | grep git; if no git process remains, the context is being propagated and reaped.git command cancelled due to context deadline; absence of such a line indicates the default behavior (no propagation).Are you running a stock Forgejo v1.21 build, or have you applied any custom patches that already modify how the git subprocess is launched?
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.