Fixing Concrete5 Gateway Timeout

Apparently this seems to be an issue with this popular Content Management System, something which should be definitely addressed by the development team looking at the amount of threads in their forum related to this issue. Also, it doesn’t seem to be something new on the scene as many are as old as six years: come on guys, your software looks too good not to fix this!

So, here a quick summary: if you try to install Concrete5 (currently latest stable version is 8.3.2), unless you have a super fast computer you’ll end up with a 504 Gateway Timeout error during the installation phase, specifically during the database initialization sequence.

The reason for this error can be associated to two factors:

  1. the database initialization process takes a gargantuan amount of time (I love the word gargantuan, don’t you?)
  2. the database initialization process is executed all in one, remotely activated, operation

While I can’t say much on point one, as optimizing on that front might be difficult, surely something can be done on point 2, like splitting the operation in multiple steps. But how doing that operation in multiple steps might help?

Well, those steps are client initiated via a web browser, which asynchronously calls a URL that gets mapped to a PHP call: here comes the culprit.

I’m far from being a PHP expert, I actually try to avoid PHP as much as I can for personal tastes, but it sounds logic that PHP imposes a maximum execution time per request, to prevent a badly written page to hang an entire system I guess. As the database initialization sequence is mapped onto one single PHP page, that step must complete within the allowed timeframe otherwise the request is killed and the initialization fails.

You can find plenty of solutions for such a problem, but in my case none worked as I’m using Docker to create a Nginx + PHP-FPM + Concrete5 container.

So my solution was to extend the allowed maximum execution time for the URLs used by the installation process, with the intent to disallow such exemption once the process is completed. To do so I had to google a lot (as I said, I’m not a PHP or Nginx expert) and here is what I ended with:

server {
    log_not_found off;

    listen 80;
    server_name _;
    root /var/www/concrete5;
    index index.php index.html index.htm;

    location ~* .(gif|jpg|jpeg|png|ico|wmv|3gp|avi|mpg|mpeg|mp4|flv|mp3|mid|js|css|wml|swf)$ {
        expires max;
        add_header Pragma public;
        add_header Cache-Control "public, must-revalidate, proxy-revalidate";

    location / {
        try_files $uri $uri/ /index.php$request_uri /index.php;

    # php-fpm configuration
    location ~ .php$ {
        try_files $uri =404;
        fastcgi_pass unix:/var/run/php-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 256 4k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;

        # extend install scripts timeout: remove after install
        fastcgi_read_timeout 1200;

Now, if you believe 1200 seconds is an absurd amount of time, here are the timings I’ve collected while performing the Concrete5 installation in a DOcker container on my UDDOx86 :

  • install_permissions 34.29 sec
  • install_attributes 20.55 sec
  • install_blocktypes 1.93 min
  • install_database 3.76 min
  • install_permissions 31.75 sec
  • install_blocktypes 1.91 min
  • install_dashboard 2.50 min
  • import_files 29.69 sec
  • install_content 3.01 min


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s