Operations

Backups & restore

Vortexa has two overlapping backup surfaces: the CLI's backup_now(), which snapshots the panel host's own filesystem state, and the panel's /backups page, which lists/downloads/restores/deletes backups and pulls node-level restorable state over RPC.

_authed.backups.tsx renders a list of backups with download / restore / delete actions. Clicking Restore asks for confirmation, then calls api.backups.restore(id). Node-level restorable state is not stored inside these panel backup archives by default — it is captured separately, on demand, via the node RPC method backup.snapshot, and only bundled in when a fleet-wide backup explicitly requests it.

Panel-side (backup_now())

The CLI backup is a single command:

bash
tar -czf /root/autoscript-backup-<timestamp>.tar.gz \
  /etc/autoscript \
  /var/lib/autoscript \
  /usr/local/etc/xray
PathContains
/etc/autoscriptagent.env (secrets, ADMIN_HASH, panel port/path/domain), TLS material, SSH banner config.
/var/lib/autoscriptpanel-state.json fallback (used when /etc is read-only under systemd sandboxing) — without this, a restore comes back with empty usage/settings.
/usr/local/etc/xrayThe panel-host's own local-node Xray configuration.

The SQLite database lives under /etc/autoscript or /var/lib/autoscript

There is only one database (SQLite, see DB_PATH in agent.env) and it lives inside one of the two backed-up directories, so the CLI backup is a full logical + config backup, not config-only.

Node-side (RPC backup.snapshot)

POST /rpc/backup.snapshot returns restorable node state: the Xray config, the ZIVPN config, users.rev, quota.json, vpn-traffic.json, and the account list — secrets (BEARER, SHARED_SECRET, TLS private key) are explicitly excluded, so a snapshot alone cannot be used to impersonate the node; it captures state, not identity.

Panel CLI backup
/root/autoscript-backup-<YYYYMMDD-HHMMSS>.tar.gz on the panel host's local disk.
/backups page entries
Whatever the panel backend persists per backup job (id, timestamp, size) — download serves the archive back to the browser.
Node backup.snapshot
Returned inline in the RPC response (JSON), not written to disk on the node; the panel is responsible for persisting it if it wants it retained.

backup_now() is on-demand only — there is no cron/timer wired up for it in cli.sh or the systemd unit set; it runs exactly when triggered from the menu (option 11), the autoscript backup flag, or whatever schedule an operator wires up themselves (e.g. a cron entry calling autoscript backup). There is no automatic retention/pruning of old archives in /root — old autoscript-backup-*.tar.gz files accumulate until removed manually.

Recommended pattern

Add a root crontab entry (for example nightly) calling autoscript backup, and a second job that copies the newest archive off-box and deletes local copies older than your retention window.
bash
# /etc/cron.d/autoscript-backup
0 3 * * * root /usr/local/bin/autoscript backup >/var/log/autoscript-backup.log 2>&1
30 3 * * * root find /root -maxdepth 1 -name 'autoscript-backup-*.tar.gz' -mtime +14 -delete

Vortexa does not ship a built-in off-box uploader (no S3/rsync integration in cli.sh). Treat every autoscript-backup-*.tar.gz as sensitive (it contains agent.env, which hasADMIN_HASH, node bearer/shared secrets, and TLS keys) and copy it off the VPS yourself, for example:

bash
scp root@panel-host:/root/autoscript-backup-*.tar.gz /secure/offsite/backups/
# or
rsync -avz root@panel-host:/root/autoscript-backup-*.tar.gz /secure/offsite/backups/
  1. 1
    Provision a fresh Ubuntu/Debian VPS with the same DNS A/AAAA records the old panel used (or update DNS afterward and expect a propagation delay before nodes/clients can reach it).
  2. 2
    Copy the latest autoscript-backup-*.tar.gz onto the new box (scp/rsync), e.g. into /root/.
  3. 3
    Run install.sh fresh on the new VPS exactly as for a first-time install (installs OS packages, Xray, nginx, stunnel, the venv, and systemd units) — do not skip this even though you have a backup, because the archive only contains config/data, not the installed binaries/services.
  4. 4
    Stop the freshly-installed stack before overwriting its config: autoscript maintenance on, then systemctl stop autoscript-web autoscript-agent autoscript-bot autoscript-ssh-ws xray nginx.
  5. 5
    Extract the archive over the fresh install's data directories, replacing the just-generated fresh config with your real one:
    bash
    tar -xzf /root/autoscript-backup-<timestamp>.tar.gz -C /
  6. 6
    Verify /etc/autoscript/agent.env permissions are still 0600 (it holds secrets) and that PANEL_DOMAIN/PANEL_PORT match the new box's intended DNS.
  7. 7
    Re-run backend/scripts/apply_settings.sh (or the CLI's "Change panel domain" action) so TLS is reissued for the new host if the domain/IP changed.
  8. 8
    Run autoscript repair to make sure Xray/stunnel/nginx configs are reconciled against the restored settings.
  9. 9
    Bring the stack back with autoscript restart (this also lifts maintenance once the web port answers).
  10. 10
    Log in and check autoscript status: confirm the admin user, release version, and that every listed service is active.
  11. 11
    For each fleet node, its pinned handshake fingerprint is stored on the panel side (in the same restored database/state), so nodes should re-associate automatically on their next heartbeat — verify on /nodes that every node flips back to Online. If any stay on "fingerprint mismatch", use Force re-pin (see Troubleshooting).

Node-side state is not restored by this runbook

This runbook restores the panel/master only. If a node itself needs to be rebuilt from scratch, re-run its install one-liner (idempotent) and, if you captured a backup.snapshot for it, push that snapshot back down via backup.restore_latest (RPC, 180s timeout) rather than trying to hand-copy Xray/ZIVPN config files.