feat: launch desfoto.de as a standalone photography site and retire the old redirect
This commit is contained in:
86
nginx.conf
Normal file
86
nginx.conf
Normal file
@@ -0,0 +1,86 @@
|
||||
# desfoto.de - static site behind the existing VPS Traefik (Docker provider).
|
||||
#
|
||||
# Truthfulness contract (see /datenschutz/): this server writes no access log,
|
||||
# sets no cookies, runs no analytics and loads no third-party assets. YouTube is
|
||||
# only embedded after an explicit click (youtube-nocookie.com).
|
||||
map $uri $desfoto_cache {
|
||||
default "public, max-age=0, must-revalidate";
|
||||
~^/assets/img/ "public, max-age=604800, stale-while-revalidate=86400";
|
||||
~^/assets/fonts/ "public, max-age=604800, stale-while-revalidate=86400";
|
||||
~^/assets/site\.(css|js)$ "public, max-age=0, must-revalidate";
|
||||
~^/(favicon\.svg|site\.webmanifest)$ "public, max-age=86400";
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name _;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
charset utf-8;
|
||||
server_tokens off;
|
||||
# Redirects stay relative so they keep the https scheme terminated by Traefik.
|
||||
absolute_redirect off;
|
||||
|
||||
# No stored visitor data: the privacy page promises log-free operation.
|
||||
# Access logging is off and error messages are discarded completely, so this
|
||||
# server never writes a log file that could contain a visitor IP address.
|
||||
access_log off;
|
||||
error_log /dev/null crit;
|
||||
|
||||
etag on;
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_comp_level 6;
|
||||
gzip_min_length 512;
|
||||
gzip_types text/css text/javascript application/javascript application/json application/ld+json application/xml application/manifest+json image/svg+xml;
|
||||
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header X-Frame-Options "DENY" always;
|
||||
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()" always;
|
||||
add_header Strict-Transport-Security "max-age=31536000" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src https://www.youtube-nocookie.com; object-src 'none'; base-uri 'self'; form-action 'self' mailto:; frame-ancestors 'none'; upgrade-insecure-requests" always;
|
||||
add_header Cache-Control $desfoto_cache always;
|
||||
|
||||
error_page 404 /404.html;
|
||||
|
||||
location = /404.html {
|
||||
internal;
|
||||
}
|
||||
|
||||
location = / {
|
||||
try_files /index.html =404;
|
||||
}
|
||||
|
||||
# Keep canonical URLs: no /index.html duplicates in the index. The check uses
|
||||
# $request_uri so the internal redirect from the index module (which still
|
||||
# carries the original URI) is not caught in a loop.
|
||||
if ($request_uri ~ ^/(.*/)?index\.html(\?.*)?$) {
|
||||
return 301 /$1;
|
||||
}
|
||||
|
||||
location = /impressum.html { return 301 /impressum/; }
|
||||
location = /datenschutz.html { return 301 /datenschutz/; }
|
||||
location = /kontakt.html { return 301 /kontakt/; }
|
||||
|
||||
location ^~ /.well-known/ {
|
||||
allow all;
|
||||
autoindex off;
|
||||
types { }
|
||||
default_type text/plain;
|
||||
}
|
||||
|
||||
location /assets/ {
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
|
||||
location ~ /\.(?!well-known/) {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user