Self-Hosting Remark42 with Docker Compose

What Is Remark42?

Remark42 is a self-hosted, privacy-focused commenting engine that replaces Disqus, Commento, and similar third-party commenting services. It stores all data in an embedded BoltDB database — no PostgreSQL, MySQL, or Redis required. You embed a JavaScript widget on your site and the comments live entirely on your server. Official site

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 512 MB of free RAM (Remark42 is lightweight)
  • 1 GB of free disk space for the application and comment data
  • A domain name pointed at your server (for OAuth callbacks and SSL)
  • At least one OAuth provider (GitHub, Google, etc.) or email authentication configured

Docker Compose Configuration

Create a directory for Remark42 and a docker-compose.yml file:

mkdir -p ~/remark42 && cd ~/remark42
services:
  remark42:
    image: ghcr.io/umputun/remark42:v1.15.0
    container_name: remark42
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:8080"
    environment:
      # REQUIRED: Full URL where Remark42 is accessible (no trailing slash)
      - REMARK_URL=https://comments.example.com
      # REQUIRED: JWT signing secret — generate with: openssl rand -hex 32
      - SECRET=change-this-to-a-long-random-secret
      # Site identifier — use your site's short name
      - SITE=my-site
      # OAuth providers — configure at least one (or enable anonymous/email auth)
      - AUTH_GITHUB_CID=your-github-client-id
      - AUTH_GITHUB_CSEC=your-github-client-secret
      - AUTH_GOOGLE_CID=your-google-client-id
      - AUTH_GOOGLE_CSEC=your-google-client-secret
      # Anonymous commenting — set to true if you don't want to require login
      - AUTH_ANON=false
      # Admin user IDs — set after your first login (find your ID in the admin panel)
      - ADMIN_SHARED_ID=
      - [email protected]
      # Comment settings
      - MAX_COMMENT_SIZE=2048
      - EDIT_TIME=10m
      - LOW_SCORE=-5
      - CRITICAL_SCORE=-10
      # Image handling
      - IMAGE_PROXY_HTTP2HTTPS=true
      - IMAGE_MAX_SIZE=5000000
      # Misc
      - EMOJI=true
      - TIME_ZONE=UTC
    volumes:
      # All data: BoltDB database, avatars, images, backups
      - ./var:/srv/var

Start the stack:

docker compose up -d

Initial Setup

  1. Remark42 starts on port 8080. If you’ve mapped it to 127.0.0.1:8080, set up your reverse proxy to point your domain (e.g., comments.example.com) to localhost:8080.

  2. Open your Remark42 URL in a browser. You should see a blank page — this is normal. Remark42 serves the API and the comment widget, not a standalone UI.

  3. Add the embed script to your website. Place this snippet where you want comments to appear:

<script>
  var remark_config = {
    host: 'https://comments.example.com',
    site_id: 'my-site',
  }
</script>
<script>
  !function(e,n){for(var o=0;o<e.length;o++){var r=n.createElement("script"),
  c=".js",d=n.head||n.body;r.async=!0;r.defer=!0;
  r.src=remark_config.host+"/web/"+e[o]+c;d.appendChild(r)}}
  (remark_config.components||["embed"],document);
</script>
<div id="remark42"></div>
  1. Log in using one of your configured OAuth providers. Your first login creates your user account.

  2. Find your user ID in the admin UI (append /web to your Remark42 URL) and set it as ADMIN_SHARED_ID in the Docker Compose environment. Restart the container.

Configuration

Authentication Providers

Remark42 supports multiple OAuth2 providers. Configure the ones your audience uses:

ProviderClient ID VariableClient Secret Variable
GitHubAUTH_GITHUB_CIDAUTH_GITHUB_CSEC
GoogleAUTH_GOOGLE_CIDAUTH_GOOGLE_CSEC
FacebookAUTH_FACEBOOK_CIDAUTH_FACEBOOK_CSEC
MicrosoftAUTH_MICROSOFT_CIDAUTH_MICROSOFT_CSEC
DiscordAUTH_DISCORD_CIDAUTH_DISCORD_CSEC
TwitterAUTH_TWITTER_CIDAUTH_TWITTER_CSEC
TelegramAUTH_TELEGRAM=trueTELEGRAM_TOKEN

