How to Self-Host NodeBB with Docker Compose
What Is NodeBB?
NodeBB is a forum platform built on Node.js with real-time streaming discussions via WebSockets. When someone posts a reply, everyone viewing that topic sees it instantly — no page refresh needed. Since v4.8 (January 2026), NodeBB supports ActivityPub federation, making your forum topics discoverable from Mastodon and other fediverse platforms. Official site
NodeBB supports three database backends (MongoDB, PostgreSQL, or Redis), has a 700+ plugin ecosystem, and runs on significantly less RAM than Discourse. If you want a modern community forum that participates in the fediverse, NodeBB is the only serious option.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 1 GB of free RAM (512 MB minimum)
- 5 GB of free disk space
- A domain name (required for federation)
| Requirement | Minimum | Recommended |
|---|---|---|
| CPU | 1 core | 2 cores |
| RAM | 512 MB | 1 GB |
| Disk | 2 GB | 10 GB |
| Optional | SMTP for notifications |
Docker Compose Configuration
NodeBB’s official image is available at ghcr.io/nodebb/nodebb. The default database is MongoDB, with PostgreSQL available as an alternative.
Option 1: MongoDB Backend (Default)
Create a setup.json file first:
{
"url": "https://forum.example.com",
"secret": "change-this-to-a-long-random-string",
"database": "mongo",
"mongo:host": "mongo",
"mongo:port": 27017,
"mongo:username": "nodebb",
"mongo:password": "change_this_password",
"mongo:database": "nodebb",
"admin:username": "admin",
"admin:email": "[email protected]",
"admin:password": "ChangeThisAdminPassword123",
"admin:password:confirm": "ChangeThisAdminPassword123"
}
Create a docker-compose.yml:
services:
nodebb:
image: ghcr.io/nodebb/nodebb:v4.9.1
restart: unless-stopped
ports:
- "127.0.0.1:4567:4567"
volumes:
- nodebb-build:/usr/src/app/build
- nodebb-uploads:/usr/src/app/public/uploads
- nodebb-config:/opt/config
- ./setup.json:/usr/src/app/setup.json:ro
depends_on:
mongo:
condition: service_healthy
redis:
condition: service_healthy
mongo:
image: mongo:7-jammy
restart: unless-stopped
environment:
MONGO_INITDB_ROOT_USERNAME: nodebb
MONGO_INITDB_ROOT_PASSWORD: change_this_password
MONGO_INITDB_DATABASE: nodebb
volumes:
- mongo-data:/data/db
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:8.2.1-alpine
restart: unless-stopped
command: ["redis-server", "--appendonly", "yes", "--loglevel", "warning"]
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
nodebb-build:
nodebb-uploads:
nodebb-config:
mongo-data:
redis-data:
Option 2: PostgreSQL Backend
Replace MongoDB with PostgreSQL. Update setup.json:
{
"url": "https://forum.example.com",
"secret": "change-this-to-a-long-random-string",
"database": "postgres",
"postgres:host": "postgres",
"postgres:port": 5432,
"postgres:username": "nodebb",
"postgres:password": "change_this_password",
"postgres:database": "nodebb",
"admin:username": "admin",
"admin:email": "[email protected]",
"admin:password": "ChangeThisAdminPassword123",
"admin:password:confirm": "ChangeThisAdminPassword123"
}
Replace the mongo service with:
postgres:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_USER: nodebb
POSTGRES_PASSWORD: change_this_password
POSTGRES_DB: nodebb
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U nodebb"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres-data:
Start the stack:
docker compose up -d
On first boot, NodeBB runs the setup process using setup.json and creates the admin account automatically.
Initial Setup
- Wait for the setup to complete (check logs:
docker compose logs -f nodebb) - Navigate to
https://forum.example.com(orhttp://localhost:4567for testing) - Log in with the admin credentials from
setup.json - Configure your forum from the admin panel: Admin → Settings
Key first-run settings:
- Site title and description
- Email — configure SMTP under Admin → Settings → Email
- Registration — Admin → Settings → User → Registration Type (invitation-only recommended)
- Federation — Admin → Settings → ActivityPub (enable to join the fediverse)
Configuration
Key Admin Settings
| Setting | Location | Purpose |
|---|---|---|
| Site title & description | Settings → General | Branding and SEO |
| Registration type | Settings → User | Open, invite-only, admin-only |
| SMTP email | Settings → Email | Notifications and password resets |
| Upload limits | Settings → Uploads | Max file size and types |
| ActivityPub | Settings → ActivityPub | Enable fediverse federation |
| Notification settings | Settings → Notifications | Per-notification-type toggles |
| Unread cutoff | Settings → User | How old posts show as unread |
| Spam prevention | Settings → Spam | Akismet, StopForumSpam, honeypot |
ActivityPub Federation (v4.8+)
NodeBB v4.8 introduced ActivityPub support. Enable it in Admin → Settings → ActivityPub. Once enabled:
- Topic crossposts federate as
as:Announceactivities - Remote users can follow your forum’s categories from Mastodon
- Users on your instance can interact with fediverse content
This is a unique feature among forum platforms — neither Discourse nor Flarum support ActivityPub.
Plugin Installation
Install plugins from the admin panel:
- Go to Admin → Extend → Plugins
- Search the plugin directory
- Click Install on the plugin you want
- Restart NodeBB:
docker compose restart nodebb
Popular plugins:
| Plugin | Purpose |
|---|---|
nodebb-plugin-emoji | Extended emoji support |
nodebb-plugin-markdown | Markdown formatting |
nodebb-plugin-mentions | @user mentions |
nodebb-plugin-spam-be-gone | Anti-spam tools |
nodebb-plugin-sso-oauth2 | OAuth2 SSO |
nodebb-plugin-calendar | Event calendar |
nodebb-widget-essentials | Sidebar widgets |
Reverse Proxy
NodeBB listens on port 4567. Place it behind a reverse proxy for HTTPS. WebSocket support is required for real-time features.
Caddy:
forum.example.com {
reverse_proxy localhost:4567
}
Caddy handles WebSocket upgrade headers automatically.
Nginx:
server {
listen 443 ssl;
server_name forum.example.com;
location / {
proxy_pass http://127.0.0.1:4567;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
}
The Upgrade and Connection headers are essential for WebSocket support. Without them, real-time updates won’t work.
See our Reverse Proxy Setup guide for more options.
Backup
What to Back Up
| Data | Volume | Priority |
|---|---|---|
| Database (MongoDB) | mongo-data | Critical |
| Uploaded files | nodebb-uploads | Critical |
| Configuration | nodebb-config | Important |
| Build artifacts | nodebb-build | Low (rebuilds on start) |
| setup.json | Local file | Important |
Backup Commands
# MongoDB dump
docker compose exec mongo mongodump \
--username nodebb --password change_this_password \
--db nodebb --archive=/tmp/nodebb-backup.archive
docker compose cp mongo:/tmp/nodebb-backup.archive ./nodebb-backup-$(date +%F).archive
# Uploads backup
docker run --rm \
-v nodebb-uploads:/data \
-v $(pwd):/backup \
alpine tar czf /backup/nodebb-uploads-$(date +%F).tar.gz -C /data .
If using PostgreSQL:
docker compose exec postgres pg_dump -U nodebb nodebb > nodebb-backup-$(date +%F).sql
See our Backup Strategy guide.
Troubleshooting
WebSocket Connection Fails
Symptom: Real-time updates don’t work. Console shows WebSocket errors.
Fix: Your reverse proxy must pass WebSocket upgrade headers. For Nginx, add proxy_set_header Upgrade $http_upgrade; and proxy_set_header Connection "upgrade";. For Caddy, this works automatically. Verify by checking browser developer tools → Network → WS tab.
NodeBB Won’t Start After Plugin Install
Symptom: Container crashes after installing a plugin. Fix: Reset the plugin by entering the container:
docker compose exec nodebb node -e "require('./src/cli').reset.plugin('nodebb-plugin-name')"
docker compose restart nodebb
MongoDB Authentication Fails
Symptom: MongoServerError: Authentication failed in logs.
Fix: The MONGO_INITDB_ROOT_USERNAME and MONGO_INITDB_ROOT_PASSWORD are only applied on first database initialization. If you changed them after the volume was created, delete the volume and recreate:
docker compose down -v
# Warning: this deletes all data
docker compose up -d
Setup Wizard Appears Instead of Forum
Symptom: NodeBB shows the setup page even after initial configuration.
Fix: The setup.json wasn’t found or has invalid JSON. Check that it’s mounted correctly and validate the JSON syntax. Also verify the nodebb-config volume contains a config.json after initial setup.
High Memory Usage
Symptom: NodeBB process uses 500+ MB RAM. Fix: Node.js allocates memory aggressively by default. Set a heap limit via environment variable:
environment:
NODE_OPTIONS: "--max-old-space-size=256"
This limits the V8 heap to 256 MB, suitable for small forums.
Resource Requirements
| Resource | Small Forum (<100 users) | Medium Forum (100-1000 users) |
|---|---|---|
| RAM | 300-512 MB | 1-2 GB |
| CPU | 1 core | 2 cores |
| Disk | 2-5 GB | 10-30 GB |
| Bandwidth | 5 GB/month | 20 GB/month |
NodeBB is lighter than Discourse (which needs 2-4 GB RAM) but heavier than Flarum (256-512 MB). MongoDB adds ~200 MB overhead. If using PostgreSQL, overhead is similar. Redis adds ~50 MB.
Verdict
NodeBB fills a gap between lightweight forums like Flarum and heavyweight platforms like Discourse. The real-time WebSocket discussions feel genuinely modern — topics update live, notifications appear instantly, and the user experience is closer to chat than traditional forums.
Choose NodeBB if you want real-time forum discussions, ActivityPub federation, and a Node.js stack that’s easier to customize than Ruby. It’s the only forum platform that federates with the fediverse, which matters if you believe decentralized communities are the future.
Look elsewhere if you need the deepest moderation tools and largest plugin ecosystem — Discourse still leads there. If you want the lightest possible forum, Flarum uses less RAM. If you want a federated Reddit-style community, Lemmy is purpose-built for that.
FAQ
Does NodeBB support ActivityPub?
Yes, since v4.8 (January 2026). Topic crossposts federate as as:Announce activities. Users on Mastodon and other fediverse platforms can discover and interact with your NodeBB forum topics.
Can I migrate from Discourse to NodeBB?
NodeBB has a Discourse import plugin. It transfers categories, topics, posts, and users. Test on a staging instance first — some formatting may need cleanup after migration.
Which database should I choose?
MongoDB is the default and most tested option. PostgreSQL is a solid alternative if you’re already running PostgreSQL for other services and want to consolidate. Redis is supported as a database backend but is less common for production forums.
Is NodeBB actively maintained?
Yes. v4.9.1 was released on March 1, 2026. The project has consistent bi-weekly releases with new features and bug fixes. The core team is funded through NodeBB’s hosted offering.
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