docs
TYPO3 v14
Erste Schritte  /  Installation mit DDEV

03 — Installation mit DDEV

Der empfohlene Weg, und der, für den die Auslieferung gebaut ist. Was heruntergeladen wird, ist keine Extension, sondern ein vollständiges TYPO3-Projekt: entpacken, ein Skript starten, und eine lauffähige Site steht — samt Demo-Inhalten. Man beginnt bei einer fertigen Standard-Site und passt sie an, statt eine aus einem leeren Seitenbaum aufzubauen.


Die Installation im Video

Drei Minuten, vom leeren Verzeichnis bis zum laufenden TYPO3: die Abfragen des Installers, der DDEV-Start und der erste Blick ins Backend. Die geschriebene Fassung folgt unten und bleibt die Referenz — das Video zeigt nur, wie es dabei aussieht.

Das Video wird erst von YouTube geladen, wenn Play gedrückt wird — vorher geht keine Anfrage hinaus (warum).


Was ausgeliefert wird

Auf licence.yavithemes.com anmelden, dann Konto → Downloads. Zu jeder aktiven Lizenz gehört ein ZIP, benannt nach dem Produktcode — yavi-lucerne.zip für Lucerne. Es enthält das Theme, die Core-Extension und das Projekt darum herum:

PfadWas es ist
.ddev/DDEV-Konfiguration: Projekttyp typo3, PHP 8.4, nginx-fpm, MariaDB 10.11, Docroot public/
composer.jsonTYPO3-v14-Basisdistribution, Bootstrap Package 16, b13/container — und ./packages/* als path-Repository
packages/yavi-core/die Core-Extension: Inhaltselemente, Backend-Modul, SCSS
packages/yavi-lucerne/das Theme: das Design auf dem Core
packages/yavi-lucerne/Initialisation/Site/yavilucerne/die Site-Konfiguration, die der Installer nach config/sites/<id>/ kopiert
packages/yavi-lucerne/Initialisation/Files/die Demo-Medien, ca. 25 MB, die Bilder, auf die diese Seiten verweisen
.tarballs/yavi-demo.sql.gzdie Demo-Datenbank — jede Seite, die die Demo-Site zeigt
.tarballs/yavi-lucerne-demo.t3dderselbe Inhalt als Importdatei, um die Demo in ein bestehendes TYPO3 zu ergänzen. Auf diesem Weg nicht verwendet; siehe 04 — Bestehendes TYPO3.
.tarballs/yavi-static-elements.t3dTopbar, Footer und die Hüllen der Rechtsseiten, ohne Demo-Inhalte. Wird verwendet, wenn ohne Demo installiert wird.
init-static-elements.phprichtet diese Struktur ein und schreibt die Einstellungen um, die darauf zeigen
.env, .env.localUmgebungsvariablen für die beiden Kontexte
init-yavi.shdas Setup-Skript

Ein config/sites/ gibt es im Archiv nicht. Die Site-Konfiguration reist als Vorlage im Theme mit, und der Installer kopiert sie auf den gewählten Site-Identifier. Das hält zugleich den Lizenzschlüssel aus dem Paket heraus — die mitgelieferte Vorlage trägt einen leeren.

!
Für die Installation ist keine Registrierung nötig. Die Pakete liegen nicht auf Packagist, und das ZIP braucht kein eigenes Repository: seine composer.json löst packages/* als lokales path-Repository auf, die Installation läuft also ohne Zugangsdaten und ohne Netzverbindung zu uns. Für Updates gibt es ein lizenziertes Composer-Repository, das sich später einschalten lässt — siehe Updates.

Voraussetzung

Ein laufendes DDEV mit Docker. DDEV selbst zu installieren und einzurichten liegt auf deiner Seite und wird hier nicht behandelt — dafür gibt es die Dokumentation von DDEV. Alles Weitere, was das Projekt braucht — Composer, PHP und die Datenbank —, läuft im Container.

Sobald ddev auf der Kommandozeile verfügbar ist, ist der Rest dieses Kapitels die vollständige Installation.

1. Entpacken und starten

Das Archiv bringt bereits einen eigenen Ordner mit; es wird also dort entpackt, wo es liegen soll:

bash
unzip yavi-lucerne.zip
cd yavi-lucerne
chmod +x init-yavi.sh
./init-yavi.sh

Das Skript ist interaktiv und stellt acht Fragen:

AbfrageBedeutung
Choose [1/2]1 = .env.local, 2 = .env. Beide liegen im ZIP; passend zur Maschine wählen.
Enter DDEV project nameWird zu name: in .ddev/config.yaml und damit zur URL — yavilucerne → https://yavilucerne.ddev.site.
Enter site identifierDer Ordner unter config/sites/. Jeder Pfad in dieser Dokumentation, der config/sites/<id>/ schreibt, meint diesen Namen.
Enter project titlePflichtangabe, ohne Vorgabe. Wird im Backend angezeigt.
Install the demo site …? [Y/n]Y installiert den Seitenbaum, seine Inhalte und die Medien. n legt stattdessen eine Wurzelseite mit der Grundstruktur des Themes an — Topbar, Footer und die Rechtsseiten, aber nichts aus der Demo. Siehe Ohne die Demo installieren weiter unten.
Enter backend usernameVorgabe admin.
Enter backend passwordWird nicht angezeigt.
Enter backend e-mailPflichtangabe.

Die letzten drei kommen am Ende, wenn die Datenbank steht. Alles Übrige stammt aus der Umgebungsdatei, und das Skript schreibt die Antworten dorthin zurück — ein zweiter Lauf kennt sie also bereits.

Den Lizenzschlüssel vorab eintragen

Optional, spart aber einen Schritt. Der Schlüssel gehört vor dem Start in die Umgebungsdatei:

bash
LICENCE_KEY="XXXX-XXXX-XXXX-XXXX"

Der Installer schreibt ihn dann nach config/sites/<id>/settings.yaml. Bleibt er leer, sagt das Skript das und macht weiter; der Schlüssel wird danach im Backend eingetragen.

2. Was das Skript tut

Der Reihe nach — einmal lesenswert, denn zwei Schritte sind destruktiv:

  1. Findet DDEV. Das bin-Verzeichnis von Homebrew landet nur über eine Login- oder interaktive Shell im PATH; ein Lauf aus einem VSCode-Task oder aus cron sähe es also nicht. Das Skript sieht selbst in /opt/homebrew/bin und /usr/local/bin nach.
  2. Lädt die gewählte Umgebungsdatei.
  3. Schreibt den Projektnamen in .ddev/config.yaml. Das geschieht, bevor irgendetwas gelöscht wird, denn ddev delete löst das Projekt über diese Datei auf — der mitgelieferte Name ist der, aus dem dieses Paket gebaut wurde, nicht deiner.
  4. Löscht das bestehende DDEV-Projekt — ddev delete --omit-snapshot -y —, aber nur bei RESET_DB=1. Die mitgelieferte .env hat RESET_DB=1.
  5. Startet DDEV, nachdem public/ angelegt wurde. Das Verzeichnis muss vor ddev start existieren, sonst warnt DDEV vor einem falsch konfigurierten Docroot.
  6. Schreibt PROJECT_NAME, SITE_IDENTIFIER, PROJECT_TITLE, INSTALL_DEMO und das aufgelöste DDEV_BASE in die Umgebungsdatei zurück.
  7. ddev composer install — hier werden packages/yavi-core und packages/yavi-lucerne über das path-Repository nach vendor/ verlinkt.
  8. Startet DDEV ein zweites Mal. DDEV schreibt config/system/additional.php — Datenbankverbindung, ImageMagick-Pfade, Mail-Transport und trustedHostsPattern —, aber erst, wenn es das Projekt als TYPO3 erkennt, und das erkennt es an vendor/typo3. Bei Schritt 5 gab es das noch nicht. Ohne diesen Schritt beantwortet die Site jede Anfrage mit
  9. „The current host header value does not match the configured trusted hosts pattern“.
  10. Installiert TYPO3 mit typo3 setup, sofern config/system/settings.php nicht schon existiert.
  11. Importiert .tarballs/yavi-demo.sql.gz — nur wenn die Demo gewünscht war und nur, wenn die Tabelle pages leer ist. Eine bestehende Site wird von diesem Schritt nie überschrieben.
  12. extension:setup aktiviert beide Extensions.
  13. Wendet init-settings.php an, falls das Projekt eine solche Datei mitbringt. Sie muss nach extension:setup laufen, das die Vorgaben aus ext_conf_template.txt schreibt und diese Werte sonst überschreiben würde.
  14. Richtet config/sites/<id>/ ein — benennt die eine mitgelieferte Konfiguration auf deinen Site-Identifier um oder kopiert sie aus dem Initialisation/Site/ eines Pakets. Bringen mehrere Pakete eine mit, fragt das Skript nach.
  15. Schreibt den Lizenzschlüssel aus LICENCE_KEY nach config/sites/<id>/settings.yaml. Mitgelieferte Site-Konfigurationen tragen einen leeren Schlüssel, damit nie ein Schlüssel verteilt wird — siehe unten.
  16. Richtet die Grundstruktur ein — nur bei einer Installation ohne Demo. Legt eine Wurzelseite an, importiert .tarballs/yavi-static-elements.t3d darunter und schreibt die fünf Einstellungen um, die diese Datensätze über ihre uid adressieren, denn der Import vergibt neue. Danach wird der Cache geleert, weil die Einstellungen erst nach dem Bau der TypoScript-Konstanten geschrieben werden.
  17. Kopiert additional.php aus dem Initialisation/System/ eines Pakets, aber niemals über eine bestehende Datei.
  18. Kopiert Initialisation/Files jedes Pakets nach public/fileadmin/ — wiederum nur bei gewünschter Demo, da sonst nichts auf diese Dateien verweisen würde.
  19. Löscht alle Backend-Benutzer und -Gruppen und legt danach den abgefragten Administrator an.
  20. Leert die Caches und gibt die URLs aus.
!
init-yavi.sh ist ein Installer, kein Updater. Schritt 4 löscht bei RESET_DB=1 das gesamte DDEV-Projekt samt Datenbank, und Schritt 18 führt bedingungslos DELETE FROM be_users aus — jedes Redaktionskonto ist damit weg. Niemals auf eine Site richten, in der bereits Inhalte oder Benutzer stehen.

Am Ende gibt es aus, wo alles liegt:

text
==> Done
Frontend: https://yavilucerne.ddev.site
Backend:  https://yavilucerne.ddev.site/typo3
Site ID:  yavilucerne
User:     admin
Demo:     installed

3. Was die Demo-Inhalte mitbringen

Dieser Weg installiert mit Demo-Inhalten. Sie kommen in zwei Hälften, und beide werden gebraucht — die Datenbank hält die Datensätze, der Medienordner die Dateien, auf die diese Datensätze zeigen:

HälfteQuelleSchrittLandet in
Seiten und Inhalte.tarballs/yavi-demo.sql.gz10der Datenbank
Bilder, Video, Audiopackages/*/Initialisation/Files/17public/fileadmin/

