# 256 MiB covers current and near-future firmware images (the aarch64 # .pkg is ~160 MiB today) without setting an alarming body-size cap on # devices that may only have 512 MiB of RAM. nginx is the single source # of truth for the upload ceiling. # # Set at server scope (top of file) rather than once on an outer # `location /` with a nested inner location: nginx inheritance of # client_max_body_size into a nested location that declares its own # `proxy_pass` block has bitten us before, silently falling back to # the http-level default of 1m and rejecting 160 MiB firmware uploads # with 413. client_max_body_size 256m; location / { include /etc/nginx/webui-proxy.conf; } location = /firmware/upload { # Body is buffered by nginx (to /var/cache/nginx/client-body, ext4 # on eMMC, with 16 KB RAM cap before spill) before forwarding to # Go. The extra disk pass on a 160 MiB upload is ~30s on eMMC; in # exchange Go gets a complete, well-formed request with a known # Content-Length. The previous setup used `proxy_request_buffering # off` to stream the body straight through and avoid the double # write, but that raced the response write with the body forward: # net/http EOFs the body reader at Content-Length, then closes the # socket, but with streaming the multipart trailer can still be in # the kernel receive buffer, so close() sends RST instead of FIN # and nginx serves /50x.html to the client. proxy_read_timeout 600s; include /etc/nginx/webui-proxy.conf; } # Liveness probe served by nginx itself — no upstream call, no log line. # Used by the watchdog div in base.html and the reboot-overlay poller. location = /device-status { access_log off; return 204; }