How set up Mastodon on a Self-Managed VPS
Mastodon is an open-source social network. Users can create their own servers and operate a microblogging service based around a timeline, similar to Twitter. These servers are often called ‘instances’.
It benefits from being ad-free and wholly managed and moderated by its users: it’s decentralized.
So we’ve created this guide on how set up a Mastodon instance on a Self-Managed VPS. At minimum, we would recommend setting up a 2-Core Self-Managed VPS on Ubuntu 22.04 - this can be done on our self-managed VPS.
In order to begin setting up Mastodon, you’ll need to first make sure that your Self-Managed VPS is set up on the correct operating system (OS). This guide will be using Ubuntu 22.04, which we recommend using for your installation. You may need to modify the commands that follow if you decide to go with a different OS.
Depending on the number of updates required by your system, you may need to reboot before proceeding. Once done and you’re all up to date, these instructions should help you get your Mastodon instance up and running in an hour.
Connect via SSH and run updates
To get started with setting up Mastodon, you’ll need to first connect to your VPS using SSH. If you’re unfamiliar with this process, we have a full guide on how to do so available here - https://www.20i.com/support/ssh/connect-vps-ssh
Once you’ve connected to your VPS, you should see something similar to the following:
20i Support:~$ ssh firstname.lastname@example.org email@example.com's password: Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-50-generic x86_64) Last login: Wed Nov 16 15:05:51 2022 root@vps-a1n2c3d4:~#
If you do, you’ll be signed into your VPS as the root user.
From here, you’ll want to make sure you have the latest system packages by running the following commands:
apt-get update -y apt-get upgrade -y
This will ensure your VPS is up-to-date. If your VPS requires a reboot after the update, you can do so via the Manage VPS area in your My20i account.
Secure your server
Next, you’ll want to secure your VPS and protect it from potential brute force attacks, as well ensuring that only SSH, HTTP and HTTPS ports are open. To do this, first install fail2ban:
apt install fail2ban
Once that’s completed, you’ll want to edit the file /etc/fail2ban/jail.local and add the following:
[DEFAULT] destemail = firstname.lastname@example.org sendername = Fail2Ban [sshd] enabled = true port = 22 [sshd-ddos] enabled = true port = 22
Replacing the email email@example.com with your email. Once that’s configured, restart fail2ban using the following command:
systemctl restart fail2ban
You’ll then want to look into adding some firewall protection to close off any ports except for SSH, HTTP and HTTPS access. To do this, first install iptables-persistent:
apt install -y iptables-persistent
Then, edit the file /etc/iptables/rules.v4 and add the following code:
*filter # Allow all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0 -A INPUT -i lo -j ACCEPT -A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT # Accept all established inbound connections -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Allow all outbound traffic - you can modify this to only allow certain traffic -A OUTPUT -j ACCEPT # Allow HTTP and HTTPS connections from anywhere (the normal ports for websites and SSL). -A INPUT -p tcp --dport 80 -j ACCEPT -A INPUT -p tcp --dport 443 -j ACCEPT # Allow SSH connections # The -dport number should be the same port number you set in sshd_config -A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT #Allow ping -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT # Log iptables denied calls -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7 # Reject all other inbound - default deny unless explicitly allowed policy -A INPUT -j REJECT -A FORWARD -j REJECT COMMIT
On your next load time, the above configuration will be loaded. However, if you want to load this configuration now, you can use the command:
iptables-restore < /etc/iptables/rules.v4
Install Mastodon dependencies
Now that the VPS is set up and has some baseline security, we can now begin working on installing Mastodon. We’ll first need to make sure curl, wget, gnupg, apt-transport-https, lsb-release, make and ca-certificates are installed as these are required to set up Mastodon, so add these dependencies with the following command:
apt install -y curl wget gnupg apt-transport-https lsb-release make ca-certificates
You’ll also want to add the following dependencies, which will be used by Mastodon and include core services such as NGINX, Redis, and PostgreSQL:
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
With these added, we’ll next need to configure Node.js and Yarn.
Install Node.js and Yarn
Setting up Node.js for Mastodon will first require you to add the nodesource repo – you can do so with this command:
curl -sL https://deb.nodesource.com/setup_16.x | bash -
You can then install nodejs using apt-get:
apt-get install nodejs -y
Once this is completed, you’ll have access to the command corepack, which can be used to set up and enable Yarn:
corepack enable yarn set version stable
And that’s set. Now, we need to set up a user for your Mastodon server on your VPS.
Create a new system user
Mastodon will require a user on the server to grant it access to the services it requires. You can add one using the command below:
adduser --disabled-login --gecos 'Mastodon Server' mastodon
You’ll want to now sign in as that user – this will test to make sure it’s set up correctly, and allow you to proceed with the next step of installing Ruby. To sign in the user, simply run the command:
su - mastodon
If done correctly, you should see a different username in your bash area like so:
While logged in as the Mastodon user, you’ll need to set up the rbenv repo for Ruby. This can be done with the git clone command below:
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
Then navigate to the directory .rbenv and set this up – these commands do this:
cd ~/.rbenv && src/configure && make -C src echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc echo 'eval "$(rbenv init -)"' >> ~/.bashrc exec bash
You can then clone Ruby’s main build to your VPS using git clone with this command:
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
You now have all you need to install Ruby. Using the built-in RUBY_CONFIGURE_OPTS that was added with the git, install Ruby 3.0.4.
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.0.4
You’ll now want to set the global Ruby version as 3.0.4, and then update gem with these commands:
rbenv global 3.0.4 gem update –system
Finally, install bundler, which will be required to complete your Mastodon installation later on.
gem install bundler --no-document
You will now have Ruby fully installed and ready to go. You can check this by running the following command to check the current Ruby version:
Once you’re happy and ready to move on, simply use the exit command to log out of the Mastodon user and return to root:
You’ve already installed base PostgreSQL, but you also need to add their latest repository. You can do so with the following command:
wget -O /usr/share/keyrings/postgresql.asc https://www.postgresql.org/media/keys/ACCC4CF8.asc echo "deb [signed-by=/usr/share/keyrings/postgresql.asc] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/postgresql.list
Once that’s done, you’ll need to sign into the PostgreSQL user that will have been created by the command. You can do so much as you did with the Mastodon account, with the following command:
su – postgres
You can then boot PostgreSQL to access your database:
In this database, we’ll want to set up a user for Mastodon, which will allow it to access the database, create tables and update any data for functionality. You can do so with the following SQL command:
CREATE USER mastodon CREATEDB;
Now that’s created, we can close PostgreSQL. To do so, enter the command exit twice – first to close the connection to the database, then again to return to the root user.
You’ll now want to install and configure your Mastodon setup. You’ll need to swap back to Mastodon’s user for this next step, so do so as you did before:
su - mastodon
First, we’re going to grab the latest Mastodon version from git with git clone, as we did with Ruby:
git clone https://github.com/tootsuite/mastodon.git ~/live
Then navigate to the live directory:
And use git to ‘checkout’ the repository’s latest branch. You can do so with the following command:
git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)
Now that we have this downloaded, we can enable development, and use bundle and yarn to install the remaining files. You’ll want to use the following commands for this:
dle config deployment 'true' bundle config without 'development test' bundle install -j$(getconf _NPROCESSORS_ONLN) yarn install --pure-lockfile
Now that we have all the files we need, we can use Ruby to initiate Mastodon’s setup wizard:
RAILS_ENV=production bundle exec rake mastodon:setup
If you’ve done everything correctly, you’ll get the following output – “Mastodon will step you through each of the requirements and ask for answers”. Use the below as a guide for what to add, replacing the domain name with what domain you want to use for Mastodon and your own email. For options like PostgreSQL’s host, port and database and Redis’ host and port, the wizard should autofill these selections. You’ll want to leave the passwords as blank for these unless you’ve added a password for these yourself.
Your instance is identified by its domain name. Changing it afterward will break things. Domain name: mastodon.mydomain.com Single user mode disables registrations and redirects the landing page to your public profile. Do you want to enable single user mode? No Are you using Docker to run Mastodon? no 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 host: localhost Redis port: 6379 Redis password: Redis configuration works! Do you want to store uploaded files on the cloud? No Do you want to send e-mails from localhost? yes E-mail address to send e-mails "from": Mastodon
Send a test e-mail with this configuration right now? no 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! All done! You can now power on the Mastodon server Do you want to create an admin user straight away? Yes Username: admin E-mail: firstname.lastname@example.org You can login with the password: [PASSWORD] You can change your password once you login.
Note the admin details you’re provided by the wizard – you’ll need them to log into Mastodon later!
Once you’ve got all the information you need and you’ve made a note of the username and password of the admin user, you can exit the Mastodon user on your VPS with exit, as before.
Configure Nginx and add an SSL to your installation
We’re getting close to the end of our installation now – we have Mastodon installed and configured, and our requirements are all set. We now need to link up the domain we’re using to the VPS, install an SSL and configure NGINX to allow it to serve Mastodon.
First, point the domain you wish to use for Mastodon to your VPS. Your VPS IP can be found in your hosting control panel, on the Manage VPS page in your My20i account. Simply select Options, then Manage on the VPS you’re using and you’ll see this available under VPS Information on the right of the screen.
Your domain registry should have instructions on how to update the DNS of your domain – if your domain is registered with 20i and the nameservers are on our StackDNS nameservers, you can do so with the following steps:
- Log into My20i and navigate to Manage Domains.
- Search for your domain, and hit Options, then Manage DNS.
- Using the fields provided at the bottom of the DNS page, enter your record.
- Enter your subdomain in the ‘Name’ field. If you’re using your main domain, leave this area blank.
- Select A from the dropdown box.
- Insert the IP of your VPS into the data field.
- Hit Update DNS, and once propagated, your domain should be properly pointing to your site.
Once that’s pointing to the site you can use certbot, which we installed earlier, to install a Let’s Encrypt free SSL on the domain, and configure NGINX to use it:
certbot --nginx -d mastodon.example.com
Then take the Mastodon NGINX config file from their file setup and copy this over to NGINX. You can do so with the following command:
cp /home/mastodon/live/dist/nginx.conf /etc/nginx/sites-available/mastodon
You should then use a symlink to set up the virtual host configuration file with this command:
ln -s /etc/nginx/sites-available/mastodon /etc/nginx/sites-enabled/
Then, you’ll need to update the domain in the virtual host configuration file to the domain you wish to use, replacing mastodon.mydomain.com in the below code with the domain you want to add:
sed -i 's/example.com/mastodon.mydomain.com/g' /etc/nginx/sites-enabled/mastodon
After this has done, remove the NGINX default configuration file to prevent the NGINX default page loading on your site:
rm -v /etc/nginx/sites-enabled/default
Lastly, open your mastodon file in sites-enabled with a file editor such as vim:
You should see two lines commented out in this file, like so:
# Uncomment these lines once you acquire a certificate: # ssl_certificate /etc/letsencrypt/live/mastodon.mydomain.com/fullchain.pem; # ssl_certificate_key /etc/letsencrypt/live/mastodon.mydomain.com/privkey.pem;
Remove the hashes before ‘ssl_certificate’ and ‘ssl_certificate_key’ to uncomment these lines. Once done, save and close the file (you can do this in vim by entering :x or :wq) and then restart nginx.
systemctl restart nginx
You’ve now fully installed and configured NGINX to serve Mastodon.
Create a System service for Mastodon
Mastodon requires a few services to launch with the VPS whenever it reboots. You can configure this by first copying the systemd service templates from the Mastodon directory to your system folder with these commands:
cp /home/mastodon/live/dist/mastodon-web.service /etc/systemd/system/ cp /home/mastodon/live/dist/mastodon-sidekiq.service /etc/systemd/system/ cp /home/mastodon/live/dist/mastodon-streaming.service /etc/systemd/system/
Now that the system services are in place, you can start them up and enable them – this will ensure that they launch at startup:
systemctl start mastodon-web systemctl start mastodon-sidekiq systemctl start mastodon-streaming systemctl enable mastodon-web systemctl enable mastodon-sidekiq systemctl enable mastodon-streaming
To make sure that this has been configured correctly, you can use the following command to check the status of these services:
systemctl status mastodon-web mastodon-sidekiq mastodon-streaming
Lastly, you’ll want to make sure that Mastodon has all the right permissions to access the core files. So, run the following commands to set the permissions.:
chown mastodon:www-data /home/mastodon/ chmod 0710 -v /home/mastodon/
You’ve successfully installed Mastodon, and should now be able to access it from your site!
Access the Mastodon interface
The final steps are now to access the site itself. Open your web browser, and navigate to your domain. You should be greeted with Mastodon’s Dashboard.
You can log in using the ‘Sign in’ option on the right. The credentials to log in are the admin details you noted earlier while running the configuration wizard for Mastodon.
With that, you’ve fully set up a Mastodon service on your own VPS and domain, and can freely post and configure the setup to customize its appearance.