# -------------------------------- # FileRise portable .htaccess # -------------------------------- Options -Indexes -Multiviews DirectoryIndex index.html # Allow PATH_INFO for routes like /webdav.php/foo/bar AcceptPathInfo On # ---------------- Security: dotfiles ---------------- # Block direct access to dotfiles like .env, .gitignore, etc. Require all denied # ---------------- Rewrites ---------------- RewriteEngine On # 0) Let ACME http-01 pass BEFORE any other rule (needed for auto-renew) RewriteCond %{REQUEST_URI} ^/.well-known/acme-challenge/ RewriteRule - - [L] # 1) Block hidden files/dirs anywhere EXCEPT .well-known (path-aware) # Prevents requests like /.env, /.git/config, /.ssh/id_rsa, etc. RewriteRule "(^|/)\.(?!well-known/)" - [F] # 2) Deny direct access to PHP except the API endpoints and WebDAV front controller # - allow /api/*.php (API endpoints) # - allow /api.php (ReDoc/spec page) # - allow /webdav.php (SabreDAV front) RewriteCond %{REQUEST_URI} !^/api/ [NC] RewriteCond %{REQUEST_URI} !^/api\.php$ [NC] RewriteCond %{REQUEST_URI} !^/webdav\.php$ [NC] RewriteRule \.php$ - [F,L] # 3) Never redirect local/dev hosts RewriteCond %{HTTP_HOST} ^(localhost|127\.0\.0\.1|fr\.local|192\.168\.[0-9]+\.[0-9]+)$ [NC] RewriteRule ^ - [L] # 4) HTTPS redirect (enable ONE of these, comment the other) # A) Direct TLS on this server #RewriteCond %{HTTPS} !=on #RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # B) Behind reverse proxy that sets X-Forwarded-Proto #RewriteCond %{HTTP:X-Forwarded-Proto} =http [OR] #RewriteCond %{HTTP:X-Forwarded-Proto} ^$ #RewriteCond %{HTTPS} !=on #RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # 5) Mark versioned assets (?v=...) with env flag for caching rules below RewriteCond %{QUERY_STRING} (^|&)v= [NC] RewriteRule ^ - [E=IS_VER:1] # ---------------- MIME types ---------------- AddType font/woff2 .woff2 AddType font/woff .woff AddType image/svg+xml .svg AddType application/javascript .mjs # ---------------- Security headers ---------------- Header always set X-Frame-Options "SAMEORIGIN" Header always set X-XSS-Protection "1; mode=block" Header always set X-Content-Type-Options "nosniff" Header always set Referrer-Policy "strict-origin-when-cross-origin" Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()" Header always set X-Download-Options "noopen" Header always set Expect-CT "max-age=86400, enforce" Header always set Cross-Origin-Resource-Policy "same-origin" Header always set X-Permitted-Cross-Domain-Policies "none" # HSTS only when HTTPS (safe for .htaccess) Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS # CSP — keep this SHA-256 in sync with your inline pre-theme script Header always set Content-Security-Policy "default-src 'self'; base-uri 'self'; frame-ancestors 'self'; object-src 'none'; script-src 'self' 'sha256-ajmGY+5VJOY6+8JHgzCqsqI8w9dCQfAmqIkFesOKItM='; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self'; connect-src 'self'; media-src 'self' blob:; worker-src 'self' blob:; form-action 'self'" # ---------------- Caching ---------------- # HTML/PHP: no cache Header setifempty Cache-Control "no-cache, no-store, must-revalidate" Header setifempty Pragma "no-cache" Header setifempty Expires "0" # version.js: never cache Header set Cache-Control "no-cache, no-store, must-revalidate" Header set Pragma "no-cache" Header set Expires "0" # JS/CSS: long cache if ?v= present, else 1h Header set Cache-Control "public, max-age=31536000, immutable" env=IS_VER Header set Cache-Control "public, max-age=3600, must-revalidate" env=!IS_VER # Images/fonts: long cache if ?v= present, else 7d Header set Cache-Control "public, max-age=31536000, immutable" env=IS_VER Header set Cache-Control "public, max-age=604800" env=!IS_VER # ---------------- Compression ---------------- AddOutputFilterByType BROTLI_COMPRESS text/html text/css application/javascript application/json image/svg+xml AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json image/svg+xml # ---------------- Disable TRACE ---------------- RewriteCond %{REQUEST_METHOD} ^TRACE RewriteRule .* - [F]