Move from EspoCRM Cloud or another instance to self-hosted EspoCRM

Moving an existing EspoCRM Cloud or hosted instance onto your own servers is mostly a controlled export, import and validation exercise. This page covers what transfers cleanly, what needs rebuilding, and where the effort goes.

On this page

How to move EspoCRM Cloud to self-hosted EspoCRM without losing records or configuration

Moving a team from EspoCRM Cloud or another hosted instance to servers it controls is a planned export, rebuild and validation exercise, not a file copy. The effort depends on how much the instance has been customized, which extensions it runs, how many integrations depend on it and how much data it holds. The open-source edition of EspoCRM can be downloaded and self-hosted for free, according to the EspoCRM pricing page, but that changes only the license line. Cloud plans include the Advanced Pack, so the target instance needs the same reports, workflows and Business Process Management, either through a licensed copy of that extension or by rebuilding what the team actually uses.

Start by inventorying the source instance: its exact EspoCRM version, installed extensions, Entity Manager entities, layouts, formula scripts, workflows, roles, teams, API users, email accounts and integrations. Then confirm the target version and extension versions, since the Advanced Pack and any other extension must match the core release you deploy. Confirm with the vendor and your own environment which extension licenses you hold, and which of them the self-hosted build can use, before you commit to a cutover date. Also check that your target server meets the current PHP, database and web server requirements in the EspoCRM server configuration docs, with cron configured for background jobs.

Plan the data transfer around the Export Import extension and the CSV import tooling, and rehearse it on a copy before cutover. Compare record counts, attachments, relationships, user assignments and permissions field by field, and test the critical paths: lead capture, approvals, scheduled reports and email delivery. Keep the source instance read-only or frozen during the final delta, and record who signs off on each validation check. Retain the source until the new instance has run through a full business cycle, and confirm the retention and deletion terms of your hosting contract for the old data.

Which parts of an EspoCRM instance map cleanly to a self-hosted instance

This table compares each part of a cloud or hosted EspoCRM instance with its equivalent on your own servers. Read the middle column for the target equivalent, the third column for whether it moves by export or must be rebuilt, and the last column for the note to act on before cutover.

ComponentTransfer method on self-hosted targetMigration note
Records and relationshipsExport Import extension run per entity, with related records exported in dependency orderConfirm record IDs and relationship fields survive the import in a test instance before cutover
Entity definitions (Entity Manager)Exported as configuration through the Export Import extension, then reviewed on the targetCustom entities must exist before dependent records are imported
Layouts and field settingsExported with entity configuration and checked against the target's user rolesLayouts can look correct while role-level field visibility differs, so test each role
Users and rolesUsers are not a clean export; accounts and role assignments are usually recreated and linked to the new identity sourceConfirm how passwords and sessions are handled, since the target starts with its own authentication setup
TeamsRecreated on the target and assigned to users and recordsTeam membership often drives record visibility, so verify access after import
Workflows and BPM flowchartsExported as configuration with the Advanced Pack, where the feature set is licensedConfirm the Advanced Pack or equivalent extension is licensed for the self-hosted instance before import
Formula scriptsCarried in entity and workflow configuration; formula logic is reviewed, not re-authoredCheck that any script calls to external services still resolve from the new network
Integrations and API usersRecreated on the target with new API keys or HMAC credentialsRotate credentials, since keys issued by the source host should not be reused
Extensions and licensesExtension packages are installed on the target; paid or licensed extensions need their own activationConfirm license terms and whether the license is tied to the source instance or domain
Files and attachmentsCopied from the source storage path or external storage, not included in standard record exportsPlan transfer of attachment storage separately and verify file counts and access after copy
Authentication (SSO, OIDC, LDAP)Reconfigured on the target with its own redirect URIs and identity provider client settingsHosted instances may use a provider-side setup; update identity provider callback URLs and test fallback login

Documented export and import paths for moving between EspoCRM instances

Moving from a cloud or hosted EspoCRM to your own servers usually combines more than one path. The Export Import extension covers the broadest set of data, the CSV importer handles record data with controlled write modes, and the REST API lets you read what the other paths miss. Each path has limits, so confirm what each one carries before you plan the cutover.

Export Import extension scope

