Build Your Own Mastodon Server on Debian (Step by Step Server Build Guide)

There’s way too much drama with Twitter nowadays, so the alternatives are looking more attractive than ever. Setting up your own Mastodon server is a fun project, and also a potential alternative to Twitter. In this video, Jay walks you through the entire process of setting up your own Mastodon server on a Debian-based VPS.

YouTube player

What you’ll need

  • A domain from a registrar
  • A VPS instance, 4GB RAM recommended
  • DNS A record pointing to VPS
  • An SMTP provider for outbound mail

Initial server setup

These commands aren’t specific to Mastodon, but will help us set up some common things that should be done on a fresh server build.

Create a non-root user

Create a user account to use while setting up the server.

adduser jay
usermod -aG sudo jay

Exit the session:

exit

Re-establish ssh as the new user you’ve created

ssh user@IP

Install all updates

It’s always a good idea to install all updates on all fresh server deployments. To do so, first update the repository index to update the local cache with any packages that have been made available recently:
sudo apt update

sudo apt dist-upgrade

Set the hostname

To set the hostname of your server, edit the /etc/hostname file:

sudo nano /etc/hostname

Inside that file, change the hostname to match the domain you plan to use.

Next, edit /etc/hosts and set the name there too:
sudo nano /etc/hosts

Reboot the server

The first stage of setup is done, so it’s a good idea to reboot the server:

sudo reboot

Installing the required packages

There’s going to be a handful of packages that will need to be installed from various categories. In this section, we’ll install all of the packages that we’ll end up needing through the rest of the tutorial.

Install basic development packages

First, we’ll install development packages from Debian’s default repositories:

sudo apt install build-essential bundler git libidn11-dev libjemalloc-dev libpq-dev nginx nodejs npm postgresql postgresql-contrib rbenv redis-server ruby ruby-dev

Next, we’ll need to install yarn via npm:

sudo npm install --global yarn

Database setup and configuration

Set up PostgreSQL

sudo su - postgres
psql
CREATE DATABASE mastodon_production;
CREATE USER mastodon;
ALTER USER mastodon createdb;
ALTER USER mastodon WITH ENCRYPTED PASSWORD 'super_secret_password';
ALTER DATABASE mastodon_production OWNER TO mastodon;
exit

A second time, to return to original user:

exit 

Set up the mastodon system user

We should create a dedicated user for mastodon. To do so, run the following command:

sudo adduser --group --system mastodon

Download mastodon

Download the Mastodon repository locally

We can download the git repository for mastodon locally by running the following command:

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

Adjust permissions

We should change the permissions such that the mastodon user and group owns the downloaded repository:

sudo chown -R mastodon:mastodon mastodon

Create the app directory

Move Mastodon’s files into the www directory

Rather than serve Mastodon from our home directory (bad idea) we should move it into the /var/www directory instead:

sudo mv mastodon /var/www/

Setting the Mastodon version to use

Change directory to the Mastodon directory

Change into the directory where Mastodon’s files are now located:

cd /var/www/mastodon

Adding the Mastodon directory to the safe list

If we try to manage the repository now, it will fail. By default, repositories are now protected. To allow the mastodon user to manage mastodon files, we need to add the directory to the safe list (and do so as the mastodon user):

sudo -u mastodon git config --global --add safe.directory /var/www/mastodon

Determining the latest version number of Mastodon

We should specify the verison of Mastodon to use. First, visit the following URL:
https://github.com/mastodon/mastodon/releases
Make note of the version number marked “latest”.

Set the Mastodon version

With the version number you noted in the previous step, check out that version of the code:

sudo -u mastodon git checkout <version>

Example:

sudo -u mastodon git checkout v3.5.4

Prepare Mastodon for installation

sudo gem install bundler
sudo -u mastodon bundle config deployment 'true'
sudo -u mastodon bundle config without 'development test'
sudo -u mastodon bundle install -j$(getconf _NPROCESSORS_ONLN)

Set up Mastodon:

Run the setup script

The following command will run the setup script:

sudo -u mastodon RAILS_ENV=production bundle exec rake mastodon:setup

Install systemd units

Copy the example mastodon startup scripts to the /etc/systemd/system directory:

sudo cp /var/www/mastodon/dist/mastodon*.service /etc/systemd/system
sudo sed -i 's/home\/mastodon\/live/var\/www\/mastodon/g' /etc/systemd/system/mastodon-*.service
sudo sed -i 's/home\/mastodon\/.rbenv\/shims/usr\/local\/bin/g' /etc/systemd/system/mastodon-*.service
sudo systemctl daemon-reload
sudo systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming

Set up reverse proxy

sudo cp /var/www/mastodon/dist/nginx.conf /etc/nginx/conf.d/mastodon.conf
sudo nano /etc/nginx/conf.d/mastodon.conf


Fix home path, and also the servername. Both in 80 and 443 sections
Add the following near the commented-out certificate section:

ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

Restart nginx

Next, restart nginx so it takes advantage of the new settings:

sudo systemctl restart nginx

Set up TLS certificate

sudo apt install snapd
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --nginx

Add some default security tweaks

Install unattended-upgrades

sudo apt install unattended-upgrades

Edit /etc/apt/apt.conf.d/50unattended-upgrades

Enable automatic reboot, automatic reboot time, and enable automatic reboot with users.

Install Crowdsec

curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash
sudo apt install crowdsec
sudo apt install crowdsec-firewall-bouncer-iptables

Shout out

The following articles helped me with some things I was stuck on while figuring out how to set this up: