levelrail-cli is a scriptable client for the control plane’s HTTP API. Everything it does goes through /api/v1, with the same tokens and permissions as the dashboard, so you need no SSH key and no open port on your servers. This page lists every command group with its subcommands and the flags you will use most. Run levelrail-cli with no arguments for the command list, or levelrail-cli <command> <subcommand> -h for any command’s own flags.
Commands are shown as levelrail-cli .... If you rename the binary, the command name follows it (the CLI reads its name from os.Args[0]). The server is a separate binary, levelrail, which has a few maintenance commands of its own, such as setup-token, restore-snapshot, restore-db, recover-admin, upgrade-note (record who swapped the binary by hand), and healthcheck. Those are in Installing and Disaster recovery.
Install and sign in
curl -fsSL https://levelrail.com/install-cli.sh | sh
--device prints a short code that you approve in the dashboard, the same model as gh auth login. Credentials are saved to ~/.config/levelrail-cli/credentials. For CI, create an API token under Settings, API tokens and pass it with --token or APP_API_TOKEN.
Each command resolves its target in this order, and an explicit flag always wins:
Manage more than one control plane with named profiles:
levelrail-cli auth login --profile staging, then --profile staging on any command. levelrail-cli profile list shows them.
Scripting: --json and exit codes
Every command that returns data or a result supports --json (shorthand for --output json), and --query takes a JMESPath expression. With --json, stdout carries only the JSON result. The exceptions are completion bash|zsh|fish (a shell script) and control-plane-backups help-dr (a static runbook). A test walks the command tree and fails when a new command has no --json and is not on that exempt list.
On failure, --json also prints an error object to stdout (the message still goes to stderr):
error is the original field. code is one of validation, network, unauthorized, forbidden, not_found, conflict, rate_limited, invalid_request, server_error, api_error. http_status, retry_after (rate limits) and hint appear when they apply.
Exit codes are stable and shared by every command:
Codes 3 and 4 are broad on purpose so existing scripts keep working; the JSON error object carries the finer distinction.
Scripting: --debug
--debug works anywhere on the command line (before or after the subcommand) and traces every outgoing request this invocation makes to stderr: method, URL, and the response status and timing, one line per call. It never prints request or response headers or bodies, so Authorization and any token value never appear, even in debug mode; a token that somehow ended up in a URL’s query string is also redacted. stdout is untouched, so --debug composes with --json/--query for scripting.
Experimental command groups
Some groups are off by default and stay hidden from--help and shell completion until the shell you run the CLI from sets APP_EXPERIMENTAL. This page marks them. The keys are ai-chat (ai, settings ai-assistant), ai-models (models), load-balancer (lb), iac (apply, diff, export) and cloudflare-tunnel (cloudflare-tunnel). See Experimental features.
Web CLI console: host diagnostics
The dashboard’s CLI console (experimental keycli-console) runs the commands on this page against the control plane. It also answers a small host namespace itself, inside the control plane process, without starting the CLI or any other program. It is read only and is not a shell.
None of them take arguments: paths, process names, container names and flags are refused. Each line goes through the same step-up, one-command-at-a-time, idle timeout, output cap and audit log (
cli_console.run) as any other console command. Linux only; other platforms reply “not supported on this platform”. Set APP_CLI_CONSOLE_HOST=off on the server to turn the namespace off while keeping the rest of the console.
Top-level convenience aliases
apps deploy; deploy an image to an existing app.
apps rollback; redeploy an older image.
Apps
apps list prints every app the caller can read as a bare JSON array. On a fleet large enough that matters, add --max-items N to cap the page size; the response becomes {"items": [...], "next_token": "...", "total_count": N} instead, and an empty next_token means there is no further page. Pass that next_token back in as --starting-token to fetch the next page (requires --max-items, since the server only pages a result when a limit is set):
levelrail-cli apps <subcommand> -h for the full flag list of any command below. Deploy lifecycle is covered in Deploying and managing apps.
Create, inspect and list
apps createregisters an existing image or triggers a real build from a git repository;--filereads an app spec,--interactiveruns a step-by-step wizard. Required flags missing outside--interactivefail with an error instead of prompting.apps statusshows an app’s current reconcile conditions;apps overviewshows CPU, memory, traffic and errors for every app (or the names given) in one request;apps networkshows the live traffic path (container port, host port, running).apps validateparses and validates an app.yaml or a Docker Compose file locally, with no API call and no deploy. It prints the detected format, service count, and every non-blockingnoticesentry a real deploy would also surface.apps deleteremoves an app and stops its containers; if the node is unreachable the delete is reported as pending and retried.
Deploy, roll back and scale
apps waitpolls until a deploy attempt converges and exits 0 on success, 5 if it converged as a failure, 6 on timeout. On success it says what happened:rolled out,already up to date(the deploy changed nothing) orrestarted;--jsoncarries the same asoutcome.apps deploy-specfans an app.yaml’sservices:map out into independent builds under one app;apps groupshows a service’s siblings under the same multi-service app.apps builds triggerbuilds an image from a git source and deploys it to an existing app.apps promotepromotes the app’s image onto a sibling app in another environment.apps applyrestarts an app so saved env, secret and config changes reach the running container; it does nothing when nothing is pending.apps scalechanges the replica count and/or the deploy strategy.apps hook-runsshows the most recent outcome of an app’s pre and post deploy hooks;apps imageslists the locally present image tags under the app’s current image repo.apps set-nodeandapps clear-nodemove an app to another node, or back to the control plane’s own local node. With--with-volumesthe named volumes move too, andapps movesshows the history of those moves.
Deploy history, approvals and automation
apps deploys listis real, row per attempt deploy history, newest first.apps deploys showprints one attempt (the newest by default) with its structured failure: code, cause, failing step, redacted log excerpt, suggested fix, docs link and retryable. See Deploy failures.apps deploys waitblocks until one deploy is healthy, failed, canceled, superseded or blocked (a freeze window or approval) and prints the result with its failure. Exit 0 healthy, 7 failed, canceled, superseded or blocked, 6 timeout. Without a deploy id it resolves the newest deploy once and follows it by id.apps deploys comparediffs two deploy attempts, or one against the current live state.apps deploys logsprints one attempt’s full build and log output to stdout.apps deploys stepsstreams the pipeline steps (detecting, building, pushing, deploying) until the attempt ends and exits non-zero if a step failed; an already finished attempt replays only a short summary.apps deploys failedlists every app’s latest failed deploy in the window (default set by the server), with the image of its newest good deploy as a rollback target.apps deploys cancelcancels a queued or in-progress deploy before it cuts traffic.apps deploys rollback-toredeploys a past succeeded deploy’s exact image, pinned by digest or rollback pin, with that deploy’s config;--watchfollows it through the readiness gate.apps deploys gate(aliasdeploy status) prints a release’s gate timeline: readiness passes, stable window, cutover, drain, rollback pin and post-deploy watch.--watchfollows it until the release clears its watch, fails, is rolled back or is replaced. Exit 0 healthy or in progress, 7 failed or rolled back.apps deploy-safetyshows and overrides the per-app thresholds (set web --stable-window 20s --auto-rollback false,defaultclears one) and lists pinned rollback targets. See Deploy safety.apps timelineshows what happened to an app, newest first: deploys, rollbacks, restarts, env, secret and config changes (key names only, never values), scaling, stop and start.apps diagnoseexplains a failed deploy or crashloop and can apply a suggested fix with--apply-fix N.apps preflightruns pre-deploy checks (DNS, ports, disk, image, env).apps freezemanages deploy freeze windows: a window starts at every match of a 5 field cron expression, evaluated in--timezone(default UTC), and lasts--duration. While one is active, webhook, pipeline and released deploys are held and run when the window ends; a manual deploy needsapps deploy --override-freeze --override-reason TEXT.setreplaces the app’s windows with the one given. Fleet-wide windows are undersettings deploy-freeze.apps scheduleconfigures a recurring redeploy of a branch’s latest commit on a cron schedule.apps cancel-supersededlets a newer queued deploy replace older queued ones of the same branch. Only queued deploys are replaced; a deploy that already started building is never canceled automatically.jobsmanages an app’s scheduled jobs: fresh-container or exec cron jobs with run history, logs, retries and catch-up (see Scheduled jobs).apps scheduled-tasksis the older exec-only form of the same resource.functionsruns an image as a function: it sleeps when idle, and a request to a sleeping one waits through the cold start (see Functions).apps sleepstops an app after it has had no requests for a set time and wakes it on the next request (see Sleep when idle).apps canaryruns a new image beside the app and sends it a share of traffic until you promote or abort it (see Canary deploys).apps auto-updateredeploys an app automatically when its image tag moves to a new digest (see Image auto-update).apps auto-rollbackopts an app into or out of automatic rollback when a crashloop alert fires.apps auto-rollback-slo-burnsets how the app reacts when an SLO burn rate alert fires.
--cursor paging), counts by status with failure rate and duration percentiles, and a live event stream (--json prints one object per event).
list defaults to pending. approve runs the gated deploy or promote now; reject leaves the app’s desired state untouched.
Domains, ports and traffic
apps domains addcreates the DNS record when a provider is connected (--dns offskips it,--dns previewshows it);--waitprints the go-live steps and exits non-zero when the domain is not live within--timeout. See Add a domain and go live.apps domainsshows or changes an app’s domains; a domain already used by another app is refused and nothing is changed. Per-domain TLS, redirects, WAF and the like are under Domains.apps streamsforwards a host port to one container port as raw TCP (onlytcpis supported). A stream change takes effect on the app’s next container recreation, such as an image change orapps restart.apps egressrestricts an app’s outbound traffic to the declaredhost:portpairs; with nothing configured, egress is unrestricted. DNS and loopback traffic stay open regardless.apps exec-accessis on by default. When disabled,apps execand the interactive terminal are refused whatever abilities the token has.
Run, logs and metrics
apps execruns a command in the app’s container and exits with its real exit code.apps logssearches an app’s stored log entries, or streams live with--follow. For a capped excerpt seelogs queryunder Logs.apps requestsshows request rate, errors and latency from the ingress;apps resource-usageranks every app by latest CPU, memory and network usage.apps resource-recommendationsuggests memory and CPU limits from historical usage;apps costestimates what the app’s CPU and memory would cost under reference providers (not a real bill).usage report|settings|budgetsshows cost showback and manages prices and budgets, see usage and cost.usage report --csvprints the export.advisor findings|summary|apply|dismiss|snooze|restore|enable|disabledrives the beta resource advisor.advisor apply IDonly previews; add--yesto apply.apps health-scoregives a synthesized pass, warn or fail readiness verdict across deploy health, security, resilience and observability.apps log-drainforwards container logs to an external HTTP or syslog sink, in addition to the built-in node-local log store.apps scheduled-tasksruns a command inside the app’s running container on a cron schedule. The command is a real argv with no shell; put--before it when the command takes flags.
Health probes, volumes and storage
apps health setsets one probe and keeps the other. A probe is an HTTP(S) check or a command run inside the container (exit 0 is healthy).--presetfills path, interval, timeout and failures from a shortcut (healthz,health,api-health,ping,status); explicit flags win.apps health discoverprobes well-known paths and reports what each one did.apps volumesmanages named Docker volumes outside a redeploy. The name is lowercase letters, numbers and hyphens starting with a letter; the path is where it mounts in the container.apps storage setattaches a connected bucket as object storage and injects its credentials asS3_*env vars at container create time. See Object storage.apps build-cacheconfigures the BuildKit remote cache on a storage destination.--globalapplies to every app without its own setting.clearis bounded per call; run it again while it reports more to delete. A cache problem never fails a build.
Environment, secrets and Vault
apps env importmerges a .env file into an app’s plain env vars and prints which keys are new, changed or unchanged. Keys that are already secrets are skipped. It reports how many changes are pending, or restarts the app right away with--apply.apps env diffcompares two apps’ env vars, for example staging against production. Secret values are never read: secrets are compared by key only, and the dashboard has the same comparison on an app’s Environment page.apps env exportwrites env vars as .env text; sensitive and secret keys are written empty with a comment unless--revealis given.apps env getprints one variable, masked when sensitive.--revealasks for your password (and authenticator code) at the prompt, never from flags or the environment, and needs a token withread:sensitiveandsecrets:revealplusAPP_SECRET_REVEAL_TOKENS=onon the server. See Environment variables and secrets.apps secrets setsets or rotates one secret’s encrypted value and declares the key as secret backed so it is injected;--applyrestarts the app now. With--env-fileit bulk imports every key in a .env format file as its own secret. Values are never returned:listshows key names and locked state only.locktoggles a secret’s overwrite guard.apps vault-envdeclares an env var resolved live from the configured external Vault (see Vault); only the reference is stored.apps preview-envandapps branch-envoverride an env var for previews only. A branch override applies when the preview’s own branch matches PATTERN (an exact name or a glob such asrelease/*);--secretstores it envelope encrypted. Neither affects the app’s own running deploy.
Source, previews and webhooks
apps git-sourceconnects a repo for auto deploy on push;settingssets push path filters and forge status reporting;rotate-secretmints a fresh webhook secret, shown once.apps webhook-deliverieslists recent inbound webhook requests, verified or not.replayre-runs a stored delivery’s payload and can trigger a real build and deploy.apps previewsmanages preview environments per pull request, see Preview environments per pull request.previewsis the same command at the top level.extendkeeps one preview past its TTL;settingsshows or changes the lifecycle, resource, database and exposure policy.limitsshows or changes preview caps, fork policy and TTL;approvedeploys a held fork pull request once;teardownremoves one PR’s preview now;sweeptears down every stale preview across all apps now;pr-statustoggles the PR comment and commit status per preview deploy.
Supply chain
apps sbom shows a deploy’s software bill of materials (newest deploy with one by default), or prints or saves the raw SPDX or CycloneDX document. Scanning is off by default and needs APP_BUILD_ATTEST=true on the server so builds produce an SBOM; a server can refuse every scan with APP_SCAN_ENABLED=false. gate block_on_critical keeps the previous release serving; override lets the next blocked release through once, with a recorded reason. See Supply chain.
Alerts, connections and templates
apps alerts create takes one of these kinds: threshold (needs --metric, --comparator, --threshold), crashloop (--restart-count-threshold, --restart-window), cert_expiry, patch_status, scheduled_task_failure (--scheduled-task-id, --restart-count-threshold), node_disk_space, node_resource_usage, node_offline, domain_health, control_plane_backup_stale, log_archive_stale, backup_missing (--backup-resource-kind database with --backup-database-name, or volume with --backup-volume-name) and slo_burn (--slo, optional --slo-latency-ms). Mute, schedule and review alerts with the top-level Alerts commands.
apps connectconnects an app to a managed database and injects its resolved connection value as an env var; unlikeapps database, an app can have any number of these.connections listshows each connection, including whether it resolves to a mesh DNS name (cross node capable) or a container name;connections suggestlists databases the app could connect to.apps disconnectremoves one connection by its env var name.apps database setattaches one already created managed database as the app’s connection env var source (defaultDATABASE_URL, fieldurl);cleardetaches it.apps save-as-templatederives a compose.yaml from the app’s current desired state and saves it as a reusable template. No secret, database or vault backed env value is captured, only the key name.apps tagattaches a tag by name, creating it if new;apps untagdetaches it. See Tags.
Projects, environments and organizations
- A project groups apps and databases; an organization groups projects. Deleting either leaves its members running, simply ungrouped again.
- Shared env vars layer in this order: organization, then project, then environment, then the app’s own env, each overriding the one before.
env-setreplaces that scope’s shared env vars. For per scope secrets see Shared env. - A protected environment requires
--confirm(or an interactive yes) onapps deploy,apps rollbackandapps promotetargeting an app tagged with it, and routes the deploy through deploy approvals. apps environments clone-previewshows what cloning would create without applying it;env-diffdiffs two environments’ resolved effective env vars.apps projects topologyprints a diagram ready graph of a project’s apps, databases and volumes. See Projects and organizations.
Tags
delete detaches the tag from every app. apps lists every app attached to a tag. Attach one to an app with apps tag.
Pipelines
validatechecks a pipeline file locally with no API call and exits 2 when it has problems.savecreates or updates pipelines from one file, or from every file in a repository’s pipeline directory.runslists runs, or shows one run’s jobs, steps and approval gates;--alllists runs across every app.approvedecides approval gates, or releases a run held for approval.syncsyncs pipeline files from the repository now, or sets the repository as source of truth.triggersshows why recent git events did or did not start runs.oidcshows whether pipeline jobs can mint OIDC tokens and the JWKS URL to wire to a cloud provider;oidc rotate-keyrotates the signing key, and the old key stays published until it retires.
Load balancers
Experimental: requiresAPP_EXPERIMENTAL=load-balancer. See Load balancing.
listshows every load balancer across apps with upstream health.setcreates or changes the load balancer and only the flags you pass change;clearremoves it, back to a single upstream.statusis the live upstream table;checkprobes every upstream once, right now;historyshows recent checks and state changes per upstream;upstreamsets an upstream active, draining or disabled.exportgenerates an infrastructure as code definition with no cloud API calls;importloads theloadbalancer:block of an app.yaml.
Preview
Deploy previews are the screenshot or metadata card captured after a deploy, not pull request previews (those areapps previews). See Deploy previews.
enable turns deploy previews on: metadata reads the page title and social image with one small request (no browser), screenshot (the default here) runs a browser container per deploy and pulls a large image once. capture recaptures the current release now; prune deletes old previews now, or every preview of the app with --all. Previews need the server to run with APP_PREVIEW_ENABLED=true (the default).
Databases
statusshows a database’s current reconcile conditions (useful when it exists but is not running yet).deletestops and removes a database but keeps its data volume;--forceis needed if apps use it.slow-querieslists a Postgres or MySQL database’s slow query log.schemalists a SQL database’s tables with row estimates and sizes;queryruns one statement through the control plane, read-only by default. See Database viewer.dbis a short alias fordatabases.set-resourcesapplies memory and CPU limits to an already created database, replacing whatever was set before (a full replace, not a patch).public-access setexposes a database on a host port;--bind-addressisprivate(the default),public, or a literal IP.set-versionis a minor or patch image change on the same data.major-upgradeis a guarded Postgres major upgrade with a rollback snapshot;major-upgradeslists the attempts,major-upgrade-rollbackrestores the pre upgrade data, andmajor-upgrade-discarddeletes a rollback snapshot to free disk.
AI models
Experimental: requiresAPP_EXPERIMENTAL=ai-models. See AI models.
deployruns a model as a container on a GPU node and prints its API key once. Flags:--engine(ollama,vllmorllamacpp),--model,--node,--gpus(a count orall),--gpu-devices,--context,--quantization,--domain,--hf-token-from-env,--residency(alwaysoron_demand),--idle-ttl,--swap-group.logssearches a model engine’s logs, or--followstreams download and load progress live.deletekeeps the downloaded weights volume.restartrecreates the engine container.rotate-keyissues a new API key, printed once;keysmanages named API keys with limits, expiry and rotation grace;usageshows gateway requests, tokens, errors and latency per key.residencysets a model always resident oron_demand(stopped when idle, started on first request);wakeandsleepstart or stop an on demand engine now;swap-grouplets models share a GPU (--clearremoves it).fitestimates VRAM fit on each GPU node;gpuslists GPU nodes with VRAM and usage;preflightchecks a Hugging Face repo (access, size, quantizations, fit, disk);metricsshows engine metrics.cache listshows cached model weights per node;cache pruneremoves unused, unreferenced weights (use--dry-runfirst).
Auth
loginauthenticates and persists a new API token; with--profile NAMEit saves under a named profile instead of overwritingdefault.login --device --jsonprints one JSON line first (verification_url,user_code,expires_in,expires_at) so an agent can relay it, then the token resource once approved. See Attention center.session-linkmints a short lived (about 2 minutes), single use login link that signs in as whoever minted it, meant for browser automation. It needs a token with the root ability.codeprints the sign-in codes waiting for your account with the requester’s IP address, browser and time, plus password sign-ins from new browsers waiting for approval;approveanddenydecide one of those (approveneeds--matchwith the two digit number the waiting browser shows, typed in; a wrong number denies it, and the number is never printed bycode), anddeviceslists or revokes browsers trusted for password sign-in. They need a token that belongs to your user. Listing anddevicesacceptwrite:sensitive; showing a code andapproveordenyneedsignin:approve, which no device login, root orwrite:sensitivetoken carries. Mint one from a signed-in session withlevelrail-cli tokens create --name approver --abilities signin:approve --expires-in-days 30(it must expire within 30 days by default, cannot be an agent token, and is revoked when you change or reset your password or sign out your other sessions), or use the dashboard.code-loginshows or changes who may sign in with a code (changing it needs root). See Identity and access.- Every
2fasubcommand needs a live session:--usernameand--password(prompted if omitted), never the CLI’s saved bearer token.setupstarts enrollment and returns a secret and provisioning URI;enableconfirms it and returns recovery codes once;recovery-codesregenerates them and invalidates the old set.
Auth engine
Profile
Tokens
tokens subcommand requires a username and password (prompted if omitted), because these routes are session only server side and a bearer token cannot call them. create mints a new API token; --agent labels it as issued to an AI agent so audit entries record the agent name. list never shows a secret.
Domains
Per domain settings take<app> <domain>, and the domain must already be one of the app’s configured domains. Domain TLS and ingress behavior is covered in Domains and ingress.
-
standalonemanages standalone domains: domains with no app that proxy toPORT,HOST:PORT, anhttp(s)://URL,app:NAME[:PORT]orcontainer:NAME:PORT. Options are--upstream-tls,--insecure-skip-verify,--tls-server-name,--host-header preserve|upstream|NAME,--no-websocket,--connect-timeout,--read-timeout,--strip-prefixand--description. Loopback, private, container and control-port targets need--confirm.updatesends only the flags you pass. Per-domain commands take_standaloneas the app name, for exampledomains waf set _standalone tools.example.com. -
listshows every app’s domains in one call.checkruns a real DNS lookup and reports whether the domain reaches this control plane.certificateslists every certificate in certmagic storage, healthy or not. -
basic-auth settakes--usernameand--password.maintenance setserves a fixed maintenance response instead of proxying, without stopping the container.redirect set --target URLredirects every request for the domain; maintenance mode takes precedence if both are set. -
tls-certuploads an operator supplied certificate and key;clearreverts to automatic issuance andrenewforces re-issuance of an automatic certificate. -
wafconfigures the opt-in Web Application Firewall and rate limiting.--modedefaults todetect(matches are logged, never rejected) rather thanblock. -
error-pagessets custom HTML for status code 404, 500, 502 or 503;clearremoves one mapping, or all if--codeis omitted. -
dnsreads and writes the real A, AAAA, CNAME, TXT, MX, SRV and CAA records in the domain’s zone through whichever DNS-01 provider is configured.removemust match an existing record exactly. -
cloudflare-dns set --cf-api-token TOKENandroute53-dns set --aws-access-key-id ID --aws-secret-access-key KEYconfigure the ACME DNS-01 credentials needed for wildcard domains. A domain is wildcard eligible by having a leading*.label; if both providers are enabled, Cloudflare takes precedence.
DNS
See DNS zones and records.zones verifycompares the NS set the system resolver, 1.1.1.1 and 8.8.8.8 return with the zone’s assigned name servers.records importandrecords templateprint a plan and change nothing until--apply.--replacedeletes sets missing from the file and needs--confirm.
Backups
See Backups and storage.list-alllists backup history across every database and app volume instance wide.deleteremoves one archived backup (destructive).downloadstreams a succeeded backup’s object to stdout.restorerestores in place and is destructive;--confirmtakes the database name.restore-as-newrestores into a brand new database and is non destructive.restoresandclone-restoreslist the attempt history of each.verifychecks a backup is intact without a live restore;verificationslists past attempts.healthshows every backed up resource with its last backup and last verified restore.protectionshows bucket object lock and versioning.drill runrestores a backup into a scratch resource, validates and destroys it, and exits non zero when it fails. See Prove your backups work.volumes restorerestores into a new volume only, optionally named for another app or on another node.
App volume backups
backups, for a named volume declared in the app’s app.yaml (apps volumes get <app> lists them). restore is destructive and its --confirm takes APP/VOLUME; restore-as-new creates a standalone volume.
Point-in-time restore
Postgres only. Recovery covers the time range from whenpitr enable was called, forward; use backups restore for anything older.
enable turns on continuous WAL archiving going forward; status shows whether PITR is enabled and the current recoverable window; restores lists point in time restore attempts (base backup, target time, status, error). restore is destructive.
Build
detect shows which framework the builder detects without running a build, and prints no framework detected (exit 0) when nothing matches. branches lists the branches a repo advertises; private or unreachable repos fail with an API error.
Cloudflare Tunnel
Experimental: requiresAPP_EXPERIMENTAL=cloudflare-tunnel.
cloudflared container with a tunnel token from your own Cloudflare Zero Trust dashboard, exposing the control plane without an inbound port. This is a different credential from domains cloudflare-dns.
Vault
role_id is echoed on get. disconnect disables and forgets the stored credential.
Channels
--kind values: generic, slack, discord, telegram, email, pushover, pagerduty, teams, resend, ntfy, gotify, mattermost, lark, rocketchat, opsgenie, webex, googlechat. update fully replaces a channel’s configuration. --notify-device-login opts a channel into a link-only notice when a CLI login is waiting. test sends a real test message; deliveries lists a channel’s recorded send history, newest first. See Email notifications.
Push subscriptions
register subcommand: a subscription’s endpoint and keys only come from a real browser. See Observability.
Alerts
Top-level commands for muting, scheduling and reviewing alerts. The rules themselves are managed underapps alerts. See Observability.
- A silence keeps matching alerts evaluating and recorded in history but stops them notifying. Every filter given must match; repeat a flag to accept any of several values.
silences deleteends a silence now and keeps it in history (silences list --all). silenceis the quick action: silence one rule,--fordefaults to1h.- A maintenance window is a recurring silence: a 5 field cron expression for each start, a
--duration, and--tz(defaultUTC).--scopeisall(default),appornode, with--targetnaming the apps or nodes. historylists firings and resolutions, newest first (--limitdefaults to 50).--outcomeis one ofsent,silenced,grouped,inhibited,failed,ratelimited,flappingorskipped;--eventisfired,resolved,flappingorflap_ended;--sincetakes an RFC 3339 timestamp.--changesadds what changed on the app before each firing, with the most likely cause tagged.
Status page
The opt-in public status page. It stays off untilset --enable. Only public component names, statuses and operator written announcements are published; targets (app names, hostnames, check URLs) stay private. See Status page.
--enableand--disableare mutually exclusive.--domainserves the page on a hostname that the ingress must route to the control plane.incidents create:--kinddefaults toincident,--impacttonone. Amaintenancekind requires--startsand--ends(RFC 3339).--bodyis markdown-lite.incidents update --statustakesinvestigating,identified,monitoringorresolvedfor an incident, andscheduled,in_progressorcompletedfor maintenance.
Shared env
Environment variables shared at project, organization or environment scope, plain or secret. See Projects and organizations.SCOPE is project, organization or environment, and --id is that resource’s id. A plain value is stored as is. --secret encrypts it the same way an app’s { secret: true } env vars are, and its value is never shown again, only its key. list shows plain and secret marked entries alike; pass --secret to delete when the key is secret marked.
Registry
registry:2). The first enable generates a username and password; the password is printed once and never shown again. disable forgets the generated credentials. This is distinct from registry-credentials, which stores credentials for an external registry.
Registry credentials
update can rotate the password. test authenticates against the registry without pulling anything; repositories and tags browse the external registry.
Backup targets
--provider values are aws, r2 and custom; --endpoint is required for r2 and custom. test probes the bucket over its stored credentials without uploading or deleting anything.
Storage
providers lists the presets (aws, r2, b2, minio, wasabi, custom). add also takes --account-id (r2), --region (aws, b2, wasabi), --endpoint (minio, custom), --virtual-hosted and --skip-verify. test writes, reads back and deletes a probe object.
Data export
See Data export.Logs
See Log archive.TIME is an RFC 3339 timestamp or a duration back from now such as 24h. Without --app, a policy or dump covers every app. fetch downloads one archived object (gzip NDJSON). query returns a capped excerpt of an app’s newest matching log lines with match counts and a truncation notice; the byte cap defaults to 8 KB or APP_MCP_LOG_MAX_BYTES.
Network shares
NFS and CIFS network share mounts, the same shares an app’s volume mount can reference by name. See Network shares.--name, --protocol, --host and --remote-path are required on create and update. A CIFS share also needs --username and --password; on update, omit --password to keep the existing one. test checks that the share’s host is reachable on its protocol’s standard port.
Firewall
Declarative host firewall rules, reconciled onto the control plane’s localufw. See Host firewall. exposure, restrict and unrestrict are covered in Exposure audit.
--port is required (1 to 65535); --protocol defaults to tcp and --source-cidr to any source. A deny rule, or an allow rule scoped to a source CIDR, that targets a port the control plane itself needs (the management API, agent connections or ingress) is refused rather than applied.
Security center
The security score, sessions and devices, and the platform security policy. See Security center.posture prints the score for anyone with read; the item list needs root. The sessions commands act on your own account; --user names another account and needs root. A token used for them must belong to a user and hold write:sensitive or signin:approve. policy set needs root and changes only the flags you pass.
Feature flags
GET /api/v1/flags/evaluate/{key} with a read scoped API token. Changes take effect immediately with no redeploy. The key is globally unique across the control plane and cannot change after create.
Apply, diff and export
Experimental: requiresAPP_EXPERIMENTAL=iac. See Platform as code for the document format, secrets handling, prune rules and CI use.
--dry-run --exit-code). ${{ env.NAME }} placeholders are filled only from --var, --var-file or the names listed with --allow-env (a trailing * allows a prefix, but never covers credential looking names such as AWS_*, GITHUB_TOKEN or anything containing TOKEN, SECRET, PASSW or _KEY, which must be named exactly). An unresolved placeholder fails before anything is sent.
${{ env.NAME }} placeholders; supply them at apply time with --var, --var-file or --allow-env. Callers without read:sensitive always get placeholders for every env value.
Nodes
See Multi-node.deletefails while the node still has placements; drain it first.join-tokenmints a one-time enrollment token, shown once.reenroll-tokenmints a one-time token that re-issues a node’s agent certificate, keeping its identity, and prints the command to run on the node.revoke-certrevokes the certificate and closes the node’s session; only a re-enroll token brings it back.cordonmarks a node unschedulable without evacuating it;uncordonreverses that;drainmoves every service and database off a node.listshows each node’s certificate state and days left (CERT) and agent version (AGENT);getadds expiry, last renewal, key origin, platform and commit.resource-usageshows every node’s latest CPU, memory and disk usage plus a fleet rollup;capacity-forecastprojects disk and memory usage forward, roughly how many days until full.meshshows the live WireGuard mesh state and peers;rotate-keyrotates a node’s WireGuard key;rejoin-meshforces an immediate resync for a stuck peer.providersmanages cloud provider credentials (Hetzner, DigitalOcean) andprovisioncreates a server at a provider and enrolls it as a node;ssh-provisionadopts a machine you already have over SSH.provisionsandssh-provisionstrack either through to enrollment. See Multi-cloud provisioning.topologyis a whole mesh summary (nodes, apps, databases, load balancers, connections);trafficshows per domain ingress reachability and TLS status.
Status
Upgrade
--apply. See Installing.
backup-now takes a control plane backup and re-runs the preflight. schedule queues the upgrade for a time or the next maintenance window; the preflight re-runs at that time and nothing is applied if it fails. auto reads and sets the automatic upgrade policy, which is off by default; set changes only the flags you pass. All of these need a root token. See Upgrade safely.
--plan shows the breaking changes between the running version and the target (default: latest on the channel). --apply asks the control plane to run the safe self-update on its host: verified download, snapshot, migration dry run, swap, health check and automatic rollback. Breaking changes flagged as needing acknowledgement are refused until you list their ids with --ack-breaking. It follows the attempt to its outcome unless --no-wait, and exits non-zero when the upgrade was rolled back or failed. --attempts lists every attempt with its step timeline. See Upgrade safely.
System restart
--yes; without a terminal, --yes is required. With --wait it polls until the control plane answers from a new process (its boot_id changes), tolerating connection errors while it is down, and gives up after --timeout. status prints the current boot_id, whether restart is supported and whether one is pending.
If no process supervisor was detected, the command prints the reason and the command to run on the server (for example sudo systemctl restart levelrail) and exits non-zero. The API is GET and POST /api/v1/system/restart.
Readiness
install.sh --check instead, see Installing.
Version
Changelog
--limit the server default applies. The dashboard shows the same notes in the What’s new panel.
Init
app.yaml (the app spec, validated with the platform’s own validator), AGENTS.md (how an AI agent deploys, checks and rolls back the app) and .mcp.json (MCP server config; the token is an env var reference, never a value).
- Existing files are never overwritten unless
--forceis given. A diff of what would change is shown either way. - Without
--yes, a terminal is asked to confirm; a script must pass--yesor--dry-run. --modeselects the tool exposure written to.mcp.json:agent-core(the default, a small profile for deploy and debug work),read-only(every read tool, no mutations),standard(read and mutating tools, no destructive ones) orfull.--api-urlor the active profile is written intoAGENTS.mdand.mcp.jsonwhen known.--mcp-binaryoverrides the MCP server binary name.
API docs
--json, --output and --query. See API explorer.
Deploy link
--launcher, the launcher is APP_BRAND_DOCS_URL plus /deploy.html. --server also prints the direct https://<server>/apps/new?deploy=1&... link. Supports --json, --output and --query. See Deploy links and badge.
AI assistant
Experimental: requiresAPP_EXPERIMENTAL=ai-chat, and a provider, model and key set with settings ai-assistant set. The assistant is read and suggest only: a tool call that would change state pauses for an explicit confirmation. See In-app AI assistant chat.
ai chatsends one message and streams the reply to stdout. Without--sessionit starts a new session and prints its id to stderr; pass that id back with--sessionto continue the conversation.--jsonprints one JSON object per stream event.ai sessions resolveapproves or rejects a mutating tool call the assistant proposed (shown byai chatas a pending confirmation), then streams the continuation.
AI control
Control what AI agents can do on your platform.statusshows the current mode, allowed environment kinds, and when it was last changed.setchanges the mode or allowed environment kinds. Agent tokens cannot approve deploy or pipeline approvals, and cannot change this setting.revoke-agentsrevokes every labeled agent token.
Audit log
audit-log lists every recorded write, deploy and root tier request plus automatic certificate renewals, newest first. Read only requests are not recorded. It needs an admin or root scoped token. Flags: --limit N, --before RFC3339, --path, --method, --client-kind cli|dashboard|mcp|api, --agent <name> (entries made with a token labeled with that agent name), --search <text> (case-insensitive substring across actor, ability, method, path and remote address), --resource domain:<name>|zone:<name>|app:<name> (one resource’s own trail), --actions <prefixes> (comma separated action prefixes such as dns_record.,proxy_route.,domain.), --failed (status 400 or higher), --format csv with --output-file FILE. --agent, --search and --failed are applied server side and carry into csv exports.
audit-purge deletes every entry older than the retention window (APP_AUDIT_LOG_RETENTION_DAYS, default 90 days) right now instead of waiting for the automatic sweep. It needs an admin or root scoped token.
Attention
/status). Exit code is 1 if any item is critical, 0 otherwise, so it works as a script gate. Supports --json, --output json|table|text, and --query.
TUI
Doctor
Setup
status prints every step with its state, time estimate and note, plus the “ready for production” percentage. next prints the one step to do next and where to do it. skip and undo record or clear an operator override for a step id such as teammate; reset clears every override and shows the guide again. The three writes need a root scoped token. Steps and their rules: Getting started. Supports --json, --output json|table|text, and --query.
Proxy
--domain) or an app’s domain (--app, upstream is the ingress HTTP port). setup detects a Traefik (Coolify’s included) and, with --confirm, turns on tls_terminated_upstream, saves the detected entrypoints, certificate resolver, directory and upstream host, writes one route file per domain and verifies each over HTTPS; without --confirm it is a dry run. It exits with an API error and the precise gap (detection_incomplete, upstream_unreachable with the drop-in fix, not_writable) when it cannot proceed. status prints detection, per-domain state (missing, written, stale, error), certificate issuer and expiry, and the checklist. apply rewrites the files now, verify probes again, disable removes the files it wrote. Writes need a root scoped token. Details: Run behind an existing proxy.
Containers
list shows every container on this node, managed or not. stop, remove and claim only act on a container the platform does not already manage (409 otherwise); for a managed app use apps stop, apps start, apps restart or apps delete. claim adopts an orphaned container into a new app. orphans lists leftover containers, volumes and certificates that no app or database accounts for, with where each stands against its grace period. reap runs one removal pass now (--dry-run reports without removing; exit 1 if anything could not be removed). Details and the APP_ORPHAN_* settings are in Delete and clean up.
System address
--domain adds the exact DNS records to create for that name. --ipv4 and --ipv6 set a manual override (root), --clear goes back to detection. See Standalone domains.
System maintenance
Fleet wide cleanup. These commands need an admin or root scoped token.System prune
Control plane backups
<data dir>/control-plane-backups/. create takes one now (manual snapshots are never auto-deleted), download saves one to --out FILE (or raw bytes to stdout), verify re-checks the checksum, SQLite integrity and schema version without restoring (exit 1 if any check fails), delete removes one. Snapshots never contain the master key. Restore is an offline server command, levelrail restore-db <file>; see Control plane backup and restore.
The --offbox, schedule, run-now, drill, escrow and keys subcommands drive encrypted off-box backups. keys generate makes an age key pair on your machine (private key to a 0600 file, public key to stdout). schedule set changes only the flags you pass (--enable, --disable, --destination, --recipient, --schedule, --drill-schedule, --retain-daily, --retain-weekly, --retain-monthly, --escrow-destination). run-now and drill run wait for the run and exit 1 if it failed; drill status exits 1 when the last drill failed or none has run. escrow writes the master key and agent CA key encrypted to your recipients (never uploaded unless --upload, and never to the backup bucket). help-dr prints a static runbook. Restore an off-box backup on the server with levelrail restore --from <s3://... | file> --identity FILE [--dry-run]. See Disaster recovery.
Orphaned volumes
system-prune even after the app or database that created them is deleted, since Docker never removes a named volume on its own. volumes-orphaned lists every one this instance created that no current app, database or storage attachment references any more. volumes-orphaned-cleanup removes exactly the volumes named with --names (comma separated), after the control plane re-confirms each one is still genuinely orphaned. There is no flag that deletes every orphaned volume unseen; review the list first.
Users
--role is a curated preset (admin, operator, viewer, guest, or a custom role by name; users roles lists the curated presets and roles list lists every stored role); --abilities is a comma separated list from read, read:sensitive, write, write:sensitive, deploy, root. users role set changes a user’s role; users grants manages which environments a guest can see. invites create invites a teammate by email; invites list and invites revoke manage pending invites. See Access control for details.
Roles
IAM
--abilities. DOC is a policy document JSON string, passed inline or as file://path/to/policy.json:
update replaces the policy’s name, description and document. attachments lists a policy’s attached principals. templates shows built-in policy templates and apply instantiates one, optionally attaching it to a principal. See Access control.
Environments
Secrets
generate-master-key writes a new master key to a file (mode 0600, never overwrites), locally, without contacting the control plane. rotate-master-key re-wraps every stored data encryption key under a new master key in one atomic step, live, then binds any legacy values. binding-status counts stored secret values not yet bound to their slot, and rebind binds them (safe to rerun). Read Master key rotation before running these in production.
Migrate
app.yaml files plus a migration report into --out-dir (default ./migrated); --apply creates the apps directly on a target instance instead, using --target-token, --target-api-url and --target-profile. --include-secret-values also fetches real env var values. For Coolify, --token is an API bearer token (with the read:sensitive ability if you want secret values); for Dokploy it is an API key; for CapRover it is the login password.
Import
import classifies its input (a GitHub, GitLab, Gitea or Bitbucket repo URL, a docker run command, an image reference, a docker-compose.yml or a Dockerfile) and prints a deployment plan. Nothing is created unless --deploy is given. --file - reads from stdin. --env KEY=VALUE is repeatable, and a required variable with no value blocks --deploy.
import <repo-url> --analyze prints what the New app wizard would suggest (stack, build, port, health path, env variable names, databases) with the evidence for each, and creates nothing. --apply creates the suggested databases, the app, the connections, the repository link and the first build; --base-directory, --dockerfile, --build-type, --name, --port and --env override suggestions. See New app wizard.
import platform reads apps, databases and settings from another platform (read only) and creates them here. Use --dry-run first. Databases and volumes are created empty; data is not migrated. Re-running skips what was already imported. The source token is read from APP_IMPORT_SOURCE_TOKEN, --token-stdin or --token (which lands in shell history). Other flags: --only, --collision suffix|skip, --insecure-tls, --allow-private, --allow-loopback. See migrating from Coolify, Dokploy or CapRover.
import cutover moves one staged app’s traffic in a reversible flow. plan prints the readiness checklist, run --dry-run exercises everything except the switch, run --confirm NAME switches and verifies (rolling back on its own if verification fails), status shows the timeline, and rollback restores the previous DNS value and stops the staged app. Other flags: --run ID, --accept-warnings, --no-wait, --wait DURATION, --json. See guided cutover.
Completion
source <(levelrail-cli completion bash); run levelrail-cli completion -h for the zsh and fish install lines.
Settings
Instance wide configuration, gated at the root ability server side on every write.oauth set <provider>enables, configures or disables one sign in provider;<provider>isgoogle,githuboroidc.ingress getshows the primary domain, ACME settings, the automatic hostname toggle and the detected public address.ingress setchanges them (--primary-domain,--acme-enabled,--acme-email,--acme-directory-url,--fallback-domains=false,--hsts-enabled,--apps-base-domain,--dns-cname-target,--dns-ttl,--dns-proxied); flags you leave out keep their current value.ingress https statusshows whether the dashboard’s free sslip.io HTTPS is off, pending, issued or failed.ingress https enablepoints the dashboard at<dashed-ip>.sslip.ioand issues a real Let’s Encrypt certificate for it, with no DNS setup.dashboard-url setsets the public dashboard URL; once it ishttps://, sign in over plain HTTP is refused (--url ""clears it).updatesconfigures the release channel and auto update checking.deploy-freezemanages fleet wide freeze windows; per app windows are underapps freeze.ai-assistantis experimental (APP_EXPERIMENTAL=ai-chat):getshows the current settings (the key itself is never returned, only whether one is stored),set --model NAME --api-key KEYconfigures the assistant, andclearclears the stored key and resets provider and model.
Git integrations
git-providersshows connection status and capabilities (list branches, register a webhook, authenticated clone) for GitHub, GitLab, Bitbucket and Gitea in one call.- Connecting a provider is dashboard only, because it is a browser redirect through the provider’s own OAuth or manifest flow. Once connected, these commands browse its repos and branches, connect one as an app’s git source with
use-as-source, or check and forget the connection. disconnectforgets the stored connection locally; it does not uninstall the App or revoke the token on the provider’s side.github-app register-urlprints the dashboard link that starts GitHub App registration, for your personal account or, with--owner, an organization.--publiclets other accounts and organizations install the App. It makes no request; open the link in a signed-in browser.github-app installations addprints the URL to install the App on another account or org; it does not open a browser.installations removeis refused (409) while a git source still points at a repo under it.
Templates
list browses the curated service catalog, or --custom for your own saved templates. get shows one entry including its full compose.yaml. deploy deploys a template’s compose.yaml as an app, and the app name defaults to the template id; pass --name to use another. A custom template works with every verb the same as a built-in one, except delete: only a custom template can be deleted (see apps save-as-template). See Templates.
install is for manifest templates (the ones get shows with settings): it fills each ${KEY} setting from --env, a generated secret or its default, puts the listed services behind --domain hosts, and deploys the result as a compose app that is not a trial. See Compose apps.
Compose
deploydeploys or updates a stack and records a numbered revision;-f -reads stdin.--profile-nameenables services behind composeprofiles:.previewasks the server to parse and check a file without saving anything, lists each service with its generated and required env vars, and exits with code 2 when the file would be rejected.statusprints the stack phase and each service’s ready state with the reconciler’s reason.logsmerges recent lines from every service, or hands one service toapps logswith--service, where-ffollows it.redeployrecreates every service’s containers, or one service’s.rollbackre-applies an earlier compose file (default: the one before the latest) as a new revision.downremoves every service and its containers; named volumes and generated secrets are kept unless you pass--volumes.
Static sites
build.type: static app served directly through the embedded Caddy ingress, with no container involved.
Related
Getting started
Install the control plane and deploy a first app.
Deploying and managing apps
The app lifecycle, command by command.
App spec reference
Every field of
app.yaml.Feature catalog
The complete feature overview.