diff --git a/typo3-konsoleh-staging-deploy/SKILL.md b/typo3-konsoleh-staging-deploy/SKILL.md index 87b8d76..b539f02 100644 --- a/typo3-konsoleh-staging-deploy/SKILL.md +++ b/typo3-konsoleh-staging-deploy/SKILL.md @@ -3,7 +3,7 @@ name: typo3-konsoleh-staging-deploy description: "Deployt ein lokal mit DDEV gebautes TYPO3-Projekt (v13/v14, Composer) als Staging-Seite auf einen Hetzner-Managed-Webhosting-Server (konsoleH). Der Composer-Build läuft AUF dem Server (kein vorgefertigtes vendor/ wird hochgeladen). Verwenden, wenn eine TYPO3-Staging- oder Vorschau-Umgebung auf Hetzner Managed Hosting (konsoleH), einem *.your-server.de-Host oder dedi*-Server eingerichtet werden soll, oder wenn eine lokale DDEV-TYPO3-Seite per SSH auf ein Managed-/Shared-Hosting übertragen werden soll. Umfasst: SSH-Inventar, per-User-composer.phar, Deploy-Keys für private Git-Repos (gitea) + Registry-Auth, Datenbank + Dokumentstamm über konsoleH, rsync von Quellcode + fileadmin, DB-Import, Staging-additional.php, .htaccess, Sprachpakete, HTTP-Basic-Auth und Let's Encrypt. NICHT für Root-VPS-/Docker-/DDEV-auf-dem-Server-Deployments." metadata: author: Wappler - version: "1.0" + version: "1.1" --- # TYPO3 → Hetzner konsoleH staging deployment @@ -224,3 +224,11 @@ On subsequent rsyncs, **exclude** the files that hold staging-specific state: 9. `.htpasswd` must be `chmod 644` (Apache auth uid ≠ PHP uid) and live outside the web root. 10. SSL = admin sets Let's Encrypt in the konsoleH SSL-Manager. 11. Always run composer/typo3 with `php -d memory_limit=-1` (128M host limit). + +## Danach live gehen +Diese Skill baut und pflegt eine **Staging**-Umgebung. Sie in Produktion zu überführen ist eine eigene +Aufgabe mit anderem Risikoprofil — siehe die Skill **`typo3-staging-to-live-cutover`**. Zwei Dinge, die +diese Skill bewusst erzeugt und die **nicht** auf live gehören: der **Basic-Auth-Block samt +`.htpasswd`** und die **DB-Dumps / Ticket-Sicherungen**, die sich im Home des Accounts ansammeln. +Dumps von Anfang an außerhalb des Docroots ablegen, mit Datum benennen und löschen, sobald die +Änderung abgenommen ist, die sie absichern. diff --git a/typo3-staging-to-live-cutover/SKILL.md b/typo3-staging-to-live-cutover/SKILL.md new file mode 100644 index 0000000..74a95ab --- /dev/null +++ b/typo3-staging-to-live-cutover/SKILL.md @@ -0,0 +1,150 @@ +--- +name: typo3-staging-to-live-cutover +description: "Promote an approved TYPO3 staging site to production — the go-live step AFTER a staging environment exists. Use when a TYPO3 site is about to go live, when a staging/preview site must become the public site, when asked to clean up a staging server before launch, or when preparing a launch checklist for a shared/managed host. Covers: what must NOT travel to live (DB dumps, one-off SQL/PHP scripts, .bak files, error logs), the environment-specific config that must change (trustedHostsPattern, displayErrors, site base, DB credentials, mail), removing basic-auth/staging locks, indexing and redirects, scheduler and SSL, plus verification and rollback. Assumes the build already runs on staging (see the staging-deploy skill for that)." +metadata: + author: Wappler + version: "1.0" +--- + +# TYPO3 — staging → live cutover + +Turning an approved staging site into the public site. Different risk profile from building staging: +**public, hard to reverse, and observed by the customer**. Work through the phases in order; do not +start Phase 4 before Phase 1–3 are verified. + +Placeholders: `@`, `` (e.g. `~/public_html/`), ``, +``, ``, ``. + +--- + +## Phase 0 — Decide the cutover model FIRST +It determines everything else. Three common shapes: +- **Domain switch in place** — the staging webspace becomes the live one (point ``'s + document root at the same project). Cheapest; but staging then no longer exists as a separate + environment, so agree with the user where future work is previewed. +- **Copy into the live webspace** — rsync the project + DB into a separate account/space. Keeps + staging alive. Everything in Phase 1 matters twice: you must not copy the junk over. +- **Rebuild from the repo** — `composer install` on the live space, DB imported from staging. Cleanest; + the artefacts in Phase 1 never exist there. **Prefer this when the host allows it.** + +Also settle **who owns the DNS/TTL change** and **when** (lower the TTL a day ahead), and confirm the +content freeze: the customer's editors are usually working in staging until the last minute. + +--- + +## Phase 1 — What must NOT travel to live +Staging accumulates working material. Inventory it, then decide per item: delete, or keep outside +the project tree. **Never just leave it.** + +```bash +# Dumps, backups, one-off scripts in the account home +ls -lah ~/ | grep -viE '^d|\.bashrc|\.profile|\.ssh' +# Leftovers inside the project (exclude vendor) +find -path '*/vendor' -prune -o \ + \( -name '*.bak' -o -name '*.bak-*' -o -name '*.orig' -o -name '*.sql' \ + -o -name '*.sql.gz' -o -name '*.zip' -o -name '*.tar.gz' \) -print +# Anything executable in the docroot besides the entry point +find /public -maxdepth 1 -name '*.php' +``` + +Typical finds, and why each matters: +- **Database dumps** (`*-db*.sql.gz`, `backup-*.sql`) — often tens of MB and a **full copy of the + production dataset**, including `be_users` hashes and any personal data in content records. + Usually they sit in the account home, i.e. *outside* the docroot and not web-reachable — verify + that rather than assume it (`ls -la ~/public_html` and compare with the domain's document root). + Even when unreachable they must not be copied to live and should not linger indefinitely. +- **Per-ticket safety backups** (`backup--.sql`) and permission exports + (`be_group*.bak`) — the same, in miniature. Delete once the change they protected is accepted. +- **One-off migration/build scripts** (`build-*.php`, `*-debug.php`, `fix-*.php`) — the real hazard: + a script written to run once, left in a web-reachable path, is a remote code path nobody reviews. + **Nothing but the framework's entry point belongs in the docroot.** +- **`*.bak` config files** (e.g. `config/sites//config.yaml.bak-`) — these DO sit + inside the project and will be rsynced to live. Remove them; they are noise at best and a + stale-config trap at worst. +- **Empty/failed artefacts** (`dumperr.log`, `importerr.log`, 20-byte `.sql.gz` files from a dump + that failed) — evidence a step went wrong; read them once, then delete. +- **The staging `.htpasswd`** — see Phase 3. + +Before deleting a dump, confirm its content is either reproducible or genuinely obsolete. If the user +wants an archive, move it **off the server** (they download it), don't relocate it within the account. + +--- + +## Phase 2 — Environment-specific configuration +Every one of these is pinned to staging and silently wrong on live. + +- **`config/system/additional.php`** (or the live equivalent): + - `SYS/trustedHostsPattern` — pinned to ``; a wrong value gives a hard failure on + the live host. Set it to `` (escape the dots), or `.*` only if the host terminates + the Host header itself. + - `SYS/displayErrors` — staging typically runs `1`. **Must be `0` (or removed) on live**, otherwise + stack traces with paths and query fragments are public. + - `SYS/devIPmask`, `exceptionalErrors`, `systemLogLevel`, debug/preview flags — reset to production. + - **Application context** — `Production` on live (`TYPO3_CONTEXT`, often via `.htaccess`/vhost). +- **DB credentials** — the live database is a different one. Keep the pattern of reading the password + from a `chmod 600` file outside the docroot rather than inlining it; **generate fresh credentials + for live, do not reuse staging's.** +- **Site configuration** `config/sites//config.yaml` — `base` is usually `/` or the staging + host. Set the live base (or base variants keyed on the application context, which lets one config + serve both). Check `baseVariants` blocks left over from earlier environments. +- **Mail** — sender address/domain, SMTP credentials, and any staging-wide redirect of outgoing mail + (a "catch all recipients" setting is common on staging and **must** be off on live). +- **File permissions** — `settings.php` holds the `encryptionKey` and is often world-readable (644) on + shared hosting. Tighten what the host allows, and rotate the encryption key if staging was widely + shared. + +--- + +## Phase 3 — Remove the staging locks +- **HTTP basic-auth**: staging is usually protected in `public/.htaccess` + (`AuthType Basic` / `AuthUserFile …/.htpasswd` / `Require valid-user`). Remove that block for live — + and delete the `.htpasswd` file. Verify with `curl -sk -o /dev/null -w '%{http_code}' `: + **200, not 401**. +- **Indexing**: whatever was decided for staging is usually the opposite for live. Check `robots.txt`, + any `X-Robots-Tag` header, and the site's SEO settings for a global `noindex`. +- **Test accounts**: remove backend users created for the launch, reset the install-tool password, and + confirm no `_cli_`/demo account carries an interactive password. +- **Placeholder files** left in the webspace root from before the project (`index.htm`, "coming soon" + pages) — they can shadow the real entry point depending on the host's `DirectoryIndex`. + +--- + +## Phase 4 — Content, SEO, operations +- **Redirects** — a relaunch usually changes slugs. Export the old URL set, map it to the new one, and + load it into `sys_redirect` **before** DNS switches. Check the old site's top URLs from its access + logs or analytics, not from the sitemap alone. +- **Scheduler** — set up the cron entry on the live host (`vendor/bin/typo3 scheduler:run`, typically + every minute); staging often has none. +- **Language packs** — `vendor/bin/typo3 language:update` on the live host; in Composer mode they are + not shipped, and labels silently fall back to English. +- **SSL** — issue/activate the certificate for `` (on managed panels this is a UI step and + may need a retry before it takes). Verify the chain from outside, not just `curl -k`. +- **Caches and index** — `cache:flush`, clear compiled CSS/JS artefacts, `referenceindex:update`. +- **Search/indexed search** — re-index after the content freeze lifts. + +--- + +## Phase 5 — Verify, then keep a way back +- **Rollback plan before the switch**: a final DB dump plus the previous DNS values, written down. + Store the dump outside the docroot and **delete it once the launch is accepted** — otherwise it + becomes exactly the Phase 1 problem on the live server. +- **Smoke test the live host** over the real domain (loop the slug list, assert 200), including the + backend, a form submission, and one page per template type. +- **Confirm from outside your network** — DNS, SSL and caching behave differently from a machine that + has been talking to the staging IP all week. +- **Re-run the Phase 1 inventory on the live server** after the cutover. If you copied rather than + rebuilt, the junk came along. + +--- + +## Recurring traps +- **Remote DB writes and schema commands are frequently blocked by tooling guards.** Expect it: stage + a reviewed `.sql` file on the server, keep a row-level backup beside it, and hand the user the + one-line command to execute rather than fighting the guard. +- **Editors keep working during the cutover.** A dump taken at 13:00 does not contain the 13:40 edit. + Agree a content freeze, or take the final dump immediately before the switch and re-verify counts. +- **`composer install` ships the locked reference.** If the sitepackage is tracked from a branch, the + lock may point at an older commit — `composer update ` explicitly, else live runs + a template older than staging's. +- **Do not promote by copying the staging DB onto an existing live DB** without checking which side is + the content master. Once real editors touch the live site, the direction reverses permanently.