Blog

TorrentApp

I have a small app on my computer that I wrote myself. Itā€™s
small and simple, and itā€™s the default application for opening BitTorrent files on our computers. When I
download one of these files the app takes the file and moves it to a folder on
the server. This folder is watched by my torrent
client of choice
which runs on the server and immediately starts the
download when it sees the file.

The app then pops up a notification to the user to ask if
they want to be directed to the deluge web interface to see the download
progress.

I rewrote the app about a year ago. The original version was
written in RealStudio but the
location of the watched folder and the URL for Delugeā€™s web interface were
hard-coded in: a reasonable design decision given it was just a small app for
only my use one, but still a poor one ā€“ when a change I made to my network
configuration required me to adjust these variables I no longer had a copy of
RealStudio available.

I wrote a new version in Visual
Basic 2010 Express
, and this time I did a little extra work to take the
configuration variables out of the source code and put them into an .ini file.

Why am I telling you all this?

Well, not that I think youā€™d need the app, but I have today
made the source code
(and the compiled executable, for good measure) publicly available on my brand
new GitLab account!

Iā€™ve been using Git for a while (and Iā€™ve written about it once
or twice
before), but I really havenā€™t been taking advantage of its featureset.

Iā€™m working on something right now thatā€™s big and complex
and I value having version control and branches to work with. I already have
Git installed on my server (both my home server and my public webserver), but
Iā€™ve downloaded a windows Git client
to compliment that setup and opened a GitLab account to use as an external
repository and a means to eventually make a finished product public.

Why have I chosen GitLab over the more ubiquitous GitHub? GitHub makes you pay to host a private
repository, and I want somewhere where I can both host code thatā€™s a work in
progress (and not ready for public distribution) and distribute completed code
thatā€™s ready for download, public review and maybe even improvement by the
wider community. GitLab gives me free private repositories for
partially-completed things that I can later make public once Iā€™m ready to.

Iā€™ve already created a couple of public repositories, mostly
to test the platform out, and TorrentApp is one of them.

So use it if itā€™s a tool that might be useful to you,
improve upon it if you have the expertise, and send me a merge request so I
can incorporate your changes into the code!

Blog

Windows Authentication on External Websites

My home network is domain-based, and Iā€™m running a Windows Server 2008 VM as the domain controller. Iā€™ve written
in the past
about how to use PHP to do authentication using domain
credentials, and that works great for some scenarios. As a case in point, I use
Pydio to host a web-based file manager that
allows me access to my files when Iā€™m out and about. Pydio runs on a linux
server VM on my home
server
, and it actually includes a built-in mechanism to authenticate
against an LDAP server (the Windows domain controller) so I didnā€™t have to
modify it with my PHP code. The principle is the same, though.

image

This is all good stuff for anything hosted on my home
server, but what if that isnā€™t what I want? What if I want to host something on
my external, public webserver, and still use my active directory credentials to sign in to
it? And, while weā€™re at it, what if I want to be even more restrictive and
limit access to a particular organizational unit within active directory?

As luck would have it, these are all problems that I solved
this week. Read on!

Creating a Reverse SSH Tunnel

The first thing we need is to establish a secure connection
between the external webserver (the VPS) and the internal webserver (the local
linux VM). Weā€™re going to use a reverse SSH tunnel to do this,
and, specifically, weā€™re going to use a tool called autossh that will keep an eye on
the tunnel and restart it if something goes wrong.

Iā€™ll skip most of the technical detail here, but essentially
a reverse tunnel is going to forward a particular port on the external server
to a particular port on the internal server. Itā€™s called a reverse tunnel
because itā€™s the internal server that triggers the connection. Thatā€™s important:
the internal server can reach the external one just fine, but not the other way
around (thanks to things like me having a dynamic IP address for my home
internet connection, my home routerā€™s firewall, DHCP, etc).

I installed autossh on my Ubuntu server VM:

sudo apt-get install autossh

And then wrote a one-line script that I placed in /etc/network/if-up.d:

#!/bin/sh
su -c "autossh -M 29001 -f -N -R 8080:localhost:80 remote-server.com" localadmin

Teasing this apart just a little, it uses the local account ā€œlocaladminā€
to run the command enclosed in the quotation marks. That command forwards port
8080 on ā€œremote-server.comā€ to port 80 on the local machine.

