Command line
Clicking through the web UI is nice until you do the same thing for the fifth time, or need it
in a CI pipeline. That’s what the CLI is for. It’s the same envoryx binary that runs the
server: envoryx project …, envoryx backup …, envoryx db …, envoryx worker …,
envoryx cron …, envoryx git …, envoryx import and envoryx up talk to a running Envoryx over the
REST API, with an API token. It works the same in an SSH session, a
cron job or a pipeline.
Getting started
Section titled “Getting started”On the Docker host itself there’s nothing to install - the binary inside the container does the job, and all it needs there is a token:
docker exec -it envoryx envoryx project listFrom your laptop or a build agent you tell it once which server to talk to:
envoryx login --url https://envoryx.example.com # asks for the tokenenvoryx login --url https://envoryx.example.com --token "$ENVORYX_TOKEN"envoryx whoami # account, scope, projectsenvoryx logoutlogin checks the token and keeps it in ~/.config/envoryx/cli.json (mode 0600). In CI you’ll
usually set ENVORYX_URL and ENVORYX_TOKEN instead, which works just as well. If your Envoryx
uses the local CA, hand the certificate over once with --ca-cert ~/envoryx-ca.crt (or
ENVORYX_CA_CERT); --insecure skips the check altogether.
A token can’t create other tokens, so a leaked one can’t mint its successors. If a script sets up a CI job or an assistant and needs a token for it, it creates one from a shell in the container:
docker exec envoryx envoryx admin create-token --name ci --scope read --project shop --quietdocker exec envoryx envoryx admin tokens # owner, scope, projects, last usedocker exec envoryx envoryx admin revoke-token ci # by name, id or prefix (stq_…)create-token acts for the only account unless --user NAME names another, and never gives a
token more than that account’s role allows. Without --scope you get operate, --project
(repeatable) limits the token to projects, and --quiet prints nothing but the token.
Commands
Section titled “Commands”Here’s what’s there, grouped roughly by what you’ll use it for:
envoryx project list # name, slug, state, URLenvoryx project show shop # services, versions, ports, gitenvoryx project create "Shop" --php 8.4 --database mariadb --template laravel --startenvoryx project duplicate shop "Shop Test" # config, files and databaseenvoryx project rename shop "Acme Blog" --yesenvoryx project start|stop|restart shopenvoryx project delete shop --yes [--delete-files]envoryx project logs shop --service php --tail 200 --followenvoryx project exec shop -- composer install # any command, any containerenvoryx project run shop artisan:migrate # a catalogue actionenvoryx project share shop --for 2h # a temporary public addressenvoryx project branches shop # its branch environmentsenvoryx project branch shop feature/login # a copy of shop on that branchenvoryx project deploy shop-feature-login [--no-pull] # pull it and run the deploy commandsenvoryx import ./old-site "Old Site" --db dump.sql # an existing website as a projectenvoryx import shop-20261010-084321-4ed7a89e.tar # a downloaded backup as a new project
envoryx backup list|create|restore|download|delete shopenvoryx backup offsite|remote|fetch shop … # offsite copiesenvoryx backup recover [blog[/<backup>]] [name] # any project on the target, as a new project
envoryx instance backups # Envoryx itself, needs an admin tokenenvoryx instance backup|download|upload|delete …envoryx instance restore <backup> --yes --wait # restarts Envoryx, waits for itenvoryx instance offsite|remote|fetch …
envoryx diagnostics [--all] [--strict] # the set-up check, exit code 1 on errorsenvoryx audit --project shop --since 2026-10-01 # --user, --action, --search, --export csvenvoryx docker images # Envoryx images no project usesenvoryx docker prune --yes # remove themenvoryx docker orphans [--refresh] # what projects left behindenvoryx docker remove volume <name> --yes
envoryx settings # the instance settingsenvoryx settings set public-host=192.168.1.5 force-https=onenvoryx domain list|add|remove shop [api.shop.test] # a project's extra domains
envoryx db snapshot shop --note "before a migration"envoryx db snapshots shopenvoryx db restore shop <snapshot> --yesenvoryx db clone local --from staging --yes # every db command takes --db NAME
envoryx worker list shop # its workers and their stateenvoryx worker presets shop # what a worker can runenvoryx worker add shop queue --preset laravel:queue --arg default,emailsenvoryx worker edit|enable|disable|restart shop queueenvoryx worker remove shop queue --yes
envoryx cron list shop # next and last run of each jobenvoryx cron add shop backup --schedule "0 3 * * *" -- php artisan backup:runenvoryx cron edit shop backup --schedule @hourly # or a new command after --envoryx cron run shop backup --wait # now, with output and exit codeenvoryx cron runs shop backup [--output] # the recent runsenvoryx cron enable|disable shop backupenvoryx cron remove shop backup --yes
envoryx git status|clone|pull shopenvoryx git checkout shop mainYou can name a project by its name, its slug or its id, whatever is at hand. --json gives you
the API’s JSON instead of a table, which is what you want in scripts. --service picks a
container other than the application container (php, python, go, ruby, node, web,
database, redis, … worker:<id>). The URL that project list and project show print is the
full one, with the proxy’s port when it doesn’t listen on 443 (https://shop.test:18443), so you
can open it as it is.
Workers and cron jobs go by their name or their id.
worker edit and cron edit change only what you give them and keep the rest. A cron job runs in
the project’s application runtime unless --runtime names another one, and --max-time stops a
run after that long (10 minutes if you don’t say). cron run --wait waits for the run, prints
its output and ends with the command’s exit code, so a pipeline can run a job and react to how it
went. The logs of a worker need its id, which worker list --json shows:
envoryx worker list shop --json | jq -r '.[] | "\(.name) \(.id)"'envoryx project logs shop --service worker:<id> --followenvoryx settings lists the instance settings the CLI can change, and settings set takes several
NAME=VALUE at once: 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 and ssh-keys. On/off
settings take on or off, an empty value clears a text setting, and ssh-keys=@keys.pub reads
the keys from a file (they replace all keys there were).
The branch commands work on copies of a project on other
branches of its repository. project branch copies the project and deploys the copy once, which
takes as long as the project is big. An environment is a project of its own, so project deploy
(and every other command) takes its slug as project branches lists it, shop-feature-login
for the branch feature/login.
For scripts it also matters how a command ends: 0 means success, 1 failure and 2 a usage
error. A missing --yes on a command that deletes or overwrites something counts as a usage
error, so it ends with 2 as well. project exec passes on the exit code of the command you ran, so a failing
composer install fails your pipeline too. When the server fails, the CLI prints the cause the
server sends along, not just “an internal error occurred”.
Creating a project
Section titled “Creating a project”envoryx project create --help lists every flag. The runtimes are what you’ll look up most:
| Flag | Meaning |
|---|---|
--php VERSION |
PHP version, e.g. 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 builds and runs the server, --go-package ./cmd/server |
--ruby VERSION |
Ruby; --ruby-server runs the server (bundle install first), --ruby-preset rails|rack |
--java VERSION |
Java (17, 21, 25); --java-server runs the server, --java-preset spring-boot|quarkus|jar |
--dotnet VERSION |
.NET SDK (8, 10); --dotnet-server runs the server, --dotnet-preset aspnetcore|dll |
For services there are --database TYPE[:VERSION], --expose-database,
--add-database NAME=TYPE[:VERSION], --redis, --memcached, --mailpit, --rabbitmq,
--storage, --meilisearch, --typesense, --opensearch, --opensearch-dashboards,
--ollama and --ollama-gpu. Files and repository come with --path, --docroot,
--template, --starter, --git, --branch, --git-username and --git-token. And then
there’s --env KEY=VALUE, --secret-env, --start, and --from-json FILE if you’d rather
pass the whole create request as JSON.
What a token may do
Section titled “What a token may do”The CLI can do exactly what its token may do. A read token lists projects and follows logs, an
operate token can also start, stop and run commands (restart a worker, run a cron job and read
its output), and creating, changing or deleting projects, workers and cron jobs needs admin. Every command shows up in the audit log under the token’s name, so give tokens names
you’ll recognise later.
Project manifest (envoryx.yml)
Section titled “Project manifest (envoryx.yml)”This is what makes the CLI more than a remote control. envoryx.yml describes a project inside
its own repository - runtimes, services, domains, environment, workers and cron jobs. Commit it
with the code, and anyone with access to Envoryx gets the same environment from a fresh clone
with one command:
git clone git@github.com:acme/shop.git && cd shopenvoryx up # creates "shop" on the server, or brings it in lineenvoryx up --dry-run # only show what would changeenvoryx project manifest shop -o envoryx.yml # write the file for an existing projectIf the server doesn’t have a project of that name yet, up clones the repository itself (the
origin remote and the branch you have checked out), creates the project exactly as described
and starts it. If the project already exists, up applies the differences with a single
restart. It never removes anything unless you add --prune.
A manifest looks like this:
version: 1name: shopdocroot: publicweb: {server: nginx}php: version: "8.4" extensions: [bcmath, intl, pdo_mysql, redis, zip]database: {type: mariadb, version: "11.4"}databases: analytics: {type: postgres}redis: truemailpit: truedomains: [api.shop.example.com]env: APP_ENV: localsecrets: [STRIPE_SECRET] # names only - values never go into the repositoryworkers: - {name: queue, preset: "laravel:queue", arg: default}cron: - {name: prune, schedule: "0 3 * * *", command: php artisan model:prune, timeout: 5m}healthcheck: /healthnode:, python:, go: and ruby: take the same fields as the wizard (for Ruby: version,
server, mode, preset, port, debug, debugPort). Unknown keys are errors - that sounds
strict, but it means a typo can never quietly drop a service. Host ports, generated credentials,
backup schedules and the values of secrets stay out of the file on purpose; envoryx up asks for
missing secrets, or you pass one with --secret KEY=VALUE.
In the web UI, the Git section shows the project as envoryx.yml and applies a changed file after a
git pull.