Creating WordPress Site

Installation WordPress on Raspberry Pi 4

My original Web Site was served up using the wonderful Raspberry Pi 3. I then included WordPress as an add-on to provide blogging functionality, but that left the site looking distinctly non integrated. Performace was, for the most part not too bad. My site pages used Javsascript to provide any behaviour that I need, and whilst some Server side Javascript, the vast majority was execute client side. i.e. Not impacted by the Pi modest CPU power.

I then started the project to integrating the two aspects into WordPress. problem was once suceeded the performance in serving up the pages was slow and definitely CPU limited.  All of the client-side javbascript became Server side PHP.

The arrival of the Pi 4, which is advertised as being 2 to 4 times faster than the Pi 3, promised to provide a solution to the performance issue. Transferring the site on to the Pi 4 would also give me an opportunity to migrate to PHP 7.x.x from 5.x.x. (which also brings some perfomance improvments 🙂 )and to run through my notes on the previous installation process and document what was needed.

Minimum Equipement

  • Raspberry Pi 4 (At least this configuration is targetted at the Pi 4)
  • Pi 4 power supply
  • HDMI cable for the Pi 4 – which is not the same as HDMI cable for the previous Pi series.
  • Network connection (WiFi or Ethernet)
  • SD card
  • Keyboard, mouse and screen (but only for set-up)
  • PC, with SD card reader and internet connection.

SD Card

If, like me, you have gone for the fastest, largest, reasonably priced SD card , then you may have bought one larger than 64Gbyte. (For me I purchased a 256Gbyte V30). There is a slight problem with these cards in that they are SDXC cards. The SDXC spec states that they should be formatted as exFAT, which, by default on Windows, they will be. The Raspberry Pi will not work with exFAT partitions, it needs FAT32. To get round this you can format the card on a MAC, which will default to FAT32 or download guiformat.exe on your Windows PC, and use that to format the card.

At a high level the steps are:

  • Pi Configuration
  • LAMP Installation
  • WordPress set-up
  • Web site transfer
  • Certificate transfer

Pi Configuration

Initial Set-up Steps

  • On PC
    • Formatted SD card using ‘SD Card Formatter’
    • Downloaded
    • Unziped and copied contents to SD card
  • On Raspberry Pi
    • Plugged in Screen to HDMI
    • Plugged in Keyboard and Mouse remote USB dongle
    • Inserted SD card
    • Connected Power

System booted fine, and presented a screen that enabled me to connect to WiFi and install Rasperian. Installation of Rasperian requests

  • Password for user Pi
  • Location, and Keyboard layout

Pi 4 Configuration

  • Create a new user with SUDO privileges, so that we can restrict user Pi to just local login.
  • sudo adduser <name>
    • Password – followed by the following optional prompts
      • Fullname
      • Room Number
      • Work Phone
      • Home Phone
      • Other
    • Is the information correct (Y/N)
  • sudo usermod -aG sudo <name> – to give new user sudo privileges
  • Logout and login as new user. Test sudo privileges (eg sudo visudo)
  • groups pi – to get list of groups that pi is in
  • sudo usermod -aG <group1,group2,…> <name> to add new user to same set of groups. That basically makes <name> == Pi.
  • If you have a Pi 3, then you may need to adjust your screen settings at this point to make maximum use of your screen:
    • sudo cp /boot/config.txt /boot/config.txt.backup
    • sudo nano /boot/config.txt to get full use of screen.
      • Left and Right values -nn
      • Top and Bottom values -mm
    • Note: This does not work on the Pi 4. The overscan controls in config.txt do not have any effect on the Pi 4. This is a known feature. If you have off-screen image issues with your Pi 4, then, as of  July 2019, as I understand it, there is no solution
  • System>Preferences – These are my preferences.
    • Select medium sized ICONs for top menu
    • Select font Sans and size 10 for text.
  • Keyboard was not correctly configured. Backslash key was being mapped to ‘>’, plus other annomalies
    • sudo raspi-config
    • select option 4 – Localisation Options
    • select Change Keyboard Layout.
    • And now we come to the messy bit. You have to select your keyboard from an extremely long list of options. It, possibly, doesn’t matter which one you choose as long as you get something that matches the number of keys and layout. I am using an  ASUS cordless  107 key QWERTY keyboard. The only ASUS option was for a laptop keyboard – which didn’t sound correct, so I selected the generic sounding Microsoft Office keyboard.
    • Then you have to choose the keyboard Layout, and here it does matter that you get it right. Get this wrong and your key mappings will be completely screwed.  The first issue was that whilst my locale was UK, the selection of layouts was all US, at least that was the appearance. You have to scroll to the bottom and select Other before you get given any none US options. At this point I was able to select English (UK).
    • As an FYI  – In case you don’t know what Colemak, Dvorak, and Workman are – they are non QWERTY layouts. If you have a QWERTY keyboard, do not select one of these.