For this to work itā€™s essential that the user ā€œlocaladminā€
is able to log on to ā€œremove-server.comā€ without
needing to enter a password
.

The Local Server

The local webserver is where most of the heavy-lifting is
going to take place. The first thing I did was create a new virtual host in the
webserver configuration on that machine. Iā€™m using lighttpd, so my configuration looks like
this:

$HTTP["host"] =~ "^auth.gateway" {
    $HTTP["remoteip"] !~ "127.0.0.1" {
        url.access-deny = ("")
    }

    server.document-root = "/home/jason/WebServer/Production/auth.gateway"

    url.rewrite-once = (
        "^(.*)$" =>"auth.php"
    )
}

Essentially it creates a new host with the hostname ā€œauth.gatewayā€
thatā€™s only accessible to the local machine (127.0.0.1). Any request that comes
in regardless of the URI is rewritten to a file called auth.php in the document
root.

The hostname here isnā€™t real (i.e. thereā€™s no public DNS
entry for it), and thatā€™s probably a good thing for the sake of locking down
security as tightly as possible. Also on that line of thinking is the fact that
access is limited to the local machine. The webserver doesnā€™t know that requests
coming through our SSH tunnel are coming from another machine thanks to the
virtues of port forwarding ā€“ it thinks theyā€™re coming from other processes
running locally (i.e. coming from 127.0.0.1).

Next is auth.php itself, the engine that runs all this
stuff:

<?php
    session_name ('AGSESSID');
    session_set_cookie_params(600);
    session_start();

    $domain = "testdomain.local";
    $domaincontroller = "dc1.testdomain.local";
    $requiredou = "FamilyMembers";
    $authkey = "big-random-string";

    if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['HTTP_X_AUTH_KEY']) || $_SERVER['HTTP_X_AUTH_KEY'] != 'big-random-string') {
        header('WWW-Authenticate: Basic realm="Authentication Required"');
        header('HTTP/1.0 401 Unauthorized');
        exit;
    } elseif (!isset($_SESSION['AuthKey']) || $_SESSION['AuthKey'] != md5($_SERVER['HTTP_X_FORWARDED_FOR'].$_SERVER['PHP_AUTH_USER'].$_SERVER['PHP_AUTH_PW'])) {
        $ldap = ldap_connect($domaincontroller);

        ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
        ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);

        if (!$bind = ldap_bind($ldap, $_SERVER['PHP_AUTH_USER']."@".$domain, $_SERVER['PHP_AUTH_PW'])) {
            header('WWW-Authenticate: Basic realm="Authentication Required"');
            header('HTTP/1.0 401 Unauthorized');
            exit;
        } else {
            $result = ldap_search($ldap, "DC=".implode(",DC=", explode(".", $domain)), Ā "(samaccountname=".$_SERVER['PHP_AUTH_USER'].")");
            $entries = ldap_get_entries($ldap, $result);
 
            if (strpos($entries[0]['distinguishedname'][0], "OU=".$requiredou) === FALSE) {
                header('WWW-Authenticate: Basic realm="Authentication Required"');
                header('HTTP/1.0 401 Unauthorized');
                exit;
            } else {
                $_SESSION['AuthKey'] = md5($_SERVER['HTTP_X_FORWARDED_FOR'].$_SERVER['PHP_AUTH_USER'].$_SERVER['PHP_AUTH_PW']);
            }
        }
    }
?>

As you can see, this is quite a bit more sophisticated than
the previous example in my SSO post, but letā€™s tease this one apart at a high
level too.

When the script is loaded, it first checks to see if the thereā€™s
a username, password and ā€œAUTH_KEYā€ contained within the HTTP headers of the
request. If so, it verifies that the ā€œAUTH_KEYā€ is what it was expecting, and it
tries to use the username and password to establish an LDAP connection to the
Windows server VM. If thatā€™s successful, it retrieves some information about
the user and checks if theyā€™re a member of the required organizational unit.

If all that works it sends back an empty page, but,
crucially a HTTP 200 status (meaning everything is OK). If any of those checks fail
then it sends back a HTTP 401 status (unauthorized) header instead.

In addition to this, the script creates a PHP session with a
custom name. The name is custom to avoid collisions with any session that
the external server may be creating, but essentially the session lasts 10
minutes, and if subsequent requests come in for a user thatā€™s already been
authorized then it skips all the checks and just sends back the HTTP 200
header. It does that because without it, every HTTP request made to the remote
server (not just every page served, but every image on every page, every CSS
file, JavaScript file, etc, etc) would involve a query to the domain controller
to validate the credentials, and thatā€™s a potential bottleneck with performance
implications.

