Nginx Configuration
Note: " in the web root" known to work with ownCloud 10.0-10.3 (older/newer versions as well as subdirectory config untested)
Introduction
This page covers example Nginx configurations to use with running an ownCloud server. Note that Nginx is not officially supported, and this page is community-maintained. Thank you, contributors!
- Depending on your setup, you need to insert the code examples into your Nginx configuration file.
- Adjust server_name, root, ssl_certificate, ssl_certificate_key ect. to suit your needs.
- Make sure your SSL certificates are readable by the server (see Nginx HTTP SSL Module documentation).
- Nginx configuration blocks inherit
add_header
directives from their enclosing blocks, so you just need to place theadd_header
directive in the top‑level server block. There’s one important exception:
if a block includes anadd_header
directive itself, it does not inherit headers from enclosing blocks,
and you need to redeclare alladd_header
directives or reinclude them. - Because Nginx does not allow nested if directives, you need to use the map directive.
The position of a location directive connected to the result of themap
directive is important for success.
TIP: For better readability, it is possible and advised to move common add_header
directives into a separate file and include that file wherever necessary. However, each add_header
directive must be written in a single line to prevent connection problems with sync clients.
TIP: The same is true for map
directives which also can be collected into a singe file and then be included.
Example Configurations
CAUTION: Be careful about line breaks if you copy the examples, as long lines may be broken for page formatting.
You can use ownCloud over plain HTTP. However, we strongly encourage you to use SSL/TLS to encrypt all of your server traffic and to protect users’ logins, and their data while it is in transit. To use plain HTTP:
- Remove the server block containing the redirect
- Change
listen 443 ssl http2
tolisten 80;
- Remove all
ssl_
entries. - Remove
fastcgi_params HTTPS on;
Note 1
fastcgi_buffers 8 4K;
- Do not set the number of buffers to greater than 63. In our example, it is set to 8.
- If you exceed this maximum, big file downloads may consume a lot of system memory over time. This is especially problematic on low-memory systems.
Note 2
fastcgi_ignore_headers X-Accel-Buffering
- From ownCloud version 10.0.4 on, a header will be sent to Nginx not to use buffers to avoid problems with problematic
fastcgi_buffers
values. See note above. - If the values of
fastcgi_buffers
are properly set and no problems are expected, you can use this directive to reenable buffering overriding the sent header. - In case you use an earlier version of ownCloud or can´t change the buffers, or can´t remove a existing ignore header directive, you can explicitly enable following directive in the location block
fastcgi_buffering off;
NOTE: The directives fastcgi_ignore_headers X-Accel-Buffering;
and fastcgi_buffering off;
can be used separately but not together.
Note 3
TIP: Raymii.org provides an excellent introduction to strong SSL security measures with Nginx.
ownCloud in the web root of Nginx
The following config should be used when ownCloud is placed in the web root of your Nginx installation.
The configuration assumes that ownCloud is installed in /var/www/owncloud
and is accessed via http(s)://cloud.example.com
.
upstream php-handler {
server 127.0.0.1:9000;
#server unix:/var/run/php7.2-fpm.sock;
}
server {
listen 80;
listen [::]:80;
server_name cloud.example.com;
# For SSL certificate verification, this needs to be served via HTTP
location /.well-known/(acme-challenge|pki-validation)/ {
root /var/www/owncloud; # Specify here where the challenge file is placed
}
# enforce https
location / {
return 301 https://$server_name:443$request_uri; # Change 443 if using a custom HTTPS port
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name cloud.example.com;
ssl_certificate /etc/ssl/nginx/cloud.example.com.crt;
ssl_certificate_key /etc/ssl/nginx/cloud.example.com.key;
# Example SSL/TLS configuration. Please read into the manual of Nginx before applying these.
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "-ALL:EECDH+AES256:EDH+AES256:AES256-SHA:EECDH+AES:EDH+AES:!ADH:!NULL:!aNULL:!eNULL:!EXPORT:!LOW:!MD5:!3DES:!PSK:!SRP:!DSS:!AESGCM:!RC4";
ssl_dhparam /etc/nginx/dh4096.pem;
ssl_prefer_server_ciphers on;
keepalive_timeout 70;
ssl_stapling on;
ssl_stapling_verify on;
# Add headers to serve security related headers
# The always parameter ensures that the header is set for all responses, including internally generated error responses.
# Before enabling Strict-Transport-Security headers please read into this topic first.
# https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
#add_header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Robots-Tag "none" always;
add_header X-Download-Options "noopen" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
# Path to the root of your installation
root /var/www/owncloud/;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location = /.well-known/carddav {
return 301 $scheme://$host:$server_port/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $scheme://$host:$server_port/remote.php/dav;
}
# set max upload size
client_max_body_size 512M;
fastcgi_buffers 8 4K; # Please see note 1
fastcgi_ignore_headers X-Accel-Buffering; # Please see note 2
# Disable gzip to avoid the removal of the ETag header
# Enabling gzip would also make your server vulnerable to BREACH
# if no additional measures are done. See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=773332
gzip off;
# Uncomment if your server is build with the ngx_pagespeed module
# This module is currently not supported.
#pagespeed off;
error_page 403 /core/templates/403.php;
error_page 404 /core/templates/404.php;
location / {
rewrite ^ /index.php$uri;
}
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|changelog|data)/ {
return 404;
}
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console|core/skeleton/) {
return 404;
}
location ~ ^/core/signature\.json {
return 404;
}
location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|oc[sm]-provider/.+|core/templates/40[34])\.php(?:$|/) {
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name; # necessary for ownCloud to detect the contextroot https://github.com/owncloud/core/blob/v10.0.0/lib/private/AppFramework/Http/Request.php#L603
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTPS on;
fastcgi_param modHeadersAvailable true; #Avoid sending the security headers twice
fastcgi_param front_controller_active true;
fastcgi_read_timeout 180; # increase default timeout e.g. for long running carddav/caldav syncs with 1000+ entries
fastcgi_pass php-handler;
fastcgi_intercept_errors on;
fastcgi_request_buffering off; #Available since Nginx 1.7.11
}
location ~ ^/(?:updater|oc[sm]-provider)(?:$|/) {
try_files $uri $uri/ =404;
index index.php;
}
# Adding the cache control header for js and css files
# Make sure it is BELOW the PHP block
location ~ \.(?:css|js)$ {
try_files $uri /index.php$uri$is_args$args;
add_header Cache-Control "max-age=15778463" always;
# Add headers to serve security related headers (It is intended to have those duplicated to the ones above)
# The always parameter ensures that the header is set for all responses, including internally generated error responses.
# Before enabling Strict-Transport-Security headers please read into this topic first.
# https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
#add_header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Robots-Tag "none" always;
add_header X-Download-Options "noopen" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
# Optional: Don't log access to assets
access_log off;
}
location ~ \.(?:svg|gif|png|html|ttf|woff|ico|jpg|jpeg|map|json)$ {
add_header Cache-Control "public, max-age=7200" always;
try_files $uri /index.php$uri$is_args$args;
# Optional: Don't log access to other assets
access_log off;
}
}
ownCloud in a subdirectory of Nginx
The following config should be used when ownCloud is placed under a different context root of your Nginx installation such as /owncloud or /cloud.
The configuration assumes that ownCloud is installed in /var/www/owncloud
is accessed via http(s)://example.com/owncloud
and that you have 'overwriteweb root' => '/owncloud',
set in your config/config.php
.
upstream php-handler {
server 127.0.0.1:9000;
#server unix:/var/run/php7.2-fpm.sock;
}
server {
listen 80;
listen [::]:80;
server_name cloud.example.com;
# For SSL certificate verification, this needs to be served via HTTP
location /.well-known/(acme-challenge|pki-validation)/ {
root /var/www/owncloud; # Specify here where the challenge file is placed
}
# enforce https
location / {
return 301 https://$server_name:443$request_uri; # Change 443 if using a custom HTTPS port
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name cloud.example.com;
ssl_certificate /etc/ssl/nginx/cloud.example.com.crt;
ssl_certificate_key /etc/ssl/nginx/cloud.example.com.key;
# Example SSL/TLS configuration. Please read into the manual of Nginx before applying these.
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "-ALL:EECDH+AES256:EDH+AES256:AES256-SHA:EECDH+AES:EDH+AES:!ADH:!NULL:!aNULL:!eNULL:!EXPORT:!LOW:!MD5:!3DES:!PSK:!SRP:!DSS:!AESGCM:!RC4";
ssl_dhparam /etc/nginx/dh4096.pem;
ssl_prefer_server_ciphers on;
keepalive_timeout 70;
ssl_stapling on;
ssl_stapling_verify on;
# Add headers to serve security related headers
# The always parameter ensures that the header is set for all responses, including internally generated error responses.
# Before enabling Strict-Transport-Security headers please read into this topic first.
# https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
#add_header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Robots-Tag "none" always;
add_header X-Download-Options "noopen" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
# Path to the root of your installation
root /var/www/;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location = /.well-known/carddav {
return 301 $scheme://$host:$server_port/owncloud/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $scheme://$host:$server_port/owncloud/remote.php/dav;
}
location ^~ /owncloud {
# set max upload size
client_max_body_size 512M;
fastcgi_buffers 8 4K; # Please see note 1
fastcgi_ignore_headers X-Accel-Buffering; # Please see note 2
# Disable gzip to avoid the removal of the ETag header
# Enabling gzip would also make your server vulnerable to BREACH
# if no additional measures are done. See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=773332
gzip off;
# Uncomment if your server is build with the ngx_pagespeed module
# This module is currently not supported.
#pagespeed off;
error_page 403 /owncloud/core/templates/403.php;
error_page 404 /owncloud/core/templates/404.php;
location /owncloud {
rewrite ^ /owncloud/index.php$uri;
}
location ~ ^/owncloud/(?:build|tests|config|lib|3rdparty|templates|changelog|data)/ {
return 404;
}
location ~ ^/owncloud/(?:\.|autotest|occ|issue|indie|db_|console|core/skeleton/) {
return 404;
}
location ~ ^/owncloud/core/signature\.json {
return 404;
}
location ~ ^/owncloud/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|oc[sm]-provider/.+|core/templates/40[34])\.php(?:$|/) {
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name; # necessary for ownCloud to detect the context root https://github.com/owncloud/core/blob/v10.0.0/lib/private/AppFramework/Http/Request.php#L603
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTPS on;
fastcgi_param modHeadersAvailable true; #Avoid sending the security headers twice
# EXPERIMENTAL: active the following if you need to get rid of the 'index.php' in the URLs
#fastcgi_param front_controller_active true;
fastcgi_read_timeout 180; # increase default timeout e.g. for long running carddav/caldav syncs with 1000+ entries
fastcgi_pass php-handler;
fastcgi_intercept_errors on;
fastcgi_request_buffering off; #Available since Nginx 1.7.11
}
location ~ ^/owncloud/(?:updater|oc[sm]-provider)(?:$|/) {
try_files $uri $uri/ =404;
index index.php;
}
# Adding the cache control header for js and css files
# Make sure it is BELOW the PHP block
location ~ /owncloud/.*\.(?:css|js) {
try_files $uri /owncloud/index.php$uri$is_args$args;
add_header Cache-Control "max-age=15778463" always;
# Add headers to serve security related headers (It is intended to have those duplicated to the ones above)
# The always parameter ensures that the header is set for all responses, including internally generated error responses.
# Before enabling Strict-Transport-Security headers please read into this topic first.
# https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
#add_header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Robots-Tag "none" always;
add_header X-Download-Options "noopen" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
# Optional: Don't log access to assets
access_log off;
}
location ~ /owncloud/.*\.(?:svg|gif|png|html|ttf|woff|ico|jpg|jpeg|map|json) {
try_files $uri /owncloud/index.php$uri$is_args$args;
add_header Cache-Control "public, max-age=7200" always;
# Optional: Don't log access to other assets
access_log off;
}
}
}