Simple SVN Server

I’ve recently started to teach a friend of mine, with an aspiration to embark on a career in software development, how to program. One of the aspects of software development that people often don’t get exposure to when learning how to program is version control systems. This omission means that a lot of the time when a person begins their career as a software developer their first exposure to version control systems is during their first job (if they’re not unlucky enough to work somewhere that doesn’t use version control!).

I thought it would be useful for my friend to get to grips with SVN from the get go as it’s relatively simple to learn compared to Git. I had a look for some free options that would provide multiple users for a single repository but it seemed that most of the basic SVN hosting packages only offered a single user repository. Seeing as I had a spare Raspberry Pi kicking about I thought why not set it up as an SVN server and host the server next to the Raspberry Pi that hosts this site putting it under the same domain.

For the initial set up of Raspbian you might want to follow the steps from my tutorial setting up raspbian with a web server in mind as this allows Raspbian to run from a USB stick which is more reliable than running from an SD card.

Following the set-up of Raspbian I carried out the steps below.

Subversion Installation

Install the Subverion package via the APT package handling utility.

sudo apt-get install subversion

Create a repository directory

Run the command below, the ‘-p’ flag creates nested directories if they don’t already exist. This directory will be the place all of your repositories will go, we are only going to be creating a single repository during this tutorial.

mkdir -p /home/pi/repos

Create a new empty repository

Create a new empty repository in the new ‘repos’ directory. The previous step was required as svnadmin doesn’t create intermediate repositories.

sudo svnadmin create /home/pi/repos/test

Create a project directory

mkdir -p /home/pi/projects/test

Import the project

sudo svn import /home/pi/projects/test/ file://localhost/home/pi/repos/test

This completes the set up of SVN – it’s so simple that there is no reason to not use a version control system!  Now we need to provide remote web access so that the SVN repository can be accessed remotely.

Install Apache components

To enable web access requires the installation of the Apache web server and Apache Subversion server module.

sudo apt-get install apache2 libapache2-svn

Restrict access control

As the repository can be publicly accessed we want to restrict access so that a username and password are required to check out the repository and to commit changes to the repository.

Open the apache svn module configuration file.

sudo nano /etc/apache2/mods-available/dav_svn.conf

Append the following to the bottom of the file then save and close.

<Location /svn>
DAV svn
SVNParentPath /home/pi/repos
AuthType Basic
AuthName "Subversion Repo"
AuthUserFile /etc/apache2/dav_svn.passwd
<LimitExcept GET="" PROPFIND="" OPTIONS="" REPORT="">
Require valid-user
</LimitExcept>
</Location>

Restart Apache

Restarting Apache is required so that the new configuration settings take effect.

sudo /etc/init.d/apache2 restart

Update permissions

Give the SVN server permission to modify the repository directory.

sudo chown -R www-data:www-data /home/pi/repos

Create users

I needed to create two users, one for me and one for my friend.

Create the first user, you will be asked to provide a password.

sudo htpasswd -c /etc/apache2/dav_svn.passwd calum

Notice that after creating the first user you should omit the ‘-c’ flag this is used to create the passwdfile and will overwrite the file if you use it again.

Create the second user, again you will be asked to provide a password.

sudo htpasswd /etc/apache2/dav_svn.passwd tom

The SVN server should now be accessible via a suitable SVN client. My favourite client for Windows is TortoiseSVN.

If you want to be able to access the server externally follow step 4 onwards in my tutorial Setting up WordPress on a Raspberry Pi.

I’ve been successfully running SVN on my raspberry PI for over a month with no down time. This has allowed my friend to get to grips with C# (and version control!) by building his very own version of the classic game pong!

Cutie Pi

My friend was recently feeling down so I came up with a simple project to inject some ‘aww’ into their day to cheer them up. This project also provides a good example of how to automate basic scripts on the Raspberry Pi and as my Pi was already on 24/7 hosting this site reliably I thought it would be easy to set up an automated emailing task. I wanted to set up a script that would run every day downloading and emailing cute pictures of puppies and bunnies etc, that would make my friend go ‘aww’ and would hopefully fill their day with delight.  The following tutorial is targeted at people wanting to get started writing and running Python scripts in Raspbian and who have already learnt the fundamentals of Python although this isn’t necessary as all the code is here. The following resources and techniques would allow me to do what I wanted:

  • The image hosting server Imgur would be used to provide the daily cute picture.
  • Google’s SMTP server would be used to send the email.
  • Cron would be used to automate the running of the script every day.
  • The modules provided in the Standard Library would be used to make the script pause for a random time so that the email would be sent at an unexpected time.

The environment

You should already have Raspbian loaded onto your Pi and you should be able to boot up into the terminal. If you haven’t then you should follow the first three steps of my tutorial that explains how to set up your Raspberry Pi. Once you’ve loaded up the terminal type the following command to load up the Graphical User Interface:

startx

Once the desktop has loaded you will see icons on the desktop for some of the pre-installed software that comes  bundled with Raspbian. The programs that are relevant to this tutorial is IDLE, specifically IDLE 3. IDLE  or “Integrated DeveLopment Environment” is completely written in Python and is a good basic environment to start writing Python applications with. IDLE is used for writing applications in Python 2.x and IDLE 3 is used for writing application in Python 3.x which is the most up to date version of Python and the version we will be using. Initially when Python 3.x was released Pyton 2.x libraries had to be rewritten which caused a slow adoption of Python 3, this was due to Python 3 having breaking changes and not being backwards compatible. If you load IDLE 3 you will be presented with the Python Shell. The Python Shells allows you to enter Python statements and expressions which will be immediately executed. For example below I have assigned 5 to the name x in one line and have printed the value of x + 3 on the next line. The Python Shell is great for trying out code and executing individual statements but we want to have the ability to build and automate scripts. pythonshell To create a new script select File, New Window or press Ctrl + N. When a script is saved a module is created, the name of the module is the file name without the extension and it can contain variables, functions, and classes. A module’s functionality can be imported into other modules which makes reusing functionality very easy. This will be explained in the following sections.

Organisation

Creating a number of modules will be useful when writing the code as it allows for the responsibilities of the Python program to be divided up for easy reuse later. We could have all the logic in one script but if we wanted to write another script for a different purpose that involved sending images as attachments, perhaps for emailing images in a home security application, this would be hard. Spend more time thinking about how to structure modules first to save time later! The modules that I created were:

  • imgur.py – responsible for interacting with Imgur and getting an image.
  • advancedemail.py – responsible for sending emails already preconfigured with the gmail SMTP server settings.
  • sleep.py – responsible for pausing the application to alter the time the email gets sent.
  • awwemailer.py – responsible for tying the above together. This will be the script that will be executed by Cron.

Getting the image

The first step if to create the module that will retrieve images from Imgur, a popular image hosting service. Imgur has many image categories including aww which is a category for pictures that… make you go ‘Aww!’. The popular images of the day for the ‘aww’ category can be loaded using the URL below:

https://imgur.com/r/aww/top/day

Browsing to the URL brings back the top images in your browser however this isn’t ideal for being consumed by an application. Thankfully Imgur provides a Restful API for retrieving the same information but as JSON instead of HTML. JSON is a lightweight structured format which allows our application to consume the data easily and isn’t at risk of breaking which would be the case if HTML was scraped and parsed – the HTML structure on sites often changes! The JSON version can be retrieved by appending .json to the URL.

https://imgur.com/r/aww/top/day.json

If a request to the above URL is made in a browser like Chrome the JSON will be nicely formatted and you will be able to see the meta data associated with each image, the format is designed to be human readable. To get started creating the Imgur module, double click on IDLE 3 on the desktop and then go to  File, New Window or press Ctrl + N. This will open a new Python file which you should save as Imgur.py, I saved the modules in the location /home/pi/AwwEmail. First we want to import some required modules that come packaged with Python in order to use their functionality. A third party module is also required called requests which will need to be installed. The documentation states that python requests can be installed by running the following command in LXTerminal which can be opened from the desktop along side IDLE 3:

apt-get install python-requests

However, this will only install requests for Python 2.x and as we are using IDLE 3 we require the version for Python 3.x. This can be achieved by installing the Python package manager and then installing requests:

sudo apt-get install python3-pip
sudo pip-3.2 install requests

The modules can now be imported by putting the following at the top of imgur.py:

# Requests needs downloading.
import requests

# Dealing with JSON data.
import json

# Time access and conversions.
import time

# Miscellaneous operating system interfaces.
import os

# Used for creating Universally Unique Identifiers
import uuid

Define a function that takes an Imgur category and directory as parameters:

def GetDailyTopImageForImgurCatory(imgurCategory, destinationPath):

Get the top images and generate a URL of the most popular JPEG of the day, I appended a Unique Identifier to the URL as the standard URL was being cached for some reason, not cute. The unique name and title were extracted from the JSON, the title is a caption and will accompany the image in the email to provide some context from the author:

# Get the JSON data for the top items of the day in the given category, a UUID is appended to
# the URL as the request is being cached for some reason.
r = requests.get('http://imgur.com/r/aww/top/day.json?var=' + str(uuid.uuid4()))

# Parses the JSON and creates a dictionary.
j = json.loads(r.text)

# Gets the list of images from 'data' field.
imageList = j['data']

# Extract the first JPEG from the list of images.
imageName = None
title = None

for image in imageList:
	if image['ext'] == '.jpg':
		imageName = image['hash']
		title = image['title']
		break

# Create a suitable name for the file based on the current time.
filename = time.strftime("%Y%m%d-%H%M%S")

# Generate the image URL.
url = r'http://imgur.com/{name}{ext}'.format(name=imageName, ext='.jpg')

Download the image to the specified location and return the path and title of the image, notice the second parameter passed to the open function this opens the file for writing in binary format.

# Create a suitable name for the file based on the current time.
filename = time.strftime("%Y%m%d-%H%M%S")

# Generate the image URL.
url = r'http://imgur.com/{name}{ext}'.format(name=imageName, ext='.jpg')

# Download the image data.
response = requests.get(url)

# Create the destination path and save the image in that location.
path = os.path.join(destinationPath, '{name}{ext}'.format(name=filename, ext='.jpg'))
fp = open(path, 'wb')
fp.write(response.content)
fp.close()

# Return the path and title of the image.
return (path, title)

The new module can be tested in the Python Shell as shown below, if the module works the specified directory will contain a funny image:

imagedownload

Emailing the image

A separate module for emailing will provide good flexibility without adding much complexity. The advancedemail module contains a function for sending an image with some text as an email to one or more recipients via email when provided with credentials for a Gmail account.  The module is bound to using  Google’s SMTP server however this allows the interface to be easier to use, the consumer doesn’t need to provide a host or port.

A new Python file should be created in the same directory as the previous module created. At the top of the file write the required import statements:

# Import the email modules we'll need.
import smtplib
# Email related modules.
import email.mime.application
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

Notice the from … import construct. This allows for access to the MIMEMultipart and MIMEText without having to fully qualify the calls by specifying the module each time the functions are used.

Define a function that takes a message, image path, a list of recipients and valid Gmail credentials which will provide access to Gmail’s SMTP servers for sending the email.
Also create an email and attach the message text.

def SendGmailEmail(message, jpegPath, recipients, gmailAddress, gmailPassword):

    # Compose the message.
    msg = MIMEMultipart()
    msg['Subject'] = 'Cutie Pi'
    msg['From'] = gmailAddress
    msg['To'] = "; ".join(recipients)

    msgtext = message

    body = MIMEMultipart('alternative')
    body.attach(MIMEText(msgtext))

Open the file, specifying ‘rb’ as the second parameter to open, opens a file for reading in binary format. Create an email attachment and set ‘Content-Disposition’ as ‘attachment’ as opposed to ‘inline’ so that the image is treated as an attachment by the recipient’s email client. Attach both the body and attachment to the email.

# Create the attachment and set the headers.
type='jpg'
fp=open(jpegPath,'rb')
att = email.mime.application.MIMEApplication(fp.read(),_subtype=type)
fp.close()
att.add_header('Content-Disposition','attachment',filename=os.path.basename(jpegPath))

# Attach the body and image to the email.
msg.attach(body)
sg.attach(att)

Create an SMTP instance to encapsulate the SMTP connection and use Google’s SMTP host details. Enable TLS (transport layer security) to provide extra security when connecting and finally send the complete email.

# Set the SMTP server address to use Gmail.
s = smtplib.SMTP('smtp.gmail.com:587')
# Enable Transport Layer Security.
s.starttls()
s.login(gmailAddress,gmailPassword)
s.sendmail(gmailAddress, recipients, msg.as_string())
s.quit()

