Skip to content
Open
71 changes: 53 additions & 18 deletions admin_manual/installation/nginx-root.conf.sample
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Version 2025-07-23
# Nextcloud nginx configuration — root installation
# Version 2026-03-26

# PHP-FPM backend.
upstream php-handler {
# Use one of the options below, not both:
server 127.0.0.1:9000;
#server unix:/run/php/php8.2-fpm.sock;
}
Expand Down Expand Up @@ -148,37 +151,69 @@ server {
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; }

# Ensure this block, which passes PHP files to the PHP process, is above the blocks
# which handle static assets (as seen below). If this block is not declared first,
# then Nginx will encounter an infinite rewriting loop when it prepends `/index.php`
# to the URI, resulting in a HTTP 500 error response.
# Pass PHP requests to PHP-FPM.
#
# Important: this block must appear above the static asset locations
# below. Those locations fall back to `/index.php$request_uri`; if
# they appear first, nginx can repeatedly rewrite to `/index.php`,
# causing an internal redirection loop.
location ~ \.php(?:$|/) {
# Required for legacy support
rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /index.php$request_uri;

# Rewrite most PHP requests to Nextcloud's front controller (`/index.php`).
#
# (Mirrors the rewrite exceptions in Nextcloud's Apache .htaccess.)
#
# Exceptions (not rewritten; must remain directly reachable):
# index.php, remote.php, public.php, cron.php, status.php
# ocs/v1.php, ocs/v2.php, ocs-provider/*
# core/ajax/update.php, updater/*
# */richdocumentscode(_arm64)?/proxy
#
# Other exceptions (e.g. /.well-known) are handled by dedicated
# location blocks elsewhere in this config.
#
# Caution: small edits to this regex can break routing or introduce
# rewrite loops.
rewrite ^/(?!index|remote|public|cron|status|ocs\/v[12]|ocs-provider\/.+|core\/ajax\/update|updater\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /index.php$request_uri;

# Split `/file.php/path/info` into:
# - script name: `/file.php`
# - PATH_INFO: `/path/info`
Comment on lines +179 to +180
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make clear which variables are set by calling fastcgi_split_path_info:

Suggested change
# - script name: `/file.php`
# - PATH_INFO: `/path/info`
# - $fastcgi_script_name: `/file.php`
# - $fastcgi_path_info: `/path/info`

Can be seen from context and Nginx docs, of course, but as we aim to enhance clarity, this could make it easier to read through and understand.

#
# This is required for entry-points such as `remote.php` and `public.php`,
# which route requests based on PATH_INFO.
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
set $path_info $fastcgi_path_info;
set $path_info $fastcgi_path_info; # Save before try_files resets it

# Return 404 for nonexistent PHP scripts (avoids passing arbitrary
# paths to PHP-FPM, which is a known security risk).
try_files $fastcgi_script_name =404;

include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_param HTTPS on;

fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice
fastcgi_param front_controller_active true; # Enable pretty urls
fastcgi_pass php-handler;

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_param HTTPS on; # Assumes TLS terminates here
fastcgi_param modHeadersAvailable true; # Avoid duplicate security headers
fastcgi_param front_controller_active true; # Enable pretty URLs

# Let nginx handle HTTP error responses from PHP-FPM (e.g. custom
# error pages). Disable for debugging if PHP errors are being hidden.
fastcgi_intercept_errors on;
fastcgi_request_buffering on; # Required as PHP-FPM does not support chunked transfer encoding and requires a valid ContentLength header.

# PHP-FPM 504 response timeouts
# Uncomment and increase these if facing timeout errors during large file uploads
# Required for uploads: PHP-FPM does not support chunked
# transfer encoding and needs a Content-Length header.
fastcgi_request_buffering on;

# Optional PHP-FPM timeout tuning (e.g. for 504 response timeouts).
# Increase these only if uploads or long-running PHP requests are
# timing out in your environment.
#fastcgi_read_timeout 60s;
#fastcgi_send_timeout 60s;
#fastcgi_connect_timeout 60s;

# Disable on-disk buffering of FastCGI responses (reduces disk I/O at
# the cost of holding responses in memory).
fastcgi_max_temp_file_size 0;
}

Expand Down
74 changes: 55 additions & 19 deletions admin_manual/installation/nginx-subdir.conf.sample
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Version 2025-07-23
# Nextcloud nginx configuration — subdirectory installation (/nextcloud)
# Version 2026-03-26

# PHP-FPM backend.
upstream php-handler {
# Use one of the options below, not both:
server 127.0.0.1:9000;
#server unix:/run/php/php8.2-fpm.sock;
}
Expand Down Expand Up @@ -52,7 +55,7 @@ server {
include mime.types;
types {
text/javascript mjs;
application/wasm wasm;
application/wasm wasm;
}

location = /robots.txt {
Expand Down Expand Up @@ -147,37 +150,70 @@ server {
location ~ ^/nextcloud/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
location ~ ^/nextcloud/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; }

# Ensure this block, which passes PHP files to the PHP process, is above the blocks
# which handle static assets (as seen below). If this block is not declared first,
# then Nginx will encounter an infinite rewriting loop when it prepends
# `/nextcloud/index.php` to the URI, resulting in a HTTP 500 error response.
# Pass PHP requests to PHP-FPM.
#
# Important: this block must appear above the static asset locations
# below. Those locations fall back to `/nextcloud/index.php$request_uri`;
# if they appear first, nginx can repeatedly rewrite to
# `/nextcloud/index.php`, causing an internal redirection loop.
location ~ \.php(?:$|/) {
# Required for legacy support
rewrite ^/nextcloud/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /nextcloud/index.php$request_uri;

# Rewrite most PHP requests to Nextcloud's front controller
# (`/nextcloud/index.php`).
#
# (Mirrors the rewrite exceptions in Nextcloud's Apache .htaccess.)
#
# Exceptions (not rewritten; must remain directly reachable):
# index.php, remote.php, public.php, cron.php, status.php
# ocs/v1.php, ocs/v2.php, ocs-provider/*
# core/ajax/update.php, updater/*
# */richdocumentscode(_arm64)?/proxy
#
# Other exceptions (e.g. /.well-known) are handled by dedicated
# location blocks elsewhere in this config.
#
# Caution: small edits to this regex can break routing or introduce
# rewrite loops.
rewrite ^/nextcloud/(?!index|remote|public|cron|status|ocs\/v[12]|ocs-provider\/.+|core\/ajax\/update|updater\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /nextcloud/index.php$request_uri;

# Split `/file.php/path/info` into:
# - script name: `/file.php`
# - PATH_INFO: `/path/info`
#
# This is required for entry-points such as `remote.php` and `public.php`,
# which route requests based on PATH_INFO.
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
set $path_info $fastcgi_path_info;
set $path_info $fastcgi_path_info; # Save before try_files resets it

# Return 404 for nonexistent PHP scripts (avoids passing arbitrary
# paths to PHP-FPM, which is a known security risk).
try_files $fastcgi_script_name =404;

include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_param HTTPS on;

fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice
fastcgi_param front_controller_active true; # Enable pretty urls
fastcgi_pass php-handler;

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_param HTTPS on; # Assumes TLS terminates here
fastcgi_param modHeadersAvailable true; # Avoid duplicate security headers
fastcgi_param front_controller_active true; # Enable pretty URLs

# Let nginx handle HTTP error responses from PHP-FPM (e.g. custom
# error pages). Disable for debugging if PHP errors are being hidden.
fastcgi_intercept_errors on;
fastcgi_request_buffering on; # Required as PHP-FPM does not support chunked transfer encoding and requires a valid ContentLength header.

# PHP-FPM 504 response timeouts
# Uncomment and increase these if facing timeout errors during large file uploads
# Required for uploads: PHP-FPM does not support chunked
# transfer encoding and needs a Content-Length header.
fastcgi_request_buffering on;

# Optional PHP-FPM timeout tuning (e.g. for 504 response timeouts).
# Increase these only if uploads or long-running PHP requests are
# timing out in your environment.
#fastcgi_read_timeout 60s;
#fastcgi_send_timeout 60s;
#fastcgi_connect_timeout 60s;

# Disable on-disk buffering of FastCGI responses (reduces disk I/O at
# the cost of holding responses in memory).
fastcgi_max_temp_file_size 0;
}

Expand Down