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 | |
|---|---|
| Who | Root (or sudo) on the Lawliet server |
| Console role | None. Backups are taken and restored on the server only |
| Four-eyes | Not 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:
| File | Contents | Why it matters |
|---|---|---|
lawliet-<time>.sql.gz | The PostgreSQL database: users, roles, agents, findings, compliance history, evidence bundles, audit trail, settings | Everything the console shows, except collected log events |
lawliet-<time>.keys | SECRET_KEY and DATA_ENCRYPTION_KEY | Two-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.gz | Agent releases hosted on this server | Without it, a restored server lists agent releases it cannot serve |
Not in a backup (keep these some other way):
| Item | Where it lives | What to do |
|---|---|---|
| Collected log events (the Logs search) | ClickHouse, Docker volume clickhouse_data | They 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 |
.env | Installation directory | Copy it off the server, encrypted and access-controlled. It holds every secret and the licence key |
.lawliet.conf | Installation directory | Copy it with .env |
| The certificate and key | infra/docker/ssl/ | Copy them with .env. Agents trust this exact certificate |
| The installation fingerprint | Docker volume lawliet_config | Cannot be moved to another server. A new server needs a new licence |
| Offline agent packages | Never backed up on purpose | They 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:
| Setting | Default | Meaning |
|---|---|---|
BACKUP_INTERVAL_SECONDS | 86400 | Time between dumps |
BACKUP_KEEP | 7 | Dumps 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.
In the installation directory:
sudo ./lawliet backupOr into another directory:
sudo ./lawliet backup /mnt/backup-share.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#
| Message | Cause 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 discarded | The 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 name | This 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#
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>&1Copy
backups/to another system after each run, with the tool your site uses (rsync,scp, a backup agent). Keep the.keysfiles apart from the dumps, for example in a different, encrypted location: a dump and its keys together open every stored secret.Copy
.env,.lawliet.confandinfra/docker/ssl/off the server whenever they change (after install, licence installation, certificate changes,token --rotate).Remove old dumps from
backups/on your own schedule../lawliet backupnever 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.
| Risk | Everything written after the dump is lost: findings, events, agent enrolments, users, settings. Agents enrolled after the dump must be reinstalled |
| Rollback | Take a backup immediately before restoring (step 1). To undo, restore that backup |
| Downtime | A few minutes |
Procedure#
Take a backup of the current state:
sudo ./lawliet backupPut the dump's
.keysand.agent-artifacts.tar.gzfiles beside the dump, with the same name stem, if you copied them elsewhere.Restore:
sudo ./lawliet restore backups/lawliet-20261014-020000.sql.gzAnswer Continue? (y/N) with
y.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 keysandRecreating the application with the restored keys, and finallyRestored the hosted agent artefacts.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#
| Message | Meaning 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 error | The 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/.
| Risk | Data written after the dump is lost. The new server is a new installation: its fingerprint differs, so the licence must be reissued |
| Rollback | The old server, if it still exists, is unchanged by this procedure |
Procedure#
Prepare the new server as in Installation 2.1 and 2.2: same CPU type, Docker, NTP.
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.
Unpack the same bundle version the dump was taken with (see Installation 2.4). Do not run
install.Copy into the installation directory:
.env(thenchmod 600 .env),.lawliet.conf, andinfra/docker/ssl/fullchain.pemandprivkey.pem(thenchmod 600 infra/docker/ssl/privkey.pem).Start the platform. This loads the images and creates an empty database:
sudo ./lawliet startRestore the dump (with its
.keysand artefacts beside it):sudo ./lawliet restore /path/to/lawliet-<time>.sql.gzShow the new installation fingerprint and request a licence for it:
sudo ./lawliet licenceInstall the new key when it arrives:
sudo ./lawliet licence <key-file>.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:
- 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. - Run
sudo ./lawliet statusthere. The Estate counts (agents, compliance scans, findings) must match the source server at the time of the dump. - Sign in with a real account and its two-factor code. A successful sign-in proves the
.keysfile matches. The test server has its own fingerprint, so the console then shows the activation screen; that is expected. - Remove the test deployment with
./lawliet uninstallin its directory.
The test server makes no outbound connections. Keep it off the agents' network so agents do not connect to it.

