Okay, so everyone knows about the major social media platforms (Twitter, Facebook, Instagram, etc.). Apparently, there are a few more out there that exist as part of the “fediverse” with the goal of being more open and transparent with their users. As an example of why that may be important to you, think about your Facebook feed. How many articles, junk posts and advertisements do you see versus actual friend posts? We have no visibility to the code behind the algorithm, and frankly many of the large platforms are simply there to mine and sell your data. So, what if you could host your own social media? In my case, I ran across Mastodon. This article will show you how to host a Mastodon server.

A little more context

What is the Fediverse, exactly?

Fediverse image

First proposed in 2008, the fediverse is a collection of “federated”, or interconnected, web servers used for web publishing and file hosting. Each server is independently hosted but can communicate with other servers, and users on one server can interact with users on another server.

Different types of networks, explained

Think of it this way; you have an account on Twitter, an account for Facebook, and an account for Snapchat. These accounts cannot communicate with each other. You cannot log in to Twitter (natively) with your Facebook account, and your Twitter account can’t log in to your Snapchat account. You cannot publish to Twitter and see your post show up on Facebook. The algorithms are proprietary, and no communication happens between servers. This is a centralized network.

Alternatively, in a distributed network like email, for example, you again have separate accounts for each provider (Google, Outlook, etc.). However, because of standardized protocols, Google can talk to Outlook, Outlook can talk to Yahoo! and everybody can communicate between platforms. The platforms are still proprietary but can talk to each other. This is a distributed network.

In the federated network servers are hosted by individuals. Again, because of adherence to a published standard, each server can talk with other federated servers. Likewise, an individual who joins one server joins all other servers. In other words, if you create an account on my Mastodon instance, you have an account for all Mastodon servers. However, it is still up to the individual administrators of other servers to grant you access to their servers if you request access. The code and algorithms are open source, so everyone can see what goes on under the hood. Examples include WordPress (the same program used for this site), Mastodon, Prismo, Hubzilla, and many others.

Why should I care?

Data privacy. Period. Source code for all federated servers is open source and viewable to anyone who installs it. The developers are privacy conscious, and even if they were not other users would be and would call them out on it. You’re not going to go look at that nice Dewalt table saw on Bing today and see nothing but tool ads on your Mastodon feed later. You will on Facebook, though. Your data is valuable and is a tradeable commodity as far as the large data corporations are concerned, and manufacturers and retailers pay to have access to your data to boost sales.



Mastodon is a fairly hefty piece of software, so you’ll need something with a little muscle to run it. At least 4GB of RAM will be needed on a machine that is always on. I’ve got this on an Raspberry Pi 4, so this guide will focus on Linux installs.

Raspberry Pi 4 with at least 4GB RAM
MicroSD card (or a USB SSD, optional, but preferred over a MicroSD)

Software and Other Items

A 64-bit OS (Raspbian 64-bit OS is just fine).
A dedicated domain name pointed to your public IP address (IP addresses will not work with Mastodon)
A transactional email provider (Sendgrid, Mailgun, etc.) to send Mastodon confirmation links and notifications.
Optional: a cloud storage provider (Amazon S3, Google Cloud, Wasabi, etc.) to backup and store database files.

OS Installs

Note that you cannot use a 32-bit OS. You must use a 64-bit OS for this install to work.


The guide I followed for the most part is located here at PiMyLifeUp. It’ll get you 99% of the way there, but I ran across a few snags that required a little research and additional work. I used the official installation documentation to fill in any gaps.

User Switching

For the most part you will be executing commands with two users: the root user and the mastodon user created during setup. The guide will tell you when to switch.

Raspberry Pi Setup

OS Setup

If not already installed, or you need to upgrade to a 64-bit OS, head over to this post to get started with the Raspberry Pi OS. Once installed come back here.

Secure your system

Because you’re going to run a public service, you need to secure your machine. This server will be exposed to the web at large, so you want to make sure only people you trust can access it and discourage malicious users.

We’ll install fail2ban to block repeated login attempts as well as UFW as a firewall. First, make sure all system packages are updated.

sudo apt update && apt upgrade -y

Next, install fail2ban.

sudo apt install fail2ban

Edit the jail file.

sudo nano /etc/fail2ban/jail.local

Add the following, replacing “[email protected]” with your system admin email:

destemail = [email protected]
sendername = Fail2Ban

enabled = true
port = 22

enabled = true
port = 22

Now, restart fail2ban.

sudo systemctl restart fail2ban

Next, we need to add a firewall.

Device Access

We’re messing with the firewall here. Make sure you can physically connect to the device in the event you block yourself out (if accessing remotely).

If you took a break, make sure everything is up to date again.

sudo apt update && apt upgrade -y

Install UFW.

sudo apt install ufw

