Raspberry Pi Apache, MariaDB, PHP & WordPress Server

The purpose of this tutorial is to walk you through the process of using a Raspberry Pi as a web server.

This tutorial assumes:

  1. You already know how to flash a microSD card with Raspbian.
  2. You are already somewhat familiar with setting up and using a Raspberry Pi.
  3. You have already followed my previous tutorial titled Raspbian Stretch Lite Secure Baseline Setup.

Before We Begin

The way I have outlined this tutorial is to

  1. Walk you through the steps of getting the Raspberry Pi setup as a fully functional web server.
  2. Once everything is fully setup we will move the Raspberry Pi web server onto the Internet.

Sure, we could do everything live. However, I prefer this method so the system is secure before I move it into production. Once we do move things online, there will be a couple of adjustments that we have to make so all of the links on the site will work properly.

Please keep in mind that the instructions I am providing to you are what allowed me to make this work. There are probably (most likely) better instructions out there. I try my hardest to be as secure in my setups as possible. I have a background in Information Technology and currently hold a CompTIA Security+ certification. With that being said, I make zero claims of being an expert! I wish I were! Ultimately, use these instructions at your own risk!

Now that all of the disclaimers are out of the way, let’s have some fun!

Install Apache, MariaDB, PHP, & phpMyAdmin

Once you have your Raspberry Pi running with your baseline image of Raspian Lite and are logged in with an account that has super user (sudo) privileges, it is time to get to work installing all of the components of your Raspberry Pi Web Server. The following command will install Apache 2 (web server), MariaDB (Maria Database Server, which is a fork of MySQL), PHP 7.0 (a scripting language that WordPress relies on), and a few other necessary components to make everything work.

themaster@IRGOS:/home/themaster$ sudo apt-get install apache2 apache2-utils mariadb-server mariadb-client php7.0 libapache2-mod-php7.0 php7.0-mysql php-common php7.0-cli php7.0-common php7.0-json php7.0-opcache php7.0-readline

Once all of the packages have completed installation you should be able to view the Apache test page by entering http://IPADDRESS (replace IPADDRESS with your Pi’s IP address) into the browser of your choice on your local network.

Secure the MariaDB Installation

themaster@IRGOS:/home/themaster$ sudo mysql_secure_installation

Super user permissions are required. Enter your password, if prompted.

themaster@IRGOS:/home/themaster$ [sudo] password for themaster:

You will be prompted for the current root password of MariaDB. Since there is currently no password, press Enter.

themaster@IRGOS:/home/themaster$ Enter current password for root (enter for none):

You will now have the opportunity to set the root password. I highly encourage you to set this to its own password. Make it an extremely complex password. Use a password manager to save it.

themaster@IRGOS:/home/themaster$
Change the root password? [Y/n] y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
... Success!

You will be asked if you would like to perform additional tasks. For the sake of increased security I would recommend answering ‘Y’ (Yes) to all of them.

themaster@IRGOS:/home/themaster$
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, MariaDB 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...
... Success!
- 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 MariaDB
installation should now be secure.

Thanks for using MariaDB!

Install phpMyAdmin

This will allow for easy management of databases.

themaster@IRGOS:/home/themaster$ sudo apt-get install phpmyadmin

You will be prompted to select the web server that should be automatically configured to run phpMyAdmin. Select the apache2 option.

You will also be prompted to configure a database for phpmyadmin using dbconfig-common. When this prompt appears, select Yes.

You will then be prompted to enter a password for phpmyadmin.

You can verify the installation was successful by navigating to http://IPADDRESS/phpMyAdmin

Create a Database Manager (User) Account

Next, we will create a new database user account that we will use for general database administration. We’ll need to create this via the command line. Afterward, we’ll be able to use it in phpMyAdmin.

themaster@IRGOS:/home/themaster$ sudo mariadb

You may need to enter your password again. After successful authentication, you will drop into the MariaDB console. You will enter the following commands to create a user and grant that user all privileges on all databases.

CREATE USER ‘USERNAME’@‘localhost’ IDENTIFIED BY ‘PASSWORD’;
 
GRANT ALL PRIVILEGES ON *.* to ‘USERNAME’@‘localhost’ WITH GRANT OPTION;
 

Once you have entered the above commands you can exit out of the MariaDB console by typing exit and pressing Enter.

themaster@IRGOS:/home/themaster$ sudo mariadb
[sudo] password for themaster:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 294
Server version: 10.1.23-MariaDB-9+deb9u1 Raspbian 9.0

Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> CREATE USER 'themaster'@'localhost' IDENTIFIED BY 'OjI4\zMxVzIwC=V';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* to 'themaster'@'localhost' WITH GRANT OPTION;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> exit
Bye

Create WordPress Database

We will now setup our WordPress database inside of phpMyAdmin. Navigate to http://IPADDRESS/phpMyAdmin. Logon using the administrative account that we just created in the MariaDB console. Once you are logged in, navigate to User accounts.

Click on Add user account.

Enter a username. My recommendation for this field is to make the username the same name as the database.

Leave the host name field set to % so the database can be accessed from anywhere.

Enter a password for the database and re-type it.

If you are following my recommendation, select the “Create database with same name and grant all privileges” option.

Click on the Go button at the bottom.

You should receive a message at the top that says “You have added a new user.” Note the line below. This is the command that you could have used in the command line (CLI). While I love the CLI, I don’t love it enough to type out that entire command! This is also a great way to learn how to perform a task in MariaDB if you’re trying to create a database driven website.

Backup Current Apache Configuration

themaster@IRGOS:/home/themaster$ cd /etc
themaster@IRGOS:/etc$ sudo cp apache2 apache2backup -r

Configure an Apache Site

We will start by disabling the default Apache site.

