Backup and Restore
What to back up on a self-hosted installation, how the update backup works, and the steps to restore onto a new server.
Last reviewed against source:
Signals does not schedule backups for you. Nothing in its scheduled tasks takes a database or file backup, so a self-hosted installation needs its own backup routine. This page covers self-hosted installations.
The only backup Signals takes itself is the pre-update dump described below.
What to back up
| Item | Why |
|---|---|
| PostgreSQL database | All business data lives here: rentals, invoices, accounts, settings, users and the audit trail. Back up every application schema. |
| File storage | Uploaded attachments, generated documents and exports. With local storage these are under storage/app: the local disk is storage/app/private and the public disk is storage/app/public. With S3-compatible storage, back up the bucket. |
.env |
Holds your connection settings, APP_KEY, SIGNALS_INSTALLED, SIGNALS_SETUP_COMPLETE, SIGNALS_SETUP_PROOF and SIGNALS_INSTALLATION_ID. |
APP_KEY |
Encrypted values in the database and update backups are readable only with the original key. Store a copy separately from the database backup. |
SIGNALS_UPDATE_BACKUP_KEY, if you set one |
When set, update backups are encrypted with it instead of APP_KEY. |
| Plugins and custom code | Keep composer.json and composer.lock in version control so the same release can be installed again. |
Everything else, including caches, compiled views and the vendor/ directory, can be rebuilt.
PostgreSQL needs the btree_gist and pg_trgm extensions. If you use AI embeddings it also uses the vector extension. A dump carries the data, so install the same extensions on the restore server first. See Installation.
Back up the database and the files together. Records point to files by path. A database restored without its files, or the reverse, leaves broken links to documents and attachments.
Take a backup
Use your usual PostgreSQL tooling, for example pg_dump -Fc, with the same major version of the client tools as the server. Copy storage/app or snapshot the bucket at the same time. Keep copies on a different machine from the one running Signals, and test a restore regularly into a disposable database.
The update backup
php artisan signals:update takes its own backup before it changes anything. It puts the application into maintenance mode, runs pg_dump -Fc, encrypts the archive into storage/app/update-backups/, and verifies it before installing the new release. Retention defaults to 30 days (SIGNALS_UPDATE_BACKUP_RETENTION_DAYS).
| Command | Purpose |
|---|---|
php artisan signals:update:prune-backups |
Removes expired update backups. --days= overrides retention; --dry-run lists what would go. The live rollback point is kept. |
php artisan signals:update:decrypt-backup {path} --output=FILE |
Decrypts an update backup so pg_restore can read it. --output must be a new file in an existing directory. |
php artisan signals:update:recover --status |
Shows the state of an interrupted update. |
php artisan signals:update:recover --restore |
Restores the recorded backup after a failed update, once the source release is reinstated. |
These commands are unavailable on Signals Cloud. The full recovery procedure is in Updates and Upgrading.
The update backup is a safety net for updates. It is not a replacement for scheduled backups: it holds only the database, and only at the time of the last update.
Restore onto a new server
- Install the same Signals release and PHP extensions on the new server. See Installation. Do not run the setup wizard.
- Restore
.envwith its originalAPP_KEY. Set the database, cache, queue and storage values for the new environment. KeepSIGNALS_INSTALLED=trueandSIGNALS_SETUP_COMPLETE=true. - Create an empty PostgreSQL database with the
btree_gistandpg_trgmextensions, andvectorif the source used it. - Restore the database into it. For a dump you took yourself, use
pg_restoreas you normally would. For an update backup, decrypt it withsignals:update:decrypt-backupfirst, then follow the worked sequence in Updates. - Restore
storage/app, or point the storage settings at the restored bucket. - Clear and rebuild caches, then restart workers:
php artisan optimize:clear,php artisan optimize,php artisan queue:restart. - Run
php artisan signals:statusto check the database, Redis and storage connections. - Restart the scheduler cron entry and the queue workers, as described in Scheduled Tasks. Open Admin → System → System Health and confirm the checks are green.
- If the backup is older than live use, tell your team which changes were lost. Everything entered after the backup is gone.
If the restored installation runs a different release from the backup, run php artisan migrate --force and follow Upgrading.
Privacy requests and restores
If your organisation erased or anonymised accounts after the backup was taken, a restore brings that personal data back. Inspect the recorded restore tombstones with:
php artisan signals:privacy:reapply-tombstones --dry-run
Running it without --dry-run opens draft privacy cases for human verification and approval. It needs the original encryption key. If the key, the tombstone integrity or the acting user fails its check, the command refuses and commits no cases. See Accounts.
If you restore without .env
The setup pages return 404 once any user exists, even if SIGNALS_SETUP_COMPLETE was lost with the old .env. Rebuild .env from your copy rather than running setup again.
signals:reset removes data
Danger.
php artisan signals:resetis not a backup or restore tool. It permanently deletes documents, document sequences, settings, warehouses and users, then setsSIGNALS_SETUP_COMPLETE=false. It does not undo itself and does not guarantee that setup can run again afterwards.
--force is required, and production also needs --allow-production-reset. Run it with --dry-run first to see row counts without changing anything, and take a verified backup before any real run. Details are in Configuration.
Related
| Reference | Use it for |
|---|---|
| Updates | Update backups, recovery and the worked manual restore |
| Upgrading | Preparing and running an upgrade |
| Storage | Where uploaded files are held |
| Configuration | Setup, reset and ownership guards |