Skip to content
NebulaCtrldocs
Guides

Use the nebula command line

Install the nebula command, log in, and use it to check status, read logs, change variables, deploy, run a command with a service's variables and plan nebula.toml changes from a terminal.

The nebula command lets you do the everyday work of the console from a terminal, and gives scripts and coding agents the same operations with --json output. It calls the control plane's API with an API token, so it can do what that token's role allows and nothing more.

Before you begin

  • Know your control plane's address, for example https://nebula.example.com.
  • Creating the token that nebula login stores needs the admin or owner role. With a lower role, ask an admin for a token and log in with --token.

Install the command

curl -fsSL https://get.nebulactrl.dev/cli.sh | sh

The script picks the build for your system (Linux, macOS or Windows in a POSIX shell, on x86-64 or arm64), checks it against the release's published SHA-256 list and installs nebula into /usr/local/bin when you run it as root, or ~/.local/bin otherwise. Pass --dir DIR to choose another directory and --version X.Y.Z to install an older release.

nebula version
0.41.0 go1.27.1 linux/amd64

The same binary is the control plane. The downloaded build is for the client commands; run the server from its container image.

Log in

nebula login --url https://nebula.example.com

The command opens your browser on the control plane's authorize page and waits. Sign in if you are not, then check the organization, choose the Role (Viewer, Deployer or Admin; Deployer is the default) and when the token Expires (90 days by default), and select Authorize. The browser sends the new token to the command on your own computer, which stores it in ~/.config/nebula/credentials.json (or $XDG_CONFIG_HOME/nebula/credentials.json) with mode 0600.

The token appears in Settings > API tokens as nebula CLI on COMPUTER, where you can revoke it at any time.

To log in without a browser, for example over SSH, pass the token on standard input:

echo "$NEBULA_TOKEN" | nebula login --url https://nebula.example.com --token

NEBULA_TOKEN holds an API token you created in Settings > API tokens. Add --no-browser to the browser flow to print the authorize address instead of opening it.

In CI, skip login: set NEBULA_URL and NEBULA_TOKEN in the job's environment and every command uses them.

nebula whoami
https://nebula.example.com
  organization  Acme (acme)
  token         nebula CLI on laptop, role deployer, all projects, expires in 89 days

Choose a project and environment

Commands that act on an environment take --project and --env. To stop typing them, link the directory:

nebula link --project shop --env development

This writes .nebula/link.json, which holds slugs only and can be committed. Commands look for it in the working directory and every parent. A flag wins over the link, and NEBULA_PROJECT, NEBULA_ENV and NEBULA_SERVICE win over it too.

If a project has more than one environment and you pass none, the command lists them and stops. It never defaults to production.

nebula projects

Check status

nebula status
shop · development

SERVICE  STATE    RELEASE  REPLICAS  DOMAIN
api      healthy  r-12     2/2       api.dev.example.com
worker   healthy  r-9      1/1       –

A service whose newest deployment failed gets the full reason underneath and the release that is still serving.

Read logs

nebula logs --service api --since 30m

Add -f to follow new lines. Without --service, the command reads every service of the environment and prefixes each line with its slug. Narrow the output with --level error, --filter TEXT and --pod NAME, and print more history with -n 500. While following, the command reconnects if the control plane closes the stream; lines written in the gap are not replayed.

Change variables

nebula variables list --service api

Secrets are masked. Add --reveal to see them; each revealed secret is recorded in the audit log.

nebula variables set LOG_LEVEL=debug --service api --env development

The command stages the change in your draft change set and applies it, which redeploys the services that read the variable. Values can hold references such as '${{ db.DATABASE_URL }}'; quote them so your shell leaves them alone. Add --secret to mark a value secret, --message TEXT to say why, and --wait to follow every deployment it starts.

In a protected environment the apply opens an approval instead. The command prints a link and exits without changing anything:

production is protected, so this change waits for an approval; nothing has changed yet.
Approve it here (expires 2026-10-03 10:00):
  https://nebula.example.com/acme/approvals?approval=APPROVAL_ID

Remove variables with nebula variables unset KEY. If your draft already holds staged changes, set and unset stop without touching them; pass --include-staged to apply everything together. A variable that nebula.toml owns cannot be changed here; the error names the file and commit.

Deploy

nebula deploy --service api --env staging

Without --ref this redeploys the release that is serving against the service's newest configuration. For a service built from Git, --ref BRANCH builds the branch head and deploys it; for an image service, --ref TAG deploys that tag of the service's repository, or a full image reference. The command prints each stage as the rollout moves and exits 0 only when the new release is healthy.

If the deployment fails, the command exits 1 and prints the full reason. The previous release keeps serving. In a protected environment the deployment first waits for an approval and the command prints its link. Add --no-wait to start the deployment and return, and --timeout 15m to stop waiting; the deployment continues either way.

Run a command with a service's variables

nebula run --service api --env development -- npm run migrate

The command fetches the variables the service runs with, resolves every ${{ service.KEY }} reference as a release does, and starts your command with them added to your environment. Its exit status becomes the exit status of nebula run. Reading secrets this way needs the deployer role and records each secret as revealed.

Hosts inside the cluster, such as svc-db, resolve only there. To reach a database from your computer, use a tunnel or a Tailscale address and override that variable in your shell.

Plan nebula.toml changes

nebula config plan --project shop

The command sends your local nebula.toml files (the one in the working directory and every nebula.toml below it, or the files you name) to the control plane, which answers what pushing them would create, change or release in each environment. Nothing is written. Secret values print as ••••. Add --env production to plan one environment.

Plan for project shop

development: no changes

production: changes (change api)
  variable.set  api LOG_LEVEL: info → debug

Problems in a file print as PATH:LINE: MESSAGE. The exit status is 0 when nothing would change and 1 for an error, a problem or an environment the control plane would refuse. With --detailed-exit-code it is 2 when there are changes, so a pull request check can fail until someone reviews the plan:

nebula config plan --detailed-exit-code --json

To check a file without a control plane, use nebula config validate.

Use it from scripts and agents

  • Every read command takes --json. nebula logs --json prints one JSON object per line.
  • Failures are one plain line on standard error, prefixed nebula:. Exit status 1 is a failure, 2 a mistyped command line.
  • NEBULA_URL and NEBULA_TOKEN replace nebula login.

Log out

nebula logout

This revokes the stored token and deletes the credentials file. If the control plane cannot be reached, nothing is deleted, so a valid token is never left without a copy you can revoke; --local deletes the file anyway.

Next steps

On this page