Remote Access

I want to use the Pi4 headless and have FTP available for file transfers.

  • Open System Menu>Preferences>Raspberry Pi Configuration
  • Select Interfaces Tab
  • Enable SSH and VNC

LAMP Instalation


  • sudo apt-get update
  • sudo aptget install apache2

Yep – that simple.  As a quick test to check Apache2 is installed and running type whatever the IP address is of your PI and you should see the following image.

(To determine the IP address type ifconfig or hostname -I (Note: if you have both WiFi and Ethernet connection, you may have two IP addresses.)


  • sudo apt-get install php php-xml php-mysql
  • php -v

And the result:

PHP 7.3.4-2 (cli) (built: Apr 13 2019 19:05:48) ( NTS )

As a quick test of the Apache and PHP install.

  • cd /var/www/html
  • sudo rm index.html
  • sudo nano index.php – create a php file with the following content.
    • <?php echo (“Hello World “);
    • echo date(‘Y-m-d H:i:s’); ?>

Maria / MySql DB

As you may already be aware installing MySql on Raspberry Pi actually installs Maria D/B, and not MySql. I will confess that I have not investigated the difference between these two packages nor their relative provences. For me Maria D/B has provided all the functionality I have required and so have stuck with that.

  • sudo mysql_secure_installation – installs MariaDB
  • sudo mysql -u root -p – to create a root user with a password.
    • Remove annoymous user
    • Disallow root login remotely.
    • Remove Test D/B
  • apt-get install emma – Emma is a MySQL GUI. There are others, this one works for me.

WordPress Set-up

Downloading WordPress

  • cd /var/www
  • sudo wget
  • sudo tar -xzf latest.tar.gz
  • sudo mv wordpress quintic
  • sudo rm latest.tar.gz

Setting up WordPress D/B

  • sudo mysql -uroot -p#####
  • create database quintic;  – Note the ‘;’ at the end of the command.
  • grant all privileges on quintic.* to ‘root’@’localhost’ identified by ‘#######’; – The ‘######’ is the root password.
  • flush privileges;
  • <CTRL>D to exit

As it happens I decided to divert from a straight Pi 3 -> Pi 4 installation copy. I do have three domains –, and I decidied to try to create a Multi-site installation. So I also created databases called stephendickinson and bliki and created the required directories, copying the contents from quintic.

Configure Apache.

  • sudo chown -R www-data:www-data /var/www/quintic – to give apache ownership of the WordPress directories.
  • We now need to create virtual hosts files for the three directories.
  • cd /etc/apache2/sites-available
  • created quintic.conf, bliki.conf, stephendickinson.conf – All created to re-direct to HTTPS, so will need SSL Certificates for all. An example conf file is detailed below.
    • <VirtualHost *:80>
      # The Primary domain for this host
      ServerName [site-name]
      # Optionally have other subdomains also managed by this Virtual Host
      ServerAlias www. [site-name]
      DocumentRoot /var/www/ [site-name]
      <Directory /var/www/ [site-name] >
      Require all granted
      #Allow local .htaccess to override Apache configuration settings
      AllowOverride all
      # Enable RewriteEngine
      RewriteEngine on
      RewriteOptions inherit  # Block .svn, .git
      RewriteRule \.(svn|git)(/)?$ – [F]
      # Recommended: XSS protection
      <IfModule mod_headers.c>
      Header set X-XSS-Protection “1; mode=block”
      Header always append X-Frame-Options SAMEORIGIN
      RewriteCond %{SERVER_NAME} =*. [site-name] [OR]
      RewriteCond %{SERVER_NAME} = [site-name] [OR]
      RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
  • sudo a2ensite quintic/bliki/stephendickinson – this creates links from the conf files to the sites-enabled directory.
  • added .htaccess files to the Quintic, Bliki and StephenDickinson sites to set index.php as the default file to open.
  • Edited apache2.conf to set the default site.
  • Added ‘DirectoryIndex [site-name]/index.php‘  instruction to apache2.conf to prevent  access to  directory /var/www

Note: It is easy to make a typo when creating / editing the .conf files. If you do make an error Apache will not restart. Keep calm. Apart from the apache2.conf file you can just rename the other conf files out of the way whilst you track down the problem. I would however recommend taking a copy of apache2.conf before starting to edit that file – just in case. All sites are now up and running WordPress. So now I have to determine how to transfer a WordPress site over to a new server.

Transferring WordPress site

I hand-crafted the transfer of the code files.

  • tar -cf -R [site-name].tar [site-name]
  • ftp tar file to Pi4
  • tar -xvf [site-name].tar .
  • sudo chown -R www-data:www-data /var/www/[site-name] – to redo apache2 ownership
  • Edit wp-config.php to set database user, password and table prefix.

Transferring WordPress database

  • mysqldump -u ‘username’ -p ‘password’ [site_db_name] > [site_db_name] .txt – This exports the database ‘ site_db_name ‘ to file site_db_name .txt (Note: the command is mysqldump)
  • ftp file to Pi4
  • mysql -u ‘username’ -p ‘password’ [site_db_name] < [site_db_name ].txt

Test and Debug

An initial test gave the appearance that everything was working beautifully. However, appearances can and were deceptive. Typing in http://Pi4/ on a browsers on my PC did indeed display the Home page. When I clicked on any of the links from the HomePage, the requested page was displayed. The problem was all links jumped to the actual web site, still running on the Pi3. And here we hit a problem with testing the site as constructed. I had copied the site verbatum, including the configurations. I had made some changes to relflect the new environment, but not enough changes to allow testing. Not difficult though. All I needed to do was:

  • MySql: In wp_options change all rows with an option_value http://www.[site-name] to http://pi4/
  • For TESTING ONLY remove the restricted access to wp-config.php and wp-admin
  • apt-get install php-xml

Obviously, the first two entries need to be ‘undone’ for release, but testing was now fine.

Release Stage

  • Undo testing config changes detailed above
  • Install SSL Certificate from Let’s Encrypt
    • sudo apt-get install python-certbot-apache
    • sudo certbot -apache
  • Install Fail2Ban
  • Configure Firewall to forward ports 80 and 443 to Pi4

Everything appears to be working perfectly, and the Pi4 is noticably faster at serving content than the Pi3. Still not fast, but acceptable.


As soon as you have any ports open on the internet, they will be attacked. Hosting a WordPress site increases that vulnerability because the structure and file content are well known. Therefore it is incumbant upon you to secure the site.

My recommendations:

  • If you have configured your server for remote access, then install fail2ban. This piece of software will lock out for a period of time, any IP address from which a number of consequtive failed login attempts have been made
  • If you are using Apache2 as your Web Server then create and configure .htaccess files to:
    1. Prevent Apache from serving up directory listings
    2. Prevent Apache from serving up actual files
    3. Prevent access to wp-login.php, except from certain IP addresses
    4. Disable the ?author=n query from non admin sites.
    5. Install one of the Security plugins. I like Securi, but any that monitor the site and communicate any changes is good.

Here is an example .htacess file from the top level web site directory.

DirectoryIndex index.php

<Files wp-login.php>
Order Deny,Allow
Deny from all
Allow from
Allow from 192.168.100.*
Allow from

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]


RewriteEngine On
RewriteCond %{REQUEST_URI} !^/wp-admin [NC]
RewriteCond %{QUERY_STRING} author=\d
RewriteRule ^ /? [L,R=301]

# END WordPress

And from the wp-admin directory

# BEGIN WordPress Admin Access
order deny,allow
deny from all
allow from
allow from 192.168.1.*     [Allows access from PC's on your home network]
allow from [IP address of your Web Site]
# END WordPress Admin Access