The Export Import extension is the path this migration is built around for records, settings, customizations and files. Before you rely on it, confirm that the extension is available for your target version and edition, because a cloud plan and a self-hosted install may not expose the same options. Run a full test export and import on a copy of the source, then list which records, configuration items and files actually arrived. Treat that list as your acceptance baseline.

CSV import for record data

The CSV importer moves record data in three modes: Create Only, Create and Update, and Update Only. Field mapping lets you align source columns with target fields, so check that every custom field exists on the target before you import. Use Create Only for the first load into an empty instance, and Update Only when you refresh existing records after a delta export. Keep each file to one entity so you can control the order of the loads.

Duplicate matching and reverts

Duplicate matching uses fields you choose, and record IDs usually change between instances, so match on stable business keys such as an email address or an external reference. Test the matching rules on a sample file to see how many records would be created in place of updated. The import docs describe reverting imported records, which gives you a way to undo a bad batch. Confirm the revert behavior on your version before you rely on it for a production load.

Large files and cron

For large files, the importer can run idle execution through cron, so the job continues in the background rather than in a browser session. Make sure cron is configured on the target before you start, since background jobs depend on it. Measure run time with a representative file, and split the load by entity when one file grows too large. Plan parent records, such as accounts, to load before the child records that link to them, and check how the import handles linked records on your version.

REST API for source reads

The REST API reads source data when no export or CSV path covers it, such as a custom entity, a related list or attachment metadata. Create a dedicated API user with a role limited to read access, and use HMAC authentication, which the docs describe as the most secure method. Basic authentication is not recommended. Check that the role can see every team and record set you need, because permissions filter what the API returns and missing rows can look like a failed export.

Source admin access and token cleanup

Run exports under a named migration account, not an everyday admin account, and confirm that your cloud provider gives you the admin rights the extension and API need. Review the source password policy, token lifetime and IP restrictions before the run, since they can block reads partway through. After cutover, revoke the migration API user, remove its tokens and restore the source access settings. Record these steps in the cutover checklist so they are not skipped.

Migration sequence from inventory through parallel run and cutover

This sequence takes an EspoCRM Cloud or hosted instance onto your own servers with a documented inventory, a rehearsed import, validated data and customizations, a supervised parallel run, and a controlled cutover followed by a retained source.

  1. Inventory the source instance

    Record the EspoCRM version, the PHP and database expectations of that version, every installed extension and its license status, the entities and layouts you have customized, workflows and BPM flowcharts, roles, teams, API users, integrations, scheduled jobs, and the file attachments and their volume. Ask the cloud provider or your administrator which exports you can run and what the source does not expose, such as server-side files or mail settings. The output is a written inventory signed off by the business owners of sales and service, with each item marked as migrate, rebuild or retire.

  2. Build the target server with the documented stack

    Provision the target servers in infrastructure you control using the server configuration documented for the EspoCRM version you will run, including a supported PHP version, a supported MySQL, MariaDB or PostgreSQL release, your web server, and cron for background jobs. Choose between the installation script, which deploys a Docker-based stack with Nginx and MariaDB on supported Linux distributions, and a manual install. Confirm the TLS certificate, backups, and network access. The output is an empty, reachable instance that passes the installation checks and runs a scheduled job.

  3. Align versions and extensions on both sides

    Install the same EspoCRM version on the target as the source, or plan a documented upgrade on the target before data moves, so that entity definitions and field types match. Install the extensions that the inventory marked as migrate, and confirm that each extension license is valid for self-hosted use with the vendor before you rely on it. Check that the PHP version on the target satisfies the release you chose. The output is a target whose core version and extension list match the source, with any difference recorded.

  4. Run a pilot export and import into staging

    Create a staging instance from the target build, then run the Export Import extension on the source for a bounded set of records, settings, customizations and files. Import the package into staging in dependency order, starting with reference data and users, then accounts, contacts and opportunities, and finally activities and attachments. Record every error, skipped record, and mismatch in a log. The output is a pilot run log with an error list and a re-run plan that tells you which exports and imports need to be repeated.

  5. Validate records and customizations

    Compare record counts per entity between source and staging, then sample records across each entity and check relations, owners, teams, assigned users, custom fields, dropdown values, and attachment links. Open each custom layout, dynamic logic rule, formula script, workflow and BPM flowchart on staging and run a test case for each. Check that scheduled jobs, email settings and integrations were re-pointed to target values. The output is a signed validation checklist where each failure has an owner and a fix applied and retested.

  6. Test access and identity on staging

    Verify roles, teams, portal roles and API users on staging with test accounts that represent each business role. If you plan to use OpenID Connect or LDAP, configure the identity provider against the staging URL, confirm group-to-team mapping and the fallback login method, and confirm that two-factor authentication is handled by the identity provider where EspoCRM's own two-factor authentication is not compatible with OIDC. Confirm admin accounts are used only for administration. The output is a documented access test with each role and sign-in path marked as passed or open.

  7. Run a parallel period with controlled data entry

    Run the source and the target side by side for an agreed period, with a defined rule for where new records are entered. Limit parallel entry to the team that has been trained on the target, and reconcile changes at an agreed interval by re-exporting the delta from the source and importing it into the target, checking for duplicates before each run. Track open issues in a shared list. The output is a reconciliation record that shows the delta was clean on the final pass and that every open issue has an accepted outcome.

  8. Cut over with DNS and identity changes

    Freeze writes on the source, run the final delta export and import, and confirm the counts match. Change the DNS record that users open, update the site URL and identity provider redirect addresses to the production hostname, and confirm the backchannel logout and sign-in paths work. Disable source access for regular users and keep it available for read-only reference. The output is a cutover record with the time of freeze, the final counts, the DNS change, and a sign-in test by each business role.

  9. Decommission the source after the retention period

    Keep the source instance and its export archive under read-only access for the retention period your records and legal teams set, then remove users, revoke API keys and integrations pointing at it, cancel the cloud subscription or shut down the server, and delete data according to your retention and deletion policy. Confirm with the provider how exported archives and backups held by them are removed. The output is a written decommissioning record that lists what was deleted, where copies remain, and who approved the deletion.

