CodiMD / HedgeDoc

Real-time collaborative markdown editing — deployment, features, authentication & operations

01

Overview

CodiMD (now renamed HedgeDoc) is an open-source, self-hosted platform for real-time collaborative markdown editing. It allows multiple users to simultaneously edit a single markdown document in the browser, seeing each other's changes instantly via WebSocket connections.

HedgeDoc is the community-driven successor to CodiMD, which itself was a fork of the open-source edition of HackMD. The naming history is confusing: HackMD → CodiMD (open-source fork) → HedgeDoc (community rename in 2020). The commercial HackMD product continues as a separate SaaS offering, while HedgeDoc is the fully open-source, self-hosted alternative.

Why self-host collaborative markdown?

  • Data sovereignty — Sensitive meeting notes, runbooks, and documentation stay on your infrastructure, not on third-party SaaS
  • Real-time collaboration — Google Docs-like experience but for markdown, with syntax highlighting, live preview, and no vendor lock-in
  • Developer-friendly — Native support for code blocks, Mermaid diagrams, LaTeX math, slide decks, and other markdown extensions
  • Lightweight — A single Node.js process with a database is all you need. Minimal infrastructure compared to a full wiki or CMS
  • Integration — Supports LDAP, OAuth2, SAML for enterprise SSO. Export to PDF, HTML, or GitHub Gist
Naming

Throughout this guide, "CodiMD" and "HedgeDoc" are used interchangeably. The Docker image is quay.io/hedgedoc/hedgedoc and the project repository is github.com/hedgedoc/hedgedoc. If you see references to codimd in older documentation or config files, it refers to the same software.

02

Architecture

HedgeDoc 1.x is a Node.js application built on Express.js. The architecture is straightforward: a single application process handles HTTP requests, serves the web UI, manages WebSocket connections for real-time collaboration, and communicates with a database for persistence.

Browser (User A) ——> [HTTPS / WSS] ——> Reverse Proxy (Nginx/Caddy) Browser (User B) ——> [HTTPS / WSS] ——> Reverse Proxy (Nginx/Caddy) | v +-----------------+ | HedgeDoc | | (Node.js) | +--------+--------+ | +-------------+-------------+ | | v v +---------------+ +----------------+ | Database | | File Storage | | (PostgreSQL / | | (Local / S3 / | | MySQL/SQLite)| | MinIO) | +---------------+ +----------------+

Core components

Node.js Application

Single process running Express.js. Handles HTTP routes, WebSocket connections (via Socket.IO), markdown rendering, and authentication. Stateless beyond database and file storage.

Database

Stores notes, user accounts, revision history, and session data. Supports PostgreSQL (recommended for production), MySQL/MariaDB, and SQLite (single-user/dev only).

File Storage

Uploaded images and attachments are stored on the local filesystem (default), S3-compatible storage (AWS S3, MinIO), Azure Blob Storage, or Imgur. Local storage is the default.

Reverse Proxy

Nginx, Caddy, or similar. Required for TLS termination and WebSocket proxying. Must be configured to pass Upgrade and Connection headers for WebSocket support.

Recommendation

For production, always use PostgreSQL as the database backend. SQLite does not handle concurrent writes well and will cause issues under multi-user load. MySQL works but PostgreSQL has better JSON support and is the best-tested backend for HedgeDoc.

03

Deployment

HedgeDoc can be deployed via Docker (recommended), manual Node.js installation, or on Kubernetes. Configuration is done through environment variables or a config.json file.

Docker deployment (recommended)

The official Docker image is the simplest way to run HedgeDoc in production. A docker-compose.yml with HedgeDoc + PostgreSQL is the most common setup:

services:
  hedgedoc:
    image: quay.io/hedgedoc/hedgedoc:1.10.7
    environment:
      - CMD_DB_URL=postgres://hedgedoc:secret@db:5432/hedgedoc
      - CMD_DOMAIN=docs.example.com
      - CMD_PROTOCOL_USESSL=true
      - CMD_URL_ADDPORT=false
      - CMD_ALLOW_ANONYMOUS=false
      - CMD_DEFAULT_PERMISSION=limited
      - CMD_IMAGE_UPLOAD_TYPE=filesystem
    volumes:
      - uploads:/hedgedoc/public/uploads
    ports:
      - "3000:3000"
    depends_on:
      - db
    restart: always

  db:
    image: postgres:17-alpine
    environment:
      - POSTGRES_USER=hedgedoc
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=hedgedoc
    volumes:
      - db-data:/var/lib/postgresql/data
    restart: always

