How to Install WordPress with Nginx, PHP7, MariaDB and https on Raspberry Pi (Rasbian) πŸ“‡

1. Overview

In this tutorial we will show you how to get WordPress running on a Raspberry Pi. Usually WordPress runs on an Apache HTTP server but this time we will deploy a performant Nginx configuration. Moreover, we want to secure our traffic with SSL/TLS and obtain a free certificate from Letsencrypt.

Requirements:

  • Our own domain “YOURDOMAIN” and a corresponding email address “YOUREMAIL”
  • A fresh rasbian installation
  • Firewall / Router configured to let incoming traffic on port 80 and 443 through

2. Installing Nginx, PHP and MariaDB

First we install all the programs we need to eventually run WordPress. We update our Rasbian and run apt-get install. When it’s done Nginx will be running in default configuration. For the next step we will stop the service temporarily since certbot will be listening on the http port.

sudo apt-get update;sudo apt-get upgrade;
sudo apt-get install nginx php7.0 php7.0-fpm php7.0-mcrypt php7.0-mbstring mariadb-server mariadb-client php7.0-mysql
sudo nginx -s stop

3. Obtaining SSL Letsencrypt certificates

Next, we need to get a valid certificate associated to our domain (replace “YOURDOMAIN” and YOUREMAIL). That is where letsencrypt comes in. We can obtain the certificates using certbot. and download certbot using wget and make it runnable. Then we contact the license service and download the certificates.

We then have the certificates in /etc/letsencrypt/live/YOURDOMAIN. Later we will come back to make use of them.

sudo wget https://dl.eff.org/certbot-auto; 
sudo chmod a+x certbot-auto;
sudo ./certbot-auto certonly --debug --non-interactive --email YOUREMAIL --agree-tos --standalone --domains YOURDOMAIN --keep-until-expiring;

Make sure your domain is pointing to your servers ip address! There are other certbot options like using DNS TXT entries.

If you are just testing, you can also proceed with self-signed certificates:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt

4. Installing Nginx

After we got the right certificates we start up Nginx again and start the PHP-FPM. With mysql_secure_installation we make a basic configuration of our mysql(MariaDB) server and database. You can set a custom root password, remove the demo database and reload the user privileges.

sudo nginx
sudo systemctl start php7.0-fpm
sudo mysql_secure_installation

5. Setting up a WordPress Database

We use the mysql client to create a database, a user with password and grant the required privileges. Adjust the names and password according to your wishes.

 sudo mysql 
  >create database wp_db;
  >CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'new_password_here';
  >GRANT ALL ON wp_db.* TO 'wp_user'@'localhost' IDENTIFIED BY 'new_password_here' WITH GRANT OPTION;
  >exit

4. Download WordPress and File Permissions

We change into our Nginx root directory and download the latest wordpress version. After unpacking the file, we change the user to our Nginx www-data user and set appropriate privileges.

cd /var/www/
sudo wget http://wordpress.org/latest.tar.gz
sudo tar xfz latest.tar.gz
sudo chown www-data:www-data wordpress -R
cd wordpress 

# Set all directories permissions to 755
find . -type d -exec chmod 755 {} \;

# Set all files permissions to 644
find . -type f -exec chmod 644 {} \;

5. Configuring nginx

The critical step is to configure Nginx correctly. This is done in a custom file under /etc/nginx/sites-available. After creating a backup we open the file with root privileges and nano editor.

cd /etc/nginx/sites-available
sudo cp default default.bak
sudo nano default

The basic ingredients for a successful Nginx setup for wordpress are the php-handler where requests to php files get forwarded to. Also, we employ a 301 redirect for request on port 80 to https. Make sure your certificates are existing!

The root directory is changed from /var/www/html to /var/www/. If you want to access your wordpress later with https://YOURDOMAIN/ only change root to /var/www/wordpress/ .

upstream php-handler {
    server 127.0.0.1:9000;
}

server {
    listen 80;
        server_name localhost;
    location / {
        return 301 https://$server_name$request_uri; # enforce https
    }
}

server {
        listen 443 ssl;
    #ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
    #ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
        ssl_certificate /etc/letsencrypt/live/YOURDOMAIN/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/YOURDOMAIN/privkey.pem;

    # Path to the root of your installation
    root /var/www/;
    client_max_body_size 1000M; # set max upload size
    fastcgi_buffers 64 4K;
    fastcgi_read_timeout 300;
    index index.php index.html;

   location / {
        # The following 2 rules are only needed with webfinger
      try_files $uri $uri/ index.php;
        autoindex on;
  }
 location ~ \.php(?:$|/) {
        #try_files $uri /$uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        if (!-f $document_root$fastcgi_script_name) {
                    return 404;
        }
        include fastcgi_params;
       # fastcgi_param SCRIPT_FILENAME /var/www/$fastcgi_script_name;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS on;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
#       include fastcgi.conf;
   }
   # Optional: set long EXPIRES header on static assets
    location ~* \.(?:jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
         expires 30d;
         # Optional: Don't log access to assets
         access_log off;
    }
}

5. Check and Troubleshooting

In the last step we test our nginx configuration and start Nginx if everything is ok.

sudo nginx -t
sudo nginx -s reload

WordPress will be accessible later from https://localhost/wordpress or https://YOURDOMAIN/wordpress

Since this is a more advanced setup there are many points where something can go wrong. Here is a (non-comprehensive) checklist to run through if it is not working:

  • Inbound traffic on port 80 allowed?
  • Inbound traffic on port 443 allowed?
  • Is nginx up and running? => see process list
  • Is nginx listening to port 443
  • Was certbot installed successfully?
  • Did certbot obtain the certificates => check destination folder
  • Is http 301 redirect working? => check with chrome debugger tools, for example

6. Conclusion and Performance

With Nginx and PHP-FPM we can achieve a decent wordpress performance. It is worthwhile to test the access times via tools like Apache Benchmark.

ab -n 100 -c 10 http://YOURDOMAIN/wordpress

Leave a Reply

Your email address will not be published. Required fields are marked *