-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path.htaccess
More file actions
76 lines (67 loc) · 3.46 KB
/
Copy path.htaccess
File metadata and controls
76 lines (67 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# TestnetScan Apache config. Drop the folder into the docroot and go.
# Requires mod_rewrite; mod_headers recommended.
Options -Indexes
DirectoryIndex index.php
# Cap request bodies (defense-in-depth vs oversized-POST abuse). The broadcast /
# decode / PSBT tools only ever POST a raw tx hex or PSBT, comfortably under 1 MiB.
# Raise this if you need to broadcast unusually large transactions.
LimitRequestBody 2097152
# ---- block source / data / config ----------------------------------------
RewriteEngine On
# Internal directories and the live config must never be served directly.
RewriteRule ^(lib|views|db|tools)(/|$) - [F,NC]
RewriteRule ^config\.php$ - [F]
# Dotfiles (.git, .htaccess, .gitignore, etc.) except ACME challenges.
RewriteRule (^|/)\.(?!well-known/) - [F]
# Defense in depth: deny sensitive extensions by basename.
<FilesMatch "\.(sqlite|sqlite-wal|sqlite-shm|db|db-wal|db-shm|db-journal|md|bak|orig|swp|inc)$|(^|/)config\.example\.php$">
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
</IfModule>
</FilesMatch>
# ---- front controller -----------------------------------------------------
# Serve real files/dirs (assets, robots.txt, sitemap.xml, manifest) directly.
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Everything else is routed through index.php (which parses REQUEST_URI).
RewriteRule ^ index.php [L]
# ---- headers --------------------------------------------------------------
<IfModule mod_headers.c>
# 'always' so the headers attach to error responses too, not just 2xx.
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "DENY"
Header always set Referrer-Policy "no-referrer"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
# HSTS is left to the CDN/proxy (Cloudflare), matching the sibling sites.
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; manifest-src 'self'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'; object-src 'none'"
# Long-cache static assets (they're versioned with ?v=).
<FilesMatch "\.(css|js|svg|woff2?|png|ico|webmanifest)$">
Header set Cache-Control "public, max-age=604800"
</FilesMatch>
# The service worker must revalidate so updates propagate.
<FilesMatch "^sw\.js$">
Header set Cache-Control "no-cache"
</FilesMatch>
</IfModule>
# ---- compression ----------------------------------------------------------
# Text responses (HTML pages, Esplora JSON, CSS/JS, SVG) compress ~4-8x. This
# shrinks the origin->edge (and any non-Cloudflare) transfer of dynamic bodies
# that the CDN does not cache. Binary /raw octet-stream is deliberately excluded
# (already compact, and re-compressing wastes CPU). Both modules emit Vary
# themselves, so no manual Vary is needed. Brotli is preferred when available;
# mod_deflate (gzip) is the universal fallback.
<IfModule mod_brotli.c>
AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/css text/xml \
application/json application/javascript application/xml image/svg+xml \
application/manifest+json
</IfModule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css text/xml \
application/json application/javascript application/xml image/svg+xml \
application/manifest+json
</IfModule>