Deploy- und Cutover-Skill: lokaler Admin-Account darf nicht mitwandern

Jeder DB-Dump enthaelt be_users, der DDEV-Admin reist beim ersten Import also
mit auf den Server. Sein Passwort ist typischerweise ein Wegwerfpasswort
(admin, password, Projektname), weil lokal niemand sonst herankommt. Auf
Staging sitzt es hinter Basic Auth, und beim Go-live wird genau diese Sperre
entfernt - dann steht ein trivial erratbarer Admin an einem oeffentlichen
/typo3/.

Deploy-Skill: nach dem Import be_users auflisten und dem Entwickler
ausdruecklich sagen, dass sein lokaler Admin NICHT mitkommen soll;
deaktivieren, loeschen oder neues starkes Passwort, aber nie so lassen.
be_sessions ebenfalls leeren, sonst bleibt ein kopiertes Session-Cookie
gueltig.

Cutover-Skill: als eigener Punkt in "Test accounts", weil das Entfernen der
Basic-Auth-Sperre in derselben Phase passiert. Mit dem Hinweis, das mit dem
Entwickler zu klaeren statt es zu entscheiden - es ist sein Account, und im
selben Dump koennen Agentur-Accounts stecken, die bleiben muessen. lastlogin
als Unterscheidungsmerkmal, und danach von aussen pruefen, dass der Login
wirklich fehlschlaegt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-10 12:20:29 +02:00
co-authored by Claude Opus 5
parent 3a27825de1
commit 38b9ae49e5
2 changed files with 31 additions and 2 deletions
+17 -1
View File
@@ -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.1"
version: "1.2"
---
# TYPO3 → Hetzner konsoleH staging deployment
@@ -159,6 +159,22 @@ $SSH 'MYSQL_PWD="$(cat ~/public_html/<PROJECT>/config/system/.env.db)" mysql -h
(A `ddev export-db` dump is clean — no `USE`/`CREATE DATABASE`/`DEFINER`. If importing an arbitrary
dump, check for those first.)
**⚠ The dump carries `be_users`, so the developer's LOCAL admin travels to the server with it.** A
DDEV admin usually has a throwaway password (`admin`, `password`, the project name) because nothing
but the developer can reach it. On staging it sits behind basic-auth at best — and at go-live that
lock gets removed (see the cutover skill), so the trivial password ends up on a publicly reachable
backend. **Say this to the developer explicitly and get their decision; do not silently carry the
account over.** After the import, show who can log in:
```
$SSH 'cd ~/public_html/<PROJECT> && MYSQL_PWD="$(cat config/system/.env.db)" mysql -h <DB_HOST> -u <DB_USER> <DB_NAME> -e \
"SELECT uid,username,admin,disable,deleted,FROM_UNIXTIME(lastlogin) FROM be_users ORDER BY admin DESC,uid;"'
```
Then, for the local-only account: disable it (`UPDATE be_users SET disable=1 WHERE username='<LOCAL_ADMIN>'`),
delete it, or give it a fresh strong password on the target — but never leave the local one usable. The
target should carry its own named admin accounts. Also clear `be_sessions` after an import, otherwise a
copied session cookie stays valid. **Ask before touching any other account:** on a customer system,
disabling the wrong user locks somebody out of their own backend.
## Step 10 — Ship uploaded files (fileadmin)
```
rsync -az --exclude='_processed_/' --exclude='_temp_/' -e "ssh -p <SSH_PORT>" public/fileadmin/ <SSH_USER>@<SSH_HOST>:<WEBROOT>/<PROJECT>/public/fileadmin/
+14 -1
View File
@@ -3,7 +3,7 @@ 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.2"
version: "1.3"
---
# TYPO3 — staging → live cutover
@@ -114,6 +114,19 @@ Every one of these is pinned to staging and silently wrong on live.
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.
- **⚠ The DEVELOPER'S LOCAL ADMIN, carried in with the database.** Every DB dump contains `be_users`,
so the DDEV admin came along on the first import — typically with a throwaway password (`admin`,
`password`, the project name) that was harmless only because nothing but the developer could reach
it. Removing the basic-auth lock in this very phase is what makes it dangerous: a trivially
guessable admin on a public `/typo3/`. **Raise this with the developer explicitly rather than
deciding for them** — it is their account, and the same dump may also hold agency accounts that
must stay. List the candidates and their last login, then disable, delete, or re-password the
local-only one:
```
SELECT uid,username,admin,disable,deleted,FROM_UNIXTIME(lastlogin) FROM be_users ORDER BY admin DESC,uid;
```
A `lastlogin` of 0 or one that only ever happened locally is the tell. Clear `be_sessions` too. Then
verify from outside that the account is really gone: a login attempt must fail, not just be hidden.
- **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`.