Zum Inhalt springen

Kommandozeile

Durch die Weboberfläche klicken ist angenehm - bis du dasselbe zum fünften Mal machst oder es aus einer CI-Pipeline heraus brauchst. Dafür gibt es die CLI. Sie steckt im selben envoryx-Binary, das auch den Server betreibt: envoryx project …, envoryx backup …, envoryx db …, envoryx worker …, envoryx cron …, envoryx git …, envoryx import und envoryx up sprechen über die REST-API mit einem laufenden Envoryx, angemeldet mit einem API-Token. Das funktioniert in einer SSH-Sitzung genauso wie in einem Cron-Job oder einer Pipeline.

Auf dem Docker-Host selbst musst du nichts installieren - das Binary im Container erledigt das, es braucht dort nur einen Token:

Terminal-Fenster
docker exec -it envoryx envoryx project list

Von deinem Laptop oder einem Build-Agent aus sagst du einmal, mit welchem Server er reden soll:

Terminal-Fenster
envoryx login --url https://envoryx.example.com # fragt nach dem Token
envoryx login --url https://envoryx.example.com --token "$ENVORYX_TOKEN"
envoryx whoami # Konto, Scope, Projekte
envoryx logout

login prüft den Token und legt ihn in ~/.config/envoryx/cli.json ab (Modus 0600). In CI setzt du meistens stattdessen ENVORYX_URL und ENVORYX_TOKEN, das klappt genauso. Nutzt dein Envoryx die lokale CA, gibst du das Zertifikat einmal mit --ca-cert ~/envoryx-ca.crt (oder ENVORYX_CA_CERT) mit; --insecure lässt die Prüfung ganz weg.

Ein Token kann keine anderen Tokens anlegen, damit ein geleakter Token sich keine Nachfolger erzeugen kann. Braucht ein Skript, das einen CI-Job oder einen Assistenten einrichtet, einen Token, legt es ihn aus einer Shell im Container an:

Terminal-Fenster
docker exec envoryx envoryx admin create-token --name ci --scope read --project shop --quiet
docker exec envoryx envoryx admin tokens # Besitzer, Scope, Projekte, letzte Nutzung
docker exec envoryx envoryx admin revoke-token ci # per Name, ID oder Präfix (stq_…)

create-token handelt für das einzige Konto, außer --user NAME nennt ein anderes, und gibt einem Token nie mehr, als die Rolle dieses Kontos erlaubt. Ohne --scope bekommst du operate, --project (mehrfach möglich) beschränkt den Token auf Projekte, und --quiet gibt nur den Token aus.

Das gibt es, grob danach sortiert, wofür du es brauchst:

Terminal-Fenster
envoryx project list # Name, Slug, Zustand, URL
envoryx project show shop # Dienste, Versionen, Ports, Git
envoryx project create "Shop" --php 8.4 --database mariadb --template laravel --start
envoryx project duplicate shop "Shop Test" # Konfiguration, Dateien und Datenbank
envoryx project rename shop "Acme Blog" --yes
envoryx project start|stop|restart shop
envoryx project delete shop --yes [--delete-files]
envoryx project logs shop --service php --tail 200 --follow
envoryx project exec shop -- composer install # jeder Befehl, jeder Container
envoryx project run shop artisan:migrate # eine Aktion aus dem Katalog
envoryx project share shop --for 2h # eine temporäre öffentliche Adresse
envoryx project branches shop # seine Branch-Umgebungen
envoryx project branch shop feature/login # eine Kopie von shop auf diesem Branch
envoryx project deploy shop-feature-login [--no-pull] # pullen und die Deploy-Befehle ausführen
envoryx import ./alte-seite "Alte Seite" --db dump.sql # eine bestehende Website als Projekt
envoryx import shop-20261010-084321-4ed7a89e.tar # ein heruntergeladenes Backup als neues Projekt
envoryx backup list|create|restore|download|delete shop
envoryx backup offsite|remote|fetch shop … # Offsite-Kopien
envoryx backup recover [blog[/<backup>]] [name] # jedes Projekt auf dem Ziel, als neues Projekt
envoryx instance backups # Envoryx selbst, braucht einen Admin-Token
envoryx instance backup|download|upload|delete …
envoryx instance restore <backup> --yes --wait # startet Envoryx neu und wartet darauf
envoryx instance offsite|remote|fetch …
envoryx diagnostics [--all] [--strict] # die Einrichtungsprüfung, Exit-Code 1 bei Fehlern
envoryx audit --project shop --since 2026-10-01 # --user, --action, --search, --export csv
envoryx docker images # Envoryx-Images, die kein Projekt nutzt
envoryx docker prune --yes # sie entfernen
envoryx docker orphans [--refresh] # was Projekte zurückgelassen haben
envoryx docker remove volume <name> --yes
envoryx settings # die Instanz-Einstellungen
envoryx settings set public-host=192.168.1.5 force-https=on
envoryx domain list|add|remove shop [api.shop.test] # die zusätzlichen Domains eines Projekts
envoryx db snapshot shop --note "vor einer Migration"
envoryx db snapshots shop
envoryx db restore shop <snapshot> --yes
envoryx db clone local --from staging --yes # jeder db-Befehl nimmt --db NAME
envoryx worker list shop # seine Worker und ihr Zustand
envoryx worker presets shop # was ein Worker ausführen kann
envoryx worker add shop queue --preset laravel:queue --arg default,emails
envoryx worker edit|enable|disable|restart shop queue
envoryx worker remove shop queue --yes
envoryx cron list shop # nächster und letzter Lauf jedes Jobs
envoryx cron add shop backup --schedule "0 3 * * *" -- php artisan backup:run
envoryx cron edit shop backup --schedule @hourly # oder ein neuer Befehl nach --
envoryx cron run shop backup --wait # sofort, mit Ausgabe und Exit-Code
envoryx cron runs shop backup [--output] # die letzten Läufe
envoryx cron enable|disable shop backup
envoryx cron remove shop backup --yes
envoryx git status|clone|pull shop
envoryx git checkout shop main

