Getting Started with Yocto on the Raspberry Pi


I’ve been wanting to have a play with Yocto so decided to have a go at getting an image running on a Raspberry Pi. I found plenty of references but no step by step that just worked. This post just covers my notes on how to get going.

Development Machine

The Yocto Project Quick Start states “In general, if you have the current release minus one of the following distributions, you should have no problems”, then lists several distros including Ubuntu. I originally tried using Ubuntu 16.04, and had problems, I think because of the later version of gcc.

I used a clean install of Ubuntu 14.04 desktop running on a virtual machine, the rest of the process was actually pretty straight forward

Firstly I made sure that Ubuntu was fully patched

sudo apt-get update
sudo apt-get upgrade

Then following the Yocto Project Quick Start  I installed the required packages

sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib build-essential chrpath socat libsdl1.2-dev xterm

I then disabled the dash shell in favour of the bash shell ( I did this because I saw it advised, not sure if this is required)

sudo dpkg-reconfigure dash

Getting the code and Building

At the time of writing krogoth is the latest version of Yocto, hence I am working with that branch. The raspberrypi meta data is not currently branched so I am working with the master branch. The first step is to clone yocto and meta-raspberrypi

mkdir yocto
cd yocto
git clone -b krogoth git:// poky
cd poky
git clone -b master git://

Now generate the default configuration files into the default directory build.

. oe-init-build-env build

Now we need to edit the build configuration. Firstly edit yocto/poky/build/conf/local.conf add these lines

MACHINE ?= "raspberrypi2"
GPU_MEM = "16"

MACHINE could also be set to raspberrypi, or to raspberrypi3 depending on your target hardware (The raspberrypi2 image should also run on an RPI3). The GPU_MEM setting allocates the minimum amount of memory to the GPU leaving the rest for the ARM processor. See the READEME in meta-raspberrypi for details of these and other options.
Secondly edit 
yocto/poky/build/conf/bblayers.conf and add meta-raspberrypi, mine looks like this

# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly

Now it’s time to build, it’s worth noting that the command oe-init-build-env doesn’t just create the configuration files and build directory – it also sets up the environment including the path, so if you build in a  new shell, or having logged in you need to re-run oe-init-build-env. It won’t overwrite the changes you’ve made to the configuration. So to build I cd to the poky directory and then

. oe-init-build-env build
bitbake rpi-basic-image

The build takes a long time the first time, potentially hours, numerous packages are fetched, when I build the first time I had a package fail to download because the git repository was unavailable, and the build failed. Just re-run the bitbake command. Assuming everything succeeds you should see output that looks like this

Parsing recipes: 100% |#########################################| Time: 00:00:22
Parsing of 891 .bb files complete (0 cached, 891 parsed). 1321 targets, 67 skipped, 0 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
Build Configuration:
BB_VERSION = "1.30.0"
BUILD_SYS = "x86_64-linux"
TARGET_SYS = "arm-poky-linux-gnueabi"
MACHINE = "raspberrypi2"
DISTRO = "poky"
TUNE_FEATURES = "arm armv7ve vfp thumb neon vfpv4 callconvention-hard cortexa7"
TARGET_FPU = "hard"
meta-yocto-bsp = "krogoth:f5da2a5913319ad6ac2141438ba1aa17576326ab"
meta-raspberrypi = "master:2745399f75d7564fcc586d0365ff73be47849d0e"
NOTE: Preparing RunQueue
NOTE: Executing SetScene Tasks
NOTE: Executing RunQueue Tasks
NOTE: Tasks Summary: Attempted 2167 tasks of which 911 didn't need to be rerun and all succeeded.

The resultant sdcard image is found beneath the build directory, flash it to SDCard as you would any other image



Insert the media into your raspberry pi, attach keyboard and monitor, power on…

Screen Shot 2016-08-09 at 20.10.02

ssh is also available in this image, access is available as root with no password. Before doing anything else tighten up security.

Have fun…

VPN bridge from home network to AWS VPC with Raspberry Pi

Introduction and disclaimer

I wanted to extend my home network to a Virtual Private Cloud (VPC) within Amazon Web Services (AWS), primarily for use as a jenkins build farm. I have achieved this using a Raspberry Pi as my Customer Gateway device. This post covers the process of configuring the raspberry pi from scratch and AWS from scratch. I’m posting as a reminder to myself, hopefully others will find this useful.

NOTE: I found this post by Pahud Hsieh on very helpful while developing this. I have also relied heavily on the excellent documentation at

I have a fairly standard home network on 192.168.0/24 with a router provided by my ISP.  This post uses a Raspberry Pi, on a static IP address within my home network as a VPN gateway. Allowing any devices on my home network to communicate with EC2 instances (virtual machines), running within my VPC.

Network Diagram

