Symlinks with Nginx and PHP-FPM

Recently I’ve been putting time into rebuilding the server infrastructure for
Holiday API.

This has included hardening the system to be more fault tolerant and building
out a new cluster of web servers. The biggest improvement was [finally]
introducing a continuous deployment pipeline to complement the existing
continuous integration flow.

Everything has come together quite swimmingly, and I was even able to flip the
switch this past weekend, without any downtime.

That’s not to say things came together as smoothly as I would have liked. This
has been something I’ve been chipping away at for the last week or two, tweaking
and tuning along the way.

The biggest issue I ran into was in regard to how the code was being linked on
the server. Originally I was deploying to a single directory, no symbolic
linking (or symlinking) involved at all.

With the new deployment flow, I opted to build the release and then symlink to
the “current” release. This was all then symlinked to a directory in /var/www/
to marry up with how the existing Docker configuration works.

Nothing revolutionary or anything and everything actually worked great. When the
deployment pipeline ran, new code would go live and all was well.

That was, until I made a change to the primary index.php file in the document
root. This particular file’s changes would not register until I restarted the
php-fpm service.

Changes to other PHP files were picked up immediately. The issue was limited to
the aforementioned index.php file in the document root.

The old web server didn’t have this issue, so I knew it had something to do with
the new server’s configuration. Without knowing for certain, I assumed it had
something to do with the symlinks that were now in play.

At this point, I did quite a bit of web searching, and ran into quite a few web
sites that were discussing getting PHP files to serve correctly with nginx, and
not necessarily anything related to my issue.

Finally, I stumbled upon a Stack Overflow post that seemed like what I was
experiencing, but sadly was scummed up by some asshole letting the original
poster know that their issue wasn’t well researched at all and they shouldn’t
have even posted the question.

There’s always a critic, right?

This was my first time running into the issue, and at least for me and my
Google Fu, it was a pain in the butt to find a solution for the issue.

That said, after more research, going through the nginx documentation and some
experimenting, I did figure things out. It had to do with the php-fpm portion
of my nginx configuration file.

Originally, the configuration for my server, looked a little something like this
(abridged for the sake of this post):

server {
  location ~ .php$ {
    try_files $uri =404
    include /etc/nginx/fastcgi_params
    fastcgi_pass unix:/run/php/php-fpm.sock
    fastcgi_index index.php
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name
  }
}

The big issue here is the $document_root variable being used in the
fastcgi_param.

As I came to find out, when using symbolic links, that particular variable ends
up being converted to an absolute path and is effectively cached when the server
starts or something like that.

Fortunately, there’s another variable that doesn’t does fall victim of this
alleged caching. The $realpath_root variable is a drop in replacement for the
$document_root.

The updated file looked more like this:

server {
  location ~ .php$ {
    try_files $uri =404
    include /etc/nginx/fastcgi_params
    fastcgi_pass unix:/run/php/php-fpm.sock
    fastcgi_index index.php
    fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name
  }
}

After quick restart of both nginx and php-fpm, I went ahead and deployed some
new code that affected the index.php in the document root. After deployed, the
changes were showing up and all was well again!

Josh Sherman - The Man, The Myth, The Avatar

About Josh

Husband. Father. Pug dad. Musician. Founder of Holiday API, Head of Engineering and Emoji Specialist at Mailshake, and author of the best damn Lorem Ipsum Library for PHP.


If you found this article helpful, please consider buying me a coffee.