Das Ergebnis ist eine vollständige Standard-Site — 60 Seiten mit Navigation und Megamenü, ein Hero-Karussell und jeder Inhaltselementtyp im echten Einsatz. Zusammen mit den Theme-Einstellungen in config/sites/<id>/settings.yaml ist das das komplette Setup: Es muss nichts weiter konfiguriert werden, damit die Site wie die Demo rendert.

Die Medien liegen nach Thema sortiert unter fileadmin/dummy-media/: hero/, team/, casestudy/, services/, gallery/, header/, audio/, video/, documentation/, downloads/, dazu yavi-icons/ und yavi-logos/ als Symbol- und Platzhalter-Logo-Bibliotheken für eigene Seiten.

Der Datenbankimport ist bedingt: Schritt 10 läuft nur, wenn die Tabelle pages leer ist. Ein zweiter Lauf des Skripts überschreibt also nie bereits angelegte Inhalte.

Ohne die Demo installieren

Bei Install the demo site mit n antworten oder vor dem Lauf INSTALL_DEMO=0 in die Umgebungsdatei schreiben. Der Demo-Dump und die Demo-Medien entfallen dann — aber am Ende steht trotzdem keine leere Installation.

Das Theme rendert seinen Rahmen aus Inhaltsdatensätzen: Topbar, Stickybar und die fünf Footer-Spalten sind allesamt Inhaltselemente, keine Einstellungen. Eine Installation, die nur die Demo überspringt, zeigte deshalb eine Site ohne Kopfleiste und mit leerem Footer — und es gäbe nichts anzuklicken, um herauszufinden, warum.

