Do everyone a favor. Don't use PHP.


It's a list of lists.

My own horror story

People write code. I get paid to get that code running in production. Easy job right? As long as you don't have to run Symfony.

The interwebs is not a safe place

Now if you know a thing or two about running any sort of network services, you're probably aware that the Internet is full of danger for such little apps. Every Internet host is a yummy snack for the bad guys, either because you can send spam, mine bitcoins, or use it in further attacks. You don't want this, because this will interfere with legit services that your box is trying to provide. Yuck.

So you apply the simplest and most important principle in computer security: privilege separation. You can minimize the amount of damage that a compromised application can deal to your system.

The simplest possible step you can take, is to forbid the application any write rights to the filesystem, except for perhaps /tmp or some user uploads area. You should also make sure, that even if the application can write in such places, it won't be able to execute any code that resides there. We can say that we're trying to enforce a principle called W^X, or execution prevention.

Enter PHP

PHP is well known for making each and every file with the .php extension a possible entry point to your application. This supposedly simplifies deployments (just copy files using the FTP Sadness to the target machine!), but it also creates up a wide range of security-related headaches.

Think: many web applications will allow uploads of user-generated data to some sort of on-disk directory, where these files are later made available by the same web server daemon that allowed the upload in the first place. Can you connect the dots?

Smart developers put all but one PHP files outside of the web server's document root, and use that single "proxy" file to load the rest of the application. Smart sysadmins teach the web server to deny inclusion or execution of PHP files outside of specific, whitelisted paths. So far, so good.

Enter Symfony

PHP's execution model is extremely performance-unfriendly: the entire application's source code is parsed and recompiled on each and every request. Various methods have been developed to mitigate this problem. Symfony has one as well: the (dreaded) cache.

So what Symfony does: Symfony has a "cache". This cache mechanism, it reads, parses, "transpiles" (is that a word?) and packages the entire application source (plus its runtime configuration) and writes a bunch of "optimized" PHP code; not unlike what JS compilers/minifiers do. The performance benefits during runtime are obviously tremendous.

However, Symfony has a particular peculiarity regarding this cache. It insists that the cache be generated upon the first request that hits the application. (See the problem yet?)

In order for this to happen, the application demands that an area be both writable by itself and PHP-executable, even if the associated tooling allows to purge and generate the cache in an offline mode.

No, seriously. Go read what the official Symfony documentation advises on this matter. I'll wait here for you, and when you're back, I'll iterate on how sad this makes me.

None of these are fixing the root problem. Yet the solution is so simple: do not try writing to the damn cache. Leave it up to the system administrator to generate it, and run without it, or with the old version, for the 2 seconds it takes to run the command.

We ended up using option 1., as it was the simplest way forward and posed the smallest security risk.

Enter Composer

Symfony depends on, and heavily integrates Composer, PHP's answer to pip, npm, gems, etc.

What happens when you need to update library dependencies between app code updates?

One idea that our team has had, was to put up a simple, static page informing that maintenance is in progress. This obviously sucks.

Another idea is to have several hosts behind a load balancer, and update the code in batches, taking each host off the LB pool for the update. (Naturally it's impossible without at least two hosts and a load balancer, but if you don't have a redundant setup, you probably don't care about uptime in the first place!)

Yet another idea (we have a working PoC) is to hack Composer, to stop it from requiring this sadness. Keeping hacked forks around is not really a good solution though.

So much for simple deployments.


I wanted to write about Wordpress, but decided not to.

See this as plaintext. Get the permalink. Check out related. Go home.