The Remote Server

My remote server is running nginx as its webserver (Iā€™m new to it,
but I think I like it better than lighttpd. Thatā€™s kind of beside the point
though). The configuration looks like this:

server {
    server_name example.com;
    listen 80;

    root /home/jason/example.com/www;

    auth_request /__auth;
    auth_request_set $saved_set_cookie $upstream_http_set_cookie;
    add_header Set-Cookie $saved_set_cookie;

    location = /__auth {
        auth_request off;

        proxy_pass http://localhost:8080;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header Host auth.gateway;
        proxy_set_header X-Original-URI $request-uri;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Auth-Key "big-random-string";
    }
}

When we tease this one apart, there are two key details. One
is that ā€œauth_requestā€ declaration in the fourth line. As per nginxā€™s
documentation
, auth request ā€œimplements client authorization based on the
result of a subrequest.ā€ In other words, instead of nginx doing the
authentication itself it forwards the request on. The configuration above
defers the authentication of http://example.com to http://example.com/__auth.

The second crucial chunk of the configuration file is
everything within the ā€œlocation = /__authā€ declaration. The first thing this does
is turn off the ā€œauth_requestā€ functionality (otherwise, weā€™re stuck in an
endless loop), and it then creates a proxy to redirect any requests to
http://example.com/__auth to http://localhost:8080. Port 8080, if you recall,
is in turn forwarded through our SSH tunnel to port 80 on the local server.

Additionally, it sets the hostname involved in the request
to ā€œauth.gateway,ā€ forwards a couple of other pieces of information as headers,
and, for some added security, sends an ā€œX-Auth-Keyā€ header that our PHP script
checks for.

Back outside of this block the ā€œauth_request_setā€
declaration takes the session cookie from our PHP script and saves it to a
variable, then the following line (ā€œadd_headerā€) sends that cookie back to the
clientā€™s browser as part of the response they receive.

Done!

Real World Problems with All This

I mentioned earlier that we set a session cookie as part of
the whole interaction to avoid the need to query the LDAP server for every HTTP
request the remote server receives, and I said this was to avoid a performance
bottleneck. Thatā€™s true, but we still have a performance bottleneck here: for
every HTTP request the remote server receives itā€™s still querying the local
server through our SSH tunnel, even if all the local server is doing is
responding that the credentials are good based on the existence of the session
cookie.

This communication has to take place over my home internet
connection, which is absolutely not what my ISP intended it to be used for. I don’t think it’s against their terms and conditions or anything like that, itā€™s just that it isnā€™t
really fast enough.

If the site deployed on the remote server was one of my own
making then Iā€™d modify this approach to create an authentication API of sorts
on the local server, and Iā€™d do the session setting and credential caching
entirely on the remote server, drastically reducing the number of queries to
the local server (all the way down to a single query, in fact, when the session
is first created and the user logs on).

The other problem is one of securing the whole interaction.
Weā€™re using ā€œbasicā€ HTTP authentication methods here, which means that the
username and password are passed around in the clear (theyā€™re not encrypted or hashed as
part of the process). Thatā€™s necessary: the auth.php script has to receive the
password in cleartext because it has to pass it to the Windows server to check
its validity. Itā€™s also not an issue with the communication between the remote
and local webservers, because that happens through an SSH tunnel thatā€™s using
public/private keypairs to provide encryption. It is a problem for the
communication between the user and the remote webserver though, and it leaves
our user vulnerable in several ways (especially if theyā€™re using a public WiFI
hotspot). Essentially what Iā€™m getting it is that you must use SSL between the user and the remote server.

Conclusion

This is not the most optimal way of doing things,
particularly in regards to the bottleneck it creates by deferring authentication
of every HTTP request to my local server which is connected to the internet
using a typical consumer-grade ADSL connection, but as a quick and dirty way of
securing resources on my public webserver without needing to modify the
resource itself in any way, it works great!

Enjoy!

Blog

Compiling Third-Party Modules Into Nginx

I want my public web server, which runs nginx, to authenticate against my active directory server using LDAP. Iā€™ve written in the past about how to use PHP to authenticate against active directory in this way, but there are a couple of problems: my active directory server isnā€™t accessible to the internet, and I want to use standard HTTP authentication instead of username and password boxes included on a webpage.

