From 7df90179c96a8fd3d8ad662d3d83811b0ab715dc Mon Sep 17 00:00:00 2001 From: Manuel Thalmann Date: Fri, 13 Dec 2024 01:51:47 +0100 Subject: [PATCH] Improve Nextcloud nginx config --- .../docker/services/nextcloud/main.fish | 30 ++++- .../docker/services/nextcloud/nginx/web.conf | 124 ++++++++++-------- 2 files changed, 97 insertions(+), 57 deletions(-) diff --git a/scripts/Common/Software/docker/services/nextcloud/main.fish b/scripts/Common/Software/docker/services/nextcloud/main.fish index bbff0f9d..764f9896 100644 --- a/scripts/Common/Software/docker/services/nextcloud/main.fish +++ b/scripts/Common/Software/docker/services/nextcloud/main.fish @@ -103,19 +103,45 @@ begin printf "%s\0" \ "$name" "^~ /browser" "static files" \ "$name" "^~ /hosting/discovery" "WOPI discovery URL" \ - "$name" "^~ /hosting/capabilities" "Capabilities" \ + "$name" "^~ /hosting/capabilities" Capabilities \ "$name" "~ ^/cool/(.*)/ws\$" "main websocket" \ "$name" "~ ^/(c|l)ool" "download, presentation and image upload" \ "$name" "^~ /cool/adminws" "Admin Console websocket" end end - function getServiceLocationConfig -a domain s location -V office -V flood + function getServiceLocationConfig -a domain s location -V service -V office -V flood if [ "$s" = "$office" ] set -l argv $argv[4..] getServiceDefaultProxy $domain $s "$location" --scheme https $argv else getServiceDefaultProxy $argv --path "$location" + + if [ "$s" = "$service" ] + printf "%s\n" \ + "server_tokens off;" \ + "" \ + "client_max_body_size 512M;" \ + "client_body_timeout 300s;" \ + "fastcgi_buffers 64 4K;" \ + "" \ + "# enable gzip but do not remove ETag headers" \ + "gzip on;" \ + "gzip_vary on;" \ + "gzip_comp_level 4;" \ + "gzip_min_length 256;" \ + "gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;" \ + "gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;" \ + "" \ + "# Pagespeed is not supported by Nextcloud, so if your server is built" \ + "# with the `ngx_pagespeed` module, uncomment this line to disable it." \ + "#pagespeed off;" \ + "" \ + "# The settings allows you to optimize the HTTP2 bandwidth." \ + "# See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/" \ + "# for tuning hints" \ + "client_body_buffer_size 512k;" + end end end diff --git a/scripts/Common/Software/docker/services/nextcloud/nginx/web.conf b/scripts/Common/Software/docker/services/nextcloud/nginx/web.conf index 1f5c9842..19e451ce 100644 --- a/scripts/Common/Software/docker/services/nextcloud/nginx/web.conf +++ b/scripts/Common/Software/docker/services/nextcloud/nginx/web.conf @@ -11,10 +11,6 @@ http { include mime.types; default_type application/octet-stream; - types { - application/javascript cjs mjs; - } - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; @@ -24,50 +20,75 @@ http { server_tokens off; keepalive_timeout 65; + upstream php-handler { + server core:9000; + #server unix:/run/php/php8.2-fpm.sock; + } + # Set the `immutable` cache control options only for assets with a cache busting `v` argument map $arg_v $asset_immutable { "" ""; default "immutable"; } - upstream php-handler { - server core:9000; - } - server { listen 80; + # Path to the root of the domain + root /var/www/html; + + # Prevent nginx HTTP Server Detection + server_tokens off; + + # HSTS settings + # WARNING: Only add the preload option once you read about + # the consequences in https://hstspreload.org/. This option + # will add the domain to a hardcoded list that is shipped + # in all major browsers and getting removed from this list + # could take several months. + #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always; + # set max upload size and increase upload timeout: client_max_body_size 512M; client_body_timeout 300s; fastcgi_buffers 64 4K; - # The settings allow you to optimize the HTTP2 bandwith. + # Enable gzip but do not remove ETag headers + gzip on; + gzip_vary on; + gzip_comp_level 4; + gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; + gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; + + # Pagespeed is not supported by Nextcloud, so if your server is built + # with the `ngx_pagespeed` module, uncomment this line to disable it. + #pagespeed off; + + # The settings allows you to optimize the HTTP2 bandwidth. # See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/ # for tuning hints client_body_buffer_size 512k; - # Enable gzip but do not remove ETag headers - gzip on; - gzip_vary on; - gzip_comp_level 4; - gzip_min_length 256; - gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; - gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; - - # HTTP response headers - add_header Referrer-Policy "no-referrer" always; - add_header X-Content-Type-Options "nosniff" always; - add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-Permitted-Cross-Domain-Policies "none" always; - add_header X-Robots-Tag "noindex, nofollow" always; - add_header X-XSS-Protection "1; mode=block" always; + # HTTP response headers borrowed from Nextcloud `.htaccess` + add_header Referrer-Policy "no-referrer" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Permitted-Cross-Domain-Policies "none" always; + add_header X-Robots-Tag "noindex, nofollow" always; + add_header X-XSS-Protection "1; mode=block" always; # Remove X-Powered-By, which is an information leak fastcgi_hide_header X-Powered-By; - # Path to the root of your installation - root /var/www/html; + # Set .mjs and .wasm MIME types + # Either include it in the default mime.types list + # and include that list explicitly or add the file extension + # only for Nextcloud like below: + include mime.types; + types { + text/javascript mjs; + application/wasm wasm; + } # Specify how to handle directories -- specifying `/index.php$request_uri` # here as the fallback means that Nginx always exhibits the desired behaviour @@ -76,7 +97,7 @@ http { # 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`, `/ocm-provider`, `/ocs-provider`), and thus + # `/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; @@ -98,13 +119,17 @@ http { # access it despite the existence of the regex rule # `location ~ /(\.|autotest|...)` which would otherwise handle requests # for `/.well-known`. + location ^~ /.well-known { # The rules in this block are an adaptation of the rules - # in `.htaccess` that concern `/.well-known`. + # in the Nextcloud `.htaccess` that concern `/.well-known`. location = /.well-known/carddav { return 301 /remote.php/dav/; } location = /.well-known/caldav { return 301 /remote.php/dav/; } + 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; @@ -120,7 +145,7 @@ http { # to the URI, resulting in a HTTP 500 error response. location ~ \.php(?:$|/) { # Required for legacy support - rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri; + rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /index.php$request_uri; fastcgi_split_path_info ^(.+?\.php)(/.*)$; set $path_info $fastcgi_path_info; @@ -132,8 +157,8 @@ http { 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_param modHeadersAvailable true; # Avoid sending the security headers twice + fastcgi_param front_controller_active true; # Enable pretty urls fastcgi_pass php-handler; fastcgi_intercept_errors on; @@ -142,35 +167,24 @@ http { fastcgi_max_temp_file_size 0; } - # Javascript mimetype fixes for nginx - # Note: The block below should be removed, and the js|mjs section should be - # added to the block below this one. This is a temporary fix until Nginx - # upstream fixes the js mime-type - location ~* \.(?:js|mjs)$ { - types { - text/javascript js mjs; - } - - try_files $uri /index.php$request_uri; - add_header Cache-Control "public, max-age=15778463, $asset_immutable"; - access_log off; - } - # Serve static files - location ~ \.(?:css|svg|gif|png|jpg|ico|wasm|tflite|map|ogg|flac)$ { + location ~ \.(?:css|js|mjs|svg|gif|ico|jpg|png|webp|wasm|tflite|map|ogg|flac)$ { 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; - } + # HTTP response headers borrowed from Nextcloud `.htaccess` + add_header Cache-Control "public, max-age=15778463$asset_immutable"; + add_header Referrer-Policy "no-referrer" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Permitted-Cross-Domain-Policies "none" always; + add_header X-Robots-Tag "noindex, nofollow" always; + add_header X-XSS-Protection "1; mode=block" always; + access_log off; # Optional: Don't log access to assets } - location ~ \.woff2?$ { + location ~ \.(otf|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 + expires 7d; # Cache-Control policy borrowed from `.htaccess` + access_log off; # Optional: Don't log access to assets } # Rule borrowed from `.htaccess`