Installing a Mastodon Community on Ubuntu Bionic

Mastodon Overview

Mastodon is an open-source, self-hosted, social media and social networking service. It allows the hosting of your own instances which may have their own code of conduct, terms of service and moderation policies. There is no central server and Mastodon instances are connected as a federated social network, allowing users from different instances to interact with each other. The platform provides privacy features allowing users to adjust the privacy settings of each of their posts.

Mastodon provides the possibility to use S3 compatible Object Storage to store media content uploaded to instances, making it flexible and scalable.

As there is no central server, may choose to join or leave an instance according to its policy without actually leaving Mastodon Social Network. Mastodon is a part of Fediverse, allowing users to interact with users on other platforms that support the same protocol for example: PeerTube, Friendica and GNU Social.

Requirements

  • You have an account and are logged into console.scaleway.com
  • You have configured your SSH Key
  • You have a cloud compute instance running on Ubuntu Bionic Beaver$
  • You have a domain name or subdomain pointing to the instance

Installing Mastodon

Installation Prework

1 . Connect to your compute instance via SSH.

2 . Update the APT packet cache and the software already installed on the instance:

apt update && apt upgrade -y

3 . Add the required additional repositories to the instance and update the apt packet cache:

add-apt-repository multiverse
add-apt-repository restricted
apt update

4 . Another external repository is required to install the required version of Node.js, install it by running the following commands:

apt install curl -y
curl -sL https://deb.nodesource.com/setup_8.x | bash -

5 . Mastodon uses the Yarn packet manager. Install the repository for the required version of Yarn by running the following commands:

curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
apt update

6 . Mastodon depends on various other packages, which have to be installed before the installation of the software:

  • Imagemagick for image related operations
  • FFmpeg for conversion of GIFs to MP4s
  • Protobuf with libprotobuf-dev and protobuf-compiler, used for language detection
  • Nginx as frontend web server
  • Redis for its in-memory data structure store
  • PostgreSQL is used as SQL database for Mastodon
  • Node.js is used for Mastodon’s streaming API
  • Yarn is a Node.js package manager

As well as some other -dev packages and g++ - These packages are required for the compilation of Ruby using ruby-build.

Install them via the apt packet manager:

apt install 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 libgdbm5 libgdbm-dev nginx redis-server redis-tools postgresql postgresql-contrib certbot yarn libidn11-dev libicu-dev ruby-dev -y

7 . Create a user under which the mastodon service will run:

adduser mastodon

8 . Log into the mastodon user account and enter into the home directory of the user:

su mastodon
cd

9 . Setup rbenv and ruby-build:

git clone https://github.com/rbenv/rbenv.git ~/.rbenv
cd ~/.rbenv && src/configure && make -C src
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
# Restart the users shell
exec bash
# Check if rbenv is correctly installed
type rbenv
# Install ruby-build as a rbenv plugin
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build

10 . Install and enable the Ruby version that is used by Mastodon. This step may last some time:

rbenv install 2.5.1
rbenv global 2.5.1

Once this is done, you can switch back into the root account by typing exit.

Configuring PostgreSQL

Mastodon requires access to a postgreSQL database. Change into the postgres user account, run psql and create a database:

su postgres
psql

In the following prompt create the database and exit it:

CREATE USER mastodon CREATEDB;
\q

Leave the postgres user account and switch back to the root account by typing exit.

Downloading Mastodon

1 . Switch into the mastodon user account:

su mastodon

2 . Enter the users home directory and clone the Mastodon Git repository into the directory live:

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

3 . Checkout to the latest stable branch

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

4 . Install bundler and use it to install the rest of the Ruby dependencies:

gem install bundler
bundle install -j$(getconf _NPROCESSORS_ONLN) --deployment --without development test

5 . Use yarn to install the node.js dependencies:

yarn install --pure-lockfile

6 . Exit back to the root account by typing exit.

Configuring Nginx

1 . Open a new file in nano or your favourite text editor to create a new nginx configuration:

nano /etc/nginx/sites-available/example.com.conf

Important: Replace example.com in the file name with your domain or subdomain. Replace it also with your domain in all following occurences.

2 . Copy & paste the following content into the file and make edits when needed:

map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

server {
  listen 80;
  listen [::]:80;
  server_name example.com;
  root /home/mastodon/live/public;
  # Useful for Let's Encrypt
  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 example.com;

  ssl_protocols TLSv1.2;
  ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:10m;

  ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

  keepalive_timeout    70;
  sendfile             on;
  client_max_body_size 80m;

  root /home/mastodon/live/public;

  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

  add_header Strict-Transport-Security "max-age=31536000";

  location / {
    try_files $uri @proxy;
  }

  location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) {
    add_header Cache-Control "public, max-age=31536000, immutable";
    try_files $uri @proxy;
  }

  location /sw.js {
    add_header Cache-Control "public, max-age=0";
    try_files $uri @proxy;
  }

  location @proxy {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";
    proxy_pass_header Server;

    proxy_pass http://127.0.0.1:3000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  location /api/v1/streaming {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";

    proxy_pass http://127.0.0.1:4000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  error_page 500 501 502 503 504 /500.html;
}

Save the file by pressing on CTRL+O, then exit nano by pressing on CTRL+X.

3 . Activate the new configuration:

ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/example.com.conf

Requesting a Let's Encrypt Certificate

1 . Stop Nginx before requesting the certificate:

systemctl stop nginx

2 . Request a certificate by using certbot with TLS SNI validation in standalone mode:

certbot certonly --standalone -d example.com

3 . Restart Nginx:

systemctl start nginx

4 . Renew the certificate with the webroot method:

certbot certonly --webroot -d example.com -w /home/mastodon/live/public/

When asked to keep or to renew the certificate, select renew.

5 . As Let’s Encrypt have a validity of 90 days, a cron-job can be used to renew them and to restart nginx automatically. Create a new file and open it in a text editor like nano:

nano /etc/cron.daily/letsencrypt-renew

6 . Copy the following content into the file, save it and exit nano:

#!/usr/bin/env bash
certbot renew
systemctl reload nginx

7 . Allow execution of the script and restart the cron daemon. It will run the script daily:

chmod +x /etc/cron.daily/letsencrypt-renew
systemctl restart cron

Configuring the Mastodon Application

1 . Enter the mastodon user account:

su mastodon

2 . Change into the /home/mastodon/live directory and run the Mastodon installer:

cd /home/mastodon/live
RAILS_ENV=production bundle exec rake mastodon:setup

The interactive installer guides through the setup process.

When asked enter the domain name or subdomain of the instance. When asked to use Docker choose No. Most of the other values are already pre-filled with the correct settings. Edit them if required for your setup.

To setup Mastodon with Object Storage choose Amazon S3 as service provider and enter the following information for the account. A valid API-Token is required for the configuration with Object Storage.

When asked, enter the details as following:

Provider Amazon S3
S3 bucket name: [scaleway_bucket_name]
S3 region: nl-ams
S3 hostname: s3.nl-ams.scw.cloud
S3 access key: [scaleway_access_key]
S3 secret key: [scaleway_secret_key]

Once the configuration is complete, the installer will start to compile the application. This may take some time and consume a lot of RAM.

3 . Type exit to switch back into the root account.

Creating Systemd Scripts

Systemd scripts are used to manage services on Ubuntu systems. Three different scripts are required for Mastodon.

1 . Open a text editor and create a new file for the Mastodon web service:

nano /etc/systemd/system/mastodon-web.service

2 . Copy the following content into the file, save it and quit the text editor:

[Unit]
Description=mastodon-web
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="PORT=3000"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec puma -C config/puma.rb
ExecReload=/bin/kill -SIGUSR1 $MAINPID
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target

3 . Create another file for the background queue service:

nano /etc/systemd/system/mastodon-sidekiq.service

4 . Copy the following content into the file, save it and quit the text editor:

[Unit]
Description=mastodon-sidekiq
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="DB_POOL=5"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 5 -q default -q push -q mailers -q pull
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target

5 . Create a systemd script for streaming API service:

/etc/systemd/system/mastodon-streaming.service

6 . Enable all three services:

systemctl enable /etc/systemd/system/mastodon-*.service

7 . Start the Mastodon services:

systemctl start mastodon-*.service

8 . Verify if all services are running:

systemctl status mastodon-*.service

If everything is running, open a web browser and go to your domain name. You will see the home page of your Mastodon instance:

Mastodon Home Page

You can login with the admin account that you have created during the installation to configure additional parameters of your instance, link the instance with another one to join a federated network, create another user account and start sharing posts and photos on your timeline. If configured with Object Storage, all files uploaded to the instance are automatically stored in the Object Storage bucket and embedded in the users timeline:

Mastodon Timeline

For more information and advanced configuration of Mastodon, you may refer to the official documentation.

Discover a New Cloud Experience

Deploy SSD Cloud Servers in seconds.