Files
tillandClaude Opus 5 bfcfd14625 Impressum and Datenschutz, in both languages — and stop logging IPs
Four pages: /imprint/ and /privacy/ in English, /de/impressum/ and
/de/datenschutz/ in German, linked from the footer of the matching language.
The German version is the authoritative one; the English one says so.

Every fact in them was checked rather than assumed. The hosting section comes
from the Art. 28 processing agreement with Hetzner (EU/EEA only, DPO appointed,
breach notification, ISO 27001, BSI C5 Type 2); the server location comes from
the provider's API and is Nuremberg; the "no cookies, no third-party requests,
nothing in your browser" claim comes from loading the live page in a browser
that records every outgoing request — all of them went to this domain, with
zero cookies and an empty localStorage.

nginx now logs without the client address. The default format was writing
$remote_addr and X-Forwarded-For, so a static page that needs no personal data
at all was storing the IP of everyone who looked at it. The log keeps time,
request, status, size, referrer and user agent — enough to operate the site,
minus the field that identifies a person. Data minimisation beats a retention
policy you then have to honour.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nh4A79bbqT9dcd2inzYUdg
2026-09-15 16:02:50 +00:00

41 lines
1.6 KiB
Nginx Configuration File

# Access log without the client address.
#
# The default format writes $remote_addr and X-Forwarded-For, so a static page
# that needs no personal data at all was storing the IP of everyone who looked
# at it. This format keeps what is useful for operating the site — when, what,
# which status, how big, from where, with what — and drops the one field that
# identifies a person. Data minimisation is cheaper than a retention policy.
log_format noip '[$time_local] "$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
server {
listen 80;
access_log /var/log/nginx/access.log noip;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Hashed asset file names, so they can be cached hard. The HTML is not hashed
# and must not be, or a redeploy would go unnoticed for a year.
location /_astro/ {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri =404;
}
location = /index.html {
add_header Cache-Control "no-cache";
}
# This page loads nothing from anywhere else, so it can say so.
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 Content-Security-Policy "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; font-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" always;
gzip on;
gzip_types text/css application/javascript image/svg+xml application/json;
gzip_min_length 1024;
location / { try_files $uri $uri/ /index.html; }
error_page 404 /index.html;
}