Skip to main content

Self-Host HedgeDoc: Collaborative Markdown Editor 2026

·OSSAlt Team
hedgedocmarkdowncollaborationself-hostingdocker2026

TL;DR

HedgeDoc (AGPL 3.0, ~5K GitHub stars, TypeScript) is a real-time collaborative Markdown editor. Multiple people edit the same document simultaneously with live preview — like Google Docs, but for Markdown. Code blocks with syntax highlighting, Mermaid diagrams, LaTeX math, and even presentation mode (turn any document into slides). HackMD charges $5/user/month for team features; HedgeDoc is free with unlimited users and documents.

Key Takeaways

  • HedgeDoc: AGPL 3.0, ~5K stars, TypeScript — collaborative Markdown editor
  • Real-time collaboration: Multiple editors at once with live cursors
  • Markdown++: Code blocks, Mermaid diagrams, LaTeX math, Vega charts
  • Presentation mode: Turn any document into slides with --- separators
  • Permissions: Public, editable, locked, private — per document
  • Export: HTML, PDF, raw Markdown, EPUB

HedgeDoc vs HackMD vs Google Docs vs Etherpad

FeatureHedgeDocHackMDGoogle DocsEtherpad
FormatMarkdownMarkdownRich textRich text
Real-time collabYesYesYesYes
Self-hostedYesNo (mostly)NoYes
Code highlightingYes (100+ languages)YesNoNo
DiagramsMermaid, PlantUMLMermaidNoNo
Math formulasLaTeX (MathJax)LaTeXEquation editorNo
PresentationsYesYesSeparate toolNo
PriceFree$5/user/moFree (cloud)Free

Part 1: Docker Setup

# docker-compose.yml
services:
  hedgedoc:
    image: quay.io/hedgedoc/hedgedoc:latest
    container_name: hedgedoc
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - hedgedoc_uploads:/hedgedoc/public/uploads
    environment:
      CMD_DB_URL: "postgres://hedgedoc:${DB_PASSWORD}@db:5432/hedgedoc"
      CMD_DOMAIN: docs.yourdomain.com
      CMD_PROTOCOL_USESSL: "true"
      CMD_URL_ADDPORT: "false"
      CMD_SESSION_SECRET: "${SESSION_SECRET}"   # openssl rand -hex 32

      # Registration:
      CMD_ALLOW_EMAIL_REGISTER: "true"    # Set to false after creating your account
      CMD_ALLOW_ANONYMOUS: "false"
      CMD_ALLOW_ANONYMOUS_EDITS: "true"   # Allow anonymous users to edit shared docs

      # Default permission for new notes:
      CMD_DEFAULT_PERMISSION: "editable"  # freely, editable, limited, locked, protected, private

      # Image upload:
      CMD_IMAGE_UPLOAD_TYPE: filesystem

    depends_on:
      - db

  db:
    image: postgres:16-alpine
    restart: unless-stopped
    volumes:
      - hedgedoc_db:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: hedgedoc
      POSTGRES_PASSWORD: "${DB_PASSWORD}"
      POSTGRES_DB: hedgedoc

volumes:
  hedgedoc_uploads:
  hedgedoc_db:
echo "DB_PASSWORD=$(openssl rand -base64 24)" >> .env
echo "SESSION_SECRET=$(openssl rand -hex 32)" >> .env

docker compose up -d

Part 2: HTTPS with Caddy

docs.yourdomain.com {
    reverse_proxy localhost:3000
}

Part 3: Writing in HedgeDoc

