How To Install Mastodon on Ubuntu 20.04

Published on December 19, 2022
How To Install Mastodon on Ubuntu 20.04


Mastodon is a microblogging social networking application that uses a decentralized model, also called a federation. Mastodon is open-source and can be deployed by anyone on any server, with each server being its own instance. Each instance can have its own policies and moderation. Within the federation of all Mastodon servers, each Mastodon instance can be made aware of other instances. This allows interaction with other users both within a single server and across multiple instances.

In this tutorial, you will install the latest version of Mastodon, which is 4.0.2 at the time of this writing. You will configure the official Mastodon install repository, and set up the environment to install all other dependencies. Using the interactive setup, you will set up your custom Mastodon instance for storage, email, assets, and your administrator account. Finally, you’ll secure your instance with SSL/TLS certificates through Let’s Encrypt.

Note: This tutorial details an installation on a bare metal server, as recommended by the team behind Mastodon. You can also consider this alternative Mastodon installation method:


To follow along with this tutorial, you will need:

Once you’ve set everything up, you’re ready to begin the first step.

Step 1 — Creating a mastodon System User and PostgreSQL Role

Mastodon’s source code makes the assumption that your server will be administered using a specific system user named mastodon. This is currently hardcoded into many parts of Mastodon. This tutorial will follow the recommendation of creating and using the mastodon user, at both the system level and as a role for your PostgreSQL database.

This tutorial assumes you created a user in the initial server setup in the prerequisites, but the following commands can also be run as root with the omission of sudo before the commands. First, use adduser to create your mastodon user:

  1. sudo adduser mastodon

Next, add your mastodon user to the sudo group to grant it administrative privileges:

  1. sudo usermod -aG sudo mastodon

With your system level mastodon user created, next create a matching role in your database. PostgreSQL uses peer authentication, which associates created roles with matching system users. Create a user with the matching name of mastodon:

  1. sudo -u postgres createuser --interactive

The interactive flag will display the following prompt where you can choose the name of your new role, mastodon. Make sure to enter y to make your new role a superuser:

Enter name of role to add: mastodon Shall the new role be a superuser? (y/n) y

Now you can log into your newly created mastodon user:

  1. su - mastodon

For the rest of this tutorial, you will be running all commands as this mastodon user.

Step 2 — Installing Dependencies and Cloning Mastodon

The majority of Mastodon’s configuration is handled through an interactive setup that you will do in a later step. First, you need to install its dependencies. Mastodon is a project that is based heavily around Ruby and Node.js while operating in a Linux environment, resulting in a need for three package managers: APT at the Linux system level, Bundler for Ruby gems, and Yarn for Node.js packages. To install from source, you need to clone the Mastodon repository. The process will go in the following order:

  • Install APT dependencies.
  • Clone Mastodon from source.
  • Install Ruby and Mastodon’s Ruby dependencies.
  • Install Node.js dependencies.

The first step is to install the dependencies through apt, which includes: Redis as a key-store database, Certbot for handling TLS/SSL encryption, and miscellaneous libraries for building, compiling, and image handling. To install these, use apt update to update your package index:

  1. sudo apt update

Then install the packages with apt install:

  1. sudo apt install \
  2. imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev \
  3. libprotobuf-dev protobuf-compiler pkg-config \
  4. redis-server redis-tools \
  5. certbot python3-certbot-nginx libidn11-dev libicu-dev libjemalloc-dev

Cloning Mastodon

Now your server is ready to clone the Mastodon source from its official repository. As mentioned previously, this tutorial will use the latest version of Mastodon, which is v4.0.2 at the time of this writing, for the most up-to-date features, security, and bug fixes.

First, clone the Mastodon repository to your server into a new directory named live:

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

This directory naming convention is used throughout Mastodon’s documentation, and is recommended for consistency. Next, move into the directory you created, note that this will be your project directory for the rest of the tutorial:

  1. cd live

Now you can use git to check out the latest version v4.0.2:

  1. git checkout v4.0.2

Installing Ruby and Mastodon’s Ruby Dependencies

