Setup a Mastodon instance on Fedora Server
2022-12-12
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.
Prerequisites and basic setup
Become the root user and install the following packages:
dnf 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:
npm install -g corepack
corepack enable
yarn set version classic
Add the mastodon user, then switch to it:
adduser -m -U mastodon
su - mastodon
As the mastodon user, install rbenv and rbenv-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
exec bash
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
Install the required Ruby version:
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.0.6
rbenv global 3.0.6
Install bundler:
gem install bundler --no-document
Return to the root user:
exit
Setup postgresql:
postgresql-setup --initdb --unit postgresql
systemctl enable --now postgresql
Become the postgresql user and run psql:
su - postgres
psql
In the psql prompt, create the database role:
CREATE USER mastodon CREATEDB;
\q
Go back to the root user:
exit
Become the mastodon user:
su - mastodon
Check out the Mastodon code:
git clone https://github.com/mastodon/mastodon.git live
cd live
git 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=.
bundle config deployment 'true'
bundle config without 'development test'
bundle install -j$(getconf _NPROCESSORS_ONLN)
export NODE_OPTIONS=--openssl-legacy-provider
yarn install --pure-lockfile
This is the end of the prerequisites and basic setup. Choose one of the options below to continue.
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:
cd /home/mastodon/live
export NODE_OPTIONS=--openssl-legacy-provider
RAILS_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.
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:
systemctl stop mastodon-web mastodon-sidekiq mastodon-streaming
Become the mastodon user:
su - mastodon
Dump the postgresql database to
/home/mastodon/mastodon_production.dump
:
pg_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:
systemctl enable --now redis
Become the mastodon user:
su - mastodon
Create an empty database:
createdb -T template0 mastodon_production
Import the postgresql database:
pg_restore -Fc -U mastodon -n public --no-owner --role=mastodon -d mastodon_production mastodon_production.dump
Precompile Mastodon’s assets:
cd live
export NODE_OPTIONS=--openssl-legacy-provider
RAILS_ENV=production bundle exec rails assets:precompile
Rebuild the home timelines for each user:
RAILS_ENV=production ./bin/tootctl feeds build
Go back to root user:
exit
As root, start the Mastodon systemd services:
systemctl 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.
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:
dnf install nginx certbot python3-certbot-nginx
Copy the Nginx configuration:
cp -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:
nginx -t
To acquire an SSL certificate, ensure the HTTP ports are open in your firewall:
firewall-cmd --zone=FedoraServer --permanent --add-service=http
firewall-cmd --zone=FedoraServer --permanent --add-service=https
firewall-cmd --reload
Now run Certbot to obtain the certificate (change example.com to your domain):
certbot --nginx -d example.com
Enable and start Nginx:
systemctl enable --now nginx.service
You can now go to section SELinux
Setup with Caddy
Add the Caddy repository and install Caddy:
dnf install 'dnf-command(copr)'
dnf copr enable @caddy/caddy
dnf install caddy
Create or edit the Caddyfile at /etc/caddy/Caddyfile
:
example.com {
@local {
file
not path /
}
@local_media {
path_regexp /system/(.*)
}
@streaming {
path /api/v1/streaming/*
}
@cache_control {
path_regexp ^/(emoji|packs|/system/accounts/avatars|/system/media_attachments/files)
}
root * /home/mastodon/live/public
log {
output file /var/log/caddy/mastodon.log
}
encode zstd gzip
handle_errors {
rewrite 500.html
file_server
}
header {
Strict-Transport-Security "max-age=31536000"
}
header /sw.js Cache-Control "public, max-age=0"
header @cache_control Cache-Control "public, max-age=31536000, immutable"
handle @local {
file_server
}
reverse_proxy @streaming {
to http://localhost:4000
transport http {
keepalive 5s
keepalive_idle_conns 10
}
}
reverse_proxy {
to http://localhost:3000
header_up X-Forwarded-Port 443
header_up X-Forwarded-Proto https
transport http {
keepalive 5s
keepalive_idle_conns 10
}
}
}
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:
chmod +x /home/mastodon/live/public
chmod +x /home/mastodon/live
chmod +x /home/mastodon
chmod +x /home
You can now go to section SELinux
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:
ausearch -m AVC -ts recent
Nginx
This can be fixed by setting the following SELinux booleans:
setsebool -P httpd_read_user_content=1
setsebool -P httpd_enable_homedirs=1
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:
checkmodule -M -m -o caddy.mod caddy.te
semodule_package -o caddy.pp -m caddy.mod
semodule -i caddy.pp
Set the SELinux booleans for httpd:
setsebool -P httpd_read_user_content=1
setsebool -P httpd_enable_homedirs=1
Restart Caddy.
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:
checkmodule -M -m -o bundle.mod bundle.te
semodule_package -o bundle.pp -m bundle.mod
semodule -i bundle.pp
Restart the Mastodon systemd services:
systemctl 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: https://fedi.hyperreal.coffee/hyperreal
- IRC: hyperreal on Tilde.chat and Libera.chat
- Email: hyperreal AT fedoraproject DOT org