Backups and upgrades
The control plane is two Postgres databases and one directory of config. Back those up and you can rebuild the server anywhere.
What matters
| Item | Where | Contains |
|---|---|---|
| Config and secrets | /opt/tzxmesh/app | .env, owner.hash, compose file, Caddy and control-plane config |
| Control-plane database | Postgres tzxmesh | devices, keys, groups, policies, routes, activity |
| Identity database | Postgres tzxmesh_idp | local users, password hashes, signing keys, sessions |
| Data volume | server_data | geolocation databases; regenerated if lost |
The encryption key in
.env protects secrets inside the database. A database backup without the .env that goes with it cannot be decrypted.Back up
cd /opt/tzxmesh/app
docker exec tzxmesh-postgres pg_dump -U tzxmesh -d tzxmesh -Fc > tzxmesh.dump
docker exec tzxmesh-postgres pg_dump -U tzxmesh -d tzxmesh_idp -Fc > tzxmesh_idp.dump
tar czf tzxmesh-config.tgz .env owner.hash docker-compose.yml Caddyfile config.yaml
Encrypt the three files before they leave the server, and copy them somewhere the server cannot reach. Run it nightly from cron.
Restore
- Run the installer on the new server with the same domain, then stop the stack:
docker compose down. - Unpack the config archive over
/opt/tzxmesh/app. - Start only Postgres, restore both dumps with
pg_restore --no-ownerinto their databases, thendocker compose up -d. - Point DNS at the new server. Devices reconnect on their own; nothing needs re-enrolling.
Practise it once on a scratch machine. A restore you have never run is not a backup.
Upgrade
cd /opt/tzxmesh/app
docker compose pull
docker compose up -d
Database migrations run automatically on start. To pin a version, edit the image tags in .env before pulling. Rolling back is the same with the previous tag.