Nginx Configuration
Depfloy generates and manages a nginx configuration for every project. The Nginx tab on a project lets you layer your own customisations on top of Depfloy's defaults without editing nginx files over SSH.
When to use it
You'll need the Nginx tab when you want to:
- Add custom HTTP headers
- Increase upload size or proxy buffer sizes
- Add a custom error page or redirect
- Add a
locationblock with special handling - Proxy a subpath to a separate service
For most projects, the defaults are fine — you don't need to touch this tab at all.
Server and Location snippets
The Nginx tab gives you two text areas:
- Server snippet — injected at the top level of the project's
serverblock. Use this for directives that apply to the whole virtual host (client_max_body_size,add_header,error_page, additionallocationblocks). - Location snippet — injected inside the project's default
location /block. Use this for directives that should only apply to the application's main route.
Save your changes and Depfloy regenerates the nginx configuration on the server and reloads nginx.
# Example server snippet — bigger uploads, custom security header
client_max_body_size 50M;
add_header X-Custom-Header "Custom Value";
# Example location snippet — extra proxy header
proxy_set_header X-Real-IP $remote_addr;
Custom snippets can override Depfloy's defaults
Most nginx directives can only appear once in a server or location block — client_max_body_size, keepalive_timeout, gzip, and similar. If both Depfloy's template and your snippet set the same directive, nginx fails with a "directive is duplicate" error.
To make custom snippets work cleanly, Depfloy detects when your snippet sets one of these single-instance directives and removes Depfloy's default for that directive before injecting your custom block. Your snippet wins; nginx stays valid.
Directives that can be overridden
If your snippet sets one of these directives, Depfloy drops its own copy in favour of yours:
client_max_body_size, client_body_buffer_size, client_body_timeout, client_header_buffer_size, client_header_timeout, large_client_header_buffers, keepalive_timeout, send_timeout, proxy_read_timeout, proxy_send_timeout, proxy_connect_timeout, proxy_buffer_size, proxy_buffers, proxy_busy_buffers_size, proxy_buffering, fastcgi_read_timeout, fastcgi_send_timeout, fastcgi_buffer_size, fastcgi_buffers, server_tokens, charset, root, index, autoindex, gzip, gzip_types, gzip_min_length, gzip_proxied, gzip_comp_level.
Directives that are always kept
Directives that can legitimately appear multiple times (add_header, set_real_ip_from, listen, server_name, log_format, location, if, and others) are not affected. Your snippet's directives are appended alongside Depfloy's.
Where it applies
The override behaviour only applies at the top level of the server block and the top level of the default location / block. Directives inside nested location blocks in your snippet are left alone.
Maintenance Mode interaction
When a project is in Maintenance Mode, the nginx tab is read-only — the configuration is locked to the maintenance page until you turn maintenance off. You can still view what would be deployed, you just can't save changes until the project is out of maintenance.
Plugin error visibility
If you have a Laravel plugin installed on the project (Octane, Reverb, Horizon, Nightwatch — see Background Jobs) and its setup or runtime hits an error, the plugin row shows an Error badge with a destructive banner below it. The banner contains:
- A truncated single-line error message with Show full error to expand
- A Copy button to grab the error text
- A Logs button that opens the full plugin log
This is especially useful when an nginx-related setup fails because a directive collides with something — the override behaviour above usually catches that, but if not, the banner tells you exactly which directive nginx rejected.
Node.js Upstream
Node.js projects (Next.js, Nuxt, Remix, React Router) use blue/green deployment, which means the application port changes between deployments. Depfloy automatically manages an nginx upstream block for each Node.js project:
upstream upstream_{project_id} {
server 127.0.0.1:{port} max_fails=2 fail_timeout=5s;
keepalive 32;
}
If you write a custom nginx configuration that references a Node.js project, always use the upstream alias instead of a hardcoded port number. The port will change on every deployment and a hardcoded port will cause 502 errors.
# ✅ Correct — uses upstream alias, port updates automatically
location /docs {
proxy_pass http://upstream_232;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# ❌ Wrong — hardcoded port will break after deployment
location /docs {
proxy_pass http://127.0.0.1:3093;
}
You can find your project's upstream name in the nginx configuration file. It follows the pattern upstream_{project_id}. The project ID is visible in the URL when you open the project in Depfloy.