The answer, I think, is to put an authentication PHP script on my home server, make that available to the public web server through an SSH tunnel, and then use nginxā€™s Auth Request module to authenticate against it using the public server as a proxy.

This is – I hope – less complicated than it sounds. Weā€™ll see, and Iā€™ll post more if and when Iā€™m successful, but the problem Iā€™ve initially run into is that nginx in Ubuntuā€™s repositories doesnā€™t include the Auth Request module. I have remove nginx and re-install it from source, compiling it with the additional module included.

Itā€™s a bit of a daunting process, but the page Iā€™ve linked seems like it will take me through it step by step.

Wish me luck!

Compiling Third-Party Modules Into Nginx

Blog

Raspberry Pi Whole Home Audio: Playing Music

Itā€™s very rare that I tweet teasers to my blog post, but
last weekend I was so excited to be making progress on my Raspberry Pi Whole
Home Audio
project that I told the world Iā€™d be publishing this one on
Thursday.

Here we are on Friday morning. Thereā€™s doubtless a lesson in
here for me about making promises I canā€™t keep, but Iā€™m hoping youā€™ll forgive
me when you read about what Iā€™ve done.

If youā€™ve been following my #RPiWHA Project
hashtag on this blog then youā€™ll know that when we left off last time I had
three Raspberry Pis networked together with synchronized clocks, and one of
them had access to the internet and the music library I keep on my home server.
Thatā€™s important, but not especially exciting. Today weā€™re going to move in a
more exciting direction, though.

Today weā€™re going to put Pis #2 and #3 aside, but weā€™re
going to get Pi #1 playing music!

Specifying and Testing the Piā€™s Audio Output

The Raspberry Pi has two options for audio output. It has a
3.5mm analog output, and digital output through its HDMI port. It decides which
output to use automatically ā€“ if you have a HDMI monitor plugged in then the Pi
will detect this and assume you want to use HDMI for audio too.

Thatā€™s not the situation for me (my Pi is ā€œheadlessā€ and
doesnā€™t have a display connected at all), and audio comes out of the 3.5mm
output automatically ā€“ which is what I want. If you need to specify, you can
run:

sudo amixer cset numid=3 1

The digit 1 at the
end means the Pi should use the analog audio output. Putting 0 there instead would mean auto-detect
(the default) and putting 2 would
mean digital output over HDMI.

Plug in some headphones or speakers and run:

aplay /usr/share/sounds/alsa/Front_Center.wav

You should hear a voice saying ā€œfront centre.ā€

Install Mopidy

Weā€™re going to install music playing software called mopidy.
It provides a web-based interface so you can control your music, or there are
controller apps available in your app-marketplace of choice. Mopidyā€™s website
takes you through the
install process in detail
, but Iā€™m going to summarize the commands here:

wget -q -O - https://apt.mopidy.com/mopidy.gpg | sudo apt-key add -
sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/mopidy.list
sudo apt-get update
sudo apt-get install mopidy python-setuptools

Done! We now have a basic install of mopidy, and the especially
astute amongst you will have noticed that weā€™ve also installed a package called
python-setuptools. Mopidy is written
in the python programming language, and the latter package is going to help us
with installing and setting up some mopidy extensions in an automated way. The
first thing weā€™re going to do is install something called pip, which is a tool for installing python packages:

sudo easy_install pip

Now that we have that, weā€™re going to in turn use pip to
install some mopidy extensions:

sudo pip install Mopidy-MusicBox-Webclient
sudo pip install Mopidy-WebSettings

With those commands weā€™ve added a web-based interface to our
player so we can control it from a browser on another computer or mobile
device.

Setting Up Mopidy

Weā€™re almost ready to start mopidy and try things out, but
there is a little bit of initial setup to be done first. Edit the file ~/.config/mopidy/mopidy.conf. In the http section, change the following line
so that the web interface becomes accessible to any device on your network:

hostname = ::

In the local
section, tell mopidy where it should find your music library. In my case:

media_dir = /mnt/music

Save the file and exit. The next step is to tell mopidy to
scan your music folder:

mopidy local scan

If, like me, you have a large music collection stored on a
network share, be prepared for this to take a very long time. I started it
running before I went to bed, and it eventually completed the process about 45
minutes after I got up the following morning.