volumes:
  uploads:
  db-data:

Manual Node.js install

  • Requires Node.js 20+ (Node 18 support was dropped; check HedgeDoc docs for exact version compatibility)
  • Clone the repository, run yarn install and yarn build
  • Configure via config.json or environment variables prefixed with CMD_
  • Use a process manager like systemd or pm2 to keep it running

Kubernetes deployment

  • Community Helm charts are available (not officially maintained)
  • Key considerations: persistent volume for uploads, database as a StatefulSet or external managed database, WebSocket-aware ingress configuration
  • Set CMD_DOMAIN to match the ingress hostname
  • If using multiple replicas, you need sticky sessions or a shared session store (Redis) since WebSocket connections are stateful
WebSocket Proxy

The most common deployment issue is failing to configure the reverse proxy for WebSocket connections. Nginx requires explicit proxy_set_header Upgrade $http_upgrade; and proxy_set_header Connection "upgrade"; directives. Without these, real-time collaboration will not work.

04

Features

HedgeDoc provides a rich collaborative editing experience with powerful markdown extensions beyond standard CommonMark.

Real-time collaboration

  • Simultaneous editing — Multiple users can edit the same note at the same time. Changes appear instantly for all participants via WebSocket
  • Cursor presence — See where other editors are typing in real time
  • Conflict resolution — Operational Transformation (OT) handles concurrent edits without conflicts

Markdown extensions

Diagrams

  • Mermaid — flowcharts, sequence diagrams, Gantt charts
  • PlantUML — UML diagrams (requires external server)
  • GraphViz (dot) — graph visualization

Math & Science

  • LaTeX math via MathJax / KaTeX
  • Inline: $E = mc^2$
  • Block: $$\int_0^\infty f(x)dx$$

Slide Decks

  • Create presentations from markdown using --- slide separators
  • Powered by reveal.js
  • Slide mode accessible via /slide/note-id

Code & Embeds

  • Syntax highlighting for 180+ languages
  • YouTube, Vimeo, Gist, Speakerdeck embeds
  • ToC generation, footnotes, task lists

Revision history

Every note maintains a revision history. Users can browse previous versions and see what changed. Revisions are stored in the database and can be configured for automatic cleanup to prevent unbounded growth.

Permissions model

PermissionWho can readWho can edit
FreelyEveryone (including anonymous)Everyone (including anonymous)
EditableEveryoneSigned-in users only
LimitedSigned-in users onlySigned-in users only
LockedEveryoneNote owner only
ProtectedSigned-in users onlyNote owner only
PrivateNote owner onlyNote owner only

Export options

  • Markdown — Download the raw .md file
  • HTML — Rendered output as a standalone HTML file
  • PDF — Print-ready export (requires browser or additional tooling)
  • GitHub Gist — Publish directly to a GitHub Gist
  • Reveal.js slides — Export presentations
05

Authentication

HedgeDoc supports a wide range of authentication backends, making it easy to integrate into existing enterprise identity infrastructure.

Supported providers

Enterprise LDAP / Active Directory

Bind to an LDAP server for user authentication. Configure via CMD_LDAP_URL, CMD_LDAP_BINDDN, CMD_LDAP_SEARCHBASE, and related environment variables. Supports TLS/STARTTLS.

Enterprise SAML 2.0

Integrate with SAML identity providers (ADFS, Okta, Keycloak). Configure via CMD_SAML_* environment variables. Supports metadata URL or manual certificate configuration.

Flexible OAuth2 / OIDC

Generic OAuth2 support plus specific integrations for GitLab, GitHub, Google, Keycloak, and Mattermost. Each has dedicated CMD_* environment variables for client ID, secret, and base URL.

Simple Local Accounts

Email + password registration. Can be enabled alongside external providers. Control registration with CMD_ALLOW_EMAIL_REGISTER. Useful as a fallback or for small teams.

