DOKPLOY-GUIDE 10 min read fordnox

Deploy Mastodon with Dokploy: Docker Compose Setup Guide

Step-by-step guide to deploying Mastodon social network on your VPS using Dokploy and Docker Compose. Includes PostgreSQL, Redis, Sidekiq workers, and SSL configuration.


Deploy Mastodon with Dokploy

Dokploy is an open-source server management platform that simplifies deploying Docker Compose applications on your VPS. It handles reverse proxy configuration, SSL certificates, and deployment management — which is valuable for running Mastodon's multi-service federated social network.

This guide walks you through deploying Mastodon with PostgreSQL, Redis, Sidekiq background workers, and a streaming service. Mastodon is a decentralized social platform that federates with the Fediverse via the ActivityPub protocol.

Prerequisites

Docker Compose Configuration

Create a new Compose project in Dokploy and paste the following configuration:

version: "3.8"

services:
  mastodon-web:
    image: ghcr.io/mastodon/mastodon:latest
    restart: unless-stopped
    command: bundle exec puma -C config/puma.rb
    ports:
      - "3000:3000"
    environment:
      - LOCAL_DOMAIN=${MASTODON_DOMAIN}
      - REDIS_HOST=mastodon-redis
      - REDIS_PORT=6379
      - DB_HOST=mastodon-db
      - DB_PORT=5432
      - DB_NAME=mastodon
      - DB_USER=mastodon
      - DB_PASS=${MASTODON_DB_PASSWORD}
      - SECRET_KEY_BASE=${MASTODON_SECRET_KEY}
      - OTP_SECRET=${MASTODON_OTP_SECRET}
      - VAPID_PRIVATE_KEY=${MASTODON_VAPID_PRIVATE_KEY}
      - VAPID_PUBLIC_KEY=${MASTODON_VAPID_PUBLIC_KEY}
      - SMTP_SERVER=${SMTP_SERVER}
      - SMTP_PORT=${SMTP_PORT:-587}
      - SMTP_LOGIN=${SMTP_LOGIN}
      - SMTP_PASSWORD=${SMTP_PASSWORD}
      - SMTP_FROM_ADDRESS=${SMTP_FROM_ADDRESS}
    volumes:
      - ../files/mastodon-public:/opt/mastodon/public/system
    depends_on:
      mastodon-db:
        condition: service_healthy
      mastodon-redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://localhost:3000/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 5

  mastodon-streaming:
    image: ghcr.io/mastodon/mastodon-streaming:latest
    restart: unless-stopped
    ports:
      - "4000:4000"
    environment:
      - DB_HOST=mastodon-db
      - DB_PORT=5432
      - DB_NAME=mastodon
      - DB_USER=mastodon
      - DB_PASS=${MASTODON_DB_PASSWORD}
      - REDIS_HOST=mastodon-redis
      - REDIS_PORT=6379
      - SECRET_KEY_BASE=${MASTODON_SECRET_KEY}
    depends_on:
      mastodon-db:
        condition: service_healthy
      mastodon-redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://localhost:4000/api/v1/streaming/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3

  mastodon-sidekiq:
    image: ghcr.io/mastodon/mastodon:latest
    restart: unless-stopped
    command: bundle exec sidekiq
    environment:
      - LOCAL_DOMAIN=${MASTODON_DOMAIN}
      - REDIS_HOST=mastodon-redis
      - REDIS_PORT=6379
      - DB_HOST=mastodon-db
      - DB_PORT=5432
      - DB_NAME=mastodon
      - DB_USER=mastodon
      - DB_PASS=${MASTODON_DB_PASSWORD}
      - SECRET_KEY_BASE=${MASTODON_SECRET_KEY}
      - OTP_SECRET=${MASTODON_OTP_SECRET}
      - SMTP_SERVER=${SMTP_SERVER}
      - SMTP_PORT=${SMTP_PORT:-587}
      - SMTP_LOGIN=${SMTP_LOGIN}
      - SMTP_PASSWORD=${SMTP_PASSWORD}
      - SMTP_FROM_ADDRESS=${SMTP_FROM_ADDRESS}
    volumes:
      - ../files/mastodon-public:/opt/mastodon/public/system
    depends_on:
      mastodon-db:
        condition: service_healthy
      mastodon-redis:
        condition: service_healthy

  mastodon-db:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      - POSTGRES_DB=mastodon
      - POSTGRES_USER=mastodon
      - POSTGRES_PASSWORD=${MASTODON_DB_PASSWORD}
    volumes:
      - ../files/mastodon-db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U mastodon"]
      interval: 10s
      timeout: 5s
      retries: 5

  mastodon-redis:
    image: redis:7-alpine
    restart: unless-stopped
    volumes:
      - ../files/mastodon-redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

