CLI tasks & recovery
These are the commands you’ll reach for when the UI isn’t the right tool: a locked
-out password, a controller rebuild, or scripting setup. All accept the global
--data-dir flag.
Reset the admin password
Locked out of the console? Reset it from the host:
asternodis auth set-password [--password PW]
This sets the password of the built-in admin account, creating it if no account named
admin exists (for example, when first run used a different username). Omit --password
to pass the new password on standard input instead of as an argument: pipe it in, or type
it and press Enter then Ctrl-D. This is the documented recovery path when the first-run
admin password is lost.
Back up & restore the controller
Protect the thing that protects everything else, the controller’s own config:
asternodis backup [--out FILE] # write a config backup (DB + keys)
asternodis restore --in FILE [--force] # restore one (run with the daemon stopped)
Restoring rebuilds a lost controller from a backup. restore refuses to overwrite a data
dir that already holds a database; add --force to replace it, for example on a freshly
installed host whose service has already started. You can also do both from
Settings → Controller backup & restore in the UI.
Support bundle
asternodis support-bundle [--out FILE] # redacted diagnostics for a support request
Writes a .tar.gz of this controller’s versions, licensing state, topology, and recent
operations, replication runs, alerts and audit entries. By default it goes into the current
directory, or to --out FILE (--out - writes to standard output). Unlike backup, it
carries no keys, tokens or passwords; open it before you send it if you want to check.
Licensing
asternodis license [status] # show licensing / trial state
asternodis license activate --key KEY # install an activation key
asternodis license deactivate # remove the key (revert to trial)
license status also prints the paid-through date, when the licensing service last confirmed
this controller, and the service’s verdict, matching the License page.
Remotes (Proxmox connections)
asternodis remote add ... # add a cluster/node
asternodis remote list # list managed remotes
asternodis remote test [--name NAME] # test connectivity (all, or one)
asternodis remote rm --name NAME # remove a remote
asternodis remote cluster [--name NAME] # check SSH reach to every node in the cluster
asternodis remote authorize --name NAME # install this controller's SSH key on every cluster node
asternodis inventory # list resources across all remotes
remote add registers a cluster by API token only (--name, --host, --port,
--token-id, --token-secret, --insecure-tls). Replication also needs SSH access to
the nodes, which you configure when you connect the cluster
in the web UI; remote cluster and remote authorize work on remotes that have it.
remote cluster checks that this controller can SSH to every member of each cluster, or
only the one named with --name: the entry node directly, the other members by name
through it. It prints each node as OK or UNREACH and exits non-zero if any is unreachable.
A node that fails here would break replication for any protected guest that migrates onto it.
remote authorize --name NAME writes to ~/.ssh/authorized_keys on every member of
that cluster: it adds the public half of the SSH key this controller holds for that
cluster to the entry node directly and to each other member over the cluster’s own
node-to-node SSH. The web UI does the same when you add a clustered node; run this command
to repeat it, for example after a node joins the cluster or when remote cluster reports
one unreachable. It is idempotent (a node that already has the key reports present)
and it lists each node as added, present or failed, exiting non-zero if any failed.
Site identity & pairs
asternodis site [rename --name NAME] # show / rename this site's identity
asternodis pair add --name NAME [--role primary|recovery] # step 1: create a pair
asternodis pair join --endpoint HOST:PORT --code CODE --advertise HOST:PORT # step 2, on the peer
asternodis pair list # list pairs
asternodis pair rm --uuid UUID # remove a pair
Pairing from the shell takes one command on each controller:
- On the first controller,
pair addcreates the pair and prints its UUID, this site’s role, a pairing code, and thepair joincommand to run on the peer with that code filled in.--rolesets this site’s role and defaults toprimary;--peer-nameand--peer-endpointare optional, since both are learned during pairing. - On the other controller,
pair joincontacts the first controller’s peer port, authenticates both sides with the pairing code, and activates the pair on both controllers. The first controller’s daemon (asternodis serve) must be running to answer it.
pair join flags:
| Flag | Purpose |
|---|---|
--endpoint HOST:PORT | Required. The first controller’s peer address: its peer-link host and port (:8444 by default). |
--code CODE | Required. The pairing code pair add printed. |
--advertise HOST:PORT | This controller’s own peer address. The first controller records it and uses it to reach this one, so always pass it. |
--web-advertise URL | Optional. This controller’s web-console URL, shared with the peer for its “open peer console” link. |
--role ROLE | Optional. primary or recovery; defaults to the opposite of the first controller’s role. A primary pairs only with a recovery site. |
Disaster-recovery operations
Drive failover, failback and DR tests headless. These call the local daemon, so
asternodis serve must be running. Unlike the commands above, they don’t edit the database
directly, and they honour the same guards (and audit log) as the UI. Most operators run DR
from the web console, but the CLI is here for scripts and break-glass access. Run it as root
on the controller host: it authenticates with the daemon’s token in the data dir
(cli.token; ASTERNODIS_TOKEN and ASTERNODIS_URL override the token and the default
https://127.0.0.1). Each command is routed to the site that holds the guest’s recovery
copy, so the same command works from either site.
asternodis dr status # each guest's DR posture (source / recovery)
asternodis dr failover --pair UUID --vmid N # boot the guest at the RECOVERY site
asternodis dr failback --pair UUID --vmid N # return the workload HOME (final delta + boot)
asternodis dr test --pair UUID --vmid N # start an isolated, non-disruptive DR test
asternodis dr test-stop --pair UUID --vmid N # tear down a running DR test
asternodis dr reseed --pair UUID --vmid N # rebuild the DR copy onto the primary
Run asternodis dr status to find a pair’s UUID. Apart from status, every command takes:
| Flag | Applies to | Purpose |
|---|---|---|
--pair UUID, --vmid N | all | Required: the pair and the guest. |
--reason TEXT | all | Recorded in the audit log. |
--yes, -y | failover, failback, reseed | Skip the confirmation prompt. Without it these commands refuse to run non-interactively, so a script must pass it. |
--no-start | failover | Promote the copy but don’t power it on. A copy that isn’t running makes the failback slower (see Settings). |
--force | failover, failback | failover: override the split-brain fencing guard. failback: proceed even if the primary’s disk could not be verified against the DR copy; a verified mismatch still aborts. |
--replace-leftover | failover | Destroy and rebuild a stopped Asternodis failover VM left at the destination VMID by an interrupted promote. |
failover and test also take --point ID to boot a specific recovery point instead of the
latest one, the CLI equivalent of “Recover to this” in the Points dialog:
asternodis dr failover --pair UUID --vmid N --point SNAP_ID --reason "pre-incident restore"
asternodis dr test --pair UUID --vmid N --point SNAP_ID
asternodis dr reseed is the recovery path for a diverged or stalled reverse lane. It
forces a full reverse re-seed so the next failback has a clean copy to work from, without
any database surgery. It’s the CLI equivalent of the Rebuild DR copy button on a
guest’s replication page.
Failover prints the preflight first. asternodis dr failover runs the same go/no-go
capacity and network preflight as the web console and prints the verdict before it asks
you to confirm:
✓ capacity/network preflight: OK: go.! capacity/network preflight: OK, with warnings: each warning is listed beneath it.✗ capacity/network preflight FAILED: each failing check is listed (memory, vCPU, storage, machine type or network, for example a target bridge that does not exist on the recovery node, Open vSwitch bridges included), with the note that the failover is likely to fail partway.
The preflight is advisory: it never blocks a failover, here or in the console. A failed one is
repeated in the confirmation prompt, so answering y is your acknowledgement; with --yes the
failover proceeds without a prompt, and says so. The preflight is bounded to 20 seconds: if it
can’t answer in time the CLI prints capacity/network preflight did not run and carries on,
which is not a report that the recovery node can host the guest.
Everything here has a UI equivalent. The CLI just lets you do it headless or in a script.
Verify a release
asternodis verify-release [--dir DIR] [--name NAME]
Checks a directory holding a downloaded SHA256SUMS, SHA256SUMS.sig and the release binary
(--name, default this host’s asset name: asternodis_linux_amd64 or …_arm64) against the
Ed25519 release key built into the binary (the same check the in-app updater, install.sh
and update.sh make) and exits non-zero if it does not verify. Run it from a trusted,
already-installed asternodis; a freshly downloaded binary should not vouch for itself.
Audit log
asternodis audit verify [--json] # check this controller's audit log (read-only)
asternodis audit verify-export --log CSV --anchors JSON [--fingerprint FP] # check a COPY of a log against a paired site's signed anchors, offline
asternodis audit export-anchors [--out FILE] # write the signed anchors this site holds for its peers
audit verify needs no running daemon: it opens the database read-only and checks the hash
chain, the seals, the local anchor and every anchor a paired site holds for this log, printing
Result: OK or the first problem and exiting non-zero when the log does not verify.
verify-export checks an exported CSV copy of a log against the signed statements a paired
site holds for it. It is the check that still works when the controller’s own binary can’t be
trusted; pass the audited site’s certificate fingerprint (from its pair page) with
--fingerprint, or the export’s own certificate is taken on its word.
export-anchors writes the document verify-export reads.