themaster@IRGOS:/etc$ cd apache2/sites-available
themaster@IRGOS:/etc/apache2/sites-available$ sudo a2dissite 000-default

Next, we will create a directory to store the website. My preference for this is to store the website in the home folder of a user account that is named after the website. In my examples, I’m creating a website called IRGos so I will create an account named irgos.

themaster@IRGOS:/etc/apache2/sites-available$ sudo adduser irgos

If you’re wondering why I do this: I prefer to not have my website in the home folder of a user account that has sudo permissions. Yes, I could host the website in Apache2’s default location of /var/www/html/htdocs. However, I would then have to fiddle with permissions for FTP’ing files to the site. If I have a user account for the website, I can simply connect into the server via SFTP with that user account and have read/write permissions by default. If I ever needed to host a website for someone else, I could create an account for them or their website and it would be in its own little world.

Once you have the website account created, we will switch into it to create some directories. I will apologize in advance. I will be having you to switch between this account and themaster (or whichever account you use that has sudo permissions) quite often. If it is easier for you, you may choose to have two SSH sessions open at the same time.

themaster@IRGOS:/etc/apache2/sites-available$ su irgos

Enter the password for the site user account.

Next, we will create a folder structure in which to store our website files. It will look like the following:

  • htdocs
    • logs
    • public_html
  • scripts
  • temp

htdocs is where we will store all of our website files.

scripts is where we will store the backup scripts.

temp will be used when a backup operation is in progress.

irgos@IRGOS:/home/irgos$ mkdir htdocs scripts temp
irgos@IRGOS:/home/irgos$ cd htdocs
irgos@IRGOS:/home/irgos/htdocs$ mkdir logs public_html

We will now create the .log files in the logs folder.

irgos@IRGOS:/home/irgos/htdocs$ cd logs
irgos@IRGOS:/home/irgos/htdocs/logs$ touch {access,error}.log

We will now create a symbolic link in /var/www/html to /home/irgos/htdocs/public_html

We do this because Apache is configured to host files out of /var/www/html by default. Yes, we could change this in the Apache configuration. However, creating a symbolic link will allow us the ability to host multiple websites for several users on the system, should we choose to do so.

You will need to drop out of the site user account to do this. Type exit and press Enter to return to your account with sudo privileges. Then enter the following command to create the symbolic link.

themaster@IRGOS:/etc/apache2/sites-available$ sudo ln -sf /home/irgos/htdocs /var/www/html/irgos.com

Setup the Apache VirtualHost

Navigate to the sites-available directory if you are not already there.

themaster@IRGOS:/etc/apache2/sites-available$ cd /etc/apache2/sites-available

Copy the default configuration file to a new file for your site.

themaster@IRGOS:/etc/apache2/sites-available$ sudo cp 000-default.conf irgos.com.conf

Delete the default configuration file (remember, we have already made a backup of this). I suggest removing this so that it does not get enabled by accident.

themaster@IRGOS:/etc/apache2/sites-available$ sudo rm 000-default.conf

Open the newly created configuration file and modify it to match the following (replacing folder names & domain names where applicable).

themaster@IRGOS:/etc/apache2/sites-available$ sudo nano irgos.com.conf

In Nano you can use Ctrl + K to quickly delete all of the lines of text.

Listen 80
<VirtualHost IPADDRESS>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request’s Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
ServerName www.irgos.com

ServerAdmin webmaster@irgos.com
DocumentRoot /var/www/html/irgos.com/public_html

# Available loglevels: trace8, …, trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn

ErrorLog /var/www/html/irgos.com/logs/error.log
CustomLog /var/www/html/irgos.com/logs/access.log combined

# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf

</VirtualHost>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

We now need to activate the site that we just created and restart Apache2.

themaster@IRGOS:/etc/apache2/sites-available$ sudo a2ensite irgos.com.conf
themaster@IRGOS:/etc/apache2/sites-available$ sudo apachectl -k graceful

Open the apache2.conf file and ServerName localhost to the bottom to suppress the “Unable to determine FQDN” message. Then re-run the apachectl -k graceful command.

Setup WordPress

Download WordPress from WordPress.org and extract the ZIP file.

Note that I’ll be using my regular desktop computer (Windows) for a lot of the following tasks.

Rename wp-config.php to wp-config.php then open it (in Notepad, Notepad++, etc.).

Add your database details to the following section:

// ** MySQL settings – You can get this info from your web host ** //
/** The name of the database for WordPress */
define(‘DB_NAME’, ‘your_database’);

/** MySQL database username */
define(‘DB_USER’, ‘your_database_user’);

/** MySQL database password */
define(‘DB_PASSWORD’, ‘your_database_password’);

/** MySQL hostname */
define(‘DB_HOST’, ‘localhost’);

/** Database Charset to use in creating database tables. */
define(‘DB_CHARSET’, ‘utf8’);

/** The Database Collate type. Don’t change this if in doubt. */
define(‘DB_COLLATE’, );

Navigate to the WordPress unique phrase generator website. Copy the newly generated phrases over what is already in the configuration file.

Save the wp-config.php file.

Re-connect to your server using an FTP client. Use the site credentials. I’ll be using FileZilla.

Navigate to the /home/irgos/htdocs/public_html folder.

Upload all of the WordPress files.

Navigate to http://IPADDRESS (replace IPADDRESS with the IP address of your Pi).

You should now be greeted with the WordPress installer screen. Follow the instructions on the screen to configure your web site.

Must Have Plugins

SMTP Mailer Plugin

