I think the procedures on migrating a site at https://wiki.civicrm.org/confluence/display/CRMDOC/Moving+an+Existing+Installation+to+a+New+Server+or+Location are out of date. They certainly don't reflect how we at JMA migrate sites from production to staging in 2016. For example, we don't create a fresh install of CiviCRM, and instead pull the source code from git and copy the dbs. We also use various techniques to prevent staging, dev and local test sites from sending out emails, which are not included the recipe.

So: what is a good recipe for migrating a production site to a staging instance?

3 Answers 3


Many of the steps documented on the "Migrating a site" wiki page are handled automatically now. Here's my recipe, which is far from perfect, but is much closer.

  • Copy the entire filesystem to the staging server. Git works well for this, but when it's not an option, we'll use SFTP or create a tarball.
  • Dump the database using mysqldump, either directly or using drush civicrm-sql-dump or wp-cli cv sql-dump. Copy the db dump to the staging server. We don't use git for this because of the database size; we either use drush sql-sync or copy it manually.
  • Assuming a manual database dump copy, we need to remove the trigger definers - unless the MySQL username is identical on both production and staging. I use sed -i -e 's:/\*\!50017.*\*/::g'.
  • Load the database into MySQL on the staging server.

Assuming this is not the first time we set up the server, we're done! On first time setup, there are a few other things we need to do:

  • Replace all the usernames, passwords, paths, etc. in settings.php, civicrm.settings.php, and/or wp-config.php with the values appropriate to the staging server. If using git, these files are ignored in git, only local copies exist.
  • There are a number of values we override in civicrm.settings.php on the staging server to use the appropriate paths. Here's what I put in mine, directly below the <?php marker:


global $civicrm_setting;
$civicrm_setting['CiviCRM Preferences']['allowPermDeleteFinancial'] = 1;
$civicrm_setting['Directory Preferences']['customTemplateDir'] = '/home/jon/local/example/wp-content/civicrm/templates';
$civicrm_setting['Directory Preferences']['customPHPPathDir'] = '/home/jon/local/example/wp-content/civicrm';
$civicrm_setting['Directory Preferences']['extensionsDir'] = '/home/jon/local/example/wp-content/civicrm/extensions';
$civicrm_setting['URL Preferences']['extensionsURL'] = 'http://example.local/civicrm/extensions/';
$civicrm_setting['URL Preferences']['imageUploadURL'] = 'http://example.local/wp-content/plugins/files/civicrm/persist/contribute/';
$civicrm_setting['URL Preferences']['userFrameworkResourceURL'] = 'http://example.local/wp-content/plugins/civicrm/civicrm';

In Wordpress, we also need to add a few overrides to wp-config.php. Some of these may be overkill but: define('WP_HOME','http://example.local'); define('WP_SITEURL','http://example.local'); define('RELOCATE',true); Finally, if this is a multi-site Wordpress, we need to do a search and replace of the database for the URL. We do this with wp-cli search-replace https://oldsite.com https://newsite.com but this tool also does the trick.

  • 1
    And in most cases, disable sending email, the most stable would be: Activate in civicrm.settings.php the CIVICRM_MAIL_LOG. An alternative is to do it in Admin screen, but you have to remember it with every staging copy, while in most cases you would keep the staging civicrm.settings.php with the next copy.
    – Catorghans
    Feb 27, 2016 at 22:39
  • 2
    It would be helpful to get this into the documentation.
    – Graham
    Sep 26, 2017 at 16:42
  • 1
    If you are using CiviCRM 4.7 or newer and you did not change the paths on production you don't need to change the Directory Preferences or URL preferences in civicrm.settings.php May 24, 2018 at 11:39

Thanks to Jon G and alec for this answer that mostly works for me.

Just a detail on the sed expression that was not working out of the box for me, I use:

sed -e 's:/\*\!50017[^*]*\*/::g' <DUMP_ORIG> > <NEW_DUMP>

The /*!50017 ...*/ is in the middle of a long line that define other stuff related to triggers that I want to keep. This modified regex ensure that I remove only this /*!50017 ... */ and not the whole comment.

  • 1
    Welcome to CiviCRM.SE. I've flagged for a moderator to convert this into a comment, as it is not a full answer to the original question. If you are new to Stack Exchange, I strongly recommend you take the site tour and review the help center.
    – choster
    May 29, 2018 at 22:29

Steps to migrate site having CiviCRM from prod to staging:

  1. Take SQL dump of your CMS database and if civicrm is using a different database than CMS (which in most cases people does that), take sqldump of civicrm database too
  2. Copy codebase over to staging server
  3. Create a new database for your CMS and civicrm (if civicrm on prod was using different DB than of CMS) on staging server
  4. Load both databases with dumps you took in #1
  5. Update CMS DB config file (drupal = settings.php || Wordpress = wp-config.php) to match correct database credentials
  6. Update civicrm_settings.php file to match correct database credentials
  7. Update civicrm_settings.php file for correct CIVICRM_UF_BASEURL and civicrm_root variables

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.