Timing Is Everything

“The idea of waiting for something makes it more exciting” 
― Andy Warhol

The prospect of receiving an email of a cute kitten at an unknown time would make the experience a lot more fun for my friend, if they haven’t received the email yet then they will just have to wait… full of fuzzy anticipation, how exciting!

To allow us to achieve this the module below was created, this module contains the simplest function yet but allows for the email to be sent at a random time in a given window. The window is specified by providing the minimum and maximum number of hours to wait. The hours are then converted into seconds then the program generates a random number using the random module which is then passed to the sleep function of the time module. The program then pauses for the given number of seconds, this module was saved as sleep.py. Even though the message gets sent at random times the image is downloaded at midnight to ensure a new image is used each time.

import random
import time

def SleepForRandomIntervalBetweenHours(minHours, maxHours):

    minSeconds = minHours * 3600
    maxSeconds = maxHours * 3600

    randomWaitInSeconds = random.randint(minSeconds, maxSeconds)
    time.sleep(randomWaitInSeconds)

Putting it all together

Now that all the modules are complete we need a function that we can call at regular intervals that brings the other modules together. Create a new Python file, I called it awwemailer.py.First, our custom modules need to be imported so that we can use them.

import advancedemail
import imgur
import sleep

I wanted the email to be sent between 9:00 and 17:00, after all, who wants to be woken up by their phone to see a picture of a cat snuggling up to a dog? The hours specified only work out to be the hours in the day if the function is called at midnight every day. Set the category and set the directory to save the images, you could get images from a different category or build the functionality to include more than one category.

# Send the email during social hours.
minHours = 9
maxHours = 17
# Imgur category.
category = 'aww'
# Location to save images.
destinationImageDirectory = '/home/pi/AwwEmail/Awws'

Pass the required details to the functions from the modules created before and send the email. The recipients variable is a list of one or more email addresses and the email credentials should belong to an account that you have set up. This script will pause half way through for the random time interval, notice that there isn’t a function, we want python to execute the entire script:

# Recipient email addresses.
recipients = ['friend@gmail.com', 'anotherfriend@gmail.com']

# Gmail credentials for sending the email.
gmailAddress = 'cuteimageemailer@gmail.com'
gmailPassword = 'password'

# Download the daily top image and return the image path and title.
imagePath, title = imgur.GetDailyTopImageForImgurCatory(category, destinationImageDirectory)

# Wait a random amount of time between set hours in the day.
sleep.SleepForRandomIntervalBetweenHours(minHours, maxHours)

# The message for the email body.
message = "Here is your daily dose of 'aww'!"

# Send the email.
advancedemail.SendGmailEmail(message, imagePath, recipients, gmailAddress, gmailPassword)

At this point all the code is complete and all that is left to do is to set up the automation so that the email will send automatically, every day. For this we will use Cron, a Unix task-based job scheduling utility. Cron is driven by crontab (cron table) which can be edited and set up to run the awwemailer.py file at midnight. Open LXTerminal from the desktop icon and enter the following command to edit crontab.

crontab -e

You will see an explanation of the purpose of this utility and an example of how it can be used. Any line preceded with a hash is a comment, it can be useful to put hashes in front of entries that you want to temporarily disable without removing the entire line. Enter the following line at the end of the file to make Python run the script at the specified location at midnight:

00 00 * * * Python /home/pi/awwemail/awwemailer.pi

There is no need to restart anything, the changes will be made instantly! Everything is set up and your friend should start receiving images everyday that will make them go…

cat and dog
“…Aww!”

imgur.py module

# Requests needs downloading.
import requests
# Dealing with JSON data.
import json
# Time access and conversions.
import time

# Miscellaneous operating system interfaces.
import os

# Used for creating Universally Unique Identifiers
import uuid

def GetDailyTopImageForImgurCatory(imgurCategory, destinationPath):

# Get the JSON data for the top items of the day in the given category, a UUID is appended to
# the URL as the request is being cached for some reason.
r = requests.get('http://imgur.com/r/aww/top/day.json?var=' + str(uuid.uuid4()))

# Parses the JSON and creates a dictionary.
j = json.loads(r.text)

# Get the list of images from 'data' property.
imageList = j['data']

