Repository navigation
Webserver offload
Tip
TL;DR Apache or nginx send the file body instead of PHP. Off by default. With nginx set a size threshold: offloaded nginx responses carry no CSP.
| Key | Type | Default | Effect |
|---|---|---|---|
raw_sendfile_backend |
off, apache, nginx
|
off |
which mechanism to use |
raw_sendfile_allow_private |
bool | false |
also offload private URLs (/raw/u/...) |
raw_sendfile_min_size_mb |
int | 0 |
offload only files of at least this size, 0 = no threshold |
raw_sendfile_nginx_prefix |
string | /_raw_sendfile |
internal nginx location |
A file is offloaded only when all of these hold:
- it lies on local storage inside Nextcloud's
datadirectory; - the request is public, or
raw_sendfile_allow_privateistrue; - with a threshold set, its size is known and reaches the threshold.
Otherwise PHP streams the file as usual.
Warning
The app restricts offload to the data directory. The webserver side is the administrator's responsibility.
-
nginx:
internal;is mandatory. Without it the offload location can be requested directly from the internet, and every file in the data directory is reachable without authentication. -
Apache: set
XSendFilePath. The app only sends paths inside the data directory, so this is defense in depth.
Needs mod_xsendfile or an equivalent X-Sendfile implementation, enabled for the Nextcloud vhost:
XSendFile On
XSendFilePath /path/to/nextcloud/data'raw_sendfile_backend' => 'apache',Uses X-Accel-Redirect, no extra module. The location must match raw_sendfile_nginx_prefix:
location /_raw_sendfile/ {
internal;
alias /path/to/nextcloud/data/;
}'raw_sendfile_backend' => 'nginx',
'raw_sendfile_nginx_prefix' => '/_raw_sendfile',
'raw_sendfile_min_size_mb' => 10,Tip
The redirect target is the file path with the realpath of datadirectory stripped. The alias must use that same resolved path with a trailing /. If datadirectory is a symlink and nginx points elsewhere, the paths do not match.
Warning
nginx offload drops the Content-Security-Policy header. With X-Accel-Redirect nginx sends the body itself and does not pass on the CSP set by PHP. Set raw_sendfile_min_size_mb (for example 10) so HTML, text, feeds and images stay with PHP and keep their CSP, and only large binaries are offloaded. If every response needs a CSP, do not use the nginx backend.
Send X-Raw-Offload-Debug: 1 to get the reason in the response:
curl -sI -H 'X-Raw-Offload-Debug: 1' 'https://cloud.example.com/raw/<token>/video.mp4' | grep -i '^x-raw-offload'X-Raw-Offload |
Meaning |
|---|---|
apache-xsendfile; reason=offloaded |
sent by Apache |
nginx-x-accel; reason=offloaded |
sent by nginx |
none; reason=backend_off |
raw_sendfile_backend is off
|
none; reason=private_disallowed |
private URL, raw_sendfile_allow_private is false
|
none; reason=too_small |
below raw_sendfile_min_size_mb
|
none; reason=size_unknown |
threshold set, size not reported by the storage |
none; reason=not_in_datadir |
file outside datadirectory
|
none; reason=no_local_path |
storage has no local file, for example external or object storage |
none; reason=nginx_map_fail |
datadirectory could not be resolved |
none; reason=no_fast_etag |
storage reports no mtime or size, PHP sends the body |
none; reason=head_request |
HEAD, no body to send |
none; reason=not_modified |
304, no body to send |
Without the debug header an offloaded response still carries X-Raw-Offload: apache-xsendfile or nginx-x-accel.
Getting started
Controlling access
Security headers
Performance
Reference