Pleroma and Mastodon on the Raspberry Pi 3
Pleroma and Mastodon on the Raspberry Pi 3
This is a little guide a wrote for myself when setting up Pleroma and Mastodon on my Raspberry Pi 3.
The Raspberry Pi is a very popular Arm-based system that runs Linux. It has a quad-core Arm Cortex-A53 CPU and 1GB or memory.

Summary
- Update: I have stopped running Mastodon on my Pi as it needs too much memory, I only run Pleroma now. So this tutorial is only kept up-to-date for Pleroma.
- Setting up Pleroma is straightforward, but the info on the repo page is rather terse, I followed this guide. For Pleroma you need Elixir, and the instructions for installing it on the Pi are here.
- There is also this guide for installing on Debian/Ubuntu.
- Setting up Mastodon following the documentation is also straightforward. I used the instructions below to install Rails and PostgreSQL on the Pi and the official Mastodon production guide to install Mastodon.
- One point to note: you need extra swap for Mastodon, I increased it to 256MB.
- Usually you would set up and test Mastodon or Pleroma on a local port as a first step.
- But Mastodon and Pleroma only federate if you have a proper domain for your instance, and most ISPs don't allow that for ordinary users. So you need to arrange some form of dynamic DNS. I used FreeMyIP, see below.
- Typically your home router will have a firewall, so you'll have to make sure people can talk to it from the outside. If you have an Apple Airport this is very easy using the Airport Utility.
- You need to sort out encryption certificates for your domain, I used LetsEncrypt, see below.
- I use a different subdomain for Mastodon and Pleroma, each with their own certificates. Because I have only one external IP address I can't run both at the same time.
Getting started on the Raspberry Pi 3
The easiest way to get started is to connect a display, keyboard and mouse. The Pi will boot straight in to a graphical desktop. It will also automatically find your WiFi. You can then do some basic admin like enabling VNC, setting up wired Ethernet access and creating extra accounts.
Make sure that the Raspbian on your Pi is up-to-date:
$ sudo apt-get update
$ sudo apt-get dist-upgradeAt the time of writing (2019-01-05), after doing this, the distro is Stretch:
$ cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 9 (stretch)"The Linux kernel is now:
Linux 4.14.79-v7+ #1159 SMP Sun Nov 4 17:50:20 GMT 2018 armv7lThis is advertised on log in or you can run uname -a to get this information.
Increasing swap space
Mastodon requires a lot of memory, so I had to increase the swap space to 256MB. This is very easy: edit /etc/dphys-swapfile to set CONF_SWAPSIZE=256, then restart the service:
/etc/init.d/dphys-swapfile restartAccounts
Apart from the default pi account, which I only use for VNC access, I created three other accounts:
-
pleroma: to run Pleroma, no SSH access allowed -
mastodon: to run Mastodon, no SSH access allowed -
wim: for SSH access, I use key-based access
Edit /etc/ssh/sshd_config:
AllowUsers wim
DenyUsers pi pleroma mastodon
$ sudo systemctl restart sshI allowed all three sudo access for convenience.
IP Setup for wired access
If it is for some reason not possible to create a fixed IP for WiFi access to your Pi you can use wired access. I set up the eth0 interface with a fixed IP of 192.168.x.y.
dhcpcd.conf:static ip_address=192.168.x.y/24
hosts:192.168.x.y rpi
hosts:192.168.x.y rpi.limited.systemsInstalling Pleroma
Installing Elixir
For Pleroma you need Elixir, and the instructions for installing it on the Pi are here
The Elixir version is the latest version offered by Erlang Solutions:
$ elixir -v
Erlang/OTP 20 [erts-9.1.5] [source] [smp:4:4] [ds:4:4:10] [async-threads:10] [kernel-poll:false]
Elixir 1.6.1 (compiled with OTP 19)Building Pleroma
The most recent Pleroma requires Elixir version 1.7 or newer. This is actually because of the ex_doc dependency. If your Elixir version is older, you need to make the following changes in mix.exs:
Change the Elixir version to match the version on the Pi:
#elixir: "~> 1.7",
elixir: "~> 1.6",
Changed the ex_doc version as per their documentation to match this:
#{:ex_doc, "~> 0.19", only: :dev, runtime: false},
{:ex_doc, "~> 0.18.0", only: :dev, runtime: false},
Setting up Pleroma
Setting up Pleroma is also straightforward, but the info on the repo page is rather terse, I followed this guide.
-
The configuration for Pleroma is, for development mode, in
config/dev.exswhich includesconfig/dev.secret.exsor, for production mode,config/prod.exswhich includesconfig/prod.secret.exs. -
To generate the secret key
secret_key_baseyou can run the commandpleroma@rpi:~/pleroma $ mix phx.gen.secretThis will print a key which you can copy and paste into
secret_key_base: "..." -
By default, Pleroma runs in development mode. To use production mode,
pleroma@rpi:~/pleroma MIX_ENV=prod mix phx.server
Installing Mastodon
Setting up Mastodon following the documentation is straightforward. The Ruby version on the Pi is 2.3.3 and Mastodon requires 2.4 (and will soon require 2.5). To install Ruby 2.4, Rails and Postgresql follow these steps:
-
Update the package database
$ sudo apt-get upgrade -
Install Node
$ sudo apt-get install nodejs -
Instal rbenv and Ruby 2.4
$ sudo apt-get install rbenv ruby-build $ echo 'eval "$(rbenv init -)"' >> ~/.bashrc -
Build ruby
$ rbenv install --list $ MAKE_OPTS="-j 4" rbenv install 2.4.0 $ rbenv global 2.4.0 -
Check that it works
$ ruby --version => ruby 2.4.0p0 (2016-12-24 revision57164) [armv7l-linux-eabihf] $ which ruby => /home/pi/.rbenv/shims/ruby -
Install Rails
$ gem install bundler $ gem install rails -
Install Postgresql
$ sudo apt install postgresql libpq-dev postgresql-client postgresql-client-common -y
Then I used the official Mastodon production guide to install Mastodon.
The problem I ran into is that you can't really try out Mastodon unless you have a domain with an SSL certificate for your instance. As long as that is not the case, you can use it on its local port (3000 by default). So I point my browser at 10.0.x.y:3000 for testing.
Also, the guide says to edit the .env.production file. A few points there:
- My PostgreSQL database settings are a bit different from the guide:
DB_HOST=localhost DB_USER=mastodon DB_NAME=mastodon DB_PASS=mastodon - The comments in the
.env.productionfile tell you how to generate a number of secret keys, you must generate them, don't leave them blank! - I have a single-user instance:
SINGLE_USER_MODE=true
Mastodon administration
I ran into some trouble with Mastodon and found the following to be very helpful:
Adding a user on command line
mastodon@rpi:~ $ RAILS_ENV=production bundle exec rails mastodon:add_userMastodon user ..., pwd ...
Confirming an email (because I never bothered to set up email support)
mastodon@rpi:~ $ USER_EMAIL='...@...' RAILS_ENV=production bundle exec rails mastodon:confirm_emailReactivating a previously deleted user
Start Rails console:
mastodon@rpi:~ $ RAILS_ENV=production bundle exec rails cIn rails console:
account = Account.find_by(username: '...', domain: nil)
account.suspended = false
user = User.create!(email: '...@...', password: '...', account: account)
user.confirm
account.save!
user.save!Making your instance visible from the internet
To make the Pi visible from the internet, you need to open a hole in your firewall, usually this means on your WiFi router.
Change firewall settings
- I set the Pi WiFi internal IP to
10.0.x.yfixed using the MAC address of thewlan0interface. The Pi will use this automatically. - I opened port 443 (SSL) for the Pi
Update Pi hosts file (optional)
- I added the fixed IP to
/etc/hosts, this is actually not needed for Mastodon or Pleroma.
root@rpi:/etc# grep -r 10.0.x.y
hosts:10.0.x.y rpi
hosts:10.0.x.y rpi.limited.systemsTo get external IP and Dynamic DNS:
I use freemyip.com, I registered two subdomains, one for Mastodon and one for Pleroma. To bind the domain to the IP address of the Pi, I use a script with the following commands:
#!/usr/bin/env bash
# Find your external IP address
MY_IP=`dig +short myip.opendns.com @resolver1.opendns.com`
# Bind it to your domain
curl "https://freemyip.com/update?token=...&domain=...&myip=$MY_IP"I created a service on the Pi to renew dynamic DNS, see the repo.
So now you can access your Mastodon and Pleroma instances via these domains. But this is not good enough because you can't get an SSL certificate for this domain, you need to use a domain that you own for that purpose.
Setting up a domain
I used Vidahost as provider for my domain, but this should be similar for other providers. I bought the domain limited.systems.
I added the domain rpi.limited.systems as follows:
| Name | Type | Content |
|---|---|---|
| limited.systems | NS | ns1.vhdns.net |
| limited.systems | NS | ns2.vhdns.net |
| limited.systems | A | 192.30.252.153 |
| www.limited.systems | CNAME | 192.30.252.153 |
| rpi.limited.systems | CNAME | ... |
| pynq.limited.systems | CNAME | ... |
The A and www. CNAME records point to GitHub.com, this was something I needed while I was setting up the domains.
Getting an SSL certificate
Like almost everybody else nowadays, I use LetsEncrypt.
Encryption via LetsEncrypt
I installed the letsencrypt tool, shut down nginx and generated a certificate for my domains.
$ sudo apt-get install letsencrypt
$ service nginx stop
$ letsencrypt certonly --standalone -d rpi.limited.systems
$ letsencrypt certonly --standalone -d pynq.limited.systems- NOTE: for Mastodon, please see the Production Guide for full details.
Running Mastodon or Pleroma
With the above setup, there is one external IP address shared by the two instances, Mastodon on rpi.limited.systems and Pleroma on pynq.limited.systems. So you have to select one of them. This is easily done by having a separate nginx config file for each of them.
- My Mastodon nginx config is almost identical to the one in the guide, except for the
server_nameand the port used for the streaming API, which I changed to4042. I also changed this port number in/etc/systemd/system/mastodon-streaming.service. - My Pleroma nginx config is almost identical to the one in the guide, except for the
server_nameand thelocation /entry:location / { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass http://127.0.0.1:4000; } - Both of these go in
/etc/nginx/sites-enabled/.
Final Note
My Raspberry Pi is switched off most of the time so the instance urls will most likely not work.