Der Installer richtet deshalb einen Startpunkt ein:

text
==> Setting up base structure (no demo)
    Created root page 'Home' (uid 1)
    Imported static elements below uid 1
    page.footer.pid: 4
    page.stickybar: 16
    page.topbar: 15
    page.socialtopbar: 13
    page.theme.footernavigation.navigationValue: 5
Was entstehtWo es liegt
Eine Wurzelseite Homedie Site-Wurzel, rootPageId zeigt darauf
Ordner Static Elementsunter Home, aus der Navigation ausgeblendet
Topbar, Stickybar, Social-LinksSeite Static-Elements darin
Die fünf Footer-SpaltenSeite Footer darin
Sechs Seiten für Impressum, Datenschutz, AGB, Lizenz, Widerruf und Cookie-HinweisOrdner Footer-Navigation, bereits im Footer-Menü verdrahtet
Eine leere Seite Contactdirekt unter Home, aus der Navigation ausgeblendet. Sie existiert, damit der Kontaktlink im Footer ein Ziel hat; entweder füllen oder den Link umhängen

Zwölf Seiten und sechzehn Inhaltselemente insgesamt. Ihre URLs sind flach — /imprint, /privacy-policy, /contact; die Ordner, in denen sie liegen, tauchen im Pfad nicht auf.