If you are going to use your installation of WordPress offline in an Intranet environment, the SMTP Mailer plugin is crucial to allow WordPress to send email messages. In the server’s current configuration no email messages will be sent. Using this plugin will allow you to connect your WordPress installation to an SMTP server to allow outgoing messages from WordPress. If you are using Gmail or gSuite (formerly Google Apps, Google Apps for Domains) you will have to enable the option in your settings that allows for less secure applications to connect to the SMTP server (as a security conscious person, this makes me cringe). This will not work if you have two-factor authentication enabled. A more secure option would be to use the Gmail SMTP plugin. If you would prefer to use that option, after we get our server moved online we can setup that plugin.

To enable the “Allow less secure apps” option (again I cringe), login to your Google account. Go to the “My Account” page. Click on the link for “Sign-in & security” then scroll down to the section titled “Apps with account access” and turn on the “Allow less secure apps” option.

Because this is a less secure option, I would highly encourage that if you have any sensitive information in the account you were planning to use, that you create another account. Perhaps create a “no-reply” account as you have undoubtedly seen utilized on thousands of websites.

Download the SMTP Mailer plugin and extract the ZIP file.

Upload the extracted files to /home/username/htdocs/public_html/wp-content/plugins

While logged into your WordPress installation, click on the Plugins link.

Activate the SMTP Mailer plugin. Click on the Settings button.

For Gmail or gSuite, use the following settings:

SMTP Host: smtp.gmail.com
SMTP Authentication: True
SMTP Username: Your Gmail address or your gSuite address.
Type of Encryption: TLS
SMTP Port: 587
From Email Address: Your Gmail address or your gSuite address.
From Name: Use what you would like your recipients to see.

You should now be able to click on the Test Email tab and send a test email message. Another way to test this would be to logout of WordPress and select the “Lost your password?” option. Enter your username. You should receive an email in your mailbox with a link to reset your password.

WP-DBManager

Next, we need to setup a method for backing up the WordPress database. My recommendation is the WP-DBManager plugin.

Download the plugin and extract the ZIP file.

Connect to your Pi via sFTP and navigate to /home/irgos/htdocs/public_html/wp-content and create a directory named “backup-db”

Open the newly created directory.

From the contents of the extracted plugin (wp-dbmanager.2.79\wp-dbmanager), upload the htaccess.txt file then rename the file to .htaccess

Go back up one level. Right click on the newly created directory and select File permissions.

Enter 777 into the Numeric value field.

Select the “Recurse into subdirectories” and “Apply to all files and directories” options.

Upload the extracted plugin files (the wp-dbmanager folder within the wp-dbmanager.2.79 folder) to /home/irgos/htdocs/public_html/wp-content/plugins

While logged into your WordPress installation, click on the Plugins link.

Activate the WP-DBManager plugin.

From the sidebar, click on the Database option.

Select the “DB Options” option. This is where you definitely want to make some changes. You will want to setup automatic backups. Select a schedule that reflects how often you plan to make changes to your WordPress site. I do recommend using the Gzip option. It is a good idea to run automatic database optimization and repair at least once per month. At the bottom you configure the backups to be emailed to your preferred email inbox.

Other options you may find useful:

The Database option will show you local server information and the tables from your WordPress database that will be backed up.

Click on the Backup DB option. This is where you can confirm that all of your settings are good to go. Additionally, at the bottom, there is an option to GZIP the database backup file. The default is set to “No” but I generally change this to “Yes.”

The Manage Backup DB option will allow you to select a specific database backup and either email, download, restore, or delete it.

The Optimize DB option will allow you to run a database optimization on your tables.

The Repair DB option will allow you to repair your database tables.

The Empty/Drop Tables option is dangerous. Be careful with it. This one allows you to empty the contents or delete a database table.

If you’d rather not connect to the MariaDB console or access phpMyAdmin, you can run SQL queries from the Run SQL Query option.

Akismet Anti-Spam

While I do not plan to go into the details of how to setup Akismet, I will say two things: 1.) If your website is publicly accessible and has a high volume of traffic, definitely set it up. 2.) While I am fully aware that my website does not receive a ton of traffic, I do not have the plugin enabled on this site and I rarely receive comment spam. Should that change, I will re-enable it or another option.

The main reason I stopped using Akismet was due to needing to have a license for several websites. Now that I have merged all of my websites into one, this may be another reason to re-enable Akismet.

For internal intranet sites I don’t think it is necessary unless you think internal users will abuse the comments.

Backup Site Files

In the plugins section I wrote about backing up the WordPress database. Now we need to also backup the actual website files. We also need a way to get them off of the Pi’s microSD card in case it becomes corrupted. I personally think offloading these files to Dropbox is the best solution.

Once again we need to switch into the site user’s account.

themaster@IRGOS:/etc/apache2/sites-available$ su irgos

Change into the scripts directory.

irgos@IRGOS:/home/irgos$ cd /home/irgos/scripts

Next, we will download Andrea Fabrizi’s Dropbox-Uploader script using curl.

irgos@IRGOS:/home/irgos/scripts$ curl "https://raw.githubusercontent.com/andreafabrizi/Dropbox-Uploader/master/dropbox_uploader.sh" -o dropbox_uploader.sh

Because we could potentially have additional sites running on this server that we may want to backup to different Dropbox accounts, we will want to edit the dropbox_uploader.sh script. By default, the script places a configuration file into the root user’s home directory. We will change this to our site user account’s home directory.

irgos@IRGOS:/home/irgos/scripts$ nano dropbox_uploader.sh

We will modify the CONFIG_FILE line

FROM:

CONFIG_FILE=~/.dropbox_uploader

TO:

CONFIG_FILE=.dropbox_token

You will notice that I changed the name of the file. The reason for this is because the only thing contained within this file is the token we will generate shortly.

Save and exit the file.

The script will need execute permissions in order to run. Unfortunately, we will once again need to switch users. We’ll switch to themaster account and then exit it so that we are back at the command line for the site user account.

