How to Self-Host Lemmy with Docker Compose
A Federated Reddit You Actually Control
Lemmy is a link aggregator and discussion platform for the fediverse. Think Reddit, but decentralized — your Lemmy instance federates with other Lemmy instances and the broader ActivityPub network. Users on any instance can subscribe to communities on any other instance, vote on posts, and comment across server boundaries. Official site
Born from the 2023 Reddit API controversy that killed third-party apps, Lemmy saw explosive growth and has matured significantly since. The v0.19.x series is stable and feature-rich, with v1.0 in alpha testing.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose v2+ installed (guide)
- 2 GB RAM minimum
- 10 GB of free disk space
- A domain name with DNS configured
- SMTP credentials (recommended for email notifications)
| Requirement | Minimum | Recommended |
|---|---|---|
| CPU | 2 cores | 4 cores |
| RAM | 1 GB | 2 GB |
| Disk | 10 GB | 20 GB+ |
| Optional | SMTP for notifications |
Docker Compose Configuration
Lemmy has four services: the backend API, the web frontend, PostgreSQL, and pictrs (image hosting).
services:
lemmy:
image: dessalines/lemmy:0.19.15
restart: unless-stopped
volumes:
- ./lemmy.hjson:/config/config.hjson:ro
depends_on:
postgres:
condition: service_healthy
pictrs:
condition: service_started
networks:
- lemmy
lemmy-ui:
image: dessalines/lemmy-ui:0.19.15
restart: unless-stopped
environment:
LEMMY_UI_LEMMY_INTERNAL_HOST: lemmy:8536
LEMMY_UI_LEMMY_EXTERNAL_HOST: lemmy.example.com
LEMMY_UI_HTTPS: "true"
depends_on:
- lemmy
networks:
- lemmy
pictrs:
image: asonix/pictrs:0.5.27
restart: unless-stopped
user: 991:991
volumes:
- pictrs-data:/mnt/sled-repo
- pictrs-data:/mnt/files
environment:
PICTRS__MEDIA__VIDEO_CODEC: vp9
PICTRS__MEDIA__GIF__MAX_WIDTH: 256
PICTRS__MEDIA__GIF__MAX_HEIGHT: 256
PICTRS__MEDIA__GIF__MAX_AREA: 65536
PICTRS__MEDIA__GIF__MAX_FRAME_COUNT: 400
networks:
- lemmy
postgres:
image: postgres:16-alpine
restart: unless-stopped
shm_size: 256mb
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_DB: lemmy
POSTGRES_USER: lemmy
POSTGRES_PASSWORD: change_this_strong_password
healthcheck:
test: ["CMD-SHELL", "pg_isready -U lemmy"]
interval: 10s
timeout: 5s
retries: 5
networks:
- lemmy
proxy:
image: nginx:1-alpine
restart: unless-stopped
ports:
- "127.0.0.1:8536:8536"
volumes:
- ./nginx_internal.conf:/etc/nginx/nginx.conf:ro
depends_on:
- lemmy
- lemmy-ui
- pictrs
networks:
- lemmy
networks:
lemmy:
volumes:
postgres-data:
pictrs-data:
Lemmy Configuration (lemmy.hjson)
Create lemmy.hjson alongside your docker-compose.yml:
{
# The domain of your Lemmy instance (CANNOT be changed after first run)
hostname: "lemmy.example.com"
# Bind address for the API server
bind: "0.0.0.0"
port: 8536
# Set to true for HTTPS (production)
tls_enabled: true
# Database connection
database: {
uri: "postgres://lemmy:change_this_strong_password@postgres/lemmy"
}
# Image hosting service
pictrs: {
url: "http://pictrs:8080/"
api_key: "generate_a_random_api_key_here"
}
# Email (optional but recommended)
email: {
smtp_server: "smtp.example.com:587"
smtp_login: "your_smtp_user"
smtp_password: "your_smtp_password"
smtp_from_address: "[email protected]"
tls_type: "starttls"
}
# Instance settings
setup: {
admin_username: "admin"
admin_password: "change_this_admin_password"
site_name: "My Lemmy Instance"
}
}
Nginx Internal Configuration (nginx_internal.conf)
Create nginx_internal.conf — this routes traffic between the API and frontend:
worker_processes auto;
events {
worker_connections 1024;
}
http {
upstream lemmy {
server "lemmy:8536";
}
upstream lemmy-ui {
server "lemmy-ui:1234";
}
server {
listen 8536;
server_name localhost;
# API and federation endpoints
location ~ ^/(api|pictrs|feeds|nodeinfo|.well-known) {
proxy_pass http://lemmy;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Frontend
location / {
set $proxpass "http://lemmy-ui";
if ($http_accept = "application/activity+json") {
set $proxpass "http://lemmy";
}
if ($http_accept = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") {
set $proxpass "http://lemmy";
}
proxy_pass $proxpass;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
Start everything:
docker compose up -d
Initial Setup
-
Navigate to
https://lemmy.example.com -
Log in with the admin credentials from
lemmy.hjson(admin/ your password) -
Go to Admin Settings to configure:
- Site name, description, sidebar content
- Registration mode (open, application-required, closed)
- Federation settings (allowed/blocked instances)
- Content policies (NSFW, slur filter)
-
Create your first community at
/create_community
Configuration
Key Settings in lemmy.hjson
| Setting | Purpose | Notes |
|---|---|---|
hostname | Instance domain | Immutable after first run |
database.uri | PostgreSQL connection | Include password |
pictrs.url | Image hosting service | Internal URL |
email | SMTP configuration | Required for password resets |
setup.admin_username | First admin account | Only used on initial setup |
federation.enabled | Enable ActivityPub | true by default |
federation.allowed_instances | Allowlist (empty = all) | Leave empty for open federation |
federation.blocked_instances | Blocklist | Block specific instances |
Admin Panel Settings
Access via /admin:
- Registration: Open, require application, or closed
- Content: Enable/disable NSFW, downvotes, bot accounts
- Rate limiting: Post, comment, search, and register rate limits
- Taglines: Rotating taglines on the homepage
- Custom CSS/JS: Style your instance
Reverse Proxy
The internal nginx proxy listens on port 8536. Place your external reverse proxy in front of it.
Caddy:
lemmy.example.com {
reverse_proxy localhost:8536
}
See our Reverse Proxy Setup guide for Nginx Proxy Manager and Traefik examples.
Backup
# Database backup
docker compose exec postgres pg_dump -U lemmy lemmy > lemmy_backup_$(date +%F).sql
# Image data backup
docker run --rm -v lemmy_pictrs-data:/data -v $(pwd):/backup \
alpine tar czf /backup/pictrs_backup_$(date +%F).tar.gz -C /data .
Also back up lemmy.hjson and nginx_internal.conf. See our Backup Strategy guide.
Troubleshooting
Federation Not Working
Symptom: Can’t find communities on other instances.
Fix: Check that your instance is reachable at https://lemmy.example.com/.well-known/nodeinfo. Verify the internal nginx config routes /api and /.well-known to the backend, not the frontend. Check logs: docker compose logs lemmy | grep -i error.
502 Bad Gateway
Symptom: Nginx returns 502 errors.
Fix: The backend hasn’t started yet or crashed. Check docker compose logs lemmy for errors. Common cause: wrong database password in lemmy.hjson — it must match POSTGRES_PASSWORD in the Compose file.
Images Not Loading
Symptom: Uploaded images show broken image icons.
Fix: Check pictrs is running: docker compose logs pictrs. Verify the pictrs.api_key in lemmy.hjson matches if you set one. Check volume permissions — pictrs runs as UID 991.
Search Returns No Results
Symptom: Searching for remote communities or users returns nothing.
Fix: Lemmy uses WebFinger to resolve remote resources. Use the full URL format: [email protected] for communities, @[email protected] for users. The first search triggers a federation lookup — wait a moment and retry.
High Memory Usage
Symptom: Server running out of RAM.
Fix: PostgreSQL is usually the culprit. Reduce shared_buffers and work_mem in PostgreSQL config. Add shm_size: 256mb to the postgres service. Consider increasing swap space on small servers.
Resource Requirements
| Resource | Small Instance (<100 users) | Medium Instance (100-1000 users) |
|---|---|---|
| RAM | 1-2 GB | 3-4 GB |
| CPU | 2 cores | 4 cores |
| Disk | 10 GB | 30-50 GB |
| Bandwidth | 10 GB/month | 50+ GB/month |
Lemmy is more lightweight than Mastodon but heavier than GoToSocial. The five containers (backend, frontend, postgres, pictrs, nginx) add up. Plan for pictrs storage growth if your users post images.
Verdict
Lemmy is the best self-hosted Reddit alternative. The federation model means your community can interact with every other Lemmy instance and the broader fediverse. The moderation tools are solid, communities are well-organized, and the user experience is familiar to anyone who’s used Reddit.
Choose Lemmy if you want to build a link-aggregation community with upvotes, communities, and threaded comments. It’s Reddit, but you own it and it federates.
Look elsewhere if you want a traditional forum experience. Discourse is better for long-form discussions. If you want a microblogging platform, use Mastodon or GoToSocial instead.
FAQ
Can users on other Lemmy instances post in my communities?
Yes. That’s the core value proposition. Users on any federated Lemmy instance can subscribe to, post in, and comment on your communities. Votes also federate.
Is Lemmy compatible with Mastodon?
Partially. Mastodon users can follow Lemmy communities and see posts in their timeline. They can comment on posts (which appear as replies in Lemmy). However, the full Reddit-like experience (voting, creating posts) works best from a Lemmy client.
How do I moderate effectively across federation?
Instance-level moderation (admin) can block entire instances, IP ranges, and individual users. Community-level moderation (moderators) can remove posts, ban users from specific communities, and set content rules. Each community can have different moderators.
What clients are available?
Web frontend is the primary client. Mobile apps include Jerboa (official Android), Thunder, Voyager, and Boost for Lemmy. Most support multiple instances.
Can I import data from Reddit?
There’s no official import tool, but community-built tools can export your Reddit subscriptions and bookmarks. Content doesn’t migrate — you start fresh on Lemmy.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments