In followup to my last article I wanted to document all the changes I have made to run Mastodon on relatively minimal resources. With the changes below Mastodon averages about 1GB of RAM for running processes, suggesting a box with about 1.5GB would be sufficient.
I won’t touch on Postgres here since the topic is pretty well explored by other blogs and tools. As my other article says I am currently using a 1GB box to host postgres, but 512 would plausibly work.
Everything below assumes that your Mastodon instance followed the install from source guide, and runs using systemd on linux.
Puma
Mastodon runs its primary web service via Puma using a default configuration of two workers with five threads each. This configuration is able to handle a considerable amount of traffic, and frankly far more than a single user instance needs.
To reduce the memory required, Puma can be run in “non-clustered” mode with only one process (rather than the three run
by default). To make this change an environmental variable must be inserted into /etc/systemd/system/mastodon-web.service
.
11a12
> Environment="WEB_CONCURRENCY=0"
The environmental variable cannot be placed in .env.production
as that is not loaded prior to Puma instantiation and
will therefore be ignored. The change must be in the systemd configuration.
Once the change is made run systemctl daemon-reload
and systemctl restart mastodon-web
.
Sidekiq
Mastodon runs all of it’s background tasks through a job system called Sidekiq. By default this is configured with 25 workers, each with a connection to the database. Again, this is far more than a typical single-user instance needs, so we can reduce it. At the same time, we can reduce the DB connection pool as it should always match the worker count.
The precise value to use is difficult to guess, so trial and error is recommended. I am currently using ten workers, but
a smaller value is likely fine. To make this change several environmental variables need to be changed in
/etc/systemd/system/mastodon-sidekiq.service
.
10c10
< Environment="DB_POOL=25"
---
> Environment="DB_POOL=10"
13c13
< ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 25
---
> ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 10
I also tweaked the nice
and oom_score_adjust
values for Sidekiq as it should never be allowed to crash the system
due to load. With the changes below (inserted into the same file as above) Sidekiq will run at a lower CPU priority
and be the first process killed due to memory pressure.
50a51,53
> OOMScoreAdjust=1000
> Nice=10
Once the change is made run systemctl daemon-reload
and systemctl restart mastodon-sidekiq
.
To reduce memory sprawl, I also restart sidekiq hourly. The following line, when added to the root crontab, will work:
@hourly systemctl restart mastodon-sidekiq
nginx
For nginx, I enabled gzip_static
in nginx. Mastodon pre-compresses all static assets but doesn’t use them by default
so it is incumbent on the user to enable this setting.
Happily, the change is quite easy, just add the following to your /etc/nginx/sites-enabled/mastodon
config.
46a51
> gzip_static on;
Nightly Cleanup
Finally, I run the various cleanup tasks nightly using the script below. This script is stored at /home/mastodon/nightly.sh
and is executed using the crontab also below. These scripts remove files from media storage and clean up the database.
Before using this script, consider the values that you feel are appropriate for deletion. Mine may be higher or lower
than you would want. Also note that the days
argument for preview_cards doesn’t appear to work, so I think it always deletes data after
seven days.
#!/usr/bin/env bash
set -uexo pipefail
run_all() {
export RAILS_ENV=production
export PATH=/home/mastodon/.rbenv/shims:/home/mastodon/.rbenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
date
nice /home/mastodon/live/bin/tootctl media remove --days=30 --concurrency=1 --prune-profiles
date
nice /home/mastodon/live/bin/tootctl media remove --concurrency=1 --days=7
date
nice /home/mastodon/live/bin/tootctl preview_cards remove --concurrency=1 --days=7
date
}
run_all | tee -a ~/nightly.log
0 10 * * * /home/mastodon/nightly.sh