User Tools

Site Tools


  • mastodon
  • Jonathan Haack
  • Haack's Networking


This tutorial is for users of Debian GNU/Linux who want to set up a mastodon instance. This particular instance runs in a VM (4-core / 16GB RAM / 1TB) for which the underlying host OS setup and hardware is outlined here: VM Server. I used Mastodon's official docs and also relied fairly heavily on Linux Babe's tutorial whose use cases are often similar to my own. Alright, first install postgres SQL:

echo "deb [signed-by=/etc/apt/keyrings/postgresql.asc] $(lsb_release -cs)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list
sudo mkdir -p /etc/apt/keyrings/
wget --quiet -O - | sudo tee /etc/apt/keyrings/postgresql.asc
sudo apt update
sudo apt install -y postgresql postgresql-contrib

Once it is installed, create a database for mastodon:

sudo -u postgres -i psql
<CREATE USER mastodon;>
<ALTER USER mastodon WITH ENCRYPTED PASSWORD 'your_preferred_password';>
<ALTER USER mastodon createdb;>
<ALTER DATABASE mastodon OWNER TO mastodon;>

Once the database is created, we need to install ruby/gems, which is the platform mastodon uses along with nginx to serve content on the web. This includes creating a mastodon user to perform gem/rake operations. Also, the install method clones a git repo and builds the instance from source.

sudo apt install ruby ruby-dev
sudo adduser mastodon --system --group --disabled-login
sudo apt install git
git clone
sudo mv mastodon/ /var/www/
sudo chown mastodon:mastodon /var/www/mastodon/ -R
cd /var/www/mastodon/
sudo -u mastodon git checkout v3.5.3
sudo gem install bundler
curl -sL | sudo bash -
sudo apt install nodejs
echo "deb stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
curl -sL | sudo apt-key add -
sudo apt update
sudo apt -y install yarn

That's the ruby/gem toolchain there, and now install dependencies and libraries required for compiling the project from source:

sudo apt install redis-server optipng pngquant jhead jpegoptim gifsicle nodejs imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev file g++ libprotobuf-dev protobuf-compiler pkg-config gcc autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev libidn11-dev libicu-dev libjemalloc-dev

After installing the package dependencies, I created an A record for GNU/Linux Social and then set up a postfix send-only MTA. I also created a PTR record for my domain, an SPF record, and a dmarc record. I have a separate tutorial on how to setup spf records, so view that if you need help. Typically, you need to contact your ISP or datacenter for help with your PTR records; my provider,Brown Rice Internet ,provides a web panel where I can add them myself. To setup postfix, do the following:

sudo apt install postfix mailutils
<Internet Site>
sudo nano /etc/postfix/
<inet_interfaces = loopback-only>
systemctl restart postfix

Now that our Mail Transfer Agent is setup, we can switch over to building the ruby/gem bundle. To do that, we first use the mastodon user to perform a ruby bundle configuration prior to building from source. After those three configurations are complete, we run the ruby install script with an environment variable required for the compiling.

sudo -u mastodon bundle config deployment 'true'
sudo -u mastodon bundle config without 'development test'
sudo -u mastodon bundle install -j$(getconf _NPROCESSORS_ONLN)
sudo -u mastodon RAILS_ENV=production bundle exec rake mastodon:setup

Next, we want to use the systemd units that Mastodon provides and change the example web root directory to our production web root directory. You can do this with sed like Linux Babe did, or just edit the files manually is fine too. Once you finish, reload all systemd units and start the three required services.

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

Now that the back end ruby/gem environment is working and operational, you need to setup an nginx reverse proxy that will forward port 80/443 requests to that. To do this, install nginx and use the Mastodon suggested server blocks and edit appropriately in both the 80 and 443 blocks. Note, since the Mastodon template has a 443 block, we must temporarily use the self-signed cert/keys so that the service can start without error. Optionally, you could use cert-only with ACME, but I have trouble with that myself.

sudo apt install nginx
sudo cp /var/www/mastodon/dist/nginx.conf /etc/nginx/conf.d/mastodon.conf
sudo nano /etc/nginx/conf.d/mastodon.conf
<root /var/www/mastodon/public;>
<ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;>
<ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;>
sudo mkdir -p /var/nginx/cache/
systemctl restart nginx

Now that nginx is all set up with self-signed certs and the service is running, we can easily set up Let's Encrypt. Personally, Linux Babe's ACME command failed for me, so I ran my own trusted command that I've used for years and it worked right away.

sudo apt install certbot python3-certbot-nginx
sudo certbot --authenticator standalone --installer apache -d --pre-hook "systemctl stop nginx" --post-hook "systemctl start nginx"

Make sure to set up a cronjob for the cert to automatically renew:

30 2 * * 1 /usr/bin/certbot renew >> /var/log/le-renew.log

Also, I have four scripts that I run on this instance to keep nginx, postgres, and fail2ban running. I also have a separate script that dumps the entire database daily with a time stamp. If you need help setting up fail2ban, use this tutorial. Here are the scripts currently in use:

  1. Keep Fail2Ban
  2. Keep Postgres Running:
  3. Keep Nginx Running:
  4. Nightly DB Dumps:

Also, there's no point in setting this up unless you have regular backups! In my case, since this is a VM, I just use the same script as I use for all my other instances. That script powers down the VM, and copies a sparse file, then tarballs it. After restarting the VM, my backup workstation pulls down the tarballs (also sparse) on a set schedule, keeping approximately 90 days of restore points. The backup script I use is found here and, of course, this runs on the host OS (not the Mastodon VM instance):

  1. VM Backup Script:

Lastly, I also have a hot-spare in case my co-located hardware fails. Swing on by:

  1. Self-hosted Mastodon Instance: GNU/Linux Social

oemb1905 2022/11/23 20:47

computing/mastodon.txt · Last modified: 2022/11/24 03:53 by oemb1905