In this post we will see How to Install WordPress on Debian Jessie LAMP stack with Nginx Reverse Proxy.

This will be a fairly long post as we will see how get a working LAMP stack up and running first and the Install nginx, enable reverse proxy and do some performance optimization in it, like enabling gzip compression, static file caching, and passing dynamic contents to apache.

1) Setting up Postfix SMTP listening to localhost and Install Logwatch (Optional).

Postfix is not necessary as Debian comes with EXIM4 which takes care of SMTP. I prefer postfix over it. But you may definitely like to see the logwatch installation. You may click this link to see how to do it.

2) Install MySql or MariaDB database server

The repositories of Debian Jessie come with both MySql 5.5 and MariaDB 10.0 database servers. Install anyone of your choice. I am installing MySql, if you install MariaDB then just replace mysql-server with mariadb-server

apt-get install mysql-server

During installation you will be asked to set database root password, make sure that you use a strong password. Once installed, we need to secure our database server with following command.

mysql_secure_installation

The output listed below should be good enough for a newbie to understand how to secure mysql

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL

SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY! In order to log into MySQL to secure it, we’ll need the current

password for the root user. If you’ve just installed MySQL, and

you haven’t set the root password yet, the password will be blank,

so you should just press enter here. Enter current password for root (enter for none):

OK, successfully used password, moving on… Setting the root password ensures that nobody can log into the MySQL

root user without the proper authorisation. You already have a root password set, so you can safely answer ‘n’. Change the root password? [Y/n] n

… skipping. By default, a MySQL installation has an anonymous user, allowing anyone

to log into MySQL without having to have a user account created for

them. This is intended only for testing, and to make the installation

go a bit smoother. You should remove them before moving into a

production environment. Remove anonymous users? [Y/n] y

… Success! Normally, root should only be allowed to connect from ‘localhost’. This

ensures that someone cannot guess at the root password from the network. Disallow root login remotely? [Y/n] y

… Success! By default, MySQL comes with a database named ‘test’ that anyone can

access. This is also intended only for testing, and should be removed

before moving into a production environment. Remove test database and access to it? [Y/n] y

– Dropping test database…

ERROR 1008 (HY000) at line 1: Can’t drop database ‘test’; database doesn’t exist

… Failed! Not critical, keep moving…

– Removing privileges on test database…

… Success! Reloading the privilege tables will ensure that all changes made so far

will take effect immediately. Reload privilege tables now? [Y/n] y

… Success! Cleaning up… All done! If you’ve completed all of the above steps, your MySQL

installation should now be secure. Thanks for using MySQL!

3) Create the database to be used for wordpress

mysql -u root -p create database wordpress; grant all on wordpress.* to 'wpuser'@'localhost' identified by 'abc123'; flush privileges quit

I am using a simple password abc123 in this tutorial. Choose a strong password for yourself. So we have a database called wordpress and the databse user wpuser has complete privileges on it. We will use it during wordpress installation.

4) Install Apache WebServer with event mpm and PHP5-FPM

Edit ‘/etc/apt/sources.list‘ file and Enable the contrib and non-free repositories. you just need to add the values in red to the jessie main repository lines.

deb http://debian.mirror.constant.com/ jessie main contrib non-free

deb-src http://debian.mirror.constant.com/ jessie main contrib non-free

Update the repositories metadata and install the packages

apt-get update apt-get install libapache2-mod-fastcgi php5-fpm apache2-mpm-event php5-gd php5-mysql php5-curl php5-pspell

Then create the file ‘ /etc/apache2/conf-available/php5-fpm.conf' with the contents:

<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>

Enable the new modules

a2enmod actions fastcgi alias a2dismod mpm_prefork php5 a2enconf php5-fpm a2enmod mpm_event a2enmod rewrite service apache2 restart

Becuase our Apache Server will sit behind a proxy, In this step we will install an Apache module named mod_rpaf which rewrites the values of REMOTE_ADDR, HTTPS and HTTP_PORT based on the values provided by a reverse proxy. Without this module, some PHP applications would require code changes to work seamlessly from behind a proxy.

apt-get install libapache2-mod-rpaf

Now its time to make a few changes with how php5-fpm works and connect it to nginx. Open the main php-fpm configuration file

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

Find the parameter that sets “cgi.fix_pathinfo”. This will be commented out with a semi-colon (;) and set to “1” by default.

This is an extremely insecure setting because it tells PHP to attempt to execute the closest file it can find if a PHP file does not match exactly. This basically would allow users to craft PHP requests in a way that would allow them to execute scripts that they shouldn’t be allowed to execute.

We will change both of these conditions by uncommenting the line and setting it to “0” like this:

cgi.fix_pathinfo=0

Now we will test the working of Apache Webserver and php

echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php /etc/init.d/apache2 restart

Now just type the url http://your-server-ip/info.php, the image below shows the output of working LAMP stack.

So our LAMP stack is functional.

5) Download wordpress and keep the setup ready

cd /tmp && wget https://wordpress.org/latest.tar.gz && tar -xf latest.tar.gz touch wordpress/.htaccess cp -R wordpress /var/www/ chown -R www-data.root /var/www/wordpress