When itā€™s done though, weā€™re ready! Run mopidy:

mopidy

Itā€™ll take a little while to fully start up, but when you
see the line

INFO     HTTP server running at [::]:6680

that means weā€™re good to go. Open the browser on your
computer or mobile device and point it to
http://192.168.1.71:6680/musicbox_webclient (replace 192.168.1.71 with the IP
address of your Pi as appropriate). Go to Browse, Local Media, and select a
song!

If all is well the music will be playing through the
headphones or speakers attached to the Pi, and weā€™re all done until the next
installment ā€“ rerouting the audio from Pi #1 and streaming it, synchronized, to
Pis #2 and #3 instead.

Enjoy!

Blog

Browse Anonymously with a DIY Raspberry Pi VPN/TOR Router

So, after last week’s post about preparing my Raspberry Pis for my whole home audio project, I had three Pis that should have been set up properly, but weren’t working very well – and the culprit was the USB WiFi dongles I was using.

Happily a stumbled upon the article linked above, and it solved the issues I was having!

Surf the Internet securely with your very own portable WiFi VPN/TOR router. You can configure a Raspberry Pi with Linux and some extra software to connect to a VPN server of your choice.

I didn’t follow all the steps because they’re doing something different to me, but there is some commonality and, crucially, the article folks are using WiFi adapters with the same chipset that mine have. Step four shows you how to download and compile a version of hostapd that’s built especially for them and works well. I’ve updated my previous post with these steps.

Now that I have networking all set up I’ve taken a couple of extra steps:

  • I set up passwordless ssh between the three Pis. This isn’t required for my solution per se, it just makes things easier.
  • I used sshfs on pi #1 to connect it to my existing home server, and mount the folder that holds all my music.

I’m excited to move on to next steps! The prep work was necessary, but it didn’t make for an especially interesting blog post because it’s all a bit dry.

Keep following my #RPiWHA Hashtag! The next installment will be more interesting, I promise. We’re going to get some actual music playing!

Browse Anonymously with a DIY Raspberry Pi VPN/TOR Router

Blog

Raspberry Pi Whole Home Audio: Preparation and Networking

At the start of the month I announced my plan to try and build my own whole home audio system using a handful of Raspberry Pis to act as the player and audio
receivers. Iā€™ve received
all the stuff I need
now, and Iā€™m ready to get to building!

The first thing Iā€™m doing is preparing the Pis and setting
up networking. Next Iā€™m going to install audio playing software with a
web-interface on Pi number one, and thirdly Iā€™ll adjust the setup so that this
player sends itā€™s audio to the other two Pis (the receivers) instead of
outputting it directly to its own speakers. You can follow the whole journey by
following the #RPiWHA
Project
hashtag right here.

Installing Raspbian

Raspbian is the Raspberry Piā€™s recommended operating system.
Thereā€™s plenty of guidance online on how
to install it
, so I wonā€™t reiterate the whole process here. When I ran
through Raspbianā€™s initial setup options on first boot I set my location,
timezone and keyboard layout (in Internationalisation Options), set the memory
split to 16mb for graphics (in Advanced Options ā€“ we can set this low because
we wonā€™t even be connecting a display) and finally expanded the filesystem
(right from the main menu).

Minimizing SD Card Access

The Pi has no power button. If itā€™s plugged in then itā€™s on,
and you turn it off by pulling the plug. Iā€™ve read online that if the power is
pulled while the system is in the process of writing to the Piā€™s SD card (which
is the only storage the system has) this can cause problems and possible
corruption.

Linux systems do a lot of logging, most commonly to the
folder /var/log. They also write stuff about running process to the folder
/var/run. To minimize writes to the SD card, weā€™re going to mount these two
folders in memory instead of on the card. Another cause of frequent writes is
that linux systems store the time that a file was last accessed, so even if weā€™re
just reading a file the system is actually writing back to the disk to update
the time that the file was accessed. Weā€™re going to change that behaviour too.

To make these changes, weā€™re going to edit the file
/etc/fstab so that it looks like this:

proc            /proc           proc    defaults          0       0
/dev/mmcblk0p1  /boot           vfat    defaults,noatime  0      2
/dev/mmcblk0p2  /               ext4    defaults,noatime  0      1
none            /var/run        tmpfs  size=1M,noatime   0       0
none            /var/log        tmpfs  size=1M,noatime   0       0

