docs+ci: own security headers at Cloudflare, drop dead .htaccess path
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:
hsiegeln
2026-04-24 23:04:09 +02:00
parent d6851cd5aa
commit 3a1fe5f2c7
4 changed files with 35 additions and 82 deletions

View File

@@ -34,7 +34,11 @@ See `.env.example`. All are `PUBLIC_*` (build-time, embedded in HTML).
## Deployment
Push to `main` Gitea Actions runs tests, builds, lints, then `rsync`s `dist/` to Hetzner over SSH (ed25519 key, host-key-pinned). Rollback is `git revert && git push`.
**Manual trigger only.** Merging to `main` does NOT auto-deploy. To ship: Gitea **Actions → deploy → Run workflow** on `main`. The workflow runs tests, builds, then `rsync`s `dist/` to Hetzner over SSH (ed25519 key on port 222, host-key-pinned), and post-deploy curls the live site to verify security headers.
Rollback: trigger the deploy workflow on the previous `main` commit (Actions UI lets you pick a ref).
**Security headers** (HSTS, CSP, X-Frame-Options, etc.) are owned by **Cloudflare Transform Rules**, not by anything in this repo. Hetzner Webhosting L ignores file-based `.htaccess` (`AllowOverride None`), so origin-side header config is impossible from code. See `OPERATOR-CHECKLIST.md` §2.
See [`OPERATOR-CHECKLIST.md`](./OPERATOR-CHECKLIST.md) for the one-time Hetzner + Cloudflare setup.