Navigate inside the directory “/var/www/wordpress”. copy the file “wp-config-sample.php” as “wp-config.php”

cp -R wp-config-sample.php wp-config.php

Once copied, update the file with your wordpress database details as created above. The changes will be made in the following sections in the file:

/** The name of the database for WordPress */ define('DB_NAME', 'wordpress'); /** MySQL database username */ define('DB_USER', 'wpuser'); /** MySQL database password */ define('DB_PASSWORD', 'abc123'); /** MySQL hostname */ define('DB_HOST', 'localhost');

6) Prepare the Apache backend

We will now disable the default site and make Apache listen to an alternate port 8080. So that Nginx listens to all the incoming http connections on port 80, and servers the clients by proxying those request to apache backend.

a2dissite 000-default touch /etc/apache2/sites-available/wordpress.conf

put contents in it as follows using nano editor

nano /etc/apache2/sites-available/wordpress.conf

<VirtualHost *:8080>

#ServerName www.example.com

ServerAdmin webmaster@localhost

DocumentRoot /var/www/wordpress

ErrorLog ${APACHE_LOG_DIR}/error.log

CustomLog ${APACHE_LOG_DIR}/access.log combined

<Directory /var/www/wordpress>

AllowOverride All

</Directory>

</VirtualHost>

In this virtual host definition, we are making apache to listen to port 8080. We also have to make Apache to listen to port 8080 in ‘/etc/apache2/ports.conf‘ file as well, just find the line ‘Listen 80′ in it and change it to ‘Listen 8080′, and restart apache.

a2ensite wordpress /etc/init.d/apache2 restart

7) Install Nginx and enable reverse proxy feature

apt-get install nginx

The main nginx configuration file resides in ‘/etc/nginx‘ , and it is known as ‘nginx.conf‘. The contents of file that I used is pasted below for your reference. I have enabled gzip and some other basic optimization features:

user www-data;

worker_processes 1;

pid /run/nginx.pid;

events {

worker_connections 1024;

multi_accept on;

use epoll;

}

http {

sendfile on;

tcp_nopush on;

tcp_nodelay on;

keepalive_timeout 20;

client_max_body_size 15m;

client_body_timeout 60;

client_header_timeout 60;

client_body_buffer_size 1K;

client_header_buffer_size 1k;

large_client_header_buffers 4 8k;

send_timeout 60;

reset_timedout_connection on;

types_hash_max_size 2048;

server_names_hash_bucket_size 64;

server_tokens off;

server_name_in_redirect off; open_file_cache max=2000 inactive=20s;

open_file_cache_valid 60s;

open_file_cache_min_uses 5;

open_file_cache_errors off;

include /etc/nginx/mime.types;

default_type application/octet-stream;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE

ssl_prefer_server_ciphers on;

access_log /var/log/nginx/access.log;

error_log /var/log/nginx/error.log;

gzip on;

gzip_static on;

gzip_disable “msie6”;

gzip_vary on;

gzip_proxied any;

gzip_comp_level 6;

gzip_min_length 512;

gzip_buffers 16 8k;

gzip_http_version 1.1;

gzip_types text/css text/javascript text/xml text/plain text/x-component application/javascript application/x-javascript application/json application/xml application/rss+xml font/truetype application/x-font-ttf font/opentype application/vnd.ms-fontobject image/svg+xml image/x-icon;

include /etc/nginx/conf.d/*.conf;

include /etc/nginx/sites-enabled/*;

}

Next, we will remove the default virtual host config and create a new one with our proxy definitions as well as the static content caching parameters.

rm /etc/nginx/sites-enabled/default touch /etc/nginx/sites-available/example vi /etc/nginx/sites-available/example

The contents of the new virtual host called example is listed below:

server {

server_name example.com www.example.com;

root /var/www/wordpress/;

access_log /var/log/nginx/example.com_access.log; error_log /var/log/nginx/example.com_error.log;

#####Caching Static contents######

location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {

expires 31536000s;

add_header Pragma public;

add_header Cache-Control “max-age=31536000”;

}

location ~* “^.*?\.(eot)|(ttf)|(woff)|(woff2)$” {

#add_header Access-Control-Allow-Origin *;

expires 31536000s;

add_header Pragma public;

add_header Cache-Control “max-age=31536000”;

}

######Forwarding Dynamic Content to Apache######

location / {

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header Host $host;

proxy_pass http://127.0.0.1:8080; }

##### Stuff In our Web Root That Should not be accessible to the outside world ######

location ~ /\. {

deny all;

}

location ~ /(\.|wp-config.php|readme.html|license.txt) {

return 404;

#deny all;

}

}

Put your own server name instead of example.com. Next, we will enable the the virtual host ‘example’ and restart nginx.

cd /etc/nginx/sites-enabled ln -s ../sites-available/example /etc/init.d/nginx/restart

9) Lets start the wordpress installation

Just open your web browser and type http://your_domian_name, and installer will start like the images below:

So this is How to Install WordPress on Debian Jessie LAMP stack with Nginx Reverse Proxy.