Update nginx.conf
my last
This commit is contained in:
316
nginx.conf
316
nginx.conf
@@ -1,164 +1,306 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# Full nginx.conf for Nextcloud running in Docker BEHIND an external
|
||||||
|
# SSL-terminating reverse proxy (at 192.168.0.215).
|
||||||
|
#
|
||||||
|
# - This Nginx instance listens on HTTP/80.
|
||||||
|
# - It serves Nextcloud directly using PHP-FPM from the 'nextcloud:9000' container.
|
||||||
|
# - It trusts headers forwarded by the external proxy.
|
||||||
|
# - NO SSL configuration is needed here.
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
user www-data;
|
user www-data;
|
||||||
|
# Use 'auto' or set to the number of CPU cores available to the container
|
||||||
worker_processes auto;
|
worker_processes auto;
|
||||||
error_log /var/log/nginx/error.log warn;
|
|
||||||
pid /var/run/nginx.pid;
|
# Standard error log and PID file paths within the container
|
||||||
|
error_log /var/log/nginx/error.log warn;
|
||||||
|
pid /var/run/nginx.pid;
|
||||||
|
|
||||||
events {
|
events {
|
||||||
|
# Adjust worker_connections based on expected load
|
||||||
worker_connections 1024;
|
worker_connections 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
http {
|
http {
|
||||||
# Basic settings
|
# Include standard MIME types
|
||||||
include /etc/nginx/mime.types;
|
include /etc/nginx/mime.types;
|
||||||
default_type application/octet-stream;
|
default_type application/octet-stream;
|
||||||
server_tokens off;
|
|
||||||
|
|
||||||
# Additional MIME types
|
# Custom MIME types - Enhanced for MJS support
|
||||||
types {
|
types {
|
||||||
application/javascript mjs;
|
image/x-raw raw;
|
||||||
|
image/x-sony-arw arw;
|
||||||
|
application/javascript mjs; # Ensure MJS has proper MIME type
|
||||||
}
|
}
|
||||||
|
|
||||||
# Logging
|
# Double-check the MIME type mapping by adding it globally
|
||||||
access_log /var/log/nginx/access.log combined;
|
map $uri $javascript_module {
|
||||||
error_log /var/log/nginx/error.log error;
|
~\.mjs$ "application/javascript";
|
||||||
|
default "";
|
||||||
|
}
|
||||||
|
|
||||||
# Gzip compression
|
# ==================================================
|
||||||
gzip on;
|
# Proxy Handling & Real IP Configuration
|
||||||
gzip_vary on;
|
# ==================================================
|
||||||
gzip_comp_level 4;
|
# Define the IP of the trusted external reverse proxy
|
||||||
gzip_min_length 256;
|
set_real_ip_from 192.168.0.215;
|
||||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
|
# Specify the header containing the client's real IP
|
||||||
|
real_ip_header X-Forwarded-For;
|
||||||
|
# Use 'on' if the proxy might add multiple IPs (e.g., X-Forwarded-For: client, proxy1)
|
||||||
|
# real_ip_recursive on;
|
||||||
|
|
||||||
# Upstream PHP handler
|
# ==================================================
|
||||||
|
# Logging Configuration
|
||||||
|
# ==================================================
|
||||||
|
# Log format including the forwarded-for header.
|
||||||
|
# If realip module works, $remote_addr will show the real client IP.
|
||||||
|
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;
|
||||||
|
|
||||||
|
# ==================================================
|
||||||
|
# Performance & Security Defaults
|
||||||
|
# ==================================================
|
||||||
|
server_tokens off; # Hide nginx version
|
||||||
|
sendfile on; # Use efficient file transfer
|
||||||
|
tcp_nopush on; # Optimize packet sending
|
||||||
|
tcp_nodelay on; # Reduce latency for keep-alive
|
||||||
|
keepalive_timeout 65; # Keep connections open longer
|
||||||
|
|
||||||
|
# Helper map for cache control (retained from original)
|
||||||
|
map $arg_v $asset_immutable {
|
||||||
|
"" "";
|
||||||
|
default ", immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==================================================
|
||||||
|
# Upstream PHP-FPM Definition
|
||||||
|
# ==================================================
|
||||||
|
# Define the Nextcloud application container running PHP-FPM
|
||||||
upstream php-handler {
|
upstream php-handler {
|
||||||
|
# Use the Docker service name and port
|
||||||
server nextcloud:9000;
|
server nextcloud:9000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ==================================================
|
||||||
|
# Main Server Block (Listens on HTTP/80)
|
||||||
|
# ==================================================
|
||||||
server {
|
server {
|
||||||
listen 80 default_server;
|
# Listen on port 80 within the container network
|
||||||
listen [::]:80 default_server;
|
listen 80;
|
||||||
server_name gabenszip.com;
|
# listen [::]:80; # Uncomment if using IPv6 internally
|
||||||
|
|
||||||
# Path to webroot
|
# Optional: Set server name (domain used publicly)
|
||||||
root /var/www/html;
|
# server_name cloud.example.com; # <<< Your public Nextcloud domain
|
||||||
|
|
||||||
# Max upload size
|
# --- Basic Settings ---
|
||||||
client_max_body_size 10G;
|
# Set maximum allowed size for uploaded files
|
||||||
|
client_max_body_size 512M; # Adjust as needed
|
||||||
|
# Set timeout for reading client request body
|
||||||
client_body_timeout 300s;
|
client_body_timeout 300s;
|
||||||
|
# FastCGI buffer settings for PHP communication
|
||||||
fastcgi_buffers 64 4K;
|
fastcgi_buffers 64 4K;
|
||||||
|
client_body_buffer_size 512k; # Buffer for client request body
|
||||||
|
|
||||||
# Enable gzip but do not remove ETag headers
|
# --- Gzip Compression ---
|
||||||
gzip on;
|
gzip on;
|
||||||
gzip_vary on;
|
gzip_vary on;
|
||||||
gzip_comp_level 4;
|
gzip_comp_level 4; # Balance between CPU and compression ratio
|
||||||
gzip_min_length 256;
|
gzip_min_length 256; # Don't compress very small files
|
||||||
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
|
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; # Compress even for proxied requests
|
||||||
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject 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;
|
# Define types of files to compress
|
||||||
|
gzip_types
|
||||||
|
application/atom+xml 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
|
# --- Security Headers ---
|
||||||
add_header Referrer-Policy "no-referrer" always;
|
# These add defense-in-depth. HSTS should be set on the external proxy (192.168.0.215).
|
||||||
add_header X-Content-Type-Options "nosniff" always;
|
# add_header Strict-Transport-Security "max-age=..." always; # DO NOT set HSTS here
|
||||||
add_header X-Download-Options "noopen" always;
|
add_header Referrer-Policy "no-referrer" always;
|
||||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
add_header X-Permitted-Cross-Domain-Policies "none" always;
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
add_header X-Robots-Tag "noindex, nofollow" always;
|
add_header X-Permitted-Cross-Domain-Policies "none" always;
|
||||||
add_header X-XSS-Protection "1; mode=block" always;
|
add_header X-Robots-Tag "noindex, nofollow" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
# Content Security Policy (retained from original - review if suitable)
|
||||||
|
add_header Content-Security-Policy "frame-ancestors 'self'; connect-src 'self' blob: stun.nextcloud.com:443 wss://gabenszip.com https://gabenszip.com http://gabenszip.com ws://gabenszip.com gabenszip.com:* 'unsafe-eval' 'unsafe-inline'" always;
|
||||||
|
|
||||||
# Remove X-Powered-By, which is an information leak
|
# Hide PHP's "X-Powered-By" header
|
||||||
fastcgi_hide_header X-Powered-By;
|
fastcgi_hide_header X-Powered-By;
|
||||||
|
|
||||||
# Specify how to handle directories -- first look for an index.html file
|
# --- Document Root ---
|
||||||
|
# IMPORTANT: Adjust this path if your Nextcloud files are mounted elsewhere in this container
|
||||||
|
root /var/www/html;
|
||||||
|
# Define default index files
|
||||||
index index.php index.html /index.php$request_uri;
|
index index.php index.html /index.php$request_uri;
|
||||||
|
|
||||||
# Rule borrowed from `.htaccess` to handle Microsoft DAV clients
|
# --- Location Blocks ---
|
||||||
location = / {
|
|
||||||
if ( $http_user_agent ~ ^DavClnt ) {
|
# Deny access to sensitive files/directories
|
||||||
return 302 /remote.php/webdav/$is_args$args;
|
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; }
|
||||||
}
|
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; }
|
||||||
|
|
||||||
|
# Handle /.well-known requests for service discovery (CalDAV, CardDAV, etc.)
|
||||||
|
location ^~ /.well-known {
|
||||||
|
location = /.well-known/carddav { return 301 /remote.php/dav/; }
|
||||||
|
location = /.well-known/caldav { return 301 /remote.php/dav/; }
|
||||||
|
# ACME challenges usually handled by external proxy, otherwise allow here if needed
|
||||||
|
location ~ ^/\.well-known/(acme-challenge|pki-validation)/ { allow all; }
|
||||||
|
# Let Nextcloud handle other .well-known requests via PHP
|
||||||
|
return 301 /index.php$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Special handling for Microsoft DAV clients hitting the root
|
||||||
|
location = / {
|
||||||
|
if ($http_user_agent ~ ^DavClnt) {
|
||||||
|
return 302 /remote.php/webdav/$is_args$args;
|
||||||
|
}
|
||||||
|
# If not DAV, fallback to PHP front controller
|
||||||
|
try_files $uri $uri/ /index.php$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Robots.txt - allow access
|
||||||
location = /robots.txt {
|
location = /robots.txt {
|
||||||
allow all;
|
allow all;
|
||||||
log_not_found off;
|
log_not_found off;
|
||||||
access_log off;
|
access_log off;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Make a regex exception for `/.well-known` so that clients can still
|
# Enhanced handling for JavaScript module files (.mjs)
|
||||||
# access it despite the existence of the regex rule
|
location ~* \.mjs$ {
|
||||||
# `location ~ /(\.|autotest|...)` which would otherwise handle requests
|
# Multiple methods to ensure correct Content-Type header
|
||||||
# for `/.well-known`.
|
types { application/javascript mjs; }
|
||||||
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/; }
|
# Force the correct MIME type
|
||||||
location = /.well-known/caldav { return 301 /remote.php/dav/; }
|
default_type application/javascript;
|
||||||
|
|
||||||
location /.well-known/acme-challenge { try_files $uri $uri/ =404; }
|
# Explicitly set Content-Type header
|
||||||
location /.well-known/pki-validation { try_files $uri $uri/ =404; }
|
add_header Content-Type application/javascript always;
|
||||||
|
|
||||||
# Let Nextcloud's API for `/.well-known` URIs handle all other
|
# Override any default Content-Type
|
||||||
# requests by passing them to the front-end controller.
|
if ($javascript_module) {
|
||||||
return 301 /index.php$request_uri;
|
add_header Content-Type $javascript_module always;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Try serving file directly, else pass to PHP
|
||||||
|
try_files $uri /index.php$request_uri;
|
||||||
|
|
||||||
|
# Caching headers
|
||||||
|
add_header Cache-Control "public, max-age=15778463$asset_immutable";
|
||||||
|
|
||||||
|
# Add security 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;
|
||||||
|
add_header Content-Security-Policy "frame-ancestors 'self'; connect-src 'self' blob: stun.nextcloud.com:443 wss://gabenszip.com https://gabenszip.com http://gabenszip.com ws://gabenszip.com gabenszip.com:* 'unsafe-eval' 'unsafe-inline'" always;
|
||||||
|
|
||||||
|
# Disable access logging for static files
|
||||||
|
access_log off;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Rules borrowed from `.htaccess` to hide certain paths from clients
|
# Main PHP processing block
|
||||||
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(?:$|/) {
|
location ~ \.php(?:$|/) {
|
||||||
# Required for legacy support
|
# Security rewrite: Prevent direct access to PHP files except known endpoints
|
||||||
rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-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;
|
||||||
|
|
||||||
|
# Split path info for PHP (e.g., /index.php/foo/bar)
|
||||||
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
|
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
|
||||||
set $path_info $fastcgi_path_info;
|
set $path_info $fastcgi_path_info;
|
||||||
|
|
||||||
|
# Try the script itself, otherwise return 404
|
||||||
try_files $fastcgi_script_name =404;
|
try_files $fastcgi_script_name =404;
|
||||||
|
|
||||||
|
# Include standard FastCGI parameters
|
||||||
include fastcgi_params;
|
include fastcgi_params;
|
||||||
|
|
||||||
|
# --- Crucial FastCGI Parameters ---
|
||||||
|
# Set script filename and path info
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
fastcgi_param PATH_INFO $path_info;
|
fastcgi_param PATH_INFO $path_info;
|
||||||
fastcgi_param HTTPS on;
|
|
||||||
|
|
||||||
fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice
|
# HTTPS handling
|
||||||
fastcgi_param front_controller_active true; # Enable pretty urls
|
fastcgi_param HTTPS off; # Let Nextcloud config handle the protocol
|
||||||
|
|
||||||
|
# Force protocol settings to use HTTP (not HTTPS)
|
||||||
|
fastcgi_param HTTP_X_FORWARDED_PROTO http;
|
||||||
|
fastcgi_param REQUEST_SCHEME http;
|
||||||
|
|
||||||
|
# Pass the client's real IP address to PHP
|
||||||
|
fastcgi_param REMOTE_ADDR $remote_addr;
|
||||||
|
|
||||||
|
# Pass other useful headers from the proxy (ensure proxy sets them!)
|
||||||
|
fastcgi_param HTTP_X_FORWARDED_FOR $http_x_forwarded_for;
|
||||||
|
|
||||||
|
# Pass host header
|
||||||
|
fastcgi_param HTTP_HOST $http_host;
|
||||||
|
|
||||||
|
# Parameters for Nextcloud pretty URLs and header management
|
||||||
|
fastcgi_param modHeadersAvailable true;
|
||||||
|
fastcgi_param front_controller_active true;
|
||||||
|
|
||||||
|
# Send request to the PHP-FPM upstream handler defined earlier
|
||||||
fastcgi_pass php-handler;
|
fastcgi_pass php-handler;
|
||||||
|
|
||||||
fastcgi_intercept_errors on;
|
# --- Performance & Error Handling ---
|
||||||
fastcgi_request_buffering off;
|
fastcgi_intercept_errors on; # Let Nginx handle PHP errors (e.g., show custom 50x page)
|
||||||
|
fastcgi_request_buffering off; # Disable buffering for long-running scripts/uploads
|
||||||
fastcgi_max_temp_file_size 0;
|
fastcgi_max_temp_file_size 0; # Prevent writing large uploads to temp files
|
||||||
fastcgi_read_timeout 3600;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Serve static files
|
# Serve static files (CSS, JS, images, including custom types)
|
||||||
location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map)$ {
|
location ~* \.(?:css|js|svg|gif|ico|jpe?g|png|webp|wasm|tflite|map|ogg|flac|arw|raw)$ {
|
||||||
|
# Try to serve file directly, else pass to PHP (e.g., for theming)
|
||||||
try_files $uri /index.php$request_uri;
|
try_files $uri /index.php$request_uri;
|
||||||
add_header Cache-Control "public, max-age=15778463";
|
# Caching headers
|
||||||
access_log off; # Optional: Don't log access to assets
|
add_header Cache-Control "public, max-age=15778463$asset_immutable";
|
||||||
|
# Add security headers (can potentially be inherited)
|
||||||
|
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;
|
||||||
|
# Disable access logging for static files
|
||||||
|
access_log off;
|
||||||
|
|
||||||
|
# Specific MIME type for WebAssembly if needed explicitly
|
||||||
location ~ \.wasm$ {
|
location ~ \.wasm$ {
|
||||||
default_type application/wasm;
|
default_type application/wasm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ \.woff2?$ {
|
# Serve font files with longer expiry
|
||||||
|
location ~ \.(?:woff2?|ttf|eot)$ {
|
||||||
|
# Try to serve file directly, else pass to PHP
|
||||||
try_files $uri /index.php$request_uri;
|
try_files $uri /index.php$request_uri;
|
||||||
expires 7d; # Cache-Control policy borrowed from `.htaccess`
|
# Caching headers (fonts rarely change)
|
||||||
access_log off; # Optional: Don't log access to assets
|
add_header Cache-Control "public, max-age=15778463$asset_immutable";
|
||||||
|
expires 7d; # Alternative cache control
|
||||||
|
# Add security headers (can potentially be inherited)
|
||||||
|
add_header Referrer-Policy "no-referrer" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
# Disable access logging for static files
|
||||||
|
access_log off;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Rule borrowed from `.htaccess`
|
# Redirect for /remote endpoint used by some clients
|
||||||
location /remote {
|
location /remote {
|
||||||
return 301 /remote.php$request_uri;
|
return 301 /remote.php$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Fallback location - pass everything else to the PHP front controller
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.php$request_uri;
|
try_files $uri $uri/ /index.php$request_uri;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
} # End server block (port 80)
|
||||||
|
} # End http block
|
||||||
Reference in New Issue
Block a user