docs+ci: own security headers at Cloudflare, drop dead .htaccess path
All checks were successful
ci / build-test (push) Successful in 3m33s
All checks were successful
ci / build-test (push) Successful in 3m33s
Hetzner Webhosting L runs Apache with AllowOverride None on the user docroot, so file-based .htaccess is silently ignored — directives in public/.htaccess never applied. Confirmed via direct-origin tests: neither Header, Rewrite, nor FilesMatch fired regardless of the file being present and readable. The only origin-side override path on this tier is konsoleH's per- directory Serverkonfiguration UI, which writes to a separate Apache config file outside the user's filesystem (and thus outside any deploy pipeline). Make the architecture honest: - Delete public/.htaccess (dead code Apache never reads). - Remove the "Copy .htaccess into dist" CI step (now a no-op). - Update deploy.yml header comment to point at Cloudflare for headers. - Update OPERATOR-CHECKLIST.md §1 with the three Webhosting-L gotchas: port 222 for SSH, SFTP_PATH must match the actual vhost docroot (default is bare public_html/), and AllowOverride None. - Update §5 to reflect manual workflow_dispatch (no auto-deploy on push) and 5-header expectation. - Update README.md deploy section likewise. Headers (HSTS, CSP, XFO, X-Content-Type-Options, Referrer-Policy, Permissions-Policy) are now owned by Cloudflare Transform Rules, documented in OPERATOR-CHECKLIST.md §2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,10 +5,15 @@
|
||||
# (Actions → deploy → Run workflow). Does NOT auto-deploy on push to main —
|
||||
# merges to main must be explicitly promoted to production.
|
||||
#
|
||||
# Build and deploy run in a single job so the built dist/ (including
|
||||
# dotfiles like .htaccess) flows directly into rsync. An earlier split-job
|
||||
# design was abandoned because actions/upload-artifact@v3 excludes dotfiles
|
||||
# by default and the v4 client does not work on Gitea Actions / GHES.
|
||||
# Build and deploy run in a single job; rsync uploads dist/ directly. No
|
||||
# upload-artifact round-trip (v3 strips dotfiles, v4 isn't supported on Gitea).
|
||||
#
|
||||
# Security headers (HSTS, CSP, X-Frame-Options, etc.) are NOT set by this
|
||||
# deploy. Hetzner Webhosting L runs Apache with AllowOverride None on the
|
||||
# user docroot, so file-based .htaccess is silently ignored. All response
|
||||
# headers are owned by Cloudflare Transform Rules — see OPERATOR-CHECKLIST.md
|
||||
# §2 "Cloudflare". Apache config exposed via konsoleH UI is the only origin-
|
||||
# side override path and is not managed from this repo.
|
||||
#
|
||||
# Runner: self-hosted arm64 Gitea runner. Adjust `runs-on` if your runner's
|
||||
# labels differ. Deploy target is Hetzner amd64 — arch mismatch is a non-issue
|
||||
@@ -54,15 +59,6 @@ jobs:
|
||||
- name: Build site
|
||||
run: npm run build
|
||||
|
||||
# Astro/Vite does not copy dotfiles from public/ into dist/, so .htaccess
|
||||
# never reaches the deployed origin and Apache never sees the security
|
||||
# headers it sets. Copy it explicitly. Fail if the source is missing
|
||||
# rather than silently shipping a header-less site.
|
||||
- name: Copy .htaccess into dist
|
||||
run: |
|
||||
test -f public/.htaccess
|
||||
cp public/.htaccess dist/.htaccess
|
||||
|
||||
- name: Guard — no TBD markers may ship in built HTML
|
||||
run: |
|
||||
if grep -rlE '(TBD):' dist 2>/dev/null | grep -E '\.(html|svg)$'; then
|
||||
|
||||
Reference in New Issue
Block a user