Setup a Mastodon instance on Fedora Server
I’ll go through the steps to setup a Mastodon instance on Fedora Server. This guide is based on the original Install from source guide in the Mastodon documentation, but includes Fedora-specific tweaks such as packages, file path differences, and SELinux policies. I’ll first go through prerequistes and basic setup, and then branch off in the style of a choose-your-own-adventure. Section 2 is for installing a new Mastodon instance; Section 3 is for Migrating from an existing Mastodon instance; Section 4 is for setting up Mastodon with Nginx and Certbot; Section 5 is for setting up Mastodon with Caddy; Section 6 covers SELinux policy modules that need to be enabled for some critical services and executables to work.
This guide presumes the following:
- Vanilla Fedora 37 Server install with SELinux in enforcing mode, fail2ban, and firewalld with the HTTP/S ports open.
- Mastodon version 4.0.2
- You have a domain name for hosting the Mastodon instance.
- You know how to configure SMTP, should you want it.
I’ll come back and update the guide as necessary for new releases of the software.
1. Prerequisites and basic setup
Become the root user and install the following packages:
1dnf install postgresql-server postgresql-contrib ImageMagick ImageMagick-devel ffmpeg-free ffmpeg-free-devel libpq libpq-devel libxml2-devel libxslt-devel file git-core '@c-development' '@development-tools' protobuf-devel pkgconf-pkg-config nodejs bison openssl-devel libyaml-devel readline-devel zlib-devel ncurses-devel libffi-devel gdbm-devel redis libidn-devel libicu-devel jemalloc-devel perl-FindBin
Install corepack and set the yarn version:
1npm install -g corepack
2corepack enable
3yarn set version classic
Add the mastodon user, then switch to it:
1adduser -m -U mastodon
2su - mastodon
As the mastodon user, install rbenv and rbenv-build:
1git clone https://github.com/rbenv/rbenv.git ~/.rbenv
2cd ~/.rbenv
3src/configure
4make -C src
5echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
6echo 'eval "$(rbenv init -)"' >> ~/.bashrc
7exec bash
8git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
Install the required Ruby version:
1RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.0.6
2rbenv global 3.0.6
Install bundler:
1gem install bundler --no-document
Return to the root user:
1exit
Setup postgresql:
1postgresql-setup --initdb --unit postgresql
2systemctl enable --now postgresql
Become the postgresql user and run psql:
1su - postgres
1psql
In the psql prompt, create the database role:
1CREATE USER mastodon CREATEDB;
2\q
Go back to the root user:
1exit
Become the mastodon user:
1su - mastodon
Check out the Mastodon code:
1git clone https://github.com/mastodon/mastodon.git live
2cd live
3git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)
Install Ruby and JavaScript dependencies:
Note that the version of NodeJS installed on Fedora uses OpenSSL3, but Mastodon requires a version of Node with OpenSSL1.1. We can remedy this by using
export NODE_OPTIONS=--openssl-legacy-provider
.
1bundle config deployment 'true'
2bundle config without 'development test'
3bundle install -j$(getconf _NPROCESSORS_ONLN)
4export NODE_OPTIONS=--openssl-legacy-provider
5yarn install --pure-lockfile
This is the end of the prerequisites and basic setup. Choose one of the options below to continue.
2. Install a new Mastodon instance
After running the steps from the previous section, we can now run the interactive setup wizard to setup a new Mastodon instance:
1cd /home/mastodon/live
2export NODE_OPTIONS=--openssl-legacy-provider
3RAILS_ENV=production bundle exec rake mastodon:setup
This will:
- Create a configuration file
- Run asset precompilation
- Create the database schema
Choose one of the options below to continue.
3. Migrate from an existing Mastodon instance
After running the steps from the prerequisites and basic setup section, we can now start migrating the data from an existing Mastodon instance.
Run these commands on the old server machine
Stop the mastodon systemd services:
1systemctl stop mastodon-web mastodon-sidekiq mastodon-streaming
Become the mastodon user:
1su - mastodon
Dump the postgresql database to /home/mastodon/mastodon_production.dump
:
1pg_dump -Fc mastodon_production -f mastodon_production.dump
Copy the following files from the old server machine to the same paths on the new server machine using rsync or whatever method you think best:
/home/mastodon/live/public/system
directory, which contains user-uploaded images and videos. This is not required if you’re using S3./home/mastodon/live/.env.production
, which contains the server config and secrets./home/mastodon/mastodon_production.dump
- Your web server configuration
Run these commands on the new server machine
Ensure the Redis server is started:
1systemctl enable --now redis
Become the mastodon user:
1su - mastodon
Create an empty database:
1createdb -T template0 mastodon_production
Import the postgresql database:
1pg_restore -Fc -U mastodon -n public --no-owner --role=mastodon -d mastodon_production mastodon_production.dump
Precompile Mastodon’s assets:
1cd live
2export NODE_OPTIONS=--openssl-legacy-provider
3RAILS_ENV=production bundle exec rails assets:precompile
Rebuild the home timelines for each user:
1RAILS_ENV=production ./bin/tootctl feeds build
Go back to root user:
1exit
As root, start the Mastodon systemd services:
1systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming
You can now update your DNS settings to point to the new server machine, rerun Certbot to update LetsEncrypt, etc. If you still need a web server setup, you can choose one of the options below, otherwise you can continue with section 6. SELinux.
4. Setup with Nginx and Certbot
The Mastodon repository provides an Nginx configuration. On Fedora, the Nginx configuration path is /etc/nginx/conf.d
.
Become root on your Fedora Server and install Nginx and Certbot:
1dnf install nginx certbot python3-certbot-nginx
Copy the Nginx configuration:
1cp -v /home/mastodon/live/dist/nginx.conf /etc/nginx/conf.d/mastodon.conf
Edit /etc/nginx/conf.d/mastodon.conf
and change example.com
in the server_name
directive to your Mastodon domain. You can make any other adjustments you need.
Ensure the syntax of the Nginx configuration is okay:
1nginx -t
To acquire an SSL certificate, ensure the HTTP ports are open in your firewall:
1firewall-cmd --zone=FedoraServer --permanent --add-service=http
2firewall-cmd --zone=FedoraServer --permanent --add-service=https
3firewall-cmd --reload
Now run Certbot to obtain the certificate (change example.com to your domain):
1certbot --nginx -d example.com
Enable and start Nginx:
1systemctl enable --now nginx.service
You can now go to section 6. SELinux
5. Setup with Caddy
Add the Caddy repository and install Caddy:
1dnf install 'dnf-command(copr)'
2dnf copr enable @caddy/caddy
3dnf install caddy
Create or edit the Caddyfile at /etc/caddy/Caddyfile
:
1example.com {
2 @local {
3 file
4 not path /
5 }
6 @local_media {
7 path_regexp /system/(.*)
8 }
9 @streaming {
10 path /api/v1/streaming/*
11 }
12 @cache_control {
13 path_regexp ^/(emoji|packs|/system/accounts/avatars|/system/media_attachments/files)
14 }
15
16 root * /home/mastodon/live/public
17 log {
18 output file /var/log/caddy/mastodon.log
19 }
20
21 encode zstd gzip
22
23 handle_errors {
24 rewrite 500.html
25 file_server
26 }
27
28 header {
29 Strict-Transport-Security "max-age=31536000"
30 }
31 header /sw.js Cache-Control "public, max-age=0"
32 header @cache_control Cache-Control "public, max-age=31536000, immutable"
33
34 handle @local {
35 file_server
36 }
37
38 reverse_proxy @streaming {
39 to http://localhost:4000
40
41 transport http {
42 keepalive 5s
43 keepalive_idle_conns 10
44 }
45 }
46
47 reverse_proxy {
48 to http://localhost:3000
49
50 header_up X-Forwarded-Port 443
51 header_up X-Forwarded-Proto https
52
53 transport http {
54 keepalive 5s
55 keepalive_idle_conns 10
56 }
57 }
58}
To allow Caddy to access files in the user home directory, the executable bit needs to be set on the parent directories of the files being served:
1chmod +x /home/mastodon/live/public
2chmod +x /home/mastodon/live
3chmod +x /home/mastodon
4chmod +x /home
You can now go to section 6. SELinux
6. SELinux
At this point, a web server should be running, but if SELinux is in enforcing mode, you will get a 502 Bad Gateway error if you try to browse to your Mastodon domain. The problem is that SELinux is not allowing the web server daemon to access files in /home/mastodon/live
. This can be verified by running:
1ausearch -m AVC -ts recent
6.1 Nginx
This can be fixed by setting the following SELinux booleans:
1setsebool -P httpd_read_user_content=1
2setsebool -P httpd_enable_homedirs=1
6.2 Caddy
You’ll need to set an SELinux policy to allow Caddy to write to /var/log/caddy
:
module caddy 1.0;
require {
type httpd_log_t;
type httpd_t;
class file write;
}
#============= httpd_t ==============
allow httpd_t httpd_log_t:file write;
Save this to a file named caddy.te
. Now check, compile, and import the module:
1checkmodule -M -m -o caddy.mod caddy.te
2semodule_package -o caddy.pp -m caddy.mod
3semodule -i caddy.pp
Set the SELinux booleans for httpd:
1setsebool -P httpd_read_user_content=1
2setsebool -P httpd_enable_homedirs=1
Restart Caddy.
6.3 bundle
SELinux also denies the /home/mastodon/.rbenv/shims/bundle
executable. This can be verified by looking at journalctl -xeu mastodon-web.service
and ausearch -m AVC -ts recent
.
You’ll need the following SELinux policy for bundle to work:
module bundle 1.0;
require {
type init_t;
type user_home_t;
class file { execute execute_no_trans open read };
}
#============= init_t ==============
allow init_t user_home_t:file { execute execute_no_trans open read };
Save this to a file named bundle.te
. Now check, compile, and import the module:
1checkmodule -M -m -o bundle.mod bundle.te
2semodule_package -o bundle.pp -m bundle.mod
3semodule -i bundle.pp
Restart the Mastodon systemd services:
1systemctl restart mastodon-web mastodon-streaming mastodon-sidekiq
Your Mastodon instance should now be up and running!
Closing
If you have any questions, want to report any errors, or have any suggestions for improving this article, you can find me at the following places. You can also open up an issue in the GitHub interface.
- Mastodon: hyperreal@fedi.hyperreal.coffee
- Matrix: @hyperreal:matrix.envs.net
- IRC: hyperreal on Tilde.chat and Libera.chat
- Email: hyperreal AT fedoraproject DOT org