Once installed, you need to configure the firewall to only allow access through specific ports. If you want to limit access from specific devices, you can do that as well. In this case, the only ports we need open are 80, 443, and 22 (since we’re only interacting with the Pi through SSH). Now, I also use Webmin to manage multiple servers, so I have a specified Webmin port as well.

Additionally, I know that I only access my servers from one of only a handful of devices. My server sits behind a reverse proxy, so I know ports 80 and 443 should only ever be accessed from the IP address of that reverse proxy. Likewise, port 22 will only ever be accessed by one of my admin PCs or laptops.

To simply allow all traffic through a port, use:

sudo ufw allow 22

Or, to allow ports associated with a service (defined in the /etc/services file), type:

sudo ufw allow ssh

Now, if I want to allow access to a port from a specific IP the syntax is as follows:

sudo ufw allow from TARGET IP to DESTINATION port PORTNUMBER

The target IP is the device you want to allow access from (i.e. the reverse proxy), destination is the local point you want to access (“any” if you don’t have a specified virtual address), and portnumber is the port to you want access to. For example:

sudo ufw allow from to any port 80

Once you have your rules set up, enable the firewall.

Device Access

Remember, if accessing remotely make sure you added your remote port rule before you enable the firewall!

sudo ufw enable

If you want to check that it is running and actively blocking ports:

sudo ufw status

You should get a table looking similar to this (depending on how your rules are set up):

Status: active

To                         Action      From
--                         ------      ----
22                         LIMIT       Anywhere
80                         ALLOW       Anywhere
443                        ALLOW       Anywhere
22 (v6)                    LIMIT       Anywhere (v6)
80 (v6)                    ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)

Install software and dependencies

Install required software for Mastodon

First up we are going to install the software packages Mastodon requires to run. Its a handful, including Nginx, Python, Certbot, various libraries, and dependencies. It may take a minute to compile.

Make sure the system is up to date if you took a break.

sudo apt update && apt upgrade -y

Now, install most of the required software.

sudo apt install curl lsb-release imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev file git-core g++ libprotobuf-dev protobuf-compiler pkg-config nodejs gcc autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev nginx redis-server redis-tools certbot python3-certbot-nginx libidn11-dev libicu-dev libjemalloc-dev

Create a Mastodon user

Mastodon will need to have a user to run, but doesn’t need to be a user that can log in.

sudo useradd --disabled-login mastodon -m

Install NodeJS

Next up we need to install NodeJS. If you’re following the PiMyLifeUp guide, do not grab the latest version of NodeJS. We’re going to use the recommended install script from Mastodon to grab Node 16.X. Later versions can cause compilation errors.

curl -sL https://deb.nodesource.com/setup_16.x | bash -

Install NodeJS:

sudo apt install nodejs

To verify successful installation and version:

node -v

Setup PostgreSQL Database

PostgreSQL will store all the data from your instance. Also, of note, if you installed a 32-bit OS instead of a 64-bit OS the install will fail.

Start by adding the GPG key for the repository:

curl -L https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | sudo tee /usr/share/keyrings/postgresql-archive-keyring.gpg >/dev/null

Next, add the repository to the package source list:

echo "deb [arch=arm64 signed-by=/usr/share/keyrings/postgresql-archive-keyring.gpg] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" | sudo tee  /etc/apt/sources.list.d/postgresql.list

Update the package list to include the new repository:

sudo apt update

And finally, install PostgreSQL:

sudo apt install postgresql postgresql-contrib

Create a PostgreSQL Mastodon User

Next, add a user to PostgreSQL so that Mastodon can interact with the database. Switch to the PostgreSQL command line interface (CLI)

sudo -u postgres psql

Add the user:


Exit the CLI.


Enable Yarn

Next, enable Yarn, a package manager for NodeJS. Run the following two commands:

sudo corepack enable
sudo yarn set version stable

Install Ruby

Mastodon uses Ruby to generate web pages and the REST API. This can take a little bit to compile, so be patient. To get started, switch to the mastodon user first.

sudo su mastodon

Next grab the repository for the “rbenv” utility:

git clone https://github.com/rbenv/rbenv.git ~/.rbenv

Also, get the ruby-build plugin:

git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build

Run the following command to initialize the rbenv utility:

echo 'eval "$(~/.rbenv/bin/rbenv init - bash)"' >> ~/.bashrc

Make sure all the changes are available immediately by reloading the bash file:

exec bash

Finally, install Ruby. This step may take a while (about 10 minutes on my Pi).

RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.0.4

Now, make sure the everything knows to use this as the version of Ruby to use:

rbenv global 3.0.4

Lastly, install bundler for Ruby:

gem install bundler --no-document

Install Mastodon

Now that all the required software and users are installed and added, we can install the actual Mastodon software. If you followed the guide to this point, it should proceed without a hitch.

