Hosting your own mastodon instance via docker-compose

Mastodon mascotteRecently I’ve setup an invite-only mastodon instance as a private space for

friends and family. While I am still evaluating whether mastodon is the right tool for such a private space, I’d like to share a number of issues I encountered during setup.

Careful with non-official guides

The mastodon documentation focuses on hosting mastodon on a dedicated machine. It is thorough and I would recommend reading through it, even if you do not want to dedicate a separate machine to hosting mastodon. Mastodon also maintains a docker-compose config file, unfortunately the documentation on setting it up appears lackluster. The best guides I’ve found details are a alibaba cloud guide and a howtoforge guide. Note these guides aren’t perfect: the official docs recommend running the latest tagged releases whereas both guides run from the master branch, generating the necessary secrets is done differently than in the official documentation and I also don’t like how they automate certificate renewal.

Issues related to the db service

After initial tweaking of the .env.production file I encountered two issues related to the db service. Fortunately I stumbled upon this stackoverflow answer. I recap my findings belows.

Issue #1

rails aborted! PG::ConnectionBad: could not connect to server: No such file or directory

This is caused by the web service being unable to connect to the database. In my case this was due to an invalid value for DB_HOST  in .env.production. Setting DB_HOST to mastodon_db_1 solved this issue for me. The resulting postgres section looks as follows:

# PostgreSQL
# ----------
DB_HOST=mastodon_db_1
DB_USER=mastodon
DB_NAME=mastodon_production
DB_PASS=xyz
DB_PORT=5432

In the same vain you’ll want to change REDIS_HOST from localhost to mastodon_redis_1.

Issue #2:

Error: Database is uninitialized and superuser password is not specified.
You must specify POSTGRES_PASSWORD to a non-empty value for the
superuser

This is caused by the pg_isready healthcheck failing and can be fixed by setting the necessary env variables in docker-compose.yml. The resulting db compose service looks as follows:

db:
  restart: always
  image: postgres:9.6-alpine
  shm_size: 256mb
  networks:
    - internal_network
  healthcheck:
    test: ["CMD", "pg_isready", "-U", "mastodon", "-d", "mastodon_production"]
  volumes:
    - ./postgres:/var/lib/postgresql/data
  environment:
    POSTGRES_PASSWORD: xyz
    POSTGRES_DB: mastodon_production
    POSTGRES_USER: mastodon

Optional features enabled by default

s3 object storage

This is enabled by default in the sample environment file. If you don’t configure it correctly (or forget to turn it off), you’ll notice that media uploads are failing. The failures are accompanied by the following log message: method=POST path=/api/v2/media format=html controller=Api::V2::MediaController action=create status=500 error='Aws::Sigv4::Errors::MissingCredentialsError: missing credentials,provide credentials with one of the following options.

If you want to store media on local storage, just comment the lines under File Storage in the env file. Do check to ensure that /opt/mastodon/public/system/ in the web container is persisted on the host system (this should be case via the volume defined in the docker-compose.yml).

elastic search

Elastic search is also enabled by default in the sample env file, while it is commented out in the docker-compose.yml file. If you don’t have the es containter running, you’ll notice a large number of sidekiq jobs starting to accumulate in the ‘Retry’ state with the following error message: Faraday::ConnectionFailed: Failed to open TCP connection to localhost:9200 (Cannot assign requested address - connect(2) for "localhost" port 9200). Either enable the es container or comment out ES_ENABLED=true in the ENV file.

My entire ENV file

For completeness you can find my entire .env.production file below, where sensitive entries have been redacted. Note I am currently using mailgun as an SMTP server, as I found sendgrid to be blocked by Spam filters.

# This is a sample configuration file. You can generate your configuration
# with the `rake mastodon:setup` interactive setup wizard, but to customize
# your setup even further, you'll need to edit it manually. This sample does
# not demonstrate all available configuration options. Please look at
# https://docs.joinmastodon.org/admin/config/ for the full documentation.

# Federation
# ----------
# This identifies your server and cannot be changed safely later
# ----------
LOCAL_DOMAIN=social.vdna.be

# Redis
# -----
REDIS_HOST=mastodon_redis_1
REDIS_PORT=6379

# PostgreSQL
# ----------
DB_HOST=mastodon_db_1
DB_USER=mastodon
DB_NAME=mastodon_production
DB_PASS=xyz
DB_PORT=5432

# ElasticSearch (optional)
# ------------------------
# ES_ENABLED=true
# ES_HOST=localhost
# ES_PORT=9200

# Secrets
# -------
# Make sure to use `rake secret` to generate secrets
# -------
SECRET_KEY_BASE=xyz
OTP_SECRET=xyz

# Web Push
# --------
# Generate with `rake mastodon:webpush:generate_vapid_key`
# --------
VAPID_PRIVATE_KEY=xyz
VAPID_PUBLIC_KEY=xyz

# Sending mail
# ------------
SMTP_SERVER=smtp.eu.mailgun.org
SMTP_PORT=587
SMTP_LOGIN=postmaster@mg.social.vdna.be
SMTP_PASSWORD=xyz
SMTP_FROM_ADDRESS=social@mg.social.vdna.be

# File storage (optional)
# -----------------------
#S3_ENABLED=true
#S3_BUCKET=files.example.com
#AWS_ACCESS_KEY_ID=
#AWS_SECRET_ACCESS_KEY=
#S3_ALIAS_HOST=files.example.com

2 comments

  1. Thank you very much for this very helpful blog post.
    Helped me a lot during initial setup and again for the upgrade to mastodon 4.0.2.

    Best regards
    Martin

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.