Create a document

  1. + New Note (or visit https://docs.yourdomain.com/new)
  2. Left panel: Markdown editor
  3. Right panel: Live preview
  4. Toggle: edit-only, split view, preview-only

Extended Markdown features

Code blocks with syntax highlighting

```python
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)
```

```rust
fn main() {
    println!("Hello from HedgeDoc!");
}
```

Mermaid diagrams

```mermaid
graph TD
    A[Client] -->|HTTP| B[Load Balancer]
    B --> C[Web Server 1]
    B --> D[Web Server 2]
    C --> E[(Database)]
    D --> E
```

Sequence diagrams

```mermaid
sequenceDiagram
    Client->>API: POST /login
    API->>DB: Query user
    DB-->>API: User data
    API-->>Client: JWT token
```

LaTeX math

Inline: $E = mc^2$

Block:
$$
\int_{0}^{\infty} e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
$$

Tables

| Feature | Status | Notes |
|---------|--------|-------|
| Auth    | ✅     | OAuth2 |
| API     | 🟡     | In progress |
| Tests   | ❌     | Not started |

Alerts/admonitions

:::info
This is an info box.
:::

:::warning
This is a warning.
:::

:::danger
This is a danger alert.
:::

Part 4: Presentation Mode

Turn any document into slides with --- separators:

---
title: My Presentation
---

# Slide 1: Introduction

Welcome to the presentation!

---

# Slide 2: Architecture

```mermaid
graph LR
    A[Frontend] --> B[API] --> C[Database]

Slide 3: Key Metrics

MetricValue
Users10K
Uptime99.9%

Questions?

Thank you! 🎉


Click the **presentation icon** (📊) → full-screen slide presentation.

---

## Part 5: Permissions

### Per-document permissions

| Permission | View | Edit | Owner |
|------------|------|------|-------|
| **Freely** | Anyone | Anyone | Creator |
| **Editable** | Anyone | Logged-in users | Creator |
| **Limited** | Logged-in users | Logged-in users | Creator |
| **Locked** | Logged-in users | Owner only | Creator |
| **Protected** | Logged-in users | Owner only | Creator |
| **Private** | Owner only | Owner only | Creator |

### Share a document

https://docs.yourdomain.com/abc123


Share the URL — permission controls who can view/edit.

### Publish a document

1. Click **Publish** → generates a read-only URL
2. Published URL: `https://docs.yourdomain.com/s/abc123`
3. Clean rendered view without editor

---

## Part 6: OAuth2 / SSO

### Login with Authentik

```yaml
environment:
  CMD_OAUTH2_PROVIDERNAME: Authentik
  CMD_OAUTH2_CLIENT_ID: hedgedoc-client-id
  CMD_OAUTH2_CLIENT_SECRET: hedgedoc-client-secret
  CMD_OAUTH2_AUTHORIZATION_URL: https://auth.yourdomain.com/application/o/authorize/
  CMD_OAUTH2_TOKEN_URL: https://auth.yourdomain.com/application/o/token/
  CMD_OAUTH2_USER_PROFILE_URL: https://auth.yourdomain.com/application/o/userinfo/
  CMD_OAUTH2_SCOPE: "openid email profile"
  CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR: preferred_username
  CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR: name
  CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR: email

Login with GitHub

environment:
  CMD_GITHUB_CLIENTID: your-github-client-id
  CMD_GITHUB_CLIENTSECRET: your-github-client-secret

Part 7: API

BASE="https://docs.yourdomain.com"

# Create a new note:
curl -X POST "$BASE/new" \
  -H "Content-Type: text/markdown" \
  -d "# My New Document

This was created via API."

# Get note content:
curl "$BASE/abc123/download"

# Export as HTML:
curl "$BASE/abc123/html" -o document.html

# Export as PDF (if configured):
curl "$BASE/abc123/pdf" -o document.pdf

Part 8: Use Cases

Meeting notes

  1. Create a shared document before the meeting
  2. Share URL with attendees
  3. Everyone takes notes simultaneously
  4. Notes are saved automatically — no "someone forgot to share the doc"

Technical documentation

  1. Write docs in Markdown with diagrams and code blocks
  2. Publish as read-only pages
  3. Embed diagrams and architecture decisions
  4. Version history included

Team standups

# Standup - March 9, 2026

## Alice
- ✅ Finished auth migration
- 🔄 Working on API rate limiting
- 🚫 Blocked on staging environment

## Bob
- ✅ Fixed deployment pipeline
- 🔄 Writing integration tests
- 🚫 No blockers

Decision records

Use HedgeDoc for Architecture Decision Records (ADRs):

# ADR-001: Use PostgreSQL for primary database

## Status: Accepted
## Date: 2026-03-09

## Context
We need a relational database...

## Decision
PostgreSQL 16...

## Consequences
- ✅ Strong consistency
- ❌ Requires backup strategy

Maintenance

# Update:
docker compose pull
docker compose up -d

# Backup database:
docker exec hedgedoc-db-1 pg_dump -U hedgedoc hedgedoc \
  | gzip > hedgedoc-db-$(date +%Y%m%d).sql.gz

# Backup uploads:
tar -czf hedgedoc-uploads-$(date +%Y%m%d).tar.gz \
  $(docker volume inspect hedgedoc_hedgedoc_uploads --format '{{.Mountpoint}}')

# Logs:
docker compose logs -f hedgedoc

See all open source productivity tools at OSSAlt.com/categories/productivity.

Comments