# Backups & restore

> Protect System and company Vaults, restore a complete installation, and preserve off-host recovery points.

_Updated: 2026-09-22_

New installations use a System Vault and an independently encrypted Vault for
each company. Their recovery point is one encrypted `.vault` **bundle** containing
System, every physical company Vault (including suspended companies), local
attachments, local audit archives and installation identity material. The
manifest pins the inventory and hashes. A copy of `system.vault` alone is not a
complete recovery point and is rejected as a replacement for this bundle.

The System workspace is the normal capture surface. In-process capture fences
company provisioning and writes while it takes a consistent copy; plan capacity
and a suitable window for large installations. Ordinary company writes otherwise
use independent Vault queues. The offline operator command is also available.

An existing installation that has not yet completed
[company migration](/en/learn/company-vault-migration) still uses the legacy single-file
snapshot. Its attachments and secrets must be copied separately as described
below. Updating the executable alone does not migrate existing data.

## Take a snapshot

```bash
./railbase operator backup
```

The offline `operator backup` command takes the vault file lock,
so **stop the server first** (or take the snapshot from the system workspace, which
runs in-process). This writes a copy to `<data-dir>/backups/backup-<UTC>.vault`
(or `RAILBASE_BACKUPS_DIR` if set). Choose your own path with `--out`:

```bash
./railbase operator backup --out /backups/railbase-2026-06-04.vault
```

List local snapshots (newest first). This lists both the `.vault` snapshots
`railbase operator backup` writes and the scheduled job's `backup-<UTC>.tar.gz` archives,
and honors `RAILBASE_BACKUPS_DIR` (so archives on an off-host mount show up too):

```bash
./railbase operator backup list
./railbase operator backup list --dir /backups
```

> [!IMPORTANT]
> Keep the original Vault unlock material separately in the protected recovery
> store. Even when an encrypted bundle contains installation keys, it cannot be
> opened without its external unlock material. A whole-installation bundle
> contains other companies' records and must never be handed to one customer.

Company bundles include `.secret`, node/audit identity files and a local
`.vault_password` when present. External configuration and externally stored
passwords are not captured automatically. Off-host audit archives follow their
own retention and recovery policy. For **legacy single-file snapshots**, preserve
all of the following separately:
>
> - the **vault password** that decrypts the file (Argon2id unlock material,
>   from `RAILBASE_VAULT_PASSWORD`, `RAILBASE_VAULT_PASSWORD_FILE`, or
>   `<data-dir>/.vault_password`). Without it the `.vault` copy can't be
>   opened at all.
> - `railbase-data/.secret`, the 32-byte master key Railbase uses to hash session
>   tokens, sign cookies, seal the audit chain, and derive the **field-level
>   encryption KEK**. A snapshot restored without the matching `.secret` opens,
>   but every existing session/token is invalidated **and any field-encrypted
>   values (and, with `RAILBASE_ENCRYPT_STORAGE`, encrypted file blobs) become
>   permanently undecryptable** — real data loss, not just re-login. Back it up.
> - the **storage directory** (`<data-dir>/storage` by default, or
>   `RAILBASE_STORAGE_DIR`) if you use `File()` / `Files()` fields. The Vault
>   stores file metadata; the blob bytes live in the storage directory.

## Restore

Restore publishes the data from a verified recovery point:

```bash
./railbase operator backup --restore /backups/railbase-2026-06-04.vault
```

There is no separate `restore` command — restore is the `--restore` flag on
`backup`. Stop the server first: restore needs the vault file lock, so it won't
overwrite a path a running instance still holds open. Use the installation's
original data-directory and Vault unlock configuration.

For a company bundle, restoration checks inventory, hashes, company identities
and keys, prepares a new generation, then atomically switches
`vault-layout.json`. It preserves the previous generation. It can recover a
missing System Vault or damaged layout pointer without starting HTTP, jobs or
Federation. A different node's identity requires a fresh data directory;
restoration does not silently replace an existing installation's identity.

The **System → Settings → Backups** screen lists, creates, and deletes snapshots.
Use the offline CLI recovery path above while the server is stopped.
Products-driven rollback uses the same snapshot discipline to recover from a
failed Product installation or update.

> [!CAUTION]
> Restoring makes the recovery point authoritative: later business changes will
> not be present in the restored generation. Preserve a current recovery point
> before switching. Do not run the former and restored writers simultaneously.

After restoration, verify audit integrity, company membership, one employee
workflow, document contents and Product state before opening traffic. Managed
Cloud also requires current control-plane permits; historical permits are never
restored as live authority. Reapply current deletion and revocation decisions.

## Snapshot before risky operations

Make a habit of snapshotting before anything irreversible:

- a **core self-update** (so you can roll back across a bad upgrade),
- a Product data **purge** (which permanently deletes its stored records — the
  console takes its own backup first, but a manual one is cheap insurance),
- bulk data imports or migrations.

The console's **Backup** action takes an on-demand snapshot for exactly these
moments. See [Installation](/en/learn/installation) and [Updating](/en/learn/updating).

## Scheduled backups

Automatic backups are **off by default**. In **System → Security & storage**,
turn on **Automatic backups** (`backups.enabled`), approve the requested
settings change in Operations, and restart Railbase. An installation
without a stored setting may instead use `RAILBASE_BACKUPS_ENABLED=true` in its
service environment. The stored setting takes precedence over the environment.

After activation, Railbase creates a daily 02:30 UTC `scheduled_backup` recovery
point and runs backup retention. Destination and retention are governed settings;
there is no customer-facing raw cron editor. The scheduled job writes the
installation's recovery format with a legacy `.tar.gz` filename (it is not
gzip-compressed): a complete encrypted bundle for the company layout, or an
encrypted single-file snapshot for the legacy layout.
It defaults to `<data-dir>/backups` and honors `RAILBASE_BACKUPS_DIR` (a
per-schedule output directory overrides both). The default retention is 30 days.

With automatic backups off, Railbase does not seed either backup schedule or
run existing scheduled-backup/pruning jobs from older versions. Existing files
and historical jobs remain intact. Set the option to false and restart to stop
a previously enabled schedule. A snapshot already running may finish before
shutdown; changing the setting alone does not interrupt it. Manual backup
requests and update safety snapshots remain available through their existing
paths. Managed Cloud's separately operated external recovery service has its
own explicit policy.

Pair it with off-box copies:

```bash
# e.g. a nightly rsync of the backups dir to object storage / another host
rsync -a /var/lib/railbase/backups/ backup-host:/railbase/
```

> [!TIP]
> Keep at least one copy **off the box**. A snapshot that lives only on the same
> disk as the original doesn't protect you from losing that disk.