irgos@IRGOS:/home/irgos/scripts$ su themaster
irgos@IRGOS:/etc/apache2/sites-available$ sudo chmod 777 /home/irgos/scripts/dropbox_uploader.sh

Type exit and press Enter to return to the site user account.

From a web browser logon to Dropbox. After you have logged onto Dropbox, access the Dropbox Developer website.

As of 10/14/2017, there is a link in the middle of the page titled “Create your app.” Click on that link.

Select the Dropbox API.

Select the App folder option.

Name your app. Example: Website Backup

Click on Create app.

Now we will run the Dropbox Uploader script so that we can enter an access token for the application that we created on Dropbox.

irgos@IRGOS:/home/irgos/scripts$ ./dropbox_uploader.sh

When prompted, you will enter an access token that you generate on the Dropbox website.

Once you have entered the token and confirmed that it looks good, we will upload a file to Dropbox to make sure that it works. For convenience we will simply upload the dropbox_uploader.sh script. Don’t forget the “.” at the end of the command. This will put the file into the root of our application folder in Dropbox.

irgos@IRGOS:/home/irgos/scripts$ ./dropbox_uploader.sh upload dropbox_uploader.sh .

If successful you should see the following in the terminal:

irgos@IRGOS:/home/irgos/scripts$ Uploading "/home/irgos/scripts/dropbox_uploader.sh" to "/dropbox_uploader.sh"... DONE

You should now see the file in the folder for the app that we created within Dropbox.

We will now create another shell script that will backup the site user’s home directory to a compressed file and upload it to Dropbox.

irgos@IRGOS:/home/irgos/scripts$ nano irgos_site_files_backup.sh

Once the file is open, paste in the following. Modifying paths where necessary.

#!/bin/bash

DATE=$(date +"%d-%m-%Y_%H%M")
BKP_FILE="/home/irgos/temp/irgos_site_files_backup_$DATE.tar"
BKP_DIRS="/home/irgos/htdocs /home/irgos/scripts /etc/apache2/sites-available/irgos.com.conf"
DROPBOX_UPLOADER=/home/irgos/scripts/dropbox_uploader.sh

tar cf "$BKP_FILE" $BKP_DIRS
gzip "$BKP_FILE"

$DROPBOX_UPLOADER -f /home/irgos/scripts/.dropbox_token upload "$BKP_FILE.gz" .

rm "$BKP_FILE".gz

Save and exit the file.

We need to make this script executable as well. By now you know the drill. Switch to an account with sudo privileges and execute the following command.

themaster@IRGOS:/etc/apache2/sites-available$ sudo chmod 777 /home/irgos/scripts/irgos_site_files_backup.sh

Save and exit the file. Type exit again to return to the site user account.

Finally, we will setup a cron job to automate the backup/upload process. Run the following command and select your preferred text editor. I prefer nano.

irgos@IRGOS:/home/irgos/scripts$ crontab -e

Enter the following at the bottom of the file, replacing “m” “h” “dom” “mon” “dow” with the appropriate values (additional information below). Once you have the command in place, save and exit the file.

m h dom mon dow /home/irgos/scripts/irgos_site_files_backup.sh

m = minute
h = hour
dom = date of month (1 – 31)
mon = month (1 – 12)
dow = day of week [0 – 6, 6 is Saturday], [0 – 7, 7 is Sunday], or [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, or Saturday]

Additionally, instead of specifying the date/time as described above, you could use one of the following options:

@reboot (runs once at system startup)
@daily (runs at midnight)
@midnight (same as @daily)
@monthly (once a month)
@hourly (every hour)

Example:

@midnight /home/irgos/scripts/irgos_site_files_backup.sh

Move to the Internet

Dynamic DNS

Unless your ISP provides you with a static IP address, you will need to subscribe to a service that captures your router/modem’s public IP address and reports that back to their DNS servers as it changes.

No-IP Setup

Because I already pay for NO-IP services, this is the dynamic DNS service that I will write instructions for in this article. There are other dynamic DNS services out there. You may prefer one of those better based on pricing, options, etc.

Create an account at noip.com then configure a new host.

