
This content was originally posted on cyotek.com.
I've been running Mopidy for a few weeks now on a Raspberry Pi 3
Model A using a spare set of computer speakers. As I also have a
spare Raspberry Pi Zero W, I decided to buy a HAT for this that
would allow me to use a set of proper hi-fi speakers that were
powered by the Pi instead of external power.
This article describes how to set up the Mopidy music server
with selected extensions using the Pimoroni pHAT Beat.
However, you could follow most of this guide to create a Mopidy
music server using another model of Raspberry Pi via the built
in audio chip and 3.5mm audio jack. In this case, just ignore
the instructions for installing the pHAT Beat software and
follow everything else.
Required Hardware
For my setup, I used the equipment below. The links point to
The Pi Hut but if you aren't based in the UK you could try
Adafruit or your own electronics retailer.
- A Raspberry Pi Zero W. Mine was an older model 1.1
version and was bare - GPIO headers (both male and female, male to fit to the bare
board and female for connecting to the HAT). As I don't
currently have a soldering iron, I choose to use this kit
that included solderless versions of both headers along with a
nifty installation jig for hammering them into the boards
without breaking anything - pHAT Beat audio board. This has two pairs of connectors
for wiring a pair of speakers, two rows of 8 leds and some
hardware buttons - Speakers. I picked up a pair of 40W 8Ω speakers from eBay
(TEAC LS-X8 for the curious). I naively assumed any speakers
would work but this isn't correct - Speaker wire. Again, I didn't really do my research and just
grabbed a coil of 1.5mm pure copper speaker wire, which does
work but is probably overkill - A 64GB class 10 U1 A1 SD card
- A monitor for at least the initial set up
- A keyboard for at least the initial set up
Preparing the operating system
I'm going to assume that if you're using a Raspberry Pi you
already know how to flash operating systems onto the SD card, so
I won't provide instructions. Previously I used Rufus for
this sort of task, but the recently introduced Raspberry Pi
Imager could scarcely make this easier if it tried and is my
new go-to tool for imaging Raspberry Pi cards. As I don't need a
desktop environment for this project, I installed Raspbian
Buster Lite.
This guide is assuming you are starting from a completely fresh
setup.
Caveat Emptor
As is sometimes the case, this guide comes with a caveat or two.
Firstly, I'm not a Linux expert. I know enough to be dangerous
as they say. So I may not be using the most efficient commands
or may not be following best practices. Suggestions on
improvements are definitely welcome!
Secondly, I know even less about electronics that I do about
Linux. My level is basically plugging LED's and resistors into a
breadboard and getting overly excited when they light up.
Therefore I am not making any recommendations on what speakers
are compatible or what type of speaker wire to use... it's more
than likely I'm using the wrong ones now, even though so far
everything has been running fine.
Finally, this being Linux all the software I will be installing
is open source by various individuals. At the time of writing
(April 4th 2020) this guide works fine (I have done a fresh run
run from start to end four times during the course of writing
this article) but that is no guarantee it will work in a months
time. On the bright side, at least it isn't using Node so more
than likely it will work in a months time.
Installation

