If a web server is going to host many copies of one particular software application, it only makes sense to centralize as much of that code as possible. By that, I mean collecting most code from this application, and keeping it in one spot, rather than having a completely unique copy of the application for each website served.
A centralized web application means that application takes less disk space, fewer resources, can be more easily maintained, more easily backed up, and is easier to upgrade when new versions are released.
concrete5: Built for Centralization
When concrete was originally rebuilt and re-released as concrete5, one of the projectʼs absolute highest priorities was that it could be run as a centralized application. This meant several things:
- Most, if not all, code should be able to exist in one place, on a server, and power multiple websites.
- Plugin items like blocks, addons and themes should be centralized, powering multiple websites from one instance, as well as able to exist in a particular websiteʼs web root, for that one web site.
- Plugin items could have their view templates overridden at the site level, to allow extensive customization. The core, shared concrete5 libraries could then be upgraded, with no damage to the custom presentation code used by individual sites.
To do this, concrete5 places its core functionality, including core blocks, controllers, themes, classes, libraries and assets, in the “concrete/” sub-directory, while shipping an almost identical – and empty – filesystem one level up. While the exact details of how this works arenʼt germane to this document, suffice it to say that items placed within the empty directories will typically override those in the core, leaving the core to be swapped out entirely with a new version, when an upgrade is available.
This is how concrete5 was built, and it allows people lots of flexibility in how they want to extend it, without worrying about forking the core with custom code. But it also opens the door to the purpose of this document: centralization. The following steps detail the best way to take a single, existing concrete5 installation, and turn it into a centralized install. Once thatʼs done, Iʼll cover the creation of additional sites, as well as how to upgrade these sites when new versions of the software are available.
Step One: Download concrete5 and install it somewhere.
This is pretty straightforward: download the most recent copy of concrete5 and install it somewhere. Make sure you can get it up and running. Once thatʼs the case, youʼll have the concrete5 filesystem within a particular virtual hostʼs web directory (likely something like /home/youruser/public_html or /var/www/vhosts/yoursite.com/html/). Youʼll also notice the concrete/ directory that appears within that webroot. These are the core files.
Step Two: Move the concrete/ directory to a proper shared location.
Choose a Location This is a matter of preference. Any location on your server is appropriate, provided it is readable by the web server user, but we typically try to follow Linux conventions. For example, on our server, weʼve created a directory named
Move the concrete/ directory into this location, inside a directory that denotes its version. Within this directory weʼve placed different versions of concrete5, so that the directory looks like:
Additionally, weʼve setup a symlink within this directory, which weʼve named
We symlink this directory so that it points to the latest stable version that weʼre going to be running multiple sites from. So, if we were going to do that with version 5.1.0, weʼd do this with this command:
ln -s /usr/local/share/concrete5/concrete5.1.0/ ./concrete-latest-stable
Itʼs important to note that we are included the “concrete/” directory inside these version- named directories. This is due to the way that concrete5ʼs include path works. There doesnʼt need to be anything else inside these directories.
Step Three: Make your existing concrete5 installation use this concrete directory
This can be accomplished in several ways:
Method One: Symlink the concrete/ directory into the siteʼs webroot.
By symlinking the concrete/ directory from your central location into the siteʼs webroot, you can run the site as though the full assets were present in that location.
cd /path/to/your/webroot/ ln -s /usr/local/share/concrete5/concrete-latest-stable/concrete ./concrete
While this is a very popular method of centralizing concrete (and is used by us in our development environments daily), there are some things to keep in mind. First, this alerts users to the presence of a concrete/ directory in their web root, when that is something they should definitely stay out of. Granted, with a properly setup filesystem, users wonʼt be able to modify files there, but it might be advisable if they didnʼt even know they existed. Secondly, this process will have to be repeated every time a new site is setup, and it is definitely not as centralized as storing all of these mappings in one location, like an Apache configuration file. If this location ever needs to be changed, many symlinks will need to be unlinked and rebuilt.
Method Two: Modify the virtual host section of your web serverʼs configuration file to point to this location.
You can add two lines to the section of your web serverʼs configuration file that defines the particular virtual host. I will use Apacheʼs VirtualHost section as an example:
Alias /concrete /usr/local/share/concrete5/concrete-latest-stable/concrete
php_value include_path ".:/usr/share/pear:/usr/local/share/concrete5/concrete-latest-stable"
This method is great because, assuming you store all your virtual hosts in one file, it centralizes not only the concrete5 code base, but also all the rules about how that code base operates. You need only modify your Apache virtual host configuration file to
change which alias points where, and which site operates off of which concrete5 codebase.
The method still isnʼt perfect, however. If you ever find yourself modifying your paths, you will have to change aliases and include_paths everywhere in this file (although that wouldnʼt be that difficult to do.)
Method Three: Modify the global section of your web serverʼs configuration point to this location.
This method is a variation on the previous method. Instead of placing the alias and include path directives within each virtual host section, place them globally inside your httpd.conf file. Just copy the Alias and php_value lines above and place them in the global context.
The strong benefit to this method is that it truly allows the centralization of these concrete5 rules in one place. All virtual hosts and websites hosted through Apache will honor these rules, and your concrete5 core libraries will be available in a global include path. (Similarly, you can setup your global include path within php.ini to include your concrete5 path.)
A word of warning about this method: this method is great if you are certain that all your sites will forever run the same version of concrete. For example, if youʼre setting up several servers, and on Server A you will keep versions of sites that run the “latest stable” version of concrete, and Server B you will keep versions of sites that run bleeding edge concrete (for purpose of testing upgrades) then this may work well. However, if you ever intend to mix and match sites on the same box with multiple versions of concrete5, this method will not work.
At this point, your existing site should work as it always did, but without its own version of the concrete/ directory.
Adding More concrete5 Sites
To add another concrete5 site, simply make a copy of your first siteʼs files, into the new webroot for the new site. Make sure to remove any custom modifications to blocks/, controllers/, etc... Then, make sure that your new site is setup to used the shared concrete5 source that you created in step 3 above. Access this new site in a browser, and proceed with installation.
Using a Skeleton Directory
We employ WHM on our reseller servers, which is popular server management software. This software has a skeleton directory feature, which enables us to place certain files and directories into a directory, which is then automatically duplicated into the web root of newly created accounts. This system is perfect for centralized concrete5: simply copy your websiteʼs root directory structure (as well as index.php) into your skeleton directory, and these items are duplicated out every time you create a new account on your server.
You donʼt need to WHM to accomplish this. Skeleton directories can be employed by any kind of scripts that you use to provision accounts on your servers.
Note: additionally, make sure your provisioning process preserves permissions, as the files/ directory and config/ directory need to be writable by the web server, but nothing else should be.
At this point, weʼve centralized concrete5 and can use it to easily create new sites. What happens when a new version of concrete5 comes along? This is typically how we handle this process.
Before You Start
Always ensure you have a valid backup of each shared concrete5 installation, including its custom files, and its database.
Step One: Unpack the new versionʼs concrete/ directory to your shared location.
Letʼs say our server runs concrete 5.1.1, and we want to upgrade our sites to 5.2. We download 5.2 to ~/downloads/concrete5.2.0/. Then we move the concrete/ directory to the shared location:
mkdir /usr/local/share/concrete5/concrete5.2.0/ cp -a ~/downloads/concrete5.2.0/concrete /usr/local/share/concrete5/ concrete5.2.0/concrete
Step Two: Point your concrete-latest symlink to the new concrete version
To do this quickly and avoid any downtime for websites, try the following operation, which couples the unlinking process with the creation of the new symlink
cd /usr/local/share/concrete5/ unlink concrete-latest-stable; ln -s /usr/local/share/concrete5/ concrete5.2.0 ./concrete-latest-stable
Step Three: Run the upgrade routine for all shared concrete5 installations.
At this point, all your concrete5 installs are now pointing to a new shared codebase. While simply pointing these sites to the new files will frequently be enough to upgrade a site, the siteʼs upgrade routine must also be run. If it is not, certain features in the new version may not work properly, and the sites themselves will present notification messages to the end user, asking the user to upgrade their databases.
The need to upgrade the database is why the official concrete5 upgrade instructions conclude with asking the user to visit this script:
This script, when run, will automatically re-parse the official database schema for both the core and the core blocks, and automatically apply any changes that may have occurred in the new version, as well as clearing the siteʼs cache files. Any new functionality that requires database changes to be recognized (including new dashboard pages, new blocks or themes) will also be installed by the upgrade process.