For full disclosure, I should say that I run three social networks now and they all run on the Mastodon platform, I’ve installed all three. I am biased, I’m not running Diaspora or anything else and I’m not running a forum on an established commercial website. And frankly on Mastodon all I do is run servers; the network seems to take care of itself after installing Mastodon.

What really started out as a fun Docker project turned into a full-on passion and a new way to interact with people that was not based on Twitter, Facebook and the rest of the commercial based social network offerings available. I’ve discovered new ideas, trends and people I wouldn’t have discovered in the noise of Twitter and I refuse to submit myself to the tracking that comes with Facebook (across the entire web).

Fediverse proposed Logo from Wikipedia under the GNU FPL & CC SA

To Start

Let’s start with what Mastodon is – Mastodon is an open source software project that aims to be a replacement for Twitter. The interface uses the style of a popular Twitter client and has real time streaming updates across servers so that users can interact with each other in a familiar fashion. You can mention, reply, boost, favorite and directly message (away from the eyes of the world). All of this bundled into a free and open source software package that uses a common protocol to federate with other servers creating what we’d call the “Fediverse”.

Mastodon hits the basics and more. What honestly intrigues me most, and has pulled me into it, is the real-time nature of the tool. How you use it, what privacy settings you use and what the server is setup to do is what makes the experience more or less like Facebook or Twitter (or entirely different). I have one network that’s all private and operates like a Facebook – and another that is totally open and each user’s profiles are public like Twitter.

But neither Twitter or Facebook offer the same real time view. Right now as I write this there are things I’m missing. It’s missed, there isn’t much hope of catching up – I follow too many people. While it feels ephemeral it isn’t actually. That amazing post from a few hours ago, it’ll get boosted again and I’ll see it next time I check. And when I check, I can watch it stream by me.

And this is where it’s the most fun. I have a long day, I get up early and I go to bed late. I can watch the stream in the early morning and see a whole set of (European technotrash) people posting and boosting statuses and throughout the day watch it turn as the sun moves it’s light across the Earth (to Japanese technotrash). It slows down, but the Fediverse never sleeps. New shifts take over, new people sign in, and the flow of ideas keeps going.

Social networks are what you make of it

And Mastodon is almost for everyone. In the first 24 hours of setting up my server I was following everyone from Alt-Right Nazis to Tri-Gender Iron Front members. And oddly, I was interacting with both almost immediately too (beyond a follow or a follow request). I was in the wild west trying to find friends and it was easy to find them in the Fediverse (but easy to be blocked for making those same friends as well).

One of the things that makes the Fediverse stand strong, though also fragments it, is the idea that you can decide to block those people you do not like. I’m sure my aforementioned and newfound Nazi and Iron Front friends have already blocked each other. You too get to decide if you want to wholesale block an instance based on their political views (or even lack thereof, speaking of nihilists) or their views on gender, race, or you get to federate with them and follow their posts as too if you’d like.

Real people

Surely this isn’t an article to describe how Mastodon works – there are others that do that well, and even videos that describe how it all fits together. What I find most interesting isn’t how it works but instead that it does work, and it works well. Beyond the live updates, the constant flow of information in the timeline I have found that people do actually like interacting on the platform.

I follow a lot of people, as I said, and I reach out to a lot of them. Their funny jokes I try to add onto and make a bit funnier, their questions I reply to and their polls I make my opinions known on. And I have to say for a group of total strangers, people just posting and following and interacting with blind faith that people are interested in the same things, everyone seems to mesh well together. At least, they interact with each other, they take the time and they seemingly respect each other at some level as human beings. There is a fair level of blocking, to the point of #Fediblock becoming a trending tag at one point recently, but overall people are genial.

For this reason, and the freedom inherent in the software – it’s freely available and open source code – we have to say it’s not lame. We are suggesting you leave Twitter and Facebook behind and join and support the Fediverse.

How Do I Join?

Mastodon is actually just a piece of software and not the entire story, but super easy to join – there are other options as well, including Soapbox FE, Pleroma, and others. And it turns out you can do it your own way as well regarding your first step. You do not have to run any software of your own you can join an existing server, and of which, there are many. Or you can roll your own server using the software mentioned above.

