Multi-server Setup for EE 2
by Matt Weinberg
Now that ExpressionEngine 2 is at a non-beta release, and EllisLab has published a timeline for phasing out new distributions of ExpressionEngine 1, we at Vector Media Group have been choosing EE2 for more and more client projects. One of the first difficulties we ran into when we started using EE2 was the same one we ran into when we started using EE1 many years ago—how to handle our multiple server environments gracefully.
At Vector (like many other development shops) we’re typically concerned with three primary servers: the local machines we use for day-to-day coding, the staging site where we deploy releases for the client to see and build new features, and the production server where the live site actually exists. These machines all typically have completely different URLs and file paths. While one common approach is to keep different config.php files on each server, we’ve found a single dynamic configuration file works better for our workflow.
We’ve also added a lot of settings to config.php that aren’t usually in there. We find that it can be useful to use a file for these instead of having to login to the backend. (Remember that anything set in config.php will override whatever’s been set in the Control Panel.)
Let’s start with five quick notes:
- The file I’m editing is the config.php located in system/expressionengine/config1. This corresponds to EE1’s system/config.php file. It’s not the Config.php file located in the “core” folder.
- These modifications should be done after going through the actual ExpressionEngine installation. If you’re setting up a sandbox that you copy for each new site, go through the full installation on that before starting these modifications.
- If you are accessing your site in a subdirectory some of this may need to be modified (we always favor subdomains over subdirectories for development). The same goes for masked CPs.
- In some cases I’ll be using PHP that’s more verbose than strictly necessary. We prioritize human reading clarity, but feel free to adjust as you see fit.
- Some of the path options here were originally based on this article about EE1 from Kenn Wilson. We’ve made some major changes and additions, though.
Site-wide Settings
Start by opening up your config.php file; the section we’re concentrating on is in the first 25 or so lines—everything on top of // END EE config items. With one exception that I’ll mention later, you’ll never want to touch anything below that commented line.
I like to begin the file by declaring a few major site-wide settings and temporarily moving out some of the path configuration. Here’s my first section:
$config['app_version'] = "202pb01";
$config['install_lock'] = "";
$config['license_number'] = "";
$config['doc_url'] = "http://www.VectorMediaGroup.com/";
$config['is_system_on'] = "y";
$config['site_label'] = 'Test Site';
$config['cookie_prefix'] = '';
$config['allow_extensions'] = "y";
$config['hidden_template_indicator'] = "_";
$config['autosave_interval_seconds'] = "0"; # Disabling entry autosave
The first 3 lines are from the default. I’ve removed the next two — cp_url and debug because I’m going to set them later in more relevant sections. I changed the doc url to point to our domain because if clients need help, they’ll typically want to reach out to us instead of reading the docs. The next 3 — is_system_on, site_label, and cookie_prefix are all standard.
We’re now up to our first two major customizations. hidden_template_indicator allows us to changes the character that signifies a hidden template from its default (the period). Many file/FTP browsers default to hiding any file that begins with a period so we change it to the more lovable underscore.
autosave_interval_seconds sets the amount of time, in seconds, between each autosave of channel entry content you have open. Setting it to 0 disables autosave completely (the default is 60 seconds). We’ve unfortunately found autosaving buggy and confusing for our clients so continue to disable it on EE2 builds. This is a decision you should make for yourself.
At this point you’ll want to look down a few lines in your config.php file—past the // END EE config items part—and find $config[‘base_url’] = ‘’. Remove it; we’ll add our own in a second and don’t want our value getting overwritten.
Server Settings
Here’s the next section of our config.php. This section is the key to letting your site work across multiple servers. We start by setting a few variables that won’t be fed directly to EE but will be used as a base to build on further down.:
// Dynamic paths for cross-server compatibility
$protocol = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") ? "https://" : "http://";
$base_url = $protocol . $_SERVER['HTTP_HOST'];
$base_path = $_SERVER['DOCUMENT_ROOT'];
$system_folder = "system";
$images_folder = "images";
$images_path = $base_path . "/" . $images_folder;
$images_url = $base_url . "/" . $images_folder;
$config['index_page'] = "";
$config['base_url'] = $base_url . "/";
$config['site_url'] = $config['base_url'];
$config['cp_url'] = $config['base_url'] . $system_folder . "/index.php";
$config['theme_folder_path'] = $base_path . "/themes/";
$config['theme_folder_url'] = $base_url . "/themes/";
$config['tmpl_file_basepath'] = APPPATH . "templates/";
$config['emoticon_path'] = $images_url . "/smileys/";
$config['captcha_path'] = $images_path . "/captchas/";
$config['captcha_url'] = $images_url . "/captchas/";
$config['avatar_path'] = $images_path . "/avatars/";
$config['avatar_url'] = $images_url . "/avatars/";
$config['photo_path'] = $images_path . "/member_photos/";
$config['photo_url'] = $images_url . "/member_photos/";
$config['sig_img_path'] = $images_path . "/signature_attachments/";
$config['sig_img_url'] = $images_url . "/signature_attachments/";
$config['prv_msg_upload_path'] = $images_path . "/pm_attachments/";
First, we check if the current request is over SSL, set the base url using the current domain name, the base file path using the document root (typically your public_html or httpdocs folder), and then our system and main images folders. EE needs separate URLs and file paths for most image-related directories, so we add the image folder name to our previously set $base_url and $base_path to make our full image path and URL.
Most of the other paths here are self explanatory. We set the main site and control panel URLs, the theme and template information, and then cycle through the various image upload directories—emoticon, captcha, avatar, photo, signature image, and private message. Most need a URL *and* path. Remember that these are our settings; change this as necessary if you organize your folders a different way.
Debugging and Performance Settings
The last part of our customizations are to set some global debugging and performance options:
// Debugging and performance
$config['show_profiler'] = 'n'; # y/n
$config['template_debugging'] = 'n'; # y/n
$config['debug'] = '1'; # 0: no PHP/SQL errors shown. 1: Errors shown to Super Admins. 2: Errors shown to everyone.
$config['disable_all_tracking'] = 'y'; # y/n
$config['enable_sql_caching'] = 'n'; # Cache Dynamic Channel Queries?
$config['email_debug'] = 'n'; # y/n
“Show Profiler” and “Template Debugging” turn on those relevant outputs to logged-in Super Admins browsing the site. We’ve always found it far more convenient to set them inside config.php, where they can be easily turned on and off if the site’s having any trouble. Make sure to use “y” and “n” to toggle these.
The debug mode sets who sees PHP and MySQL errors that pop up on the site. We usually set it to “1” so our Super Admins can be aware of any problems.
“Disable all tracking” turns off items like online user tracking, template hit tracking, and channel entry view tracking. We rarely use these functions and so don’t want the processing and query overhead they add. On a similar note, “enable_sql_caching” corresponds to the Cache Dynamic Channel Queries preference in the control panel. Use this caching wisely; it can have nasty side effects with things like future entries and author_id=“CURRENT_USER”.
And, finally, “email_debug” is just a quick way to toggle the “Enable Email Debugging?” Control Panel preference.
Conclusion
That’s it—the config.php file we use on every ExpressionEngine 2 site we work on. It’s a standard part of our base sandbox install and saves a lot of headaches when developing and moving across servers. With it, no matter what server you’re running the site from, all the important paths will continue to work—and all you’ll have to worry about is copying the database.
1 Note: this path may be changing in EE 2.1 according to a recent EllisLab blog post, however, the key is to find it in the main expressionengine/config directory.
Email
Print
Post to Twitter
Post to Delicious
Ray Brown — 14:27 on 07.13.2010
Hey, Matt! Thanks for the tips. This seems like a natural progression from Ryan’s previous article and Jamie’s EECI2010 presentation. Thanks again for sharing!
Matt Weinberg — 16:35 on 07.13.2010
I appreciate the comment, Ray—and glad you liked it!
Nat — 22:39 on 07.13.2010
Great article. Just tried it when I upgraded to EE 2.1, and everything works fine, except for the tmpl_file_basepath setting.
Also, how do you handle file upload paths? Do you just use relative paths in the control panel?
Matt Weinberg — 00:28 on 07.14.2010
Hi Nat,
I didn’t have a problem with tmpl_file_basepath on my 2.1. Are you using a masked CP?
I do use relative paths, yes. They’re like this:
Server Path: ../images/content/article_pics/
URL: /images/content/article_pics/
Note the “..” in front of the server path.
Does that help?
Nat — 00:33 on 07.14.2010
Yes, that helps. Thanks.
I’m not using a masked cp, but I have moved my template folder outside of my system folder (the url is example.com/assets/templates/ ). Would that have something to do with it?
Matt Weinberg — 00:38 on 07.14.2010
Definitely. You’ll want to set it to something like:
$base_path . “/assets/templates”
Feel free to email me if you have any other questions. Matt at Vector Media Group dot com.
Nat — 00:40 on 07.14.2010
Got it working. I didn’t even think about that before. Thanks for your help.
Bob Monsour — 00:15 on 07.16.2010
Matt, this worked flawlessly for me. The only hiccup I had was cockpit error on my part and forgetting that in addition to copying the database, I had to change the hostname and cachedir in my database.php (certainly would’ve had to also change DB name, user, and password if they were different too). In my case, I had success moving from a locally based MAMP installation to a shared host at Dreamhost.
Matt Weinberg — 00:34 on 07.16.2010
Glad it worked well, Bob! I’m hoping to followup with a Part II for database.php. Using similar methods to the above we can automatically switch the database credentials being used while still only having one database.php. (With CI’s database groups this became a lot cleaner on EE2 than EE1).
Nic Plum — 12:48 on 07.19.2010
Do you have any experience / suggestions for trying to do something similar where there is the Multiple Site Manager and multiple sites?
Matt Weinberg — 13:56 on 07.19.2010
Hi Nic,
There’s a few ways you can handle it, but a lot of this should carry over without issue. Depending on your file structure and how you’ve setup config.php, path.php, etc… you may also want to write a few if/thens or switches in there based on the current hostname being accessed.
Sincerely,
Matt
Nic Plum — 14:17 on 07.19.2010
Matt - I’m not sure it’s that easy as each site/all sites can be accessed/controlled from any single one using the site switch i.e. without any change in the domain.
It works up until they change sites within the CP.
Matt Weinberg — 19:17 on 07.19.2010
Got it, I didn’t realize you were switching sites inside the CP.
You can always base it on something—is $PREFS->ini(‘site_id’) loaded by then?
If you’d like, shoot me an email at Matt at VectorMediaGroup dot com and maybe we can figure it out!
Stuart McCoy — 12:16 on 07.25.2010
How do you keep the content in the databases synced? This isn’t as important from the local to the staging or live servers but between the staging and live servers it could be very helpful to know. Leevi graham has a config.php file available to manage the same feat in this article with the exception of adding a fourth server. The dev has both a local and staging server while the client has a staging or production server and live server. If I add an article entry to the staging server in your example or the production server in Leevi’s case, how would I update the database on the live server other then copying/pasting the article once it’s approved?
Matt Weinberg — 15:50 on 07.25.2010
Hi Stuart,
Unfortunately this is a huge issue and there’s not an easy answer. MySQL syncing is a hard problem to solve. There are some non-EE specific software solutions, and you can do fancy things like just syncing changes to some tables (exp_channel_data, exp_channel_titles, exp_relationships, etc…) but it’s pretty complex.
I end up committing the SQL export to a non-public area in the repository and importing/re-exporting as necessary. I make any structural DB changes during slow times so I can work on templates in my local when necessary.
I’ve been looking into some of the MySQL syncing solutions but haven’t fell in love with any yet.
Sincerely,
Matt
Stuart McCoy — 06:57 on 07.28.2010
Thanks. That’s what I figured, and what I’ve been doing. You just have to be careful to not export/import the preferences from one to the next or you have a mess on your hands.
Matt Weinberg — 11:59 on 07.28.2010
Hi Stuart,
With regards to preferences, which are you referring to exactly? With most you can use my method above, combined with a switch on hostname or some other item, and keep them in config.php. Then you can import/export everything and not worry.
-Matt