# Extract the first JPEG from the list of images.
imageName = None
title = None

for image in imageList:
	if image['ext'] == '.jpg':
		imageName = image['hash']
		title = image['title']
		break

# Create a suitable name for the file based on the current time.
filename = time.strftime("%Y%m%d-%H%M%S")

# Generate the image URL.
url = r'http://imgur.com/{name}{ext}'.format(name=imageName, ext='.jpg')

# Download the image data.
response = requests.get(url)

# Create the destination path and save the image in that location.
path = os.path.join(destinationPath, '{name}{ext}'.format(name=filename, ext='.jpg'))
fp = open(path, 'wb')
fp.write(response.content)
fp.close()

# Return the path and title of the image.
return (path, title)

advancedemail.py module

# Import the email modules we'll need.
import smtplib
# Email related modules.
import email.mime.application
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

# Miscellaneous operating system interfaces.
import os

def SendGmailEmail(message, jpegPath, recipients, gmailAddress, gmailPassword):
    # Compose the message.
    msg = MIMEMultipart()
    msg['Subject'] = 'Cutie Pi'
    msg['From'] = gmailAddress
    msg['To'] = "; ".join(recipients)

    msgtext = message

    body = MIMEMultipart('alternative')
    body.attach(MIMEText(msgtext))

    # Create the attachment and set the headers.
    type='jpg'
    fp=open(jpegPath,'rb')
    att = email.mime.application.MIMEApplication(fp.read(),_subtype=type)
    fp.close()
    att.add_header('Content-Disposition','attachment',filename=os.path.basename(jpegPath))

    # Attach the body and image to the email.
    msg.attach(body)
    msg.attach(att)

    # Set the SMTP server address to use Gmail.
    s = smtplib.SMTP('smtp.gmail.com:587')

    # Enable Transport Layer Security.
    s.starttls()
    s.login(gmailAddress,gmailPassword)
    s.sendmail(gmailAddress, recipients, msg.as_string())
    s.quit()

sleep.py module

import random
import time
def SleepForRandomIntervalBetweenHours(minHours, maxHours):

    minSeconds = minHours * 3600
    maxSeconds = maxHours * 3600

    randomWaitInSeconds = random.randint(minSeconds, maxSeconds)
    time.sleep(randomWaitInSeconds)

awweamiler.py module

# Import the custom modules
import advancedemail
import imgur
import sleep

# Send the email during social hours.
minHours = 9
maxHours = 17

# Imgur category.
category = 'aww'

# Location to save images.
destinationImageDirectory = '/home/pi/AwwEmail/Awws'

# Recipient email addresses.
recipients = ['sadfriend@gmail.com']

# Gmail credentials for sending the email.
gmailAddress = 'cuteimageemailer@gmail.com'
gmailPassword = 'password'

# Download the daily top image and return the image path and title.
imagePath, title = imgur.GetDailyTopImageForImgurCatory(category, destinationImageDirectory)

# Wait a random amount of time between set hours in the day.
sleep.SleepForRandomIntervalBetweenHours(minHours, maxHours)

# The message for the email body.
message = "Here is your daily dose of 'aww'! Love from Calum and me, the Pi. :)\n\n\"" + title + "\""

# Send the email.
advancedemail.SendGmailEmail(message, imagePath, recipients, gmailAddress, gmailPassword)

Maze Race

Maze Race is a simple game that I wrote as a C# Console Application. The game is based around the player solving perfect mazes in the quickest time possible by navigating from a corner to the opposite corner. A perfect maze can be described as a maze where there is only a single path between any two points and there are no loops. They are equivalent to trees in graph theory.

Initially I just had the desire to make a simple application that generated mazes of arbitrary size but I thought it would be much more fun and interesting as a game.

mazerace

The game contains a number of modes:

  1. Ten level speed run – race around 10 mazes starting from a 5 x 5 maze and ending with a 15 x 15 maze. This mode has top scored and replays.
  2. Race the CPU – best out of 10 games with a choice of five difficulty levels.
  3. Race another person – best out of 10 games.

The technologies and techniques used are listed below:

  1. Recursive backtracking for automated maze generation and solving.
  2. ASP.NET Web API for posting scores and game recordings.
  3. Serialization of objects to JSON using Json.NET.
  4. Microsoft SQL database for saving the game scores and replays.
  5. AES encryption to prevent fake scores.

