From dfb8419b083968203409431cf37e7f27befa71e4 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Fri, 24 Apr 2026 17:22:25 +0200 Subject: [PATCH] Add .htaccess for origin hardening, HTTPS redirect, and cache headers --- public/.htaccess | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 public/.htaccess diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..bff4fa0 --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,55 @@ +# --------------------------------------------------------------- +# www.cameleer.io — Apache config at the Hetzner origin. +# Defense in depth: Cloudflare handles most of this at the edge; +# these rules make sure the origin is hardened even without the CDN. +# --------------------------------------------------------------- + +# Enable rewriting +RewriteEngine On + +# Force HTTPS — redundant with Cloudflare but belts-and-braces. +RewriteCond %{HTTPS} !=on +RewriteCond %{HTTP:X-Forwarded-Proto} !=https +RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] + +# Redirect apex -> www. +RewriteCond %{HTTP_HOST} ^cameleer\.io$ [NC] +RewriteRule ^(.*)$ https://www.cameleer.io/$1 [L,R=301] + +# Disable directory listings. +Options -Indexes + +# Block access to dotfiles and sensitive extensions that should never be here. + + Require all denied + + +# Prevent MIME sniffing, clickjacking, etc. (primary copy also comes from Astro middleware +# and Cloudflare Transform Rules — these apply if either layer is bypassed). + + Header always set X-Content-Type-Options "nosniff" + Header always set X-Frame-Options "DENY" + Header always set Referrer-Policy "strict-origin-when-cross-origin" + Header always set Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=(), usb=()" + Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" + + # Cache hashed build assets aggressively; HTML must be revalidated. + + Header set Cache-Control "public, max-age=31536000, immutable" + + + Header set Cache-Control "public, max-age=3600, must-revalidate" + + + # Remove Server header leak where possible. + Header unset X-Powered-By + + +# Compression (Hetzner supports mod_deflate). + + AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json image/svg+xml text/plain + + +# Custom error pages (optional — fall back to default if not present). +ErrorDocument 404 /404.html +ErrorDocument 403 /404.html