Guest and anonymous access

  • CMD_ALLOW_ANONYMOUS=true — Allows anonymous users to create new notes without signing in
  • CMD_ALLOW_ANONYMOUS_EDITS=true — Allows anonymous users to edit existing shared notes (if note permissions allow). Works independently of CMD_ALLOW_ANONYMOUS
  • CMD_ALLOW_FREEURL=true — Allows creating notes at custom URLs (e.g., /my-meeting-notes)
Security

In production, disable anonymous access (CMD_ALLOW_ANONYMOUS=false) and email registration (CMD_ALLOW_EMAIL_REGISTER=false) unless you have a specific need. Use LDAP or OAuth2 as the primary authentication method and set CMD_DEFAULT_PERMISSION=limited so new notes are not publicly readable by default.

06

Storage & Database

HedgeDoc requires a database for note content and metadata, and a storage backend for uploaded images and files.

Database options

DatabaseProduction ReadyNotes
PostgreSQLRecommendedBest concurrency, JSON support, most tested. Use version 14+ (official examples use 17).
MySQL / MariaDBSupportedWorks well. Use utf8mb4 charset for full Unicode support.
SQLiteDev OnlySingle file, no concurrent write support. Not suitable for multi-user.

The database connection is configured via CMD_DB_URL (connection string format) or individual CMD_DB_* environment variables for host, port, username, password, and database name.

Image and file upload storage

Default Local Filesystem

Uploads stored in /hedgedoc/public/uploads. Simple but requires persistent volume in containerized deployments. Not suitable for multi-replica setups without shared storage.

Scalable S3 / MinIO

Store uploads in S3-compatible object storage. Configure via CMD_S3_BUCKET, CMD_S3_REGION, CMD_S3_ACCESS_KEY_ID, CMD_S3_SECRET_ACCESS_KEY. Works with AWS S3, MinIO, Ceph RGW.

Azure Blob Storage

Store uploads in Azure Blob Storage. Set CMD_IMAGE_UPLOAD_TYPE=azure and configure CMD_AZURE_CONNECTION_STRING and CMD_AZURE_CONTAINER. Good option for Azure-hosted deployments.

Imgur

Upload images to Imgur's public hosting. Set CMD_IMAGE_UPLOAD_TYPE=imgur and provide CMD_IMGUR_CLIENTID. Not recommended for private or enterprise content.

CDN for Assets

Static assets (JS, CSS) can be served from a CDN by setting CMD_CDN_URL. This offloads bandwidth from the application server and improves load times for geographically distributed users.

Recommendation

For production deployments behind Docker or Kubernetes, use S3-compatible storage (MinIO if self-hosted) for uploads. This decouples file storage from the application container, simplifies backups, and enables multi-replica deployments.

07

Administration

HedgeDoc is a low-maintenance application, but production deployments require attention to backups, user management, and monitoring.

User management

  • Users are created on first login via the configured authentication provider
  • No built-in admin panel in HedgeDoc 1.x — user management is done via the database directly
  • Set user roles by updating the Users table: UPDATE "Users" SET "role" = 'admin' WHERE "email" = 'admin@example.com';
  • Deactivated users can be removed from the database, but their notes persist (owned by a deleted user)

Note cleanup

  • Old, unused notes accumulate over time. There is no built-in auto-cleanup
  • Write a periodic job to identify and archive notes not accessed in X months
  • Revision history can grow large; consider pruning old revisions from the Revisions table

Backup strategies

Database Backup

Use pg_dump (PostgreSQL) or mysqldump (MySQL) on a schedule. This captures all notes, users, revisions, and sessions. Automate with cron and store backups off-site.

Upload Backup

Back up the uploads directory or S3 bucket. If using local filesystem, include /hedgedoc/public/uploads in your backup. If using S3, enable versioning and cross-region replication.

# PostgreSQL backup
pg_dump -U hedgedoc -h localhost hedgedoc | gzip > hedgedoc_$(date +%Y%m%d).sql.gz

# Restore
gunzip -c hedgedoc_20260319.sql.gz | psql -U hedgedoc -h localhost hedgedoc

