{"result":{"depiction_url":null,"edges":{"observes":{"objects":[{"created":"2026-09-09T13:47:41Z","object_id":{"id":1466,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_admin_menu","title":"observe_admin_menu\/3","uri":"https:\/\/zotonic.com\/id\/1466"},"seq":1},{"created":"2026-09-09T13:47:41Z","object_id":{"id":1738,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_media_update_done","title":"observe_media_update_done\/2","uri":"https:\/\/zotonic.com\/id\/1738"},"seq":2},{"created":"2026-09-09T13:47:41Z","object_id":{"id":1981,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_rsc_update_done","title":"observe_rsc_update_done\/2","uri":"https:\/\/zotonic.com\/id\/1981"},"seq":3},{"created":"2026-09-09T13:47:41Z","object_id":{"id":1982,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_search_query","title":"observe_search_query\/2","uri":"https:\/\/zotonic.com\/id\/1982"},"seq":4},{"created":"2026-09-09T13:47:41Z","object_id":{"id":2050,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_rsc_delete","title":"observe_rsc_delete\/2","uri":"https:\/\/zotonic.com\/id\/2050"},"seq":5},{"created":"2026-09-09T13:47:41Z","object_id":{"id":2053,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_rsc_upload","title":"observe_rsc_upload\/2","uri":"https:\/\/zotonic.com\/id\/2053"},"seq":6},{"created":"2026-09-09T13:47:41Z","object_id":{"id":2126,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_edge_delete","title":"observe_edge_delete\/2","uri":"https:\/\/zotonic.com\/id\/2126"},"seq":7},{"created":"2026-09-09T13:47:41Z","object_id":{"id":2158,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_m_config_update","title":"observe_m_config_update\/2","uri":"https:\/\/zotonic.com\/id\/2158"},"seq":8},{"created":"2026-09-09T13:47:41Z","object_id":{"id":2168,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_edge_insert","title":"observe_edge_insert\/2","uri":"https:\/\/zotonic.com\/id\/2168"},"seq":9}],"predicate":{"id":2550,"is_a":["meta","predicate"],"name":"observes","title":{"_type":"trans","tr":{"en":"Observes"}},"uri":"https:\/\/zotonic.com\/id\/observes"}},"references":{"objects":[{"created":"2020-05-30T05:47:24Z","object_id":{"id":1279,"is_a":["text","documentation"],"name":"doc_glossary","title":"Glossary","uri":"https:\/\/zotonic.com\/id\/1279"},"seq":1000000},{"created":"2023-09-27T14:06:27Z","object_id":{"id":1329,"is_a":["text","documentation","reference","module"],"name":"doc_module_mod_filestore","title":"mod_filestore","uri":"https:\/\/zotonic.com\/id\/1329"},"seq":1000000}],"predicate":{"id":332,"is_a":["meta","predicate"],"name":"references","title":{"_type":"trans","tr":{"en":"References"}},"uri":"https:\/\/zotonic.com\/id\/references"}},"refers":{"objects":[{"created":"2026-09-09T13:47:41Z","object_id":{"id":1329,"is_a":["text","documentation","reference","module"],"name":"doc_module_mod_filestore","title":"mod_filestore","uri":"https:\/\/zotonic.com\/id\/1329"},"seq":1000000}],"predicate":{"id":2409,"is_a":["meta","predicate"],"name":"refers","title":{"_type":"trans","tr":{"en":"Refers"}},"uri":"https:\/\/zotonic.com\/id\/refers"}},"subject":{"objects":[{"created":"2026-09-09T13:47:41Z","object_id":{"id":2555,"is_a":["categorization","keyword","keyword_information_type"],"name":"zotonic_topic_reference","title":"Reference","uri":"https:\/\/zotonic.com\/id\/2555"},"seq":1},{"created":"2026-09-09T13:47:41Z","object_id":{"id":2566,"is_a":["categorization","keyword","keyword_audience"],"name":"zotonic_topic_operator","title":"Operator","uri":"https:\/\/zotonic.com\/id\/2566"},"seq":2},{"created":"2026-09-09T13:47:41Z","object_id":{"id":2602,"is_a":["categorization","keyword","keyword_domain"],"name":"zotonic_topic_backup_and_restore","title":"Backup and restore","uri":"https:\/\/zotonic.com\/id\/2602"},"seq":3},{"created":"2026-09-09T13:47:41Z","object_id":{"id":2635,"is_a":["categorization","keyword","keyword_architecture"],"name":"zotonic_topic_module","title":"Module","uri":"https:\/\/zotonic.com\/id\/2635"},"seq":4},{"created":"2026-09-09T13:47:41Z","object_id":{"id":2656,"is_a":["categorization","keyword","keyword_task"],"name":"zotonic_topic_schedule","title":"Schedule","uri":"https:\/\/zotonic.com\/id\/2656"},"seq":5}],"predicate":{"id":308,"is_a":["meta","predicate"],"name":"subject","title":{"_type":"trans","tr":{"en":"Keyword"}},"uri":"http:\/\/purl.org\/dc\/elements\/1.1\/subject"}}},"id":1521,"is_a":["text","documentation","reference","module"],"links":[{"rel":"self","target":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/1521"},{"rel":"hub","target":"https:\/\/zotonic.com\/.zotonic\/websub"}],"medium":null,"medium_url":null,"name":"doc_module_mod_backup","page_url":{"en":"https:\/\/zotonic.com\/docs\/1521\/mod_backup","x-default":"https:\/\/zotonic.com\/docs\/1521\/mod_backup"},"preview_url":null,"resource":{"version":4027,"pivot_location_lat":null,"title":"mod_backup","is_authoritative":true,"body":"<p>mod_backup serves two different purposes: it makes a nightly backup of your files and database, and can also\nbackup\/restore individual <a href=\"\/id\/doc_glossary#term-resource\">resource<\/a> items.<\/p>\n<h2>Daily backup of database and files<\/h2>\n<p>Losing data is bad for business. This applies to your customers as well if you are building sites for them. It is\ncritical to keep backups of any Zotonic sites you develop.<\/p>\n<p>After enabling mod_backup, it will make a backup of the site’s data and configuration every night at 3 AM. It keeps\nthe last 7 daily copies of the data and a weekly backup for the last 4 weeks, so you have always a backup to roll back to.<\/p>\n<p>The backups are stored under <code>backup<\/code> in the files directory of your site. Check in the admin under System &gt; Status to\nsee where the site files directory is located.<\/p>\n<p>The site’s media files are stored as a <code>&lt;site-name&gt;-N.tar.gz<\/code> file. The configuration is named\n<code>config-&lt;site-name&gt;-N.tar.gz<\/code>, while the database is stored compressed in a <code>&lt;site-name&gt;-N.sql.gz<\/code> file. N is the\nday number. Sunday (day 1) is stored as the weekly backup, which rotates over w1..w4.<\/p>\n<p>It is possible to encrypt the backups by enabeling the Encrypt Backups option on the configuration page of the backup\nservice. When you enable this for the first time, a password will be generated automatically. This password should be\nstored in a safe location to be able to decrypt the backups. When encryption is enabled, the files have the <code>.enc<\/code> extension.<\/p>\n<p>The zotonic shell command <code>decrypt<\/code> can be used to decrypt encrypted zotonic backup files.<\/p>\n<p>If <a href=\"\/id\/doc_module_mod_filestore\" class=\"doc-reference doc-reference-module\"><code>module#mod_filestore<\/code><\/a> is enabled then the media files are not backed up, as it is assumed\nthat the files are already backed up on the cloud filestore. The data backups are uploaded to the cloud filestore, so\nthey are also backed up.<\/p>\n<p>If <a href=\"\/id\/doc_module_mod_filestore\" class=\"doc-reference doc-reference-module\"><code>module#mod_filestore<\/code><\/a> is not enabled then we advise to add a\n<a href=\"http:\/\/en.wikipedia.org\/wiki\/Cron\">cron<\/a> script to the server for copying the data to remote storage.<\/p>\n<h2>Per-resource revision log<\/h2>\n<p>If a resource is updated or deleted then a copy of the resource data is saved to a revision log.<\/p>\n<p>Using the revision log a resource can be rolled back to an older revision or, when deleted, recovered.<\/p>\n<p>Edges are added to the revision log, and are replayed in reverse chronological order to recover the connections of a resource.<\/p>\n<p>If a connection is re-instantiated and it is referring to a <em>dependent<\/em> resource that is now deleted, then that\n<em>dependent<\/em> resource will also be recovered.<\/p>\n<p>Medium files are kept for 4 weeks before they are deleted. That means that up to four weeks a medium file can be\nrecovered, and after that it will be lost. Unless the file is still available on the filestore (which has its own\ndeletion interval).<\/p>\n<p>Revisions are pruned daily and deleted if:<\/p>\n<ol><li>older than 18 months; This can be changed by setting the configuration <code>mod_backup.revision_retention_months<\/code> to\nanother number of months.<\/li><li>of user resources and older than 90 days; This can be changed by setting the configuration\n<code>mod_backup.user_revision_retention_days<\/code> to another number of days.<\/li><li>of users resources and the users was deleted for at least 30 days; This can be changed by setting the configuration\n<code>mod_backup.user_deletion_retention_days<\/code> to another number of days (maximum 30).<\/li><\/ol>\n<h2>Replication and failover<\/h2>\n<p>It is possible to replicate data from one server to another server. The receiving server must have the site running with\nits environment set to <code>backup<\/code>.<\/p>\n<p>If a site’s environment is set to <code>backup<\/code> then the site will start in a special mode. In backup mode only essential\nmodules, <code>mod_filestore<\/code> and <code>mod_backup<\/code> are started.<\/p>\n<p>If there is a working filestore configuration then the backup module will start polling for new backups uploaded to the\nfilestore. Any newly found backups are downloaded to the local file system. After all backup files are downloaded, then\nfor the newest backup:<\/p>\n<ul><li>the database backup will be imported; and<\/li><li>the configuration files in the <code>priv\/<\/code> and <code>priv\/config.d\/<\/code> overwritten with the config files from the backup; and<\/li><li>certificates and secrets are written to the site’s security directory; and<\/li><li>any files backup tar will be unpacked in the local files directory; and finally<\/li><li>a file <code>priv\/BACKUP<\/code> will be written.<\/li><\/ul>\n<p>After this the site will restart.<\/p>\n<p>Because the file <code>priv\/BACKUP<\/code> is present the environment of the site will be forced to <code>backup<\/code> and the site will start\nchecking again for a new backup.<\/p>\n<p>If a failover is needed, then:<\/p>\n<ol><li>change the DNS to point to the new server; and<\/li><li>remove the <code>priv\/BACKUP<\/code> file; and<\/li><li>restart the site to start the site normally.<\/li><\/ol>\n<h2>Command-line backups<\/h2>\n<p>Run these commands from the Zotonic installation directory. The <code>backup<\/code> commands connect to a running\nZotonic node and require <code>mod_backup<\/code> to be enabled for the named site. Replace <code>mysite<\/code> with the site name.<\/p>\n<table class=\"table\"><thead><tr><th>Command<\/th><th>Description<\/th><\/tr><\/thead><tbody><tr><td><code>bin\/zotonic backup mysite list<\/code><\/td><td>List available backups and their names and file metadata.<\/td><\/tr><tr><td><code>bin\/zotonic backup mysite start<\/code><\/td><td>Start a backup in the background using the site&#39;s backup configuration. Reports an error if a backup is already running.<\/td><\/tr><tr><td><code>bin\/zotonic backup mysite restore BACKUP_NAME<\/code><\/td><td>Restore the backup identified by a name from <code>list<\/code>.<\/td><\/tr><tr><td><code>bin\/zotonic backup mysite restore recent<\/code><\/td><td>Restore the most recent available backup.<\/td><\/tr><tr><td><code>bin\/zotonic backup mysite download<\/code><\/td><td>Download and restore the newest backup from the configured filestore. Requires the site&#39;s environment to be <code>backup<\/code>.<\/td><\/tr><\/tbody><\/table>\n<p>Both <code>restore<\/code> and <code>download<\/code> ask you to type the site name to confirm. The site is unavailable during\nrestoration and restarts afterwards. The <code>download<\/code> command starts the download and restoration in the\nbackground; its return does not mean that restoration has finished.<\/p>\n<p>The <code>restore<\/code> command also asks which configuration and security files to restore. Database and media\nfiles are always selected. Press Enter or type <code>N<\/code> to keep the current configuration and security files,\n<code>c<\/code> to restore configuration, <code>s<\/code> to restore certificates and other security files, or <code>a<\/code> to restore both.\nThe <code>download<\/code> command follows the replication and failover workflow described above.<\/p>\n<p>Encrypted backup files can be decrypted separately:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-sh\">bin\/zotonic decrypt PASSWORD BACKUP_FILE.enc\nbin\/zotonic decrypt PASSWORD BACKUP_FILE.enc OUTPUT_FILE\n<\/code><\/pre>\n<p>The password is the backup encryption password (<code>mod_backup.backup_encrypt_password<\/code>). If no output\nfilename is given, the command removes the <code>.enc<\/code> suffix to determine the output filename. Decryption\noperates on local files and does not require a running site. It decrypts the file; it does not restore\nthe database or unpack the archive.<\/p>\n<h2>Accepted Events<\/h2>\n<p>This module handles the following notifier callbacks:<\/p>\n<ul><li><code>observe_admin_menu<\/code>: Add backup and restore entries to the admin menu.<\/li><li><code>observe_backup_download<\/code>: Validate and stream a requested backup archive from the backup directory.<\/li><li><code>observe_backup_list<\/code>: List available backup archives from the configured backup directory.<\/li><li><code>observe_backup_restore<\/code>: Restore a selected backup archive after path and permission validation.<\/li><li><code>observe_backup_start<\/code>: Start creation of a new backup archive in the backup directory.<\/li><li><code>observe_edge_delete<\/code>: Record edge removals as backup revisions for changed resources.<\/li><li><code>observe_edge_insert<\/code>: Record edge insertions as backup revisions for changed resources.<\/li><li><code>observe_m_config_update<\/code>: Toggle revision backup behavior immediately when backup config flags change.<\/li><li><code>observe_media_update_done<\/code>: Store a backup revision when media metadata or file references are updated.<\/li><li><code>observe_rsc_delete<\/code>: Preserve media and complete resource revisions, including URI aliases and deleted-page metadata, before resource deletion.<\/li><li><code>observe_rsc_update_done<\/code>: Save a resource revision snapshot after successful updates.<\/li><li><code>observe_rsc_upload<\/code>: Include uploaded files in backup revision tracking and metadata.<\/li><li><code>observe_search_query<\/code>: Provide module-specific search query handlers with ACL-aware filtering.<\/li><li><code>observe_tick_24h<\/code>: Run daily backup retention and cleanup tasks according to site environment settings.<\/li><\/ul>","slug":"mod_backup","doc_module_config":[{"default":"&quot;0&quot;","description":"How to perform a daily backup. 0 = no backup, 1 = database and file, 2 = only database.","has_default":true,"key":"daily_dump","module":"mod_backup","type":"integer"},{"default":"false","description":"Show the revisions admin panel on the resource edit pages in the admin.","has_default":true,"key":"admin_panel","module":"mod_backup","type":"boolean"},{"default":"true","description":"Allow downloading of the backup files from the admin backups page.","has_default":true,"key":"allow_backup_download","module":"mod_backup","type":"boolean"},{"default":"true","description":"Allow manual backups to be started from the admin backups page.","has_default":true,"key":"allow_manual_backup","module":"mod_backup","type":"boolean"},{"default":"18","description":"How many months to keep revisions of resources. At least 1 month.","has_default":true,"key":"revision_retention_months","module":"mod_backup","type":"integer"},{"default":"90","description":"How many days to keep revisions of resources with personal information. At least 1 day.","has_default":true,"key":"user_revision_retention_days","module":"mod_backup","type":"integer"},{"default":"30","description":"How many days to keep revisions of resources with personal information of deleted users. Maximum is 30 days.","has_default":true,"key":"user_deletion_retention_days","module":"mod_backup","type":"integer"},{"default":"false","description":"Encrypt backups with a password. If enabled, a password is generated if not set in the config.","has_default":true,"key":"encrypt_backups","module":"mod_backup","type":"boolean"},{"default":"[]","description":"The password to encrypt the backups with. This must be kept secret and copied to offline, secure storage. If not set, a random password is generated.","has_default":true,"key":"backup_encrypt_password","module":"mod_backup","type":"string"}],"is_protected":false,"visible_for":0,"tz":"UTC","language":["en"],"doc_source_hash":"97f5482f3633e5471b6ffdbc48ae5ae6cfbbc7b0ee33628a78f5c14866f66c50","is_featured":false,"content_group_id":{"id":2551,"is_a":["meta","content_group"],"name":"content_group_imported_docs","title":"Imported documentation","uri":"https:\/\/zotonic.com\/id\/content_group_imported_docs"},"category_id":{"id":320,"is_a":["meta","category"],"name":"module","title":"Modules","uri":"https:\/\/test.zotonic.com\/id\/320"},"doc_source_path":"apps\/zotonic_mod_backup\/src\/mod_backup.erl","publication_start":"2023-06-24T08:17:43Z","github_url":"https:\/\/github.com\/zotonic\/zotonic\/blob\/master\/apps\/zotonic_mod_backup\/src\/mod_backup.erl","pivot_location_lng":null,"doc_source_kind":"module","name":"doc_module_mod_backup","is_unfindable":false,"is_published":true,"pivot_geocode":null,"created":"2020-05-30T05:47:24Z","uri":null,"doc_status":"current","is_dependent":false,"erlang_app":"zotonic_mod_backup","publication_end":"9999-06-01T00:00:00Z","modifier_id":{"id":1,"is_a":["person"],"name":"administrator","title":"Site Administrator","uri":"https:\/\/zotonic.com\/id\/1"},"privacy":0,"doc_source_commit":"c19e5c894d3bd01b57581e2af43e176d42c6877a\n","creator_id":{"id":336,"is_a":["person","robot"],"name":"gitbot","title":"Git","uri":"https:\/\/zotonic.com\/id\/336"},"modified":"2026-10-08T10:40:46Z","title_slug":"mod_backup"},"uri":"https:\/\/zotonic.com\/id\/1521","uri_template":"https:\/\/zotonic.com\/id\/:id","websub":{"hub":"https:\/\/zotonic.com\/.zotonic\/websub","topic":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/1521"}},"status":"ok"}