The first two lines havenā€™t changed, but on the third line
weā€™ve added the flag ā€œnoatimeā€ to indicate that we donā€™t want to store the
timestamp that the file was last accessed. The fourth and fifth lines are
entirely new, and these create 1mb partitions in RAM to house the /var/run and /var/log folders respectively.

Setting Up Networking on Pi #1

The next step was to connect one of the Pis (and only one)
to my existing home WiFi network. To do this I plugged in one of my USB WiFi
adapters and modified the /etc/network/interfaces file to include the
following:

auto wlan0
allow-hotplug wlan0
iface wlan0 inet static
wpa-ssid MyHomeWiFiName
wpa-key-mgmt WPA-PSK
wpa-group CCMP TKIP
wpa-pairwise CCMP TKIP
wpa-psk MyHomeWiFiPassword
address 192.168.1.71
netmask 255.255.255.0
gateway 192.168.1.254
dns-nameservers 192.168.1.53 192.168.1.254

Your setup will probably be slightly different, but
essentially this connects to my home network, gives the pi a static IP address
(192.168.1.71 in my case) and defines my two DNS servers.

You may be wondering why Iā€™m only doing this on one of the
Pis, given that they all need to be connected together. The reason is that this
first pi (the player) is ultimately going to be sending audio out over the
network as multicast packets. In other words, this data goes to every device on
the network whether they want it or not.

The problem is that this is a lot of data flowing around, and
a typical home WiFi network struggles under the load of it all. My solution is
to have two WiFi networks. The one weā€™ve set up above will connect us to the
internet (for streaming audio services) and other stuff on my network (like the
fileserver where my music collection lives), but weā€™ll use a second, separate
WiFi network to send the multicast audio to other Pis.

Letā€™s plug in a second USB WiFi adapter to the first Pi, and
make some more additions to the /etc/network/interfaces file:

auto wlan1
allow-hotplug wlan1
iface wlan1 inet static
address 192.168.5.1
netmask 255.255.255.0

This section is pretty minimal as you can see, but itā€™s
setting a static IP address on the second wireless interface. The important
part is that this uses a different subnet to the other WiFi network (in my
case, 192.168.1.x is my existing network, 192.168.5.x is the dedicated network
for the Pis).

This section of the /etc/network/interfaces file is so short
because this Pi is going to act as a wireless access point that the others will
connect to. To set this up we need an additional bit of software, called
hostapd. Because I’m using WiFi adapters based on a Realtek 8188 chipset, I had to download and compile this myself – the version found in the debian software repositories wouldn’t work for me:

wget https://github.com/jenssegers/RTL8188-hostapd/archive/v1.1.tar.gz
tar -zxvf v1.1.tar.gz
cd RTL8188-hostapd-1.1/hostapd
make
sudo make install

Then edit the file /etc/hostapd/hostapd.conf to change the following three lines:

interface=wlan1
ssid=PiWHA
wpa_passphrase=mySecurePassword

Finally, start the service and add it to the boot autostart services for future:

sudo /etc/init.d/hostapd start
sudo update-rc.d hostapd enable

Setting Up Networking on the Other Pis

We want the other Pis to connect to the wireless network
hosted by Pi #1. To do so, plug one USB WiFi adapter into each and modify the
/etc/network/interfaces file on each to reflect the following:

auto wlan0
allow-hotplug wlan0
iface wlan0 inet static
wpa-ssid PiWHA
wpa-key-mgmt WPA-PSK
wpa-group CCMP TKIP
wpa-pairwise CCMP TKIP
wpa-psk mySecurePassword
address 192.168.5.2
netmask 255.255.255.0

The important point here is that the IP address for each
must be unique, and must be on the same subnet (192.168.5.x) that we set on the
first Pi.

Setting Up Time Synchronization

The Raspberry Pi has no real-time clock, and instead it gets
the time from internet time servers at boot. Having the time synchronized on
each of our Pis is going to be important to make sure that they play music in
sync. Only the first Pi has a connection to the wider internet though, so we
need to take some additional steps. On Pi #1, edit the file /etc/ntp.conf and
uncomment (or add) the following line:

broadcast 224.0.0.1

This tells the pi to broadcast a time signal out onto the
network using a special multicast IP address that the other Pis will listen
for.

