How set up Mastodon on a Self-Managed VPS

Reudiger Dalchow
Published: 25 November 2022
Share:

Mastodon is an open-source social network. Users can create their own servers and operate a microblogging service based around a timeline, similar to Twitter. These servers are often called ‘instances’.

It benefits from being ad-free and wholly managed and moderated by its users: it’s decentralised.

So we’ve created this guide on how set up a Mastodon instance on a Self-Managed VPS. At minimum, we would recommend setting up a 2-Core Self-Managed VPS on Ubuntu 22.04.

By using a 20i VPS, you'll also be able to register your instance on the Green Fediverse, as our VPS run on 100% renewable energy.

In order to begin setting up Mastodon, you’ll need to first make sure that your Self-Managed VPS is set up on the correct operating system (OS). This guide will be using Ubuntu 22.04, which we recommend using for your installation. You may need to modify the commands that follow if you decide to go with a different OS.

Depending on the number of updates required by your system, you may need to reboot before proceeding. Once done and you’re all up to date, these instructions should help you get your Mastodon instance up and running in an hour.

Connect via SSH and run updates

To get started with setting up Mastodon, you’ll need to first connect to your VPS using SSH. If you’re unfamiliar with this process, we have a full guide on how to do so available here - https://www.20i.com/support/ssh/connect-vps-ssh

Once you’ve connected to your VPS, you should see something similar to the following:

20i Support:~$ ssh root@111.111.111.111  
root@111.111.111.111's password:  

Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-50-generic x86_64)
Last login: Wed Nov 16 15:05:51 2022
root@vps-a1n2c3d4:~#  

If you do, you’ll be signed into your VPS as the root user.

From here, you’ll want to make sure you have the latest system packages by running the following commands:

apt-get update -y
apt-get upgrade -y

This will ensure your VPS is up-to-date. If your VPS requires a reboot after the update, you can do so via the Manage VPS area in your My20i account.

Secure your server

Next, you’ll want to secure your VPS and protect it from potential brute force attacks, as well ensuring that only SSH, HTTP and HTTPS ports are open. To do this, first install fail2ban:

apt install fail2ban

Once that’s completed, you’ll want to edit the file /etc/fail2ban/jail.local and add the following:

[DEFAULT]
destemail = example@email.com
sendername = Fail2Ban

[sshd]
enabled = true
port = 22

[sshd-ddos]
enabled = true
port = 22

Replacing the email example@email.com with your email. Once that’s configured, restart fail2ban using the following command:

systemctl restart fail2ban

 

You’ll then want to look into adding some firewall protection to close off any ports except for SSH, HTTP and HTTPS access. To do this, first install iptables-persistent:

apt install -y iptables-persistent

 

Then, edit the file /etc/iptables/rules.v4 and add the following code:

*filter

# Allow all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT


# Accept all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow all outbound traffic - you can modify this to only allow certain traffic
-A OUTPUT -j ACCEPT

# Allow HTTP and HTTPS connections from anywhere (the normal ports for websites and SSL).
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

# Allow SSH connections
# The -dport number should be the same port number you set in sshd_config
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT

#Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

# Log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# Reject all other inbound - default deny unless explicitly allowed policy
-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT

On your next load time, the above configuration will be loaded. However, if you want to load this configuration now, you can use the command:

iptables-restore < /etc/iptables/rules.v4

 

Install Mastodon dependencies

Now that the VPS is set up and has some baseline security, we can now begin working on installing Mastodon. We’ll first need to make sure curl, wget, gnupg, apt-transport-https, lsb-release, make and ca-certificates are installed as these are required to set up Mastodon, so add these dependencies with the following command:

apt install -y curl wget gnupg apt-transport-https lsb-release make ca-certificates

You’ll also want to add the following dependencies, which will be used by Mastodon and include core services such as NGINX, Redis, and PostgreSQL:

apt install -y \
  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 postgresql postgresql-contrib \
  certbot python3-certbot-nginx libidn11-dev libicu-dev libjemalloc-dev

 

With these added, we’ll next need to configure Node.js and Yarn.

Install Node.js and Yarn

Setting up Node.js for Mastodon will first require you to add the nodesource repo – you can do so with this command:

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

You can then install nodejs using apt-get:

apt-get install nodejs -y

Once this is completed, you’ll have access to the command corepack, which can be used to set up and enable Yarn:

corepack enable
yarn set version stable

And that’s set. Now, we need to set up a user for your Mastodon server on your VPS.

Create a new system user

Mastodon will require a user on the server to grant it access to the services it requires. You can add one using the command below:

