Updates, backup and restore

The rivo update, rivo rollback, rivo backup and rivo restore commands, the backup passphrase, rotation, S3 upload and moving to a new server.

This article is for your own installation (Self-host and Managed VPS). The Cloud updates and backs itself up.

The rivo CLI

rivo status              # containers, domain, API health, last backup, data size
rivo logs api -f         # service logs (api, web, db, caddy)
rivo update              # update (a backup is taken automatically first)
rivo rollback            # undo an update: previous version plus the data as of the update
rivo backup              # back up right now
rivo restore --latest    # restore the latest archive
rivo start | stop | restart

If the rivo command isn't on the path, use /opt/rivo/infra/rivo.

Updating

sudo rivo update                  # latest version
sudo rivo update --version 1.4.2  # a specific version

A backup is taken first. Then the new images are downloaded and the stack restarts; the API applies database migrations itself on start. Updates don't touch data, certificates or secrets.

Before updating, keep BACKUP_PASSPHRASE off the server (see below) and make sure the disk has room for one more copy: without the copy the update won't start.

Rolling back an update

sudo rivo rollback                                    # the latest pre-update copy
sudo rivo rollback backups/rivo-20261007-031500.tar.gz.enc   # a specific archive

The new version may have upgraded the database schema, which the previous version doesn't know. So a rollback restores both the version and the data, using the copy taken before the update. Anything entered after that copy is lost. The command asks you to type ROLLBACK (or pass --yes in scripts), and it takes a safety dump of the current database before restoring.

The steps run in this order: the previous version's images are pinned and the API stops. Then the copy is restored and the stack starts on the previous version. The previous version is read from the archive itself.

rivo update --version <previous> over an upgraded database won't work. It refuses without changing the version and suggests rivo rollback. The exception is a version with the same database schema.

If the instance was updated by a version from before October 2026, its pre-update copy has a regular name (rivo-<date>-<time>). Pass it explicitly: it's the last archive before the update time.

When updates have expired

A Self-host license is perpetual, while updates are paid for a term: 12 months from purchase, then renewable by the year. A version built after your updates end won't install — the command stops with an "updates have ended" error and a link to renew.

Nothing breaks: the installed version keeps working without limits, and versions built before the end date still install with --version. To get newer ones, renew updates in your customer account, then Settings → License → check now (otherwise the instance re-checks the license within a day) and run rivo update again. Subscriptions (Cloud, Managed VPS) have no such limit.

Backups

rivo backup                  # back up now → backups/rivo-<date>-<time>.tar.gz.enc
rivo backup --to /mnt/usb    # one-off copy to another directory
sudo rivo backup --schedule  # daily at 03:30 (the installer enables this too)

The archive holds the database dump, uploaded files (already encrypted), deploy/.env with the instance keys and service markers. It is encrypted with the BACKUP_PASSPHRASE key.

Take BACKUP_PASSPHRASE off the server — into a password manager, for example. The installer prints it at the end; it is also in /opt/rivo/deploy/.env. With it an archive restores on any new server together with the encryption keys. Without it nothing can open the archive.

Settings live in deploy/.env:

  • BACKUP_DIR — where archives go;
  • BACKUP_KEEP_DAILY=7, BACKUP_KEEP_WEEKLY=4 — rotation: one copy per day for the last 7 days and one per week for the 4 weeks before;
  • S3_BUCKET, S3_ENDPOINT, S3_REGION, S3_PREFIX, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY — when filled in, the archive is also uploaded to S3-compatible storage (needs awscli or mc). Retention there is set by the bucket policy.

Check the schedule with systemctl list-timers rivo-backup.timer, errors with journalctl -u rivo-backup.service -n 50. No timer — run sudo rivo backup --schedule.

Restoring

sudo rivo restore --latest
sudo rivo restore backups/rivo-20261006-033000.tar.gz.enc

Until every check passes, the database is untouched:

  1. The archive is decrypted and checked for integrity.
  2. The archive's encryption keys are compared with the instance's: passwords and files restored under different keys could never be decrypted, so it refuses.
  3. The schema version is compared: an archive older than the software restores (the API applies missing migrations itself), a newer one is refused — run rivo update first.
  4. You confirm by typing the word the command shows — the Russian for "RESTORE", copy it from the prompt (--yes for scripts).
  5. A safety dump of the current database is taken, the database is loaded in one transaction, previous files are set aside, and the stack comes back up.

Moving to a new server

  1. Install Rivo on the new server — Installing on your own server.
  2. Put the archive into /opt/rivo/backups/ (from a USB stick or S3).
  3. Run it with the explicit archive path:
sudo rivo restore backups/<archive from the old server> --with-keys

--with-keys takes the old instance's keys (APP_SECRET, VAULT_KEY, BACKUP_PASSPHRASE) from the archive. The command asks for the old BACKUP_PASSPHRASE — the new installation has its own, which doesn't fit the old archive.