Prerequisites#
- Docker and Docker Compose installed
- Domain name pointing to your server
1. Create Project Directory#
mkdir mastodon
cd mastodon2. Create Docker Compose File#
Create a docker-compose.yml file:
version: '3'
services:
db:
restart: always
image: postgres:14-alpine
shm_size: 256mb
networks:
- internal_network
healthcheck:
test: ['CMD', 'pg_isready', '-U', 'postgres']
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_HOST_AUTH_METHOD=trust
redis:
restart: always
image: redis:7-alpine
networks:
- internal_network
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
volumes:
- redis_data:/data
web:
restart: always
image: tootsuite/mastodon:latest
networks:
- external_network
- internal_network
healthcheck:
test: ['CMD-SHELL', 'wget -q --spider http://localhost:3000/health || exit 1']
timeout: 10s
depends_on:
- db
- redis
environment:
- DB_HOST=db
- DB_USER=postgres
- DB_NAME=postgres
- DB_PASS=
- REDIS_HOST=redis
- LOCAL_DOMAIN=your-domain.com
- SINGLE_USER_MODE=false
- SMTP_SERVER=smtp.mailgun.org
- SMTP_PORT=587
- SMTP_LOGIN=your-smtp-login
- SMTP_PASSWORD=your-smtp-password
- SMTP_FROM_ADDRESS=notifications@your-domain.com
volumes:
- ./public/system:/mastodon/public/system
ports:
- "3000:3000"
command: bash -c "rm -f /mastodon/tmp/pids/server.pid && bundle exec rails s -p 3000"
streaming:
restart: always
image: tootsuite/mastodon:latest
networks:
- external_network
- internal_network
depends_on:
- db
- redis
environment:
- DB_HOST=db
- DB_USER=postgres
- DB_NAME=postgres
- DB_PASS=
- REDIS_HOST=redis
- LOCAL_DOMAIN=your-domain.com
volumes:
- ./public/system:/mastodon/public/system
ports:
- "4000:4000"
command: node ./streaming
sidekiq:
restart: always
image: tootsuite/mastodon:latest
networks:
- internal_network
depends_on:
- db
- redis
environment:
- DB_HOST=db
- DB_USER=postgres
- DB_NAME=postgres
- DB_PASS=
- REDIS_HOST=redis
- LOCAL_DOMAIN=your-domain.com
volumes:
- ./public/system:/mastodon/public/system
command: bundle exec sidekiq
networks:
external_network:
internal_network:
internal: true
volumes:
postgres_data:
redis_data:3. Create Environment File#
Create a .env.production file with your configuration:
# Database
DB_HOST=db
DB_PORT=5432
DB_NAME=postgres
DB_USER=postgres
DB_PASS=
# Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=
# Mastodon
LOCAL_DOMAIN=your-domain.com
SECRET_KEY_BASE=generate-a-secret-key
OTP_SECRET=generate-an-otp-secret
# Web Push
VAPID_PRIVATE_KEY=generate-vapid-private-key
VAPID_PUBLIC_KEY=generate-vapid-public-key
# SMTP (Email)
SMTP_SERVER=smtp.mailgun.org
SMTP_PORT=587
SMTP_LOGIN=your-email-login
SMTP_PASSWORD=your-email-password
SMTP_AUTH_METHOD=plain
SMTP_OPENSSL_VERIFY_MODE=none
SMTP_FROM_ADDRESS=notifications@your-domain.com
# Optional: S3 storage
S3_ENABLED=false
# S3_BUCKET=your-bucket-name
# AWS_ACCESS_KEY_ID=your-access-key
# AWS_SECRET_ACCESS_KEY=your-secret-key
# S3_REGION=us-east-1
# S3_PROTOCOL=https
# S3_HOSTNAME=s3.amazonaws.com4. Generate Secrets#
Run the following commands to generate the required secrets:
# Generate secret key base
docker run --rm tootsuite/mastodon:latest bundle exec rake secret
# Generate OTP secret
docker run --rm tootsuite/mastodon:latest bundle exec rake secret
# Generate VAPID keys
docker run --rm tootsuite/mastodon:latest bundle exec rake mastodon:webpush:generate_vapid_keyUpdate your .env.production file with these generated values.
5. Start Mastodon#
# Pull images
docker-compose pull
# Start services
docker-compose up -d
# Run database setup
docker-compose run --rm web bundle exec rake db:migrate
# Pre-compile assets
docker-compose run --rm web bundle exec rake assets:precompile6. Create Admin User#
docker-compose run --rm web bundle exec rake mastodon:setupFollow the interactive prompts to create your admin account.
7. Reverse Proxy Setup (Nginx)#
Create an Nginx configuration file:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
server_name your-domain.com;
# Uncomment for SSL
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# ssl_certificate /path/to/certificate.crt;
# ssl_certificate_key /path/to/private.key;
root /home/mastodon/live/public;
location / {
try_files $uri @proxy;
}
location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri @proxy;
}
location /sw.js {
add_header Cache-Control "public, max-age=0";
try_files $uri @proxy;
}
location @proxy {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Proxy "";
proxy_pass_header Server;
proxy_pass http://127.0.0.1:3000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
add_header Strict-Transport-Security "max-age=31536000";
}
location /api/v1/streaming {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Proxy "";
proxy_pass http://127.0.0.1:4000;
proxy_buffering off;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
error_page 500 501 502 503 504 /500.html;
}8. Useful Commands#
# Check logs
docker-compose logs -f
docker-compose logs -f web
docker-compose logs -f sidekiq
# Stop services
docker-compose down
# Backup database
docker-compose exec db pg_dump -U postgres postgres > backup.sql
# Update Mastodon
docker-compose pull
docker-compose run --rm web bundle exec rake db:migrate
docker-compose run --rm web bundle exec rake assets:precompile
docker-compose restartImportant Notes#
- Replace placeholders: Update
your-domain.comwith your actual domain - Email configuration: Set up proper SMTP settings for email notifications
- Backup regularly: Implement a backup strategy for your database
- Security: Use SSL/TLS certificates and keep your system updated
- Resources: Mastodon can be resource-intensive; ensure your server has adequate RAM and CPU
This setup provides a basic Mastodon instance. You may want to customize it further based on your needs, such as adding object storage for media files or configuring additional security measures.