219 lines
7.7 KiB
Plaintext
219 lines
7.7 KiB
Plaintext
# ============================================================
|
||
# Nextcloud - nginx (Docker) default.conf
|
||
# - Single file, no includes, no compose changes
|
||
# - Upstream: nextcloud-fpm-v1:9000
|
||
# - Well-known + OCS/OCM fixes
|
||
# - Collabora prepared (commented)
|
||
# - No HTTP/2 assumptions (host terminates TLS)
|
||
# ============================================================
|
||
|
||
# Upstream PHP-FPM in Docker (keepalive for throughput)
|
||
upstream php_nextcloud {
|
||
server nextcloud-fpm-v1:9000 max_fails=3 fail_timeout=5s;
|
||
keepalive 10;
|
||
}
|
||
|
||
# Upgrade mapping for potential websocket use later (e.g., Collabora)
|
||
map $http_upgrade $connection_upgrade {
|
||
default upgrade;
|
||
'' close;
|
||
}
|
||
|
||
server {
|
||
# App-nginx listens only inside the container
|
||
listen 8080;
|
||
server_name _;
|
||
|
||
# Nextcloud docroot from the mounted volume
|
||
root /var/www/html;
|
||
|
||
# Log to stdout/stderr for `docker logs`
|
||
access_log /dev/stdout;
|
||
error_log /dev/stderr warn;
|
||
|
||
# --- Security headers (HSTS/OCSP etc. should be handled by host proxy) ---
|
||
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;
|
||
fastcgi_hide_header X-Powered-By;
|
||
|
||
# Fix für Nextcloud Self-Tests (PHP curl intern)
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Forwarded-Proto https;
|
||
proxy_set_header X-Forwarded-Ssl on;
|
||
|
||
# --- Client / FastCGI tuning ---
|
||
# Match your PHP env (PHP_UPLOAD_LIMIT=10G)
|
||
client_max_body_size 10g;
|
||
fastcgi_buffers 64 4k;
|
||
fastcgi_read_timeout 3600s;
|
||
fastcgi_send_timeout 3600s;
|
||
fastcgi_request_buffering off;
|
||
gzip off; # per Nextcloud recommendation (preserve ETag)
|
||
|
||
# --- Docker internal resolver for self-connect checks ---
|
||
resolver 127.0.0.11 valid=30s;
|
||
resolver_timeout 5s;
|
||
|
||
# --- Real client IP from host reverse proxy ---
|
||
set_real_ip_from 0.0.0.0/0;
|
||
real_ip_header X-Forwarded-For;
|
||
|
||
# --- Minimal type additions for modern JS & sourcemaps ---
|
||
# (keine globalen mime.types nötig – wir ergänzen nur, was gebraucht wird)
|
||
types {
|
||
font/otf otf;
|
||
text/html html htm shtml;
|
||
text/css css;
|
||
text/javascript js;
|
||
application/javascript mjs;
|
||
application/json json;
|
||
application/manifest+json webmanifest;
|
||
application/wasm wasm;
|
||
application/octet-stream map;
|
||
font/woff woff;
|
||
font/woff2 woff2;
|
||
image/svg+xml svg;
|
||
image/png png;
|
||
image/jpeg jpg jpeg;
|
||
image/gif gif;
|
||
text/plain txt;
|
||
}
|
||
|
||
# --- Serve .mjs and .js.map correctly (fixes admin checks) ---
|
||
location ~* \.mjs$ {
|
||
default_type application/javascript;
|
||
try_files $uri $uri/ =404;
|
||
access_log off;
|
||
expires 1d;
|
||
}
|
||
location ~* \.js\.map$ {
|
||
default_type application/octet-stream;
|
||
try_files $uri =404;
|
||
access_log off;
|
||
expires 1d;
|
||
}
|
||
|
||
# --- robots.txt ---
|
||
location = /robots.txt {
|
||
allow all;
|
||
log_not_found off;
|
||
access_log off;
|
||
}
|
||
|
||
# --- .well-known handling (webfinger + cal/carddav + generic) ---
|
||
location ~ ^/\.well-known/(acme-challenge/.*)$ { allow all; }
|
||
location = /.well-known/carddav { return 301 $scheme://$host/remote.php/dav; }
|
||
location = /.well-known/caldav { return 301 $scheme://$host/remote.php/dav; }
|
||
location ^~ /.well-known { return 301 /index.php$uri; }
|
||
location = /.well-known/webfinger { return 301 /index.php$uri; }
|
||
|
||
# --- Deny sensitive dirs, as per Nextcloud docs ---
|
||
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ { deny all; }
|
||
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { deny all; }
|
||
|
||
# ============================================================
|
||
# OCS/OCM PROVIDER FIXES
|
||
# ------------------------------------------------------------
|
||
# 1) Some NC checks expect /ocs-provider/ to return a valid JSON.
|
||
# We provide a tiny static JSON (no PHP needed), satisfying the check.
|
||
location = /ocs-provider/ {
|
||
default_type application/json;
|
||
return 200 '{"version":"1.0","status":"ok"}';
|
||
}
|
||
location = /ocs-provider/index.php {
|
||
default_type application/json;
|
||
return 200 '{"version":"1.0","status":"ok"}';
|
||
}
|
||
|
||
# 2) Ensure ocs/ocm provider paths resolve to index.php for dynamic routes.
|
||
location ~ ^/(?:ocs-provider|ocm-provider)(?:$|/) {
|
||
try_files $uri /index.php$uri$is_args$args;
|
||
}
|
||
# ============================================================
|
||
|
||
# --- Main entry: route everything through front controller ---
|
||
location / {
|
||
rewrite ^ /index.php;
|
||
}
|
||
|
||
# --- PHP handling: main Nextcloud endpoints ---
|
||
location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|oc[sm]-provider/.+|core/templates/40[34])\.php(?:$|/) {
|
||
include fastcgi_params;
|
||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||
try_files $fastcgi_script_name =404;
|
||
|
||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||
|
||
# avoid duplicate security headers
|
||
fastcgi_param modHeadersAvailable true;
|
||
fastcgi_param front_controller_active true;
|
||
|
||
fastcgi_pass php_nextcloud;
|
||
fastcgi_intercept_errors on;
|
||
}
|
||
|
||
location ^~ /apps/ {
|
||
try_files $uri /index.php$request_uri;
|
||
}
|
||
|
||
|
||
# --- Static assets caching (below PHP block) ---
|
||
location ~* \.(?:css|js)$ {
|
||
try_files $uri /index.php$uri$is_args$args;
|
||
add_header Cache-Control "public, max-age=7200";
|
||
add_header X-Content-Type-Options nosniff;
|
||
add_header X-XSS-Protection "1; mode=block";
|
||
access_log off;
|
||
expires 2h;
|
||
}
|
||
location ~ \.woff2?$ {
|
||
try_files $uri /index.php$request_uri;
|
||
expires 7d;
|
||
access_log off;
|
||
}
|
||
location ~* \.(?:svg|gif|png|html|ttf|woff|ico|jpg|jpeg)$ {
|
||
try_files $uri /index.php$uri$is_args$args;
|
||
access_log off;
|
||
expires 7d;
|
||
}
|
||
|
||
# ------------------------------------------------------------
|
||
# Collabora (prepared; keep commented until subdomain is live)
|
||
# ------------------------------------------------------------
|
||
# location ^~ /loleaflet {
|
||
# proxy_pass https://collabora.knusperkerne.de;
|
||
# proxy_set_header Host $http_host;
|
||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
# proxy_set_header X-Forwarded-Proto $scheme;
|
||
# proxy_set_header X-Real-IP $remote_addr;
|
||
# proxy_set_header Upgrade $http_upgrade;
|
||
# proxy_set_header Connection $connection_upgrade;
|
||
# proxy_read_timeout 3600s;
|
||
# proxy_buffering off;
|
||
# }
|
||
# location ^~ /lool {
|
||
# proxy_pass https://collabora.knusperkerne.de;
|
||
# proxy_set_header Host $http_host;
|
||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
# proxy_set_header X-Forwarded-Proto $scheme;
|
||
# proxy_set_header X-Real-IP $remote_addr;
|
||
# proxy_set_header Upgrade $http_upgrade;
|
||
# proxy_set_header Connection $connection_upgrade;
|
||
# proxy_http_version 1.1;
|
||
# proxy_read_timeout 3600s;
|
||
# proxy_buffering off;
|
||
# }
|
||
|
||
# Simple health endpoint
|
||
location = /health {
|
||
return 200 'ok';
|
||
add_header Content-Type text/plain;
|
||
}
|
||
}
|