How to Run Multiple ExpressionEngine Websites from One Set of Core Files
At Rocket Media, we use a git submodule and lots of symlinks to separate the ExpressionEngine core files from the rest of the site-specific files. Then when it’s time to update, we check out the newest version branch and follow the appropriate EE upgrade steps.
Our main intent is to separate all EE core files from site-specific files so we can reuse the same set of core files to power multiple sites. This makes handling bug fixes and updates a bit easier, and keeps your site files more organized. The end goal is to use a git submodule to manage ExpressionEngine core files separately from the rest of your project files, but I’m not going to cover that part. The purpose of this article to walk you through the process of separating the core EE files so they’re reusable from site to site.
So if that interests you, let’s begin. There are a lot of separate pieces to this puzzle, so if things seem disjointed or confusing while you’re following along, hang in there! Once all the pieces are in place the full picture should become clear.
For the purpose of this article I’m assuming you know a few things:
- You’re familiar enough with the command line to create symbolic links and set folder permissions
- You’re familiar with the master config from Focus Lab LLC.
- You have a web host with git and SSH access, and you have access to the folders at least one level above your webroot.
- You’re going to be working with more than a few EE sites for an extended period of time (otherwise what I describe below probably isn’t worth the effort)
And to make all the work you’re about to do truly worth it, it would help if you know:
- How to set up a git repo
- How to set up and work with git submodules
Before we get started, make sure you’re familiar with the standard EE directory structure and that you have a working copy of ExpressionEngine installed. I’ll also assume that you have the master config from Focus Lab LLC integrated into your EE site and that you have your project set up and functioning as the master config docs suggest:
├── config # master config files ├── httpdocs # or public_html (webroot) | ├── images | ├── themes | ├── admin.php | └── index.php └── system # EE system files
Now we’re going to move a bunch of things around. You can either clone the repo which contains the final folder structure (without the EE files), or start with a fresh project (as defined above) and follow the step-by-step instructions. The final product will look like this:
├── ee | ├── config # master config files | ├── eecore # core EE files | | ├── images | | ├── system | | └── themes | ├── template_files # EE template files | └── third_party_addons # EE addons └── httpdocs # document root for webserver ├── themes # EE themes ├── uploads # all content uploaded from the control panel ├── admin.php └── index.php
Let’s get started.
- First, create an
eefolder above webroot to hold all of the ExpressionEngine files.
- Move the
configfolder in there and set up folders for EE template files and third-party addons. You could also create any other folders you might need for snippets or Stash files.
- Next, move the
- Now, create a copy of the
- Finally, create an
Modify your paths
The first thing we’ll need to do is update your
database.php files in
ee/eecore/system/expressionengine/config/ to point to the new location of the master config files. Look for at the bottom of those files for the line that requires the config and replace with:
require $_SERVER['DOCUMENT_ROOT'] . '/../ee/config/config.master.php';
You’ll also need to update the
httpdocs/admin.php. That should be:
$system_path = '../ee/eecore/system';
Now we need to modify a few paths in the
config.master.php file. The goal here is to tell EE how to access the core and third-party themes. Core themes are those for the control panel, the wiki module, profile themes, the built-in site themes—basically any themes that ship with EE. Third-party themes are those that support third-party addons. So…
- Change line 96 to:
$images_folder = 'uploads';
- Change lines 105 and 106 to:
$env_config['theme_folder_path'] = $base_path . '/themes/core/'; $env_config['theme_folder_url'] = $base_url . '/themes/core/';
- Then add these lines directly after line 106:
$env_config['path_third_themes'] = $base_path . '/themes/third_party/'; $env_config['url_third_themes'] = $base_url . '/themes/third_party/';
- Now, uncomment line 118 and change to:
$env_config['third_party_path'] = $base_path . '/../ee/third_party_addons/';
This tells EE that it won’t find third-party addons in the default location: (
system/expressionengine/third_party/). Remember, third-party addons are site-specific, so we want those in ee/third_party_addons/.
- Finally, near the bottom of the file (line 237), where we require the environment-specific config, update that path to point to the new location of our master config files:
require $_SERVER['DOCUMENT_ROOT'] . '/../ee/config/config.' . ENV . '.php';
Now if you access your control panel, you should see the login page but all the styles will be missing. We’ll fix this in a moment.
ExpressionEngine core files
Let’s take a closer look at how we arrange the EE core files.
├── eecore │ ├── images │ ├── system │ └── themes
We want to keep the contents of this folder looking as much like a freshly unzipped EE install as possible. This way when it will be very easy to prepare new EE versions for this setup. At this point, we only need to make one change to these core files.
- Delete the
- Replace it with a symlink:
$ ln -s ../../../httpdocs/themes/third_party
Since we’ve already told EE where to look for third-party themes (in
config.master.phplines 107–108) this step isn’t strictly necessary, but we’ll do it to accommodate older addons that don’t look for a config value for their theme path.
The folder structure now looks like:
Okay, there’s still more to do.
Up to this point we’ve set up our project folder structure, modified config paths so ExpressionEngine knows how to find things, and configured our
eecore system files so they’re reusable across multiple sites. The final step is to set up a bunch of symlinks in the
Note: we could have left the
admin.php files in
ee/eecore/ and just created symlinks in
httpdocs/, however we’re not. I don’t know why, it just feels wrong.
Remember back in
config.master.php, line 105–106, we told EE to look for core themes in
/themes/core. Let’s actually create that location.
- Delete all the folders in
- Add a symlink called
corepointing to the default themes in
$ ln -s ../../ee/eecore/themes core
themes folder structure should now look like:
└── themes ├── core -> ../../ee/eecore/themes └── third_party
Now if you access the control panel, it should appear as normal, with styles intact. But we’re not done yet. Remember that
uploads folder we created? Now it’s time to set that up.
To keep things organized, we’re going to store all user-uploaded content in a single folder and create symlinks back to our EE core files where necessary. And for the sake of simplicity, we’ll leave the default EE images like smileys and default avatars grouped in with these files.
- First, copy all folders inside
- Delete the
httpdocs/uploads/smileysfolder and replace it with a symlink:
$ ln -s ../../ee/eecore/images/smileys
- Next, delete
httpdocs/uploads/avatars/default_setand replace it with a symlink:
$ ln -s ../../../ee/eecore/images/avatars/default_set
- Finally, give all these folders write permissions with something like
$ chmod -R 777 uploads(run from within
The folder structure should now look like:
uploads ├── avatars │ ├── default_set -> ../../../ee/eecore/images/avatars/default_set │ └── uploads ├── captchas ├── member_photos ├── pm_attachments ├── signature_attachments ├── smileys -> ../../ee/eecore/images/smileys └── uploads
You’ll notice there is a
httpdocs/uploads/uploads folder which is where you could configure your additional file upload locations in EE. At Rocket Media, we usually rename this to
client and use that as a single file upload location or we configure multiple subfolders within the
client folder. Again, the idea is to keep all user-uploaded content in a single place.
And with that, we’re done!
As I mentioned at the beginning, the end goal of all this is to manage the core files in their own repo. At Rocket Media we manage the core files with a git submodule called
eecore that is composed of different branches corresponding to the EE version number, e.g.
2.7.3 etc. It’s then very easy to update EE. Simply pull into your project the latest version and follow the appropriate upgrade steps. We’ve also found it useful when we need to apply a bugfix to the core files. We apply the changes to
eecore, then run a git pull on the submodule for all sites affected by the bug. When a new version of ExpressionEngine is released there is a bit of work to prepare a new branch, but it’s work you only have to do once.
I hope you found this article helpful. Let me know if you have any questions or suggestions by sending me a comment.