But I’m curious on how to run Mastodon!

Well, if you wanted to play in Docker as I did and setup a Mastodon server I can help guide you down the path to getting a server up and running in short order. I won’t be writing a guide to installing Docker, because it is a base package to any operating system and there are guides for all flavors of Linux out there already (as well as Mac OSX and Windows 10 PRO).

I can relay the steps of installing Docker that I used prior, though I’m using Debian 10 so it’s specific for me.

Installing Docker in Debian 10

First we need to install the basics on Debian to prepare for Docker. This includes the basic security certificates if you don’t have them, CURL and other base software;

sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

Then you’ll need to get the Docker PGP key to authenticate the packages come from Docker and not from someone else – and add it to APT’s key-ring in one line;

curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -

Then you can (optionally, though you should) verify the APT key;

sudo apt-key fingerprint 0EBFCD88

You should see the below (or similar – see their Debian guide to be sure);

pub   4096R/0EBFCD88 2017-02-22
      Key fingerprint = 9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid                  Docker Release (CE deb) <docker@docker.com>
sub   4096R/F273FCD8 2017-02-22

Update your local cache of APT repositories and packages, it’s time!

sudo apt-get update

And install Docker!

sudo apt-get install docker-ce docker-ce-cli containerd.io

Now you have Docker (and Docker Compose) installed if you didn’t have it installed already and can start downloading and installing Mastodon.

Install Mastodon

Mastodon can be built from source and run or it can be run from existing Docker containers. Because you can easily mix up the master branch with the currently released version that’s stable I suggest doing a mixture of the two things – fetching the source from Github and using it as your basis for running the pre-built Mastodon Docker containers.

Install Git for Github

After you’ve determined where on your Linux system you’re going to store Mastodon you’ll need to copy the current stable branch from Github and copy the files down. If you don’t have git installed, let’s install it now!

sudo apt-get install git

Grab the Mastodon v3.2.1 source code from Github

You’ll want to be careful here and not grab the master branch, and instead target for the lastest release of Mastodon, v3.2.1 – and you can do this by grabbing a particular Github branch which will get you the docker-compose.yml file and others you’ll need to get going.

We’re going to achieve this by cloning only a certain branch from Github using git;

git clone --branch v3.2.1 https://github.com/tootsuite/mastodon.git mastodondirectory /usr/local/mastodon

Notice we are calling to the v.3.2.1 branch specifically and we are stashing the files in the ‘/usr/local/mastodon‘ directory (which you can choose as mentioned above).

Prep Docker

Now we mentioned that you can build Mastodon from source, and the files we pulled from Github do this by default. If you notice the docker-compose.yml file right now defaults to build everything you just pulled – you’ll see it in the line below where the Mastodon web services are called out (web block);

  web:
    build: .
    image: tootsuite/mastodon

If you don’t want to do this and use the pre-built containers, which we lamely suggest, we need to change all three places we see “build” to comment out this line.

Web Docker Service:

  web:
    #build: .
    image: tootsuite/mastodon

Streaming Docker Service:

  streaming:
    #build: .
    image: tootsuite/mastodon

SidekIQ Docker Service:

  sidekiq:
    build: .
    image: tootsuite/mastodon

And while we’re at it, let’s fix all three places to ensure we pull v3.2.1 of Mastodon from Docker Hub;

  web:
    #build: .
    image: tootsuite/mastodon:v3.2.1

## scroll down to streaming
  streaming:
    #build: .
    image: tootsuite/mastodon:v3.2.1

## scroll down to sidekiq ##
  sidekiq:
    build: .
    image: tootsuite/mastodon:v3.2.1

Now we’re almost setup to start running the Mastodon Docker Compose files and setting up the server. We’ll need to copy an example Production file over for us to use from the git repository;

cp .env.production.sample .env.production

Let’s not do anything with this file other than set our postgres or our “db” user up. We’ll need to do that before we can run the setup and get a successful connection test. What we’ll want to do is edit this section:

# PostgreSQL
# ----------
DB_HOST=/var/run/postgresql
DB_USER=mastodon
DB_NAME=mastodon_production
DB_PASS=
DB_PORT=5432

