How to Self-Host Pleroma with Docker Compose

Mastodon’s Lighter, More Opinionated Cousin

Pleroma is an Elixir-based microblogging server that speaks ActivityPub. It does what Mastodon does — federated microblogging with timelines, follows, boosts, and direct messages — but with roughly one-third the resource usage. It comes with its own web frontend (Pleroma-FE) built in, so unlike GoToSocial you don’t need a separate client. Official site

The project has a reputation for attracting a different corner of the fediverse than Mastodon. Technical merits aside, Pleroma is genuinely excellent for single-user instances and small communities where Mastodon’s five-container setup is overkill.

Prerequisites

  • A Linux server (Ubuntu 22.04+, Debian 12+, or any Docker host)
  • Docker and Docker Compose installed (guide)
  • 1 GB RAM minimum
  • 5 GB of free disk space
  • A domain name pointing to your server
  • SMTP credentials (recommended)
RequirementMinimumRecommended
CPU1 core2 cores
RAM512 MB1 GB
Disk5 GB15 GB
EmailOptionalSMTP for notifications

Docker Compose Configuration

Pleroma doesn’t have an official Docker image with semantic version tags. The community image from angristan/pleroma is the most widely-used option. Alternatively, build from source using the official repo:

services:
  pleroma:
    # Community image — no semver tags available; :latest is the only option
    image: angristan/pleroma:latest
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "127.0.0.1:4000:4000"
    volumes:
      - pleroma-uploads:/var/lib/pleroma/uploads
      - pleroma-static:/var/lib/pleroma/static
      - ./config.exs:/etc/pleroma/config.exs:ro
    environment:
      DOMAIN: social.example.com
      INSTANCE_NAME: "My Pleroma Instance"
      ADMIN_EMAIL: [email protected]
      NOTIFY_EMAIL: [email protected]
      DB_USER: pleroma
      DB_PASS: change_this_password
      DB_NAME: pleroma
      DB_HOST: db
    networks:
      - pleroma

  db:
    image: postgres:16-alpine
    restart: unless-stopped
    shm_size: 256mb
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: pleroma
      POSTGRES_USER: pleroma
      POSTGRES_PASSWORD: change_this_password
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U pleroma"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - pleroma

networks:
  pleroma:

volumes:
  postgres-data:
  pleroma-uploads:
  pleroma-static:

Configuration File (config.exs)

Create config.exs alongside your docker-compose.yml:

import Config

config :pleroma, Pleroma.Web.Endpoint,
  url: [host: "social.example.com", scheme: "https", port: 443],
  http: [ip: {0, 0, 0, 0}, port: 4000]

config :pleroma, :instance,
  name: "My Pleroma Instance",
  email: "[email protected]",
  notify_email: "[email protected]",
  description: "A personal Pleroma instance",
  limit: 5000,
  registrations_open: false,
  invites_enabled: true

config :pleroma, Pleroma.Repo,
  adapter: Ecto.Adapters.Postgres,
  username: "pleroma",
  password: "change_this_password",
  database: "pleroma",
  hostname: "db",
  pool_size: 10

# SMTP configuration
config :pleroma, Pleroma.Emails.Mailer,
  adapter: Swoosh.Adapters.SMTP,
  relay: "smtp.example.com",
  port: 587,
  username: "your_smtp_user",
  password: "your_smtp_password",
  tls: :always,
  auth: :always

# Media upload settings
config :pleroma, Pleroma.Upload,
  uploader: Pleroma.Uploaders.Local,
  filters: [
    Pleroma.Upload.Filter.Mogrify,
    Pleroma.Upload.Filter.Dedupe,
    Pleroma.Upload.Filter.AnonymizeFilename
  ]

# Generate a secret key with: openssl rand -base64 64
config :pleroma, Pleroma.Web.Endpoint,
  secret_key_base: "generate_a_64_byte_base64_secret_here"

config :pleroma, :media_proxy,
  enabled: true,
  redirect_on_failure: true

config :web_push_encryption, :vapid_details,
  subject: "mailto:[email protected]"

Start the stack:

docker compose up -d

Initial Setup

Create your admin account:

docker compose exec pleroma pleroma_ctl user new admin [email protected] --admin --password YourSecurePassword

Access the web interface at https://social.example.com. The built-in Pleroma-FE frontend is ready to use immediately.

Alternative Frontend: Soapbox

Many Pleroma users prefer Soapbox, a modern frontend with a Twitter-like design. Install it by downloading the build to the static files directory:

docker compose exec pleroma sh -c "
  curl -L https://gitlab.com/soapbox-pub/soapbox/-/releases/permalink/latest/downloads/soapbox.zip -o /tmp/soapbox.zip
  unzip -o /tmp/soapbox.zip -d /var/lib/pleroma/static/frontends/soapbox/stable/
