Install Mastodon without Docker (Ubuntu 20.04)

Self Hosted Dec 10, 2022

Mastodon is free and open-source software for running self-hosted social networking services. It has microblogging features similar to the Twitter service, which are offered by a large number of independently run nodes, known as instances, each with its own code of conduct, terms of service, privacy policy, privacy options, and moderation policies.

This article is my personal snippet for running Mastodon instance on Ubuntu 20.04 from source. I use self-signed certificate instead of cerbot because the instance will be run behind Cloudflare reverse proxy.

The asciinema video below is the whole process I install Mastodon instance (for reference)

Or the whole YouTube video:

Install Mastodon without Docker (Ubuntu 20.04) article written in Indonesia.


Before starting, there are several things that need to be fulfilled:

  • Fresh Ubuntu 20.04 server with root access.
  • Domain name (or sub-domain) for the Mastodon instance (in this case I'm using and the Mastodon instance will be accessed from
  • SMTP Server for email delivery service.

Preparing the system

First, make sure the Ubuntu server we're using is up to date.

apt update && apt upgrade

Install curl, wget, gnupg, apt-transport-https, lsb-release and ca-certificates:

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

Install NodeJS 16:

curl -sL | bash -

Use official PostgreSQL repository:

wget -O /usr/share/keyrings/postgresql.asc
echo "deb [signed-by=/usr/share/keyrings/postgresql.asc] $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/postgresql.list

Update and install required system package:

apt update
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

Enable NodeJS corepack feature and set Yarn version to classic:

corepack enable
yarn set version classic

Install Ruby with rbenv.

Note that rbenv must be installed for a single Linux user, therefore, first we must create linux user where Mastodon services will be running as (we'll create mastodon user):
adduser --disabled-login mastodon

Then switch to mastodon user:

su - mastodon

And as mastodon user, proceed to install rbenv and rbenv-build:

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

Once Ruby environment setup is done, we can than install the required Ruby version and bundler:

RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.0.4
rbenv global 3.0.4
gem install bundler --no-document

Return to the root user:


Setting up PostgreSQL

For optimal performance, you may use pgTune to generate an appropriate configuration and edit values in /etc/postgresql/15/main/postgresql.conf before restarting PostgreSQL with systemctl restart postgresql.

Now, create a PostgreSQL user that Mastodon service could use. The easiest way is with ident authentication so the PostgreSQL user does not have a separate password and can be used by the Linux user with the same username.

Open PostgreSQL prompt:

sudo -u postgres psql

In the psql prompt, execute:


The core system requirement is now ready, now we can move forward to setting up Mastodon instance along with it's dependency.

Setting up Mastodon

It is time to download the Mastodon code. Switch to the mastodon user:

su - mastodon

Use git to download the latest stable release of Mastodon:

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

Install Ruby and JavaScript dependencies for Mastodon code:

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

Run the interactive setup wizard:

RAILS_ENV=production bundle exec rake mastodon:setup

The command above will be:

  • Create a configuration file
  • Run asset pre-compilation
  • Create the database schema

The configuration file is saved as .env.production.

In my case, I want Mastodon instance can be accessed from but use my main domain identity to serve @[email protected] (instead of @[email protected]) So I need to change LOCAL_DOMAIN configuration value to and add in the .env.production file configuration. Please refer to documentation on configuration for more detailed information.

When done with the configuration we can switch back to root user:


Setting up Nginx

Copy the Nginx configuration template that comes from Mastodon repository:

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

Then edit /etc/nginx/sites-available/mastodon and replace to our domain name (in my case

As I said before, the instance will be serve behind Cloudflare reverse proxy and I don't want to use certbot to issue my SSL certificate. So I use my own self-signed certificate.

If you want to use certbot to issue the SSL certificate:

systemctl reload nginx
certbot --nginx -d

Replace with your domain name.

Setting up Mastodon systemd services

Copy the systemd service templates from the Mastodon directory to /etc/system/systemd directory:

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

Finally, start and enable Mastodon services:

systemctl daemon-reload
systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming

Wait for a few minutes and try to access your instance from your web browser, and enjoy your self-hosted Twitter alternative!

If you want to join my instance, please do so : The data stored somewhere in Indonesia.