Setting up your own Mastodon, with Digital Ocean and Docker
Mastodon is the decentralized social network that all the tech blogs went nuts over last week.
Decentralized (aka federated) being the key word. There’s nothing stopping you from starting up your own Mastodon instance of your very own and inviting just your friends to it, to have your own moderation policies and community. This guide will help you get set up on Digital Ocean, with the Docker containerized version of a Mastodon system. You will also be using Mailgun for email
Updated 2018–01–18
Starting your droplet
Sign up for or log in to Digital Ocean and select “Create Droplet”. Instead of using a “distribution”, select “One-click apps” and Select Docker on 16.04:

I have tried this with both 512MB and 1GB of RAM, but neither are enough to compile the assets for the Mastodon Rails server. So let’s select 2GB of RAM:

Finally, so that you get ranked high on https://instances.mastodon.xyz/ enable IPv6 networking:

Now you can either associate an SSH private key with your droplet (recommended) or use the default method of getting a root password emailed to you. Start your droplet.
Setting up DNS
Once your droplet is created, you will need to create an A record (IPv4) and an AAA record (IPv6) at your registrar. Assuming you’re using Namecheap (and you should), first remove the parking page:

Then remove the redirect domain:

Now add the following records, with your IP addresses (not mine):

Your Mastodon server will need to send outgoing email, especially when users register and need to confirm their addresses. For this we will use Mailgun. We will need to configure Mailgun in our DNS entries so that the domain can be confirmed.
Once you sign up for Mailgun, in domains, click “Add new domain”:


Now follow the instructions on the Mailgun page to add more DNS records to your domain:


Logging into your droplet
How to use SSH is beyond the scope of this tutorial, but Digial Ocean has some docs on the matter.
Assuming you have a shell, we will next want to update the server software:
# apt-get update# apt-get upgrade# reboot now
Then reconnect to your server. Next go to the Mastodon Github page and get the clone URL for the repository:
# git clone https://github.com/tootsuite/mastodon.git# cd mastodon
Now we’re basically going to follow the instructions on the github page, but they’re a little wonky.
Editing your .env.production file
First, copy .env.production.sample to .env.production
# cp .env.production.sample .env.production# nano .env.production
Now edit the file. The LOCAL_DOMAIN should be the full domain that your users will go to. In our case it is “towel.science”. But it could be “some.wacky.thing.whoknowswhat.xyz”. This is the domain that you configured A records for above.
Set LOCAL_HTTPS to true. We will be getting a cert from Let’s Encrypt and installing it soon.
For the SMTP_* lines, you’ll need your credentials from Mailgun. Simply click on your domain in the Mailgun interface and you’ll see the settings under Domain information:

SMTP_LOGIN is “Default SMTP Login” and SMTP_PASSWORD is “Default Password”. You should also change the SMTP_FROM_ADDRESS from notifications@example.com to notifications@towel.science (actually your domain).
We’re also going to need to fill out the section on Application secrets, but we can’t do that until we have built the containers once.
# docker-compose build
Now that we have the containers built, we can reach into the web container and generate our secrets using the rake secret command:
# docker-compose run --rm web rake secret
Creating mastodon_redis_1
Creating mastodon_db_1
92d4cfcd67a99a6adeb670ec4ac866611596c9792db310553f2a20b21516f27a2c95bcaf78944a6817cb05adcf0dcc47f9a21a756c30e27746f37abf4c928205
That last string is your secret. Open up .env.production again and paste it in for one of the three secrets you need (PAPERCLIP_SECRET, SECRET_KEY_BASE, OTP_SECRET). Repeat the rake secret command two more times to get the other two secrets.
Your environment file should be all set now and you should be ready to move on to the next step.
Protecting your web servers
By default, the docker containers expose their ports (3000 and 4000) to the outside world. There is a simple patch to prevent this: https://github.com/tootsuite/mastodon/pull/999/files
Basically, open up docker-compose.yml and change:
"3000:3000" to "127.0.0.1:3000:3000"
and
"4000:4000" to "127.0.0.1:4000:4000"
Opening ports
Speaking of opening ports to the outside world, your droplet comes with ufw enabled by default. In order to let the outside world communicate on port 80 (HTTP) and port 443 (HTTPS), you will have to open them on ufw. This is quite easy:
# ufw allow http
# ufw allow https
Getting a Let’s Encrypt certificate
The letsencrypt binary is already installed on your droplet, so simply do the following to get your certificate:
# letsencrypt certonly -d towel.science
Replacing towel.science with your full domain name, of course.
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/towel.science/fullchain.pem.
The official Mastodon docs have a guide to auto-renewing your certificate with cron.
Starting Mastodon and migrating
Run this command to start the containers:
# docker-compose up -d
Now run the migrations, as detailed on the github readme:
# docker-compose run --rm web rails db:migrate
# docker-compose run --rm web rails assets:precompile
After this is done, it seems you’ll need to restart the docker containers:
# docker-compose stop
# docker-compose up -d
Installing nginx
Installing nginx is easy with apt-get:
# apt-get install nginx
Next, remove the default site from sites-enabled:
# rm /etc/nginx/sites-enabled/default
Now create a config file for your site and copy in the config here, which I have saved to it’s own gist here:
# wget https://gist.githubusercontent.com/audiodude/926abe2997f210ad55e6a674109008a2/raw/9037a39423253f439117ff1822776441e22ed506/example.com.conf -O /etc/nginx/sites-available/towel.science
Then edit the file and all you should have to do is change example.com to towel.science (but not that, your actual domain). Then link your site to sites-enabled.
# nano /etc/nginx/sites-available/towel.science
# ln -s /etc/nginx/sites-available/towel.science /etc/nginx/sites-enabled/
# service nginx restart
Hello Mastodon
Fire up your web browser to https://your.domain.example.com (https://towel.science is what we’ve been using in this example) and you should see a generic Mastodon welcome screen! Congratulations!
At this point you can sign up like a normal user for your own account.
If you don’t want anyone else to sign up and you’d like to use this Mastodon instance as your own personal playground, you can edit the .env.production file and uncomment the SINGLE_USER_MODE=true line. Then simply restart the docker containers:
# docker-compose stop
# docker-compose up -d
Either way, you most likely would like to become an admin on your own server that you just set up. Instructions for that are here. For docker, use the following command:
# docker-compose run --rm web rails mastodon:make_admin USERNAME=yourusername
Cron jobs
There are some cleanup jobs that should run once a day. Simply do:
# crontab -e
And drop the following in there:
0 10 * * * /usr/local/bin/docker-compose run --rm web rake mastodon:media:remove_remote
0 20 * * * /usr/local/bin/docker-compose run --rm web rake mastodon:push:refresh
0 30 * * * /usr/local/bin/docker-compose run --rm web rake mastodon:feeds:clear
That’s it!!
You’ve got a Mastodon instance running, congrats again!
If you liked this guide or for any feedback, feel free to toot at @audiodude@tiny.tilde.website
Final Note
This guide doesn’t cover backups or upgrading, which are both important topics to consider if you’re going to run anything more than a toy server. The official Mastodon docs on Github have some information about upgrading, but it doesn’t seem like anyone has written anything specific yet about backups. Generally, it’s going to look like rsync’ing a few specific directories and the DB to a remote service. These topics are left as an exercise to the reader.