How do I backup and restore the Dédalo data?
See also: Backup best practices · Management and maintenance
Dédalo manages two databases. The main one is the work system, which holds the full dataset with the ontology and all the data. The second is the publishing system, a copy that holds only the public data. To create a backup, you must back up both systems.
The work-system (PostgreSQL) backup below is TS-native: src/core/area_maintenance/backup.ts
spawns the server's own pg_dump (version-matched against the running
PostgreSQL server, probing versioned Homebrew installs) into ../private/backups/db,
behind the "Make Backup" maintenance panel (make_backup widget in
src/core/area_maintenance/widgets/make_backup.ts). The publishing-system
(MariaDB/MySQL) backup is out of scope by design: MariaDB is the diffusion
engine's responsibility, not the work server's, so the panel's MySQL file list
is always empty. Use the manual mysqldump steps below for the publishing
system.
Recreating a publication database with work data
Publishing system is a copy and is possible recreate it doing a publication in work system. But some times will be necessary a copy because the work system is not ready to publish his data.
Backup the work system
Work system use PostgreSQL database, doing a backup of this database you will create the full copy of your data.
You can perform a backup in different ways:
Automatic backup
You can change the backup configuration — directory, cadence and other parameters — by editing Dédalo's backup settings in ../private/.env.
Gap: no automatic trigger on save
initBackupSequence() (src/core/area_maintenance/backup.ts) implements
the throttle window (an 8-hour minimum between non-forced dumps, per
DEDALO_BACKUP_TIME_RANGE) and a stable file-naming scheme, but nothing in
the save/write path calls it automatically yet — it only runs when the
"Make backup" button (or its API action) is invoked. Until this is wired
in, treat backups as manual/cron only (see below).
Manual backup
But in some times you will need do a backup manually to fix a specific point. It can be useful to update major version or change the server.
To create a full copy of Dédalo work system manually, follow this:
- Login as global administrator or root account
-
Enter into Maintenance panel:
System administration -> Maintenance
-
Locate the "Make Backup" panel
- Press the "Make backup" button.
- Wait to be finished.
The panel will indicate the directory of the copy, it will be storage into bk directory in the server and it will be named with the date, name of the database, as:
2023-09-09_205044.my_dedalo_db.postgresql_1_forced_dbv6-0-0.backup
The file lands in ../private/backups/db (getBackupDir() in
src/core/area_maintenance/backup.ts), and the name carries a .custom.
infix before the extension (custom pg_dump -F c format, e.g.
2026-07-04_205044.my_dedalo_db.postgresql_-1_forced_dbv7-0-0.custom.backup)
— otherwise the naming follows <date>.<db>.postgresql_<user>[_forced]_dbv<version>.
The user-id segment is always -1 (superuser), since the maintenance panel is
a global-admin/root-only surface.
Making a manual backup in the server shell
If you want create a backup using the server shell, you can easily backup full Dédalo data using the following command.
pg_dump -h /tmp -p 5432 -U "dedalo_database_user" -F c -b dedalo_database_name > "../dedalo_backup_database.backup"
You can see pg_dump official documentation here.
Restore a backup for the work system
A restore is a procedure the engine owns. Do not run pg_restore by hand
against a live database: pg_restore continues past errors by default, so a
run whose copy of one table failed leaves that table's OLD rows beside restored
neighbours, and nothing you can see distinguishes it from a successful restore.
The engine's restore door does the whole procedure in the right order, refuses
at the first thing that is wrong, and leaves your database exactly as it was
whenever it refuses.
You need shell access to the server with administration privileges, and the
database role Dédalo connects with needs the CREATEDB privilege (the door
builds the restored database beside the current one and swaps them by name):
ALTER ROLE dedalo_database_user CREATEDB;
-
Stop the engine, and the watchdog timer that would restart it:
systemctl stop dedalo-ts.service dedalo-ts-watchdog.timerThe door refuses while anything is still connected to the database — it tells you which connection, by process id.
-
Run the door with the backup file:
cd /opt/dedalo/master_dedalo bun scripts/restore.ts /opt/dedalo/private/backups/db/2026-08-29_033000.my_dedalo_db.custom.backupWhat it does, in order: it reads the WHOLE file to prove it is a complete dump (a file cut short by a failed backup passes every cheaper check); checks that nothing is connected; restores into a new, empty database in one transaction that either lands completely or not at all; renames your current database to
<name>_pre_restore_<stamp>and the restored one to<name>; runs the reconcile checks a restore needs (the media counters are repaired, the rest are reported); writes a report to<backups>/restores/<stamp>.json; and switches maintenance mode on so an engine started early lets only superusers in.Exit status
0means restored with nothing left to decide;2means restored, and the report lists checks HELD for your decision (thereconcilepanel in the maintenance area, orbun scripts/reconcile.ts);1means it refused or failed — and your database is untouched. -
Restore the media files from a backup generation older than the problem (see below), rebuild the derivatives with the update cache tool, and start the engine again. Switch maintenance mode off from the maintenance area once you have read the report.
-
When the restored system is accepted, drop the previous copy — it is a full second database on the same disk:
DROP DATABASE my_dedalo_db_pre_restore_20260829_033000;(or pass
--drop-previousto the door to skip keeping it).
To restore into a database with a different name — for a rehearsal, or a fresh
server — pass --database other_name; when that database does not exist yet
the door simply creates it, and nothing is renamed. This is a REHEARSAL, and
the door treats it as one: it verifies, restores and swaps, but it does not
run the reconcile checks and does not switch maintenance mode on — both belong
to the database in your .env, the one the running engine serves, so a
rehearsal is safe while the engine is up. Its verdict is the record count in
other_name, which you read yourself; drop that database when you are done.
Rehearse a restore quarterly this way: a backup that has never been restored
is a hypothesis.
Backup of media files
Media files are the most large data to be backup, usually it will be a large list of image, audiovisual, pdf, and other documents. If your Dédalo project has large audiovisual files, or thousands or millions image files, you will expect a server with large storage (TBs instead GBs) and your backup storage need to be set to retain almost 3 copies of the media files.
The nightly backup job the engine ships (deploy/dedalo-backup.service, or the
backup service of the compose stacks) already copies the media originals as
dated generations: each night's copy is a directory named by its timestamp in
which unchanged files are hard links into the previous night's, so fourteen
generations cost little more disk than one, and a file deleted by mistake is
still in every generation older than the mistake. The number kept is the
--keep value of the job. To restore, copy the generation you want back over
the media directory — never the newest one if the newest one already contains
the mistake.
If you write your own script instead, keep the same rule: never a single
mirror that deletes on the destination what was deleted at the source (rsync
--delete into one directory is ONE copy, and it follows the mistake). Use
dated rsync --link-dest generations, or filesystem snapshots.
Creating an incremental script for media files
You can use rsync with a cron or other backup solution to create a incremental script.
rsync -avzui --human-readable --links --progress --log-file="../my_backup_scrip_log$(date +%Y%m%d%H%M%S).log" -e "ssh -p 33333" "../dedalo/media" my_user@my_backup_sever.dedalo.dev:/backup/my_host/daily
ssh access to backup host
If you want to run the script automatically, maybe you will need to create a ssh keys access to backup system to log it directly without password. You can set it following this instructions or this.
And you can create a con job to execute it as:
00 01 * * * ../dd_backup_rsync/my_backup_daily.sh
You can read about rsync here
You can add more scripts to create a weekly or monthly backups in the same way.
Backup the publishing system
The publishing system uses the MariaDB/MySQL database. By backing up this database, you will create a copy of the data that was published, a copy of the public data.
Gap: no publishing-system backup button
MariaDB is the diffusion engine's database, not the work server's —
the maintenance panel's get_dedalo_backup_files action always reports an
empty mysql_backup_files list, and there is no "Make a publishing backup"
action registered (make_backup in
src/core/area_maintenance/widgets/make_backup.ts only implements
make_psql_backup/get_dedalo_backup_files). Use the manual mysqldump
steps below.
Manual backup
To create a full copy of Dédalo publishing system manually, follow this:
- Login as global administrator or root account
-
Enter into Maintenance panel:
System administration -> Maintenance
-
Locate the "Make Backup" panel
- Press the "Make a publishing backup" button.
- Wait to be finished.
The panel will indicate the directory of the copy, it will be storage into bk directory in the server and it will be named with the date, name of the database, as:
2023-09-09_205044.mysql_dump_my_publishing_database.sql
Making a manual backup in the server shell
The simplest way to make a full copy of the MariaDB/MySQL database is to run the mysqldump command with this set of parameters:
mysqldump -u publishing_bd_user_name -p -v my_publishing_database > mysql_dump_my_publishing_database.sql
Using MariaDB
If you are using a MariaBD > 11.0, you will need to use mariadb-dump instead mysqldump
Optional: if you want to compress the backup:
tar zcf mysql_dump_my_publishing_database-$(date +%Y-%m-%d-%H.%M.%S).sql.tar.gz mysql_dump_my_publishing_database.sql
Restore a backup of publishing system
You can use Adminer or other database tools to import the file that you previously created, or restore the DB backup by running the following command:
mysql -u publishing_bd_user_name -p -v mysql_dump_my_publishing_database < mysql_dump_my_publishing_database.sql
Backup a Dédalo config files
Config files store your environment, database configuration access, API access and other important information. Backup the config files ensure you that this information will be preserved in case of server failure, and it that could be necessary to restore a backup because the password encryption system need a keys stored into the config files.
The most important situations will happen in case you lose the configuration files could be:
- you can loose the access to the database user, and will need use a pw reset in postgreSQL or MariaDB
- you will need to rebuild all Dédalo passwords
Both situations are reversible but are not simple processes.
Configuration files do not change every day and usually only change when new features are required or some changes are set into the work system, so it's not mandatory to create a daily backup, but it's high recommendable create a script to automate the backup process. We recommended a monthly backup of the config files.
For transfer the files to the backup server consider compress the files in this way:
tar cvfz dedalo_configuration.tar.gz ../dedalo/config
Dédalo keeps its per-install configuration and secrets outside the code tree
entirely, in ../private/ (a sibling of the install tree — see the
check_config widget's computeCheckConfig, in
src/core/area_maintenance/widgets/check_config.ts, which reports these exact
sources): .env (credentials/config), ts_state.json (maintenance mode,
recovery mode, notification and menu overrides) and the sessions database.
Back these up together, e.g. tar cvfz dedalo_configuration.tar.gz ../private.