Login to the site account on your Pi via SSH and run the following commands from the root of that user’s home directory (i.e. /home/siteuser:

NOTE: The following instructions were taken from No-IP’s knowledge base with slight modifications.

themaster@IRGOS:/home/mydomain$ mkdir noip

Open the noip directory.

themaster@IRGOS:/home/mydomain$ cd noip

Next you will use wget to download the No-IP Dynamic Update Client (DUC).

themaster@IRGOS:/home/mydomain/noip$ wget http://www.no-ip.com/client/linux/noip-duc-linux.tar.gz

Issue the following command to untar (extract) the DUC.

themaster@IRGOS:/home/mydomain/noip$ tar vzxf noip-duc-linux.tar.gz

Open the newly created directory.

themaster@IRGOS:/home/mydomain/noip$ cd noip-2.1.9-1

Next you will run the commands to make and run the installer.

themaster@IRGOS:/home/mydomain/noip$ sudo make
themaster@IRGOS:/home/mydomain/noip$ sudo make install

You will enter your login credentials for No-IP.com, select the hostname to update, and the interval at which to update the hostname. I generally set mine to the default 30 minutes.

Next you will need to configure the No-IP DUC to launch when the Pi starts. Great instructions for doing this are available on westernwillow.com.

Once you have followed those instructions and rebooted your Pi you can run the following command to confirm that the No-IP client is running.

themaster@IRGOS:/home/mydomain$ sudo /usr/local/bin/noip2 -S

A Matter of Security

At the beginning of this article I suggested that if you had not, you should follow my previous blog article, Setting up the Raspberry Pi Zero, Zero W, or Pi 3 with Raspbian Stretch Lite. If you haven’t, I highly recommend going through it. You will learn how to configure user accounts, two factor (certificate based) authentication, a firewall, and additional ways that you can and should enhance the security of your Raspberry Pi before you place your project onto the Internet.

Move Pi to the DMZ

At this point you should be good to move your Pi into the DMZ. This will place your Pi directly onto the Internet. That is, if your ISP does not block web server traffic. Once you do have your Pi in the DMZ, start attempting to access the web site by entering your public IP address (if web server traffic is not blocked) or your No-IP hostname into your browser’s address bar. You may want to try it from an external network (mobile/cell network) if you are not having any luck. If you do get connected, you will then want to work on getting your domain name forwarded to your No-IP hostname.

Unfortunately, because almost everyone reading these instructions has a different router, it would be impossible for me to tell you how to put your Pi into the DMZ. What I can do is show you how I do have done it with my Century Link Actiontec C1000A. It will be pretty similar on most other routers.

Login to the web based admin.

Go into the Advanced Setup options.

Under the Security options, select DMZ Hosting.

Enter the IP address of your Pi and click on Apply.

If your current public IP address has had enough time to propagate through the Internet then you should be able to access your NO-IP hostname from ANOTHER network (cell/mobile phone).

In order to access your NO-IP hostname from within your own network, you’re going to have to fake it. What I mean is you will have to go to the DNS Host Mapping settings and link your NO-IP hostname to your Pi’s local IP address.

Fixing WordPress URLs

If you are successful in accessing your web server remotely you may notice that some of the URLs try to go to your Pi’s local IP address. This is because when we installed WordPress we installed it locally. Yes, we could have waited until we got everything else setup, but I wanted to have WordPress fully functional before putting the server online. This is easy to correct.

Navigate to http://IPADDRESS/phpmyadmin (you can also use http://NOIPHOSTNAME if you have made the DNS Mapping change to your router) and login using your site account’s WordPress database.

If it isn’t already, expand the database in the left sidebar.

Click on wp_options.

Under option_name you will see siteurl and home. Use the Edit button to update these values to your NOIP hostname.

Setting up the Gmail SMTP Plugin

Earlier in this post I provided instructions for setting up a WordPress plugin called SMTP Mailer. We installed this plugin because without it WordPress would not be able to send out email messages in the server’s current configuration. Unfortunately, if we use this plugin to connect to a Google account, we must enable an option that downgrades our security. The instructions in this section are for the Gmail SMTP Plugin, which allows us to take advantage of the full security offerings of a Google account. Now that we have the server online, this plugin will work.

Note that I was unable to get this plugin to work while having 2-factor authentication enabled. Which is unfortunate.

The plugin developer does have instructions on their site. However, the instructions are a bit out of date. So I will walk you through the steps of getting this setup.

I was unable to get this to work using one of my gSuite accounts. It appears as though the free version of gSuite does not allow its users to take advantage of the Google Developer Console. I started using Google Apps for Domains (what is now known as gSuite) many, many years ago when it was in beta and free. I believe for me to utilize one of those accounts I would have to upgrade my gSuite account to a paid account. At the moment I would rather not have to pay for yet another service. The good news is that you can utilize the Google Developer Console from a free Gmail account.

Download the Gmail SMTP plugin and extract the ZIP file.

Upload the extracted files to /home/username/htdocs/public_html/wp-content/plugins

While logged into your WordPress installation, click on the Plugins link.

Activate the Gmail SMTP plugin. Click on the Settings button.

In a separate tab, login to your Google account and navigate to the Google Developer Console website.

Click on the Create Project button.

Give your project a name then click on Create.

Currently, the Gmail API is listed as a popular API. Click on the Gmail API icon in the list of popular APIs.

Click on Enable

We will now create credentials that the Gmail SMTP plugin will use to access your Gmail account.

Click on the Create Credentials button.

We will leave the option Which API are you using? set to Gmail API.

In the Where will you be calling the API from? options we will select Web server.

Under What data will you be accessing? select User data. Click on the What credentials do I need? button.

You will now be presented with the form to create an OAuth 2.0 client ID. Provide a name for the client ID.

In the Authorized JavaScript origins you will need to place your website URL.

In the Authorized redirect URIs field, you will need to copy this address from the Gmail SMTP settings panel within WordPress.

If you do not click on anything the values that you enter will automatically appear above the form field. This would allow you to enter additional URL or URIs.

Click on Create client ID.

On the next screen you will need to create a Product name. Click on Continue.

You will be presented with the Client ID. Copy this to the Client ID field in the Gmail SMTP plugin settings page.

On the Google Developer Console page you will also be presented with an option to download the credential information in JSON format. Download the file. Open the file in Notepad. You will have to get the “client_secret” code to paste into the Gmail SMTP settings. You will want everything between the parenthesis. Do not include the parenthesis.

Sidenote: While writing these instructions I ran through this process multiple times. After having deleting the credentials and re-creating them I would occasionally get a pop-up with the Client ID and Client Secret. Which is much simpler than downloading the JSON file. However, either option will work.

Complete the rest of the fields in the Gmail SMPT settings in WordPress.

Click on the Save Changes button.

Once the page reloads, click on the Grant Permission button.

You will be prompted to login to your Google account. Login to the account we are setting up authentication for.

You will be taken to a screen that states This app isn’t verified. Click on the Advanced link and choose the Go to URLHERE unsafe option.

Grant the permission for your application to use your Gmail account by clicking on Allow.

You should be taken back to your Gmail SMTP settings panel. The SMTP Status should now be green with a checkmark.

You can test the connection by clicking on the Test Email tab and composing an email to yourself. It would also be a good idea to logout of WordPress and pretend you forgot your password to ensure you receive an email from the site. Also, it would be a good idea to confirm your database backups still get delivered to you.

If you are like me and need to switch your email address in WordPress from a gSuite address to a free Gmail account. You can do this in WordPress by clicking on the Settings button. Then click on the General button. Then change the email address in the Email Address field. Click on Save Changes at the bottom.

One Final Backup

After you have completed all of the above steps, it would be a shame if the microSD card became corrupted. I highly recommend that at this time you make another backup of your microSD card so that you will be even further along should you need to flash another microSD card.

Raspbian Stretch Lite Secure Baseline Setup

The purpose of this tutorial is to walk you through the process of making an installation of Raspbian Stretch Lite more secure. Which you can then create your own image from to use as a baseline setup for future Raspberry Pi projects.

This tutorial assumes that you already know how to flash a microSD card with Raspbian. It also assumes that you are already somewhat familiar with setting up and using a Raspberry Pi.

User Setup

The first thing we will do to improve the security of our setup is to add a new user account with SUDO privileges, remove the default user (pi) account and home directory (/home/pi), and change the root user password.

Add a New User Account with SUDO Privileges

Raspbian has a default user account named pi that has SUDO (super user) privileges. We want to logon to this account and create a new account with SUDO privileges. Once we create the new account we will remove the pi account. Go ahead and logon to Raspbian using the standard credentials. Currently as of 11/4/2017, Username: pi, Password: raspberry

Issue the following command to add a new user:

pi@raspberrypi:/home/pi$ sudo adduser USERNAME

I am going to use themaster as my username. A little reference to Doctor Who. This isn’t actually what I will use in the real world (sorry hackers). I just needed something for training purposes and for some reason this is the first thing that came to my mind. In my future Raspberry Pi tutorials you will see this theme re-emerge as I plan to use these setup instructions as my baseline setup for future tutorials.

You will be prompted for information about the user. It’s not necessary to include anything here. You can skip the questions by pressing enter. Then type “y” at the end to confirm the information is accurate.

We will now want to change the password of the newly created account:

pi@raspberrypi:/home/pi$ sudo passwd themaster

We will now add the user to the sudo group. This will allow themaster to have super user privileges.

pi@raspberrypi:/home/pi$ sudo usermod -a -G sudo themaster

Delete the Default “pi” Account

It is now time to say goodbye to the pi account. Logout by typing exit and pressing Enter. You should now be back at a logon screen.

Logon with the newly created account.

We now want to make sure that our new user account has sudo permissions. The easiest way to test this is to issue the following command. Only users who have sudo permissions are allowed to issue this command.

themaster@raspberrypi:/home/themaster$ sudo visudo

If successful, this will load the sudoers file. To exit the file, simply press Ctrl + X at the same time.

We will now issue the command to delete the pi account.

themaster@raspberrypi:/home/themaster$ sudo deluser pi

We will also need to ensure the pi account home directory is also deleted.

themaster@raspberrypi:/home/themaster$ sudo rm -r /home/pi

Change the “root” Account Password

themaster@raspberrypi:/home/themaster$ sudo passwd root

System Settings

We will now run the raspi-config program to make the following changes.

  1. Resize the filesystem to take advantage of the entire microSD card.
  2. Decrease the amount of memory being dedicated to the GPU.
  3. Change the hostname.
  4. Change the locale and timezone.
  5. Enable SSH for remote administration.
themaster@raspberrypi:/home/themaster$ sudo raspi-config

Some of these options will require a reboot before the changes will take effect. You can reboot when prompted or wait until we have completed all of the steps. I prefer to complete as many steps as I can before I have to reboot. I will let you know when I reboot.

Starting with the second option, 2 – Hostname, we will change the default hostname from raspberrypi to baseline. Since we’re going to use this to get future projects off the ground faster, when I flash a new microSD card with this image, I will already know what the hostname is. We’ll talk about it more in the new project setup tasks section, but when I do start a new project, I would change this hostname to reflect the project I am working on.

Example 1: In my next article I am writing about how you can use the Raspberry Pi as a web server. I used my IRGos test website to write the tutorial. So for the hostname I used irgos.

Example 2: In the past I have experimented with using a Raspberry Pi Zero as a car dashcam. For that project I used the hostname dashcam.

Next we will expand the filesystem. Select 7 – Advanced Options then A1 – Expand Filesystem. This will ensure that Raspbian has access to the entire available space of the microSD card.

From within 7 – Advanced Options, select A3 – Memory Split. On my projects where I don’t utilize a graphical user interface (GUI), I take this option all the way down to 16 megabytes (MB).

We will now change the locale. Select option 4 – Localisation Options. Then select I1 – Change Locale. Since I am in the United States I will use en_US.UTF-8 UTF-8. Select en_US.UTF-8 again to use it as the default locale for the system.

You will be taken back to the main menu. We need to go back into option 4 – Localisation Options. Then select Change Timezone. Select US then your timezone.

The settings will apply and you will again be taken back to the main menu.

To get into the system we will enable SSH. Select 5 – Interfacing Options. Then select P2 – SSH.

Once you have enabled SSH you can exit out of raspi-config. You will be prompted to reboot. Go ahead and allow the Pi to reboot at this time.

Configure a Static Ethernet IP Address

Static IP Assignment via MAC Address

In my opinion, the best option for configuring a static IP address is to have your router apply the IP address based on the MAC address of the device. I utilize this option on my network. Why?

Scenario 1: If I have my Pi connected to the switch that I have in the demilitarized zone (DMZ) it will receive one IP address. If I need to take the Pi offline and move it back onto my private network I can do so without logging back into the Pi to change the static IP address or turn off static IP addressing. It will then receive an IP address for my private network.

Scenario 2: I have a couple of Pi boards that I use for testing of miscellaneous projects. Using router based addressing allows me to print the IP address that I know the router will assign to those Pi boards.

In both of the above scenarios: 1.) The need for me to logon to the Pi to see what IP address has been assigned, 2.) The need to connect the Pi to a monitor to check the IP address, and 3.) The need to connect into my router’s console to see what IP address it assigned have all been eliminated.

