Lawliet LAWLIET
Book a demo

5. Backup and restore

This guide describes Lawliet 1.5.13.s (the current release). Screens, commands and procedures may change in later versions; the usage guide is updated with each release. Check the version your server runs under Settings > Platform or with ./lawliet version, and see the Releases page for what changed.

What to back up, how often, where to keep it, and how to get it back - on the same server or on a new one.

You need
WhoRoot (or sudo) on the Lawliet server
Console roleNone. Backups are taken and restored on the server only
Four-eyesNot applicable (the CLI is root on the server)

5.1 What is in a backup, and what is not#

sudo ./lawliet backup writes three files:

FileContentsWhy it matters
lawliet-<time>.sql.gzThe PostgreSQL database: users, roles, agents, findings, compliance history, evidence bundles, audit trail, settingsEverything the console shows, except collected log events
lawliet-<time>.keysSECRET_KEY and DATA_ENCRYPTION_KEYTwo-factor secrets, stored firewall/SIEM/deployment credentials and held approvals are encrypted with these. A dump restored without them loads, but every two-factor sign-in and stored credential then fails
lawliet-<time>.agent-artifacts.tar.gzAgent releases hosted on this serverWithout it, a restored server lists agent releases it cannot serve

Not in a backup (keep these some other way):

ItemWhere it livesWhat to do
Collected log events (the Logs search)ClickHouse, Docker volume clickhouse_dataThey age out by RETENTION_LOG_EVENT_DAYS (90 days by default). If you must keep them through a server loss, include Docker's volume storage in your host-level backup, taken while the platform is stopped
.envInstallation directoryCopy it off the server, encrypted and access-controlled. It holds every secret and the licence key
.lawliet.confInstallation directoryCopy it with .env
The certificate and keyinfra/docker/ssl/Copy them with .env. Agents trust this exact certificate
The installation fingerprintDocker volume lawliet_configCannot be moved to another server. A new server needs a new licence
Offline agent packagesNever backed up on purposeThey hold enrolment codes that expire

The automatic daily backup (HTTPS mode)#

In HTTPS mode a db-backup container dumps the database once a day into ./backups (lawliet_<YYYYmmdd_HHMMSS>.sql.gz) and keeps the newest 7. It waits for the database schema before its first dump and discards a dump with no tables. Settings in .env:

SettingDefaultMeaning
BACKUP_INTERVAL_SECONDS86400Time between dumps
BACKUP_KEEP7Dumps kept

These daily dumps do not include the .keys file or the agent artefacts. Take a full ./lawliet backup at least weekly and before every change.

./lawliet doctor warns when the newest backup in ./backups is more than 7 days old.

./backups is on the same disk as the database. A backup that shares a fate with its database is not a backup. Copy it off the server (5.3).


5.2 Take a backup now#

Before every update, certificate change, licence change or restore.

  1. In the installation directory:

    sudo ./lawliet backup

    Or into another directory: sudo ./lawliet backup /mnt/backup-share.

  2. What you see:

    > Backing up the database
      OK Wrote ./backups/lawliet-20261014-020000.sql.gz (48M, 212 tables)
      OK Wrote ./backups/lawliet-20261014-020000.keys (the keys the data is encrypted with)
      ! Keep the .keys file apart from the dump: together they open every stored secret.
      OK Wrote ./backups/lawliet-20261014-020000.agent-artifacts.tar.gz (hosted agent upgrade artefacts)
      Restore with: ./lawliet restore ./backups/lawliet-20261014-020000.sql.gz

The platform keeps running during the backup.

If it fails#

MessageCause and fix
pg_dump failed. Is PostgreSQL running?Start the platform (sudo ./lawliet start), check sudo ./lawliet status
The dump contained no tables and was discardedThe database is empty or not reachable. Check sudo ./lawliet logs postgres
Cannot write to <dir>The directory does not exist or is not writable
Could not archive the hosted agent artefacts (is the backend running?)A warning: the dump and keys were written. Start the backend and back up again if you host agent releases
A message that another Lawliet deployment is running under a different project nameThis CLI is looking at the wrong project. Use the project name the message gives (COMPOSE_PROJECT_NAME=...)

5.3 Schedule backups and copy them off the server#

  1. Create a scheduled job on the server, for example /etc/cron.d/lawliet-backup:

    30 2 * * * root cd /opt/lawliet-<version> && ./lawliet backup >>/var/log/lawliet-backup.log 2>&1
  2. Copy backups/ to another system after each run, with the tool your site uses (rsync, scp, a backup agent). Keep the .keys files apart from the dumps, for example in a different, encrypted location: a dump and its keys together open every stored secret.

  3. Copy .env, .lawliet.conf and infra/docker/ssl/ off the server whenever they change (after install, licence installation, certificate changes, token --rotate).

  4. Remove old dumps from backups/ on your own schedule. ./lawliet backup never deletes anything.