First up, grab the mastodon repository, making sure you are still the mastodon user. If your user does not start with mastodon@ in the terminal, switch to it. Now, enter the mastodon home directory:

cd ~

Grab the code base and copy it to the home directory:

git clone https://github.com/mastodon/mastodon.git live

Now, change to the “live” directory:

cd live

Use to following command to change to the latest stable release of Mastodon:

git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)

Install Mastodon and its dependencies

First up, run:

bundle config deployment 'true'

Next, remove unnecessary packages from the install:

bundle config without 'development test'

Now, install Ruby dependencies for Mastodon and tell it use as many CPU cores as available:

bundle install -j$(nproc)

Next, install NodeJS dependencies:

yarn install --pure-lockfile

Compile Mastodon

Finally, its time to get the server up and running. First up is to compile the pages, and then set up the admin user, email sends, and cloud storage.

To get started, compile the server:

RAILS_ENV=production bundle exec rake mastodon:setup

Configure general settings

Once compiled successfully, configure the general server settings. First up you need to set your domain name. Importantly, it must be the domain name you set up on your hosting provider, and you must be able to access this domain through the web. If you mess this up, it’s not easy to fix later. When you receive this prompt, enter your domain name exactly as it would be typed in a browser bar:

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

Next, you’re asked if you want the server in single-user mode. In other words, you’ll only have the one profile for yourself. If that’s the case, hit “Y”, otherwise, if setting up for the general public, type “N”.

We did not setup Mastodon in a Docker container, so type “N” when prompted.

Next, configure the PostgreSQL settings. We stuck to defaults on all of these, so continue pressing “Enter” until you hit the PostgreSQL password. We are going to leave the password empty, so go ahead and press “Enter” when prompted for a password.

Next, we’re going to configure the Redis server. This is simply a page-caching utility that improves site performance. All options are default, and the password is blank, so hit “Enter” through these prompts.

Configure Cloud Storage (Optional)

If you set up cloud storage, type “Y” and follow the prompts using the documentation from your storage provider. Otherwise, type “N” to move on.

Configure E-mail send options

Next, we will configure the E-mail send options. These are required to send the confirmation emails and notifications from your server. Its strongly recommended to use a transactional mail service rather than a self-hosted SMTP server. If you do choose to send e-mails locally, type “Y” and follow the prompts. Otherwise, type “N” to continue setting up the e-mail provider. I use Sendgrid, as an example, but each provider will have a different way of setting up the relay.

First, you need the domain or IP address of the SMTP server. Using Sendgrid as an example, you need to navigate to your Email API and integrations settings. In Sendgrid, select the SMTP Relay Option:

Sendgrid SMTP relay page

Next, set up your SMTP Relay credentials.

SMTP Relay credentials page

Give your API key a name (this is handy if you have multiple servers accessing your provider, so you don’t delete the key in error). Next, hit “Create Key” to generate your API key. Don’t leave this page yet, because you’ll need that API key in a minute, and you can’t view it again.

Back on your Pi, continue the SMTP setup, starting with the server name or IP address for your SMTP relay. In our case it would look like:

SMTP Server: (smtp.mailgain.org) smtp.sendgrid.net

Next make note of the port that your service provider uses. In our case the default port of 587 is fine. So hit “Enter”.

You’re next prompted for your username and password. The username is provided by your service provider (in this case “apikey”), and the password is the API key created by Sendgrid. Note that when you copy and paste the API key it will not display in the CLI.

Lastly, you can leave the remaining options at defaults, unless your service provides details otherwise. If unsure about the OpenSSL option, hit “none”.

To wrap it up, enter the email address that Mastodon will use to send emails. Importantly, this must be an email that is registered with your service provider, otherwise it will fail. To use the default email (Mastodon notifications@DOMAINNAME) hit enter. Now, I used a subdomain for my instance, so I have to adjust this a little because my email server sends from my top-level domain. If you need to change this, type it as such (replacing yourdomain with your actual sending domain):

E-mail address to send e-mails "from": (Mastodon <notifications@DOMAINNAME>) Mastodon <no-reply@yourdomain>

Once complete, you can test your configuration to make sure it works.

Almost done. The next step is to save all the changes to the configuration file. When asked to “Save configuration?”, hit “Y” and enter.

The next step will create the database and install needed pages and information. When prompted to set up the database, type “Y” and press enter.

The final step in configuration is to compile the visual assets. This may take a bit, and while stress out the RAM on your machine if it is not substantial. Go ahead and hit “Y” and enter.

Compilation Errors

Pay attention to this step. If you have the wrong version of NodeJS installed or your machine runs out of RAM/swap space, you’ll get a compilation error. Mastodon will, however, tell you that everything worked. You’ll need to go back and recompile after clearing the cache using the next few steps.

