Skip to content

CLI Reference

Beyond install and uninstall (see Install Alta VMS), the altavms binary wraps the rest of day-to-day operation: starting and stopping the service, checking its health, backing up and restoring data, and inspecting configuration. Each command is a thin, honest wrapper — most print the underlying systemctl or journalctl command they run (to stderr, so piped stdout stays clean), and those raw commands remain fully supported if you’d rather use them directly.

Run altavms help for the full list, or altavms help <command> for one command’s detail.

CommandWhat it does
altavms start [--force]Validates the config, then systemctl start altavms.
altavms stopsystemctl stop altavms.
altavms restart [--force]Validates the config, then systemctl restart altavms.
altavms enable [--now]systemctl enable [--now] altavms — start at boot.
altavms disable [--now]systemctl disable [--now] altavms.
altavms logs [-f] [-n N] [--since W] [--until W] [-o FMT]journalctl -u altavms --no-pager, with your flags. -f follows.

altavms logs never needs root: journal reads work for members of the systemd-journal (or adm) group. If you see no entries, add your user to that group or run it with sudo.

CommandWhat it shows
altavms status [--json] [--verbose]Unit state, the same checks /readyz runs, config/data paths and sizes, and two drift warnings: a binary that was replaced without a restart, and root-owned WAL sidecar files the service can’t write to.
altavms doctor [--json] [--config PATH] [--db PATH]An offline checkup for a box where the service won’t start: config validation, schema/environment/keyring checks, systemd unit shape, a database integrity check and schema-version check, file ownership, free disk space, the effective enabled-workers set, and the reconcile-sweep safety settings. Every finding is paired with a fix.
altavms versionPrints the binary version and build time.

Both status and doctor work without root — root-only checks are shown as skipped rather than failing. status never exits 0 while the service is down, so it’s safe to use in monitoring scripts:

Exit codeMeaning
0ok
4not installed
5unit not active
6active, but not ready
CommandWhat it does
altavms backup [--output PATH|-] [--no-secrets] [--no-maps]Consistent hot backup — no downtime. See Backup & Restore.
altavms restore <archive> [--dry-run] [--stop-service]Verified, guarded restore. See Backup & Restore.
altavms reset-password <email>Mints a one-time password-reset link for a locked-out admin. See Recover a forgotten password.
CommandWhat it does
altavms config validate [--config PATH] [--env-file PATH]Checks the installed configuration exactly the way boot would — the same merge of config.yaml and the systemd env file.
altavms config print [--format text|json]Prints the effective, merged configuration with every secret redacted — safe to paste into a support ticket.
altavms config print --referencePrints the full annotated reference configuration (every key, its default, and a description) — no installed config needed.

Neither config subcommand needs root.

CodeMeaning
0success
1attempted and failed
2usage error
3precondition failed — not Linux, no systemctl, or needs root
4not installed (no unit, config, or database found)
5 / 6status only — see the table above
  • Mutating commands (start, stop, restart, enable, disable, install, uninstall, restore) check for root themselves and refuse with exit 3 rather than letting systemctl fall through to a polkit prompt — which would hang forever without a terminal (cron, CI, a pipe).
  • Read-only commands (status, logs, config, doctor) never require root; they degrade individual rows or checks instead.

The log level is fixed at boot — there’s deliberately no runtime toggle. Set it in the env file and restart:

Terminal window
echo 'ALTAVMS_LOG_LEVEL=debug' | sudo tee -a /etc/altavms/altavms.env
sudo altavms restart

Remember to remove it afterwards — debug is verbose.

Service logs are structured JSON on stdout, which lands in journald — log rotation is journald’s job, not Alta VMS’s. If altavms logs shows the journal eating disk space, cap it in /etc/systemd/journald.conf:

[Journal]
SystemMaxUse=1G

then sudo systemctl restart systemd-journald.

Re-run the installer with the new binary — it’s idempotent (config and secrets are never overwritten) and restarts the service once the binary has actually changed:

Terminal window
curl -fsSL https://vms.cesbo.com/install.sh | sh

altavms status warns if the running process predates the binary now on disk — a sign a restart didn’t happen or was interrupted.

The binary has no TLS listener by design — production terminates TLS at a reverse proxy in front of it. A minimal nginx site:

server {
listen 443 ssl;
server_name vms.example.com;
ssl_certificate /etc/letsencrypt/live/vms.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/vms.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3303;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# SSE (alerts/status feeds) and long-lived requests:
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 3600s;
}
}

or Caddy, which handles certificates automatically:

vms.example.com {
reverse_proxy 127.0.0.1:3303 {
flush_interval -1
}
}

Then add the public origin to http.allowed_origins in /etc/altavms/config.yaml and sudo altavms restart. If you also set http.internal_addr for a separate metrics/health listener, don’t point the proxy’s own health check at /readyz on the public listener — see the note printed by altavms status.