After every update, change the directory in the scheduled job to the new installation directory. The old directory's ./lawliet would back up nothing useful once it is stopped.


5.4 Restore the database#

Replaces the whole database of this installation with a dump.

RiskEverything written after the dump is lost: findings, events, agent enrolments, users, settings. Agents enrolled after the dump must be reinstalled
RollbackTake a backup immediately before restoring (step 1). To undo, restore that backup
DowntimeA few minutes

Procedure#

  1. Take a backup of the current state:

    sudo ./lawliet backup
  2. Put the dump's .keys and .agent-artifacts.tar.gz files beside the dump, with the same name stem, if you copied them elsewhere.

  3. Restore:

    sudo ./lawliet restore backups/lawliet-20261014-020000.sql.gz
  4. Answer Continue? (y/N) with y.

  5. What you see: Stopping the application while the database is replaced, Emptying the current schema and loading <dump>, OK Restored from <dump> (<N> tables), then either the restart, or (when the keys differ) Adopted the dump's encryption keys and Recreating the application with the restored keys, and finally Restored the hosted agent artefacts.

  6. Check: sudo ./lawliet status, then sign in to the console.

Use a dump from the same version you are running. A dump from an older version is migrated forward when the backend starts. A dump from a newer version cannot be used by an older one.

A daily dump from the backup service (lawliet_<time>.sql.gz) has no .keys file. On the same installation that is fine: the keys have not changed. The warning No <file>.keys beside the dump can then be ignored.

If it fails#

MessageMeaning and fix
Usage: ./lawliet restore <dump.sql.gz>The file does not exist or is empty
Could not reset the schema. Nothing was loaded.Nothing changed. Check sudo ./lawliet logs postgres
The dump failed to load. The database is now EMPTY.The dump is damaged. Restore the backup you took in step 1 at once
The dump loaded but created no tables.The file is not a Lawliet dump. Restore the backup from step 1
After a restore on another installation, two-factor sign-in fails with an errorThe keys are missing. Put the .keys file beside the dump and restore again, or set SECRET_KEY and DATA_ENCRYPTION_KEY in .env to the values of the installation that made the dump, then sudo ./lawliet start

5.5 Restore onto a new server#

For a lost or replaced server. You need, from your off-server copies: a dump with its .keys and .agent-artifacts.tar.gz files, .env, .lawliet.conf, and infra/docker/ssl/.

RiskData written after the dump is lost. The new server is a new installation: its fingerprint differs, so the licence must be reissued
RollbackThe old server, if it still exists, is unchanged by this procedure

Procedure#

  1. Prepare the new server as in Installation 2.1 and 2.2: same CPU type, Docker, NTP.

  2. Give it the same address (IP address or DNS name) as the old server. Agents connect to that address and trust that certificate; with both unchanged they reconnect by themselves.

  3. Unpack the same bundle version the dump was taken with (see Installation 2.4). Do not run install.

  4. Copy into the installation directory: .env (then chmod 600 .env), .lawliet.conf, and infra/docker/ssl/fullchain.pem and privkey.pem (then chmod 600 infra/docker/ssl/privkey.pem).

  5. Start the platform. This loads the images and creates an empty database:

    sudo ./lawliet start
  6. Restore the dump (with its .keys and artefacts beside it):

    sudo ./lawliet restore /path/to/lawliet-<time>.sql.gz
  7. Show the new installation fingerprint and request a licence for it:

    sudo ./lawliet licence

    Install the new key when it arrives: sudo ./lawliet licence <key-file>.

  8. Check sudo ./lawliet status, sign in, and confirm in Environment that agents come back online within a few minutes.

If you do not have .env: run sudo ./lawliet install with the same address instead of steps 4 and 5 (put the old certificate in infra/docker/ssl/ first so the installer keeps it), then restore with the .keys file beside the dump. Agents keep working: each uses its own token, which is in the database. The installer creates a new enrolment secret; new agent installations use the new commands from ./lawliet token.


5.6 Test your backups#

A backup you have never restored is a hope, not a backup. At least twice a year:

  1. On a spare server, or a second deployment on a test host (COMPOSE_PROJECT_NAME=lawliet-restoretest), follow 5.5 with your latest off-server copy.
  2. Run sudo ./lawliet status there. The Estate counts (agents, compliance scans, findings) must match the source server at the time of the dump.
  3. Sign in with a real account and its two-factor code. A successful sign-in proves the .keys file matches. The test server has its own fingerprint, so the console then shows the activation screen; that is expected.
  4. Remove the test deployment with ./lawliet uninstall in its directory.

The test server makes no outbound connections. Keep it off the agents' network so agents do not connect to it.