Why the target version, extensions and server stack must be aligned first

Before any data moves, the target EspoCRM version must be compatible with the source instance, and the server stack must meet the documented requirements. Export and import are only reliable when both sides run versions that understand the same entity structure, field types and formula logic. Confirm the exact PHP, database and web server combinations in the EspoCRM server configuration docs, which list PHP 8.3 to 8.5, MySQL 8.0 or newer, MariaDB 10.6 or newer, or PostgreSQL 15, on Apache, Nginx or IIS. Check those requirements against the current release, not against the version you run in the cloud today, because the target server is where you will install first.

Next, run a license and compatibility check for every official extension the source instance uses. The Advanced Pack, which provides reports, Business Process Management and workflows, is included in EspoCRM Cloud plans, but on a self-hosted instance it needs its own license and installation on the target. Inventory each extension, confirm the license your organization holds for it, and confirm it supports the target version before you export anything. Custom entities, layouts and formula scripts can be transferred with the Export Import extension, but the extensions that generate them must be present first, or the imported configuration will reference features that do not exist on the new server.

Authentication and API access are the two areas where teams most often assume copying is enough. If the cloud instance uses OpenID Connect or LDAP sign-in, plan to rebuild the identity provider configuration on the new instance with its own client settings, group-to-team mapping and fallback login method. The same applies to API users, whose keys, HMAC secrets and role permissions should be recreated and then reissued to each integration. Plan the cron job for background tasks on the new server as part of the same stack check, because scheduled jobs, email processing and workflows do not run without it.

What makes an EspoCRM migration take longer or cost more

How does the volume of records and files affect an EspoCRM migration?

Record and file volume drives the number of export and import runs, the time spent on validation, and the disk and transfer capacity your new server needs. Large attachment libraries often take longer to copy and verify than the database itself, so ask the vendor or your own team to confirm how files are exported from the source instance and where they will sit on the target. Each run should be sized so that failures are easy to isolate and repeat. Records are one-time work during cutover, but storage capacity is recurring, so ask the quote to state which storage is assumed and who owns growth planning after go-live.

Why do custom entities, layouts and formula scripts add to the work?