adduser --disabled-login --gecos 'Mastodon Server' mastodon

 

You’ll want to now sign in as that user – this will test to make sure it’s set up correctly, and allow you to proceed with the next step of installing Ruby. To sign in the user, simply run the command:

su - mastodon

If done correctly, you should see a different username in your bash area like so:

mastodon@vps-a1n2c3d4:~$

Install Ruby

While logged in as the Mastodon user, you’ll need to set up the rbenv repo for Ruby. This can be done with the git clone command below:

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

 

Then navigate to the directory .rbenv and set this up – these commands do this:

cd ~/.rbenv && src/configure && make -C src
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec bash

You can then clone Ruby’s main build to your VPS using git clone with this command:

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

You now have all you need to install Ruby. Using the built-in RUBY_CONFIGURE_OPTS that was added with the git, install Ruby 3.0.4.

RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.0.4

 

You’ll now want to set the global Ruby version as 3.0.4, and then update gem with these commands:

rbenv global 3.0.4
gem update –system

 

Finally, install bundler, which will be required to complete your Mastodon installation later on.

gem install bundler --no-document

You will now have Ruby fully installed and ready to go. You can check this by running the following command to check the current Ruby version:

ruby --version

Once you’re happy and ready to move on, simply use the exit command to log out of the Mastodon user and return to root:

exit

Configure PostgreSQL

You’ve already installed base PostgreSQL, but you also need to add their latest repository. You can do so with the following command:

wget -O /usr/share/keyrings/postgresql.asc https://www.postgresql.org/media/keys/ACCC4CF8.asc
echo "deb [signed-by=/usr/share/keyrings/postgresql.asc] 
http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > 
/etc/apt/sources.list.d/postgresql.list

 

Once that’s done, you’ll need to sign into the PostgreSQL user that will have been created by the command. You can do so much as you did with the Mastodon account, with the following command:

su – postgres

 

You can then boot PostgreSQL to access your database:

psql

 

In this database, we’ll want to set up a user for Mastodon, which will allow it to access the database, create tables and update any data for functionality. You can do so with the following SQL command:

CREATE USER mastodon CREATEDB;

 

Now that’s created, we can close PostgreSQL. To do so, enter the command exit twice – first to close the connection to the database, then again to return to the root user.

Configure Mastodon

You’ll now want to install and configure your Mastodon setup. You’ll need to swap back to Mastodon’s user for this next step, so do so as you did before:

su - mastodon

First, we’re going to grab the latest Mastodon version from git with git clone, as we did with Ruby:

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

 

Then navigate to the live directory:

cd ~/live

And use git to ‘checkout’ the repository’s latest branch. You can do so with the following command:

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

Now that we have this downloaded, we can enable development, and use bundle and yarn to install the remaining files. You’ll want to use the following commands for this:

bun
dle config deployment 'true'
bundle config without 'development test'
bundle install -j$(getconf _NPROCESSORS_ONLN)
yarn install --pure-lockfile

Now that we have all the files we need, we can use Ruby to initiate Mastodon’s setup wizard:

RAILS_ENV=production bundle exec rake mastodon:setup

 

If you’ve done everything correctly, you’ll get the following output – “Mastodon will step you through each of the requirements and ask for answers”. Use the below as a guide for what to add, replacing the domain name with what domain you want to use for Mastodon and your own email. For options like PostgreSQL’s host, port and database and Redis’ host and port, the wizard should autofill these selections. You’ll want to leave the passwords as blank for these unless you’ve added a password for these yourself.

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

Domain name: mastodon.mydomain.com

Single user mode disables registrations and redirects the landing page to your public profile.

Do you want to enable single user mode? No


Are you using Docker to run Mastodon? no


PostgreSQL host: /var/run/postgresql

PostgreSQL port: 5432

Name of PostgreSQL database: mastodon_production

Name of PostgreSQL user: mastodon

Password of PostgreSQL user:  

Database configuration works! 


Redis host: localhost

Redis port: 6379

Redis password:  

Redis configuration works! 


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


Do you want to send e-mails from localhost? yes

E-mail address to send e-mails "from": Mastodon 

Send a test e-mail with this configuration right now? no


This configuration will be written to .env.production

Save configuration? Yes


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? Yes

Running `RAILS_ENV=production rails db:setup` ...


Created database 'mastodon_production'

Done!

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


Do you want to create an admin user straight away? Yes

Username: admin

E-mail: example@email.com

You can login with the password: [PASSWORD]