With the Mastodon source code in place, you can now proceed to installing Ruby and Mastodon’s Ruby dependencies. You will install rbenv, the version manager tool you will use to install the Ruby programming language. Because rbenv is installed at the user level instead of the system level, this step must be done here after you created and switched to your mastodon user. You will install Ruby version 3.0.4 following Steps 1 through 3 of our tutorial How To Install Ruby on Rails with rbenv on Ubuntu 20.04. While version 3.0.4 in Step 2 won’t be an explicitly listed option, it will still work if you specify this version in your install command. Keep in mind that though this tutorial is for Ruby on Rails, you will only use the steps focused on installing Ruby with rbenv.

The Ruby dependencies are managed by Bundler. Bundler installs all the Ruby gems required by Mastodon, but first you need to configure it to install with production in mind.

Use the bundle config command from Bundler to interface with its configuration system. Use it to set deployment to true:

  1. bundle config deployment 'true'

Next, use without to ensure dependencies for development and testing will not be installed:

  1. bundle config without 'development test'

You can now install your Ruby dependencies with install. This can take some time with several pauses, though this is normal behavior:

  1. bundle install
Fetching gem metadata from https://rubygems.org/......... Fetching https://github.com/ClearlyClaire/webpush.git Fetching rake 13.0.6 Installing rake 13.0.6 Fetching concurrent-ruby 1.1.10 Installing concurrent-ruby 1.1.10 . . .

Once this finishes, there is a lot of output at the end that may appear like it needs to be acted upon. However, you can safely proceed without additional action required.

Installing Mastodon’s JavaScript Dependencies

Once Mastodon’s Ruby dependencies have completed installation, you can move onto the JavaScript dependencies. Mastodon relies on yarn to manage and install JavaScript packages, instead of npm. With Node.js installations versions 16.10 and above, yarn is available by default through the corepack.

To gain access to yarn, enable Node.js’s included corepack:

  1. sudo corepack enable

Yarn has had a development history that diverges between its version 1.0, also known as classic, and version 2.0. Mastodon requires the classic version of yarn, which you enable with yarn set version:

  1. yarn set version classic

Now you can install Mastodon’s JavaScript dependencies using yarn install. The additional flag ensures a yarn.lock file is not generated:

  1. yarn install --pure-lockfile
yarn install v1.22.19 [1/6] Validating package.json... [2/6] Resolving packages... [3/6] Fetching packages... [4/6] Linking dependencies... warning Workspaces can only be enabled in private projects. [5/6] Building fresh packages... [6/6] Cleaning modules... Done in 50.84s.

You are now ready to create a custom Mastodon configuration file for your server.

Step 3 — Generating a Mastodon Configuration File with the Interactive Setup

Mastodon uses a variation of the .env file as its configuration file. There is a sample available for viewing at ~/live/.env.production.sample, but instead of copying that file you will use the interactive setup process. Upon completion, a custom file will be generated at ~/live/.env.production. This interactive setup will cover basic server information, establish PostgreSQL and Redis connections, set up cloud storage and email handling, compile CSS and JavaScript assets, and create an administrator account within Mastodon.

Before beginning the multi-step setup process, ensure your firewall allows SMTP traffic through the appropriate port. The default SMTP port for secure TLS connections is port 587, and this will be explained in the email setup portion later. For now, allow access to this port within your firewall:

  1. sudo ufw allow 587

