Install php7 + nginx + MariaDB + WordPress on Debian Jessie

wordpress-logoInstall php7, nginx, MariaDB and WordPress on Debian Jessie for a lean LEMP stack to serve your web site. I am migrating my Digital Ocean VPS from the smallest droplet to the 1 GB droplet. I currently run Apache, PHP, MySQL 5.5 and Varnish 3.x on this VPS droplet. I've been advised by many to switch to nginx and MariaDB to boost performance so I am documenting the working LEMP installation on my new droplet.

Other tutorials related to your VPS include installing Varnish 4 (guide) for high speed caching, Redis (guide) and memcached (guide) for object caching, setting up a Web Application Firewall and the CSF Firewall (guide). We will be using the fantastic dotdeb repository which works on 32-bit and 64-bit distros (sorry ARM users). Future posts will include monitoring these services on your Digital Ocean VPS.

VPS Provider
Locations
RAM
Hard Drive
Speed
Price
Vultr
US, EU, Asia
768 MB
15 GB SSD
100 Mbps
$5 / month
Digital Ocean
US, EU, Asia
512 MB
20 GB SSD
100 Mbps
$5 / month
HostUS
US, UK, China, Australia
768 MB
20 GB
1-10 Gbps
$15 / year

Install php7 + nginx + MariaDB + WordPress on Debian Jessie

Install nginx on Debian

I use the dotdeb repo as they compile nginx with useful addons like x-cache, pagespeed and others. They usually have the latest stable nginx build as well.

echo "deb http://packages.dotdeb.org jessie all" | sudo tee -a /etc/apt/sources.list.d/dotdeb.list
echo "deb-src http://packages.dotdeb.org jessie all" | sudo tee -a /etc/apt/sources.list.d/dotdeb.list
wget -qO - http://www.dotdeb.org/dotdeb.gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get install nginx -y

Make some changes to the nginx configuration

sudo nano /etc/nginx/nginx.conf

Add these values in the server block or adjust them if they are already there.

The client_max_body_size is the largest theme or plugin you'll be able to upload (here 8 megabytes) so adjust that if necessary. It should match the upload_max_filesize in php.ini.

client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 4 16k;
#prevent upstream sent too big header while reading response header from upstream errors with buffers
fastcgi_buffers 16 16k; 
fastcgi_buffer_size 32k;

Ctrl+X, Y and Enter

Install PHP 7 on Debian

The dotdeb repository has precompiled php7 packages for Debian Jessie. php7.0-fpm is used for serving PHP pages for nginx.

Note that the benefits of opcache which speeds up your site significantly will be enabled by default with these packages.

sudo apt-get install php7.0-cli php7.0-curl php7.0-dev php7.0-zip php7.0-fpm php7.0-gd php7.0-xml php7.0-mysql php7.0-mcrypt php7.0-mbstring php7.0-opcache -y

Change your pm.max_children value for the php7.0-fpm

sudo nano /etc/php/7.0/fpm/pool.d/www.conf

Adjust pm.max_children to 10 (make sure there is no leading ;), this is may be higher than necessary, see the formula link below for more precise calculations.

pm.max_children = 10

Adjust pm.max_requests, uncomment it by deleting the ; before pm.max and change it from 500 to 200

pm.max_requests = 200

Ctrl+X, Y and Enter

Note that for the php7.0-fpm www.conf configuration above, you may want to adjust it following this formula in the future.

Adjust some php.ini values

sudo nano /etc/php/7.0/fpm/php.ini

Change your timezone by removing the ; semicolon and adding your country/city (list here).

Use a larger maximum upload size because some plugins are larger than 2 megabytes.

Change max_execution_time so backup scripts and other possible slow scripts have enough time to finish

If you have a large menu like mine with tons of menu items, increase the max_input_vars.

date.timezone = America/Cayenne
upload_max_filesize = 8M
max_execution_time = 60
max_input_vars = 5000

Ctrl+X, Y and Enter to save

Install MariaDB Server on Debian

MariaDB is a MySQL drop in with better performance, luckily it's in the Debian Jessie repo so installing is easy.

sudo apt-get install mariadb-server mariadb-client -y

Enter MariaDB (MySQL drop in)

sudo mysql -u root -p

Create the SQL WordPress user, database and grant privileges.

Note that this is not the WordPress user you use to log on but the credentials WordPress needs in wp-config.php to store posts and options in the database.

CREATE USER wordpressuser@localhost IDENTIFIED BY 'passw0rd';
CREATE DATABASE wordpress;
GRANT ALL PRIVILEGES ON wordpress.* TO wordpressuser@localhost IDENTIFIED BY 'passw0rd';
FLUSH PRIVILEGES;
quit;