Download Maze Race and see how well you can do at the 10 level speed run!

 

Setting up WordPress on a Raspberry Pi

This tutorial continues on from my previous tutorial Setting up Raspbian – with a web server in mind and shows you how to get WordPress up and running on a Raspberry Pi. WordPress is one of the most popular blogging/content management systems and is what is powering this site.

Step 1 – Install The Lamp Stack

The LAMP solution stack is a popular software bundle for powering web servers and it’s the setup WordPress requires to operate.

Update the system’s package list and update the installed packages to their latest versions.

sudo apt-get update && sudo apt-get upgrade

Install the LAMP stack.

sudo apt-get install apache2 php5 php5-mysql mysql-server

After installation you should be able to test that the installation was successful by visiting the IP address of your Raspberry Pi in your web browser, mine was located at http://192.168.1.200/. A page should display that states that ‘It Works!’.

Step 2 – Install WordPress
Install the WordPress package.

sudo apt-get install wordpress

Create a symbolic link to the directory where WordPress was installed in the ‘www’ directory so Apache can find the files. A symbolic link is similar to a Shortcut except it operates at the level of the file system.

sudo ln -s /usr/share/wordpress /var/www/wordpress

Unzip the MySql installation using the gunzip command.

sudo gunzip /usr/share/doc/wordpress/examples/setup-mysql.gz

Set up the MySQL database.

sudo bash /usr/share/doc/wordpress/examples/setup-mysql -n wordpress localhost

Step 3 – Configure WordPress
Create a symbolic link to WordPress’ config file and make sure it contains the IP address of your Raspberry Pi.

sudo ln -s /etc/wordpress/config-localhost.php /etc/wordpress/config-192.168.1.200.php

Change the ownership of the WordPress directory and set the owner as www-data which is the user that Apache runs as.

sudo chown -R www-data /usr/share/wordpress

Remove the default index file that was created when Apache was installed.

sudo rm /var/www/index.html

Move the WordPress index file from the WordPress folder to the www root.

sudo mv /var/www/wordpress/index.php /var/www/

Edit the WordPress index.php.

sudo nano /var/www/index.php

Change the following line:

<? php require('./wp-blog-header.php'); ?>

This is what it should be – this is where WordPress is installed:

<? php require('./wordpress/wp-blog-header.php'); ?>

Edit the WordPress config file.

sudo nano /var/www/wordpress/wp-config.php

After the line:

<?php

Add the following then close and save:

define('WP_HOME','http://192.168.1.200');
define('WP_SITEURL','http://192.168.1.200/wordpress');

Visit ‘http://192.168.1.200/wordpress’ and set up WordPress!

The steps provide the www-data user with the permissions to modify directories required by WordPress.

Update the ownership of the WordPress directory.

sudo chown -R -f www-data:www-data /usr/share/wordpress

Update the ownership of the wp-content directories.

sudo chown -R -f www-data:www-data /var/lib/wordpress/wp-content/ && sudo chown -R -f www-data:www-data /srv/www/wp-content/

Create a configuration file for configuring the Apache web server.

sudo nano /var/www/.htaccess

Update the ownership of the .htaccess file.

sudo chown www-data:www-data /var/www/.htaccess

Set up permissions for the necessary WordPress directories:

sudo chmod 644 /var/www/.htaccess
sudo chmod 755 /var/www/wordpress/wp-content/
sudo chmod 755 /var/www/wordpress/wp-content/uploads
sudo chmod 755 /var/www/wordpress/wp-content/plugins
sudo chmod 755 /var/www/wordpress/wp-admin

Edit the default sites-available configuration file.

sudo nano /etc/apache2/sites-available/default

Set ‘AllowOverride’ to ‘All’ under /var/www/, save and exit.

Restart the Apache server.

sudo /etc/init.d/apache2 restart

Go to settings, permalinks and choose a setting. I chose ‘Post name’, this will update the .htaccess file accordingly. Permalinks make links to your posts more understandable for both humans and search engines boosting your SEO as your links now make more sense semantically.

Restart Apache.

sudo /etc/init.d/apache2 restart

Install a necessary plugin that allows a symbolically linked folder to be used as the plugins folder.