Set the OAuth callback URL for each provider to: {REMARK_URL}/auth/{provider}/callback

Email Authentication

If you prefer email-based login instead of OAuth:

- AUTH_EMAIL_ENABLE=true
- SMTP_HOST=smtp.example.com
- SMTP_PORT=587
- [email protected]
- SMTP_PASSWORD=your-smtp-password
- SMTP_TLS=true
- [email protected]

Multi-Site Support

One Remark42 instance can serve multiple websites. Set SITE to a comma-separated list:

- SITE=blog,docs,community

Each site gets its own comment namespace. Use the corresponding site_id in each website’s embed code.

Notification Settings

Enable email notifications when someone replies to a comment:

- NOTIFY_USERS=email
- NOTIFY_ADMINS=email
- SMTP_HOST=smtp.example.com
- SMTP_PORT=587
- [email protected]
- SMTP_PASSWORD=your-smtp-password

Reverse Proxy

Remark42 binds to 127.0.0.1:8080 and expects a reverse proxy in front. Here’s a Caddy example:

comments.example.com {
    reverse_proxy localhost:8080
}

For Nginx Proxy Manager or Traefik configurations, see Reverse Proxy Setup.

Backup

Remark42 stores everything under /srv/var inside the container, mapped to ./var on the host. Back up this directory:

# Manual backup
tar czf remark42-backup-$(date +%Y%m%d).tar.gz ./var/

# Remark42 also creates automatic backups at ./var/backup/
ls ./var/backup/

The MAX_BACKUP_FILES environment variable controls how many automatic backup files Remark42 retains (default: 10). For a comprehensive backup strategy, see Backup Strategy.

Troubleshooting

Comments Not Loading on the Page

Symptom: The comment widget area is blank or shows a loading spinner indefinitely. Fix: Verify that REMARK_URL in Docker Compose matches the URL in your embed script’s host field exactly (including protocol and no trailing slash). Check browser console for CORS errors — your reverse proxy may need to pass the correct headers.

OAuth Login Redirects to an Error Page

Symptom: Clicking “Login with GitHub/Google” shows an error or redirects incorrectly. Fix: Confirm the OAuth callback URL in your provider’s settings matches {REMARK_URL}/auth/{provider}/callback. Ensure REMARK_URL uses HTTPS if your site uses HTTPS.

”Unauthorized” After Login

Symptom: Login succeeds but comments show “unauthorized” when posting. Fix: Check that AUTH_SAME_SITE is set correctly. If your website and Remark42 are on different domains, set AUTH_SAME_SITE=none. The AUTH_TTL_COOKIE may also need to be extended from the default 200 hours.

Images Not Uploading

Symptom: Image upload fails silently or shows an error. Fix: Verify the ./var directory is writable by UID 1001 (the default APP_UID): chown -R 1001:1001 ./var. Check that IMAGE_MAX_SIZE is large enough for the files being uploaded.

Admin Panel Not Accessible

Symptom: Cannot access admin features after setting ADMIN_SHARED_ID. Fix: The admin ID must match your user ID exactly. Log in, then check the API at {REMARK_URL}/api/v1/user?site={SITE} to find your current user ID. Update ADMIN_SHARED_ID and restart the container.

Resource Requirements

ResourceRequirement
RAM~50-80 MB idle, ~150 MB under moderate load
CPUMinimal — handles hundreds of concurrent readers on a single core
Disk~100 MB for the application, plus ~1 KB per comment (text + metadata)

Remark42 is one of the most lightweight commenting systems available. A small VPS can handle tens of thousands of comments without performance issues.

Verdict

Remark42 is the best self-hosted commenting system for most use cases. The zero-dependency architecture (no database server, no Redis, no separate frontend) makes deployment trivial, and the embedded BoltDB handles small to medium traffic volumes without any tuning. It supports all major OAuth providers, handles image uploads, and provides admin moderation tools.

The main limitation is scalability — BoltDB is a single-file database, so sites with millions of comments may see slowdowns. For those cases, consider Commento or building a custom solution. For blogs, documentation sites, and small to medium communities, Remark42 is the clear winner.

Comments