Die sechs Rechtsseiten tragen nur Titel und Seitenkopf. Der Text wird bewusst nicht mitgeliefert: Rechtstexte gehören dem eigenen Unternehmen, nicht dem Theme-Anbieter, und plausibel klingender Blindtext ist schlimmer als eine leere Seite, die ohnehin noch gefüllt werden muss. Der Kontaktblock im Footer arbeitet genauso — er zeigt Your Company, 2978 Cedar Lane und info@example.com als Platzhalter.

Alles Weitere im Baum ist selbst zu bauen. Was die Demo gezeigt hätte — Karussells, Kartenlayouts, die Element-Galerie — gehört nicht dazu; wer es ansehen will, installiert in einem zweiten Projekt einmal mit Demo und vergleicht.

Wie die Verdrahtung den Import übersteht

Diese fünf Einstellungen adressieren Inhalte über ihre uid, und ein Import vergibt neue Nummern. Der Installer schlägt deshalb nach, was er gerade importiert hat, und schreibt die Einstellungen passend um. Deshalb steht oben page.footer.pid: 4 und nicht die 62 aus der Demo — dieselbe Struktur, andere Nummern.

Wer die Footer-Seite später verschiebt oder selbst neu baut, richtet das Theme über genau diese Einstellung auf die neue aus: Yavi Theme → Config → Footer Content Page.

Warum die Medien zweimal existieren

Schritt 17 kopiert Initialisation/Files/ flach nach public/fileadmin/ — genau dorthin, wohin die sys_file-Datensätze des Dumps zeigen (fileadmin/dummy-media/…). TYPO3 selbst kopiert denselben Ordner bei der Aktivierung der Extension zusätzlich nach fileadmin/<extension_key>/; bei Lucerne sind das ungenutzte 24 MB unter fileadmin/yavi_lucerne/. Sie zu löschen ist unbedenklich; der Vorgang ist in sys_registry vermerkt und wiederholt sich nur bei einer Neuinstallation.

4. Der Lizenzschlüssel

Vor dem Lauf in die Umgebungsdatei eintragen, dann füllt Schritt 14 ihn ein:

bash
LICENCE_KEY="XXXX-XXXX-XXXX-XXXX"

Bleibt er leer, sagt das Skript das und macht weiter; der Schlüssel wird dann im Backend unter Yavi Theme → Licence eingetragen. So oder so ist er erforderlich — ohne gültige Lizenz arbeitet die Extension nicht, siehe 11 — Lizenz.

5. Prüfen

bash
ddev exec vendor/bin/typo3 extension:list | grep yavi

yavi_core und yavi_lucerne, beide aktiv. Im Backend erscheint unterhalb von Site Management der Eintrag Yavi Theme im Modulmenü, mit fünf Seiten: Design / Colors, Layout, Custom CSS, Config, Licence.

Fehlt das Modul, ist entweder die Extension nicht aktiv oder der Backend-Benutzer kein Administrator — das Modul ist bewusst Administratoren vorbehalten.

Wenn der Lauf bei „ddev-router failed to become ready“ stehen bleibt

text
Failed to start yavilucerne: ddev-router failed to become ready after 60.0s

Das ist DDEV, nicht das Paket. Der Router bedient alle DDEV-Projekte einer Maschine gleichzeitig und hat sechzig Sekunden Zeit, deren Routen zu laden. Bei mehreren laufenden Projekten kann er dieses Fenster verpassen — meist ist er einen Moment später fertig, aber da hat der Installer schon abgebrochen.

bash
ddev poweroff
./init-yavi.sh

ddev poweroff stoppt jedes Projekt und entfernt den Router-Container; er kommt also nur mit den Routen des Projekts wieder hoch, das gerade startet. Den Installer erneut laufen zu lassen ist unbedenklich: Mit RESET_DB=1 beginnt er von vorn, und an der Abbruchstelle war noch nichts installiert.