Note: Before first deployment, you need to generate secret keys. Run docker run --rm ghcr.io/mastodon/mastodon:latest bundle exec rake secret twice (for SECRET_KEY_BASE and OTP_SECRET) and docker run --rm ghcr.io/mastodon/mastodon:latest bundle exec rake mastodon:webpush:generate_vapid_key for VAPID keys. After first deploy, run database setup: use Dokploy's terminal to execute docker compose exec mastodon-web bundle exec rake db:setup in the project directory.

Environment Variables

Set these in Dokploy's Environment tab for your compose project:

Variable Purpose Example
MASTODON_DOMAIN Your Mastodon instance domain social.yourdomain.com
MASTODON_DB_PASSWORD PostgreSQL database password a-strong-random-password
MASTODON_SECRET_KEY Rails secret key (generate with rake) (generated 128-char hex string)
MASTODON_OTP_SECRET 2FA OTP secret (generate with rake) (generated 128-char hex string)
MASTODON_VAPID_PRIVATE_KEY Web push VAPID private key (generated key)
MASTODON_VAPID_PUBLIC_KEY Web push VAPID public key (generated key)
SMTP_SERVER SMTP server hostname smtp.mailgun.org
SMTP_PORT SMTP server port 587
SMTP_LOGIN SMTP username mastodon@yourdomain.com
SMTP_PASSWORD SMTP password your-smtp-password
SMTP_FROM_ADDRESS From address for emails notifications@yourdomain.com

In Dokploy, environment variables are set via the Environment editor in the project settings. Do not create a .env file manually — Dokploy manages this for you. The secret keys and VAPID keys must be generated before first deployment and kept consistent — changing them invalidates existing sessions and push subscriptions.

Volumes & Data Persistence

This setup uses Dokploy's ../files convention for bind-mounted volumes:

The ../files path is relative to the compose file inside Dokploy's project directory. This ensures your data persists across redeployments. Avoid using absolute paths because Dokploy may clean them during redeployment.

For large instances, consider using S3-compatible object storage for media uploads by setting S3_ENABLED=true and configuring the S3_* environment variables.

Domain & SSL Setup

  1. In your Dokploy project, navigate to the Domains tab
  2. Click Add Domain and enter your domain (e.g., social.yourdomain.com)
  3. Set the container port to 3000
  4. Enable HTTPS — Dokploy automatically provisions a Let's Encrypt SSL certificate
  5. Save and wait for the certificate to be issued (usually under a minute)

Dokploy's built-in Traefik reverse proxy handles TLS termination and routes traffic to the Mastodon web container. The streaming service on port 4000 is accessed via the same domain through Mastodon's internal routing.

Verifying the Deployment

  1. In Dokploy, go to your project's Deployments tab and click Deploy
  2. Watch the build logs — all five services should start (database and Redis first, then web, streaming, and sidekiq)
  3. Run database setup on first deploy via Dokploy terminal: docker compose exec mastodon-web bundle exec rake db:setup
  4. Check the Logs tab for the mastodon-web service. Look for: Listening on http://0.0.0.0:3000
  5. Open https://social.yourdomain.com in your browser — you should see the Mastodon landing page
  6. Create an admin account: docker compose exec mastodon-web tootctl accounts create admin --email admin@yourdomain.com --confirmed --role Owner

Troubleshooting

Mastodon web shows "500" errors on first run The database must be initialized before Mastodon can serve requests. Run docker compose exec mastodon-web bundle exec rake db:setup from Dokploy's terminal. Check the web service logs for specific ActiveRecord or migration errors.

Federation not working (can't find remote users) Ensure your LOCAL_DOMAIN matches your actual domain. Mastodon uses WebFinger for federation discovery, which requires proper DNS and HTTPS. Verify that /.well-known/webfinger responds correctly at your domain.

Sidekiq jobs piling up Check the Sidekiq service logs for Redis connection errors. Ensure all services share the same Redis host configuration. For high-traffic instances, increase Sidekiq concurrency by adding -c 25 to the command.

Media uploads not persisting or showing broken images Verify the ../files/mastodon-public volume is correctly mapped and writable. The Mastodon container runs as user mastodon (UID 991) — ensure the directory has proper permissions.

SSL certificate not issuing Ensure your domain's DNS A record points to your server's IP and has propagated. Dokploy uses Let's Encrypt HTTP-01 challenges, so port 80 must be accessible. Check Traefik logs in Dokploy for certificate-related errors.


Learn more about Mastodon in our complete overview.

Need a VPS? Hostinger VPS starts at $4.99/mo — perfect for running Mastodon.


For more on Docker Compose deployments in Dokploy, see the Dokploy Docker Compose documentation.

App data sourced from selfh.st open-source directory.

~/self-hosted-app/mastodon/dokploy/get-started

Ready to get started?

Get the best VPS hosting deal today. Hostinger offers 4GB RAM VPS starting at just $4.99/mo.

Get Hostinger VPS — $4.99/mo

// up to 75% off + free domain included

// related topics

mastodon dokploy docker compose self-hosted social network mastodon deployment

fordnox

Expert VPS reviews and hosting guides. We test every provider we recommend.

// last updated: February 12, 2026. Disclosure: This article may contain affiliate links.