CMS Showdown: Nginx, Ghost, PHP and Phalcon

By Bruno Skvorc

CMS Showdown

  • CMS Showdown: Nginx, Ghost, PHP and Phalcon

Back in January, I made it one of my New Year’s resolutions to walk 4000 kilometers for the sake of fitness. I’ve been documenting this virtual journey (which is taking place on a DIY treadmill desk), on a Ghost deployed blog.

My Ghost subscription has since expired, and due to a severe lack of even the most basic CMS features, and their lack of PayPal support, I redeployed my own instance on DigitalOcean. You might be wondering why I’m writing about Ghost on a PHP oriented channel – this series will be a showdown of all the various PHP based CMS’ I can find, benchmarked against each other and against Ghost, as I look for the next best alternative.

The setup

Since my DigitalOcean droplet already runs Nginx as a reverse proxy for the blog, I’ll also be deploying all the CMS’ on that same installation, each on its own subdomain. If I, for example, try out WordPress (I won’t be – WP is the only one I won’t be testing), it will be accessible live at The default www subdomain will still serve the Ghost-based blog.

The server will also have TLS enabled, because it makes sense. I’ll be making sure I optimize all the installations to the best of my knowledge, and will be taking input from everyone on what else to do to to milk the apps for all they’ve got. Using app performance monitors like NewRelic and AppDynamics isn’t out of the question either, and all finished integrations will be perfomance audited. I intend to make this a community effort, and would like tips and input from as many sources as possible.

I’ll be using Nginx on Ubuntu 12.04, with PHP 5.5. Note that as soon as PHP updates to 5.6, the environment will be updated – there’s no point in using outdated software. Likewise, as soon as Ubuntu 14.04 is released, and is properly vetted by people capable of properly vetting it, we’ll be moving to that LTS version instead of 12.04. The upgrade procedure will be thoroughly documented when time comes.

The actual benchmarking will happen on my local SSD-powered machine, in a separate instance of an identical Vagrant box for each installation. This is so the tests can be performed on an identical server under identical conditions every time. Apache Benchmark will be used as the request bombing app. The first benchmarks will happen when we have at least 5 CMS installed and running both live and locally.

I’ll also be writing a custom data importer for all my 4kk posts for every CMS, so the full data is there and doesn’t need to be faked. These importers will be open sourced and you’ll be able to use them to export your Ghost data into any CMS we cover here.

If you’d like to fully follow along on your own DigitalOcean droplet, feel free to open an account via my referral link. Then, pick the basic server with Ubuntu 12.04. I picked a tier 2 droplet, the one with 1GB of RAM, purely due to the fact that we’ll be running so many apps on one server. If you don’t intend to follow along with every CMS, feel free to pick the smallest one.

If you’d like to install Ghost as well, you should follow this tutorial. Apply it to the most up to date version of Ghost, everything else remains the same.

Installing PHP on Nginx

On Ubuntu, we use the ondrej PPA to install the latest PHP without having to build from source. Ondrej’s versions are always at most one minor version away from the latest (e.g. 5.5.9 vs 5.5.10) and much simpler to install than the fully manual procedure.

sudo add-apt-repository ppa:ondrej/php5
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install php5-fpm php5-dev

Modify your php.ini file for timezone, upload file size settings, etc. Don’t forget to activate OpCache at the end of the INI file if you’re using PHP 5.5+ like I am. It makes a world of difference, performance-wise.

Let’s define a subdomain to test our PHP on now. We’ll make sure the URL outputs phpinfo();. Naturally, you should replace all further instances of 4kk with your own domain name, or the IP address of your droplet if that’s what you’re using for testing.

Setting up a virtual host on a subdomain

I have created a non-root user for my droplet. DigitalOcean uses root as the default, but I tend to disable both root login and all password logins when using SSH, and instead create a key-only user through which I can then perform sudo commands on my server. I’ll assume you’ll do the same – for security’s sake, you should. Make a new user on your server, and follow this tutorial but for that user – not for root. You don’t want to be remotely logging in as root, ever.