You can change your password once you login.

 
Note the admin details you’re provided by the wizard – you’ll need them to log into Mastodon later!

Once you’ve got all the information you need and you’ve made a note of the username and password of the admin user, you can exit the Mastodon user on your VPS with exit, as before.

exit

 

Configure Nginx and add an SSL to your installation

We’re getting close to the end of our installation now – we have Mastodon installed and configured, and our requirements are all set. We now need to link up the domain we’re using to the VPS, install an SSL and configure NGINX to allow it to serve Mastodon.

First, point the domain you wish to use for Mastodon to your VPS. Your VPS IP can be found in your hosting control panel, on the Manage VPS page in your My20i account. Simply select Options, then Manage on the VPS you’re using and you’ll see this available under VPS Information on the right of the screen.

Your domain registry should have instructions on how to update the DNS of your domain – if your domain is registered with 20i and the nameservers are on our StackDNS nameservers, you can do so with the following steps:

  1. Log into My20i and navigate to Manage Domains.
  2. Search for your domain, and hit Options, then Manage DNS.

Manage DNS from web hosting control panel

  1. Using the fields provided at the bottom of the DNS page, enter your record.
    1. Enter your subdomain in the ‘Name’ field. If you’re using your main domain, leave this area blank.
    2. Select A from the dropdown box.
    3. Insert the IP of your VPS into the data field.
    4. Hit Update DNS, and once propagated, your domain should be properly pointing to your site.

Once that’s pointing to the site you can use certbot, which we installed earlier, to install a Let’s Encrypt free SSL on the domain, and configure NGINX to use it:

certbot --nginx -d mastodon.example.com

Then take the Mastodon NGINX config file from their file setup and copy this over to NGINX. You can do so with the following command:

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

You should then use a symlink to set up the virtual host configuration file with this command:

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

Then, you’ll need to update the domain in the virtual host configuration file to the domain you wish to use, replacing mastodon.mydomain.com in the below code with the domain you want to add:

sed -i 's/example.com/mastodon.mydomain.com/g' /etc/nginx/sites-enabled/mastodon

After this has done, remove the NGINX default configuration file to prevent the NGINX default page loading on your site:

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

Lastly, open your mastodon file in sites-enabled with a file editor such as vim:

vim /etc/nginx/sites-enabled/mastodon

You should see two lines commented out in this file, like so:

 # Uncomment these lines once you acquire a certificate:

 # ssl_certificate     /etc/letsencrypt/live/mastodon.mydomain.com/fullchain.pem;

 # ssl_certificate_key /etc/letsencrypt/live/mastodon.mydomain.com/privkey.pem;

 

Remove the hashes before ‘ssl_certificate’ and ‘ssl_certificate_key’ to uncomment these lines. Once done, save and close the file (you can do this in vim by entering :x or :wq) and then restart nginx.

systemctl restart nginx

You’ve now fully installed and configured NGINX to serve Mastodon.

Create a System service for Mastodon

Mastodon requires a few services to launch with the VPS whenever it reboots. You can configure this by first copying the systemd service templates from the Mastodon directory to your system folder with these commands:

cp /home/mastodon/live/dist/mastodon-web.service /etc/systemd/system/
cp /home/mastodon/live/dist/mastodon-sidekiq.service /etc/systemd/system/
cp /home/mastodon/live/dist/mastodon-streaming.service /etc/systemd/system/

 

Now that the system services are in place, you can start them up and enable them – this will ensure that they launch at startup:

systemctl start mastodon-web
systemctl start mastodon-sidekiq
systemctl start mastodon-streaming
systemctl enable mastodon-web
systemctl enable mastodon-sidekiq
systemctl enable mastodon-streaming

To make sure that this has been configured correctly, you can use the following command to check the status of these services:

systemctl status mastodon-web mastodon-sidekiq mastodon-streaming

 

Lastly, you’ll want to make sure that Mastodon has all the right permissions to access the core files. So, run the following commands to set the permissions.:

chown mastodon:www-data /home/mastodon/
chmod 0710 -v /home/mastodon/

You’ve successfully installed Mastodon, and should now be able to access it from your site!

Access the Mastodon interface

The final steps are now to access the site itself. Open your web browser, and navigate to your domain. You should be greeted with Mastodon’s Dashboard.

 

 
  mastodon server set up done

You can log in using the ‘Sign in’ option on the right. The credentials to log in are  the admin details you noted earlier while running the configuration wizard for Mastodon.

With that, you’ve fully set up a Mastodon service on your own VPS and domain, and can freely post and configure the setup to customise its appearance.