Git-Tag pushen, fertig: automatisches TYPO3 Deployment mit GitHub Actions
Typo3

Git-Tag pushen, fertig: automatisches TYPO3 Deployment mit GitHub Actions

Yannick Aister 4 min read 73 Views

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_dir automatisch aus deiner composer.json – du musst den Webroot nicht manuell setzen. Stelle sicher dass bin/php auf 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:

  1. SSH-Key-Paar lokal generieren: ssh-keygen -t ed25519 -C "github-actions-deploy"
  2. Den öffentlichen Key auf dem Server in ~/.ssh/authorized_keys eintragen
  3. Den privaten Key in GitHub unter Settings → Secrets → Actions als SSH_PRIVATE_KEY hinterlegen

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:

  1. GitHub Actions checkt das Repository aus
  2. Composer installiert alle Dependencies (ohne Dev-Packages)
  3. Deployer verbindet sich per SSH mit dem Server
  4. Ein neues Release-Verzeichnis wird angelegt
  5. Shared Dirs (fileadmin, var/log etc.) werden per Symlink eingehängt
  6. Der Symlink auf current wird atomisch umgestellt – Zero Downtime
  7. TYPO3 Cache wird geleert
  8. 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

  1. Deployer 8.x per Composer installieren – das TYPO3-Recipe liest public_dir automatisch aus der composer.json
  2. deploy.php mit Host, Shared Dirs und PHP 8.2-Pfad konfigurieren
  3. SSH-Key als GitHub Secret hinterlegen
  4. GitHub Actions Workflow mit Tag-Trigger anlegen
  5. Tag setzen → alles läuft automatisch, Zero Downtime, Rollback jederzeit möglich

Leave a comment