When you order a Raspberry Pi 3 then do yourself a favour and also order the matching 5.1VDC 2.5A power supply (eg: STONTRONICS T5875DV, Element 14 item 2520785). The RPi3 is four cores of 64-bit ARM with an impressive GPU -- that's a lot to power. If you present it with too little power the circuitry will make the red "power" LED blink and the software will reduce the CPU's clock rate.

You'll notice the clever use of tolerances to allow the RPi3 power supply to charge a phone, as you might expect from its Micro USB connector (5.0V + 10% = 5.5V, 5.1V + 5% ≅ 5.4V). The cable on the RPi3 power supply has an impressive amount of copper, so they are serious about avoid voltage drop due to thin cables.

You can argue that this is poor design, that the RPi should really use one of the higher power delivery solutions designed for mobile phones. But with Google, Apple and Samsung all choosing different solutions? Whatever the RPi's designers chose to do then most purchasers would have to buy the matching power supply. At least this design is simple for makers and hobbyists to power the RPi3 (simply provide the specified voltage and current, no USB signalling is needed).

The RPi3 will also slow down when it gets too hot; this is called throttling and is a feature of all modern CPUs. People are currently experimenting with heat sinks. Even a traditional aluminium 10mm heat sink seems to make a worthwhile difference in preventing throttling on CPU-intensive tasks; although how often such tasks occur in practice is another question. The newer ceramic heat sinks are about four times more effective than the classic black aluminium heat sinks, so keep your eyes out for someone offering a kit of those for the RPi3. This is a further complication when looking at cases, as the airflow through most RPi2 cases is quite poor. I've simply taken a drill to the plastic RPi2 case I am using, although there are ugly industrial cases and expensive attractive cases with good airflow.

Further reading: Raspberry Pi 3 Cooling / Heat Sink Ideas, Pi3B thermal throttling.

Debian distributions for the Raspberry Pis

The Raspian distribution is Debian recompiled and tuned for the ARM instruction set used in the original Raspberry Pi Model A, Model B, and Model B+.

The Raspberry Pi2 has a more recent ARM instruction set. That gives RaspberryPi2 users two paths to Debian Jessie: use the Raspbian distribution or use the stock Debian ARM distribution with a hack for the Raspberry Pi kernel.

This article is about upgrading an existing Raspbian Wheezy distribution to Raspbian Jessie. Some Linux systems administration skill is required to do this.

Alter /etc/apt/sources.list