Every router is different so you will have to read through your router’s manual in order to determine how to do this. However, I can tell you how I do it on my TP-LINK (TL-WDR4300) and Century Link (Actiontec C1000A) routers.

First, we need to determine your MAC address:

themaster@webserver:/home/themaster$ ifconfig

Look for the ether address in your Ethernet adapter information. If you are using a Pi with built-in Ethernet it should be listed as eth0. It will look something like this: r8:74:er:e9:4c:9e (invalid MAC address, by the way, but this is what they look like).

On my TP-LINK router, after I logon I click on DHCP then Address Reservation. I then click on Add New and supply the MAC Address of the Pi and the IP address that I would like to have reserved for the Pi. One thing to note here, the Pi will display it’s MAC address to you with colons. In my experience, you have to use hyphens instead of the colons when reserving an address on this TP-LINK router.

Once you save you will have to allow the router to reboot before the changes occur. You will then also have to reboot the Pi, but only after the router has fully rebooted.

On my CenturyLink router, after I logon I click on the Advanced Setup button. Then the DHCP Reservation link on the sidebar. Enter your MAC address into Step 4. Then in Step 5 you will select an IP address to associate with the MAC address. Click on Apply in Step 6. Allow the router to reboot.

Static IP Assignment via the dhcpcd.conf File