Every custom entity, layout and formula script must be exported, compared and re-tested on the target instance, because each one can depend on field names, options and relationships that the import does not create by itself. Formula Script runs in before-save scripts, API before-save scripts, workflows and BPM, so a script that works in the source may behave differently once data has moved. Ask for an inventory of entities, layouts and scripts in the written scope, along with the test cases that will confirm each one still behaves as before.

How do workflows and BPM flowcharts change the migration effort?

Workflows and BPM flowcharts are configuration that references users, teams, statuses and external calls, so they need to be reviewed rather than simply copied. Some depend on the Advanced Pack, which is included in EspoCRM Cloud plans, so confirm its licensing and availability on the self-hosted target before scheduling any build. Each active process should be listed with its trigger, its dependencies and its expected result, and the quote should say whether processes are being rebuilt, re-exported or only verified.

Do extension licenses and versions affect migration cost?

Yes. Each official extension or custom package must be matched to a license that covers the self-hosted instance, and its version must align with the EspoCRM core version on the target. Cloud plans bundle some extensions, so an extension that was included in the cloud subscription may need separate handling after the move. Ask the vendor to confirm the license terms for each extension in writing, and ask the quote to list which extensions are one-time installs and which carry recurring license costs.

How many integrations need reconfiguring after cutover?

Each integration, such as email, calendar, telephony, payments, webhooks or API clients, has its own endpoints, credentials and callback addresses that change when the instance moves. API users, keys and HMAC secrets must be recreated or re-issued, and external systems must be pointed at the new site URL. Build an integration register with an owner, a test step and a rollback step for each item. Recurring costs appear when integrations need monitoring or credential rotation after go-live.

What changes when the identity provider moves to the new instance?

Identity changes are often the riskiest part of a cutover. EspoCRM supports OpenID Connect sign-in, with optional user creation on first login and mapping of identity provider groups to teams, and it also documents LDAP authentication. Redirect URIs, client secrets, group claims and fallback login must all be set on the new site URL, and EspoCRM's own two-factor authentication is not compatible with OIDC, so the identity provider must enforce that control. Ask for a test matrix that covers each role and each login path before cutover.

How do data quality and duplicates change the timeline?

Duplicate contacts, incomplete accounts and inconsistent field values slow every import run, because matching rules must be tuned and exceptions reviewed by people who know the business. The CSV import supports duplicate matching on chosen fields and reverting imported records, which helps, but the decisions about which record to keep still need an owner. Ask the quote to state the cleanup work in scope, who signs off on merges and whether cleanup happens before or after the first trial import.

How many parallel-run users affect cost and risk?

A parallel run keeps users working in the source and target systems for a period, so every change made in one must be reconciled in the other. The more users involved, the more reconciliation, permission checks and support time you need, and the more licenses you may be paying for on both sides at once. Ask the written scope to state how many users take part, how long the overlap lasts and how changes made during the overlap will be captured and re-imported.

What usually goes wrong in a cloud-to-self-hosted EspoCRM move

Most failed moves are not data loss in the obvious sense. They are attachments that did not come across, settings that stayed behind, background jobs that never started, and users or integrations that quietly kept pointing at the old instance. Each card below names one of these failure points and the check that prevents it before cutover.

Lost or stale attachments

Records can import cleanly while their files do not. Attachments, images and document templates live in the file store, so an export of database rows alone leaves broken links on the new server. Before cutover, sample attachments from several entity types, open them on the new instance, and confirm file counts match the source. Ask your partner or vendor to confirm which file directories the export covers on your instance version, and plan a fresh file copy for anything that changed after the last run.

Custom configuration left behind

Entity Manager changes, layouts, field definitions, formula scripts and workflows are customizations that may or may not be carried by a given export run. If they are missed, the new instance looks like a generic EspoCRM with working data and broken business logic. Build an inventory of custom entities, layouts, formulas and automations from the source, then compare that list against the target after import. Confirm with the extension documentation exactly which configuration types each run includes.

Extension version mismatches

Paid and official extensions must match the core version and must be licensed for the new server. An extension that is one release behind may install but fail on forms, reports or workflows, and a license tied to the old domain may not activate. Record the installed core and extension versions on the source, align them on the target before importing configuration, and confirm license transfer with the vendor in writing. Cloud plans include the Advanced Pack, so check whether your features depend on it.