"

Then set it as the default in config.exs:

config :pleroma, :frontends,
  primary: %{"name" => "soapbox", "ref" => "stable"}

Configuration

Key Settings

SettingLocationPurpose
registrations_openconfig.exsAllow public signup
invites_enabledconfig.exsInvite-only registration
limitconfig.exsPost character limit (default 5000)
upload_limitconfig.exsMax file upload size
account_activation_requiredconfig.exsEmail verification
federatingconfig.exsEnable/disable federation
:mrfconfig.exsMessage Rewrite Facility (content filtering)

Admin Panel

Pleroma includes a web-based admin panel (AdminFE) at /pleroma/admin/. From there:

  • Manage users (approve, deactivate, moderate)
  • Configure instance settings
  • Manage emoji packs
  • View federation status and manage domain blocks
  • Moderate content reports

Message Rewrite Facility (MRF)

MRF is Pleroma’s powerful content filtering system. Add policies in config.exs:

config :pleroma, :mrf,
  policies: [
    Pleroma.Web.ActivityPub.MRF.SimplePolicy,
    Pleroma.Web.ActivityPub.MRF.TagPolicy
  ]

config :pleroma, :mrf_simple,
  reject: ["spam-instance.example"],
  media_removal: ["nsfw-instance.example"],
  followers_only: ["limited-instance.example"]

Reverse Proxy

Pleroma listens on port 4000. A reverse proxy with SSL is required for federation.

Caddy:

social.example.com {
    reverse_proxy localhost:4000
}

See our Reverse Proxy Setup guide for more options.

Backup

# Database backup
docker compose exec db pg_dump -U pleroma pleroma > pleroma_backup_$(date +%F).sql

# Uploads and static files
docker run --rm -v pleroma_pleroma-uploads:/data -v $(pwd):/backup \
  alpine tar czf /backup/pleroma_uploads_$(date +%F).tar.gz -C /data .

Also back up config.exs. See our Backup Strategy guide.

Troubleshooting

Federation Not Working

Symptom: Can’t find remote users, posts don’t federate. Fix: Verify SSL is working and the domain is reachable. Check https://social.example.com/.well-known/webfinger?resource=acct:[email protected] returns valid JSON. Inspect logs: docker compose logs pleroma | grep -i error.

Database Migration Errors

Symptom: Pleroma won’t start after pulling a new image. Fix: Run migrations manually:

docker compose exec pleroma pleroma_ctl migrate

Uploads Failing

Symptom: Media uploads return errors. Fix: Check permissions on the uploads volume. Pleroma runs as UID 1000 by default in most Docker images. Verify disk space.

Slow Timeline Loading

Symptom: Home timeline takes seconds to load. Fix: Check PostgreSQL performance. Increase pool_size in config.exs if you see connection timeout errors. Run VACUUM ANALYZE on the database periodically:

docker compose exec db psql -U pleroma -c "VACUUM ANALYZE;"

Resource Requirements

ResourceSingle UserSmall Instance (10-50 users)
RAM200-400 MB500 MB - 1 GB
CPU1 core1-2 cores
Disk2-5 GB10-30 GB
Bandwidth2-5 GB/month10-30 GB/month

Pleroma is significantly lighter than Mastodon. A single-user instance runs well on a $5/month VPS or a Raspberry Pi 4.

Verdict

Pleroma is a solid choice for anyone who wants fediverse participation with lower resource usage than Mastodon and more features than GoToSocial. The 5,000-character post limit, MRF content filtering, and built-in web frontend make it a complete package.

Choose Pleroma if you want a lightweight, full-featured fediverse server with a built-in web UI. Great for single-user instances and small communities on modest hardware.

Look elsewhere if you want the largest app ecosystem and community support — Mastodon has more clients, more documentation, and more active development. If you want even lighter resources and don’t need a web UI, GoToSocial uses even less memory.

FAQ

Can I use Mastodon clients with Pleroma?

Yes. Pleroma implements the Mastodon Client API. Apps like Tusky, Ice Cubes, Ivory, and Megalodon work with Pleroma instances.

What’s the difference between Pleroma and Akkoma?

Akkoma is a fork of Pleroma with additional features and more active development. It adds custom emoji reactions, better MRF policies, and Soapbox integration. If Pleroma’s development pace concerns you, Akkoma is worth considering.

Is Pleroma still actively developed?

Development continues but at a slower pace than Mastodon. The project merged several community patches in late 2025. Akkoma is the more actively developed fork.

Can I migrate from Mastodon to Pleroma?

Not directly. You can use Mastodon’s account migration to transfer followers to a Pleroma account. Posts don’t transfer between platforms.

Comments