X-Accel (X-Sendfile)¶
X-Accel allows for internal redirection to a location determined by a header returned from a backend. This is commonly known as X-Sendfile.
How It Works¶
- Backend handles authentication, logging, or other logic
- Backend sends
X-Accel-Redirectheader with an internal URI - NGINX serves the file, freeing the backend for other requests
- End user receives the file directly from NGINX
Basic Configuration¶
Using alias¶
# Will serve /var/www/files/myfile.tar.gz
# When passed URI /protected_files/myfile.tar.gz
location /protected_files {
internal;
alias /var/www/files;
}
Using root¶
# Will serve /var/www/protected_files/myfile.tar.gz
# When passed URI /protected_files/myfile.tar.gz
location /protected_files {
internal;
root /var/www;
}
Proxying to Another Server¶
location /protected_files {
internal;
proxy_pass http://127.0.0.2;
}
internal
The internal directive prevents direct client access to this location. Only internal redirects (like X-Accel) can reach it.
Special Headers¶
X-Accel-Redirect¶
Sets the URI for NGINX to serve.
X-Accel-Redirect: /protected_files/myfile.tar.gz
X-Accel-Buffering¶
Controls proxy buffering for this connection.
| Value | Effect |
|---|---|
yes |
Allow response caching (default) |
no |
Unbuffered responses (for Comet/streaming) |
X-Accel-Buffering: no
X-Accel-Charset¶
Sets the charset of the file.
X-Accel-Charset: utf-8
X-Accel-Expires¶
Sets when to expire the file in NGINX's internal cache.
| Value | Effect |
|---|---|
off |
Disable cache expiry (default) |
<seconds> |
Expire after N seconds |
X-Accel-Expires: 3600
X-Accel-Limit-Rate¶
Sets rate limit for this single request.
| Value | Effect |
|---|---|
off |
Unlimited (default) |
<bytes> |
Limit to N bytes/second |
X-Accel-Limit-Rate: 1024
Example: Protected Downloads¶
NGINX Configuration¶
server {
listen 80;
server_name example.com;
# Public frontend
location / {
proxy_pass http://backend;
}
# Protected files (internal only)
location /protected/ {
internal;
alias /var/www/downloads/;
}
}
Backend Response (e.g., PHP)¶
<?php
// Verify user has access
if (!user_has_access($file)) {
http_response_code(403);
exit;
}
// Log the download
log_download($user, $file);
// Let NGINX serve the file
header('X-Accel-Redirect: /protected/' . $file);
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
exit;
?>