# Zero-Downtime-Deployments, Push to Deploy und Rollbacks

> So deployt Vimonto Deploy deine Site ohne Ausfallzeit: Releases, Deploy-Skript mit Variablen, Push to Deploy, Deploy-URLs für CI und schnelle Rollbacks.

Ein **Deployment** bringt eine neue Version deines Codes auf deinem Server live. Vimonto Deploy klont deinen Branch in ein neues Release-Verzeichnis, führt dort dein Deploy-Skript aus und schaltet die Site erst dann in einem atomaren Schritt um. Bis zu diesem Moment bekommen Besucher die vorherige Version zu sehen. Ein fehlgeschlagener Build legt deine Site also nie lahm.

Du kannst per Button deployen, bei jedem Push auf deinen Branch oder aus deiner CI mit einer Deploy-URL. Die letzten Releases bleiben auf dem Server, sodass du in Sekunden zu einer früheren Version zurückkehrst.

![Die Seite Deployments mit Repository, Deploy-Skript, Quick Deploy, Deploy-URL und der Liste der Deploys](https://ops.vimonto.com/docs-media/de/site-deployments.webp?v=161e760d "Die Seite Deployments einer Site")

## Wie funktioniert ein Zero-Downtime-Deployment?

Jede Site ist auf der Festplatte für Zero-Downtime-Deploys angelegt:

```text
/home/{user}/{directory}/
├── releases/
│   ├── 20261007141502/     one directory per deploy
│   └── 20261007153044/
├── shared/
│   ├── .env                kept between releases
│   └── storage/            Laravel only
└── current -> releases/20261007153044
```

Nginx liefert die Site aus `current` aus. Ein Deploy durchläuft diese Schritte, die du live verfolgen kannst:

| Schritt | Was passiert |
|---|---|
| **Code abrufen** | Der Branch wird in ein neues Release geklont, das nach Datum und Uhrzeit benannt ist (ein Shallow Clone des neuesten Commits). Commit-Hash, Autor und Nachricht werden gespeichert. |
| **Deploy-Skript ausführen** | Die geteilte `.env` wird ins Release verlinkt (bei Laravel auch `storage/`). Dann läuft dein Deploy-Skript im Release, als Benutzer der Site. |
| **Live schalten** | `current` wird mit einem atomaren Umbenennen auf das neue Release gesetzt. PHP-FPM wird neu geladen, damit OPcache die neuen Dateien übernimmt. |
| **Alte Releases aufräumen** | Alte Releases werden entfernt; die fünf neuesten bleiben erhalten. |

Nach dem Live-Schalten startet Vimonto Deploy auch neu, was deinen Code ausführt: Laravel-Queue-Worker bekommen `artisan queue:restart`, Node.js-Prozesse werden neu gestartet, und jedes eingeschaltete [Site-Feature](https://ops.vimonto.com/docs/de/sites/site-features) führt seinen eigenen Befehl aus (zum Beispiel `horizon:terminate` für Horizon).

Hat dein Repository beim ersten Deploy einer Site eine `.env.example`, wird die `.env` vor dem Deploy-Skript auf ihrer Grundlage neu aufgebaut: mit den Keys, der Reihenfolge und den Kommentaren des Beispiels, ergänzt um die Werte, die Vimonto Deploy generiert hat. Das Deploy-Log vermerkt das, und der [.env-Verlauf](https://ops.vimonto.com/docs/de/sites/environment#frühere-versionen-ansehen-und-wiederherstellen) bewahrt die Version als **Auf .env.example aufgebaut** auf. Das passiert nur einmal. Siehe [Umgebung](https://ops.vimonto.com/docs/de/sites/environment).

Bei jedem Abruf werden außerdem die Pakete in deiner `composer.json` und `package.json` gelesen, damit das Menü der [Site-Features](https://ops.vimonto.com/docs/de/sites/site-features) die Tools markieren kann, die deine App nutzt.

### Was passiert, wenn ein Deploy fehlschlägt?

Schlägt das Abrufen oder das Deploy-Skript fehl, wird das neue Release verworfen und `current` bleibt unangetastet. Die Deploy-Seite zeigt **Deploy fehlgeschlagen** mit dem Fehler und **Die Live-Version hat sich nicht geändert.** Öffne **Details und Log**, um die Ausgabe jedes Schritts zu sehen, behebe das Problem und klicke auf **Erneut deployen**.

## Jetzt deployen

Klicke auf **Jetzt deployen** im Site-Header oben auf jeder Seite der Site. Du landest auf der eigenen Seite des Deploys, die die Phasen, den laufenden Schritt und den Fortschritt zeigt. Du musst das Fenster nicht offen lassen: Der Deploy läuft auf dem Server, du bekommst in der App eine Meldung, sobald er fertig ist, und ein abgeschlossener oder fehlgeschlagener Deploy sendet außerdem eine [Benachrichtigung](https://ops.vimonto.com/docs/de/more/notifications). Sollen die Deploy-Ergebnisse einer Site auch an deinen eigenen Endpunkt oder weitere E-Mail-Adressen gehen, richte ihre [Deploy-Benachrichtigungen](https://ops.vimonto.com/docs/de/sites/site-settings#deploy-benachrichtigungen) ein.

Pro Site läuft immer nur ein Deploy gleichzeitig. Startest du einen weiteren, während einer läuft, siehst du **Für … läuft bereits ein Deployment**, mit der Domain der Site.

## Repository verbinden oder ändern

Das Panel **Repository** zeigt das Repository, den Branch und den Status des **Deploy Key**. Klicke auf **Repository verbinden** oder **Ändern**, um ein Repository von einem [verbundenen Git-Host](https://ops.vimonto.com/docs/de/connections/source-control) zu wählen oder eine **Eigene Git-URL** zu verwenden.

- **Verbundener Git-Host**: Der Deploy Key der Site wird im Repository als schreibgeschützter Deploy Key registriert und beim Wechsel aus dem alten Repository entfernt. Bei einem neu verknüpften Repository wird **Bei jedem Push deployen** sofort eingeschaltet.
- **Eigene Git-URL**: Nutze für ein privates Repository eine SSH-URL (`git@…`) und füge den Schlüssel unter **Deploy Key dieser Site** bei deinem Git-Host als Deploy Key hinzu. Für ein öffentliches Repository nutzt du eine HTTPS-URL. **Bei jedem Push deployen** ist aus, weil nur ein verbundener Git-Host einen Webhook von Vimonto Deploy bekommen kann.

## Das Deploy-Skript bearbeiten

Das Panel **Deploy-Skript** enthält das Bash-Skript, das ein Release baut, in einem Code-Editor mit Shell-Hervorhebung. Es beginnt mit einem Skript, das zu deinem Framework passt. Du kannst es frei bearbeiten und mit **Speichern** sichern (oder mit <kbd>⌘</kbd> <kbd>S</kbd>, <kbd>Strg</kbd> <kbd>S</kbd>). Das nächste Deployment verwendet es. **Standard** setzt das generierte Skript wieder in den Editor; gespeichert wird es erst, wenn du auf **Speichern** klickst.

Das Standardskript einer Laravel-Site sieht so aus:

```bash
$VIMONTO_COMPOSER install --no-dev --no-interaction --prefer-dist --optimize-autoloader

if [ -f package.json ]; then
    if [ -f package-lock.json ]; then npm ci; else npm install; fi
    npm run build
fi

$VIMONTO_PHP artisan storage:link --force
$VIMONTO_PHP artisan migrate --force
$VIMONTO_PHP artisan optimize
```

Symfony-Sites leeren den Cache und führen Doctrine-Migrationen aus, wenn es einen Ordner `migrations` gibt. Statamic-Sites wärmen zusätzlich den Stache auf. Statische und Node.js-Sites installieren die Pakete und führen den Build-Befehl aus.

Das Skript läuft als Benutzer der Site im Verzeichnis der App innerhalb des neuen Releases (bei einem Monorepo im Stammverzeichnis), mit `set -e`: Der erste fehlgeschlagene Befehl stoppt den Deploy.

### Welche Variablen kann das Deploy-Skript nutzen?

| Variable | Wert |
|---|---|
| `$VIMONTO_PHP` | Das PHP-Binary der PHP-Version der Site, etwa `php8.4`. |
| `$VIMONTO_COMPOSER` | Composer, ausgeführt mit der PHP-Version der Site. |
| `$VIMONTO_RELEASE_PATH` | Das Verzeichnis der App im neuen Release. |
| `$VIMONTO_SITE_PATH` | Das Verzeichnis der Site, etwa `/home/vimonto/shop.example.com`. |
| `$VIMONTO_BRANCH` | Der Branch, der deployt wird. |
| `$VIMONTO_COMMIT` | Der vollständige Hash des Commits, der deployt wird. |

Nutze `$VIMONTO_PHP` und `$VIMONTO_COMPOSER` statt `php` und `composer`, damit das Skript der PHP-Version der Site folgt, wenn du sie änderst.

> [!TIP]
> Zugangsdaten aus **Composer-Authentifizierung** und **npm-Authentifizierung** (beim Anlegen der Site festgelegt) stehen nur während des Builds zur Verfügung, über `COMPOSER_AUTH` und eine temporäre npm-Konfiguration. Später verwaltest du sie in den **Einstellungen** der Site in den Tabs **Composer** und **npm**: siehe [Zugangsdaten für Composer und npm](https://ops.vimonto.com/docs/de/sites/site-settings#zugangsdaten-für-composer-und-npm).

## Push to Deploy

Bei einem Repository von einem verbundenen Git-Host enthält das Panel **Quick Deploy** die Option **Bei jedem Push deployen**. Sie wird von selbst eingeschaltet, wenn du das Repository verknüpfst, beim Anlegen oder später: Vimonto Deploy fügt dem Repository bei GitHub, GitLab oder Bitbucket einen Webhook hinzu. Jeder Push auf den Branch der Site startet dann einen Deploy; Pushes auf andere Branches werden ignoriert. Schaltest du die Option aus, wird der Webhook wieder entfernt.

Bei einem Repository mit eigener Git-URL weist das Panel darauf hin, stattdessen die Deploy-URL von deinem Git-Host oder deiner CI aus aufzurufen.

## Aus der CI mit der Deploy-URL deployen

Das Panel **Deploy-URL** zeigt Personen, die Sites verwalten dürfen, eine geheime URL für die Site. Ein `POST`-Request darauf deployt den Branch der Site:

```bash
curl -X POST https://…/deploy/your-secret-token
```

Nutze sie als letzten Schritt einer GitHub-Actions-, GitLab-CI- oder anderen Pipeline, damit ein Deploy erst startet, wenn deine Tests bestanden sind. Die Antworten sind einfaches JSON:

| Status | Meldung | Bedeutung |
|---|---|---|
| `202` | `Deploy started.` | Der Deploy steht in der Warteschlange; die Antwort enthält seine ID. |
| `409` | `A deploy is already running.` | Versuche es erneut, wenn der laufende Deploy fertig ist. |
| `422` | Der Grund | Die Site ist nicht bereit oder hat kein Repository. |
| `404` | | Das Token ist falsch. |

Die URL akzeptiert 60 Requests pro Minute. Jeder, der die URL kennt, kann einen Deploy starten, also halte sie geheim. Klicke auf **Neu generieren**, um eine neue zu erzeugen; die alte URL funktioniert sofort nicht mehr, und der Webhook bei deinem Git-Host wird für dich aktualisiert.

## Einen Deploy verfolgen und seine Ausgabe lesen

Die Liste **Deploys** zeigt jeden Deploy, die neuesten zuerst, 15 pro Seite: Status, Commit, wie er gestartet wurde (**Manuell**, **Push**, **Deploy-URL**, **Rollback** oder **API**, für Deploys, die über die [REST-API](https://ops.vimonto.com/docs/de/more/api) oder die [CLI](https://ops.vimonto.com/docs/de/more/cli) gestartet wurden), wer ihn gestartet hat, den Autor des Commits, den Branch und wie lange er gedauert hat. Das Live-Release trägt ein Badge **Live**. Auch die Übersicht der Site zeigt die letzten Deploys.

Klicke auf **Ansehen**, um einen Deploy zu öffnen. Seine Seite zeigt die Phasen **Abrufen**, **Build** und **Live**, den Fortschritt während der Ausführung und unter **Details und Log** die Ausgabe jedes Schritts. Das Panel **Commit** listet Nachricht, Commit, Autor, Branch, Release und Startzeitpunkt. Mit **Zurück** und **Weiter** wechselst du zwischen Deploys.

![Ein abgeschlossener Deploy mit seinen Phasen, Commit-Details und Log](https://ops.vimonto.com/docs-media/de/deployment-detail.webp?v=161e760d "Ein einzelner Deploy")

## Auf ein früheres Release zurücksetzen

Weil die fünf neuesten Releases auf dem Server bleiben, kannst du ein früheres wieder live schalten, ohne etwas zu bauen:

1. Suche den Deploy in der Liste **Deploys** und klicke auf **Zurücksetzen**, oder öffne ihn und klicke auf **Auf dieses Release zurücksetzen**.
2. Bestätige. `current` zeigt sofort wieder auf dieses Release, PHP-FPM wird neu geladen und Worker werden neu gestartet.

Ein Rollback erscheint in der Liste als **Zurückgesetzt auf …**. Rollbacks setzen Zero-Downtime-Deploys voraus und funktionieren nur für Releases, die noch auf dem Server liegen.

> [!WARNING]
> Datenbankmigrationen werden nicht zurückgesetzt. Hat ein Release eine Migration ausgeführt, mit der der ältere Code nicht umgehen kann, setze die Migration zuerst selbst zurück.

## Deploys direkt im Release ohne Zero Downtime

Ist **Zero-Downtime-Deploys** aus (beim [Anlegen der Site](https://ops.vimonto.com/docs/de/sites/create-a-site#zero-downtime-deploys) oder in den [Site-Einstellungen](https://ops.vimonto.com/docs/de/sites/site-settings) gewählt), aktualisiert jeder Deploy direkt ein einziges Release, `releases/live`. Der Code wird abgerufen und auf den Branch zurückgesetzt, während ignorierte Dateien wie `vendor/` und `node_modules/` erhalten bleiben. Builds sind dadurch schneller.

Die Nachteile:

- Besucher sehen die Site eventuell, während sie gebaut wird.
- Ein fehlgeschlagener Build wird nicht verworfen: Der Live-Code ist der Code, dessen Build fehlgeschlagen ist.
- Es gibt keine alten Releases, also kein Rollback und keinen Aufräumschritt.

## Häufig gestellte Fragen

### Muss ich die Deploy-Seite offen lassen?

Nein. Deploys laufen als Hintergrundaufgaben auf dem Server. Du kannst die Seite schließen, und wer den Deploy gestartet hat, bekommt eine Benachrichtigung, sobald er endet. Alle Aufgaben verfolgst du auf der Seite [Aktivität](https://ops.vimonto.com/docs/de/organization/activity). Jeder Deploy und jedes Rollback wird außerdem im [Audit-Log](https://ops.vimonto.com/docs/de/organization/audit-log) festgehalten.

### Hat eine lastverteilte Site Deploys?

Nein. Eine Site auf einem Load Balancer hat keinen Code und deshalb keine Seite Deployments. Deploye die Site auf jedem App-Server dahinter. Siehe [Lastverteilung](https://ops.vimonto.com/docs/de/sites/load-balancing).

### Wie viele Releases werden aufbewahrt?

Fünf: die neuesten Releases, immer einschließlich des Live-Release. Ältere werden nach jedem erfolgreichen Deploy entfernt.

### Warum hat mein Push keinen Deploy gestartet?

Prüfe, ob **Bei jedem Push deployen** aktiv ist und ob du auf den Branch der Site gepusht hast. Pushes auf andere Branches werden ignoriert. Läuft bereits ein Deploy, wird ein zweiter ebenfalls abgelehnt.

### Kann ich Migrationen nur bei manchen Deploys ausführen?

Das Deploy-Skript ist normales Bash, du kannst also Bedingungen verwenden. Prüfe zum Beispiel `$VIMONTO_BRANCH` oder eine Datei im Release, bevor du `$VIMONTO_PHP artisan migrate --force` ausführst.