Cron not running on the new server

Email fetching, scheduled jobs, workflows and reports depend on a scheduled task that runs on the server. The documentation requires cron or an equivalent scheduler for background jobs, and a new server that lacks the crontab entry will accept logins and records while queued emails and automations silently stop. Add the crontab entry for the web user on the new host, confirm the job queue is draining, and send a test email and a test workflow trigger before users return.

Users locked out by sign-in changes

A move that changes the site URL, identity provider settings or two-factor setup can prevent users from signing in on day one. OIDC configuration, redirect URIs and fallback login methods are tied to the hostname, and an admin who relied on cloud-side recovery may have no working path on the new server. Document the sign-in method for each user group, register the new redirect URI with the identity provider in advance, keep an admin fallback account with a tested recovery path, and run a login test for each role.

Duplicates and forgotten integrations

During a parallel run, sales staff may keep working in the old instance while imports run into the new one, creating duplicate accounts and contacts. Forms, webhooks, email connections, API clients and mailbox integrations that still reference the old site will keep writing data to the instance you are leaving. Freeze new entry on the source before the final delta import, match duplicates on chosen fields, and maintain a register of every integration that points at the old URL so each one is repointed or retired.

Questions teams ask before moving EspoCRM to their own servers

What does it cost to move EspoCRM Cloud to our own servers?

The move has two cost sides: the Cloud subscription you stop paying and the one-time work to rebuild the instance on your infrastructure. According to the EspoCRM pricing page, Cloud costs 15 US dollars per user per month on the Basic plan (minimum 3 users), 25 dollars on Enterprise (minimum 5 users) and 69 dollars on Ultimate (minimum 10 users), so your current per-user rate is the baseline for any savings. The open-source edition is free to download and self-host, but you pay for servers, backups, TLS certificates, monitoring and staff time for upgrades. One-time costs include planning, export and import runs, customization checks, extension setup and validation. Recurring costs include hosting, patching and any support retainer. Record volume, file storage, the number of customizations, the extensions in use and the number of validation rounds drive the total up or down. Ask every quote for a written scope that lists these items separately.

How long does a move from EspoCRM Cloud usually take?

Duration depends on scope more than on the platform, and no supplied figure sets a general timeline, so confirm the schedule against a written plan. The main drivers are the volume of records and attachments, how many layouts, workflows, formula scripts and custom entities must be carried over, and how many extensions must be installed and matched to versions. Teams with many users or external integrations usually need more validation rounds before cutover. Scheduling matters as well: you need a cutover window in which nobody edits the source, and time for business users to test. Ask the provider to split the plan into export and import runs, version alignment, validation, cutover and a post-cutover check, with an owner and dependencies for each step. Then compare that plan with your own calendar for business freezes and staff availability.

What must our team provide before a self-hosted EspoCRM migration starts?

Before work starts, the team needs administrator access to the source instance and the target servers, plus control of DNS and certificates. Admin access should be scoped to the source EspoCRM and the target infrastructure, with a named person who can grant it. Extension licenses must be confirmed for the target, since official extensions such as the Advanced Pack carry their own terms, and you should check whether each one permits self-hosting. Data owners must decide which records, files and fields are in scope, which to archive and which to drop. Test users with the roles used by sales, service and administration must be available during validation. A decision maker must approve the cutover window and the rollback plan. Ask for this list in writing so responsibilities are clear on both sides before any export runs.

Can one capable internal admin move EspoCRM alone?

A single experienced administrator can handle a small, simple instance, but most moves are too broad for one person to carry safely. The work combines server provisioning, PHP and database setup, file transfer, Export Import extension runs, extension installation, configuration correction, crontab setup and validation with business users. The person who runs the export is also best placed to check what the import changed, so a second reviewer is worth planning. Key-person risk matters too: if one admin is the only one who understands the system, a cutover problem can stall the business. A practical split assigns one person to configuration and data, another to servers and backups, and business testers to validation. Ask a partner to quote the work or review your internal plan, then decide based on your team's experience with PHP applications, database operations and scheduled jobs.

Does the open-source edition replace every feature we use in Cloud?