If you get a compilation error, try to track down the issue. If it’s a NodeJS issue, you will receive a warning that your NodeJS version may not be stable and may not work. In this case, remove the current version of NodeJS and reinstall using the instructions in this guide or off the official install documentation. Do not use the latest NodeJS version (19.x).

Otherwise, if it is a memory issue, clear the cache and try again. In both cases, run the following two commands to clear the cache and recompile:

RAILS_ENV=production bundle exec rake tmp:cache:clear
RAILS_ENV=production bundle exec rails assets:precompile

Configure the admin account

Once successfully compiled you’ll be asked to set up the admin account. Its easiest to go ahead and do this here, so follow the prompts to set up this account. Ensure the email address entered is valid, as it will be used for notifications of user approvals and server activity.

You will be given a temporary password once the user is created; copy this password for use in a minute.

Configure Web Access

Obtain an SSL certificate

To access your server over the web you must have an SSL certificate installed. Make sure ports 80 and 443 are open on the firewall, and we’ll use certbot to grab and install the certificate.

We are done with the mastodon user, so return to your normal user:


User Switch

Important: your user from this point forward must be the default, or root user. In the CLI, if it does not start with your regular user (i.e. user@), then make sure to switch prior to running the next series of commands.

Grab the certificate from Lets Encrypt. Replace “yourdomain” with the domain you will be using.

sudo certbot --nginx -d YOURDOMAIN.com

Configure NGINX for Mastodon

Mastodon provides an example config file for NGINX in its home directory. We’re going to take that file and copy it to NGINX’s sites-available directory.

sudo cp /home/mastodon/live/dist/nginx.conf /etc/nginx/sites-available/mastodon

Now, we need to link the file in the enabled sites directory to the config file in the available sites directory so that NGINX can use it.

sudo ln -s /etc/nginx/sites-available/mastodon /etc/nginx/sites-enabled/mastodon

Now, edit the config file to include your domain name (rather than example.com). Open up the file:

sudo nano /etc/nginx/sites-enabled/mastodon

Look for the following:

server_name example.com

Typically these lines are present in 2 places near the top of each server block (will have “server {“) for both port 80 and 443. Replace “example.com” with your domain name.

Next, point NGINX to your certificate from Lets Encrypt. Find the following two lines:

# ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

Uncomment those lines and replace “example.com” with your domain name, so it would look like:

ssl_certificate     /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

Once complete, finish by saving changes (CTRL+X, followed by “Y”, then enter).

Restart the NGINX server:

sudo systemctl reload nginx

Set up Mastodon as a system service

Lastly we want to run Mastodon as a system service. Mastodon bundles the service files in the code, so it just has to be moved to your systemd directory and enabled. Start by moving the Mastodon file to the systemd directory:

sudo cp /home/mastodon/live/dist/mastodon-*.service /etc/systemd/system/

Finally, enable it and start the server:

sudo systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming

Guess what? You’re done and the server is running.

Connect to your Server

To access your server, type your domain in a browser bar.

NGINX Default Page

Oops, you got the default NGINX server page? You need to disable the default NGINX page. Do the following to remove the default page:

sudo rm /etc/nginx/sites-enabled/default

Next, restart Nginx:

sudo systemctl restart nginx

That should take care of it.

If successful, you should see the default Mastodon log-in page. Grab that temporary password; type that and your admin username to access the server and start tuning your preferences.

I recommend heading over to your preferences menu and digging through all the options. Once happy with your setup, start inviting friends and happy “tooting”. And that’s it on how to host a Mastodon server.

Post Setup

So, you’ve completed setup, and now you host a Mastodon server all on your own. What you gonna do with it?

You’ll notice the initial interface is pretty similar to the feeds on most other major social media platforms. In the case of Mastodon, you’ll be working with a Twitter-esque type of post.

Mastodon feed

Posts are limited to 500 characters, can contain media and hashtags, and mentions follow the familar “@user” style. You can mention any user that is known to your server of the Fediverse. Note that to be discovered on the Fediverse and to interact with other servers, you must commit to several basic rules, including daily backups.

Server Preferences

Importantly, under preferences server admins can define the server rules (those are important), how your server looks and feels via custom CSS, and server information. You’re running a public social media network now, so it’s important as an admin that you are creating a safe space and moderating content. It is not good practice to create a server that is then a free-for-all that violates basic privacy laws, includes content that is or could be considered lewd or offensive, or is just in general inappropriate.

Author: Zack

Pharmacist, tech guy, pianist, lover of beer, gamer, beach bum. Probably missed something. Just assume I'm into a little bit of everything.

No responses yet

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors
Filter by Categories
Alcoholic Drinks (Cocktails)
Cool Stuff
Fish and Seafood
Home and Family
Home Automation
Home Security
Orlando, FL
Recipe of the Week
Web Hosting