To begin the interactive setup, use bundle exec rake to execute Mastodon’s setup, while setting the environment variable for `production:

  1. RAILS_ENV=production bundle exec rake mastodon:setup

Enter your domain name. Note that it is difficult to change this after the fact, so double-check your input for accuracy:

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

Mastodon has a single user mode where registrations are disabled. For a server set up with the intent of creating a shared space with others, you should not enable single user mode:

Single user mode disables registrations and redirects the landing page to your public profile. Do you want to enable single user mode? No

Answer no to the prompt about using Docker, as this tutorial covers a conventional install on a bare metal server:

Are you using Docker to run Mastodon? no

Configuring Databases

All of the PostgreSQL settings can remain as the defaults by pressing Enter for each prompt. Your database does not authenticate using a password, but rather, uses peer authentication, which we will discuss later. For now, it can be left empty:

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 settings can also maintain its defaults, and with the password field left blank. You won’t be setting up a password because this database is intended to only be accessible locally on this server. You can press Enter for each prompt:

Redis host: localhost Redis port: 6379 Redis password: Redis configuration works!

The connection to both databases will be tested as working.

Configuring Storage

Next, you are asked about uploading files to a cloud storage. Mastodon storage can be set up using local storage or with cloud storage through a number of providers. If you want to use local storage, or if you do not have an cloud storage immediate solution ready, answer No.

However, this is not sustainable as a long-term storage solution, and an object storage solution is recommended for production purposes. Mastodon supports several popular object storage solutions, including DigitalOcean Spaces and other S3-compatible solutions like MinIO. Since MinIO is open-source, you can follow our tutorial on how to set up your own MinIO object storage server. For the purposes of this tutorial, you can choose Yes and use the following example for DigitalOcean Spaces. For more details on Spaces, follow this tutorial on how to create your own DigitalOcean Space and access keys:

Do you want to store uploaded files on the cloud? yes
Provider DigitalOcean Spaces
Space name: your_spaces_name
Space region: your_spaces_region
Space endpoint: your_spaces_endpoint
Space access key: your_spaces_access_key
Space secret key: your_spaces_secret_key
Do you want to access the uploaded files from your own domain? No

You’re also given the option to access files uploaded to your Mastodon instance using links on your domain, instead of using direct links to your cloud storage. You can choose this option if you want, but this tutorial will select No. You can go back later and edit the generated configuration file if you change your mind regarding storage. Check the official Mastodon documentation for configuration file parameters on file storage.

Configuring Outbound Email

Mastodon requires access to an SMTP email server as a method of sending emails. An external email service provider is recommended instead of running your own. Mastodon uses Mailgun in its examples. Maintaining a secure and reliable email server is an arduous undertaking, so it is recommended that you rely on an external third-party email service provider. However, you should be aware that most third-party email service providers charge based on volume, and may or may not have a free tier below a certain usage threshold. Your discretion is advised in this scenario.

Note: While this tutorial can be completed without an immediate SMTP solution, by leaving all the credential fields blank or default, doing this will hinder Mastodon’s full functionality and is not recommended. You do have the option of setting up an account with an email provider and adding your credentials to your configuration file later. However, this means Mastodon’s emails will not be sent until you do this, and some functionality such as following other accounts won’t be available.

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

With all email providers, you must create and configure an account. This differs depending on the provider. Most likely after signup, you need to verify your domain with your provider to enable sending emails in a process that involves adding DNS records to your domain. Additionally, you need to obtain or generate an API key as credentials for secure authentication.

This tutorial uses Mailgun as an example, though any choice of email service provider will work. These choices can also be used as a guideline for other email service providers. Mailgun in particular automatically generates SMTP credentials for every added domain. Again, this will differ depending on the email service that you use, and you should check their corresponding documentation:

SMTP server: smtp.mailgun.org SMTP port: 587 SMTP username: your_smtp_username SMTP password: your_smtp_password SMTP authentication: plain SMTP OpenSSL verify mode: peer Enable STARTTLS: auto E-mail address to send e-mails "from": Mastodon <notifications@your_domain>

While the default of plain seems out of place for SMTP authentication, the common options for SMTP authentication that are supported by email service providers include plain and login, which are both Base64 encoded. Base64 encoding alone is not a sufficient security measure. Rather, what really matters is submitting requests to your email provider through a secure TLS/SSL connection. SMTP connections on port 587 is the default for TLS connections with an email provider. While this choice is safe when TLS is properly secured, consulting the official documentation of your email service provider will give you a more detailed and specific answer on how to interface with their SMTP services securely.

Send a test email to ensure your SMTP credentials work, then specify a recipient email that you have access to, such as your personal email:

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

This test email may take a minute to arrive, depending on your email service. Again, you can return later to change your SMTP credentials in your generated Mastodon configuration file.

Finalizing your Configuration

Next, you are prompted to save your configuration. Mastodon will then use it to create your database:

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!

After, you are prompted to compile Mastodon’s CSS and JavaScript assets. Note the warning about time and resource consumption:

The final step is compiling CSS/JS assets. This may take a while and consume a lot of RAM. Compile the assets now? Yes Running `RAILS_ENV=production rails assets:precompile` ... yarn install v1.22.19 [1/6] Validating package.json... [2/6] Resolving packages... [3/6] Fetching packages... [4/6] Linking dependencies... . . . All done! You can now power on the Mastodon server

Your Mastodon server is now prepared, but not running yet. There is another prompt to create an administrator account to log into your Mastodon server:

Do you want to create an admin user straight away? Yes Username: mastodon E-mail: your_email You can login with the password: your_generated_password You can change your password once you login.

Note that you won’t have the option to choose a password for your administrator account right now. You will be given a unique, generated password that you should note elsewhere. Once you gain access to the admin UI, you have the opportunity to change your password.

Open your generated Mastodon configuration file to verify its contents in nano or your preferred text editor:

  1. nano ~/live/.env.production

The contents will be similar to the following:

# Generated with mastodon:setup on 2022-11-22 18:22:25 UTC

# Some variables in this file will be interpreted differently whether you are
# using docker-compose or not.

SMTP_FROM_ADDRESS='Mastodon <notifications@test.do-community.com>'

You can manually edit this file after the interactive setup process. Once you’re done inspecting it, save and close the file. If you are using nano, you can do this with CTRL + X, then when prompted, Y and then Enter.

Step 4 — Configuring Nginx for Mastodon with Certbot and Let’s Encrypt

Your Mastodon application server is currently only accessible locally. To allow access to it through the internet, you need to expose it using a reverse proxy. Nginx is recommended as the reverse proxy to serve your Mastodon application. To learn more on the topic of reverse proxies, you can check out our tutorial on how to configure Nginx as a reverse proxy or our general introduction to proxies.

The Mastodon repository comes with a default Nginx configuration file that you can use, however, you need to make a few changes to match it to your own domain and secure it with Certbot and Let’s Encrypt. Although Mastodon’s provided Nginx file is fully populated with the necessary blocks and directives for a full deployment, its default SSL/TLS settings prevent smooth interaction with Certbot. This step will walk through two rounds of editing the Nginx configuration file to bypass this limitation, before and after usage of Certbot.

First, adjust your firewall settings to allow both HTTP and HTTPS traffic to your Nginx server:

  1. sudo ufw allow 'Nginx Full'

This is necessary for users to access your Mastodon website, but is also required for Certbot to do the necessary verifications for your certificate. Next, copy the provided Nginx configuration from the Mastodon repository:

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

Nginx uses a common practice called symbolic links, or symlinks, to track which of your server blocks are enabled. Creating a symlink is like creating a shortcut on disk, so that you could later delete the shortcut from the sites-enabled directory while keeping the server block in sites-available if you wanted to enable it. Create a link with your newly create file:

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

Now Nginx knows the settings in this configuration file should be used to serve your Mastodon website. However, you haven’t made the necessary changes to your Nginx configuration. Open your copied configuration file with your preferred text editor:

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

You need to ensure that the server_name directive points towards your domain, and the www. version of your domain. There are two instances of server_name, one in the server block listening on port 80 for HTTP, and a second one in the block listening on port 443 for HTTPS. Make sure both server_name directives point to your domain.

Additionally, you need to comment out the listen directive in the second server block by adding a # symbol to the start of the line. With your SSL certificate not being set up yet, having an ssl parameter for this listen directive will cause Nginx to detect this configuration as invalid. This means Certbot will not create a certificate for you. To fix this, temporarily comment out this directive and re-enable it after you create your certificate:

. . .
server {
  listen 80;
  listen [::]:80;
  server_name your_domain www.your_domain;
  root /home/mastodon/live/public;
  location /.well-known/acme-challenge/ { allow all; }
  location / { return 301 https://$host$request_uri; }

server {
   # listen 443 ssl http2;
   # listen [::]:443 ssl http2;
  server_name your_domain www.your_domain;
. . .

When you’re done, save and close the file. Now you are ready to create your certificates for secure SSL/TLS access. Because you are using Mastodon’s default Nginx configuration file which is pre-populated, your Certbot command is called with certonly. This allows you to manually configure the configuration file. Otherwise, Certbot may make assumptions about your Nginx environment that are not compatible with Mastodon:

  1. sudo certbot certonly --nginx -d your_domain -d www.your_domain
. . . IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/your_domain/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/your_domain/privkey.pem . . .

Take note of the path of your generated certificate and key files. You need to add this to your configuration file. Open your configuration file with your preferred text editor again:

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

Recall the listen directives you commented out before for port 443. You can now safely uncomment them. Previously, these lines would cause an error due to the absence of certificates. With your newly created certificates through Certbot, these lines are now valid.

Additionally, uncomment the ssl_certificate and ssl_certificate_key directives in the same block. Make sure it matches the file paths to the certificates generated earlier by Certbot:

. . .
server {
   listen 443 ssl http2;
   listen [::]:443 ssl http2;
  server_name your_domain www.your_domain;
. . . 
  # Uncomment these lines once you acquire a certificate:
   ssl_certificate 	/etc/letsencrypt/live/your_domain/fullchain.pem;
   ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;
. . .

Save your file and exit the text editor. Verify that your Nginx configuration file is valid with the following command:

  1. sudo nginx -t

Finally, restart Nginx to apply the changes:

  1. sudo systemctl reload nginx

Your Mastodon server is now being served by Nginx, but you still need to set up some services before checking out your website.

Step 5 — Setting Up Mastodon Services

Mastodon is composed of three system services to maintain functionality and uptime: mastodon-web, mastodon-sidekiq, and mastodon-streaming. This allows Mastodon to always restart and keep alive the web application and asynchronous task scheduling. Mastodon comes with these services, and you need to put them in the right place and enable them.

First, copy the services from the Mastodon source:

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

These files assume that everything is installed with defaults in mind, such as using mastodon as your user. If you used anything that differed from the defaults or the recommendations of this tutorial, you can open these files in your preferred text editor and check for any usernames or paths that need to be changed:

  1. sudo nano /etc/systemd/system/mastodon-*.service

If you followed the steps in this tutorial, you won’t need to change anything. After you have inspected your files, close them and proceed to activating these services. First, you need to call daemon-reload to get these recognized:

  1. sudo systemctl daemon-reload

Then you can enable your newly recognized services:

  1. sudo systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming
Created symlink /etc/systemd/system/multi-user.target.wants/mastodon-web.service → /etc/systemd/system/mastodon-web.service.
Created symlink /etc/systemd/system/multi-user.target.wants/mastodon-sidekiq.service → /etc/systemd/system/mastodon-sidekiq.service.
Created symlink /etc/systemd/system/multi-user.target.wants/mastodon-streaming.service → /etc/systemd/system/mastodon-streaming.service.

Your Mastodon installation is now complete. You can open Mastodon in your browser by going to https://your_domain. Note, that your first attempt opening Mastodon in your browser will trigger some backend initializations that may not be complete by the time page loads—resulting in an error such as We’re sorry, but something went wrong on our end. In this scenario, wait for a few seconds, then refresh the browser while holding Shift to perform a hard refresh. This will solve the issue, and only occurs the very first time Mastodon is loaded:

Mastodon Homepage
Mastodon Homepage

You can use the administrator username and generated password from earlier to log in and get started.


In this tutorial, you set up your own Mastodon server. This included setting up the databases and the web server with reverse proxy, along with all the requirements and dependencies specific to Mastodon. Within Mastodon you set up the email, storage and assets, before creating your first administrator account. Finally, you secured your setup with SSL/TLS using Certbot and Let’s Encrypt.

It is recommended that you now change your password and the administrative settings on your new Mastodon server. To learn about how to use your new Mastodon instance and explore its features, you can check out Steps 4 through 6 of our How to Install Mastodon with DigitalOcean Marketplace 1-Click tutorial.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us

About the authors
Default avatar
Tony Tran


Default avatar

Senior Manager, DevEd

Open source advocate and lover of education, culture, and community.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

  1. bundle install - failed.
  2. apt install ruby-dev fixed issue

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Featured on Community

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel