# Nginx sidecar config for the Nextcloud PHP-FPM container. Based on the # Nextcloud admin-manual's recommended config, trimmed to what we need behind # Traefik (no TLS here — Traefik terminates). worker_processes auto; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; sendfile on; tcp_nopush on; tcp_nodelay on; server_tokens off; keepalive_timeout 65; client_max_body_size 10G; # large uploads fastcgi_buffers 64 4K; gzip on; gzip_vary on; gzip_comp_level 4; gzip_min_length 256; gzip_proxied any; 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; # Traefik does the TLS, so Nextcloud sees its forwarded headers. map $http_x_forwarded_proto $forwarded_scheme { default off; https on; } upstream php-handler { server nextcloud-service:9000; } server { listen 80; server_name _; root /var/www/html; # Security headers (Nextcloud expects these; Traefik may also add some) 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; fastcgi_hide_header X-Powered-By; # .well-known redirects (CalDAV / CardDAV / WebFinger / NodeInfo) 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$uri; } location = /.well-known/nodeinfo { return 301 /index.php$uri; } # Block sensitive paths location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; } location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; } index index.php index.html /index.php$request_uri; try_files $uri $uri/ /index.php$request_uri; location ~ \.php(?:$|/) { rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy)/.+\.php$ /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 HTTPS $forwarded_scheme; fastcgi_param modHeadersAvailable true; fastcgi_param front_controller_active true; fastcgi_pass php-handler; fastcgi_intercept_errors on; fastcgi_request_buffering off; fastcgi_read_timeout 300; } location ~ \.(?:css|js|svg|gif|png|jpg|ico|woff2?|otf|wasm|tflite|map|html|json)$ { try_files $uri /index.php$request_uri; expires 6M; access_log off; } } }