From 2487ddc80294edc986579ec04100bd2bc50f0e3c Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Sat, 22 Aug 2026 16:33:33 -0300 Subject: [PATCH] chore: update nginx.conf Make the Nginx config more similar to config made at Nextcloud admin doc. Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .docker/nginx/config/common.conf | 129 -------------- .docker/nginx/config/http.conf | 6 - .docker/nginx/config/https.conf | 16 -- .docker/nginx/config/nextcloud.conf | 263 ++++++++++++++++++++++++++++ .docker/nginx/nginx.conf | 42 ++--- 5 files changed, 280 insertions(+), 176 deletions(-) delete mode 100644 .docker/nginx/config/common.conf delete mode 100644 .docker/nginx/config/http.conf delete mode 100644 .docker/nginx/config/https.conf create mode 100644 .docker/nginx/config/nextcloud.conf diff --git a/.docker/nginx/config/common.conf b/.docker/nginx/config/common.conf deleted file mode 100644 index 5ba796c..0000000 --- a/.docker/nginx/config/common.conf +++ /dev/null @@ -1,129 +0,0 @@ -# Common configuration for both HTTP and HTTPS - -# Add headers to serve security related headers -add_header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload;" always; - -# set max upload size -client_max_body_size 20G; -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; - -# The settings allows you to optimize the HTTP2 bandwidth -client_body_buffer_size 512k; - -# 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-Download-Options "noopen" 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; - -# Add .mjs as a file extension for javascript -include mime.types; -types { - application/javascript mjs; -} - -# Specify how to handle directories -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 = /robots.txt { - allow all; - log_not_found off; - access_log off; -} - -# Make a regex exception for `/.well-known` so that clients can still -# access it despite the existence of the regex rule -location ^~ /.well-known { - # The rules in this block are an adaptation of the rules - # in `.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; -} - -# 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; } - -# 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(?:$|/) { - # 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; - - 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 $path_info; - - fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice - fastcgi_param front_controller_active true; # Enable pretty urls - fastcgi_pass php-backend; - - fastcgi_intercept_errors on; - fastcgi_request_buffering off; - - fastcgi_max_temp_file_size 0; -} - -# Serve static files -location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map|ogg|flac)$ { - try_files $uri /index.php$request_uri; - add_header Cache-Control "public, max-age=15778463"; - access_log off; # Optional: Don't log access to assets - - location ~ \.wasm$ { - default_type application/wasm; - } -} - -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; -} - -location / { - try_files $uri $uri/ /index.php$request_uri; -} diff --git a/.docker/nginx/config/http.conf b/.docker/nginx/config/http.conf deleted file mode 100644 index f7bd926..0000000 --- a/.docker/nginx/config/http.conf +++ /dev/null @@ -1,6 +0,0 @@ -server { - listen 80; - include /etc/nginx/conf.d/includes/*.conf; - - include /etc/nginx/conf.d/common.conf; -} diff --git a/.docker/nginx/config/https.conf b/.docker/nginx/config/https.conf deleted file mode 100644 index 731f32a..0000000 --- a/.docker/nginx/config/https.conf +++ /dev/null @@ -1,16 +0,0 @@ -server { - listen 443 ssl; - http2 on; - large_client_header_buffers 4 16k; - - ssl_certificate /certs/nextcloud.pem; - ssl_certificate_key /certs/nextcloud.pem; - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; - - include /etc/nginx/conf.d/includes/*.conf; - - include /etc/nginx/conf.d/common.conf; -} - - diff --git a/.docker/nginx/config/nextcloud.conf b/.docker/nginx/config/nextcloud.conf new file mode 100644 index 0000000..1476601 --- /dev/null +++ b/.docker/nginx/config/nextcloud.conf @@ -0,0 +1,263 @@ +# Nextcloud nginx configuration — root installation +# Version 2026-06-09 +# +# Upstream: +# https://github.com/nextcloud/documentation/blob/master/admin_manual/installation/nginx-root.conf.sample + +# PHP-FPM backend. +upstream php-handler { + # Use one of the options below, not both: + # LIBRECODE DEV: PHP-FPM runs in the Nextcloud Docker service. + server nextcloud: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"; +} + +# LIBRECODE DEV: HTTP and HTTPS are intentionally served by the same +# virtual host instead of redirecting HTTP to HTTPS. +server { + listen 80; + listen [::]:80; + listen 443 ssl; + listen [::]:443 ssl; + http2 on; + + # LIBRECODE DEV + server_name localhost *.localhost; + + # Path to the root of your installation + # LIBRECODE DEV: Nextcloud source is mounted here in the container to preseve the Nginx default folder. + root /var/www/html; + + # Use Mozilla's guidelines for SSL/TLS settings + # https://mozilla.github.io/server-side-tls/ssl-config-generator/ + # LIBRECODE DEV: self-signed certificate generated by nginx-entrypoint.sh. + ssl_certificate /certs/nextcloud.pem; + ssl_certificate_key /certs/nextcloud.pem; + + # 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=31536000; includeSubDomains; preload" always; + + # set max upload size and increase upload timeout: + # LIBRECODE DEV: larger limit used by this development environment. + client_max_body_size 20G; + client_body_timeout 300s; + fastcgi_buffers 64 4K; + + # Proxy and client response timeouts + # Uncomment an increase these if facing timeout errors during large file uploads + #keepalive_timeout 60s; + #proxy_connect_timeout 60s; + #proxy_send_timeout 60s; + #proxy_read_timeout 60s; + #send_timeout 60s; + + # 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; + + # 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; + + # Remove X-Powered-By, which is an information leak + fastcgi_hide_header X-Powered-By; + + # 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 + # 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 = /robots.txt { + allow all; + log_not_found off; + access_log off; + } + + # Make a regex exception for `/.well-known` so that clients can still + # 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`. + + 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; + } + + # 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; } + + # Hide metadata files which would otherwise be served as plain files and + # leak dependency information (composer.json, package.json, core/shipped.json). + location ~ ^/(?:composer\.(?:json|lock)|package(?:-lock)?\.json|core/shipped\.json)$ { return 404; } + + # 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(?:$|/) { + # 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: + # - $fastcgi_script_name: `/file.php` + # - $fastcgi_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; # 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_pass php-handler; + + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $path_info; + # LIBRECODE DEV: support both HTTP and HTTPS instead of assuming TLS. + fastcgi_param HTTPS $https; + 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; + + # 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; + } + + # Serve static files + location ~ \.(?:css|js|mjs|svg|gif|ico|jpg|png|webp|wasm|tflite|map|ogg|flac|mp4|webm)$ { + try_files $uri /index.php$request_uri; + + # 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=31536000; includeSubDomains; preload" always; + + # 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; + access_log off; # Optional: Don't log access to assets + } + + 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 + } + + # Rule borrowed from `.htaccess` + location /remote { + return 301 /remote.php$request_uri; + } + + # LIBRECODE DEV: optional development-specific nginx snippets. + include /etc/nginx/conf.d/includes/*.conf; + + location / { + try_files $uri $uri/ /index.php$request_uri; + } +} diff --git a/.docker/nginx/nginx.conf b/.docker/nginx/nginx.conf index eace938..2adf446 100644 --- a/.docker/nginx/nginx.conf +++ b/.docker/nginx/nginx.conf @@ -1,38 +1,30 @@ worker_processes auto; -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 { - disable_symlinks off; - server_tokens off; + include /etc/nginx/mime.types; + default_type application/octet-stream; - 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"'; - 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; - access_log /var/log/nginx/access.log main; + sendfile on; + keepalive_timeout 65; - sendfile on; - keepalive_timeout 65; + # Docker private networks. + set_real_ip_from 10.0.0.0/8; + set_real_ip_from 172.16.0.0/12; + set_real_ip_from 192.168.0.0/16; + real_ip_header X-Real-IP; - set_real_ip_from 10.0.0.0/8; - set_real_ip_from 172.16.0.0/12; - set_real_ip_from 192.168.0.0/16; - real_ip_header X-Real-IP; - - upstream php-backend { - server nextcloud:9000; - } - - # Load HTTP and HTTPS server configurations - include /etc/nginx/conf.d/http.conf; - include /etc/nginx/conf.d/https.conf; + include /etc/nginx/conf.d/nextcloud.conf; }