Not automatically. The open-source edition can be self-hosted for free, but you must confirm that each Cloud feature exists in the edition or in an extension you can license. According to the EspoCRM Advanced Pack page, the Advanced Pack provides reports, Business Process Management and workflows, and the pricing page states it is included in all Cloud plans, so teams that rely on reports or workflows must plan for it on their own servers. Other official extensions include Sales Pack, VoIP, Google, Outlook, MailChimp, Zoom and Stripe integrations, and each should be checked against what your teams actually use. If you modify the code, review the obligations of the AGPL-3.0 license with your legal team. Build an inventory of features in use, map each one to the edition or extension that supplies it, and confirm licensing before you retire the Cloud subscription.

How is the old EspoCRM Cloud instance retired after cutover?

Retirement is a sequence: freeze the source, take a final export, verify the target, then cancel the subscription and keep an archive for the period your policy requires. Stop edits on the source at the agreed cutover time so no changes are lost between the last export and the switch. Next, run the final Export Import delta, confirm record counts and attachments on the target, and point DNS and integrations to the new instance. Revoke API users, integration credentials and sign-in connections tied to the old site so nothing still writes to it. Keep an archive export and backups in storage you control. Only then cancel the Cloud plan, and ask the provider in writing how your data is removed and what it retains. Record each step in a cutover log so your team and auditors can see when the old instance stopped being the system of record.

What should we check on self-hosted EspoCRM before cutover?

Check that the target matches the source in data, configuration, access, background work and integrations before anyone is told to switch. Compare record counts per entity, sample records and attachments, and confirm that layouts, formula scripts and workflows behave as they did on the source. Test access with users from each role, and confirm that daily work does not run through an admin account, in line with the EspoCRM security recommendations. Verify the site URL and database settings in the configuration file, and confirm that cron runs, since background jobs depend on it. Test outbound and inbound email, and test any OIDC sign-in and API client against the new hostname. Confirm that the target version matches the source, because the UI upgrade path is disabled by default as of version 10.0 and version differences can affect extensions and customizations. Record each check as pass or fail, with an owner.

Which server stack does self-hosted EspoCRM need?

The server configuration docs list PHP 8.3 to 8.5, MySQL 8.0 or newer, MariaDB 10.6 or newer or PostgreSQL 15, running on Apache, Nginx or IIS. Cron or a scheduled task must run for background jobs, which makes scheduling part of the build rather than an afterthought. For Ubuntu, Debian and Linux Mint, the installation script deploys a Docker-based stack with Nginx and MariaDB, optional Let's Encrypt certificates and a command.sh utility for backups, restores and upgrades. Choose between the script and a manual install based on how much control you need over the operating system, reverse proxy and database. Match the database engine and version to what your source uses, and test the restore path before the data load. Ask the provider to document the stack, the backup schedule and a restore test as part of the handover.

How DeployOpen scopes and delivers an EspoCRM instance migration

DeployOpen starts with a written scope that covers which records, settings, customizations, files and extensions move from your current instance to servers you control. The work is delivered in stages, with each stage tested against the source instance before cutover.

How we scope

  • Inventory the source instance: entities, layouts, workflows, BPM flowcharts, extensions, users, roles and files.
  • Confirm the target stack matches the EspoCRM server requirements, including PHP, database engine and cron for background jobs.
  • Record in the written scope which licenses for paid extensions transfer to your servers and who holds them.

How we build

  • Align the source and target to the same EspoCRM version, planning any version change as a separate, tested step.
  • Run Export Import extension passes for records, settings and customizations, then compare results against the source counts.
  • Rebuild files, scheduled jobs and mail settings on the target, and test each with a sample of real user actions in a staging copy.

How we hand over

  • Document the export and import sequence, the configuration changes made on the target and the validation checks performed.
  • Provide a cutover runbook with a rollback point, the DNS or proxy change and the freeze window for the source instance.
  • Deliver a checklist for your administrators covering backups, admin account hygiene and the security settings applied on the new server.

How we support

  • Support after cutover can be handled as a retainer covering patches, upgrades and questions raised by your team.
  • Ask for a clear list of what the retainer excludes, such as new extension builds or major version upgrades.
  • Schedule a post-cutover review of logs, background job health and user access before the source instance is retired.

Sources and further reading

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.