The setup steps for running your own Mastodon server are excellent. What follows here are the changes I made for the way that I run things.
In keeping with my approach of making things inexpensive and easy, while still scalable, I run the following services on the host OS directly (i.e. not in a Docker container):
Plus I run one service in Docker, but outside of the provided docker-compose
approach. Elasticsearch runs separately.
These all have one thing in common: they are stateful services, and can be called a database of a sort. While I can certainly have operated them inside of a container, I wanted to keep the stateful and stateless components separate so I can treat them however is best going-forward.
Starting with the default docker-compose.yml
file, and having moved some services right to the host, means my version of the file becomes smaller.
version: '3'
services:
web:
image: tootsuite/mastodon
restart: always
env_file: .env.production
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
networks:
- external_network
- internal_network
healthcheck:
# prettier-ignore
test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:3000/health || exit 1']
ports:
- '127.0.0.1:3000:3000'
volumes:
- ./public/system:/mastodon/public/system
streaming:
image: tootsuite/mastodon
restart: always
env_file: .env.production
command: node ./streaming
networks:
- external_network
- internal_network
healthcheck:
# prettier-ignore
test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1']
ports:
- '127.0.0.1:4000:4000'
sidekiq:
image: tootsuite/mastodon
restart: always
env_file: .env.production
command: bundle exec sidekiq
networks:
- external_network
- internal_network
volumes:
- ./public/system:/mastodon/public/system
healthcheck:
test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"]
networks:
external_network:
internal_network:
internal: true
With this done I can nuke and recreate any single service easily, such as like this:
$ docker-compose down
Or just restart a single service:
$ docker-compose stop sidekiq
$ docker-compose start sidekiq
Basically, use Docker for what it's awesome for, and consider running the stateful stuff separately. Or not. This isn't a choice that makes or breaks your system
.env.production
fileWhile I cannot paste my entire config file here, I can share the minor changes I made that work well.
SMTP_FROM_ADDRESS
is set!VAPID_PRIVATE_KEY
and VAPID_PUBLIC_KEY
set, and unique values for each.OTP_SECRET
is necessary for MFA - and you do use 2FA, right?INFO
by default, which is too chatty IMHO. You can make your container logs quieter with these lines:LOG_LEVEL=warn
RAILS_LOG_LEVEL=warn
tootctl
There are some commands that you may need to run using tootctl
- the command line interface for Mastodon. I keep a copy of the latest release checked-out from Github, but do not run tootctl
from there. Instead, I take advantage of the runtime environment in the stateless docker containers. This way I can run any tootctl
commands I need in this way:
docker exec -it live_web_1 bin/tootctl media remove --days 7
docker exec live_web_1 bin/tootctl preview_cards remove --days 7
I keep to the default sidekiq worker count of five, though I hear about other people needing more. If you do, then just change this line in `docker-compose.yml':
command: bundle exec sidekiq
To this:
command: bundle exec sidekiq -c <NUMBER_OF_WORKERS>
And then recreate your container with these steps:
docker-compose stop sidekiq
docker-compose rm sidekiq
docker-compose up -d sidekiq