Why EspoCRM backup and restore needs a tested plan
A self-hosted EspoCRM holds customer records, activity history, email, uploaded files and the configuration that shapes how your teams work, and those parts live in more than one place. The database holds the records and settings, while uploaded files and attachments sit in the file storage of the instance. A backup that copies only the database leaves the attachments and the customizations behind, so a complete plan should capture the database, the file storage, the configuration files, and, for Docker-based installs, the volumes that hold the data. Teams need this plan before the first real user enters data, not after a server failure. Confirm with your own environment which paths and volumes your installation uses, because the layout depends on how EspoCRM was installed.
The decisions that matter most are where backups are stored, how often they run, how long they are kept, and who can read them. Backups contain customer personal data, so the storage location, encryption and access rights need the same review as the live system. Also decide the recovery target for each part of the instance, since restoring the database without the matching files can leave broken attachment links. The EspoCRM installation docs describe a command.sh utility that handles backups, restores and upgrades for script-based Docker installs, and the EspoCRM installation by script documentation is the natural starting point for checking what it covers in your version.
A backup is only useful if it restores, and a restore that has never been rehearsed is an untested assumption. DeployOpen sets up the backup routine and the restore procedure inside your own cloud accounts, data centers or air-gapped network, then runs test restores into a separate environment so your team can confirm the application opens, records and files are intact, and scheduled jobs behave as expected. Ask any partner, including DeployOpen, to define in writing how often test restores run, who signs off the result, and where the restore evidence is kept. Those answers belong in the scope before work starts.
Choosing between the backup script, manual dumps and Docker volume backups
EspoCRM's installation script for Ubuntu, Debian and Linux Mint deploys a Docker-based stack with Nginx and MariaDB, optional Let's Encrypt certificates, and a command.sh utility that handles backups, restores and upgrades. If your instance was installed this way, this is the first method to evaluate because it is built around the layout the installer created. Confirm the exact command syntax, options and output locations in the installation by script documentation before you rely on it.
- Environment: Ubuntu, Debian or Linux Mint hosts that the installation script set up.
- What it captures: Depends on the utility's options, so verify whether it covers both the database and the application files and data volume.
- Operator effort: Low for routine runs once scheduled, but the backup is only as complete as the options you select.
- Restore path: Use the matching restore command in the same utility, which keeps the restore aligned with the stack layout.
- Limits: It fits the installer's standard layout. Heavily customized hosts may need additional steps.
Before relying on it, check which files and volumes it writes, where they are stored, and whether the script runs unattended under cron or a systemd timer.
On a traditional server, where EspoCRM runs under Apache, Nginx or IIS with a supported database such as MySQL, MariaDB or PostgreSQL, you back up two things separately: the database and the application files. This method gives you full control over what is captured and where it goes, but every part of the procedure is your team's responsibility. Your restore is only as reliable as the steps you wrote and tested.
- Environment: Self-managed servers using the supported web server and database combinations listed in the server configuration documentation.
- What it captures: A database dump holds records, metadata and settings. The file copy must include the EspoCRM directory, configuration files and any custom files, such as uploaded attachments and extensions.
- Operator effort: Highest. You write, schedule, monitor and document each step.
- Restore path: Restore the database dump, then restore the files, then confirm the file permissions and rebuild as your version requires.
- Consistency: Dumping the database and copying files at different times can produce a mismatch, so plan a quiet window or a consistent snapshot.
Confirm the backup coverage of each command against the server configuration and upgrade documentation for your EspoCRM version.
When EspoCRM runs in Docker, application data and database data usually sit in named volumes or bind mounts rather than in the host's application directory. A Docker volume backup copies those storage locations, and it must be paired with a consistent database export, because copying a live database directory is unreliable. This approach suits teams that already manage container hosts and want backups to follow the same deployment definition.
- Environment: Docker Compose stacks, including the one the installation script creates, or a custom Compose file on your own hosts.
- What it captures: The contents of the volumes you map. Confirm which volumes hold uploaded files, configuration and database storage in your Compose file.
- Operator effort: Moderate. You manage volume names, container stop or quiesce steps and storage location for each run.
- Restore path: Recreate the stack from the same Compose definition, restore the volumes, and load the database export into a matching database version.
- Version discipline: Record the image tags in use, because restoring into a different image version can require an upgrade step.
Before you choose this method, verify that every stateful volume is listed in your backup job and that a restore reproduces a working instance on a separate host.
Backup options and when each one fits
This table compares four ways to back up a self-hosted EspoCRM: the command.sh script, manual database and file copies, Docker volume handling and off-host copies. Read each row for what it captures and what it misses, then combine options so the database, uploaded files and configuration are all covered. The main takeaway is that no single option is complete until a restore has been tested.
| Option | What it captures | When it fits | Main trade-off |
|---|---|---|---|
| Script-based backup via command.sh | Database and application files when the installation script deployed the Docker stack; confirm the exact contents in the EspoCRM installation docs | Single-server installs built with the official installation script that want a supported, repeatable routine | Only as complete as the script's coverage; confirm whether custom paths, external file storage and certificates are included |
| Manual database dump plus file copy | Database dump and the data, custom and config directories you name explicitly | Non-standard layouts, bare-metal or hand-built stacks, or teams that need full control over what is captured | Easy to omit a directory or to dump while writes are running; confirm a consistent dump procedure |
| Docker volume snapshot or export | Contents of the named Docker volumes holding database and application data | Containerized deployments where the storage backend supports consistent volume snapshots | Snapshots of a live database may be inconsistent without a dump; confirm which volumes hold state in your compose file |
| External storage or off-host copies | Copies of the backup archives moved to a separate host, bucket or site | Any production instance, since a backup on the same disk fails with the server it protects | Adds transfer, retention and access control work; confirm encryption, retention periods and who can restore |
Setting up backups step by step
This sequence produces a consistent copy of the EspoCRM database and files, stored off the host, that is scheduled to run and checked after every run. Each step ends with a check you can perform yourself before moving on.
Confirm the install method and database engine
Start by recording how EspoCRM was installed and which database engine it uses. Compare your PHP version against the range in the server configuration docs (PHP 8.3 to 8.5) and confirm your database is MySQL 8.0 or newer, MariaDB 10.6 or newer, or PostgreSQL 15. If you used the installation script, the stack runs in Docker with Nginx and MariaDB, and the command.sh utility can be part of the backup routine. Confirm these details with whoever administers the server, because the dump commands in later steps depend on them. The step is done when you have a short written record of the install method, the web server, the PHP version, the database engine and version, and the location of the EspoCRM directory or Docker volumes.
Locate every data source before backing up
An EspoCRM backup is only complete if it captures both the database and the file store. Identify the database name and credentials from the configuration file in the EspoCRM directory, and list the directories that hold uploaded attachments, custom code, extensions and the configuration itself. If the instance runs in Docker, identify each named volume or bind mount that holds database data and EspoCRM files, including any external file storage you have configured. The step is done when you have a checklist of every database, directory and volume, and someone other than the author has reviewed it against the running system.
Quiesce writes during the backup window
Before taking the copies, stop users and background jobs from writing so the database and files reflect the same moment. Put the instance into maintenance mode or block logins at the web server, and pause or stop the cron job or daemon that processes background work. Confirm that no scheduled job is running before you continue. The check is that no new records appear in the activity or job tables during a short observation, and that the web server returns your maintenance page or a block response to a test request. Record the time the window opened so you can match it to the copies later.
Dump the database and copy the files together
Create the database dump and the file copy inside the same quiet window, so both reflect one point in time. For MySQL or MariaDB, use a logical dump tool with a single transaction option where the engine supports it, and for PostgreSQL use the standard dump utility. Copy the EspoCRM directory, uploaded attachments, custom extensions and configuration, and for Docker deployments archive the relevant volumes after confirming the containers are stopped or the data is flushed. Store the dump and the archive under one dated folder. The check is that the dump file is not empty, ends with a complete closing statement or end-of-file marker, and that the archive lists the expected directories when you run a listing command on it.
Resume service and copy backups off the host
Restore normal service as soon as the copies are complete, then move the backup set to storage that is separate from the EspoCRM server. A backup stored only on the same disk fails when the host fails, so use a second system, a separate account, or an object store that your organization controls. Encrypt the archives before transfer if your policy requires it, and keep the encryption keys stored separately from the backups. The check is that the same file names and checksums appear in the off-host location, and that you can list them from a machine other than the EspoCRM server. Confirm that the instance answers normally and that background jobs have resumed.
Schedule the backup job and retention
Automate the sequence with a scheduled job, whether through the command.sh utility on an installation-script deployment or a script you maintain, and set retention so old copies are removed on a defined rule. Make the job write a log entry with its start time, end time, file sizes and exit status. Decide the schedule with the people who own recovery objectives in your organization, and ask your EspoCRM partner or internal team to confirm the commands against your version. The check is that the scheduled job runs at its first planned time, produces the expected files, and the log records a success status.
Verify each run with a test restore
A backup has value only when a restore from it succeeds. Regularly restore the latest copy into a separate test environment, not the production instance, and confirm that the application starts, a sample of records opens, attachments display, and a user can log in with the expected authentication method. Compare record counts for key entities against the source. Record the date, the backup used, the outcome and any gaps, and fix the backup routine when a test fails. The check is a written test result that someone can point to during an incident or an audit review.
How to restore EspoCRM from a backup
Restore EspoCRM in a fixed order: first match the EspoCRM version, PHP version and database engine to the ones the backup was taken from, then restore the database and the file set to a clean target, then restore configuration, and only after that run the rebuild and cache steps the EspoCRM docs direct. Confirm the exact version of the backup before anything else, because the backup records the state of one release. The supported PHP range and database versions come from the server configuration docs, which list PHP 8.3 to 8.5, MySQL 8.0 or newer, MariaDB 10.6 or newer, or PostgreSQL 15. Check the versions on the target against those requirements and against the backup's own version, and confirm any mismatch with the vendor before you proceed.
Rehearse every restore on a separate environment before you touch production. A restore target should be a clean host or container stack that never receives live traffic, so that a wrong step, a missing file or a version gap shows up there rather than in front of users. Do not mix a major upgrade into a restore unless you have a written plan for it. An upgrade changes the schema, the code and often the extensions at the same time, so a failed restore becomes hard to diagnose. Restore to the same version first, confirm it works, and then plan the upgrade as its own change. The upgrade docs and the release notes on the EspoCRM GitHub releases page are the right sources for that plan.
Validate the restored instance before you call it recovered. Log in with a named user and with the admin account, open a sample of records across the entities that matter most, and check that attachments open and that the file paths resolve. Confirm that scheduled jobs are running rather than assuming they are, because cron or the daemon is often not restored along with the files. Check that email fetching, workflows and any integrations reconnect, and that they do not replay queued actions against live systems. Record what you checked and who signed off. A restore test that is never written down cannot show an auditor, or your own team, that recovery works.
Protecting backup data and access
A backup of EspoCRM holds the same customer records, users and credentials as the live system, so it needs the same access controls. The cards below cover the layers that connect: the archives, the keys that open them, the database credentials used to create them, the admin account used to restore them and the retention rules that decide how long copies exist.
Encrypt archives and separate the keys
Backup archives of the file store and database contain customer personal data, so encrypt them before they leave the server. Store the encryption keys apart from the archives, in a secrets manager or offline vault, so that copying the backup volume alone does not expose the data. Confirm with your team who can retrieve a key during an incident, and test that a restore works using only the documented key location.
Restrict who can read and restore
Limit read access to backup storage to the service account that writes backups and a small named group that can restore them. Restoring an instance overwrites live customer data, so separate the right to run a restore from the right to read archives. Review these grants on a fixed schedule and remove access for staff who change roles.
Keep database credentials out of scripts
Backup scripts that hold database passwords in plain text leak them to anyone who can read the script or the process list. Give the backup job a read-only database account where the platform allows it, and supply its password from a protected environment file or secrets store with restricted file permissions. Rotate the password and check that the job still runs afterwards.
Protect the admin account used for recovery
The EspoCRM security documentation advises against using admin accounts for daily work and recommends requiring two-factor authentication, restricting access by IP address and disabling password recovery for admins. Apply the same rules to the break-glass admin that can start a restore. Store its credentials in a sealed location, and confirm that the account can sign in before you need it in an emergency.
Set retention under policy
Retention should follow your organization's policy for customer data, not the default of whatever the backup script keeps. Decide how long each backup set lives, how long copies stay in offsite storage and when deleted customer records must also disappear from backups. Ask your legal or compliance owner to sign off, and record the deletion schedule alongside the backup runbook.
Testing restores on a schedule
A backup that has never been restored is unproven. The archive may be incomplete, the database dump may fail to load into the version you run, or the file store may be missing attachments that the database references. A restore test is the only way to find those gaps before an incident does. Run it on a separate instance, never over the production stack, and treat it as a recurring control rather than a one-off project. Because the target is a disposable copy, the test can be repeated safely and its results compared over time.
Build the test environment from the same EspoCRM version, PHP version and database engine as production, so the restore exercises the same code path. Restore the most recent command.sh backup or the manual database dump and file archive into that environment, then run the restore steps exactly as your runbook describes them, including any cache clear or rebuild the runbook requires. Record how long each step took and every error, even the ones you resolve. Confirm the test instance can reach only the systems it needs, and that its outbound mail and scheduled jobs are disabled or pointed at a sink, so a restored copy never sends customer email or fires workflows against live integrations. Confirm this approach with your own configuration before you rely on it.
Check the restored instance against a short list that you define in advance. Compare record counts for key entities such as accounts, contacts, opportunities and cases with the production figures captured at backup time. Verify that attachments in the file store open and match the stored checksums. Log in with a named test user to confirm authentication and role permissions, and confirm that scheduled jobs show the expected status without running against live data. Store each run as evidence: the date, the backup identifier, the tester, the checks and their results, and any corrective action with an owner. Internal audit teams usually ask for this record, not for the test itself. DeployOpen can prepare the test procedure, checklists and evidence templates, but it does not issue audit reports or attestations, and the assessment of your controls rests with your independent auditor.
Limits to confirm in your environment
A backup plan for EspoCRM is only as good as the assumptions behind it. The cards below list what to confirm with EspoCRM's documentation, your own environment and your organization's recovery requirements before you write the backup procedure.
Exact backup scope
Confirm what the EspoCRM backup script and the command.sh utility cover for your installed version, and whether they include custom entities, layouts, installed extensions, and the custom and data directories. Ask EspoCRM or check the installation docs for your release. Extensions and custom code you added may sit outside the default scope, so list them explicitly and test that they come back after a restore.
Recovery point and retention targets
The schedule, retention period and acceptable data loss are business decisions, not vendor defaults. Agree a recovery point objective and a retention period with the teams that own the customer data, and confirm how long backups must be kept under your own policies. Those numbers determine how often the database and files are captured and how many copies you store.
Storage capacity and location
Estimate how fast the database and file storage grow, then confirm the capacity of the backup target and where copies live. Check whether backups stay inside your infrastructure, whether an off-site copy is required, and how long a restore takes from that location. Backups kept on the same host as the instance do not protect against host loss.
External file storage behavior
If attachments are stored outside the default local directory, confirm with EspoCRM which part of the file store the backup script captures. Files held in external storage may need a separate snapshot or bucket versioning. Verify the restore path rebuilds references to those files correctly.
Docker volume layout
On a Docker-based install, confirm which named volumes or bind mounts hold the database, uploaded files and configuration, and whether the stack uses the same names after a rebuild. Map each volume to a backup step and check the exact paths on your host, since a missed volume produces a restore that starts but lacks data.
Consistent snapshot of database and files
Confirm whether the database dump and the file copy are taken at the same point in time. If users write records or attachments while the two are captured separately, the restored database and files may disagree. Decide whether to pause writes, use a database snapshot, or accept a short inconsistency window, and document the choice.
Common questions about EspoCRM backup and restore
What does it cost to set up EspoCRM backups?
The EspoCRM open-source edition can be downloaded and self-hosted for free, according to the EspoCRM pricing page, so the cost of backups is the work to set them up and the storage they use. Setup cost is driven by scope (one instance or several, Docker or bare-metal hosting, database engine), by the environment (where backups are stored, whether they are encrypted and copied off-site), and by how much restore testing you want documented. Those costs are one-time for design and build, then recurring for storage, monitoring and periodic restore tests. Ask any partner for a quote that separates design, build, handover and retainer work, and that states which storage and retention assumptions it uses.
How long does it take to set up EspoCRM backups?
Duration depends on the number of instances, the hosting model, the storage target and how much verification you require. A single Docker-based instance with a backup script and off-site copies is a much smaller job than a multi-instance estate with encrypted storage, alerting and documented restore runbooks. Ask for a timeline that lists the environment inventory, the build, a first successful restore test and the handover, because the restore test is the step most often skipped and the one that proves the backups work.
What must our team provide before backup work starts?
You need to provide access to the servers or Docker host, the current EspoCRM version and its PHP, database and web server details, a list of custom files and extensions, the storage location you want to use, and the retention period your policy requires. You also need named owners for approving restore tests and for the recovery decision. Confirm with your own change process whether backup jobs and restore tests need a maintenance window, and whether staging capacity exists for test restores.
Can our own team run EspoCRM backups without a partner?
Yes, many teams can. EspoCRM's installation script provides a command.sh utility for backups, restores and upgrades when the Docker-based stack is used, according to the EspoCRM installation docs. Your team needs Linux administration skills, comfort with the database dump and file copy steps, and someone who can run a restore into a separate environment. The harder parts are usually off-site storage, encryption key handling, monitoring that backups actually completed, and proving restores work on a schedule. Decide who owns each of those before you start.
How often should we test EspoCRM restores?
Test restores on a schedule you can defend to auditors and to your own leadership, and also after any change to the server, database version, storage target or EspoCRM version. The right frequency depends on how much customer data changes each day, how far back you must be able to recover, and how costly a lost day of records would be. A restore test should restore the database and the files into a separate environment, start the application, and confirm that records, attachments and logins work. Record the result and the time it took.
What changes after a major EspoCRM upgrade?
A major upgrade changes what a valid backup contains and how a restore must be run. Take a fresh full backup immediately before the upgrade, and keep the previous version's files and database dump until the new version is verified. Restores must match the EspoCRM version, PHP version and database engine used when the backup was taken, so your runbook needs version notes. Also check that custom extensions and file paths still exist, and repeat a restore test on the upgraded system. Confirm the upgrade steps and supported versions in the official docs and release notes before you schedule the change.
Which parts of an EspoCRM instance must the backup cover?
A complete backup covers the database, the file directories that hold uploaded attachments, custom code and configuration, and the configuration files for the web server, PHP and cron. Engineers should also capture the cron schedule or daemon setup, since a restored instance without its background job configuration will look healthy but stop sending email and running workflows. For Docker deployments, include the named volumes and the compose files. Verify the list against your own installation, because custom paths and external file storage vary.
Do backups need encryption and off-site copies?
Backups of a CRM hold personal and commercial data, so most regulated organizations encrypt them at rest and keep at least one copy outside the primary host. The choices to make are where the copy lives, who holds the encryption keys, how long copies are kept, and how deletion requests are handled for data that sits in old backups. Those decisions belong in your security and privacy policies. A partner can build the mechanics, but your data owners must set the retention and access rules.
How DeployOpen scopes and delivers EspoCRM backup and restore
DeployOpen plans, implements, documents and supports self-hosted open-source platforms inside your own infrastructure, so EspoCRM backups stay in your cloud accounts, data centers or air-gapped network. Engagements start with a written scope that defines which backup method, storage target and restore test your team needs.
How we scope
- Confirm whether the instance runs on the Docker-based script install or on a manually built PHP, web server and database stack
- Record the database engine, MariaDB, MySQL or PostgreSQL, and where uploaded files and attachments are stored
- Agree backup frequency, retention periods, off-site storage location and who may access backup files
- Define recovery objectives in writing with your team, and list the systems that must come back first
How we build
- Configure the backup script or manual database and file dumps, with schedules that run under your cron or scheduler
- Capture Docker volumes and bind mounts so the full instance state, not only the database, is protected
- Encrypt backup copies and restrict access to them, using key handling that matches your existing secrets process
- Write restore runbooks for a full rebuild on new servers and for a single-record or single-file recovery
How we hand over
- Run a documented test restore into an isolated environment and record the time and steps it took
- Deliver the scope, configuration, runbooks and restore test results as written documentation for your operations team
- Walk your administrators through the restore procedure and the break-glass access steps they will need under pressure
- Provide a checklist for confirming backups completed, including how to read the job logs
How we support
- Offer ongoing support, upgrades and scheduled restore tests as a retainer, agreed in writing
- Review backup jobs after EspoCRM version upgrades, PHP changes and database migrations
- Repeat restore tests on a cadence your compliance and continuity requirements set, and document each result
- Quote any additional work from the written scope, so changes to storage or retention are priced before they happen

