Git-Tag pushen, fertig: automatisches TYPO3 Deployment mit GitHub Actions
Warum automatisierte Deployments?
Manuelles Deployment über SFTP war gestern. Dateien einzeln hochladen, Composer auf dem Server laufen lassen, den Cache von Hand leeren – das kostet Zeit, ist fehleranfällig und lässt sich schlecht dokumentieren. Mit GitHub Actions und Deployer läuft das alles automatisch ab, sobald ich ein Git-Tag setze.
Das Ergebnis: ein reproduzierbarer, stabiler Deploy-Prozess – mit Zero Downtime, automatischem Rollback und ohne dass ich einen einzigen Handgriff machen muss.
Was wir bauen
Der Ablauf sieht so aus: Ich setze ein Tag in Git (z. B. v1.2.0), GitHub Actions startet automatisch, baut das Projekt, und Deployer überträgt alles per SSH auf den Server. TYPO3 v14 läuft dabei ohne Downtime.
Voraussetzungen
- TYPO3 v14 als Composer-basiertes Projekt
- PHP 8.2 oder höher auf dem Server (Pflicht für TYPO3 v14)
- SSH-Zugang zum Shared Hosting
- GitHub Repository mit Actions aktiviert
Schritt 1: Deployer installieren
Deployer wird lokal als Composer Dev-Dependency installiert:
composer require --dev deployer/deployer
Schritt 2: deploy.php konfigurieren
Die deploy.php im Projektstamm ist das Herzstück. Sie nutzt das offizielle TYPO3-Recipe von Deployer 8.x, das public_dir und bin/typo3 automatisch aus der composer.json liest:
<?php
namespace Deployer;
require 'recipe/typo3.php';
// Projektname
set('application', 'mein-typo3-projekt');
// Git Repository
set('repository', 'git@github.com:dein-user/dein-repo.git');
// Anzahl der aufbewahrten Releases (für Rollback)
set('keep_releases', 3);
// Composer-Optionen für Production
set('composer_options', '--no-dev --prefer-dist --no-progress --no-interaction --optimize-autoloader');
// Shared Dirs – bleiben über Releases hinweg erhalten
add('shared_dirs', [
'public/fileadmin',
'public/typo3temp/assets',
'var/log',
'var/lock',
'var/session',
]);
// Shared Files
add('shared_files', [
'.env',
'public/.htaccess',
]);
// Writable Dirs
add('writable_dirs', [
'public/fileadmin',
'public/typo3temp',
'var',
]);
// Host-Konfiguration
host('production')
->setHostname('deinserver.example.com')
->setRemoteUser('ssh-user')
->setPort(22)
->set('deploy_path', '/var/www/html/mein-projekt')
->set('branch', 'main')
->set('bin/php', '/usr/bin/php8.2') // PHP 8.2+ für TYPO3 v14
->set('writable_mode', 'chmod');
// TYPO3 Cache nach dem Deploy leeren
// Nach deploy:publish (enthält symlink + unlock + cleanup)
after('deploy:publish', 'typo3:cache:flush');
// Bei fehlgeschlagenem Deploy: automatisch entsperren
after('deploy:failed', 'deploy:unlock');TYPO3 v14 Hinweis: Das Recipe liest
public_dirautomatisch aus deinercomposer.json– du musst den Webroot nicht manuell setzen. Stelle sicher dassbin/phpauf PHP 8.2 oder höher zeigt.
Shared Hosting: Symlink-Caveat
Auf manchen Shared-Hosting-Umgebungen ignoriert der Webserver Symlinks oder cached den alten Pfad. Wenn nach dem Deploy noch die alte Version ausgeliefert wird, hilft folgendes: Prüfe ob dein Hosting-Provider Symlinks im Document Root erlaubt. Falls nicht, kannst du Deployer statt des Symlinks den Release-Ordner direkt als Document Root konfigurieren – oder beim Provider nachfragen ob FollowSymLinks in der Apache-Konfiguration aktiv ist.
Schritt 3: SSH-Key für GitHub Actions hinterlegen
GitHub Actions braucht einen SSH-Key um sich am Server anzumelden. Den privaten Key hinterlegst du als GitHub Secret:
- SSH-Key-Paar lokal generieren:
ssh-keygen -t ed25519 -C "github-actions-deploy" - Den öffentlichen Key auf dem Server in
~/.ssh/authorized_keyseintragen - Den privaten Key in GitHub unter Settings → Secrets → Actions als
SSH_PRIVATE_KEYhinterlegen
Schritt 4: GitHub Actions Workflow
Die Workflow-Datei kommt nach .github/workflows/deploy.yml:
name: Deploy to Production
on:
push:
tags:
- 'v*' # Trigger nur bei Tags wie v1.0.0, v1.2.3 etc.
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup PHP 8.2
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: composer:v2
- name: Install Composer Dependencies
run: composer install --no-dev --prefer-dist --no-progress --optimize-autoloader
- name: Setup SSH Agent
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Add Server to known_hosts
run: ssh-keyscan -H deinserver.example.com >> ~/.ssh/known_hosts
- name: Deploy with Deployer
run: ./vendor/bin/dep deploy production --tag=${{ github.ref_name }} -vv
Wie der Deploy abläuft
Sobald ich ein Tag setze, passiert folgendes automatisch:
- GitHub Actions checkt das Repository aus
- Composer installiert alle Dependencies (ohne Dev-Packages)
- Deployer verbindet sich per SSH mit dem Server
- Ein neues Release-Verzeichnis wird angelegt
- Shared Dirs (fileadmin, var/log etc.) werden per Symlink eingehängt
- Der Symlink auf
currentwird atomisch umgestellt – Zero Downtime - TYPO3 Cache wird geleert
- Alte Releases werden aufgeräumt (3 werden behalten)
Rollback in einer Zeile
Läuft etwas schief, ist der Rollback trivial:
./vendor/bin/dep rollback production
Deployer stellt den Symlink auf das vorherige Release zurück – die Seite läuft sofort wieder.
Zusammengefasst
- Deployer 8.x per Composer installieren – das TYPO3-Recipe liest
public_dirautomatisch aus dercomposer.json deploy.phpmit Host, Shared Dirs und PHP 8.2-Pfad konfigurieren- SSH-Key als GitHub Secret hinterlegen
- GitHub Actions Workflow mit Tag-Trigger anlegen
- Tag setzen → alles läuft automatisch, Zero Downtime, Rollback jederzeit möglich
Share
Leave a comment