If you don’t have the option to use your router to assign a static IP address, you will have to do it manually via the dhcpcd.conf file.

We will use a program called nano (a text editor) to edit the dhcpcd.conf file which is located in the /etc directory.

themaster@webserver:/home/themaster$ sudo nano /etc/dhcpcd.conf

Look for the section in the file that provides an example static IP configuration. I like to put mine below the example, leaving the example in case I need to reference it in the future.

interface eth0
static ip_address=192.168.1.87/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1 8.8.8.8
 

The last IP address in static domain_name_servers, 8.8.8.8, is for Google’s public DNS servers. You do not have to add it.

Save and exit the file.

Now is a good time to go ahead and reboot.

themaster@webserver:/home/themaster$ sudo reboot

Connect to the Pi via SSH and SFTP

After the Pi reboots we will connect into the Pi using SSH and SFTP. I use two programs for these tasks. To connect in via SSH I use PuTTY. For SFTP connections I use FileZilla.

Once you have PuTTY installed. From the main screen you should be on the Session settings. In the Host Name (or IP address) field, enter your Pi’s IP address. Port should remain 22. Connection type should remain SSH. In the Saved Sessions field, enter a name for the connection. I usually use the Pi’s hostname. Click on Save. You can then click on the Open button to connect.

Once you have FileZilla installed. We will open the Site Manager and create a new connection. In the Host field, enter your Pi’s IP address. Leave the Port field blank, but be sure to select SFTP – SSH File Transfer Protocol from the Protocol drop-down.

For the Logon Type select Normal and supply the username and password. Click on Connect.

Two-factor Authentication

Now that we are able to connect into the Pi without actually having to sit in front of it, this makes administration a little easier. However, it also makes the system more vulnerable. We have made the system more secure by making a new user for system administration, deleting the old default account (pi), and changing the password for the root account. Unfortunately, it’s not enough. Though, in the times we live in, there is never enough security! The most secure computer is one that is not turned on! But what fun is that?

We can increase security further by enabling two-factor authentication. The type of two-factor that we are going to implement on our Pi uses two keys. A private key and a public key.

The Raspberry Pi website has instructions for generating keys via ssh-keygen. I prefer to use the PuTTY Key Generator. The Raspberry Pi website instructions do not instruct you to add a passphrase. I disagree with that. I think you should.

Another option for two-factor is Google Authenticator. Digital Ocean has instructions for setting this up. I really wanted to use this option because I think it’s fantastic. However, all of the programs I use for connecting to and managing my Pi are much friendlier to certificate based authentication.

During the installation of PuTTY, PuTTY Key Generator should have also been installed. On Windows, it should be on the Start Menu. I can usually get to it by searching for it on Windows through Cortana search. If not, it’s located at: C:\Program Files (x86)\PuTTY\puttygen.exe

From the main screen, in the Actions section, click on Generate.

You will see an instruction at the top to move your mouse cursor over the blank space.

Once a key has been generated you will see the new public key, a fingerprint and comment.

Make sure to add a key passphrase!

Save the public and private keys. I keep these in a cloud storage account so that if I am mobile and need to logon to a server I can easily retrieve the key file.

Return to the SSH connection you have established with your Pi:

themaster@webserver:/home/themaster$ mkdir /home/username/.ssh

The above command will create a hidden directory named .ssh

We now need to get the public key that we created via PuTTY Generator into that newly created folder in a file named authorized_keys.

Access the .ssh directory:

themaster@webserver:/home/themaster$ cd .ssh

Create the authorized_keys file:

themaster@webserver:/home/themaster/.ssh$ nano authorized_keys

You should now be able to copy and paste the public key that was generated by PuTTY Key Generator into this file.

Save and exit the file using Ctrl + X.

We now need to change the permissions of the authorized_keys file:

themaster@webserver:/home/themaster/.ssh$ chmod 644 authorized_keys

We now need to edit the sshd_config file located at /etc/ssh/sshd_config (this will require sudo privileges):

themaster@webserver:/home/themaster/.ssh$ sudo nano /etc/ssh/sshd_config