Ein Projekt kannst du beim Namen, beim Slug oder bei der ID nennen, je nachdem, was du gerade zur Hand hast. --json liefert das JSON der API statt einer Tabelle - genau das, was du in Skripten willst. --service wählt einen anderen Container als den Anwendungscontainer (php, python, go, ruby, node, web, database, redis, … worker:<id>). Die URL, die project list und project show ausgeben, ist vollständig, mit dem Port des Proxys, wenn der nicht auf 443 lauscht (https://shop.test:18443), du kannst sie also direkt öffnen.

Worker und Cron-Jobs nennst du beim Namen oder bei der ID. worker edit und cron edit ändern nur, was du angibst, und behalten den Rest. Ein Cron-Job läuft in der Anwendungs-Runtime des Projekts, außer --runtime nennt eine andere, und --max-time bricht einen Lauf nach dieser Zeit ab (ohne Angabe nach 10 Minuten). cron run --wait wartet auf den Lauf, gibt seine Ausgabe aus und endet mit dem Exit-Code des Befehls - eine Pipeline kann also einen Job starten und darauf reagieren, wie er gelaufen ist. Für die Logs eines Workers brauchst du seine ID, die worker list --json zeigt:

Terminal-Fenster
envoryx worker list shop --json | jq -r '.[] | "\(.name) \(.id)"'
envoryx project logs shop --service worker:<id> --follow

envoryx settings listet die Instanz-Einstellungen, die die CLI ändern kann, und settings set nimmt mehrere NAME=WERT auf einmal: public-host, base-domain, force-https, projects-follow-envoryx, shared-ide-backends, shared-package-cache, xdebug-client-host, folderview-folder, log-history, log-history-days, log-history-max-mb, metrics-days und ssh-keys. Ein/Aus-Einstellungen nehmen on oder off, ein leerer Wert leert eine Text-Einstellung, und ssh-keys=@keys.pub liest die Schlüssel aus einer Datei (sie ersetzen alle bisherigen).

Die Branch-Befehle arbeiten mit Kopien eines Projekts auf anderen Branches seines Repositorys. project branch kopiert das Projekt und deployt die Kopie einmal, das dauert so lange, wie das Projekt groß ist. Eine Umgebung ist ein eigenes Projekt, project deploy (und jeder andere Befehl) nimmt also ihren Slug, so wie project branches ihn auflistet: shop-feature-login für den Branch feature/login.

Für Skripte zählt auch, wie ein Befehl endet: 0 heißt Erfolg, 1 Fehler und 2 falsche Benutzung. Fehlt bei einem Befehl, der etwas löscht oder überschreibt, das --yes, ist das falsche Benutzung und endet ebenfalls mit 2. project exec reicht den Exit-Code des ausgeführten Befehls durch - ein fehlschlagendes composer install lässt also auch deine Pipeline fehlschlagen. Scheitert etwas auf dem Server, gibt die CLI die Ursache aus, die der Server mitschickt, nicht nur “an internal error occurred”.

envoryx project create --help listet alle Flags. Am häufigsten schlägst du die Runtimes nach:

Flag Bedeutung
--php VERSION PHP-Version, z. B. 8.4
--node VERSION Node.js; --node-dev-server, --node-preset vite|next|nuxt|generic
--python VERSION Python; --python-server, --python-preset django|flask|asgi|wsgi|module, --python-app NAME
--go VERSION Go; --go-server baut und startet den Server, --go-package ./cmd/server
--ruby VERSION Ruby; --ruby-server startet den Server (vorher bundle install), --ruby-preset rails|rack
--java VERSION Java (17, 21, 25); --java-server startet den Server, --java-preset spring-boot|quarkus|jar
--dotnet VERSION .NET SDK (8, 10); --dotnet-server startet den Server, --dotnet-preset aspnetcore|dll

Für Dienste gibt es --database TYP[:VERSION], --expose-database, --add-database NAME=TYP[:VERSION], --redis, --memcached, --mailpit, --rabbitmq, --storage, --meilisearch, --typesense, --opensearch, --opensearch-dashboards, --ollama und --ollama-gpu. Dateien und Repository regelst du mit --path, --docroot, --template, --starter, --git, --branch, --git-username und --git-token. Dazu kommen --env KEY=VALUE, --secret-env, --start und --from-json DATEI, wenn du die ganze Anlage-Anfrage lieber als JSON übergibst.

Die CLI kann genau das, was ihr Token darf. Ein read-Token listet Projekte und folgt Logs, ein operate-Token darf außerdem starten, stoppen und Befehle ausführen (einen Worker neu starten, einen Cron-Job laufen lassen und seine Ausgabe lesen), und zum Anlegen, Ändern oder Löschen von Projekten, Workern und Cron-Jobs braucht es admin. Jeder Befehl landet unter dem Namen des Tokens im Audit-Log - gib Tokens also Namen, die du später wiedererkennst.

Hiermit wird die CLI mehr als eine Fernbedienung. Die envoryx.yml beschreibt ein Projekt in seinem eigenen Repository - Runtimes, Dienste, Domains, Umgebung, Worker und Cron-Jobs. Committe sie mit dem Code, und jeder mit Zugang zu Envoryx bekommt aus einem frischen Klon mit einem Befehl dieselbe Umgebung:

Terminal-Fenster
git clone git@github.com:acme/shop.git && cd shop
envoryx up # legt "shop" auf dem Server an oder gleicht es an
envoryx up --dry-run # nur zeigen, was sich ändern würde
envoryx project manifest shop -o envoryx.yml # die Datei für ein bestehendes Projekt schreiben

Kennt der Server noch kein Projekt mit diesem Namen, klont up das Repository selbst (den origin-Remote und den ausgecheckten Branch), legt das Projekt genau wie beschrieben an und startet es. Gibt es das Projekt schon, übernimmt up die Unterschiede mit einem einzigen Neustart. Entfernt wird nie etwas, außer du hängst --prune an.

So sieht ein Manifest aus:

version: 1
name: shop
docroot: public
web: {server: nginx}
php:
version: "8.4"
extensions: [bcmath, intl, pdo_mysql, redis, zip]
database: {type: mariadb, version: "11.4"}
databases:
analytics: {type: postgres}
redis: true
mailpit: true
domains: [api.shop.example.com]
env:
APP_ENV: local
secrets: [STRIPE_SECRET] # nur Namen - Werte kommen nie ins Repository
workers:
- {name: queue, preset: "laravel:queue", arg: default}
cron:
- {name: prune, schedule: "0 3 * * *", command: php artisan model:prune, timeout: 5m}
healthcheck: /health

node:, python:, go: und ruby: nehmen dieselben Felder wie der Assistent (bei Ruby: version, server, mode, preset, port, debug, debugPort). Unbekannte Schlüssel sind Fehler - das klingt streng, sorgt aber dafür, dass ein Tippfehler nie still einen Dienst verschwinden lässt. Host-Ports, erzeugte Zugangsdaten, Backup-Zeitpläne und die Werte von Secrets bleiben bewusst draußen; envoryx up fragt fehlende Secrets ab, oder du übergibst eines mit --secret KEY=VALUE.

In der Weboberfläche zeigt der Bereich Git das Projekt als envoryx.yml und übernimmt eine geänderte Datei nach einem git pull.