Edit the files /etc/apt/sources.list and /etc/apt/sources.list.d/*.list replacing every occurance of "wheezy" with "jessie".

For example is /etc/apt/sources.list says:

deb http://mirrordirector.raspbian.org/raspbian/ wheezy main contrib non-free rpi

then alter that to:

deb http://mirrordirector.raspbian.org/raspbian/ jessie main contrib non-free rpi

Similarly /etc/apt/sources.list.d/raspi.list contained:

deb http://archive.raspberrypi.org/debian/ wheezy main

and this becomes:

deb http://archive.raspberrypi.org/debian/ jessie main

The repository described by the file /etc/apt/sources.list.d/collabora.list doesn't yet have a Jessie section.


The number of packages to upgrade will depend on how many packages you installed in addition to those which originally arrived with Raspbian Wheezy. In general, the mark is somewhere around 1GB of data.

Upgrades are best done from the old-fashioned text console. Press Crtl-Alt-F1 and login as root.


# apt-get update
# apt-get dist-upgrade
# apt-get autoremove

Do not reboot when that command completes. We'll fix a few of the more common issues with the upgrade at this most convenient moment.

Correct errors

udev rules

There are two files containing syntax errors in /lib/udev/rules.d/ which cause udev to fail to start: 60-python-pifacecommon.rules and 60-python3-pifacecommon.rules. These files are not owned by any packages, which is a little annoying and naive of their authors. Rename them to stop udev attempting to read them and failing.

# cd /etc/udev/rules.d
# mv 60-python-pifacecommon.rules 60-python-pifacecommon.rules.failed
# mv 60-python3-pifacecommon.rules 60-python3-pifacecommon.rules.failed

ifplugd replaced by wicd

Networking of plugin interfaces is done using ifplugd in Wheezy. This is done using wicd in Jessie.

# apt-get purge ifplugd

systemd is the cgroups controller

The init system is done using System V-style scripts in Wheezy. This is done using systemd in Jessie.

Systemd uses control groups so that unexpected process stop is reported to systemd. In Linux a control group can only have one controlling process, which has to be systemd in Jessie. This isn't a poor outcome, as systemd makes a fine controller.

However if another process attempts to be the control groups controller then systemd can fail when starting processes. So remove any existing controllers:

# apt-get purge cgmanager cgroup-bin cgroup-tools libcgroup1

systemd is the init system

A package called systemd-shim allow other init systems to use logind and other programs, as systemd-shim provides just enough of systemd's function. Jessie uses systemd, so we don't need systemd-shim. Unfortunately the dist-upgrade seems to pull this in:

# apt-get purge systemd-shim

[Thanks to ktb on the RaspberryPi.org forums for correcting a typo here.]

Allow logging to the journal

systemd doubles the number of system loggers, by adding a new logger called journald. It can provide logs to the usual syslogd. However when debugging startup issues it can be useful to have journald write the files itself. To do this create the directory /var/log/journal/

journald keeps its logs in binary. Use journalctl -xb to see the logs. The -1 parameter is hand to view the log of the previous boot.

Consider booting in single user mode

You might choose to give yourself a way to debug startup issues by having the kernel start in single user mode. Edit /boot/cmdline.txt, appending the text single

The workflow here is:

  • Boot RPi.

  • Press Ctrl-D when asked for a password to enter single user mode. The boot will continue into multi-user mode.

  • If this hangs then press Ctrl+Alt+Del to shut down.

  • Restart RPi. This time provide the root password at the single user mode password prompt. Use journalctl to view the log of the previous boot and examine what went wrong.

  • Correct the error, and use shutdown -r now to try again from the top.

Once you have sorted issues during system init then remove the single phrase from /boot/cmdline.txt so that the system boots into multiuser mode.


Reboot and work through issues resulting from the upgrade.

Clean up

# apt-get clean

Journald is a enterprise-level logging solution, so it is keen on flushing data to disk. This radically increases the number of flash blocks written and this reduction in flash card lifetime isn't appreciated on the RPi. So it's probably best to remove /var/log/journal/* and allow journald to log to RAM and syslog instead.


OpenVSwitch is a software defined networking switch for Linux. It supports its own protocol and also OpenFlow 1.3. OpenVSwitch is included in the Linux kernel and its user-space utilities ship in Debian Wheezy.

Mininet allows the simple creation of emulated networks, using Linux's namespace feature. Mininet is not packaged in Debian Wheezy.

Raspberry Pi kernel issue #377 enables the kernel features needed by OpenVSwitch and Mininet.

Installing OpenVSwitch

Since all the necessary parts are in packages, simply install the packages:

$ sudo apt-get install ovsdbmonitor openvswitch-switch openvswitch-controller openvswitch-pki openvswitch-ipsec

The packaging is done well, and automatically establishes the necessary databases and public key infrastructure.

Installing Mininet

The main Mininet installation instructions give three choices: we are using “Option 2: installation from source”.

Before going further enable memory control groups in the kernel. Edit the line in /boot/cmdline.txt to append:

cgroup_enable=memory swapaccount=1

Reboot so that those kernel parameters take effect.

Get the source:

$ sudo apt-get install git
$ git clone git://github.com/mininet/mininet

There is an installation script in mininet/utils/install.sh. It won't run successfully as Raspberry Pi doesn't keep the Linux kernel in the expected package. In any case it tries to compile OpenVSwitch as a kernel module, which is no longer needed now that OpenVSwitch is part of the stock Linux kernel.

Looking at that script we can do the steps by hand. Starting with installing the runtime dependencies:

$ sudo apt-get install build-essential iperf telnet python-setuptools cgroup-bin ethtool  ethtool help2man pyflakes pylint pep8 socat

Now install Mininet into /usr/local:

$ sudo make install

Finally, test that the installation worked:

$ sudo /etc/init.d/openvswitch-controller stop
$ sudo mn --test pingall
*** Creating network
*** Adding controller
*** Adding hosts:
h1 h2 
*** Adding switches:
*** Adding links:
(h1, s1) (h2, s1) 
*** Configuring hosts
h1 h2 
*** Starting controller
*** Starting 1 switches
*** Waiting for switches to connect
*** Ping: testing ping reachability
h1 -> h2 
h2 -> h1 
*** Results: 0% dropped (2/2 received)
*** Stopping 1 controllers
*** Stopping 1 switches
s1 ..
*** Stopping 2 links

*** Stopping 2 hosts
h1 h2 
*** Done
completed in 6.277 seconds

It's often said that today we have in the phone in our pocket computers more powerful than the supercomputers of the past. Let's see if that is true.

The Raspberry Pi contains a Broadcom BCM2835 system on chip. The CPU within that system is a single ARM6 clocked at 700MHz. Located under the system on chip is 512MB of RAM -- this arrangement is called "package-on-package". As well as the RPi the BCM2835 SoC was also used in some phones, these days they are the cheapest of smartphones.

The Whetstone benchmark was widely used in the 1980s to measure the performance of supercomputers. It gives a result in millions of floating point operations per second. Running Whetstone on the Raspberry Pi gives 380 MFLOPS. See Appendix 1 for the details.

Let's see what supercomputer comes closest to 380 MFLOPS. That would be the Cray X-MP/EA/164 supercomputer from 1988. That is a classic supercomputer: the X-MP was a 1982 revision of the 1975 Cray 1. So good was the revision work by Steve Chen that it's performance rivalled the company's own later Cray 2. The Cray X-MP was the workhorse supercomputer for most of the 1980s, the EA series was the last version of the X-MP and its major feature was to allow a selectable word size -- either 24-bit or 32-bit -- which allowed the X-MP to run programs designed for the Cray 1 (24-bit), Cray X-MP (24-bit) or Cray Y-MP (32-bit).

Let's do some comparisons of the shipped hardware.


Basic specifications. Raspberry Pi versus Cray X-MP/EA/164
Item Cray X-MP/EA/164 Raspberry Pi Model B+
Price US$8m (1988) A$38
Price, adjusted for inflation US$16m A$38
Number of CPUs 1 1
Word size 24 or 32 32
RAM 64MW = 256MB 512MB
Cooling Air cooled, heatsinks, fans Air cooled, no heatsink, no fan


Neither unit comes with a power supply. The Cray does come with housing, famously including a free bench seat. The RPi requires third-party housing, typically for A$10; bench seats are not available as an option.

The Cray had the option of solid-state storage. A Secure Digital card is needed to contain the RPi's boot image and, usually, its operating system and data.


I/O systems. Raspberry Pi versus Cray X-MP/EA/164
Item Cray Raspberry Pi
SSD size 512MB Third party, minimum of 4096MB
Price US$6m (1988) A$20
Price, adjusted for inflation US$12m A$20


Of course the Cray X-MP also had rotating disk. Each disk unit could contain 1.2GB and had a peak transfer rate of 10MBps. This was achieved by using a large number of platters to compensate for the low density of the recorded data, giving the typical "top loading washing machine" look of disks of that era. The disk was attached to a I/O channel. The channel could connect many disks, collectively called a "string" of disks. The Cray X-MP had two to four I/O channels, each capable of 13MBps.

In comparison the Raspberry Pi's SDHC connector attaches one SDHC card at a speed of 25MBps. The performance of the SD cards themselves varies hugely, ranging from 2MBps to 30MBps.


What is clear from the number is that the floating point performance of the Cray X-MP/EA has fared better with the passage of time than the other aspects of the system. That's because floating point performance was the major design goal of that era of supercomputers. Ignoring the floating point performance, the Raspberry Pi handily beats out every computer in the Cray X-MP range.

Would Cray have been surprised by these results? I doubt it. Seymour Cray left CDC when they decided to build a larger supercomputer. He viewed this as showing CDC as not "getting it": larger computers have longer wires, more electronics to drive the wires, more heat from the electronics, more design issues such as crosstalk and more latency. Cray's main design insight was that computers needed to be as small as possible. There's not much smaller you can make a computer than a system-on-chip.

So why aren't today's supercomputers systems-on-chip? The answer has two parts. Firstly, the chip would be too small to remove the heat from. This is why "chip packaging" has moved to near the centre of chip design. Secondly, chip design, verification, and tooling (called "tape out") is astonishingly expensive for advanced chips. It's simply not affordable. You can afford a small variation on a proven design, but that is about the extent of the financial risk which designers care to take. A failed tape out was one of the causes of the downfall of the network processor design of Procket Networks.

Appendix 1. Whetstone benchmark

The whets.c benchmark was downloaded from Roy Longbottom's PC Benchmark Collection.

Compiling this for the RPi is simple enough. Since benchmark geeks care about the details, here they are.

$ diff -d -U 0 whets.c.orig whets.c
@@ -886 +886 @@
-#ifdef UNIX
+#ifdef linux
$ gcc --version | head -1
gcc (Debian 4.6.3-14+rpi1) 4.6.3

$ gcc -O3 -lm -s -o whets whets.c

Here's the run. This is using a Raspbian updated to 2014-08-23 on a Raspberry Pi Model B+ with the "turbo" overclocking to 1000MHz (this runs the RPi between 700MHz and 1000MHz depending upon demand and the SoC temperature). The Model B+ has 512MB of RAM. The machine was in multiuser text mode. There was no swap used before and after the run.

$ uname -a
Linux raspberry 3.12.22+ #691 PREEMPT Wed Jun 18 18:29:58 BST 2014 armv6l GNU/Linux

$ cat /etc/debian_version 

$ ./whets
Single Precision C/C++ Whetstone Benchmark

       0.04 Seconds          1   Passes (x 100)
       0.19 Seconds          5   Passes (x 100)
       0.74 Seconds         25   Passes (x 100)
       3.25 Seconds        125   Passes (x 100)

Use 3849  passes (x 100)

          Single Precision C/C++ Whetstone Benchmark

Loop content                  Result              MFLOPS      MOPS   Seconds

N1 floating point     -1.12475013732910156       138.651              0.533
N2 floating point     -1.12274742126464844       143.298              3.610
N3 if then else        1.00000000000000000                 971.638    0.410
N4 fixed point        12.00000000000000000                   0.000    0.000
N5 sin,cos etc.        0.49911010265350342                   7.876   40.660
N6 floating point      0.99999982118606567       122.487             16.950
N7 assignments         3.00000000000000000                 592.747    1.200
N8 exp,sqrt etc.       0.75110864639282227                   3.869   37.010

MWIPS                                            383.470            100.373

It is worthwhile making the point that this took maybe ten minutes. Cray Research had multiple staff working on making benchmark numbers such as Whetstone as high as possible.

A note to readers
There are a many ways to configure wireless networking on Debian. Far too many. What is described here is the simplest option which uses the programs and configurations which ship in an unaltered Raspbian distribution. This lets people bring up wireless networking to their home access point with a minimum of fuss. More advanced configurations may be more easily done with other tools, such as NetworkManager. Now back to your originally programmed channel…

The RaspberryPi does not come with wireless onboard. But it's simple enough to buy a small USB wireless dongle. Element14 sell them for A$9.31. It's unlikely you'll see them in shops for such a low price so it is well work ordering a WiFi dongle with your RPi.

Raspbian already comes with the necessary software installed. Let's say our home wireless network has a SSID of example and a pre-shared key (aka password) of TGAB…Klsh. Edit /etc/wpa_supplicant/wpa_supplicant.conf. You will see some existing lines:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev

Now add some lines describing your wireless network:


The parameter scan_ssid=1 allows the WiFi dongle to connect with a wireless access point which does not do SSID broadcasts.

Now plug the dongle in. Check dmesg that udev installed the dongle's device driver:

$ dmesg
[    3.873335] usb 1-1.4: new high-speed USB device number 5 using dwc_otg
[    4.005018] usb 1-1.4: New USB device found, idVendor=0bda, idProduct=8176
[    4.030075] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[    4.050034] usb 1-1.4: Product: 802.11n WLAN Adapter
[    4.060398] usb 1-1.4: Manufacturer: Realtek
[    4.069904] usb 1-1.4: SerialNumber: 000000000001

[    8.586604] usbcore: registered new interface driver rtl8192cu

A new interface will have appeared:

$ ifconfig wlan0
wlan0     Link encap:Ethernet  HWaddr 00:11:22:33:44:55  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 KiB)  TX bytes:0 (0.0 KiB)

IPv4's DHCP should run and your interface should be populated with addresses:

$ ifconfig wlan0
wlan0     Link encap:Ethernet  HWaddr 00:11:22:33:44:55
          inet addr:  Bcast:  Mask:
          RX packets:100 errors:0 dropped:0 overruns:0 frame:0
          TX packets:100 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 KiB)  TX bytes:0 (0.0 KiB)

If you use multiple wireless networks, then add additional network={} stanzas to wpa_supplicant.conf. wpa_supplicant will choose the correct stanza based on the SSIDs present on the wireless network.


If you are using IPv6 (by deleting /etc/modprobe.d/ipv6.conf) then IPv6's zeroconf and SLAAC will run and you will also get a IPv6 link-local address and maybe a global address if your network has IPv6 connectivity off the subnet.

$ ifconfig wlan0
wlan0     Link encap:Ethernet  HWaddr 00:11:22:33:44:55
          inet addr:  Bcast:  Mask:
          inet6 addr: fe80::211:22ff:fe33:4455/64 Scope:Link
          inet6 addr: 2001:db8:abcd:1234:211:22ff:fe33:4455/64 Scope:Global
          RX packets:100 errors:0 dropped:0 overruns:0 frame:0
          TX packets:100 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 KiB)  TX bytes:0 (0.0 KiB)

Commonly occurring issues

If the interface is not populated with addresses then try to restart the interface. You will need to do this if you plugged the dongle in prior to editing wpa_supplicant.conf.

$ sudo ifdown wlan0
$ sudo ifup wlan0

If you still have trouble then look at the messages in /var/log/daemon.log, especially those from wpa_supplicant. Also check dmesg, ensuring that the device driver isn't printing messages indicating misbehaviour.

Also check that the default route points to where you expect; that is, the default route line says default viadev wlan0.

$ ip route show
default via dev wlan0 dev wlan0  proto kernel  scope link  src

$ ip -6 route show
2001:db8:abcd:1234::/64 dev wlan0  proto kernel  metric 256  expires 10000sec
fe80::/64 dev wlan0  proto kernel  metric 256 
default via fe80::1 dev wlan0  proto ra  metric 1024  expires 1000sec

If you have edited /etc/network/interfaces then you may need to restore these lines to that file:

allow-hotplug wlan0
iface wlan0 inet manual
 wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp


As this example shows, the pre-shared key should be long — up to 63 characters — and very random. The entire strength of WPA2 relies on the length and randomness of the key. If your current key is neither of these then you might want to generate a new key and configure it into the access point.

An easy way to generate a key is:

$ sudo apt-get install pwgen
$ pwgen -s 63 1

This works even better if you use the RaspberryPi's hardware random number generator.

There is only one secure wireless protocol which you can use at home: Wireless Protected Access version two with pre-shared key, this is known as “WPA2-PSK” or as “WPA2 Personal”. The only secure encryption is CCMP -- this uses the Advanced Encryption Standard and is sometimes named “AES” in the access point configurations. The only secure authentication algorithm for use with WPA2-PSK is OPEN: this doesn't mean “open access point for use by all, so no authentication” but the reverse: “Open Systems Authentication”.

You can configure wpa_supplicant.conf to insist on these secure options as the only technology it will use with your home network.


  # Prevent backsliding into insecure protocols

To move to the latest development kernel say:

raspberrypi$ sudo rpi-update

rpi-update will load a kernel from github.com/Hexxeh/rpi-firmware. If you know the commit you can pass that as a parameter to load a specific kernel.

To move back to a production kernel say:

raspberrypi$ sudo apt-get install --reinstall libraspberrypi-bin libraspberrypi-dev libraspberrypi-doc libraspberrypi0 raspberrypi-bootloader

Insert the SD card, via a USB dongle is that is needed.

$ diskutil list

Grab the device name, in this blog posting it is /dev/disk1.

Rewrite the partition table to delete the disk. This will also solve any permissions issues on the /dev/disk1 device.

$ sudo diskutil partitionDisk /dev/disk1 1 MBR "Free Space" "%noformat%" "100%"

Write the downloaded image to the SD card. Using unzip -p sends the image file within the .ZIP archive directly to "dd" to be copied to the SD card. That saves some time and disk space.

$ unzip -p Downloads/2014-06-20-wheezy-raspbian.zip 2014-06-20-wheezy-raspbian.img | dd of=/dev/disk1 bs=1m
$ diskutil eject /dev/disk1

The Raspberry Pi's BCM2835 system-on-a-chip has a hardware random number generator. Since the Pi doesn't have a lot of the usual sources of randomness it is well worth turning on.

Edit /etc/modules and add the line:


This will create the device /dev/hwrng at the next boot. If you can't wait until then say modprobe bcm2708_rng. When the random number generator module is installed dmesg will report:


To drop this source of random data into the kernel's pool of randomness use the rngd daemon: sudo apt-get install rng-tools.

Edit /etc/default/rng-tools to say:


The default parameters for rngd are a good fit for a inadequately described hardware random generator so there is no need to bother with setting any RNGDOPTIONS.

Restart rngd with /etc/init.d/rng-tools restart.

When rngd starts it syslogs:

rngd 2-unofficial-mt.14 starting up...
entropy feed to the kernel ready

When rngd is stopped it prints the values of statistics it maintains to validate the randomness of data read from /dev/hwrng. For example:

stats: bits received from HRNG source: 140064
stats: bits sent to kernel pool: 98944
stats: entropy added to kernel pool: 98944
stats: FIPS 140-2 successes: 7
stats: FIPS 140-2 failures: 0
stats: FIPS 140-2(2001-10-10) Monobit: 0
stats: FIPS 140-2(2001-10-10) Poker: 0
stats: FIPS 140-2(2001-10-10) Runs: 0
stats: FIPS 140-2(2001-10-10) Long run: 0
stats: FIPS 140-2(2001-10-10) Continuous run: 0
stats: HRNG source speed: (min=596.574; avg=709.100; max=743.255)Kibits/s
stats: FIPS tests speed: (min=5.947; avg=6.126; max=6.191)Mibits/s
stats: Lowest ready-buffers level: 2
stats: Entropy starvations: 0
stats: Time spent starving for entropy: (min=0; avg=0.000; max=0)us

If you underrun the "lowest ready-buffers level" then alter RNGDOPTIONS in /etc/default/rng-tools to decrease the --feed-interval from 60 seconds to 10s or even down to 1s; also increase the --rng-buffers from 3 to 5.

If programs read from /dev/random and block and this blocking is harming performance then make the hardware random number generator carry more of the load of filling the entropy pool. When --fill-watermark is not provided the contribution of the hardware random number generation to the entropy pool to 50%, increase that to 90% with --fill-watermark=90% (the "%" is required, 90 has a different meaning entirely). Note that this places more trust in the correct operation and non-subversion of the hardware random number generator.

Addendum 2015-12-03: Regenerating SSH host keys

One reason to use the random number generator is to generate secure SSH host keys. This is difficult to do without the hardware random number generate because of the low level of entropy available on the RPi soon after boot.

Remove the existing host keys:

$ sudo rm /etc/ssh/ssh_host_*

Then generate new keys, using the key algorithms recommended by your Debian distribution:

$ sudo dpkg-reconfigure openssh-server
Creating SSH2 RSA key; this may take some time ...
Creating SSH2 DSA key; this may take some time ...
Creating SSH2 ECDSA key; this may take some time ...
Restarting OpenBSD Secure Shell server: sshd.
[ ok ]

Addendum 2016-03-19: Raspberry Pi 3 and Jessie

The module name has changed to bcm2835_rng.

To install say:

$ echo bcm2835_rng | sudo tee /etc/modules-load.d/rng-tools.conf
$ sudo modprobe bcm2835_rng
$ sudo apt-get install rng-tools
$ echo 'HRNGDEVICE=/dev/hwrng' | sudo tee --append /etc/default/rng-tools
$ sudo systemctl enable rng-tools
$ sudo systemctl start rng-tools
$ sudo systemctl status -l rng-tools

Before you replace the hardware edit /etc/udev/rules.d/70-persistent-net.rules. Find the line containing the interface name you are replacing, such as NAME="eth0". Within that line alter the ATTR{address} clause from the current NIC's MAC address to the new NIC's address.

If the interface uses DHCP then remove knowledge of the DHCP lease by removing /var/lib/dhcp/dhclient.NAME.leases.

Now power down, disconnect the power lead, change the NIC card, and re-power.

If you forget to edit 70-persistent-net.rules beforehand all is not lost, you'll simply need to tidy the file up to combine the old and new NIC device entries. Alternatively, if your care factor is low then echo -n > /etc/udev/rules.d/70-persistent-net.rules, reboot, and let the file be rebuilt; of course the order of allocation of NICs to interface names might change.

Follow a similar process when using a VM and changing from emulating a NIC card to using the faster virtio adapter. Or when cloning a VM and assigning new random MAC addresses.


One thing which isn't well understood is the big number of moving parts required to get IPv6 working with your ISP. This is a quick review of what happens under the hood of your ADSL router.

Four addresses, four addressing mechanisms

Firstly, PPP Over Ethernet link control protocol allocates the link-local addressing for the PPP link. It assigns a local link-local address to the customers interface and a remote link-local address to the ISP's interface. That gives us a medium we can use to exchange IPv6 packets between the ISP and the ADSL router.

Secondly, stateless address autoconfiguration (SLAAC) assigns a global address to the PPP link between the ISP and the ADSL router. That requires both ICMPv6 and link-layer multicast to be in working order, a point often forgotten when configuring IPv6 firewalls. When autoconfiguration installs this global address from the ISP it also installs the IPv6 default route from the ISP.

Thirdly, DHCPv6 runs over the PPP link to inform the ADSL router of the IPv6 address prefixes to use for the customer LANs on the interior-facing interfaces of the ADSL router. This DHCPv6 exchange also configures routing upon the upstream ISP equipment. The implication is that if DHCPv6 stops, then your internet stops when the DHCPv6 lease expires.

The implication is that you need to take some care with which addresses are used to advertise services. If they are advertised on the prefix delegated by the ISP and that delegation disappears then the service is unreachable. For example, you may not be able to print if your ADSL link goes down. Advertising services on the link-layer address is also a bit fraught, as then the service isn't available to downstream subnets within the site.

Fourthly, there is also IPv6 link-layer addressing on each of the interior interfaces of the ADSL router, configured in the usual way for ethernet interfaces

The scenario

So much for the theory, let's have a look at the practice. I use a RaspberryPi computer as the ADSL router. It contains these interfaces:

  • eth0   An interior LAN interface. A fast ethernet interface to a fast ethernet switch. The house's access point, computers and printers plug into this switch.

  • eth1   An exterior interface to the ISP. This is a USB interface to a D-Link DSL-526B ADSL modem, configured as a bridge. The USB port carries ethernet frames to the modem using the CDC protocol.

    The Raspberry Pi's BCM2835 system-on-a-chip has one USB port. This USB bus connects across the printed circuit board to a LAN9512, which places a USB hub with one ethernet controller and two USB ports onto the bus. As a result there is no performance using the ADSL modem's ethernet port or its CDC USB port: either way the traffic enters the Raspberry Pi's BCM2835 SoC as ethernet-over-USB.

Raspbian, a Debian Wheezy Stable tuned to the ARM variant contained within the Raspberry Pi's BCM2835, is the obvious choice of operating system for this sort of fun. Just for the record it has ppp-2.4.5-5.1, ifupdown-0.7.8, and raspberrypi-bootloader-1.20130617-1 containing Linux kernel "3.6.11+ #474".


In Linux hosts don't forward out-of-the box. Let's turn that on by editing /etc/sysctl.conf


What's this special value "2"? Originally the value was "1", but this disabled autoconfiguration on all interfaces. That is, you couldn't appear to be a router on some interfaces and appear to be a host on other interfaces. But that's exactly the mental model of a ADSL router. (This is the trouble you make when you ignore the UNIX tenet that the system administrator knows what they are doing.)

There's a similar trap with enabling autoconfiguration, it disables routing. So another special value (sigh):

net.ipv6.conf.all.accept_ra = 2
net.ipv6.conf.default.accept_ra = 2

The keyword all sets the value on all current interfaces. The keyword default sets the value on all future interfaces. We need both since we don't know when sysctl -p is run to make the file's contents take effect.

Interior interface, eth0

Debian configures its interfaces in /etc/network/interfaces. It typically has private IPv4 addressing which iptables NATs to the outside, looking something like this:

auto eth0
iface eth0 inet static

My ISP, Example.Net, uses static prefix delegations. So I can statically address the interior interface. This is good as we can run services on the interior interface without its global addressing being removed.

If your ISP doesn't do this then you should allocate a random /64 subnet from fc00::/7, RFC4193 has the details. You'll then need to bind local services running on the ADSL gateway -- such as printer spooling -- to the RFC4193 subnet rather than to the prefix delegated globally-reachable address. You won't be able to access these services from the Internet, but that was your ISP's intention in allocating a dynamic address, but at least you'll be able to reach the local services when the ADSL link is down.

Let's say I was allocated 2001:0db8:1234:abcd::/56. (Not really, because this is within the documentation prefix. But hey, this is documentation.) Set /etc/network/interfaces to add:

auto eth0
iface eth0 inet6 static
    address 2001:0db8:1234:abcd::1
    netmask 64
    autoconf 0
    accept_ra 0
    privext 0

You see that we've used subnet 00. Use whatever subnet you want of the allocation you have been given. It's just that zero leads to less typing. Note IPv6's convention of placing the router on address ::1.

You'll see that we've turned off autconfiguration for this interface. That makes sense, as we've statically configured the interface. But as usual with Linux flipping autoconf bits then flips forwarding bits :-( This hack puts things back to rights:

    post-up /sbin/sysctl -w net.ipv6.conf.eth0.forwarding=2 
    post-up /sbin/sysctl -w net.ipv6.conf.default.forwarding=2 
    post-up /sbin/sysctl -w net.ipv6.conf.default.accept_ra=2 

Exterior interface, eth1

We don't need IP addressing on the ethernet interface to the ADSL modem. This ethernet link just carries PPP frames.

allow-hotplug eth1
iface eth1 inet manual
  pre-up /sbin/ifconfig eth1 up
  post-down /sbin/ifconfig eth1 down
We then add an ISP to that configuration:

allow-hotplug eth1
iface eth1 inet manual
  pre-up /sbin/ifconfig eth1 up
  up ifup ppp0=example
  down ifdown ppp0=example
  post-down /sbin/ifconfig eth1 down

iface example inet ppp
  provider example

PPPoE over exterior interface, ppp0

Configured in /etc/ppp/peers/example:

You'd have all of the regular features:
plugin rp-pppoe.so eth1
user "vk5tu@example.net"
bsdcomp 15
deflate 15

together with authentication in /etc/ppp/chap-secrets:

"vk5tu@example.net" * "Zgz4T3CRCGhH6G7Zf8mb0vIO"

Now add these to /etc/ppp/peers/example for IPv6:

+ipv6 ipv6cp-use-ipaddr
ipv6 ,

Note that comma carefully, it is needed.

Restart PPP with ifdown ppp0=example && ifup ppp0=example and look in the log messages for link-layer address assignments.

pppd[]: pppd 2.4.5 started by root, uid 0
pppd[]: PPP session is 3
pppd[]: Connected to 00:11:22:33:44:55 via interface eth1
pppd[]: Using interface ppp0
pppd[]: Connect: ppp0 <--> eth1
pppd[]: CHAP authentication succeeded
pppd[]: peer from calling number 00:11:22:33:44:55 authorized
pppd[]: local  LL address fe80::255:44ff:fe33:2211  
pppd[]: remote LL address fe80::211:22ff:fe33:4455
pppd[]: local  IP address
pppd[]: remote IP address
pppd[]: primary   DNS address
pppd[]: secondary DNS address

ISP link global addressing and default route, ppp0

ICMPv6 is used to implement IPv6 stateless automatic address configuration (SLAAC). The router advertises the subnet's prefix and the hosts add their own host addressing to that. To aid in boot time the host and prompt the router to immediately send an advertisement.

Note that these advertisements are link-layer multicasts. Some with global source addresses. It is very easy to shoot yourself in the foot with your firewall rules here. The symptom is a delayed loss of the default route, seemingly for no apparent reason.

The use of SLAAC is set using Linux's sysctl. You want these, which should already be set:

net.ipv6.conf.ppp0.disable_ipv6 = 0
net.ipv6.conf.ppp0.forwarding = 2
net.ipv6.conf.ppp0.autoconf = 1
net.ipv6.conf.ppp0.accept_ra = 2
net.ipv6.conf.ppp0.accept_ra_defrtr = 1
net.ipv6.conf.ppp0.accept_ra_pinfo = 1
net.ipv6.conf.ppp0.accept_redirects = 1
net.ipv6.conf.ppp0.accept_source_route = 0

To check operation use ip -f inet6 addr show to view the interface's addressing:

$ ip -f inet6 addr show dev ppp0
    inet6 2001:44b8:10:868:192b:b4b7:d760:9879/64 scope global dynamic 
       valid_lft 5237sec preferred_lft 5237sec
    inet6 fe80::192b:b4b7:d760:9879/10 scope link 
       valid_lft forever preferred_lft forever

Use ip -f inet6 route show to view the interface's routes.

$ ip -f inet6 route show dev ppp0
2001:44b8:10:868::/64  proto kernel  metric 256  expires 4585sec
fe80::/64  proto kernel  metric 256 
fe80::/10  metric 1 
fe80::/10  proto kernel  metric 256 
default via fe80::224:14ff:fe9a:9810  proto ra  metric 1024  expires 4525sec

If a default route isn't present then tcpdump -i ppp0 -n -v is the fastest diagnostic tool.

The SLAAC-assigned interface is dynamic. Furthermore the ISP might block access to it from the global internet. Unlike IPv4, do not use the address of the exterior interface for providing services on IPv6. Use one of the addresses from the prefix delegation. Subnet 0 is a good choice for this purpose.

ISP prefix delegation for the interior interfaces

Prefix delegation gives some addressing for you to use within your home network. You can allocate differing subnets for differing purposes. Some people like to run wired and wireless networks on different subnets to minimise the number of wireless broadcasts, which are transmitted at a low speed and thus rob wireless time from hosts doing real work.

You need to know in advance how many bits of subnetting (technically, "site local aggregator addressing") the ISP is giving you. 4, 8 and 16 are common values. For a simple network you can look at these as subnet numbers. If you use VLANs then it's a good plan to have the SLA address match the VLAN number. If you have a simple network then just use subnet 0 to make your typing simpler.

You also need to decide which IP address (technically, "interface identifier") you will use for your router's interior interfaces. ...::1 is a common and good choice and what we use in this example.

As a concrete example, we will use subnet 1 (to match the default VLAN ID) and address ::1 for the single interior interface eth0.

The ISC DHCPv6 client doesn't work over PPP links, due to a long-standing bug.

I used the WIDE DHCPv6 client. Debian packages this well, with all the necessary helper scripts out of the box.

Set /etc/wide-dhcpv6/dhcp6c.conf:

profile default
  request domain-name-servers;
  request domain-name;
  script "/etc/wide-dhcpv6/dhcp6c-script";
interface ppp0 {
  # Request a prefix delegation
  send ia-pd 1;
id-assoc pd 1 {
  prefix-interface eth0 {
    # 8 bits for subnetting
    sla-len 8;
    # Our subnet is VLAN 1
    sla-id 1;
    # Our interface has address ...::1
    ifid 1;

WIDE DHCPv6 is very quiet. If you want to debug it then hack the /etc/init.d/wide-dhcpv6-client script to add the -D debug parameter.

If you run internal services then you can set up a eth:0 interface and use subnet 0 for it. It's common for services to bind to particular addresses: ...::100 might be a web server, ::101 might be the mail server, and so on.


We are not NATing, so no firewall is required for operation. Of course we do want to keep the greater internet out of our pictures of Aunt Mabel's wedding reception. So we do want to run a stateful firewall.

I find it attractive to run a stateful firewall for connections which are forwarded through the router, but not those connecting to it. I then configure those services running on the router to reject improper usage. In this case you want the expectation-making rule in the FORWARD chain, as well as the expectation-enforcement rule for outgoing and incoming traffic.

ip6tables -A FORWARD -i eth0 -o ppp0 -m state --state NEW -j ACCEPT
ip6tables -A FORWARD -i eth0 -o ppp0 -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -A FORWARD -i ppp0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT

This simple rule checks for FORWARDed ICMPv6, discarding incoming ping6:

-A check-forward-icmp -p ipv6-icmp -m icmp6 --icmpv6-type 1 -j accept-forward-icmp
-A check-forward-icmp -p ipv6-icmp -m icmp6 --icmpv6-type 2 -j accept-forward-icmp
-A check-forward-icmp -p ipv6-icmp -m icmp6 --icmpv6-type 3 -j accept-forward-icmp
-A check-forward-icmp -p ipv6-icmp -m icmp6 --icmpv6-type 4 -j accept-forward-icmp
-A check-forward-icmp -i ppp0 -p ipv6-icmp -m icmp6 --icmpv6-type 128 -j reject-forward-icmp
-A check-forward-icmp -p ipv6-icmp -m icmp6 --icmpv6-type 128 -j accept-forward-icmp
-A check-forward-icmp -p ipv6-icmp -m icmp6 --icmpv6-type 129 -j accept-forward-icmp
-A check-forward-icmp -j reject-forward-icmp

Some comments

This is obviously more complex than with IPv4. Which should not be the case considering that IPv4 is NATing and IPv6 is routing. The major complexity and fragility is the Prefix Delegation, and doing this through SLAAC would have been a better design.

The software design is poor. The Linux kernel does its best to defeat being simultaneously a host and a router, which is the typical design for a ADSL "router". The WIDE and Dibbler DHCPv6 clients both fail when ppp0 losses carrier, rather than opening a new connection on the interface and trying again.

Errata: Router advertisement to interior network

[Whoops, left this out]

How does a host on the internal network automatically configure? It listens for advertisements from routers. Install the package radvd. Configure it to advertise the subnet's prefix and prefix length, the router's address, the MTU, and the DNS server details. radvd is fussy about the format of it's configuration file /etc/radvd.conf

interface eth0 {
  AdvSendAdvert on;
  IgnoreIfMissing on; 
  AdvLinkMTU 1500;
  AdvDefaultPreference high;
  prefix 2001:0db8:1234:abcd::/64 {
    AdvOnLink on;
    AdvAutonomous on;
  RDNSS 2001:0db8:1234:abcd::1 {
  DNSSL example.id.au {

If you are using the Raspberry Pi as a server you might want to enable the built-in hardware watchdog. This will automatically reboot the machine if user space fails to periodically write to /dev/watchdog within a reasonable time.

There are two major tasks. (1) Installing and configuring program to say "hi" to the heartbeat device periodically. (2) The kernel exposing the heartbeat device to users.

The hardware is simple enough. It counts down from n down to 0, one tick per second. Upon reaching zero the hardware reboots the machine. If the hardware is tickled then it resets the countdown timer to n and the countdown begins anew.

The Linux kernel exposes the hardware countdown timer as /dev/watchdog. The convention is that the countdown takes 60 seconds.

The Raspberry Pi watchdog runs for less time than this, between 1 and 14 seconds. That's understandable, at its heart the Raspberry Pi has a mobile phone CPU and no one is going to look at the blank screen for a minute wondering what will happen.

User space heart beat - Raspbian

The watchdog(8) daemon is the simplest way for Raspbian to periodically tickle /dev/watchdog.

sudo apt-get install watchdog
update-rc.d watchdog enable

The watchdog daemon requires some configuration on the Raspberry Pi. Edit /etc/watchdog.conf to contain only:

watchdog-device = /dev/watchdog
watchdog-timeout = 14
realtime = yes
priority = 1

If you want the daemon to consume less CPU you can extend the interval between heart beats. Four seconds still gives three chances per fourteen second interval:

interval = 4

User space heartbeat - systemd

The great simplification of system utilities by systemd encompasses watchdog timers too. Edit /etc/systemd/system.conf and set:


Kernel watchdog device

Configure the kernel to expose the watchdog device. Set the parameters to the kernel module by creating a new file /etc/modprobe.d/bcm2708_wdog.conf containing:

alias char-major-10-130 bcm2708_wdog
alias char-major-10-131 bcm2708_wdog
options bcm2708_wdog heartbeat=14 nowayout=1
  • The periodic writes from user space are called "heart beats". The heartbeat parameter to the kernel module is the maximum gap between heartbeats seen by the device before the hardware reboots. On the Raspberry Pi this gap can be as large as 14 seconds. That's substantially less than the common value of 60 seconds.

  • The nowayout parameter determines what happens when the /dev/watchdog device is closed: is a heartbeat still expected or not? A value of 0 says that no further heart beats are expected. So if the process writing the heartbeats fails then the machine will not reboot, even if that process failing is a sign that the machine is in a poor way. A value of 1 says that the countdown to a reboot keeps running and if the device is not reopened and a heartbeat written then the machine will reboot. The Raspberry Pi does not remove power to itself when halted. So setting nowayout=1 will reboot the Raspberry Pi about 14 seconds after the completion of shutdown -h now.

Normally we would put the module name into /etc/modules, but what if starting the system takes longer than the fourteen seconds available? Rather than risk a continual reboot we should let udev load the module the first time something opens /dev/watchdog. Unfortunately I can't figure out how to do that in this case :-(

The second-best option is to install the module just before it is used. The watchdog daemon on Debian allows for this in /etc/default/watchdog:

Start watchdog service

This will all take effect at the next reboot, or kick it off without interrupting service with:

sudo modprobe bcm2708_wdog
sudo service watchdog start
Check watchdog service

Check operation in the system log. Here is the module activating /dev/watchdog:

bcm2708 watchdog, heartbeat=14 sec (nowayout=1)

Here is the start of the watchdog daemon which writes the heart beats:

watchdog[]: starting daemon (5.12):
watchdog[]: int=4s realtime=yes sync=no soft=no mla=0 mem=0
watchdog[]: ping: no machine to check
watchdog[]: file: no file to check
watchdog[]: pidfile: no server process to check
watchdog[]: interface: no interface to check
watchdog[]: test=none(0) repair=none(0) alive=/dev/watchdog heartbeat=none temp=none to=root no_act=no
watchdog[]: hardware wartchdog identity: BCM2708


The USB adapter has four wires with header sockets. The purpose of the wires is

Red. VBUS (+5.0VDC 500mA) power from PC USB port.

Black. Ground for USB VBUS and PL2303's TXD and RXD.

White. RXD. Receive data (in to PL2303 USB/RS-232 adapter). Using 3.3V logic not RS-232 logic.

Green. TXD. Transmit data (out of PL2303 USB/RS-232 adapter). Using 3.3V logic not RS-232 logic.

The RPi has a set of header pins marked P1 (under pin 1 of the header). This header predominantly contains GPIO pins, but also gives an alterative to the Micro USB connector when supplying power to the Rasberry Pi. When the RPi is booted two of the GPIO pins are connected to the inbuilt UART which is used by the Linux system as a console.

Pin 6. Ground.

Pin 8. UART0_TXD using 3.3V logic not RS-232 logic, alternatively GPIO14.

Pin 9. Ground.

Pin 10. UART0_RXD using 3.3V logic not RS-232 logic, alternatively GPIO15.

Pin 11. UART0_RTS using 3.3V logic not RS-232 logic, alternatively UART1_RTS or GPIO17.

So assuing we don't want to power the RPi from this connection then we hook up the wires to the header as follows:

GPIO header USB converter
Pin 6 Black
Pin 8 White
Pin 10 Green
n.c. Red

Note that these pins are adjacent.

Plug the pins in with the RPi off. These are 3.3V logic, and they are not as robust as RS-232 logic: you can't short them or drive two loads from them like you can with RS-232 logic.

Plug the USB port into your PC. This will create a /dev/USB0 (or another number if you already have a USB character device like a 3G modem plugged in). Start up your favorite terminal emulator (minicom, screen, etc) and set the port to: 115000bps, no parity bit, 8 data bits, 1 stop bit-time, no hardware handshaking (sometimes called RTS/CTS handshaking), no software handshaking (sometimes called XON/XOFF handshaking), ignore modem status signals (such as DSR and DCD). Emulate a terminal in the VT100 or ANSI families.

When you connect the lack of modem handshaking will mean that no "login" prompt appears. Press Enter and you should see a short message and the offer to login. Otherwise check the cabling and the terminal emulator settings. Also due to the lack of modem handshaking a session will not automatically clear down when you disconnect, so remember to always log out (which us old-timers do by pressing Ctrl+D half a dozen times).

When you boot the RPi you see the Linux kernel messages but not the init system messages. If you want these to appear on the serial console then swap the order of the "console=" statements in /boot/cmdline.txt. It is the last-named console which receives the init system messages. The phrase in cmdline.txt which makes the serial port a console is:


If you want to see messages from the system logger on the console then modify /etc/rsyslog.conf. It's a sort of damned-if-you-do, damned-if-you-don't configuration. If you don't you'll miss messages about some system catastrophe which explains why the system is misbehaving. If you do then those messages will pepper your editor session as you attempt to fix the fault. If you are in the "do" camp then you want a line like:

*.err   -/dev/console

The Linux kernel will do it's hardest to get these messages out the serial port. That causes a performance reduction. So if you are using the RPi for production work rather than for development then it is wise to limit use to infrequent and interesting messages.

Hardware accessories

Now that you have your Raspberry Pi hardware you will need a Secure Digital flash memory card and a Micro USB power supply.

SD cards are plentiful. Purchase one of 4GB or more. Class 10 cards are fastest, but not all of these boot on the Raspberry Pi without firmware updates. Class 6 cards are cheaper but slower. Don't bother cards slower than Class 6, they really aren't that much cheaper and the resulting performance of the Raspberry Pi is dreadful. The larger supermarkets and office supply stores have good prices. For example, Officeworks has a "SanDisk Extreme HD Video SD HC Card 4GB", which is a Class 6 card, for A$17; the 8GB card is good value $25 and capacities above that currently have a rapidly rising cost per GB.

If your computer doesn't have a SD card slot then this would also be a good time to buy a USB/SD card dongle. Expect to pay about A$11 at Officeworks.

Plug packs with Micro USB connectors are easily found. In a retail setting, such as a mobile phone shop, you are looking at around A$30; in an electronics store like Jaycar or Altronics you are looking at around $20. If you do buy one from a retail store then check the output current: I have seen $30 plugpacks ranging from 650mA to 1200mA. Buy the highest output current you can, anything under 800mA is best avoided as the voltage sag under load will cause the Raspberry Pi to show faults.

You can also assemble a micro USB power source from a 240VAC to USB power source (A$15, or less if you keep your eyes open) and a USB-micro USB adapter (A$11 from Officeworks). The iPad and iPhone charger outputs 1000mA and the iPad2 charger outputs 2000mA.

The USB ports on the Raspberry Pi are very low powered, just enough to drive a keyboard and mouse. If you want to do something more than this then use a powered USB hub. There are substantial compatibility issues with these, as some feed voltage back to the host USB port, and the Raspberry Pi does not like that. The website www.elinux.org has a list of hubs which people have successfully used. Powered USB hubs are not popular, and so are around $30 for a 4 port hub (compared with $4 for a non-powered hub). Definately worth while shopping about.

The Raspberry Pi also has a history of packet drops on its USB port when connected to a powered hub. This seems to get better with each firmware revision. This is a major bug, since connecting a hard disk through a powered USB hub to the Raspberry Pi is just asking for data corruption.

If you are shopping for a hard disk then buy the larger USB drives which come with their own power supply rather than taking current from the host. These can be plugged directly into the Pi without a powered hub.

You'll also want to communicate with the Raspberry Pi. If you want graphics then find a USB keyboard, USB mouse and a HDMI cable. You should be able to pick up the keyboard and mouse for free on any kerbside collection day. HDMI cables are best bought from Jaycar or Altronics or Officeworks or anywhere else that isn't charging more than $10.

If you want to run headless you can connect to the ethernet ports on your ADSL router or office switch, for that you'll want a Category 5 or better UTP patch lead. These are around $5 from Rexel or $10 from Officeworks or electronics stores.

All these little items can add up, and if your Raspberry Pi seller has an optional "parts pack" then you may be able to save quite a bit. Farnell were intending to do this, but the demand for the Raspberry Pi hammered them so much that they haven't had the chance to do so yet.

Choosing a Linux distribution

There are quite a few SD card images available for the Raspberry Pi. Unfortunately the Raspberry Pi is often the victim of compatibility choices made by the distribution. The Raspberry Pi CPU is an ARM CPU with the ARMv6 instruction set with the optional vector floating point unit. Debian supports the ARMv6 with software-emulated floating point and the ARMv7 (where floating point was always included, not optional).

Ubuntu is not available as it requires ARMv7 as a minimum.

Fedora is compiled for ARMv6 with software-emulated floating point. It has a Remix aimed at the Raspberry Pi, but this is focussing on the user experience, such as allowing the partition on the SD card to be resized during the first boot.

The Raspbian distribution is Debian recompiled for exactly (and thus pretty much only) the ARM CPU used in the Raspberry Pi. The performance improvement over the stock Debian is considerable. This makes Raspbian the distribution of choice at the time of writing. Raspbian is likely to remain the best choice for headless use; hopefully a Pi-tuned Fedora or Ubuntu will eventually appear.

Writing the distribution to the CD card from a Linux machine

Download the image file for the distribution. I'll use Raspbian in the examples.

$ wget http://mirror.aarnet.edu.au/pub/raspberrypi/images/raspbian/2012-07-15-wheezy-raspbian/2012-07-15-wheezy-raspbian.zip
$ unzip -l 2012-07-15-wheezy-raspbian.zip
Archive:  2012-07-15-wheezy-raspbian.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
1939865600  2012-07-16 05:15   2012-07-15-wheezy-raspbian.img

Insert the SD card into the computer. Formatted partitions on that card usually automatically mount. Type mount and note the disk name; for example, /dev/sdb is the disk containing the mounted partition /dev/sdb1. Unmount the automatically mounted partitions with udisks --unmount /media/*. Type mount again and ensure that the disk you expected to unmount was the disk which was unmounted. Any confusion about which disk is the SD flash card will cause major problems in a moment.

Write the downloaded image to the SD card. We could do this by unpacking the .zip file and then writing the expanded image, but this is UNIX and not a toy operating system, so we can do without the time-consuming intermediate step:

$ unzip -p 2012-07-15-wheezy-raspbian.zip 2012-07-15-wheezy-raspbian.img | sudo dd of=/dev/sdb bs=64k
29600+0 records in
29600+0 records out
1939865600 bytes (1.9 GB) copied, 163.944 s, 11.8 MB/s

You can have a knowingly cynical laugh when comparing the I/O rate reported by dd (11.8MBps) versus the rate printed on the SD card's promotional packaging (30MBps).

Eject the SD card and put it into the Raspberry Pi. It will only go one way.

Thunderbirds are go!

Plug in the micro USB power supply, watch the LEDs on the board light up. If you are directly connected you'll see the Raspberry Pi logo on the screen.

If you are headless then you'll need to determine the IP address or DNS name to use.

  1. A few networks use Dynamic DNS, in this case the DNS name will be "raspberrypi".

  2. If you connected to a ADSL router, use the router's administration screens to determine the IPv4 address which was allocated.

  3. If you are connected to a larger network, then ask the network adminstrator to tell you the allocated IPv4 address. They'll look at the /var/log/messages or /var/lib/dhcpd/dhcpd.leases of the DHCP server.

Log in as the user "pi" with the password "raspberry". If you are headless say ssh pi@raspberrypi or ssh pi@ or whatever address you were assigned.

Localise the installation

Start the handy configuration tool. This is a menu front end to some commands and saves a lot of typing.

$ sudo raspi-config

Choose the "expand_rootfs" option to expand the installed partition to the full size of the SD card. It will ask you to reboot, do that with sudo shutdown -r now.

Reconnect and run raspi-config again. I set these values:

  • configure_keyboard to "PC-104" "US". If this doesn't have the desired effect then alter /etc/defaults/keyboard so that XKBLAYOUT="us", then run sudo setupcon.

  • change_locale to "en_AU.UTF-8 UTF-8". The command-line equivalent is sudo dpkg-reconfigure locales.

  • change_timezone to "Australia/Adelaide". The command-line equivalent is sudo dpkg-reconfigure tzdata.

  • Since I am running headless, memory_split to "224 224MiB for ARM, 32MiB for VideoCore"

Reboot again.

Update the installed software

I am in Australia, so the AARNet mirror is the best location for Raspbian updates. I altered /etc/apt/sources.list from

deb http://mirrordirector.raspbian.org/raspbian/ wheezy main contrib non-free rpi


deb http://mirror.aarnet.edu.au/pub/raspbian/raspbian/ wheezy main contrib non-free rpi

and then updated the installed software with:

$ sudo apt-get update
$ sudo apt-get --auto-remove --purge dist-upgrade
$ sudo apt-get clean

The Raspberry Pi also has firmware. This simplest way to update this is through rpi-update:

$ sudo wget http://goo.gl/1BOfJ -O /usr/bin/rpi-update
$ sudo chmod +x /usr/bin/rpi-update
$ sudo apt-get install git-core
$ sudo rpi-update
$ sudo shutdown -r now
Secure the Pi

Now is a good moment to change the name of the Raspberry Pi from "raspberrypi" if you wish. I used the shorter "rpi":

$ echo "rpi" | sudo tee /etc/hostname
$ sudo vi /etc/hosts
$ sudo /etc/init.d/hostname.sh restart

Being an image, everyone's SSH host keys are the same. That's not good. Regenerate the keys with:

$ sudo rm /etc/ssh/ssh_host_*
$ sudo dpkg-reconfigure openssh-server
Creating SSH2 RSA key; this may take some time ...
Creating SSH2 DSA key; this may take some time ...
Creating SSH2 ECDSA key; this may take some time ...
Restarting OpenBSD Secure Shell server: sshd.
[ ok ]

Being an image, everyone's passwords are the same.That's not good. Set a password for the "root" superuser with:

$ sudo passwd root

Rather than change the password of the "pi" user, create a user for yourself (in our example, "fredbloggs") with:

$ sudo useradd -c 'Fred Bloggs' -m -G adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,input fredbloggs
$ sudo passwd fredbloggs

It is best if the username is in lower case and doesn't contain spaces or other punctuation.

Log out of the "pi" account and test that your new account can log in and can run the sudo command.

In UNIX we don't delete accounts, we lock them:

$ sudo usermod -e 1 -L pi

You probably don't want to SSH to the Rasberry Pi as the root user, so stop people even trying (bad people will send entire dictionaries to try to log in as the root user in an attack called "door knocking"). Alter the "PermitRootLogin" line in /etc/ssh/sshd_config to "PermitRootLogin no" and restart the SSH server with sudo /etc/init.d/sshd restart.

So long and thanks for all the fish

Your Raspberry Pi is now fully installed and ready to go. There is a lot more you could do with it, but that's beyond the scope of this note. It's already long enough as it is (but hey, if you want short content-less puff pieces which make you wonder if everyone on the whole #!*$%@# planet hasn't started their own personal PR agency, then that's what Facebook or Twitter are for).

Other tasks

Consider the following:

  • Enable IPv6

  • Install random number daemon

  • Put swap into a 1GB partition if using a 16GB card (makes startup faster)

  • Move the indiecity, spi, and gpio groups out of the user groups range

  • Truncate log files

  • Change apt-get sources

Page generated 2017-10-20 23:31
Powered by Dreamwidth Studios