In the file, change all of the following options to NO:

  • PasswordAuthentication
  • PermitEmptyPasswords
  • ChallengeResponseAuthentication
  • UsePAM

Once you have changed those options to No, save and exit the file using Ctrl + X.

Restart the SSH server:

themaster@webserver:/home/themaster/.ssh$ sudo service ssh reload

We now need to go back into PuTTY and modify our connection.

Click on the connection within PuTTY and select Load.

From the Category sidebar, expand SSH and select Auth. At the bottom of the list of options you will see Private key file for authentication. Click on Browse and select your private key file.

Return to the Session options screen. Click on Save to save the new authentication method.

Upon re-connecting to the server you will be prompted for the user that you would like to logon as and the passphrase for that user’s private key.

We will also need to update our connection settings within FileZilla.

Access the Site Manager. Change the Logon Type from Normal to Key file. A username will still need to be supplied, but you will now authenticate off of the private key file that you specify. Upon reconnection you will get another pop-up to enter the passphrase.

This only changes how you logon to the server. As you are performing administration tasks on the Pi, when you are prompted for your password, you will still supply the actual account password.

Install a Firewall

A firewall may be overkill for your project. However, if it’s going to be publicly accessible, it’s a must.

The instructions below were taken from the Raspberry Pi website.

The Firewall we are going to install is called UncomplicatedFirewall or UFW. It is incredibly easy to setup and use.

themaster@webserver:/home/themaster$ sudo apt-get install ufw

For the projects you will be implementing on your Pi, you will need to find out which port they require to be open. We’ll go ahead and allow port 22 through since we will need SSH access.

You can specify the port number:

themaster@webserver:/home/themaster$ sudo ufw allow 22

You can specify the protocol by name:

themaster@webserver:/home/themaster$ sudo ufw allow ssh

The next command will enable the firewall:

themaster@webserver:/home/themaster$ sudo ufw enable

I do agree with the Raspberry Pi website’s instruction of limiting SSH login attempts. By issuing the following command, if more than 6 login attempts occur within 30 seconds, the attempt will be denied:

themaster@webserver:/home/themaster$ sudo ufw limit ssh/tcp

Install fail2ban

As suggested by the Raspberry Pi website we will also install the fail2ban program for additional security.

themaster@webserver:/home/themaster$ sudo apt-get install fail2ban

There are just a couple of configuration changes we need to make for fail2ban to work properly.

themaster@webserver:/home/themaster$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

You can view the configuration by opening the configuration file:

themaster@webserver:/home/themaster$ sudo nano /etc/fail2ban/jail.local

Update Raspbian

You will want to check for and install any available updates from time to time. At least once per month.

The following command will update your install of Raspbian as close to the downloadable image file as possible.

themaster@webserver:/home/themaster$ sudo apt-get dist-upgrade

The next section talks about creating a backup image of your microSD card. Don’t forget to make a new one after you have applied system updates in the future.

microSD Card Backup

Now that you have got your Pi setup with a good baseline set of security standards, now would be a good time to make a backup of it. With this backup you can quickly get a project off the ground. All you will have to do is change the hostname so that it doesn’t conflict with another system on the network and make sure it’s got its own IP address.

Making a backup is easy. I will walk you through how I do it on Windows using a program called Win32 Disk Imager.

First, you’ll want to shutdown the Pi:

themaster@webserver:/home/themaster$ sudo poweroff

Remove the microSD card and connect it into your Windows desktop.

Next, right click on your desktop or inside of a folder then select New > Text Document.

Before pressing Enter… Let’s give it a new filename.

I recommend something like: baseline_32GB_2017_11_12.img

baseline: Because this is our baseline image.

32GB: Because this is the size of the microSD card that I am backing up. Unfortunately, using this method, you will only be able to write the image back out to a microSD card that is the same size or larger.

Additionally, this is going to create a rather large .IMG file. Make sure you have enough space on your hard drive to create the .IMG file. A 32GB microSD card could result in an .IMG file that is close to 32GBs. We can use a program such as 7Zip to compress it after it has been created. Just know you’re still going to need to write the image to the same size card or larger.

Date: The date, so I will know when I made this backup IMG file.

To do this, open Win32 Disk Imager.

Allow it to make changes to the system.

Select the image file that you just created.

Ensure that your microSD card is selected in the Device drop-down.

Then click on Read.

This will read the contents of the microSD card and write them to the .IMG file.

Utilizing backups like this will allow you more flexibility in experimenting. If you get your Pi setup perfectly, but you would like to try something, make a backup before you make the change. If the change doesn’t work out, you can easily restore to the previous setup. Exactly where you left off. If the experiment does work, make a new backup!

New Project Tasks

When you are ready to start a new project and you have flashed your microSD card, there are a few things you will want to make sure that you do after your Pi is up and running.

IP Address

If you are using the same Pi for all of your projects, no need to worry about getting a new IP address.

However, if you’re using a different Pi, and you have hard coded a static IP address into dhcpcd.conf, make sure you change this to avoid IP address conflict issues. Your router may simply assign another IP address to your Pi if the one you have in your dhcpcd.conf file is currently in use. This isn’t guaranteed.

Hostname

In our backup image, the hostname is basline. I recommend changing this to more accurately describe the project you are working on.

Project Specific User Accounts

I do recommend creating separate accounts for your projects. For example, I am already working on my next blog post. In that post I am writing about how to use the Raspberry Pi as a web server. I take this baseline setup, but add on to it. I add another user account for the website that I am going to be hosting. The reason for this is because I do not want to host a website out of an account that has sudo privileges. If your project is going to be publicly accessible and doesn’t require sudo privileges, I would highly recommend this. Just make sure to generate public/private keys for this new user as well.