10 KiB
Deploy v1.1.0 — Checkliste
Live seit 05.10.2026 — Abschluss vom Betreiber bestätigt. Protokoll am Ende.
Stand: 05.10.2026 · Live bisher: Stand 98c465b (Deploy 28.09.2026, ca. 14:34)
Inhalt: alles danach — Blöcke 9 und 10 aus dem Audit
(ENTWICKLUNGSPLAN.md, Deploy-Plan
dort), Betriebsüberwachung Phase 1 (monitoring-plan.md),
Composer-Update, Versionsnummer.
Umfang gegenüber Live: 8 additive Migrationen, 2 neue Composer-Pakete
(sentry/sentry-laravel, Abhängigkeiten), 48 Paket-Updates, neue .env-Werte,
neue Assets (beide Builds), 2 neue Scheduler-Tasks (21 statt 19). Keine
gelöschten Code-Dateien.
Die Schritte aus dem Deploy-Plan der Blöcke 9/10 sind hier eingeordnet und mit (B9/10 Nr.) gekennzeichnet.
Auf dem Server wird kein Git gebraucht. Git läuft nur lokal (Abschnitt A):
Tag, Versionsdatei, Paket. Der Server bekommt das fertige Paket und braucht
nur tar, php und composer.
A — Lokal vorbereiten
-
Arbeitskopie committen,
mainper Fast-Forward nachziehen, Tag setzen:git tag -a v1.1.0 -m "v1.1.0 — Audit-Blöcke 9/10, Betriebsüberwachung Phase 1". Push vonmainund Tag nachorigin. -
Auf dem Tag:
composer install,npm ci && npm run build, volle Testsuite (php artisan test --compact --parallel), Larastan. -
Versionsdatei und Paket bauen (im Projektverzeichnis, auf dem Tag):
git describe --tags --always --dirty > RELEASE # muss genau "v1.1.0" ergeben git -c core.quotepath=off diff --name-only --diff-filter=AMR 98c465b v1.1.0 \ -- . ':!dev' ':!docs' ':!tests' ':!.mcp.json' ':!.codex' ':!phpunit.xml' ':!phpstan-baseline.neon' \ > deploy-files.txt tar czf deploy-v1.1.0.tgz -T deploy-files.txt public/build RELEASEErgibt
RELEASEetwas anderes alsv1.1.0(z. B.-dirty), ist die Arbeitskopie nicht sauber — erst klären. Im Devcontainer fehltdocs/(nicht eingebunden), das allein macht-dirty; dort nach Prüfung mitgit describe --tags --alwaysschreiben.Erledigt 05.10.2026: Paket
deploy-v1.1.0.tgzgebaut (148 Dateien +public/build+RELEASE=v1.1.0), liegt im Projektverzeichnis. -
Paket per SFTP nach
~/auf den Server laden.
B — Live vorbereiten (vor dem Wartungsfenster)
-
DB-Backup ziehen;
ARCHIVE_KEYliegt getrennt gesichert vor. (B9/10 Nr. 4) -
Dateibackup für den Rollback (inkl.
vendor/, ohnestorage/):cd ~ && tar czf backup-vor-v1.1.0.tgz --exclude=./storage --exclude=./node_modules -C ~/pressekonto.com . -
.envauf Live ergänzen:Variable Wert Herkunft NEWSROOM_API_ASSIGNMENT_USER_IDS13993(vorher prüfen:select id from users where email = 'info@connektar.de')E19 NEWSLETTER_SENDING_ENABLEDfalseE23 BOUNCE_UNSIGNED_KINDpolicyE25/O01 SENTRY_LARAVEL_DSNDSN Projekt 1 (errors.adametz.media) M1 SENTRY_BROWSER_DSNDSN Projekt 2 M1 SENTRY_ENVIRONMENTproductionSENTRY_RELEASE/APP_VERSIONleer lassen — kommt aus RELEASEMONITORING_NTFY_URLhttps://push.adametz.mediaM3 MONITORING_NTFY_TOPICpressekonto-opsMONITORING_NTFY_TOKENToken von pressekonto-alertsMONITORING_HEALTH_TOKENneuer Zufallswert, nicht der lokale ( openssl rand -hex 24)1.5 MONITORING_ALERT_EMAILOps-Postfach prüfen (leer = LEGAL_CONTACT_EMAIL)UMAMI_PORTAL_ENABLEDfalse— erst nach DSE-AnpassungM6 UMAMI_IDENTIFY_USERSfalse— erst nach DSE-AnpassungM6 Optionale Werte (Standards greifen) siehe B9/10 Nr. 1.
-
Hauptkategorien gegen
config/canonical.phpprüfen:select id, slug from category_translations where locale = 'de' and category_id between 1 and 14. (B9/10 Nr. 2) -
Uploadgrenzen PHP
upload_max_filesize/post_max_sizeund nginxclient_max_body_size≥ 20M (Ploi: PHP-Einstellungen bzw. nginx-Konfiguration). (B9/10 Nr. 3) -
Ausgehend erreichbar vom Server:
curl -sI https://errors.adametz.mediaundcurl -sI https://push.adametz.media(beide antworten).
C — Deploy (SSH, Wartungsfenster ca. 3–5 Minuten)
cd ~/pressekonto.com
php artisan down --retry=60
tar xzf ~/deploy-v1.1.0.tgz
composer install --no-dev --optimize-autoloader --no-interaction
php artisan migrate --force # 8 Migrationen, additiv (B9/10 Nr. 6)
[ -d public/vendor/livewire ] && php artisan vendor:publish --tag=livewire:assets --force
php artisan config:cache
php artisan route:cache
php artisan view:clear && php artisan view:cache
php artisan event:cache
php artisan schedule:clear-cache # alte 24-h-Sperren (B9/10 Nr. 7)
php artisan queue:restart
# PHP-FPM neu laden (Ploi: Server ▸ PHP ▸ Restart) — OPcache hält sonst alten Code
php artisan up
Schlägt composer install oder migrate fehl: nicht up, sondern Rollback (Abschnitt G).
D — Direkt danach (Prüfungen)
php artisan about --only=pressekonto→ Versionv1.1.0.- Admin ▸ Reports ▸ Betriebsüberwachung: Version
v1.1.0; nach 1–2 Minuten Scheduler grün, Plattenplatz grün;archive_key,archive_pending,archive_sweepgrün (nach Nr. 14). curl -s -H "Authorization: Bearer <MONITORING_HEALTH_TOKEN>" https://pressekonto.com/health→"status":"ok","version":"v1.1.0". Direkt nach dem Deploy kann der Scheduler noch fehlen (503) — eine Minute warten.php artisan archive:retry-pendingeinmal von Hand. (B9/10 Nr. 8)php artisan company-memberships:api-assignmentssichten;--removenur bei Treffern ohne Freischaltung. (B9/10 Nr. 9)php artisan press-releases:assign-canonicals. (B9/10 Nr. 10)php artisan press-release-images:sweep-orphan-originals(Trockenlauf) undphp artisan archive:sweep-orphans --dry-run. (B9/10 Nr. 11, 12)php artisan schedule:list→ 21 Tasks, daruntermonitoring:heartbeat(minütlich),queue:prune-failed(03:55),press-release-images:sweep-orphan-originals(So 04:45),press-releases:purge-events(03:50). (B9/10 Nr. 13)- GlitchTip:
php artisan tinker --execute 'report(new RuntimeException("Deploy-Test v1.1.0"));'→ erscheint in Projekt 1 mit Umgebungproduction, Releasev1.1.0. - ntfy:
php artisan tinker --execute 'App\Support\OperationalAlert::send("Deploy v1.1.0 live");'→ Push auf dem Handy (und Mail an das Ops-Postfach). storage/logs/laravel-*.logundmonitoring-*.logauf neue Fehler prüfen.
E — Abnahme mit dem Testkonto
- Anmelden per Passwort, Magic Link und Google; danach einige Seiten aufrufen. Ein eingeloggter Nutzer, der einen eigenen Magic Link öffnet, landet auf dem Ziel. (B9/10 Nr. 14)
- Einmal absichtlich falsches Passwort → Admin ▸ Reports ▸ Verlauf zeigt „Anmeldung fehlgeschlagen … falsches Passwort“. (1.7)
- Titelbild mit 13–15 MiB hochladen. (B9/10 Nr. 15)
sitemap.xml: englische Meldungen unter/en/press-release/…;article:modified_time= Veröffentlichung/letzte Textänderung. (B9/10 Nr. 16)- Admin ▸ Newsletter: Sperrhinweis, „Senden“ aus. (B9/10 Nr. 17)
- Nach dem nächsten
mail:fetch-bounces: unsignierte Rückläufer als Richtlinie „(unsigniert)“, ohne Sperre. (B9/10 Nr. 18) - Der Smoke-Test aus dem Runbook (Abschnitt 8): drei Domains, robots/sitemap, Test-PM durch die Klassifikation, Formulare mit Mail.
F — Danach
- Externer Monitor (Uptime Kuma o. Ä.) auf
https://pressekonto.com/health, HeaderAuthorization: Bearer …, 60 s, 2 Wiederholungen, Benachrichtigung über ntfy (push.adametz.media,pressekonto-ops). (1.5) KAS-Passwort rotieren(B9/10 Nr. 19) — erledigt 06.10.2026, SSH-Zugang deaktiviert.- Datenschutzerklärung (Betreiber/Anwalt): Rückläufer-Protokoll (B9/10 Nr. 20),
Fehlerprotokollierung GlitchTip (User-ID, URL, Browser, Fehlermeldung, 90 Tage),
fehlgeschlagene Anmeldungen im Verlauf (IP nur als HMAC). Danach — und erst
dann —
UMAMI_PORTAL_ENABLED/UMAMI_IDENTIFY_USERSper.env+config:cache. - Restore-Übung (B9/10 Nr. 21).
- Protokolle ergänzen: Deploy-Datum und Ergebnisse in
ENTWICKLUNGSPLAN.md(B9/10 Nr. 22) undmonitoring-plan.md. - Backups
~/deploy-v1.1.0.tgzund~/backup-vor-v1.1.0.tgznach ein paar stabilen Tagen löschen.
G — Rollback
cd ~/pressekonto.com
php artisan down
tar xzf ~/backup-vor-v1.1.0.tgz -C ~/pressekonto.com # alter Code inkl. vendor/
php artisan config:cache && php artisan route:cache && php artisan view:clear && php artisan view:cache && php artisan event:cache
php artisan queue:restart # + PHP-FPM neu laden
php artisan up
Die Migrationen sind additiv; der alte Code läuft mit den neuen Spalten und Tabellen. Nur bei Datenproblemen das DB-Backup aus Nr. 5 einspielen und danach die Archiv-Schritte aus Runbook Abschnitt 9 befolgen.
Protokoll
05.10.2026 — Deploy v1.1.0 live (Paket aus Abschnitt A, Commit df7ebdc = Tag v1.1.0).
Abschnitt D, Ausgaben auf Live:
| Nr. | Ergebnis |
|---|---|
| 11 | Zunächst Version „—“: Datei RELEASE fehlte bzw. Config-Cache war älter. Behoben mit echo v1.1.0 > RELEASE + config:cache. Eine lokal neu erzeugte RELEASE hatte v1.1.0-2-g8a64bd7-dirty ergeben (Doku-Commits nach dem Tag, docs/ nicht eingebunden) — Lehre: RELEASE aus dem Paket nehmen, nicht neu erzeugen |
| 14 | archive:retry-pending: 0 Aufträge, 0 offen |
| 15 | company-memberships:api-assignments: 3 Mitgliedschaften (connektar, User 13993), alle freigeschaltet — kein --remove |
| 16 | assign-canonicals: 9.887 Paare, 342 geändert, 13 veraltete Verweise zurückgesetzt, Caches geleert |
| 17 | sweep-orphan-originals (Trockenlauf): 6 geprüft, 0 verwaist; archive:sweep-orphans --dry-run: 0 |
| 18 | schedule:list: 21 Tasks inkl. monitoring:heartbeat, queue:prune-failed 03:55, sweep-orphan-originals So 04:45 |
| 19, 20 | GlitchTip- und ntfy-Test ausgeführt; nach config:cache wiederholt |
Abschnitt E (Abnahme Testkonto) vom Betreiber nicht einzeln gemeldet.
Abschnitt F offen: externer Monitor auf /health (29),
Datenschutzerklärung (31), Restore-Übung (32); dazu Context7-Schlüssel rotieren
(stand bis df7ebdc im Repository). KAS-Passwort (30) erledigt 06.10.2026.