Timeouts
What each timeout detects
| Timeout | Detects | Default |
|---|---|---|
sftp.login_grace_secs | an SSH connection that does not authenticate | 120 s |
uploads.idle_timeout_secs | a live client that stops sending during an upload (suspended, stuck) | 30 s |
uploads.min_rate_bytes_per_sec | a trickle upload | disabled |
[tcp_keepalive] | a peer gone with nothing in flight (machine powered off, NAT that forgot the connection) | ~60 s |
tcp_keepalive.user_timeout_secs | a peer gone while the server was sending it something; a client that stops reading | 65 s (SFTP), 35 s (HTTP) |
sftp.inactivity_timeout_secs | an SSH connection with no packet at all | 600 s |
sftp.keepalive_interval_secs | an SSH client frozen as a whole | disabled |
admin.header_read_timeout_secs | an HTTP request whose headers do not arrive | 10 s |
Uploads: [uploads]
[uploads]
idle_timeout_secs = 30
min_rate_bytes_per_sec = 1024 # 1 KiB/s on average; absent or 0: disabled
min_rate_grace_secs = 60
All the keys: Reference [uploads].
The idle timeout
The clock runs only while the server waits for the client. The time the server spends on its storage (slow S3, stalling NFS) never counts.
| Door | The clock |
|---|---|
| REST | restarts on each byte of the body |
| SFTP | one per write handle: starts at the OPEN, restarts on each complete WRITE of this handle, whatever the session does elsewhere; a packet must arrive whole within the timeout that follows its first byte |
When the timeout expires, the partial file is dropped (in-flight file deleted, S3 multipart aborted) and nothing is published.
A live upload reaches its file at least every 2 x
idle_timeout_secs: the cleanup of leftovers and the takeover of locks
rely on it, so give the same value to all instances that share a
storage. Raise it for clients that keep a file open without writing
(sshfs, a graphical client that asks for a confirmation, a very slow link:
at the default, a 32 KiB packet needs ~1.1 KB/s).
The minimum rate
Once min_rate_grace_secs of waiting have passed, an upload must have
received on average at least min_rate_bytes_per_sec, like Apache’s
RequestReadTimeout ... MinRate. The average runs from the start: a bursty
client keeps the credit of its bursts, a trickle is cut at the end of the
grace period. The bytes counted are those of accepted WRITE packets, not
the offset reached.
Below it, the upload is cut as for idleness. 1 KiB/s cuts a trickle and lets through a 10 KiB/s link that stalls.
TCP keepalive: [tcp_keepalive]
Set on each accepted connection, on the SFTP port and on the HTTP port.
All the keys: Reference [tcp_keepalive].
Network loss in the middle of a transfer: TCP_USER_TIMEOUT
Keepalive probes only a connection with nothing in flight. When the server
sends something to a client that is gone (the replies to the WRITE
packets of an SFTP upload, a download), TCP_USER_TIMEOUT cuts.
user_timeout_secs | SFTP port | HTTP port |
|---|---|---|
0 or absent | 2 x idle_timeout_secs + 5 s (65 s) | idle_timeout_secs + 5 s (35 s) |
N | N | N |
The connection is thus cut 5 s after the upload is abandoned. On Linux,
this timeout replaces count: an idle connection whose peer is gone is cut
at the first probe that exceeds it (around 70 s on SFTP). It also applies
to a client that stops reading: a REST download whose client is suspended
is cut at 35 s. A longer network loss (coverage loss, VPN reconnecting)
kills the transfer; raise user_timeout_secs if your clients go through
such losses.
Outside Linux, nothing is set.
SSH: [sftp]
login_grace_secs and inactivity_timeout_secs cut the connection (0:
never); keepalive_interval_secs (0: none) probes the client,
keepalive_max (3) cuts after that many probes without an answer. The
keys: [sftp].
The answer to an SSH keepalive counts as activity: with a keepalive
shorter than inactivity_timeout_secs, a live but idle session is no
longer cut for inactivity, only a client that no longer answers is.
That is why SSH keepalive is disabled by default.
HTTP: header read timeout
admin.header_read_timeout_secs (10 s, from 1 to 300,
CRAFT_FILE_GATE_ADMIN_HEADER_READ_TIMEOUT_SECS) bounds, on the port of
the admin API and the file API, the wait for the headers of a request:
from the connection, the TLS handshake or the previous response in
keep-alive. Beyond it, the connection is closed without a response. It
bounds neither a body nor a response.
The port serves only HTTP/1.1; over HTTPS, ALPN offers only http/1.1,
and HTTP/2 clients fall back to it.
What you will see
| When | Line |
|---|---|
| startup | INFO idle and liveness timeouts in force: ..., one value per field, and from_config: the keys set by the file |
| peer gone | INFO SSH session ended: the connection timed out: ... |