# Backup uploads (local filesystem)
tar -czf hedgedoc_uploads_$(date +%Y%m%d).tar.gz /hedgedoc/public/uploads/

Monitoring and health checks

  • Health endpointGET /_health is a lightweight health check endpoint ideal for load balancers. GET /status returns more detailed instance information including online users and note count
  • Metrics — HedgeDoc exposes a Prometheus-compatible endpoint at GET /metrics (since 1.8.0), providing the same stats as /status plus Node.js performance figures. Disable with enableStatsApi: false in config if not needed
  • Resource monitoring — Watch Node.js memory usage (can grow with many concurrent WebSocket connections), database connection pool, and disk usage for uploads
Operational Tip

Set up alerts on database size growth and upload storage consumption. A busy HedgeDoc instance with many image uploads can consume storage quickly. If using PostgreSQL, also monitor pg_stat_activity for connection pool exhaustion.

08

HedgeDoc 1.x vs 2.x

HedgeDoc 2.x is a ground-up rewrite of the application. It is not a simple upgrade from 1.x — it is an entirely new codebase with a different architecture, different API, and different feature set.

Architecture comparison

AspectHedgeDoc 1.xHedgeDoc 2.x
BackendExpress.js (Node.js)NestJS (Node.js, TypeScript)
FrontendServer-rendered + jQueryReact SPA (Next.js)
Real-timeSocket.IO (Operational Transform)Y.js (CRDT-based)
APIInformal REST APIFormal REST API with OpenAPI spec
EditorCodeMirror 5CodeMirror 6
StatusStable, production-ready (1.10.7)In development (alpha, ~88% complete)

Key changes in 2.x

  • CRDT instead of OT — 2.x uses Y.js (Conflict-free Replicated Data Type) for real-time sync. This is more robust than Operational Transform and enables offline editing with later sync
  • Separate frontend and backend — The React frontend communicates with the NestJS backend via a well-defined API. This enables alternative frontends and better API-first integrations
  • Modern editor — CodeMirror 6 provides better mobile support, accessibility, and extensibility
  • No direct migration path — There is no automated migration tool from 1.x to 2.x as of early 2026. Notes must be exported and re-imported
Migration Warning

As of March 2026, HedgeDoc 2.x is not yet production-ready (alpha stage, approximately 88% of the 2.0 milestone complete). For new production deployments, use HedgeDoc 1.x (latest: 1.10.7). Monitor the 2.x release schedule and plan migration once a stable release is available with a documented migration path. Do not attempt to run 2.x in production without understanding the alpha limitations.

What to tell clients

  • Deploy HedgeDoc 1.x for production use today
  • The 1.x branch continues to receive security fixes and minor updates
  • Plan for an eventual migration to 2.x, but do not block on it
  • If the client needs features only in 2.x (offline editing, better mobile), evaluate the alpha carefully and accept the risk
09

Consultant's Checklist

Pre-deployment

  • Choose database backend (PostgreSQL recommended for production)
  • Plan upload storage strategy (S3/MinIO for scalability, local for simplicity)
  • Determine authentication method (LDAP, OAuth2/OIDC, SAML)
  • Configure reverse proxy with WebSocket support (Nginx/Caddy)
  • Set CMD_DOMAIN and CMD_PROTOCOL_USESSL=true
  • Decide on anonymous access policy (CMD_ALLOW_ANONYMOUS)
  • Set default note permission (CMD_DEFAULT_PERMISSION)

Production hardening

  • Disable email registration if using external auth (CMD_ALLOW_EMAIL_REGISTER=false)
  • Set CMD_SESSION_SECRET to a strong random value
  • Enable HSTS and secure cookie flags via reverse proxy
  • Set CMD_CSP_ENABLE=true for Content Security Policy
  • Configure rate limiting at the reverse proxy level
  • Use non-root container user (default in official image)

Operations

  • Automate database backups (daily pg_dump + off-site copy)
  • Back up uploads directory or S3 bucket
  • Monitor /_health endpoint for health checks (/metrics for Prometheus)
  • Monitor disk usage for uploads and database growth
  • Set up log aggregation (application logs + reverse proxy access logs)
  • Plan revision history cleanup for long-running instances
  • Document upgrade procedure (Docker image tag update + database migration)