sudo git clone git://github.com/liggitt/wordpress-plugin-symlink.git /srv/www/wp-content/localhost/plugins/aaa-plugin-symlink

Set up the themes and uploads folders so that WordPress can install and access themes and uploads.

sudo rm -rf /srv/www/wp-content/localhost/themes
sudo ln -s /var/www/wordpress/wp-content/themes /srv/www/wp-content/localhost/themes
sudo rm -rf /srv/www/wp-content/localhost/uploads
sudo ln -s /var/www/wordpress/wp-content/uploads /srv/www/wp-content/localhost/uploads

Setup complete!

Step 4 – Forward router ports

At this point you can only access your WordPress site from your internal network. You will need to forward port 80 on your router to your Raspberry Pi so that your router forwards any traffic sent to port 80 straight to your Raspberry Pi allowing it to be accessible from the outside world.

Step 5 – Set up a Dynamic DNS service

Your WordPress site is now accessible to the outside world by typing in your IP address. This number is hard to remember compared to a domain name and is probably not static so is subject to change. There are a couple of free solutions I would recommend:

I use FreeDNS and it’s very easy to set up. I had previously bought a domain name from a domain provider but just switched to the FreeDNS name servers so that I could manage it from there allowing me to utilise the dynamic DNS features.

There are a number of steps you need to take to allow your domain name to resolve to your WordPress site successfully.

Create a symbolic link to your WordPress configuration file with the domain in the file name replacing ‘DOMAIN’ below.

sudo ln -s /etc/wordpress/config-localhost.php /etc/wordpress/config-DOMAIN.php

Edit the .htaccess file.

sudo nano /var/www/.htaccess

Make sure that requests that don’t contain the ‘www.’ sub-domain are redirected to your domain with ‘www.’ included permanently with a HTTP 301 redirect. This will ensure that links to your site with and without ‘www.’ will be seen as the same website removing the possibility that search engines could class your site as multiple sites potentially hurting its ranking. Put the following at the top of the file, save and exit.

 # Redirect non-www to www: 
 RewriteCond %{HTTP_HOST} !^www\. [NC] 
 RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

If you’re using FreeDNS Make sure that they know your IP address by regularly making a request to the update URL provided. Open the crontab configuration file for configuring the cron scheduler.

crontab -e

Set up the job up to make a request every five minutes using -q –spider so that wget doesn’t produce output and only makes a HEAD request as opposed to an entire GET request which isn’t necessary. Replace ‘UPDATE URL’ with your update url, save and exit:

*/5 * * * * wget -q --spider UPDATE URL

WordPress should now be successfully set up and accessible from the outside world!

Setting up Raspbian – with a web server in mind

In this tutorial I’m going to explain how to get up and running with Raspbian on your Raspberry Pi, running either from an SD card or a USB Flash Drive. I will provide pointers about optimising your Raspberry Pi as a web server.

I’m going to assume that you have a Windows background and are unfamiliar with the Linux environment and you at least have access to another machine running Windows with an SD card slot.

Step 1 – Download Raspbian

Navigate to the official Raspberry Pi Website and download Raspbian “wheezy” either by direct download or torrent. This is a version of the Debian operating system, one of the most popular Linux distributions, which is optimized for the Raspberry Pi.

Step 2 – Copy the image to your SD card

Now you have the image that represents the contents and structure of the Raspbian operating system we need to write it to an SD card. Navigate to the SourceForge website and download  Win32 Disk Imager – this tool is used for writing images to external media. Extract the contents of the zip file to a folder and run Win32DiskImager.exe.

Select the ‘Device’ ie your SD Card. It selected my SD card by default however you should check to make sure that you have selected the correct letter as this process will erase any existing data you have on your SD card. Click on the folder icon and select the Raspbian image you downloaded then click on ‘Write’ and wait…

As well as writing images to external media Win32 Disk Imager is useful for reading data from external media to an image file. This will be useful later when you have your SD card in a desired state and want to make a backup before making any further changes.

Step 3 – Boot up into Terminal

You are now in a position to boot up your Raspberry Pi! The remainder of this tutorial requires that you boot to the Linux Terminal. There are a couple of ways you can do this, first connect your Raspberry Pi to your digital TV or monitor and plug it in. It should boot in to Terminal. If you are happy interfacing locally through your TV or monitor continue to Step 3. I however prefer a headless setup.