On the other Pis edit the same file, but uncomment (or add)
the following lines:

disable auth
broadcastclient

We donā€™t need to tell the other Pis which multicast IP
address to listen for ā€“ they already know as part of the NTP protocol.

And Weā€™re Done! Or Are We?

That was a lot of setup work, but we should now have our Pis
setup and networked together, with our player device having an additional
connection to the wider internet.

The thing isā€¦ I donā€™t. The setup is all correct, but the
cheap USB WiFi adapters I bought from China donā€™t properly support access point
mode. Sometimes things work, sometimes they donā€™t.

Iā€™ve read that I can download driver source-code from the
adapterā€™s manufacturer and compile the driver myself, so Iā€™m going to try this
before I go further.

Blog

A little while ago I wrote about the Whole Home Audio project I’m planning, which will be a DIY effort based on several Raspberry Pis.

Well, good news! All the stuff I’d ordered has arrived, and I’m nearly ready to get started. Here’s what you see in the picture:

  1. 3x Raspberry Pi Model B+
  2. 3x Raspberry Pi Enclosure (Black)
  3. 3x Dual USB Power Supply
  4. 5x MicroUSB Cable
  5. 5x USB WiFi Adapter (I need four, but I accidentally ordered too many)
  6. 5x Samsung Class 10 8GB MicroSD Cards
  7. 2x Powered HDMI to VGA Adapter, with Audio Out
  8. 1x USB Wireless Mini Keyboard & Touchpad

Not all of this stuff will make it into the project, but I bought it so that I can use the Pis as media playing devices (running Kodi) that I’ll attach to the bedroom TV and the projector if things don’t work as planned.

I bought the keyboard because it would be useful in that regard, and I got the HDMI to VGA adapters because my projector doesn’t have an HDMI input at all, and the bedroom TV doesn’t have one spare. I’d read online that these things draw quite a bit of power – possibly too much for the Raspberry Pi’s HDMI output to reliably supply – which is why I went for a powered model, and why I picked power adapters with two ports each.

I’ve also read that fast MicroSD cards will greatly contribute to the Pi’s performance and that Class 10 is highly recommended. I also read that some Samsung Class 4 or 6 cards have better real-world performance than some of the Class 10 cards out there. I pushed the boat out and got some Class 10 cards from Samsung.

Follow the #RPiWHA Project hashtag on this blog to keep track of my progress. Next week I’m away travelling from work, but I’m excited to get started and start building, so it won’t be too long until the next update.

Blog

A little while ago I wrote about the Whole Home Audio project I’m planning, which will be a DIY effort based on several Raspberry Pis.

Well, good news! All the stuff I’d ordered has arrived, and I’m nearly ready to get started. Here’s what you see in the picture:

  1. 3x Raspberry Pi Model B+
  2. 3x Raspberry Pi Enclosure (Black)
  3. 3x Dual USB Power Supply
  4. 5x MicroUSB Cable
  5. 5x USB WiFi Adapter (I need four, but I accidentally ordered too many)
  6. 5x Samsung Class 10 8GB MicroSD Cards
  7. 2x Powered HDMI to VGA Adapter, with Audio Out
  8. 1x USB Wireless Mini Keyboard & Touchpad

Not all of this stuff will make it into the project, but I bought it so that I can use the Pis as media playing devices (running Kodi) that I’ll attach to the bedroom TV and the projector if things don’t work as planned.

I bought the keyboard because it would be useful in that regard, and I got the HDMI to VGA adapters because my projector doesn’t have an HDMI input at all, and the bedroom TV doesn’t have one spare. I’d read online that these things draw quite a bit of power – possibly too much for the Raspberry Pi’s HDMI output to reliably supply – which is why I went for a powered model, and why I picked power adapters with two ports each.

I’ve also read that fast MicroSD cards will greatly contribute to the Pi’s performance and that Class 10 is highly recommended. I also read that some Samsung Class 4 or 6 cards have better real-world performance than some of the Class 10 cards out there. I pushed the boat out and got some Class 10 cards from Samsung.

Follow the #RPiWHA Project hashtag on this blog to keep track of my progress. Next week I’m away travelling from work, but I’m excited to get started and start building, so it won’t be too long until the next update.

Blog

I’m Back!!

Did you miss me?