In my case, this user is called “swader”, so I’ll be putting all the PHP apps we’ll be building in this series into the /home/swader/apps/php parent folder. Create it if it doesn’t exist, and add another subfolder: dev. Apply your own username to the path in all examples below.

mkdir -p ~/apps/php/dev

In this folder, create the standard phpinfo() file. Call it index.php:


Now we need to create a new virtualhost for Nginx that looks for PHP files in that folder. This is just a copy of the default Nginx Vhost template, we’ll be fine tuning Nginx later.

server {
        listen; ## listen for ipv4; this line is default and implied
        listen   [::]:80 default_server ipv6only=on; ## listen for ipv6

        root /home/swader/apps/php/dev;
        index index.php index.html index.htm;

        # Make site accessible from

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ /index.html;
                # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules

        #error_page 404 /404.html;

        # redirect server error pages to the static page /50x.html
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
                root /home/swader/apps/php/dev;

        # pass the PHP scripts to FastCGI server listening on
        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

                # With php5-cgi alone:
                # With php5-fpm:
                fastcgi_pass unix:/var/run/php5-fpm.sock;
                fastcgi_index index.php;
                include fastcgi_params;

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        location ~ /\.ht {
                deny all;

Accessing will now produce the phpinfo() screen:

Our main domain now displays Ghost, and our subdomain displays the PHP content of the subdomain’s folder.


Seeing as one of the CMS we’ll be testing will be PhalconEye, we’ll need to install Phalcon as well. Best get it out of the way immediately. We’ll make a tools directory in the home folder of our user, and download and install from there:

mkdir ~/tools
cd ~/tools

Then, we follow the standard installation procedure.

git clone --depth=1 git://
cd cphalcon/build
sudo ./install

After you add the line to your php.ini file(s), don’t forget to restart php5-fpm, as it’s running as a separate process in the case of Nginx, not as an Apache submodule which restarts every time Apache does, too:

sudo service php5-fpm restart
sudo service nginx restart

Phalcon should now be installed and you should be able to find it on the previous phpinfo dump.


In this part, we configured our DigitalOcean droplet, linked to some Ghost installation tutorials, and installed PHP and Phalcon. We also set up a subdomain on which to test our initial PHP file, to make sure everything works as intended. If you’d like a more in-depth look at how HTTPS was set up, please comment below – I’d be happy to write a dedicated tutorial to getting HTTPS running on Nginx. In the next part, we’ll be looking at our first CMS candidate.

  • lubosdz

    This will be interesting stuff. However, I did not quite understand why installing Phalcon framework for the purpose of testing various CMS systems? Perhaps I missed some point?

    • MilSF

      He’s testing PhalconEye which is built on Phalcon.

      • Bruno Skvorc


  • MilSF

    You might want to update your Phalcon install. 1.3.0, with significant improvements and speedups, dropped a few days ago as the new GA version.

    • Bruno Skvorc

      Yep, all software will be at the latest version.

  • Felipe Lavín

    Ok, I was hoping someone else would come up with this question, but since it seems nobody else cares… why won’t you test WordPress? I’m guessing that’s because there’s so many variables like themes, plugins and many configuration and optimization alternatives that nobody would ever jus take it… is it?

    • Bruno Skvorc

      No, because I genuinely think it’s bad software and no one should use it for any purpose, not even for small personal blogs.

      • thedigitalmonk

        I understand you have a personal bias against WordPress but don’t you think it is selfish to not review it considering that a lot of people who read articles here (myself included) use WordPress? You have allowed articles on WordPress here then why this blind hate?

        I feel it is highly unprofessional to force your personal opinions down the minds of novices like me considering you are a influencer in your field and people like me really look forward to what to you say and do.

        I for one am looking forward to what you have to say. It’s not like I am a WordPress evangelist or something but I just happen to have come across it first as a blogger and then felt I could a lot more and went over to the developer side. I don’t mind being called an instagrammer level of PHP developer just because I use WordPress. Being a front-end developer I am not really concerned with the core. So far it has suited my purpose well enough. I have read many (yours included) comments on how bad WordPress is but have never been able to grasp the seriousness of it. I just don’t understand why it is as bad as you guys claim it to be. And it’s not like I don’t want to know. I do but nobody seems to be discussing it at a level I understand. For example if some one could compare how a loop is written in WordPress and Phalcon maybe I can decide for myself how much is at stake? Don’t you think that is a better way to help some one with your views than just using subjective terms like ‘bad’.

        I recently spoke to an employee of Automattic who was at a WordCamp recently. I asked him about your accusations and he said that rewriting the core as you have suggested would satisfy a very small group of people while as a product Matt has to think of what will empower his core audience- bloggers and content marketers. He has this minimum 20% rule. If 20% of his intended audience feels that something has to be added/changed he pushes for it. So they have their priorities too.

        My intent is not to insult you and if I have done that in any capacity I would like to apologize now itself. It’s just that I really look forward to your articles and opinions and it’s just in this matter that I have been a bit disappointed by the way you handle views.

        • Ernesti Kyöstilä

          Please note: I am writing as a web server administrator.

          It was only two weeks ago that an attack dropped the blog of a European minister. It made use of WordPress vulnerability or vulnerabilities. This is one of the reasons for us to forbid the use of WordPress our web servers. If somebody installs it it is a violation against TOS. There have been numerous security problems with WP ever since its launch and there is no end for them in the horizon.

          Knowing these threats is not an opinion. WP is ‘bad’ as long as thing like this happen and the ‘seriousness’ is there for everybody to see. There are other factors as well (like bad memory and database usage) but they are getting better from the dismal state just over a year ago.

          • ChrisChristoff

            That’s the most ludicrous reason I have ever heard. Your reasoning for not allowing WordPress is because there was a vulnerability. My guess is likely he was running an old version or its been patched already. But more to the point, do you not allow any applications with vulnerabilities? There’s security vulnerabilities in every single web server operating system. Are you banning yourself as well? Apache, nginx, IIS, all have known vulnerabilities. There’s a difference between good vulnerable software and bad vulnerable software. WordPress, which is of the good variety, get a vulnerability report, and patch it immediately. Your OS on the other hand, does not. Every application on the web is vulnerable. If someone had enough time, I’m sure they could find significant vulnerabilities in Joomla!, Drupal, Ghost or any other PHP based CMS,

            It’s time your criteria and thinking got a significant overhaul.

          • Ernesti Kyöstilä

            We do not allow any suspectible applications. These include self-installed WP, Joomla, Drupal and others. WP and Joomla do not update automatically. Who updates them if they are installed by customers? Not us, we do not have time for that. That is why they are forbidden. We have had our share for vulnerable open source junk.

            We know what we do: We have seen the code. We have tested all you mentioned. Drupal is possibly the safest but it is a horrible CPU and memory hog and its proramming model comes from the 1980s. We can show the performance numbers in case you do not believe. WP is a bit better but it uses database in a most idiotic manner.

            There are modules for WP and Joomla written by total morons. We have seen calendars that make a search engine walk 1000 years to the future one month at a time creating huge numbers of HTTP requests. We have seen unsecured input for forms ready for all sorts of attacks. And so forth. A normal user can install those modules but has no idea about the problems.

            Joomla and WP are so common that there are legions of attackers concentrating on them, trying to find vulnerabilities. We see that from the logs. They have NO idea about our CMS so it is damn difficult to find out how to attack it. So far zero intrusions in almost 10 years.

            If a user does not want to use the safe CMS we provide he can go somewhere else. We do not need them. Very few actually do. They respect the security, you see. 100% uptime without rounding.

        • Bruno Skvorc

          It’s not like I’m refusing to review it, I already did – I’ve used it in many scenarios and contexts, and based on this experience I am recommending people NOT use it.

          You can’t compare loops in Phalcon vs WP, because that’s microbenchmarking and has no basis in the real world. What you can compare, however, is the level of bloatware that gets included in WP vs other CMS, the differences in quality of code, the speed of the back end, the scalability, the security, and other things that become important after a certain number of active monthly visitors, but are unnoticeable at the level of a personal blog.

          This isn’t blind hate, and I’m sorry I’m coming across like a thoughtless hater – I’ll definitely take what you say here into consideration and speak out against WordPress in a more factual manner in the future, linking to resources proving its inferiority. I’ll be more careful, and I apologize.

          I also understand the attitude of the WP core devs – if my business depended on an audience that’s, in its majority, completely unable to adapt to modern PHP approaches, I too would refuse to update my software because updating it means destroying my business. But I disagree with their approach of playing it (too) safe. Old versions should be deprecated, long-term-support versions should be introduced, and major versions should introduce breaks in backward-compatibility, like in any widely deployed software. It is their attitude towards software development that makes me call them amateurs, not just the horrible level of quality in their code.

          Time and again I said I support people doing small business websites and blogs in WP – it’s perfect for non technical people, and people who want a quick buck. But it’s also a major component in holding PHP back, and gives PHP a bad name through horrible practices.

          To sum up, no, I won’t be looking at WP in this series. I think it’s awful, and I want people to stop using it. If I can convert even one person through my rants, I’ll be happy. But I will do my best to make sure that, in the future, I link to facts that support my claims of WordPress’ awfulness.

          • thedigitalmonk

            Thanks for replying Bruno. Appreciate how you took criticism so gracefully. Looking forward to the rest of the series. I am teaching myself PHP OOP from Any recommended resources before I get started with Phalcon and the like?

          • Bruno Skvorc

            Thanks for taking the time to write such a detailed comment, I wish more people would participate as actively.

            I recommend jumping into the fire after going through the basic tutorials, like I say here:

          • ChrisChristoff

            It should be noted, WordPress doesn’t keep backwards compatibility code in forever. When, for example, WordPress was upgraded to require 5.2, all <5.2 code was removed. Right now, a very very large percentage of hosts still run 5.2. Therefore, alot of 5.2 code can't be dropped. That's not really WordPress's fault, but the host's fault.

          • Bruno Skvorc

            Right, but these versions should be publicly deprecated and warned against, as with any proper software. There should be an outreach and a push IN the WP community BY the WP community to not only abandon the (more) horrible versions, but also to vote for PHP upgrades on various hosts. The hosts won’t ever change unless we want them to. With VPS as cheap as $5 per month these days, there is absolutely no reason to use a shared host anyway.

          • ChrisChristoff

            They are. Versions that are move than 2 x.y release behind are no longer supported. In 3.7 an autoupgrader for core was added to automatically update to new releases, like Chrome does. Further, hosts are abandoning PHP 5.2, it’s just not happening overnight, when millions of sites run it. If you look at the percentages for hosts running 5.2 it’s on a steady decline.

            Whether to use a shared host or not isn’t a valid question. I use dedicated servers, but thats beside the point. Unless you’re going to personally educate every single person out there one at a time what a VPS is and why you should use it, it’s a moot question. Most people on the web simply go into Google and type “cheap web hosting” and thats what they use, because they aren’t familiar with hosting and different levels of hosting, they just know they need that.

  • Aleksander Koko

    I think its better that you actually decided not to test wordpress . For my opinion its too old, and very bad in its architecture. Its bad practice. I think i gone have an eye on phalcon eye. Phalcon will be the next big thing on php . Or it is by now.

  • David Julian


    • Bruno Skvorc

      Might happen.

  • Dave Slutzkin

    No SPDY, Bruno?

  • Oz

    which php.ini should add line?

  • Mijo Džalto

    Very interesting post Bruno, but since this article is written a year ago, I wonder if there are more articles in this CMS Showdown series? Thank you.

Get the latest in PHP, once a week, for free.