Moving CMS sites around (server-to-server, server-to-local, local-to-server)
Any web developer will have to move a site from one place to another periodically, so mastering the concepts and the details are important. The details are a little different from CMS to CMS, but the big picture stays mostly the same. Please note that many people have many opinions about all of this, and some people will disapprove of what I say, but it’s intended to teach you the basic process, not the exact procedure. It also will necessarily be incomplete, since there’s no way to cover every platform or CMS, or every permutation of deployment.
- Move the code for the website. If the site is an HTML/JS site, you’re done. (Typically the code is checked via Git or some other source management situation, so it can be checked out in the new location.)
- Move the database, which has dynamic content in it. In many cases this is one database, but in complex situations it could be more than one database.
- Move the user-generated or dynamic files. On Drupal, for example, the sites/default/files directory typically has all these user-generated or dynamic files. (There may be more than one directory of user-generated/dynamic files. In Drupal there may be private files in a directory outside the docroot.)
- Move the exported configuration. In Drupal 8+, for example, the config_sync_directory has this explicit exported configuration.
- Build the site in the new location. Although older sites didn’t have a build process for deployment, almost all the newer ones do. At the very minimum, this is typically a
composer install
to populate the vendor directory, which is often not checked into code. But there may be far more sophisticated requirements to the build, like annpm install
or acompass compile
. The basic idea is that your site may have a deployment build process which will have to be replicated in the new location. - Configure database settings files. Normally the database credentials on one server will not be the same as on the other, so you’ll need to update the database settings as your CMS or platform requires.
- Transform URLs if necessary. Some CMSs like WordPress, Magento, and Shopware, have a tendency to bury multiple references to the site URL inside the database, so a transformation has to take place after all this is done. We wish they wouldn’t do this of course, but we have to live in the world we live in. Read about how to transform URLs. You’ll need to understand how to manage this in your particular CMS, as each does it differently. (Note that in Drupal, TYPO3, and Backdrop at least, incorporating a full self-referencing URL inside dynamic content is at least a party foul, probably worse, and it ruins standard deployments.)
Simplest deployment: Drupal through Drupal 7 – code, database, user-generated files, no build process
Up through Drupal 7, all you had to do to move a site in many cases was to check out the code, load the database from a database dump, and get the files into sites/default/files where they belong. In those days (and still on WordPress) that’s mostly what you have to do. Here is the process:
On the source server (can be DDEV or anywhere else):
- Dump the database. If the source project is in DDEV, this means running
ddev export-db --file=/path/to/sitename.db.sql.gz
. If you’re on a server or elsewhere, and assuming a single database, you can runmysqldump <databasename> | gzip >/path/to/sitename.db.sql.gz
. - Tar up the user-generated files:
cd <docroot>/sites/default/files && tar -czf /path/to/sitename_files.tar.gz .
. - Make sure your code has been checked in and pushed properly.
On the target server (which can be DDEV or anything else):
- Check out or update the code from your Git repository or wherever it’s stored.
- Copy your database dump to the server and load it into the database server using a tool like
mysql
, for examplegzip -dc sitename.db.sql.gz | mysql <databasename>
(or on DDEVddev import-db --src=/path/to/sitename_db.sql.gz
) - Copy your user-generated files tarball to the target server and untar it in the correct directory:
cd <docroot>/sites/default/files && tar -zxf /path/to/sitename_files.tar.gz
. (Or on DDEVddev import-files --src=/path/to/sitename_files.tar.gz
) - Edit your
settings.php
orsettings.local.php
(preferred) to point to the database you’ve loaded.
Drupal 8+ deployment: code, database, files, config, site build
Drupal 8+ is Drupal 7 with some extras, including copying the exported configuration and doing a composer install
On the source server:
- Do the steps you would have done for Drupal 7
- Determine what build processes are required for the site. compass? npm install?
- Export your configuration, for example,
drush cex
. The result will show you where the config was exported to. (This step is only necessary if configuration changes are to be migrated to the target server.)
On the target server:
- Do the steps you would have done in Drupal 7
composer install
(orddev composer install
if the target is a DDEV project.)- If there are other build steps discovered for the site, like an
npm install
orcompass
, add those processes. - Copy the exported configuration to the target server if necessary and put it in the configuration directory specified in your settings.php or settings.local.php (preferred). Then
drush cim
to import it. Best practices include checking to make sure config hasn’t been changed in the database on the target server.
TYPO3 deployment (based on TYPO3 v10)
TYPO3 is mostly the same as Drupal 7 plus a composer build, but there are often (generated) files on the local system that need to be checked into Git.
On the source server (can be DDEV or anywhere else):
- Dump the database. If the source project is in DDEV, this means running
ddev export-db --file=/path/to/sitename.db.sql.gz
. If you’re on a server or elsewhere, and assuming a single database, you canmysqldump <databasename> | gzip >/path/to/sitename.db.sql.gz
. - Tar up the user-generated files:
cd public/fileadmin && tar -czf /path/to/<sitename>_fileadmin.tar.gz .
. (The user-generated files must not be checked into Git.) - Verify that the
/config
and (optionally)/var/labels
directories are checked into your Git repository. These are directories which may have been created by sitebuilder actions, but they’re code. (Nothing else in/var
should be checked in.) - Make sure your code has been checked in and pushed properly.
On the target server (which can be DDEV or anything else):
- Check out or update the code from your Git repository or wherever it’s stored.
- Run
composer install
(on DDEV,ddev composer install
). If there are other build activities like ayarn install
, do those. - Copy your database dump to the target server and load it into the database server using a tool like MySQL, for example
gzip -dc sitename.db.sql.gz | mysql <databasename>
(or on DDEV,ddev import-db --src=/path/to/sitename_db.sql.gz
) - Copy your user-generated files tarball to the target server and untar it in the correct directory:
cd sites/default/files && tar -zxf /path/to/sitename_files.tar.gz
. (Or on DDEV,ddev import-files --src=/path/to/sitename_files.tar.gz
.) - Edit your
public/typo3conf/LocalConfiguration.php
orpublic/typo3conf/AdditionalConfiguration.php
(or.env
file, preferred) to point to the database you’ve loaded. If the target is DDEV, it will already take care of this for you.
From DDEV to Pantheon
If you’re deploying to Pantheon.io you can use the web interface to upload the database and files under “Database / Files” → “Import”. Run ddev export-db --file=/path/to/<site>_db.sql.gz
for the database and cd <docroot>/sites/default/files && tar -czf /path/to/<sitename>_files.tar.gz .
to create a files tarball and upload them. Advanced users can also use the “terminus” tool, which is bundled in the web container and already authenticated if you’ve done a ddev auth pantheon
with our integration. So ddev ssh
and use terminus to upload.
Complexities and Alternatives
There is no standard for deployment or moving sites, and nothing will replace your team’s knowledge of the site and the build process.
- Some teams prefer to do the build on a build machine (or in CI, or on a dev machine) and check in or push the resulting artifacts. For example, some teams will do a
composer install
and then check in the vendor directory and related artifacts.
Resources:
- OSTraining has a free YouTube class on Moving a Drupal 8+ Site. Highly recommended.
- Many, many agency deployment strategies are home-grown and require custom scripts to push things back and forth. There are examples of scripts like this in ddev-contrib, see Dump and deploy SQL from/to remote servers and Fetch Production DB from remote server.