Hopefully you didnā€™t even notice I was gone, but two days ago Tumblr terminated my account, removing this blog and Shrapnel from the internet. I immediately contacted support as directed and heard back from them yesterday evening: my account had been closed for contravening Tumblrā€™s community guidelines in relation to spamming and affiliate marketing.

I replied to make the point that at no point have I engaged in spamming or affiliate marketing, and apparently someone there agreed because I am now back online. The issue, as it turns out, was that my two Tumblr blogs were sending visitors back to jason.jnf.me (where I had a script that presented the blog content in a subfolder, integrating it into the site to a much greater degree than a separate domain would).

In the short-term Iā€™ve removed the redirect by simply resetting my blogā€™s theme to the default, and Iā€™ll take some time on the weekend to restore the look and feel I had previously, and probably give each of them a custom subdomain.

In the longer term, I think itā€™s time to start looking for an alternative blogging platform. When it seemed as though all the content I had on this blog had disappeared I was extremely disappointed. I run my own server, so I probably shouldnā€™t be relying on third-party services anyway.

The obvious suggestion would be to install WordPress, and while that would work great for my blog content I think Iā€™d have a hard time implementing some of the other site pages on that platform. What I want is a CMS (to give me the ability to quickly and easily manage and edit content) that lets me build custom bits and pieces (like my feed page) on top of it. Iā€™ve chosen PyroCMS. Itā€™s built on the CodeIgniter framework that Iā€™ve previously used which should make for relatively easy extensibility. Itā€™s going to take me some time, but Iā€™ve installed it on my development server to start getting my hands dirty. Iā€™m just happy Iā€™m back online and I donā€™t have to spend this weekend trying to rebuild.

Blog

Whole Home Audio

Recently, I have become enamoured by the idea of whole home audio. And when I say enamoured, letā€™s be clear what Iā€™m actually talking about: I mean I’ve become obsessed by it.

Hereā€™s the thing though: Iā€™m not obsessed with the functionality. It would be nice to be able to play some music and have it come out of all the speakers in the house (without running cables all over the place), but what Iā€™m actually obsessed with is the price of systems that can do this.

image

The most popular system for whole home audio (or at least the one against which others are apparently measured) is Sonos. In my ideal setup I would want to be able to play music in the living room, kitchen, office and bedroom. To get the Sonos hardware necessary to build the system Iā€™d want (including surround-sound capable hardware in the living room for when we watch TV) Iā€™d have to spend about $3,000, and Iā€™d have to throw out all our existing audio equipment for not being compatible.

Itā€™s simply not worth it, in my opinion.

There are alternatives to the Sonos system available, of course, but this kind of system seems to be primarily the domain of high-end audio manufactures whose wares are priced beyond what I would consider sensible given my needs.

So, Iā€™ve decided not to buy a whole home audio system at all. Iā€™ve decided to try and build my own.

Enter the Raspberry Pi.

image

If youā€™re not familiar, the Raspberry Pi is a credit-card sized computer that costs about $40. It has a 700MHz ARM processor and 512mb RAM. Itā€™s not powerful, then, but it runs a Linux distribution and is designed to be a platform for electronics projects.

To start off with Iā€™m going to buy three of them ā€“ one for sending audio and two to receive it. Iā€™ve read about people who have managed to get a setup similar to the one I want working, and Iā€™ve read about many, many more people who came across challenges they found insurmountable and gave up. The nice thing about the Pi is that I can think of a million uses for it, so if I end up falling into the latter category at least I wonā€™t feel like I wasted my money.

Thereā€™s some Linux software available called Pulse Audio, which will be the basis of my project. Iā€™ve heard of Pulse Audio before because itā€™s the audio subsystem you find in many Linux distributions. What I didnā€™t know until recently though is that itā€™s capable of taking the audio that would normally be output to the computerā€™s speakers and sending it instead to another computer (or several other computers) on the network to be output there.

From what Iā€™ve read online the people that have managed to get this working have done so on a wired network, and theyā€™ve found that if they try and switch to a wireless setup then their router is flooded with audio traffic and canā€™t cope. This is a problem for me because wireless is one of my requirements, so my plan is to use a dedicated WiFi network for the audio: the sender will have two USB WiFi dongles attached, one to connect to the existing wireless network in my home for access to my music library and the internet, and a second to connect to an ad-hoc network used to communicate with the two receivers.

If Iā€™m able to get this setup working then I have some plans for extending the system and building additional functionality. Watch this space!