Notice!
The instructions in this article are meant to be used as an example of how to setup a working vhost for a user on a server. Special care must always be taken to ensure server security. Following this article does not guarantee server security.
A LAMP stack is a very common web server setup involving Linux, Apache, MySQL, and PHP, useful for running programs like WordPress, Joomla!, phpBB, etc. In this article we’re going to discuss a more advanced LAMP stack setup, involving Apache2’s Event MPM, PHP-FPM, MariaDB (a drop-in replacement for MySQL) all running on Ubuntu Server 14.04.
For this guide, we’ll be assuming a fresh install of Ubuntu Server 14.04.
Enabling the Multiverse Package Repository
The first thing we’ll need to do is make sure that the multiverse
package repository is enabled. You’ll need to open up /etc/apt/sources.list
in your favorite text editor. An editor that’s easy to use is nano
, though power users may prefer an advanced editor such as vim
.
Once you have /etc/apt/sources.list
open in your text editor, make sure that the multiverse
repository is enabled. Look for two lines like the following, and add them if they don’t exist.
/etc/apt/sources.list
deb http://archive.ubuntu.com/ubuntu trusty multiverse
deb http://archive.ubuntu.com/ubuntu trusty-updates multiverse
At this point you’ll need to update your local cache of the package repositories. You can do this by issuing the following command.
apt-get update
Installing Core Packages
We’re ready to start setting up the LAMP stack on this server now. The packages that we’re going to need to install for a basic setup are apache2-mpm-event
, libapache2-mod-fastcgi
, php5-fpm
, php5-gd
, php5-mysql
, and mariadb-server
. You can install all of these in one fell swoop with the following command:
apt-get install apache2-mpm-event libapache2-mod-fastcgi php5-fpm php5-curl php5-gd php5-mysql mariadb-server
During the install process you’ll be prompted to set a root password for the MariaDB server. This can be the same as your server’s root password if you want it to be, but keep in mind that changing the server’s root password won’t change MariaDB’s root password and vice versa.
Configuring Apache2
The first thing we’re going to want to do after everything’s installed is configure Apache2 to forward PHP requests to PHP-FPM. You’ll need to do a bit of configuration and enable a module for this. Let’s start by creating /etc/apache2/conf-available/php5-fpm.conf
using your favorite text editor. The file should contain the following configuration.
/etc/apache2/conf-available/php5-fpm.conf
<IfModule mod_fastcgi.c>
AddHandler php5-fcgi .php
Action php5-fcgi /php5-fcgi
Alias /php5-fcgi /usr/lib/cgi-bin/php5-fcgi
FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -socket /var/run/php5-fpm.sock -pass-header Authorization
<Directory /usr/lib/cgi-bin>
Require all granted
</Directory>
</IfModule>
We need to enable that configuration, as well as the Actions module, and finally restart Apache2.
a2enconf php5-fpm
a2enmod actions rewrite
service apache2 restart
At this point, you should have a fully functional LAMP stack. Test it out by creating /var/www/html/test.php
in your favorite text editor. Let’s put the following script into it.
/var/www/html/test.php
<?php phpinfo(); ?>
Try visiting http://your-ip/test.php
. You should see a page showing you some information about your server. If you simply see the script in plain-text, you’ve missed part of the configuration and should double-check your work.
Performance Tweaks for Apache2
Your server still needs some performance tuning, so we’re going to start with some sane defaults based on your server’s CPU count. We usually recommend running Apache2 with n workers and PHP-FPM with n workers, where n is your CPU count. Be aware that these values are simply a good starting point, and you’ll want to fine-tune them based on your application.
To find out how many CPU cores you have, you’ll want to look at /proc/cpuinfo.
cat /proc/cpuinfo
Count how many CPU cores show up. Depending on the server you have, this will vary. The server we’re using for this article has 4 cores.
Let’s start with Apache2. Open up /etc/apache2/mods-available/mpm_event.conf
in your favorite text editor. The line we want to change is the StartServers
directive. Change this the number of CPU cores you have. In our case, the resulting config looks like the following.
/etc/apache2/mods-available/mpm_event.conf
<IfModule mpm_event_module>
StartServers 4 # changed from the default of 2
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 150
MaxConnectionsPerChild 0
</IfModule>
Let’s restart Apache2 to activate the new values.
service apache2 restart
Performance Tweaks for PHP-FPM
Next we’ll want to adjust PHP-FPM’s worker pool. Open up /etc/php5/fpm/pool.d/www.conf
for editing, and look for the pm.max_children
line. Around here will be the configuration we want to start setting. The values we want to set are outlined below.
/etc/php5/fpm/pool.d/www.conf
pm.max_children = 16 # changed from default of 5
pm.start_servers = 4 # changed from default of 2
pm.min_spare_servers = 2 # changed from default of 1
pm.max_spare_servers = 8 # changed from default of 3
For a good starting point, we’ll limit the absolute maximum processes to 4n, the default number of workers to n, the minimum number of spare workers to 0.5n, and the maximum number of spare workers to 2n, where n is your CPU count.
Let’s restart php5-fpm to activate the new values.
service php5-fpm restart
The value we’ve chosen for pm.max_children
helps to ensure that your CPU usage won’t spiral out of control under heavy load. Some requests may take longer when you’re really getting hit hard, but it’s better to wait a bit than it is to not serve anything at all.
The value we’ve chosen for pm.start_servers
tells PHP-FPM to by default run one server per CPU core, since we have 4 cores.
The value we’ve chosen for pm.min_spare_servers
ensures that there are always a few spare workers available to handle new requests. Since we’d have to spin up a new FPM process to handle a request if all workers were busy, we’ll make sure we keep 2 spare servers around to handle new requests.
The value we’ve chosen for pm.max_spare_servers
ensures that we don’t leave too many extra servers sitting around. If we have 16 threads sitting idle, we’ll spin down 8 of them to leave us with no more than 8 spare servers.
That’s all! Now you can start setting up your application. Remember to keep an eye on your resource usage and tweak the worker counts appropriately!