And setup our own Postgresql user details. While this image/container won’t be exposed to the outside world let’s make the password long and random (we recommend generating a non-special character key from LastPass).

# PostgreSQL
# ----------
DB_HOST=postgresql
DB_USER=databaseuser687
DB_NAME=mastodon_production
DB_PASS=Z3vGzE5WzOo5Vhj83uvc6op7Sj
DB_PORT=5432

Keep these settings handy or the text file open if you can, you’ll need them for the next steps when we generate the rest of the values in this file.

Setting Up Mastodon For the First Time

sudo docker-compose run --rm web bundle exec rake mastodon:setup

The above will launch the ruby setup for Mastodon using the Mastodon CLI and we’ll generate the values for the setup in .env.production. Doing this will also download the needed container images from Docker Hub for the first time.

Starting mastodondirectory_db_1    ... done
Starting mastodondirectory_redis_1 ... done
Pulling web (tootsuite/mastodon:v3.2.1)...
v3.2.1: Pulling from tootsuite/mastodon
d72e567cc804: Pull complete
0f3630e5ff08: Pull complete
b6a83d81d1f4: Pull complete
1aa4cf3a1701: Pull complete
9a84b78a19cb: Pull complete
b790fb18ff52: Pull complete
9a89c1b2e6ed: Pull complete
420601ca9a5f: Pull complete
fb8dcb3732a4: Pull complete
2bc41d47dd50: Pull complete
60263769a4f2: Pull complete
9bba9cfb5051: Pull complete
58c1bc840dea: Pull complete
Digest: sha256:41cd5fb48d8b15ec806f08ab06fec98df33ec9b83a1f879e0fb30da9994018dc
Status: Downloaded newer image for tootsuite/mastodon:v3.2.1

Next you’ll be asked a series of question which will pertain to your Docker setup. For this install we’ve not changed any default passwords (bad idea) but we’re running with enough to get us going and our Postgresql database will not face the outside world through Docker.

To get started you’ll have to answer which domain name you intend to use – this isn’t to be changed later so we have to assume you’ve thought this through. Example.com always works;

Your instance is identified by its domain name. Changing it afterward will break things.
Domain name: example.com

Next you’ll have to decide if you’ll want others to be able to register on your instance. This is more fun but if you aren’t intending to keep the server running that’s unfair as those users will have built up their social presence.

Single user mode disables registrations and redirects the landing page to your public profile.
Do you want to enable single user mode? (y/N)

And now the key question – are we using Docker? And the default aligns to that in which we are indeed doing, we are using Docker to run Mastodon;

Are you using Docker to run Mastodon? (Y/n)

Next you’ll be asked a series of questions that pertain to the docker-compose.yml and .env.production files you’ve edited. They will be which server names would be used and which is the username and password for the Postgres database. In this remember the server name or location is the name of the Docker service (db for postgres, redis for redis);

PostgreSQL host: db
PostgreSQL port: 5432
Name of PostgreSQL database: mastodon_production
Name of PostgreSQL user: databaseuser687
Password of PostgreSQL user: (hidden)

Then for Redis (no password):

Redis host: redis
Redis port: 6379
Redis password:
Redis configuration works! 🎆

Now you have to answer or decide if you want to use an S3 bucket to store your images. This is a bit of an advanced configuration so we’ll be skipping it here and answering no;

Do you want to store uploaded files on the cloud? No

Then we configure email. We have two main choices – we can send email from localhost using Sendmail or we can use a service like Mailgun which allows for SMTP services including a free tier that you would likely remain under their threshold to start.

To setup Sendmail/localhost email services;

Do you want to send e-mails from localhost? yes
E-mail address to send e-mails "from": no-reply@domain.com
Send a test e-mail with this configuration right now? Yes
Send test e-mail to: myemail@gmail.com

Or we can try Mailgun;

Do you want to send e-mails from localhost? No
SMTP server: smtp.mailgun.org
SMTP port: 587
SMTP username: postmaster@mail.domain.com
SMTP password: (hidden)
SMTP authentication: plain
SMTP OpenSSL verify mode: peer
E-mail address to send e-mails "from": no-reply@domain.com
Send a test e-mail with this configuration right now? Yes
Send test e-mail to: test@myemail.com

