mirror of
https://github.com/projectsend/projectsend.git
synced 2026-10-07 22:01:21 +00:00
f9e08412f2
#1804 dropped every /up request from the nginx access log, so the container's health checks stopped flooding `docker logs`. That also hid the failing ones: when the container goes unhealthy, the 5xx from /up is the line someone looks for, and Docker's health status alone does not say why. Key the map on the status as well as the path, so only a 2xx /up is dropped. Verified against the 2.6.0 image: a 503 /up logs, a 200 /up does not, and a 200 /upload still logs.
96 lines
4.0 KiB
Nginx Configuration File
96 lines
4.0 KiB
Nginx Configuration File
# Production server block for the official image.
|
|
#
|
|
# Kept deliberately close to docker/web/nginx.conf — the dev stack's config
|
|
# — because the security properties below were reviewed as a set. Two
|
|
# differences, both forced by this
|
|
# being one container instead of two:
|
|
#
|
|
# 1. fastcgi_pass targets 127.0.0.1, not the `app` compose service.
|
|
# 2. There is no user/uid coordination to do here, because the Dockerfile
|
|
# has already done it: it points the `user` directive in the package's
|
|
# own nginx.conf at www-data, so nginx and php-fpm are the same user
|
|
# and storage/ needs no group juggling. Without that step nginx runs
|
|
# as the alpine package's `nginx` (uid 100) and cannot read what
|
|
# php-fpm just wrote — see the comment on that line.
|
|
|
|
# The image's HEALTHCHECK hits /up every 30 seconds, which buried
|
|
# `docker logs` under two lines per check. Drop a passing check from the
|
|
# access log; a failing one (anything but a 2xx) still logs, because that
|
|
# is the line someone reads when the container goes unhealthy.
|
|
map "$request_uri:$status" $loggable {
|
|
~^/up:2 0;
|
|
default 1;
|
|
}
|
|
|
|
server {
|
|
listen 80 default_server;
|
|
server_name _;
|
|
root /var/www/html/public;
|
|
index index.php;
|
|
|
|
# Overrides the http-level access_log only to apply $loggable above.
|
|
access_log /dev/stdout main if=$loggable;
|
|
|
|
# Uploads arrive in chunks (Uppy resumable), so this caps a single
|
|
# chunk, not a file. Raising it does not raise the maximum file size.
|
|
client_max_body_size 100m;
|
|
|
|
# The nginx version number is nobody's business but ours — matches
|
|
# docker/web/nginx.conf.
|
|
server_tokens off;
|
|
|
|
# Baseline hardening for every response. `always` so they survive error
|
|
# responses too. NOTE: nginx does not merge add_header across levels —
|
|
# a location that declares any add_header of its own inherits none of
|
|
# these, so /protected-files/ below repeats them deliberately.
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
|
|
location / {
|
|
try_files $uri $uri/ /index.php?$query_string;
|
|
}
|
|
|
|
# Protected file serving: PHP authorizes, nginx streams.
|
|
# PHP responds with X-Accel-Redirect: /protected-files/<path>.
|
|
#
|
|
# This is the only location that returns bytes someone else uploaded,
|
|
# so it gets the strictest headers in the file. `sandbox` puts anything
|
|
# rendered as a document into an opaque origin with scripts disabled —
|
|
# if a payload ever does reach here with a renderable content type
|
|
# (FileThumbnailController's allowlist is the primary defence), it
|
|
# cannot touch this app's origin or the viewer's session. Images loaded
|
|
# as subresources are unaffected: a CSP on a subresource response never
|
|
# creates a browsing context, so thumbnails and previews still render.
|
|
# `^~` so this prefix beats the `\.php$` regex below: without it a
|
|
# protected path ending in .php would be handed to the PHP handler
|
|
# instead of streaming under the sandbox headers this block sets.
|
|
location ^~ /protected-files/ {
|
|
internal;
|
|
alias /var/www/html/storage/app/files/;
|
|
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
add_header Content-Security-Policy "sandbox; default-src 'none'" always;
|
|
}
|
|
|
|
location ~ \.php$ {
|
|
# Never hand a path to PHP-FPM that isn't a real script on disk:
|
|
# without this, any URI ending in .php reaches the interpreter and
|
|
# PATH_INFO resolution decides what actually runs.
|
|
try_files $uri =404;
|
|
|
|
fastcgi_pass 127.0.0.1:9000;
|
|
fastcgi_index index.php;
|
|
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
|
include fastcgi_params;
|
|
fastcgi_buffer_size 32k;
|
|
fastcgi_buffers 8 32k;
|
|
}
|
|
|
|
location ~ /\.(?!well-known) {
|
|
deny all;
|
|
}
|
|
}
|