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
- A VPS with at least 2 vCPUs, 4 GB RAM, and 40 GB storage
- Dokploy installed and running on your server (installation docs)
- A domain name (e.g.,
social.yourdomain.com) with DNS A record pointing to your server's IP - An SMTP email service for sending notifications (e.g., Mailgun, SendGrid, or your own mail server)
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 secrettwice (forSECRET_KEY_BASEandOTP_SECRET) anddocker run --rm ghcr.io/mastodon/mastodon:latest bundle exec rake mastodon:webpush:generate_vapid_keyfor VAPID keys. After first deploy, run database setup: use Dokploy's terminal to executedocker compose exec mastodon-web bundle exec rake db:setupin 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:
../files/mastodon-public— User uploads (avatars, media attachments, header images)../files/mastodon-db-data— PostgreSQL database files../files/mastodon-redis-data— Redis persistence data for job queues and caching
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
- In your Dokploy project, navigate to the Domains tab
- Click Add Domain and enter your domain (e.g.,
social.yourdomain.com) - Set the container port to
3000 - Enable HTTPS — Dokploy automatically provisions a Let's Encrypt SSL certificate
- 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
- In Dokploy, go to your project's Deployments tab and click Deploy
- Watch the build logs — all five services should start (database and Redis first, then web, streaming, and sidekiq)
- Run database setup on first deploy via Dokploy terminal:
docker compose exec mastodon-web bundle exec rake db:setup - Check the Logs tab for the
mastodon-webservice. Look for:Listening on http://0.0.0.0:3000 - Open
https://social.yourdomain.comin your browser — you should see the Mastodon landing page - 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.
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
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.