Wiederholt sich das, ist der Router selbst verklemmt:

bash
ddev poweroff
docker rm -f ddev-router
ddev start

6. Weiter

Die Site ist installiert, aber das Theme greift erst, wenn sein Set aktiv ist und die Lizenz eingetragen wurde. Weiter mit 05 — Die erste Site einrichten.


Updates

Updates kommen über dasselbe Kundenportal: **licence.yavithemes.com → Konto → Downloads**. Die Seite listet jede Lizenz mit ihrem Datum Updates until. Die Site läuft weiter, wenn dieses Datum verstreicht — ein abgelaufenes Update-Fenster blockiert neue Versionen, nicht die vorhandene Installation.

Aktualisiert wird nur yavi-core. Die Theme-Extension gehört dir: Du bearbeitest ihr SCSS, ihre Templates und ihre Einstellungen, und ein Update darf diese Arbeit nicht überschreiben. Deshalb bietet das Portal das Framework auch einzeln an, als Framework update, neben dem vollständigen Paket:

DownloadWas es istWann
Framework update — yavi-core-<version>.zip, ca. 5 MBdie Framework-Extension alleinbei jedem Update
Full package — yavi-lucerne.zip, ca. 60 MBProjekt, Theme, Framework, Demobei einer Neuinstallation

Ist das Update-Fenster abgelaufen, bietet die Schaltfläche Framework update weiterhin die letzte Version an, die innerhalb des Fensters erschienen ist. Das vollständige Paket wird ab diesem Tag verweigert, weil es davon nur den aktuellen Build gibt.

Vorher sichern — spätestens beim Update ist die Installation nicht mehr entbehrlich, und die Datenbankmigrationen eines Updates lassen sich nicht rückgängig machen, indem man die alten Dateien zurückspielt:

bash
ddev snapshot
ddev export-db --file=backup-$(date +%F).sql.gz

Ein Update ersetzt dann einen Ordner und sonst nichts:

bash
rm -rf packages/yavi-core
unzip yavi-core-<version>.zip -d /tmp/yavi-update
cp -R /tmp/yavi-update/yavi-core packages/

ddev composer dump-autoload
ddev exec vendor/bin/typo3 extension:setup
ddev exec vendor/bin/typo3 cache:flush
!
Den alten Ordner löschen, nicht darüber entpacken. Dateien, die die neue Version entfernt hat, blieben sonst liegen, und ein übrig gebliebenes SCSS-Partial, das irgendwo noch per @import eingebunden ist, ist ein schwer zu findender Fehler.

packages/yavi-lucerne bleibt, wo es ist. Wer auch die neueren Templates des Themes will — weil sie unverändert sind oder weil zusammengeführt werden soll —, nimmt diesen Ordner aus dem vollständigen Paket und vergleicht vor dem Überschreiben.

Composer die Arbeit überlassen

Dasselbe Archiv liefert auch ein lizenziertes Composer-Repository aus; das manuelle Kopieren entfällt damit. Einmalig einrichten:

bash
ddev composer config repositories.yavi composer https://repo.yavithemes.com
ddev composer config --auth http-basic.repo.yavithemes.com licence YOUR-LICENCE-KEY
ddev composer require webagentur-yahya/yavi-core:^1.0

Von da an ist ein Update ein einziger Befehl:

bash
ddev composer update webagentur-yahya/yavi-core
ddev exec vendor/bin/typo3 extension:setup
ddev exec vendor/bin/typo3 cache:flush

Drei Dinge sind dabei wissenswert:

Das Theme ist bewusst nicht Teil davon. Es bleibt ein lokales path-Paket, sodass kein composer update jemals die eigenen Änderungen daran berühren kann.

init-yavi.sh nicht erneut für ein Update aufrufen. Es würde die Datenbank und jeden Backend-Benutzer löschen.

Danach immer den Cache leeren. Das kompilierte theme-<hash>.css ist über den SCSS-Inhalt geschlüsselt; ohne Flush wird weiterhin die alte Datei ausgeliefert.

Entfernen

bash
ddev composer remove webagentur-yahya/yavi-lucerne
ddev exec vendor/bin/typo3 cache:flush

Die Inhaltsdatensätze bleiben in der Datenbank. Ihre Inhaltselementtypen gibt es dann nicht mehr, das Seitenmodul zeigt sie also als unbekannte Typen an — gelöscht werden sie nicht, und eine erneute Installation bringt sie unversehrt zurück.