Tweak the MariaDB configuration

sudo nano /etc/mysql/my.cnf

These values should be a good starting point for MariaDB with WordPress

# * Fine Tuning
#
key_buffer              = 16M
max_allowed_packet      = 16M
thread_stack            = 192K
thread_cache_size       = 8

# * Query Cache Configuration
#
query_cache_limit       = 1M
query_cache_size        = 20M

If you are curious about any slow queries or queries not using indexes, enable these features by adding the configuration lines below.

Looking at these from time to time has helped me eliminate poorly coded WordPress plugins

# Here you can see queries with especially long duration
slow_query_log_file = /var/log/mysql/mysql-slow.log
slow_query_log      = 1
long_query_time = 2
log_queries_not_using_indexes

These values will be adjusted in the future after you get some usage statistics and tweaking information from MySQLTuner


[mysqld]
innodb_buffer_pool_instances = 1
innodb_buffer_pool_size = 79M
[mysqldump]
quick
quote-names
max_allowed_packet      = 16M

[mysql]
#no-auto-rehash # faster start of mysql but no tab completion

[isamchk]
key_buffer              = 16M
key_buffer_size         = 7M

[mariadb]
aria_pagecache_buffer_size = 2M

Ctrl+X, Y and Enter

Install WordPress

Create the site directory, this is the folder where your WordPress installation will be stored

mkdir -p /var/www/htpcguides.com

Enter the site directory, grab the latest WordPress package and unpack it, then adjust the ownership so nginx can read it

cd /var/www/htpcguides.com
wget http://wordpress.org/latest.tar.gz
tar --strip-components=1 -xvf latest.tar.gz
rm latest.tar.gz
sudo chown -R www-data:www-data /var/www/htpcguides.com

Set up WordPress with MariaDB and nginx

Copy the sample wp-config.php file

cp /var/www/htpcguides.com/wp-config-sample.php wp-config.php

Open the wp-config.php file to adjust the SQL database used

nano /var/www/htpcguides.com/wp-config.php

Adjust these settings so WordPress can connect to MariaDB. They are the values from when you created the SQL WordPress user.

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'wordpress');

/** MySQL database username */
define('DB_USER', 'wordpressuser');

/** MySQL database password */
define('DB_PASSWORD', 'passw0rd');

/** MySQL hostname */
define('DB_HOST', 'localhost');

Change ownership of the WordPress directory

sudo chown -R www-data:www-data /var/www/htpcguides.com

Change permissions of the directories to the recommended 0755

sudo find /var/www/htpcguides.com -type d -exec chmod 755 {} +

Change permission of the wp-config.php file and other files to 0644

sudo find /var/www/htpcguides.com -type f -exec chmod 644 {} +

Create the WordPress nginx virtual host file

sudo nano /etc/nginx/sites-available/wordpress

Paste this secure WordPress nginx configuration, if you want to only use domain.com or www.domain.com see this post.

server {
	server_name www.htpcguides.com htpcguides.com;
	listen 80;
        port_in_redirect off;
	access_log   /var/log/nginx/htpcguides.com.access.log;
	error_log    /var/log/nginx/htpcguides.com.error.log error;

	root /var/www/htpcguides.com/;
	index index.php;

	location / {
		try_files $uri $uri/ /index.php?$args;
	}

	# Cache static files for as long as possible
	location ~*.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|cur)$ {
        expires max;
        log_not_found off;
        access_log off;
	}
		
	# Deny public access to wp-config.php
	location ~* wp-config.php {
		deny all;
	}
		
	location ~ \.php$ {
		try_files $uri =404;
		include fastcgi_params;
		fastcgi_pass unix:/run/php/php7.0-fpm.sock;
		fastcgi_split_path_info ^(.+\.php)(.*)$;
		fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
	}      
}

Unlink the default site and symlink the WordPress site nginx virtual host

unlink /etc/nginx/sites-enabled/default
ln -s /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/wordpress

Restart nginx and php7.0-fpm

sudo service nginx restart
sudo service php7.0-fpm restart

Now you can enter the IP address of your host into a browser and begin the 2 step process for installing WordPress on your VPS or dedicated server using nginx, MariaDB, php7-fpm.

For new guides on WordPress and VPS hosting see my new site WP Bullet.

For additional speed use Redis object cache (guide here) to ease the load on the MySQL server.

I recommend using CSF Firewall (guide) to secure your server and using Monit (guide coming) to monitor the health of these services.

For speeding up your site, consider using nginx's fastcgi caching, personally I prefer using Varnish (guide) so that I can more precisely control the cache – warming up, specifically emptying cache for certain posts, categories etc and selectively purge static files.