Network Diagram


  • Raspberry Pi on a static IP address (in this example
  • Home gateway IP address of you home network is static (My ISP doesn’t offer static IP addresses, however the address has not changed for years).
  • AWS account (I suggest also running some tutorials, the free tier is sufficient).

I’m starting with a clean install of Raspbian Jessie Lite, although other distributions of Linux should work.

Configuring VPC

Login to AWS, and select Services->VPC, this takes you to the VPC dashboard. Start the VPC Wizard

Screen Shot 2016-07-11 at 14.24.36

Choose VPC with a Private Subnet Only and Hardware VPN access and click Select.

Screen Shot 2016-07-11 at 14.27.49


Screen Shot 2016-07-11 at 14.33.15


Screen Shot 2016-07-11 at 14.37.54

Wait for the VPN to be created

Screen Shot 2016-07-11 at 14.41.53

Now on the left towards the bottom find the VPN Connections page and click the Download Configuration button at the top of the page

Screen Shot 2016-07-11 at 15.04.56

In the downloaded configuration file find the tunnel groups under the IKE section

! The tunnel group sets the Pre Shared Key used to authenticate the 
! tunnel endpoints.
tunnel-group <TUNNEL1_IP> type ipsec-l2l
tunnel-group <TUNNEL1_IP> ipsec-attributes
pre-shared-key <PSKEY_STRING>

You will need the <TUNNEL1_IP> and <PSKEY_STRING> values later, note them down.

Ensure that the static route to your home network exists in the VPN, Opne VPN Connections and select the Static Routes tab, it should show the CIDR for your home network. If not (my setup didn’t) click Edit and type in the CIDR.

Screen Shot 2016-07-12 at 10.17.03




Configure the Raspberry Pi

Enable the Random Number Generator

Edit /boot/config.tx and append

# Enable random number generator

Reboot and then install the random number generator tools

sudo apt-get install rng-tools

Install Openswan

sudo apt-get install -y openswan lsof

During package installation you get prompted about using X.509 certificates. I’m sure AWS supports these, for now I’m skipping for simplicity.

Screen Shot 2016-07-11 at 15.24.15

IPSec configuration

Edit /etc/ipsec.conf and set the content as shown below. NOTE this is including configuration files from /etc/ipsec.c/*.conf, this allows different files for different connections.

# /etc/ipsec.conf - Openswan IPsec configuration file
# Manual: ipsec.conf.5
# Please place your own config files in /etc/ipsec.d/ ending in .conf
version 2.0 # conforms to second version of ipsec.conf specification
# basic configuration
config setup
# Debug-logging controls: "none" for (almost) none, "all" for lots.
# klipsdebug=none
# plutodebug="control parsing"
# For Red Hat Enterprise Linux and Fedora, leave protostack=netkey
# Enable this if you see "failed to find any available worker"
# nhelpers=0
#You may put your configuration (.conf) file in the "/etc/ipsec.d/" and uncomment this.
include /etc/ipsec.d/*.conf

Create a configuration file for this connection, edit /etc/ipsec.d/home_to_aws.conf

conn home-to-aws


left – The IP address of your Raspberry Pi on your home network

leftid – The IP address of your home gateway

leftsubnet – the CIDR of your home network

right – the IP address of Tunnel1 in your AWS gateway.

right subnet – The CIDR of your VPC

Input the pre-shared key

edit/var/lib/openswan/ and set the content as below <TUNNEL1_IP> : PSK "<PSKEY_STRING>"

Edit /etc/sysctl.conf

Append the following lines

net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0

Then run sysctl -p to reload it.

Check IPSec status

$ sudo ipsec verify
Checking your system to see if IPsec got installed and started correctly:
Version check and ipsec on-path [OK]
Linux Openswan U2.6.38/K4.4.11-v7+ (netkey)
Checking for IPsec support in kernel [OK]
SAref kernel support [N/A]
NETKEY: Testing XFRM related proc values [OK]
Hardware RNG detected, testing if used properly [OK]
Checking that pluto is running [OK]
Pluto listening for IKE on udp 500 [OK]
Pluto listening for NAT-T on udp 4500 [OK]
Checking for 'ip' command [OK]
Checking /bin/sh is not /bin/dash [WARNING]
Checking for 'iptables' command [OK]
Opportunistic Encryption Support [DISABLED]


Restart IPSec

sudo service ipsec restart

Check IPsec status

make sure an active connection is running

$ sudo service ipsec status
● ipsec.service - LSB: Start Openswan IPsec at boot time
Loaded: loaded (/etc/init.d/ipsec)
Active: active (running) since Mon 2016-07-11 17:56:40 UTC; 8min ago
Process: 1660 ExecStop=/etc/init.d/ipsec stop (code=exited, status=0/SUCCESS)
Process: 1746 ExecStart=/etc/init.d/ipsec start (code=exited, status=0/SUCCESS)
CGroup: /system.slice/ipsec.service
├─1840 /bin/sh /usr/lib/ipsec/_plutorun --debug --uniqueids yes --...
├─1841 logger -s -p daemon.error -t ipsec__plutorun
├─1842 /bin/sh /usr/lib/ipsec/_plutorun --debug --uniqueids yes --...
├─1845 /bin/sh /usr/lib/ipsec/_plutoload --wait no --post
├─1846 /usr/lib/ipsec/pluto --nofork --secretsfile /etc/ipsec.secr...
├─1853 pluto helper # 0 
├─1854 pluto helper # 1 
├─1855 pluto helper # 2 
└─1974 _pluto_adns
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #1: STATE_MAIN_I2: sent MI2,...R2
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #1: NAT-Traversal: Result us...ed
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #1: transition from state ST...I3
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #1: STATE_MAIN_I3: sent MI3,...R3
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #1: Main mode peer ID is ID_...4'
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #1: transition from state ST...I4
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #1: STATE_MAIN_I4: ISAKMP SA...8}
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #2: initiating Quick Mode PS...8}
Jul 11 17:56:42 vpc pluto[1846]: "home-to-aws" #2: transition from state ST...I2
Jul 11 17:56:42 vpc pluto[1846]: "home-to-aws" #2: STATE_QUICK_I2: sent QI2...e}
Hint: Some lines were ellipsized, use -l to show in full.

Start on reboot

sudo update-rc.d ipsec defaults

reboot the Raspberry pi and recheck the ipsec service status

Check VPC connection in the VPC console

Make sure Tunnel1 is UP

Screen Shot 2016-07-11 at 19.40.12


For increased reliability, add the second tunnel configuration to the RPI configuration


Create an EC2 Instance

To test the configuration Launch an EC2 instance into your VPC. As an example I’m launching the free tier Ubuntu server.

From the EC2 Dashboard select Launch Instance, select Ubuntu Server 14.04 LTS (HVM), SSD Volume Type, select t2.micro (Free Tier Eligible) then click Next: Configure Instance Details. Select your VPC as the Network.

Screen Shot 2016-07-12 at 09.31.01

Click Next: Add Storage, Next: Tag Instance, Next: Configure Security Group, Create a new security group and add the rules you require, the example below adds SSH and ICMP (ping) from my home subnet.

Screen Shot 2016-07-12 at 09.38.33

Click Review and Launch, Launch, create a new key-pair (or use existing if you prefer), Download the Key Pair and keep them safe. Launch and then View Instance. Wait for the Status Checks to complete.

Screen Shot 2016-07-12 at 09.48.25

Note the private IP address – in this example

From your Raspberry Pi you should now be able to ping the instance

$ ping
PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=64 time=200 ms
64 bytes from icmp_seq=2 ttl=64 time=204 ms

Adding local Routes

Devices on your home network that are to access the VPC need to have a static route added that identifies the Raspberry Pi as the gateway to use for

On Linux based devices (including macs)

sudo route -n add

ssh access

copy the key file that you previously downloaded to the machine you want to open an ssh session from. Ensure the pen file has read only permissions.

chmod 400 jenkins_aws.pem

Open an ssh session using the key

ssh -i jenkins_aws.pem ubuntu@

All being well you are now logged in to your EC2 instance.


Install Raspberry Pi img using OSX

Up to now I have used win32Diskimager.exe in a windows VM to program images onto SDCards for the Raspberry Pi. For some reason having not done this for a while it has stopped working for me, so I decided to program using OSX directly.


Firstly I downloaded and unzipped the raspbian image in my Downloads folder, the image I downloaded and unzipped contained 2016-02-09-raspbian-jessie.img.
In the terminal on the mac

cd ~/Downloads
ls -l *.img

this showed
rwx—— 1 davidcozens staff 4127195136 20 Feb 13:11 2016-02-09-raspbian-jessie.img

Programming the SDCard

I inserted the SDCard into a USB card reader (The internal reader on my MBP didn’t recognise the card), then to identify which device OSX had mounted this as

diskutil list

The output looked like

/dev/disk0 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *1.0 TB     disk0
   1:                        EFI EFI                     209.7 MB   disk0s1
   2:          Apple_CoreStorage Macintosh HD            999.7 GB   disk0s2
   3:                 Apple_Boot Recovery HD             650.1 MB   disk0s3
/dev/disk1 (internal, virtual):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:                  Apple_HFS Macintosh HD           +999.3 GB   disk1
                                 Logical Volume on disk0s2
/dev/disk2 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *8.0 GB     disk2
   1:             Windows_FAT_32 boot                    62.9 MB    disk2s1
   2:                      Linux                         4.1 GB     disk2s2
/dev/disk3 (disk image):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        +1.6 TB     disk3
   1:                        EFI EFI                     209.7 MB   disk3s1
   2:                  Apple_HFS Time Machine Backups    1.6 TB     disk3s2
/dev/disk6 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:                                                   *613.9 KB   disk6
Now BE VERY CAREFUL to identify the device corresponding to the SDCard. Using the wrong device name in the commands below could erase all of the data on your MAC. Look for the size that matches your SDCard. In my case /dev/disk2 is the SDCard, disk0 and disk1 are the internal HD on my MAC and disk6 is may backup device.
In the commands below I use /dev/diskx to represent the SDCard device name.
Unmount the SDCard

diskutil unmountDisk /dev/diskx

zero out the partition table

sudo dd if=/dev/zero of=/dev/rdiskx bs=1024 count=1

Program the SDcard

sudo dd if=2016-02-09-raspbian-jessie.img of=/dev/rdiskx bs=4m

ensure all data is synced


You should now be safe to remove and use the SDCard.

Starting with CODESYS on the Raspberry Pi – Update

Last May I blogged about Starting with CODESYS on the Raspberry Pi. Since then I have found it a great teaching platform to help others learn CODESYS. My getting started tutorial is now a little out of date, so I thought I would reproduce it using current versions of software. This blog walks through the steps of installing CODESYS under Windows 10, installing the CODESYS for Raspberry Pi plugin, Installing the CODESYS runtime Raspbian and establishing communications.
Thanks to 3S the process is now much easier.

Installing CODESYS on Windows 10

Download CODESYS from  (You need to register, but then the download is free). Run the installer accepting all defaults

Installing CODESYS for Raspberry Pi

Download CODESYS for Raspberry Pi from the CODESYS Store Again you have to register first, everything is contained within a single .package file
Installation is a two stage process, firstly installing the package within CODESYS, and then subsequently installing CODESYS on the Raspberry Pi.

Installing the CODESYS Package

Launch the CODESYS IDE, Tools->Package Manager… then Install…, browse to the Package previously downloaded. Accept the license and then accept the default on every menu in the installer. The package should install as shown, and CODESYS then needs to be restarted.

Preparing the Raspberry Pi

Ensure that you have the latest version of Raspbian installed on your Raspberry Pi.

New Install

3S give links on their download page and the First Steps pdf tells you how to setup the RPi for various different peripherals

Upgrade Raspbian

If you choose to upgrade, be careful of anything important, perform backups before you start. On the Raspberry Pi issue these commands to upgrade, then continue to install CODESYS as instructed below.

sudo apt-get updatesudo apt-get dist-upgradesudo rpi-update

Installing CODESYS on the Raspberry Pi

Launch CODESYS and then select Tools->Update RaspberryPi, enter the password for the Raspberry Pi, click scan.
If your RPi is found then select the IP Address from the dialog and click OK.
If your RPi is not found, it is possible to enter the IP Address manually, then click OK on the Update Raspberry Pi dialog – this will install the CODESYS runtime on your Raspberry Pi. Progress is reported in the bottom left corner of the CODESYS window.
The update only takes a few seconds, on completion check for messages

There should be a single message saying the Update has finished

Login the the Raspberry Pi and reboot it – now you are ready to test your installation.

Testing The Installation

Launch CODESYS and select New Project…
Select Standard Project and give the project a name, click OK.
Select the Device: as CODESYS Control for Raspberry Pi and the programming language to use, click OK. A project is then created with this content.
Double click on PLC_PRG (PRG) and create a simple program
Now try to login (Online->Login),
Click Yes to start a network scan. (For me this didn’t work – probably because I am running Windows in a virtual machine, if that happens manually type the IP address of your RPi into the box representing the device and hit Enter, your device should then be found).
Select Online->Login again, this time login and download should succeed, the program will be in the STOP state. Switch to the PLC_PRG tab and you should see your program and Variables at their starting values.
Select Debug->Start and the application will start running, you will ten see the variables changing.
Have fun…

Cross development using eclipse and GCC for the RPi


When I decided to use eclipse to do some cross development for the Raspberry Pi hosted on windows I was surprised to find that I found lots of useful posts elsewhere that gave a part of the solution, or worked well on a Linux host. I found both of the sites below to be particularly helpful.
My blog post Using google test with CDT in eclipse gives details on how to install eclipse CDT, which is an assumed starting point for this post.

Install GCC Cross compiler

It is possible to build your own GCC cross compiler, however this is a complex process and prebuilt versions are available. I choose to download from, and selected raspberry-gcc4.6.3.exe to match wheezy raspbian. Installation was as simple as running the executable and accepting the terms of the license.

Synchronise header file and library versions

This step is required to ensure that the versions of headers and libraries used on the Raspberry Pi match those used by the cross compiler.
Run c:SysGCCRaspberryTOOLSUpdateSysroot.exe
Press Select… and setup a new SSH connection to your Raspberry PI (Mine is running a newly installed image and has the default username and password).
Click Connect and then save the key when prompted, then click Synchronize, wait while the headers and libraries are copied (This takes a few minutes).
NOTE: Whenever you update your RPi it is a good idea to resynchronize to ensure that your development environment remains in step with your target.

Configure eclipse for cross compilation

Open eclipse and in the Project Explorer right click and select New…->C++ Project. Select the Hello World C++ Project and Cross GCC, give the project a name.
Click Next> and customise as you wish
Click Next>
Click Next> and specify the cross-compiler prefix as arm-linux-gnueabihf- and cross-compiler path as C:SysGCCRaspberrybin.
Click Finish and then build the project, there should be no errors.

Configure RPi for gdb

Run SmarTY.exe from C:SysGCCRaspberryTOOLSPortableSmartty, and open the connection to your RPi.
Enter these commands
mkdir remote-debugging
Verify that gdbserver is on the path and the version of gdbserver that is installed
gdbserver --version

To automate the use of gdb on the target RPi it needs to have the DataStore server running. 
Download the server from, I used the 3.6M4 release and downloaded rseserver-linux-3.6-M4.tar to the /tmp directory on the RPi. Following the install advice from the eclipse help I executed these commands on the RPi

sudo mkdir /opt/rseservercd /opt/rseserversudo tar xf /tmp/rseserver-linux-3.6-M4.tar

The daemon needs to be run as root, so it can be manually started by

sudo su
cd /opt/rseserver
perl ./ &

To have it start automatically each time the RPi reboots, edit /etc/rc.local and just before the exit 0 at the end of the default file launch the server

cd /opt/rseserver
perl ./ &

When the RPi reboots you should see a message that says

Daemon running on: raspberry, port: 4075 

Configure eclipse for Cross debugging

Right click on the HelloWorld project in the project explorer and New->File, set the name to .gdbinit and click Finish.
In the file set sys root to point to the cross tools set sysroot C:SysGCCRaspberryarm-linux-gnueabihfsysroot

In the project explorer right click on the HelloWorld project and select Debug As->Debug Configurations…, then select C/C++ Remote Application and click the New button (circled).

In the Debug Configurations Dialog the first step is to configure a connection to the Raspberry Pi, to do this, next to Connection: click New…
Select a Remote System type of Linux, and click Next>
Enter the IP address of your RPi in Host name:, name the connection and set a description, then Next>.
Click Next>


Click Finish, ensure that the Connection: is set to your new connection
Then click Browse… under Remote Absolute File Path for C/C++ Application:


Then try to expand My Home, you will be prompted for user credentials and certificates




Select the remote-debugging directory and click OK.


When the binary is transferred to the raspberry pi we need to ensure that it has execute permissions set, so in the Commands to execute before application enter chmod 777 /home/pi/remote-debugging/HelloWorld
Now in the Debug Configurations dialog select the Debugger tab and on the Main sub-tab browse to the arm-linux-gnueabihf-gdb.exe debugger.
Now select the Gdbserver Settings sub-tab, the default settings worked for me and looked like this.
Apply these settings, and Close.
Click Window->Perspective->Open Perspective->Other... select Remote System Explorer, and click OK.
In the Remote Systems tab right click on your connection and select Connect. (I found if I didn’t connect to the RPi before launching the debugger the launch would fail, retrying usually worked – but this is cleaner).
Now select Run->Debug Configurations, ensure your configuration is selected (it should be) and click Debug. You will be prompted to confirm the perspective switch, tick to Remember your decision and click Yes.

You should then see your application stopped on the first line and ready to be debugged

I have tested this setup with setting breakpoints, viewing disassembly, stepping into and out of functions and inspecting variables. It all seems to work, however I have not yet diagnosed the error Cannot access memory at address 0x0. I will update this post if/when I get to the bottom of it.

Clean error

If you don’t have rm.exe on your path you will see an error like this when you clean the project.
This can be resolved by downloading rm.exe as part of MinGW, find the path to rm.exe, (with a default install it is C:MinGWmsys1.0bin). Add this to the end of your windows PATH and restart eclipse.

Further Reading

If you find this tutorial helpful you may find my previous postings on eclipse helpful too
Unit testing with googletest
Code coverage with Gcov
Static analysis with CppCheck
I develop for RPi by having a unit test project that compiles and runs on my PC for speed, and then a cross compiled project that shares the same source code and runs on the RPi.

Backup and Restore Raspberry Pi to Synology DiskStation


There are many articles on how to backup Raspery Pi systems, up to now I have relied on taking card images and storing these on a machine that is backed up. However it is all to easy to have a few hours of fun with the Raspberry Pi and then not get round to making a backup, I want something that is automated so that I don’t have to think about it.
The key goals for this backup strategy are:
1) Unattended backup
2) Warnings sent for backup failure [ToDo]
3) Rotating backups
4) Backup to my Synology DiskStation
5) Simple to add additional Raspberry Pi’s to the backup


None of this is particularly new, I have pulled together ideas that I’ve found in a number of other sources, all of these were helpful

Solution Overview

I have a Synology DiskStation with Raid disks that I backup all of my machines to, this post backs up to this server, the same basic approach should work going to any Linux server with small modifications.
cron is used on the server to invoke a script to perform the backup, the script is parameterised with the ip address of the Raspberry Pi to backup.
rsync is used to perform the actual backup.
ssh is used to securely connect to the Raspberry Pi.

Backing Up

Step 1 – root SSH access

We need the Synology DiskStation to have root access via SSH to the Raspberry Pi. Open up two SSH sessions, one to the DiskStation (as root) and one to the Pi (as your normal login e.g. pi).
1) In the Raspberry Pi Session first enable root login by setting a root password

sudo passwd root

Enter a password as prompted
Now we need to ensure that there is a directory to hold ssh keys.

su root

mkdir ~/.ssh


2) In DiskStation session
First check to see if you already have a pair of SSH keys by running

ls ~/.ssh

If you don’t see a file called there you need to generate a pair of keys using this command

ssh-keygen -t rsa -C root@<Your Synology server’s name>

– When prompted for the file in which to save the key, accept the default (hit <Enter>)
– When prompted for a passphrase hit <Enter> (no passphrase)

Now push the public key to the Raspberry Pi (this is why we need the Pi to briefly allow password logins on the root account, because until the public key exists on the destination server, you will be prompted for a password when you run this command):

cat ~/.ssh/ | ssh root@<your Pi’s IP address> ‘cat >> .ssh/authorized_keys’

Enter the password you created in Step 1 when prompted

Confirm that SSH key logins are now accepted by the Raspberry Pi by running this command (still from the Synology session, don’t toggle back to the Pi session yet🙂

ssh root@<Your Pi’s IP Address>

Now you can close the Synology session’s terminal window
3) In the Raspberry Pi Session remove password based root access. 

passwd -d root

Be very careful to do this on the Raspberry Pi – you could cause all sorts of problems doing this from another one of your hosts.
Now close down this ssh session as well

Step 2 Creating the backup script files

Using a web browser log in to the DiskStation as admin. Create a top level folder for holding all files related to Raspberry Pi backups (rpi_backup), use the Control Panel->Shared Folder
Then using the File Station create a directory under rpi_backup called scripts, and another called logs.
NOTE: I think the easiest way to create these scripts is to use the Text Editor from the Main Menu on the DiskStation, alternately use ssh to connect to the DiskStation and then use vi to create the files.
Create a file called rpi_backup/scripts/ with the following content.

#This script uses rsync to backup a named Raspberry Pi at a given IP address
#Three rotating backups are kept. If rsync fails then the preceding backups are retained.
if [ “$#” -ne 2 ] ; then
echo “Usage: 2 arguments required: $0 SERVERNAME IP” >&2
exit 1
# Set up string variables
NOW=$(date +”%Y-%m-%d”)
# Paths to common commands used
#Function to check for command failure and exit if there has been one. This is done
# so that when invoked from cron the error is reported
check_exit_code() {
if [ “$exit_code” -ne “0” ] ; then
echo “$1”
echo “exit with exitcode $exit_code”
exit 1
#Ping the RPI a few times to ensure the interface is up (I’ve not seen this fail)
# Ensure we have a top level backup directory for this server
if ! [ -d $SERVERDIR ] ; then
fi ;
# Backups are made to BASENAME.0, this is then moved if the backup was successfull.
# So we start by clearing out anything from a failed backup
if [ -d $BASENAME.0 ] ; then
$RM -rf $BASENAME.0 ;
# RSYNC via SSH from the RPI as an incremental against the previous backup.
$RSYNC -av
–link-dest $BASENAME.1
-e “ssh -p 22” root@$ADDRESS:/
# If RSYNC failed in any way, don’t trust the backup, exit the script
check_exit_code “RSYNC Failed”
#Rotate the existing backups
if [ -d $BASENAME.3 ] ; then
$RM -rf $BASENAME.3 ;
if [ -d $BASENAME.2 ] ; then
if [ -d $BASENAME.1 ] ; then
if [ -d $BASENAME.0 ] ; then

Create a second file called rpi_backup/scripts/rsync-exclude.txt with this content


At this stage I like to manually run the script to ensure that it is working as I like. To do this connect to the DiskStation as root via ssh, cd to /volume1/rpi_backup/scripts. To backup a Raspberry Pi that I want to identify as myRPI at address I repeat this until I am happy with the behaviour, including checking for reporting when the RPI is offline.
/volume1/rpi_backup/scripts/ myRPI

Step 3 Automating the backup

On the DiskStation desktop open Control Panel->Task Scheduler
Create a User Defined Script
Give the task a name and enter the command to run your script with the full path to the script, this example is for my jenkins server at address
Set the schedule, in my case I want this task to run at 3am every morning
Save the job by clicking OK
You can now test run the job by selecting it and clicking Run.

Step 4 Restoring from backup

The backup directories are shared from the DiskStation, mounting the volume gives access to the files, for now I have only done this from my mac and used it to restore individual files.
At this stage I have not investigated a full system restore, I rely on having a base img for each RPi taken after any major reconfiguration. I can then restore files from these backups.

Step 5 Backing up a second RPI

We need the Synology DiskStation to have root access via SSH to the Raspberry Pi. Open up two SSH sessions, one to the DiskStation (as root) and one to the Pi (as your normal login e.g. pi).
1) In the Raspberry Pi Session first enable root login by setting a root password

sudo passwd root

Enter a password as prompted
Now we need to ensure that there is a directory to hold ssh keys.

su root

mkdir ~/.ssh


2) In DiskStation session

Push the public key to the Raspberry Pi (this is why we need the Pi to briefly allow password logins on the root account, because until the public key exists on the destination server, you will be prompted for a password when you run this command):

cat ~/.ssh/ | ssh root@<your Pi’s IP address> ‘cat >> .ssh/authorized_keys’

Enter the password you created in Step 1 when prompted

Confirm that SSH key logins are now accepted by the Raspberry Pi by running this command (still from the Synology session, don’t toggle back to the Pi session yet🙂

ssh root@<Your Pi’s IP Address>

Now you can close the Synology session’s terminal window
3) In the Raspberry Pi Session remove password based root access. 

passwd -d root

Be very careful to do this on the Raspberry Pi – you could cause all sorts of problems doing this from another one of your hosts.
Now close down this ssh session as well.

4) Finally repeat step 3 Automating the Backup for the new host.


This process has given me a fully automated backup of my Raspery Pi systems. There are a number of improvements that I would like to make as and when time allows.
  1. There is currently no notification sent if the backup fails. For now I inspect the logs, and the backup does at least preserve the last three good backups. It is possible to use the synology notification system, see I may get around to this, I’m hoping that sinology may improve the system though…
  2. I want to investigate if I can perform a full system restore on to a blank card. For now I rely on taking occasional card images, and then this automated system gives me backup of all files.
  3. The timestamp on the individual backup top level directory is incorrect, it gets updated for each backup each time a backup occurs (mv is incorrectly setting the date). I did have a brief look at this, there are a number of obstacles to overcome. mv doesn’t preserve the timestamp on move, I cannot use touch with a specified timestamp because the version available on the DiskStation doesn’t support the feature. I could solve the problem with python, but this isn’t installed as standard. I think I could solve the issue using php, but I haven’t put the time in yet – more important to have a working backup.

Installing SVN and trac on Raspberry Pi

This post is step by step instructions for installing subversion (SVN) 1.8.10 and trac on the Raspberry Pi. I am writing it as a reminder to myself, but if you find it useful…


It’s a good idea to get up to date

sudo apt-get update
sudo apt-get upgrade

Install Subversion

First of all I checked the version included in the raspbian distribution, and I wanted a later version. I looked at using the WANdisco binaries, but found that they seemed to be missing the binaries required for the raspberry pi. So these instructions use the debian backports.
I followed these instructions. First I added wheezy-backports to me sources.list by creating /etc/apt/sources.list.d/wheezy-backports.list 

deb wheezy-backports main

I tried just running sudo apt-get update, however I got the following error

W: GPG error: wheezy-backports Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 8B48AD6246925553 NO_PUBKEY 7638D0442B90D010

After a little digging I found that I could add the public keys like this

gpg --keyserver --recv-key 8B48AD6246925553
gpg -a --export 8B48AD6246925553 | sudo apt-key add -
gpg --keyserver --recv-key 7638D0442B90D010
gpg -a --export 7638D0442B90D010 | sudo apt-key add -
sudo apt-get update
sudo apt-get -t wheezy-backports install subversion

Now it is possible to update with no errors

sudo apt-get update

Finally we can install subversion

sudo apt-get -t wheezy-backports install subversion
sudo apt-get -t wheezy-backports install python-subversion

(Note: originally I missed python-subversion, this left a version mismatch and caused errors)
Now check the version installed

svn --version
svn, version 1.8.10 (r1615264)

compiled Apr 24 2015, 04:16:08 on arm-unknown-linux-gnueabihf

Copyright (C) 2014 The Apache Software Foundation.

This software consists of contributions made by many people;

see the NOTICE file for more information.

Subversion is open source software, see

The following repository access (RA) modules are available:

* ra_svn : Module for accessing a repository using the svn network protocol.

– with Cyrus SASL authentication

– handles ‘svn’ scheme

* ra_local : Module for accessing a repository on local disk.

– handles ‘file’ scheme

* ra_serf : Module for accessing a repository via WebDAV protocol using serf.

– using serf 1.3.7

– handles ‘http’ scheme

Install Apache

I have decided that I am less likely to get conflicts if the versions of apace and subversion come from the same distribution. So I install from wheezy backports.

sudo apt-get -t wheezy-backports install apache2
sudo apt-get -t wheezy-backports install libapache2-svn

I got a single warning during install

Starting web server: apache2apache2: Could not reliably determine the server’s fully qualified domain name, using for ServerName

I have chosen to ignore this for now. To test the installation of apache I browsed to http://localhost/

Create Repositories

I have decided that the structure I want is to have two repositories, a play repository and a prod repository. This example just shows the creation of the play repository.
sudo mkdir /var/svn
sudo mkdir /var/svn/repos
sudo svnadmin create /var/svn/repos/play

Configure Security

I have decided to use digest access authorisation. NOTE: I am not recommending this method of securing access, but it suits my needs.
Start by editing dav_svn.conf (I use vi you could equally use nano if you prefer)
sudo vi /etc/apache2/mods-available/dav_svn.conf
The default file is all comments, and I choose to leave it intact and just append the following to the end of the file.
<Location /svn>
DAV svn
SVNParentPath /var/svn/repos
AuthType Digest
AuthName "Subversion Repo"
AuthUserFile /etc/apache2/dav_svn.htdigest
Require valid-user
Next I need to enable digest authentication and restart apache
sudo a2enmod auth_digest
sudo service apache2 restart
Next I want to create a user in the apache/subversion digest file
sudo htdigest -c /etc/apache2/dav_svn.htdigest "Subversion Repo" david
It is important to note two things here. Firstly, if you add more than one user omit the -c on all subsequent calls as this creates the digest file and so would delete all existing users. Secondly the “Subversion Repo” argument specifies the realm and must match the AuthName in dav_svn.conf.
Now is a good time to test that it is working: browse to (the ip address of your RPi), you should be prompted for a username and password, enter the ones you specified when creating the digest and you should be in.
One last step is to tie down the native file access permissions, and to grant the apache user address to write to the repository.
sudo chown -R www-data:www-data /var/svn/repos

Install trac

With trac I have decided to install the version bundled with raspbian (0.12.5). I based the decision on the availability of other trac plugins, also for compatibility with subversion 1.8 I need trac >=0.12.3.
sudo apt-get install trac
sudo apt-get install lib-apache2-mod-python

Configure trac

I want trac to share the same digest authentication as subversion. I also want a separate trac database for my play and prod repositories. The steps below only show the setup for the play repository.
sudo mkdir /var/trac
sudo mkdir /var/trac/projects
sudo chown -R www-data:www-data /var/trac/projects

Edit the apache configuration

sudo vi /etc/apache2/sites-enabled/000-default

Add the following to the end of the file, just before the </VirtualHost> tag. Note that the authentication matches the subversion settings.

<Location /trac>
SetHandler mod_python
PythonInterpreter main_interpreter
PythonHandler trac.web.modpython_frontend
PythonOption TracEnvParentDir /var/trac/projects
PythonOption TracUriRoot /trac
PythonOption PYTHON_EGG_CACHE /tmp
AuthType Digest
AuthName "Subversion Repo"
AuthDigestDomain /trac
AuthDigestProvider file
AuthUserFile /etc/apache2/dav_svn.htdigest
Require valid-user

Now it is time to create the play trac project environment

sudo -u www-data trac-admin /var/trac/projects/play initenv

You get asked a few questions, I responded play for the name of the project and accepted all other defaults.
Restart apache

sudo /etc/init.d/apache2 restart

Time to test, browse to (use the IP address of your RPi) you should see a list of your trac projects.

Click on the play project name and you should see trac

NOTE: According to TracAuthenticationIntroduction Note that in the current version of Trac, clicking on the logout link above the navigation bar does not logs user out because the browser still remembers the HTTP authentication and keeps sending it.

To be able to administer trac add a user as the trac admin. I use my normal trac login.

sudo -u www-data trac-admin /var/trac/projects/play permission add david TRAC_ADMIN

For further configuration to make the integration tighter and to improve performance see