If you’re planning to use your Raspberry Pi as a web server then the headless setup is a more suited approach. A headless setup means that the Raspberry Pi isn’t directly connected to a monitor, mouse or keyboard although it does require a connection to your router via Ethernet. When you’ve connected your Raspberry Pi to your router you should notice the green LED labelled LNK flashing which indicates that a connection has been successfully negotiated. You then need to obtain your Raspberry Pi’s IP address.

sudo ip addr show

ipaddress

Your IP address should be shown in a similar fashion as above. You need to make a note of this.

You now need to download PuTTY to another machine on the network. PuTTY is a Secure Shell (SSH) client that allows you to connect securely to your Raspberry Pi. Once you’ve completed the download; launch putty.exe, enter your IP Address using the default port of 22 and click ‘connect’. The default username is ‘Pi’ with the password ‘raspberry’ – this will bring you to the command line.

Step 3 – Configuring Raspbian

Now you’re ready to configure your Raspberry Pi. You need to launch the Configuration Tool.

sudo raspi-config

You should expand the file system to make full use of the SD card, change the default password, configure the locale (mine is set to ‘en_GB.UTF-8 UTF-8’)  and timezone under ‘Internationalisation Options’. If you want to set your Raspberry Pi up as a web server you should make a couple of other tweaks as explained below.

It is now possible to set an overclock of 1000MHz without voiding your warranty as the clock speed is dynamic and reduces if the internal temperature reaches 85°C. You may need to reduce this if your Raspberry Pi becomes unstable, each chip is unique and has different limitations so you should experiment. You should also navigate to the ‘Advanced Options’ and set the memory split. You should choose the minimum amount of memory (16 MB) to be dedicated to the graphics if your unit is running headless as graphics memory isn’t required and can be better used servicing requests.

When you’re happy everything is as you want it select ‘Finish’ then restart.

sudo reboot

Your Raspberry Pi is now set up and ready to use. If you’ve been following this tutorial with a web server in mind then it’s recommended to move the root partition onto a USB drive.

Although a convenient medium for running Raspbian, SD cards aren’t designed for handling the demands of running a web server i.e. high rates of reading and writing data. I hosted a WordPress site on an SD card and the database became corrupt after a couple of days. If you would like to know how to transfer the root file system to a USB flash drive you should continue with the next step.

Step 4 – Copying the root partition to a USB flash drive.

Plug in a USB stick and load Raspbian to the terminal. You need to copy the root partition from the SD card to the USB drive. List the USB devices connected to the system to make sure your device is recognised.

lsusb

My drive came up as /dev/sda1 – you need to copy your root partition to the USB drive using the dd utility to create a disk dump using /dev/mmcblk0p2 as the input file and /dev/sda1/ as the output file. A block size of 512 bytes was used for the transfer which will take around half an hour…

sudo dd if=/dev/mmcblk0p2 of=/dev/sda1 bs=512

You now need to update cmdline.txt, a file that controls the loading of the Linux Kernel, with the new location of the root partition. You can use Nano, a simple command-line text editor to edit text files.

sudo nano /boot/cmdline.txt

Replace root=/dev/mmcblk0p2 with the location of your USB drive, in my case /dev/sda1. Press ‘ctrl + x’ then press ‘y’ to save when you are prompted.

You also need to update the file system table with the new location of the root partition.

sudo nano /etc/fstab

Again, replace root=/dev/mmcblk0p2 with the location of your USB drive – save and exit. You should now be in a position to reboot and load the root partition from the USB drive.

sudo shutdown -r now

If all has gone well the terminal should boot up in the same way as it did in Step 3. You can show the free space on your disks in human readable format, you will probably find that the root partition isn’t expanded to fill the USB drive.

df -h

You should expand the root file system to fill the disk using the resize2fs program.

sudo resize2fs /dev/sda1

You should reboot before making any other changes. Your Raspberry Pi is now in a good position to start playing with and potentially setting up as a web server – you might want to back up the USB drive to your PC using the ‘Read’ function of the Win32 Disk Imager application you used it Step 2. This means you can restore to a good known state if you happen to break anything (you will)!

Hosted on my Raspberry Pi