Ultimately this and other settings from the setup will be written back to .env.production outside of the container (if you correctly choose yes at this step in the setup);

This configuration will be written to .env.production
Save configuration? (Y/n)

If you want to be safe collect the output and be sure it makes its way into .env.production that you created and edited earlier.

# Generated with mastodon:setup on 2020-11-23 20:05:57 UTC

LOCAL_DOMAIN=pivpn.xyz
SINGLE_USER_MODE=false
SECRET_KEY_BASE=6b15f0WzOo5Vh65525db6970dffd32ff786adafa89
OTP_SECRET=e4fd904867WzOo57aea95VWzOo5Vh412f867aea95792f
VAPID_PRIVATE_KEY=BjI0tZWzO7aea95o5VhziP5W7aea957M-u9gU=
VAPID_PUBLIC_KEY=BBGz1wIq2j_7aea956I3cXIbs=
DB_HOST=db
DB_PORT=5432
DB_NAME=mastodon_production
DB_USER=databaseuser687
DB_PASS=Z3vGzE5WzOo5Vhj83uvWzOo5Vhc6op7Sj
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=
SMTP_SERVER=smtp.mailgun.org
SMTP_PORT=587
SMTP_AUTH_METHOD=plain
SMTP_OPENSSL_VERIFY_MODE=peer
SMTP_FROM_ADDRESS=no-reply@domain.com
SMTP_LOGIN=postmaster@mail.domain.com
SMTP_PASSWORD=asdfasdf9iupasdiopsdfaiopasfdpifasd

Then you’ll be asked to create the database for the first time – this is dangerous if you’re already live so be careful!

Now that configuration is saved, the database schema must be loaded.
If the database already exists, this will erase its contents.
Prepare the database now? (Y/n)

Then you’ll want Mastodon to precompile the CSS, Javascript and other assets so your server runs at optimal speeds. Go ahead and answer yes on the final step shown below;

The final step is compiling CSS/JS assets.
This may take a while and consume a lot of RAM.
Compile the assets now? (Y/n)

When you’re complete you’ll get a nice Mastodon logo in your terminal!

All done! You can now power on the Mastodon server 🐘

Running Mastodon!

We are getting towards the end of our guide. We’ve linked to some places to find an instance of your own as well as shown the basic setup of how to get Mastodon running. Now we have an instance but it’s not up and running yet.

Before we start Mastodon for the first time we have a permissions issue with the public folder. The public folder is where Mastodon stores it’s images in the federation as well as your own posts. You’ll need to run a chown job on this folder to make sure the permissions match the container’s permissions, but you only have to do this one time;’

sudo chown -R 991:991 public

Now you’re ready to fire up the server for the first time. This is easy, you can run Mastodon and watch the logs like this;

sudo docker-compose up

Though I imagine you’ll really not care about the logs and want it running unobtrusively in the background;

sudo docker-compose up -d

You can still watch the logs with docker by combining the ability to run in the background and docker’s built in ability to watch logs (tail, follow);

sudo docker-compose up -d && docker-compose logs -f

Finishing Up

At this point you basically have Mastodon up and running, you just need to expose it to yourself and the world. For this I suggest running a reverse proxy and using Nginx to do this is the best way (though I have run Mastodon behind Apache2 without issues).

The bonus of this is that the Mastodon development team has given us Nginx configuration examples to work from that already optimized for Mastodon (here). You’ll find the example too in the “dist” folder in the files you pulled from Github. It only takes some small changes to get this working with Nginx.

Here are the steps I took to making this work with Nginx running on the host machine (not as a container);

  1. Copied nginx.conf to my sites-available folder.
  2. Edited the file to update;
    1. Server Name Directive (two locations)
    2. Root folder directive (two locations)

That was basically it. After copying down the Mastodon Github distribution I got a huge head start. Be sure to clone the proper release tag from Github and avoid the master branch – other guides tend to miss this.

Did this guide work for you? Are you interested in Mastodon – do you need your own instance? Let us know in the comment below!