Alpha. Vary is under active development and not ready for production use. Syntax, APIs, performance, and behaviour may change between releases.

Operations

This page lists the operator commands that are present in the current Via and Vary CLIs. Examples use prod as the named target and my-api as an existing Via app.

Operator examples assume via install has added your host user to the Via admin/shared group. Reconnect or run newgrp vary after first install so the membership is active in your shell.

Server status

via status
via status --json

via status reports the Via version, installed service runtime, default toolchain, upgrade state, production/dev mode, external URL, tracked component states, Docker reachability, state-directory free space, and an overall healthy or degraded result. It exits non-zero when the report is degraded.

Useful local overrides:

via status --config /etc/via/server.toml
via status --config-dir /etc/via --state-dir /var/lib/via --log-dir /var/log/via
via status --systemd-dir /etc/systemd/system --install-root /opt/vary

The tracked components are control-plane, builder, runner, test-runner, config-server, and proxy.

Server doctor

via doctor
via doctor --fix
via doctor --json
via doctor --skip-host-checks

via doctor checks the control-plane schema first, then host/service prerequisites unless --skip-host-checks is passed. It exits non-zero for failed checks or an unknown-newer schema.

Use via doctor --fix when doctor reports a safe host repair, such as runtime-trust bootstrap drift, before rerunning the normal health check.

Useful local overrides:

via doctor --db-path /var/lib/via/control-plane.db
via doctor --config-dir /etc/via --state-dir /var/lib/via --log-dir /var/log/via
via doctor --systemd-dir /etc/systemd/system

If doctor reports prebaseline_checksum_drift, create a drift-safe backup before repair:

via backup create --include-control-plane --allow-checksum-drift /var/lib/via/backups/prebaseline.zip

Preview a metadata-only rebaseline before applying it:

via control-plane rebaseline --from-prebaseline --backup-id <backup-id> --dry-run --json

Apply only after the compatibility report is clean:

via control-plane rebaseline --from-prebaseline --backup-id <backup-id> \
  --confirm "REBASELINE /var/lib/via/control-plane.db TO 1"
via upgrade resume
via doctor

The clean-install path is destructive and requires a typed confirmation:

via control-plane clean-install --dry-run

App status

vary app status my-api --target prod
vary app status my-api --target prod --json
vary app inspect my-api --target prod
vary app inspect my-api --target prod --env prod --json

status gives the current deploy/build/runtime snapshot. inspect adds state-transition history, gate results, declared config and secret names, runtime health checks, add-ons, and recent events. Secret values are never printed.

For same-host operator access, use the local Via commands:

via app status my-api
via app inspect my-api
via app doctor my-api

Logs

Remote log access:

vary app logs my-api --target prod
vary app logs my-api --target prod --source runtime --tail 200
vary app logs my-api --target prod --source build --tail 200
vary app logs my-api --target prod --follow

Local phase-specific log access:

vary app logs my-api --build <build-id>
vary app logs my-api --test <build-id>
vary app logs my-api --mutation <build-id>
vary app logs my-api --deploy <deploy-id>
vary app logs my-api --audit
vary app logs my-api --runtime --since 2026-04-25T12:00:00Z

Local --since and --until values are ISO-8601 instants. Remote target mode uses --since as the byte offset returned by the previous log response.

Builds and deploys

vary app builds my-api --target prod
vary app build <build-id> --target prod
vary app build logs <build-id> --target prod --app my-api --tail 200
vary app build logs <build-id> --target prod --app my-api --follow
vary app build cancel <build-id> --target prod --app my-api --follow
vary app deploys my-api --target prod
vary app deploy <deploy-id> --target prod
vary app deploy retry <deploy-id> --target prod --app my-api --apply-manifest --follow

builds and deploys list recent rows for an app. build and deploy show a single row by id. build logs requires the app name through --app unless the current project has [app].id in vary.toml. Use --apply-manifest on deploy retry so Via reconciles against the current effective manifest before queueing the replacement deploy.

The app-level diagnostic commands are:

vary app doctor my-api --target prod
vary app smoke my-api --target prod
vary app repair my-api --target prod --dry-run --json
vary app repair my-api --target prod

doctor diagnoses route, runtime, dependency, build consistency, stuck build, and log-availability problems. smoke probes the advertised app route from the developer workstation. repair renews runtime identity and relaunches the runtime; unsafe repair actions require --allow-unsafe --reason <text>.

Releases and rollback

vary app releases my-api --target prod
vary app releases my-api --target prod --limit 10 --json
vary app rollback my-api --target prod
vary app rollback my-api --target prod --release <release-id>
vary app rollback my-api --target prod --json

Rollback targets releases, not deploy ids. Without --release, the server chooses the immediately previous release for the app. Rollback flips the app's current release and does not trigger a rebuild.

Domains, certificates, and routes

Developer app route intent lives in via.app.toml and is applied by deploy:

vary app deploy my-api --target prod --apply-manifest
vary app deploy my-api --target prod --resume
vary app smoke my-api --target prod

Operator route and certificate surfaces:

via domain list
via domain requests
via domain approve my-api api.example.com --reason "approved"
via domain reject my-api api.example.com --reason "not allowed"
via load-balancer routes
via load-balancer validate
via load-balancer reload
via load-balancer status
via certificate list
via certificate inspect <certificate-id> --server https://vary.example.com --session-token <operator-session-token>

via domain approve, via domain reject, and via domain requests are local-only operator commands. via load-balancer status is local-only. The certificate lifecycle commands use the operator API and require --server and --session-token, except via certificate list, which also supports local control-plane reads.

Certificate private keys, PEM material, ACME account keys, and storage paths must not appear in app-owner responses, CLI output, audit exports, operation logs, or health reports.

For certificate-specific workflows, see Certificates.

Key rotation

via key rotate identity
via key rotate artifacts
via secret key rotate

Each rotation archives the previous active key under previous/, writes a new active key, and records an audit event. The commands accept --actor, --config-dir, --state-dir, --log-dir, and --systemd-dir.

CommandRotatesAudit action
via key rotate identityJWT identity signing keyidentity_key_rotated
via key rotate artifactsArtifact signing keyartifact_key_rotated
via secret key rotateSecret encryption keysecret_encryption_key_rotated

Tokens minted under the previous identity key continue to verify until they expire. Artifacts signed under the previous artifact key continue to launch. Secrets encrypted under the previous secret key continue to decrypt until that value is rewritten.

To re-encrypt an app secret after rotating the server secret key:

vary app env rotate my-api DATABASE_URL --target prod

Backup and restore

via backup create /var/backups/vary/<bundle>.zip
via backup create --include-secrets /var/backups/vary/<bundle>.zip
via backup restore /var/backups/vary/<bundle>.zip
via backup restore /var/backups/vary/<bundle>.zip --overwrite
via backup restore /var/backups/vary/<bundle>.zip --skip-secret-key

The default backup includes server config, public identity material, signing keys, bare repos, artifacts, SQLite add-on state, and a control-plane database snapshot. It does not include the secret encryption key file. --include-secrets adds that key; treat the archive itself as a recovery key.

Restore refuses to write over an initialized host unless --overwrite is passed. --skip-secret-key keeps the target host's existing secret encryption key instead of writing the key from the bundle.

After restore, restart the Via services:

systemctl restart via-server via-builder via-runner via-test-runner via-config

Continue to TLS, routing, and the proxy for the public-traffic surface.