First Steps
- Connect the pHAT to the Pi
- Connect a keyboard and monitor to the Pi
- Insert the flash card
- Power up the Pi and wait for initial setup to complete (this
may involve an automatic reboot) and for a login prompt to
appear - Log in. For Raspbian, the default credentials is user
pi
and
passwordraspberry
(Optional) Changing the password
- Execute
passwd
and follow the prompts to change the password
of thepi
user.
Changing the memory split
As this is fully headless, there's no point allocating precious
memory to the GPU, so the first thing we'll do is reduce this to
the minimum value (16MB).
- Execute
sudo nano /boot/config.txt
- Add the line
gpu_mem=16
to the start of the file - Press
Control+X
, theny
and pressEnter
to save the
changes and exit Nano (this guide requires editing a few files
but I won't be repeating this line)
Connecting to wireless
We'll be controlling music playback using a web browser, plus it
is much more convenient to manage a Raspberry Pi remotely using
SSH rather than having to plug monitors and keyboards in, so the
next step is to configure the wireless adapter.
- Execute
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
(you can presstab
while entering filenames and the shell
will try to autocomplete them for you) - Add the line
country=GB
, replacingGB
with the ISO
code of your own country as appropriate - Add at least one network definition similar to the template
below
network = {
ssid="<name>"
psk="<password>"
}
(Optional) Enabling ssh
The Raspberry Pi boot loader will automatically enable SSH if a
file named /boot/ssh
is present. We can use touch
to create
this file. SSH makes it easy to remote onto your Pi for
maintenance tasks, but if you always intend to plug into a
keyboard and monitor then you don't need to do this step.
- Execute
sudo touch /boot/ssh
(Optional) Changing the host name
The default host name is raspberrypi
. If you have multiple
Raspberry Pi's, you definitely want to change the host name and
I recommend you give it a custom name regardless.
- Execute
sudo nano /etc/hostname
- Delete the existing value and enter your own using letters
a-z, digits 0-9, or a dash
Reboot
The changes made to enable SSH (and if you changed your host
name) won't take effect until the Pi is rebooted.
- Execute
sudo reboot
to reboot
When the Raspberry Pi reboots, just before the login prompt is
displayed, check for a message stating My IP address is
x.x.x.x. If this message doesn't appear, your Pi didn't
connect to the wireless network successfully.
(Optional) Continue with SSH
After I have SSH enabled and the Pi connected to the network, I
disconnect the monitor and keyboard and remotely access it via
SSH. I used to use Putty for this, but one of the rare
things in Windows 10 I actually like is that it now includes a
SSH client which is much more convenient to use than Putty.
However, if you don't want to do this log into your Pi and
continue with the next section.
- Open a Windows command line (good old
cmd.exe
, PowerShell or
the new Windows Terminal) - Execute
ssh pi@<hostname>
, where<hostname>
is the name of
your Pi - When prompted, type
yes
and pressEnter
to store the
fingerprint of your device (if in future you try to connect to
<hostname>
and the fingerprint doesn't match, SSH will
prompt to continue as it is extremely likely you aren't
connecting to the machine you think you are)
Creating a directory to store music
For our music server, we need two different directories, one to
hold the actual music and another to store playlists. You can
stick these where ever you like, but for simplicities sake I
decided to put playlists as a subdirectory of music.
Later on, I'll be installing Samba so that I can access these
directories via SMB shares. The first time I set all this up on
my Model A, getting the share to work was a complete pain. I
ended up creating user accounts on the Pi that mirrored my
Windows user accounts and all sorts of other nonsense trying to
get it to work. This time around, I followed this answer
on Ask Ubuntu which suggested making "nobody" have full control
over these directories. This worked first time for me and so
I'll be presenting the same instructions here.
- Execute
sudo mkdir /srv/music
- Execute
sudo mkdir /srv/music/playlists
- Execute
sudo chown -R nobody.nogroup /srv/music
- Execute
sudo chmod -R 777 /srv/music
Updating the system
As this is a fresh install, it's likely to be out of date.
Before installing any other software I like to make sure that
everything else is up to date first.
- Execute
sudo apt update
(this looks for updates but doesn't
actually install anything) - Execute
sudo apt upgrade -y
(this installs all available
updates. The-y
flag means it will install without prompting
to continue first)

Installing Mopidy
Before we can install Mopidy, we need to add it to our package
resources as per their installation guilde.
- Execute
wget -q -O - https://apt.mopidy.com/mopidy.gpg | sudo apt-key add -
- Execute
sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/buster.list
Now we need to check for updates again and then install Mopidy
sudo apt update && sudo apt install mopidy -y
(the &&
operator executes multiple commands sequentially, but only if
the proceeding command(s) were successful)
Installing Python Pip
Mopidy is written using Python and some of its extensions aren't
installed via apt
, but instead with Python's own package
installer, Pip.
- Execute
sudo apt install python3-pip -y
Installing Mopidy-Iris
Mopidy includes a few basic plugins, but doesn't actually
include anything for front end playback. There are a number of
web based front ends I've tried and I don't like any of them.
Mopidy-Iris is probably the best of the bunch, it looks
good and provides basic playlist management. I don't like it
because it keeps trying to load Spotify (which I don't use) when
I'm working with playlists and because it appears to be more
focused towards making playlists out of individual tracks,
whereas I am a touch old school and my playlists are made out of
full albums and shuffle is definitely banned!
- Execute
sudo python3 -m pip install Mopidy-Iris
- Execute
sudo sh -c 'echo "mopidy ALL=NOPASSWD: /usr/local/ lib/python3.7/dist-packages/mopidy_iris/system.sh" >> /etc/ sudoers'
(this is for giving Mopidy permission to update
Iris)
Installing Mopidy-Local
Although Mopidy ships with a files plugin for playing local
media, Mopidy-Local is a better alternative - it caches all the
media in a database, so is able to quickly access media
information. It also provides album art to other plugins, for
example Iris above.
- Execute
sudo python3 -m pip install Mopidy-Local
Configuring Mopidy
With Mopidy and extensions installed, we need to update the
configuration to tell it where and how to process our media
files. I also disable the file plugin given we are using local
instead.
- Execute
sudo nano /etc/mopidy/mopidy.conf
Add the following content, replacing paths as appropriate.
[file]
enabled = false
[m3u]
playlists_dir = /srv/music/playlists
[http]
hostname = ::
[local]
media_dir = /srv/music
scan_timeout = 10000
scan_flush_threshold = 100
By default, Mopidy's HTTP browser is only accessible from local
host - not great for a headless device. The hostname = ::
opens it up fully to any computer on your network. Consider
viewing the warning in the Mopidy-HTTP documentation.
The scan_timeout
and scan_flush_threshold
values are a
matter of personal preference. I have just under 5000 MP3 files
and on both the Model 3A and Zero initial scans have timed out
with the default values, or completely stalled, loosing
progress. By increasing the scan_timeout
to 10000
and
decreasing scan_flush_threshold
to 100
I have avoided some
of these issues.
Enable Mopidy to run at start up
Although Mopidy installs a system service, this is isn't
enabled.
- Execute
sudo systemctl enable mopidy
to force Mopidy to
start at boot time - Execute
sudo systemctl start mopidy
to start Mopidy now
Checking the Mopidy configuration
To check the complete Mopidy configuration, enter the following
command. This will output a configuration similar to the file
you edited above, but also including all other parameters and
their values.
- Execute
sudo mopidyctl config
Installing Samba
I mentioned at the start of the guide I'd be installing Samba
and we're now at that point. This will make it easy to connect
to the music directory via a file share to copy new tunes over.
- Execute
sudo apt install samba -y
- If you are asked any questions by the install, just accept the
default value
Configuring Samba
I have found the default Samba configuration works out of the
box, but you still need to configure at least one share. As with
the directory permissions at the start of this guide, the share
configuration below comes from the same Ask Ubuntu answer.
- Execute
sudo nano /etc/samba/smb.conf
Add the following lines to the end of the file, replacing the
path as appropriate.
[Music]
comment = Music
path = /srv/music
browseable = yes
guest ok = yes
read only = no
create mask = 777
Restarting Samba
As we've changed the configuration, we need to restart the
service.
- Execute
sudo service smbd restart
Copying Music
You should now be able to access your music share over the
network. As copying files to a Raspberry Pi Zero seems to be
very slow (it consistently took four hours to copy 25GB of music
in my tests) you may wish to start with a single album until you
have tested everything, and then copy your full library.
Updating the music library
As we've installed Mopidy-Local which stores media information
in a database, we need to tell Mopidy to scan the file system to
update that database.
The documentation recommends setting up a cron job for this, but
this seems overkill unless you are constantly modifying your
media library. I prefer to run it on demand when I add music.
- Execute
sudo mopidyctl local scan
Note that this may take some time to run. If any file's time out
you can always run the command again when it completes and it
will try again with the skipped files.
Installing pHAT Beat
(Skip this section if you are using the built-in soundcard and
onboard audio connector.)
Installing this software will disable the onboard sound.
However, I found that it also had another impact for if I
undid the settings it made to/boot/config.txt
and
re-enabled onboard sound, audio no longer played properly
through it.
- Execute
curl https://get.pimoroni.com/phatbeat | bash
- When prompted to continue enter
y
- (Optional) When prompted to install examples and
documentation, entery
. If you answern
, the VU meter
won't automatically work. It was much easier to answery
than to install it from source - Once the installation has completed, answer
y
to reboot
Testing the speakers
To test your audio is working and you have the speakers the
right way around, you can use the speaker-test program.
- Execute
speaker-test -c2 -t wav
- Press
Ctrl+C
to terminate
Running Iris
You should now have a headless music server - last step is to
open Iris and play!
- Open a web browser pointing to
http://<hostname>:6680/iris/
(don't forget the port) - The first time you access Iris you'll be prompted for a few
settings, update these as appropriate and click Save - Click Albums and verify music is loaded
- Right click an Album and choose Play
(Optional) Adding a start up sound
As this is a headless device, it is hard to know when it is
ready to accept commands. For this reason I took to adding a
start up sound to play a brief tone when the Pi has finished
booting. As the Pi Zero is much slower to boot than the others,
this is definitely something I appreciate.
- Copy a short wave file to your music share
- Execute
sudo nano /etc/rc.local
Add the following line, changing the path and filename as
appropriate, towards the end of the file but before the
exit 0
line.
aplay /srv/music/sounds/tada.wav
(Optional) Reducing the master volume
I find that the default volume is pretty loud and as I usually
want the music to be background noise, I set the volume in Iris
to be a low single digit. I also tweak the master volume so that
when the machine starts it is already quieter, even though
Mopidy still thinks it is 100%
- Execute
sudo nano /etc/rc.local
Add the following line, changing the percentage according to
your own tastes. If you added a start up sound, it might be a
good idea to put this line before the call to aplay
.
amixer sset Master -- 70%
Closing Thoughts

Ever so slowly I'm becoming a fan of Linux, one of these days I
might try and use a full blown desktop (although that'll
probably be difficult due to Visual Studio and WinForms).
I'm not really a fan of the pHAT Beat. My original Mopidy setup
on the 3A didn't use a HAT, so the GPIO pins were free. I'd
added a couple of wires and a switch to safely shutdown the Pi
when pressed, and then start it up again if pressed again. The
pHAT Beat takes away that option, and even though it has a
hardware button, if you manage to get it working it only seems
to shutdown the device, not to start it up again. I haven't yet
looked into if there is another way I can add a power switch
(having a switch on a USB cable isn't fully sufficient as I
still want to safely halt the Pi, not just do the equivalent of
yanking out the power cable).
In addition, the VU meter doesn't scale to the current volume,
meaning that as I have everything turned quite low, only the
first pair of LED's light up - and barely at that. On the 3A, I
changed the source code and recompiled based on some advice on
the Pimoroni forums but I haven't done that on the Zero yet. It
is a shame it doesn't just scale nicely for you.
I also wish the speaker connectors on the HAT were screw based.
Instead, you just push the wires until they lock. I don't find
that to a be a particularly strong mechanism though.
However, there is no denying that quality of audio wise, using
this HAT is far better than my previous set up. Whether that's
just to the speakers or the hardware on the expansion board is
another question but it is definitely better. And at the end of
the day, a VU meter is just a nicety, it's not like I sit and
stare at it!
While I don't entirely like playlist management on Iris, I
really only need to set play lists up once. What I don't like is
having to reload from scratch each reboot and set the repeat
flag. Previously I played music on my desktop computer using
foobar2000 and what I really liked about that was it would
continue where it left off. I'm sure WinAmp used to do that too
back in the day and one of the reasons I didn't like Windows
Media Player either. I think the only way to get that behaviour
back is to write something myself to control Mopidy directly via
the Music Player Daemon protocol.
But first I definitely need to figure out a new power switch!
Updates
- 12Apr2020 - Added some images of the device
- 10Apr2020 - First published
This post was first published Tuesday 16th of June 2020 and was last modified Tuesday 16th of June 2020 at 06:39:04.
Got something to say?
Leave a comment
Replied on your own website? Send a Webmention!