Dieses Manual zeigt Schritt für Schritt die Basisinstallation eines per.net Drupal-11-Projekts mit Composer, inkl. Git und GitLab, Datenbank, Settings-Struktur, MAMP und Drush.
Intro
- Git zuerst: Das Repository wird gleich zu Beginn angelegt, damit jeder Schritt nachvollziehbar versioniert ist.
- Settings vor der Installation: Alle Settings-Dateien inkl. DB-Zugang mit Kollation werden angelegt, bevor Drupal installiert wird. Der Grund ist eine Kollation der Datenbank, die ohne Vorgabe in der Settings-Datei nicht kompatibel zwischen SQL8 und Maria DB ist (siehe 1.5).
Für die Testinstallationen gilt ein eigener, vereinfachter Ablauf ohne Settings-Struktur.
1 -- Installation
1.1 -- Projektverzeichnis anlegen
Projektverzeichnis mit der folgenden Struktur anlegen:
projekt/ Projektverzeichnis
├── --pernet-arbeitsfiles/ nicht versioniert, ausser README.md
├── --pernet-docs/ versioniert
├── --pernet-starter/
│ └── settings-examples/ Vorlagen settings local, dev, stage, live
├── config/
│ └── sync/ versioniert, mit .gitkeep
├── private/ nicht versioniert
│ ├── db-dump/
│ ├── deployment-settings/ echte settings.*.php mit Zugangsdaten
│ └── tmp/
├── public/ Composer-Root
│ ├── composer.json
│ ├── composer.lock
│ ├── vendor/
│ └── web/ Drupal-Root / Site-Folder (MAMP)
└── tools/ Lokale Erweiterungen
└── frontend/ BrowserSync1.2 -- Git einrichten
- ### WICHTIG: im Projektverzeichnis ausführen, nicht in public.
Es muss die komplette Struktur ins Git Repository aufgenommen werden, nicht nur der Inhalt von public. git init- .gitignore im Projektverzeichnis erstellen und folgenden Code einkopieren:
# macOS .DS_Store # VS Code .vscode/ # per.net Erstellungsdaten /--pernet-arbeitsfiles/* !/--pernet-arbeitsfiles/README.md # Composer-Abhängigkeiten /public/vendor/ # Drupal Core und Contrib /public/web/core/ /public/web/modules/contrib/ /public/web/themes/contrib/ # Öffentliche Dateien /public/web/media/ /public/web/sites/*/files/ # Private Dateien /private/ # Logs *.log # Umgebungsspezifische Settings /public/web/sites/default/settings.local.php /public/web/sites/default/settings.dev.php /public/web/sites/default/settings.stage.php /public/web/sites/default/settings.live.php # Frontend-Abhängigkeiten /tools/frontend/node_modules/
1.3 -- GitLab einrichten und verknüpfen
- Neues Projekt anlegen
- Gruppe auswählen: per-net
- Projektname angeben z.B.: [projektname]
- Sichtbarkeit: privat
- Keine Readme-Datei erstellen
- Im Projektverzeichnis verknüpfen:
git remote add origin git@gitlab.com:per-net/[projektname].git- Zur Kontrolle:
git remote -v
1.4 -- Erster Commit und Push
git status git add -A git commit -m "Gerüst: Ordnerstruktur, .gitignore, Doku" git push -u origin main- ### WICHTIG:
git push -u origin maingilt nur für den ersten Push in ein neues, leeres GitLab-Projekt. Legt Branch main auf GitLab an und verbindet meinen lokalen main damit. git push
Dieser Kurzbefehl reicht für alle späteren Push-Befehle.- Arbeitsweise: lokal oft committen, an Etappenstopps oder am Ende einer Sitzung pushen.
git commit --amendnur vor dem Push. - ### TIPP: Falls in VS Code noch Punkte dastehen, obwohl git clean ist:
- Cmd + Shift + P (oder Menu > View > Command palette)
Developer: Reload Window
1.5 -- Datenbank einrichten
Neue Datenbank einrichten:
- MAMP
- Webstart > Tools > PHPmyAdmin
- PHPmyAdmin
- Neue Datenbank erstellen (Kollation: utf8mb4_general_ci)
- Neuen Benutzer anlegen (Nur Benutzername, PW, keine weiteren Settings nötig)
so wird der Benutzer direkt der neu erstellten DB zugeordnet und erhält alle Rechte
- Warum die Kollation so wichtig ist: Das Installationsformular von Drupal kennt kein Feld für die Kollation. Ohne Vorgabe in den Settings übernimmt Drupal den Standard des Datenbankservers (bei MariaDB meist eine andere Kollation) und legt alle Tabellen damit an. Darum wird die Kollation in 1.8 in
settings.local.phpfest eingetragen, bevor Drupal installiert wird.
1.6 -- Drupal Struktur mit Composer anlegen
- vscode > Terminal
- ### WICHTIG: ins Public Verzeichnis wechseln:
cd public
- PHP Version prüfen (Aktuell für Drupal 11.4: php 8.3)
- ### WICHTIG!!!
- MAMP php Version muss mit der Composer PHP übereinstimmen.
which php php -v usephp83 php -v- Konfiguration für verschiedene PHP-Versionen ist in ~/.zshrc definiert, aktuell für php 7.4, php 8.3, php 8.4 (Stand August 2026)
composer create-project drupal/recommended-project .- Der Punkt am Ende heisst «hier». Ohne Punkt legt Composer einen Unterordner
recommended-projectan. Steht man noch im Projektverzeichnis, geht auchcomposer create-project drupal/recommended-project public.
- ### WICHTIG: ins Public Verzeichnis wechseln:
1.7 -- Composer-.gitignore abschalten
Composer kopiert bei jeder Installation und jedem Update einige Dateien aus dem Core-Paket an ihren Platz («Scaffolding»), z. B. default.settings.php, default.services.yml, example.settings.local.php, development.services.yml, .htaccess, robots.txt und index.php.
Weil vendor/ in der .gitignore steht, nimmt Composer an, dass auch diese Kopien nicht versioniert werden sollen, und legt dafür automatisch eigene .gitignore-Dateien an. Das widerspricht meinem Bauplan: Die Originaldateien sollen versioniert sein, damit ich nach einem Core-Update in Git sofort sehe, ob sich daran etwas geändert hat.
- In
public/composer.jsonim Blockdrupal-scaffolddie Zeile"gitignore": falseergänzen: "drupal-scaffold": { "gitignore": false, "locations": { "web-root": "web/" } },- Danach die 8 von Composer angelegten
.gitignore-Dateien löschen (im Finder versteckte Dateien mit Cmd + Shift + . einblenden), alle unterhalb vonpublic/: public/.gitignore public/recipes/.gitignore public/web/.gitignore public/web/modules/.gitignore public/web/profiles/.gitignore public/web/sites/.gitignore public/web/sites/default/.gitignore public/web/themes/.gitignore- ### WICHTIG: Die .gitignore im Projektverzeichnis bleibt, das ist die eigene. Ohne die Zeile in composer.json würde Composer die Dateien beim nächsten Update wieder anlegen.
1.8 -- Settings-Dateien anlegen
Aufbau und Hintergrund der Settings-Dateien sind im Artikel «Settings-Struktur» beschrieben. Hier nur die Handgriffe:
- In
public/web/sites/default/aus dem Starter bzw. dem letzten Projekt übernehmen:- settings.php (Pfade für config/sync, media, private, tmp und Umgebungsweiche)
- settings.development.php
- In
public/web/sites/: development.pernet.services.yml - settings.local.php: Vorlage aus
--pernet-starter/settings-examples/nachprivate/deployment-settings/kopieren, dort ausfüllen und nachpublic/web/sites/default/kopieren:- DB-Name, DB-User, DB-Passwort aus 1.5 (die Kollation
utf8mb4_general_cisteht schon in der Vorlage) - hash_salt erzeugen (Terminal) und Ausgabe anstelle des Platzhalters einsetzen:
php -r 'echo bin2hex(random_bytes(32)), PHP_EOL;'
- Trusted Host = lokaler Hostname aus 1.10, z. B.
'^local\.projekt\.test$'
- DB-Name, DB-User, DB-Passwort aus 1.5 (die Kollation
- Mit den DB-Einstellungen in den Settings wird die DB-Einstellungsseite im Installationsprozess nicht mehr angezeigt, und die Tabellen werden mit der richtigen Kollation erstellt.
1.9 -- Commit
- Vor dem Commit mit
git statusprüfen:settings.local.phpdarf nicht in der Liste stehen.default.settings.php,example.settings.local.phpunddevelopment.services.ymlsollen drin sein. git add -A git commit -m "Drupal per Composer, Settings-Struktur, Scaffold-Dateien versioniert"
1.10 -- MAMP einrichten
- MAMP
- New Site > Empty
- Site name: [local.projekt.test], muss mit dem Trusted Host in settings.local.php übereinstimmen
- Site folder festlegen: /public/web
- PHP Version prüfen (Aktuell für Drupal 11.4: php 8.3)
- SSL einrichten (manual folgt ...)
1.11 -- Drupal installieren
- Site-URL im Browser aufrufen
- Installation auf Deutsch starten (Hauptsprache der Inhalte)
- Installationsprofil: Standard
- DB-Daten: Diese Seite wird übersprungen, weil in den Settings schon alles definiert ist. Falls hier trotzdem die DB-Seite angezeigt wird, stoppen, dann stimmt etwas mit den Settings-Daten nicht.
- Site Name und weitere Basisinfos eintragen:
- Sitename: Projektname
- Site email address: webmaster@projektname.ch (Systemmeldungen werden mit dieser Absenderadresse versandt)
- Username: [Mein Adminname]
- Password: [xxxx]
- E-Mail: mail@per-net.ch
- Timezone: Zurich
- ### WICHTIG: Immer in der Hauptsprache der Inhalte installieren. Die mitgelieferte Config bleibt in der Installationssprache, ein späterer Wechsel der Standardsprache hilft nicht. Rein englisches Projekt: englisch installieren, Deutsch bei Bedarf nachziehen.
1.12 -- Übersetzung prüfen
- Der Installer lädt die deutsche Übersetzung automatisch. Kontrolle: Reports > Available translation updates (Ziel: um 99 %)
- Falls die Übersetzung unvollständig ist (passiert bei ganz neuen Core-Versionen, die .po-Datei auf dem Server ist dann noch nicht fertig):
- Die .po-Datei der Vorversion von localize.drupal.org herunterladen (z. B.
drupal-11.4.8.de.po) - Importieren: Configuration > Regional and language > User interface translation > Import
- Optionen: nicht als «custom» importieren, «Overwrite non-customized translations» an
- Später nochmals Reports > Available translation updates > Check manually, sobald die aktuelle Datei komplett ist
- Die .po-Datei der Vorversion von localize.drupal.org herunterladen (z. B.
- Aufräumen: Den Ordner
public/web/sites/default/files/translationsim Finder löschen. Das ist ein Rest des Installers, Drupal nutztmedia/translations.
1.13 -- Englisch fürs Backend
- Backend ist zu diesem Zeitpunkt noch deutsch, die Menüpunkte heissen sinngemäss gleich.
- Englisch als zweite Sprache hinzufügen: Configuration > Regional and language > Languages > Add language (nur Oberflächensprache, kein Content Translation)
- Spracherkennung: Configuration > Regional and language > Languages > Detection and selection
- «Account administration pages» aktivieren und über «URL» ziehen > Save
- Eigenes Konto: People > [Mein Adminname] > Edit > Administration pages language: English
- Ergebnis: Backend englisch, Frontend deutsch
1.14 -- Drush
- Im Ordner
public:composer require drush/drush
- ### WICHTIG: Drush ohne
--devinstallieren. Auf Stage/Live wird mitcomposer install --no-devinstalliert, dort braucht es Drush fürs Deployment trotzdem.
1.15 -- Kontrolle und Commit
- Abmelden und wieder anmelden
drushh cr drushh cex- In
config/syncliegen jetzt rund 150 Dateien. Stichprobe:system.site.ymlhatlangcode: de git add -A git commit -m "Installation de/en, Backend englisch, Drush, erster Config-Export"
Pkt. 2a: Kapitel 2, Module und Basis-Config html
2 -- Module und Basis-Config
Was die einzelnen Module tun, steht in der Modulliste im Guide des Projekts (Content > Manual & Documentation).
2.1 -- Contrib-Module holen
- Im Ordner
public:composer require drupal/backup_migrate drupal/shield drupal/pathauto drupal/redirect drupal/metatag drupal/simple_sitemap drupal/token drupal/twig_tweak drupal/focal_point drupal/editor_advanced_link drupal/editor_file 'drupal/login_destination:^2.0@beta' drupal/simplelogin drupal/menu_admin_per_menu drupal/paragraphs
- ### WICHTIG: Login Destination gibt es nur als Beta. Ohne
@betabricht Composer den ganzen Befehl ab und installiert gar nichts. - Kommen automatisch mit: Crop (für Focal Point), Entity Reference Revisions (für Paragraphs) und ctools (von Pathauto). ctools wird nicht aktiviert, Pathauto braucht es seit Version 1.11 nicht mehr, liefert es aber noch mit.
2.2 -- Entwicklermodule
composer require --dev drupal/devel drupal/kint- Kint ist ein eigenes Modul (nicht mehr Teil von Devel) und braucht kein ctools mehr.
- ### WICHTIG: Devel und Kint dürfen nicht in den Config-Export. Auf Stage/Live fehlt ihr Code (
composer install --no-dev), eindrushh cimwürde dort abbrechen. Ausgeschlossen werden sie insettings.development.phpmitconfig_exclude_modules, siehe Artikel «Settings-Struktur», 1.1.3. - Kontrolle nach dem Aktivieren (2.4) und vor jedem Deployment: In
config/sync/core.extension.ymldürfendevelundkintnicht stehen.
2.3 -- Shield
- ### WICHTIG: Im Backend keine Shield-Zugangsdaten eintragen. Zugangsdaten und Ein/Aus stehen nur in den Umgebungsdateien (
settings.local.phpusw.), siehe Artikel «Settings-Struktur». - Local: Shield ist aus (
shield_enable = FALSE), die übrigen Zeilen bleiben stehen, damit man es zum Testen schnell einschalten kann. Local ist von aussen nicht erreichbar. - Das Modul selbst ist auf allen Umgebungen aktiv, weil die Modulliste per Config übertragen wird. Ein- und ausgeschaltet wird nur über die Settings.
2.4 -- Module aktivieren
drushh en backup_migrate shield pathauto redirect metatag simple_sitemap token twig_tweak focal_point editor_advanced_link editor_file login_destination simplelogin menu_admin_per_menu paragraphs media media_library responsive_image navigation devel kint- Media, Media Library, Responsive Image und Navigation sind Core-Module, sie müssen nicht per Composer geholt werden.
- Kontrolle:
drushh cr, Site neu laden. Links erscheint die Navigation (ersetzt die alte Toolbar oben).
2.5 -- per.net Module
- Die eigenen Module pernet_env_icon und pernet_guide liegen in GitLab und werden per Composer geholt. Ablauf siehe «per.net Module: GitLab und Composer», Teil B.
- Kurzfassung für ein neues Projekt aus dem Starter (Einträge in
composer.jsonund.gitignoresind schon drin):composer require per-net/pernet_env_icon:^1.0 per-net/pernet_guide:^1.0 drushh en pernet_env_icon pernet_guide drushh cr
- Nach dem Aktivieren von pernet_guide meldet Drupal «content access permissions need to be rebuilt»: Reports > Status report > Rebuild permissions. Das ist normal und einmal pro Installation nötig.
- Kontrolle: Oben links das Umgebungs-Icon (L = local). Unter People > Roles die Rollen «per -- Manual» und «per -- Documentation», unter Structure > Content types Manual und Documentation.
2.6 -- Basic Page
- Standard-Inhaltstyp für jedes Projekt: Structure > Content types > «Basic Page» (
basic_page), Beschreibung «Standardseite», Menü: Main navigation - Felder:
- Inhalt (
field_bas_body, Text formatted long, nur Textformat Basic HTML), in Manage display Label ausgeblendet - Metatags (
field_shared_metatags), in Manage display ausgeblendet.shared, weil das Feld in weiteren Inhaltstypen wiederverwendet wird
- Inhalt (
- URL-Muster: Configuration > Search and metadata > URL aliases > Patterns > Basic Page:
/[node:title] - Paragraphs-Felder kommen pro Projekt dazu.
2.7 -- Rollen
- People > Roles. Die Drupal-Standardrollen bleiben. Benutzer bekommen die Rollen als Staffel (ein Webmaster hat auch Editor und Redaktor).
- per -- Editor (
per_editor): Einsteiger. Backend-Grundrechte (Navigation, Admin-Theme, Inhaltsübersicht, eigene unveröffentlichte Inhalte), Basic Pages erstellen und bearbeiten, eigene löschen, Revisionen, Hauptmenü pflegen, Textformat Basic HTML - per -- Redaktor (
per_redaktor): zusätzlich alle Basic Pages löschen - per -- Webmaster (
per_webmaster): leer, wird pro Projekt nach Bedarf des Kunden ausgebaut - per -- Manual und per -- Documentation: kommen mit pernet_guide (siehe 2.5)
- Kommen neue Inhaltstypen dazu, deren Rechte bei den Rollen ergänzen.
2.8 -- Textformate
- Configuration > Content authoring > Text formats and editors
- Basic HTML (Fliesstext für Editoren): keine Uploads. Button «Bild einfügen» entfernt und Bild-Upload ausgeschaltet. Bilder gehören in Media-Felder bzw. Paragraphs, damit Media Library, Focal Point und Responsive Image greifen.
- Full HTML (nur Admin):
- Bild-Upload nach
images/ck-uploads, max. 4 MB, max. 1000 × 1000 px - Datei-Upload (Button «Datei einfügen»): PDF, DOC, DOCX, TXT, max. 12 MB, nach
files/ck-uploads - Links: Attribut
targeterlaubt («In neuem Fenster öffnen»)
- Bild-Upload nach
- Keine Editor-Stile im Starter, die kommen pro Projekt.
- Kontrolle: Jedes geänderte Format einmal öffnen und Save configuration klicken. CKEditor meldet dabei, falls Toolbar und erlaubte Tags nicht zusammenpassen.
2.9 -- Backup and Migrate
- Configuration > Development > Backup and Migrate
- Zeitpläne (Schedules), alle mit der Datenbank:
- 10 -- stündlich, behält 25
- 20 -- täglich, behält 8
- 30 -- wöchentlich, behält 5 (Profil debugging_full)
- 40 -- monatlich, behält 13
- Ablageorte (Destinations) in
private/backup_migrate/: je einer pro Zeitplan, dazu 50–53 für manuelle DB-Dumps pro Umgebung (local, dev, stage, live) und 99 für ein volles Debug-Backup - Profile (Settings): «DB Dump -- Standard» (ohne Cache-Tabellen, Sessions, Watchdog) und «DB Dump -- Debugging Full» (alles)
- Die Zeitpläne laufen über Cron, also auch lokal. Das ist gewollt: Ein Dump schadet nie, und
private/ist nicht im Git. - Test: Quick Backup mit Source «Default Drupal Database» und Destination «50--DB Dump -- local», danach liegt eine
.gz-Datei inprivate/backup_migrate/50_db_dump_local/.
2.10 -- Modulliste und Kontrolle
- Modulliste mit Beschreibungen als Documentation-Inhalt «Modulliste» anlegen (Content > Create > Documentation), Abschnitt «Projektspezifische Module» leer lassen.
- Abgleich mit den aktiven Modulen:
drushh pm:list --type=module --status=enabled --no-core- Jedes Modul aus der Ausgabe muss in der Liste stehen und umgekehrt. ctools erscheint nicht, weil es nicht aktiviert ist.
- Zum Schluss:
drushh cex
✎ Claude – offen: Wie die Modulliste und künftige Manual-Seiten in neue Projekte kommen (DB-Dump des Starters oder Import), wird in Etappe 7 entschieden.