Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refine nginx.conf to handle required mime types, well-known, and present pretty URL #88

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
221 changes: 136 additions & 85 deletions nginx.conf
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
user www-data;
worker_processes 1;
user www-data;
worker_processes 1;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
worker_connections 1024;
}

http {

upstream backend {
server app-server:9000;
upstream php-handler {
server app-server:9000;
}

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
#tcp_nopush on;
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;

keepalive_timeout 65;
# Set the "immutable" cache control options only for assets with a cache busting "v" argument
map $arg_v $asset_immutable {
"" "";
default "immutable";
}

# Ensure requests properly pass to onlyoffice
map $http_host $this_host {
"" $host;
default $http_host;
Expand All @@ -40,105 +39,157 @@ http {
}

map $http_x_forwarded_host $the_host {
default $http_x_forwarded_host;
"" $this_host;
default $http_x_forwarded_host;
"" $this_host;
}

server {
listen 80;
# The below allows for being behind a reverse proxy and allowing the Nextcloud app to connect
# Allows for being behind a reverse proxy and allowing the Nextcloud app to connect
server_tokens off;

# Add headers to serve security related headers
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;

root /var/www/html;
client_max_body_size 10G; # 0=unlimited - set max upload size
fastcgi_buffers 64 4K;
# Comment out those handled by proxy
# add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
# add_header X-Content-Type-Options nosniff;
# add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag "noindex, nofollow" always;
add_header X-Download-Options noopen always;
add_header X-Permitted-Cross-Domain-Policies none always;

# Remove X-Powered-By information leak
fastcgi_hide_header X-Powered-By;

root /var/www/html;
client_max_body_size 10G; # 0=unlimited - set max upload size
fastcgi_buffers 64 4K;
client_body_buffer_size 512k;

gzip off;

index index.php;
error_page 403 /core/templates/403.php;
error_page 404 /core/templates/404.php;
# Add .mjs as a file extension for javascript
# Either include it in the default mime.types list
# or you can include that list explicitly and add the file extension
# only for Nextcloud like below:
include mime.types;
types {
text/javascript js mjs;
}

rewrite ^/.well-known/carddav /remote.php/dav/ permanent;
rewrite ^/.well-known/caldav /remote.php/dav/ permanent;
# Specify how to handle directories -- specifying `/index.php$request_uri`
# here as the fallback means that Nginx always exhibits the desired behaviour
# when a client requests a path that corresponds to a directory that exists
# on the server. In particular, if that directory contains an index.php file,
# that file is correctly served; if it doesn't, then the request is passed to
# the front-end controller. This consistent behaviour means that we don't need
# to specify custom rules for certain paths (e.g. images and other assets,
# `/updater`, `/ocs-provider`), and thus
# `try_files $uri $uri/ /index.php$request_uri`
# always provides the desired behaviour.
index index.php index.html /index.php$request_uri;

# Rule borrowed from ".htaccess" to handle Microsoft DAV clients
location = / {
if ( $http_user_agent ~ ^DavClnt ) {
return 302 /remote.php/webdav/$is_args$args;
}
}

location ^~ /.well-known {
location = /.well-known/carddav { return 301 /remote.php/dav/; }
location = /.well-known/caldav { return 301 /remote.php/dav/; }
location = /.well-known/webfinger { return 301 /index.php/.well-known/webfinger/; }
location = /.well-known/nodeinfo { return 301 /index.php/.well-known/nodeinfo/; }

# No required; behind proxy
# location /.well-known/acme-challenge { try_files $uri $uri/ =404; }
# location /.well-known/pki-validation { try_files $uri $uri/ =404; }

# Let Nextcloud's API for "/.well-known" URIs handle all other
# requests by passing them to the front-end controller.
return 301 /index.php$request_uri;
}

location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}

location ~ ^/(build|tests|config|lib|3rdparty|templates|data)/ {
deny all;
}
# Rules borrowed from ".htaccess" to hide certain paths from clients
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; }

location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
deny all;
}
## onlyoffice integration
location ~* ^/ds-vpath/ {
rewrite /ds-vpath/(.*) /$1 break;
proxy_pass http://onlyoffice-document-server;
proxy_redirect off;

location / {
rewrite ^/remote/(.*) /remote.php last;
rewrite ^(/core/doc/[^\/]+/)$ $1/index.html;
try_files $uri $uri/ =404;
}

location ~* ^/ds-vpath/ {
rewrite /ds-vpath/(.*) /$1 break;
proxy_pass http://onlyoffice-document-server;
proxy_redirect off;
client_max_body_size 10G;

client_max_body_size 100m;
proxy_http_version 1.1;

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

proxy_set_header Host $http_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-Host $the_host/ds-vpath;
proxy_set_header X-Forwarded-Proto $the_scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_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-Host $the_host/ds-vpath;
proxy_set_header X-Forwarded-Proto $the_scheme;
}

# 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.
location ~ \.php(?:$|/) {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# Required for legacy support; not required for > 27
# rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri;

fastcgi_split_path_info ^(.+?\.php)(/.*)$;
set $path_info $fastcgi_path_info;

try_files $fastcgi_script_name =404;

include fastcgi_params;

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
fastcgi_param HTTPS off;
fastcgi_param modHeadersAvailable true; #Avoid sending the security headers twice
fastcgi_pass backend;
fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice
fastcgi_param front_controller_active true; # For obfuscating index.php (aka pretty URL)
fastcgi_pass php-handler;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
fastcgi_max_temp_file_size 0;
}

# Adding the cache control header for js and css files
# Make sure it is BELOW the location ~ \.php(?:$|/) { block
location ~* \.(?:css|js)$ {
add_header Cache-Control "public, max-age=7200";
# Add headers to serve security related headers
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
# Optional: Don't log access to assets
access_log off;
# Serve static files
location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map)$ {
try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463, $asset_immutable";
access_log off; # Optional: Don't log access to assets

location ~ \.wasm$ {
default_type application/wasm;
}
}

# Optional: Don't log access to other assets
location ~* \.(?:jpg|jpeg|gif|bmp|ico|png|swf)$ {
access_log off;
location ~ \.woff2?$ {
try_files $uri /index.php$request_uri;
expires 7d; # Cache-Control policy borrowed from ".htaccess"
access_log off; # Optional: Don't log access to assets
}

# Rule borrowed from ".htaccess"
location /remote {
return 301 /remote.php$request_uri;
}

# Pass index.php internally (aka pretty URL)
location / {
try_files $uri $uri/ /index.php$request_uri;
}
}
}