# Von der Kommandozeile deployen mit der Vimonto Deploy CLI

> Installiere die Vimonto Deploy CLI, melde dich mit einem API-Token an und deploye Sites, verfolge Tasks und starte Rezepte und Backups aus Terminal oder CI.

Die Vimonto Deploy CLI ist ein kleines Kommandozeilen-Tool namens `deploy`. Damit deployst du eine Site, verfolgst ihre Ausgabe und ihren Exit-Code, listest deine Server und Sites auf und startest Rezepte und Backups, aus deinem eigenen Terminal oder aus einer CI-Pipeline wie GitHub Actions oder GitLab CI.

Die CLI ist ein schlanker Client der [Vimonto Deploy API](https://ops.vimonto.com/docs/de/more/api): Jeder Befehl besteht aus einer oder mehreren API-Anfragen, signiert mit einem persönlichen API-Token. Sie kann genau das, was das Token und deine Rolle in der Organisation erlauben, nicht mehr.

## Was brauchst du?

- **PHP 8.2 oder neuer mit der curl-Erweiterung.** Die CLI ist eine einzige PHP-Datei ohne Abhängigkeiten, es gibt also keine Composer-Installation. Prüfe das mit `php -v` und `php -m | grep curl`.
- **Ein API-Token**, erstellt unter **Account-Einstellungen** → **API-Tokens** (siehe [dein Konto](https://ops.vimonto.com/docs/de/more/account)). Das Token wird nur einmal angezeigt, wenn du es erstellst.
- macOS, Linux oder WSL. Unter Windows läuft die CLI auch mit `php deploy …`, blendet das Token beim Tippen aber nur unter macOS und Linux aus.

## Die CLI installieren

Die CLI ist die einzelne Datei `deploy`. Lade sie von deiner Vimonto Deploy-Adresse unter `/cli/deploy` herunter (der Link steht auch unter **Account-Einstellungen** → **API-Tokens**, mit dem Befehl zum Kopieren), mache sie ausführbar und lege sie in ein Verzeichnis in deinem `PATH`:

```bash
curl -fsSL https://deploy.example.com/cli/deploy -o deploy
chmod +x deploy
sudo mv deploy /usr/local/bin/deploy
deploy --version
```

`deploy --version` (oder `deploy version`) zeigt die Version, etwa `deploy 1.1.0`. Ohne die Datei zu verschieben, kannst du sie auch direkt als `./deploy` oder `php deploy` ausführen.

In einer CI-Pipeline committest du die Datei in dein Repository (zum Beispiel als `bin/deploy`) oder lädst sie im Job mit demselben `curl`-Befehl herunter, und führst sie mit `php bin/deploy` aus. Die CLI hat keine weiteren Dateien und braucht keine Installation. Zum Aktualisieren lädst du sie erneut herunter.

## Ein API-Token erstellen

1. Öffne **Account-Einstellungen** → **API-Tokens** und klicke auf **Neuer Token**.
2. Gib ihm einen **Name**, der sagt, wo es verwendet wird, etwa `GitHub Actions` oder `Mein Laptop`.
3. Wähle die **Bereiche**: **Lesen**, **Deploy** und/oder **Schreiben** (siehe die Tabelle unten).
4. Wähle, wann es **Läuft ab**: in 30, 90 oder 365 Tagen oder **Nie**.
5. Klicke auf **Token erstellen** und kopiere das Token aus **Dein neuer Token**. Es wird nur einmal angezeigt; gespeichert wird nur sein Hash.

![Die Seite API-Tokens in den Account-Einstellungen](https://ops.vimonto.com/docs-media/de/account-api-tokens.webp?v=161e760d "API-Tokens")

### Welche Bereiche braucht ein Befehl?

Listen brauchen **Lesen** (oder **Schreiben**). Ein Token mit nur **Deploy** kann trotzdem eine Site deployen und verfolgen: Die CLI sucht die Site über ihre Domain oder ID, und das erlaubt dieser Bereich. Andere Arbeit braucht **Schreiben**.

| Befehle | Bereiche, die das Token braucht |
|---|---|
| `login`, `orgs`, `use` | Jeder Bereich |
| `servers`, `sites`, `databases`, `recipes`, `backups` | **Lesen** oder **Schreiben** |
| `deployments`, `task` | **Lesen**, **Deploy** oder **Schreiben** |
| `deploy` | **Deploy** oder **Schreiben** |
| `database:create`, `recipe:run`, `backup:run` | **Schreiben** |

Zusätzlich zu den Bereichen gilt deine Rolle in der Organisation: Ein Token kann nie mehr als du. Ein Betrachter kann nicht deployen, auch nicht mit einem Token mit **Schreiben**, und Server, auf die du keinen Zugriff hast, werden nicht aufgelistet. Für eine CI-Pipeline, die nur deployt, erstellst du ein Token mit nur **Deploy**.

## Mit deploy login anmelden

Führe `deploy login` aus und beantworte die zwei Fragen: die Adresse von Vimonto Deploy (die URL, die du im Browser öffnest) und das API-Token. Das Token wird beim Tippen oder Einfügen nicht angezeigt.

```text
$ deploy login
URL of your Deploy app, such as https://deploy.example.com: https://deploy.example.com
API token (Account → API tokens):
✓ Logged in as Jane Doe (jane@example.com), scopes: read, deploy.
Organization: acme (change with "deploy use <org>")
```

Du kannst auch beides direkt angeben: `deploy login --url=https://deploy.example.com --token=…`. Beachte, dass ein Token auf der Kommandozeile in deiner Shell-History landet.

Die CLI prüft das Token und speichert dann die URL, das Token und die Organisation (die du mit `--org <slug>` angibst, sonst die bisher gespeicherte, sonst deine erste; `DEPLOY_ORG` wird nie gespeichert) in `~/.config/deploy/config.json` (oder `$XDG_CONFIG_HOME/deploy/config.json`, wenn diese Variable gesetzt ist). Das Verzeichnis wird mit Modus `0700` angelegt und die Datei mit `0600`, sodass nur du sie lesen kannst. Zum Abmelden löschst du diese Datei, und unter **API-Tokens** widerrufst du das Token, wenn du es nicht mehr brauchst.

### Die Organisation wählen

Die meisten Befehle arbeiten in einer Organisation. Nach `deploy login` ist das die Organisation, die du zuletzt verwendet hast, sonst deine erste. Liste deine mit `deploy orgs` auf (die verwendete hat einen `*`) und wechsle mit `deploy use`:

```text
$ deploy orgs
SLUG         NAME       ROLE
* acme       Acme       owner
  acme-labs  Acme Labs  developer

$ deploy use acme-labs
✓ Using acme-labs.
```

Hänge `--org=<slug>` an einen Befehl an, um nur für diesen Befehl eine andere Organisation zu verwenden.

## Die CLI in CI mit Umgebungsvariablen verwenden

In einer Pipeline führst du kein `deploy login` aus. Setze stattdessen diese Umgebungsvariablen; sie haben Vorrang vor der Konfigurationsdatei:

| Variable | Wert |
|---|---|
| `DEPLOY_TOKEN` | Das API-Token. Speichere es als Secret in deiner CI. |
| `DEPLOY_URL` | Die Adresse von Vimonto Deploy, etwa `https://deploy.example.com`. |
| `DEPLOY_ORG` | Der Slug der Organisation, wie in deinen URLs und in `deploy orgs`. |

Farben werden weggelassen, wenn die Ausgabe kein Terminal ist und wenn `NO_COLOR` gesetzt ist.

### GitHub Actions

Lege `DEPLOY_TOKEN` unter **Settings** → **Secrets and variables** → **Actions** deines Repositorys an. Dieser Workflow deployt, nachdem die Tests bestanden sind, und schlägt fehl, wenn das Deployment fehlschlägt:

```yaml
# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    # needs: tests   # führe zuerst deinen Test-Job aus
    steps:
      - uses: actions/checkout@v4

      - name: Deploy shop.example.com
        run: php bin/deploy deploy shop.example.com --watch
        env:
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
          DEPLOY_URL: https://deploy.example.com
          DEPLOY_ORG: acme
```

Die von GitHub gehosteten Ubuntu-Runner bringen PHP und die curl-Erweiterung mit, du musst also nichts einrichten.

### GitLab CI

Lege `DEPLOY_TOKEN` als maskierte Variable unter **Settings** → **CI/CD** → **Variables** deines Projekts an:

```yaml
# .gitlab-ci.yml
deploy:
  stage: deploy
  image: php:8.3-cli
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  variables:
    DEPLOY_URL: https://deploy.example.com
    DEPLOY_ORG: acme
  script:
    - php bin/deploy deploy shop.example.com --watch
```

Mit `--watch` wartet der Job auf das Deployment und bekommt dessen Ergebnis als Exit-Code, sodass ein fehlgeschlagenes Deployment die Pipeline rot macht. Ohne `--watch` endet der Job, sobald das Deployment gestartet ist.

> [!TIP]
> Willst du aus CI nur ein Deployment starten, ohne PHP oder Token? Jede Site hat auch eine geheime Deploy-URL, die du mit `curl` aufrufst. Siehe [Deployments](https://ops.vimonto.com/docs/de/sites/deployments).

## Eine Site deployen

`deploy deploy` deployt den Branch der Site, genau wie **Jetzt deployen** in der App. Nenne die Site über ihre Domain oder ihre ID:

```text
$ deploy deploy shop.example.com --watch
✓ Deploying shop.example.com (main) on web-1.
==> Fetch code
Cloning git@github.com:acme/shop.git (main)
HEAD is now at 3f9c2ab
==> Run deploy script
Installing dependencies from lock file
   INFO  Running migrations.
==> Go live
Linked current → releases/20261007101500
==> Clean up old releases
Kept the last 5 releases.
✓ Deploying to shop.example.com succeeded.
```

Die CLI findet die Site mit einer einzigen Anfrage über ihre Domain oder ID. Haben zwei Server eine Site mit derselben Domain, fügst du `--server <name>` hinzu, um nur auf einem Server zu suchen. Ein aus der CLI gestartetes Deployment erscheint wie jedes andere in der Deploy-Liste der Site; wie Deployments funktionieren, steht unter [Deployments](https://ops.vimonto.com/docs/de/sites/deployments).

Ohne `--watch` startet der Befehl das Deployment und zeigt den Befehl, mit dem du es verfolgst:

```text
$ deploy deploy shop.example.com
✓ Deploying shop.example.com (main) on web-1.
Follow it with: deploy task 4821 --watch
```

Läuft schon ein Deployment der Site, meldet die CLI das und nennt die ID dieses Tasks, damit du ihn verfolgen kannst.

### Einen Task mit --watch verfolgen

Deployments, neue Datenbanken, Rezepte und Backups laufen als Tasks im Hintergrund. `deploy task <id>` zeigt den Status eines Tasks und seine bisherige Ausgabe; mit `--watch` prüft er den Task alle zwei Sekunden, zeigt neue Ausgabe, sobald sie da ist, und endet mit dem Ergebnis:

```text
$ deploy task 4821 --watch
```

`--watch` funktioniert bei `deploy`, `task`, `database:create`, `recipe:run` und `backup:run`.

## Alle Befehle

Führe `deploy help` für die Kurzfassung aus.

| Befehl | Was er tut |
|---|---|
| `deploy login [--url=… --token=…]` | Ein Token prüfen und mit der URL speichern. |
| `deploy orgs` | Deine Organisationen auflisten; `*` markiert die verwendete. |
| `deploy use <org>` | Ab jetzt in einer anderen Organisation arbeiten. |
| `deploy servers` | Server auflisten: ID, Name, Typ, Status, IP-Adresse und PHP-Version. |
| `deploy sites [server]` | Die Sites eines Servers oder aller Server auflisten: ID, Domain, Server, Framework, Status, Branch und letztes Deployment. |
| `deploy deploy <site> [--watch]` | Eine Site deployen (Domain oder ID). |
| `deploy deployments <site>` | Die 25 letzten Deployments: Status, wie es gestartet wurde, Commit und wann. |
| `deploy task <id> [--watch]` | Status und Ausgabe eines Tasks. |
| `deploy databases <server>` | Die Datenbanken eines Servers auflisten. |
| `deploy database:create <server> <name> [--watch]` | Eine Datenbank auf einem Server anlegen. |
| `deploy recipes` | Die Rezepte der Organisation auflisten. |
| `deploy recipe:run <recipe> <server>… [--watch] [--notify]` | Ein Rezept auf einem oder mehreren Servern ausführen. |
| `deploy backups <server>` | Die Backups eines Servers mit Zeitplan und letztem Lauf auflisten. |
| `deploy backup:run <server> <backup> [--watch]` | Jetzt ein Backup erstellen. |
| `deploy version` | Die Version der CLI anzeigen; `deploy --version` tut dasselbe. |
| `deploy help` | Die Liste der Befehle anzeigen. |

Server nennst du über ihren Namen oder ihre ID, Sites über ihre Domain oder ID, Rezepte und Backups über ihren Namen oder ihre ID. Groß- und Kleinschreibung spielt keine Rolle. Setze einen Namen mit Leerzeichen in Anführungszeichen.

### Optionen

| Option | Bedeutung |
|---|---|
| `--watch` | Auf den Task warten und mit seinem Ergebnis enden. |
| `--org=<slug>` | Diese Organisation nur für diesen Befehl verwenden. |
| `--server=<name>` | Die Site nur auf diesem Server suchen (`deploy`, `deployments`). |
| `--url=<url>` | Diese Adresse von Vimonto Deploy nur für diesen Befehl verwenden. |
| `--notify` | `recipe:run`: dir einen Bericht mailen, wenn jeder Server fertig ist. |
| `--version` | Die Version der CLI anzeigen, bei jedem Befehl. |
| `--help`, `-h` | Die Liste der Befehle anzeigen. |

Optionen bekommen ihren Wert nach einem Leerzeichen oder einem `=`: `--org acme` und `--org=acme` sind dasselbe.

### Server und Sites auflisten

```text
$ deploy servers
ID  NAME   TYPE      STATUS  IP            PHP
12  web-1  app       active  203.0.113.10  8.4
14  db-1   database  active  203.0.113.11

$ deploy sites web-1
ID  DOMAIN            SERVER  FRAMEWORK  STATUS     BRANCH  DEPLOYED
31  shop.example.com  web-1   laravel    installed  main    2 h ago
```

### Datenbanken, Rezepte und Backups

```bash
deploy databases web-1
deploy database:create web-1 shop_reports --watch

deploy recipes
deploy recipe:run "Clear caches" web-1 web-2 --watch --notify

deploy backups db-1
deploy backup:run db-1 "Nightly" --watch
```

Ein Datenbankname darf Buchstaben, Ziffern und Unterstriche enthalten, bis zu 63 Zeichen, und der Server muss bereit sein und eine Datenbank installiert haben. `recipe:run` startet einen Task pro Server; mit `--watch` verfolgt er sie nacheinander und schlägt fehl, wenn einer davon fehlgeschlagen ist. Mehr zu Rezepten unter [Rezepte](https://ops.vimonto.com/docs/de/more/recipes).

## Exit-Codes und Fehlermeldungen

| Exit-Code | Wann |
|---|---|
| `0` | Der Befehl hat funktioniert. Mit `--watch`: Der Task war erfolgreich. |
| `1` | Jeder Fehler, oder mit `--watch` ein Task, der fehlgeschlagen ist oder abgebrochen wurde. |

`deploy task <id>` ohne `--watch` endet ebenfalls mit `1`, wenn der Task fehlgeschlagen ist oder abgebrochen wurde, und mit `0`, solange er noch in der Warteschlange steht oder läuft.

Fehler werden auf Standard Error ausgegeben, nach einem `✗`:

| Meldung | Was du tust |
|---|---|
| `Not logged in. Run "deploy login", or set DEPLOY_TOKEN.` | Melde dich an, oder setze in CI `DEPLOY_TOKEN` und `DEPLOY_URL`. |
| `No organization chosen. Run "deploy use <org>".` | Wähle eine mit `deploy use`, `--org=` oder `DEPLOY_ORG`. |
| `The token was not accepted. It may be revoked or expired: run "deploy login" again.` | Erstelle ein neues Token und melde dich erneut an. |
| `This token or your role does not allow that.` | Dem Token fehlt ein Bereich (siehe die Tabelle oben), oder deine Rolle erlaubt die Aktion nicht. |
| `Not found. Check the name, and that you have access to it.` | Die Organisation, der Server oder die Site existiert nicht, oder du hast keinen Zugriff darauf. |
| `No site "…".` / `No server "…".` | Prüfe die Domain oder den Namen und ob du die richtige Organisation verwendest. |
| `Too many requests. Wait a minute and try again.` | Ein Token darf 120 Anfragen pro Minute stellen. |

Meldungen von Vimonto Deploy selbst, etwa zu einer Site ohne Repository oder einem Deployment, das schon läuft, werden unverändert ausgegeben.

## Häufig gestellte Fragen

### Braucht die CLI SSH-Zugriff auf meine Server?

Nein. Die CLI spricht nur über HTTPS mit der API von Vimonto Deploy. Vimonto Deploy erledigt dann die Arbeit auf dem Server, so wie wenn du in der App auf einen Button klickst.

### Wo wird mein Token gespeichert?

Auf deinem eigenen Rechner, in `~/.config/deploy/config.json` mit den Rechten `0600`. In CI kommt das Token aus der Variable `DEPLOY_TOKEN`, und nichts wird auf die Festplatte geschrieben.

### Warum bekommt mein CI-Token "This token or your role does not allow that"?

`deploy`, `deployments` und `task` funktionieren mit einem Token mit nur **Deploy**. Andere Befehle wie `servers` oder `sites` brauchen **Lesen** oder **Schreiben** (siehe die Tabelle oben). Prüfe außerdem, ob deine Rolle in der Organisation deployen darf und ob du Version 1.1.0 oder neuer der CLI verwendest (`deploy --version`): Ältere Versionen suchten die Site über die Serverliste, und dafür braucht es **Lesen**.

### Kann ich die CLI für mehrere Organisationen verwenden?

Ja. Ein Token funktioniert in jeder Organisation, in der du Mitglied bist. Wechsle mit `deploy use <org>`, oder hänge `--org=<slug>` an einen einzelnen Befehl an.

### Gibt es eine API für das, was die CLI nicht kann?

Die CLI deckt die häufigsten Aufgaben ab. Die [API](https://ops.vimonto.com/docs/de/more/api) hat dieselben Endpunkte, die die CLI verwendet, du kannst sie also auch direkt aus deinen eigenen Skripten aufrufen.
