HedgeDoc on a VPS: Real-Time Collaborative Markdown Editor for Teams and Documentation
HedgeDoc (formerly CodiMD) is an open-source, real-time collaborative Markdown editor — multiple people edit the same document simultaneously with live preview, like Google Docs but for Markdown. It’s ideal for meeting notes, technical documentation, runbooks, and presentations (via reveal.js slide mode). Self-hosted on a VPS, your documents never leave your infrastructure, and there are no per-seat fees.
What HedgeDoc Provides
- Real-time collaboration: See other users’ cursors and edits as they type
- Live preview: Side-by-side Markdown source and rendered output
- Presentation mode: Convert Markdown to reveal.js slides with
---slide separators - Code highlighting: Syntax highlighting for 100+ languages in fenced code blocks
- Math rendering: LaTeX equations via MathJax or KaTeX
- Diagrams: Mermaid, PlantUML, Vega-Lite charts inline
- Export: PDF, Markdown, HTML
- Auth: Email, LDAP, GitHub, GitLab, Google, SAML OAuth
Step 1: Docker Compose Setup
<code">mkdir -p /opt/hedgedoc && cd /opt/hedgedoc nano docker-compose.yml
<code">version: '3.8'
services:
hedgedoc:
image: quay.io/hedgedoc/hedgedoc:latest
container_name: hedgedoc
restart: always
ports:
- "127.0.0.1:3000:3000"
environment:
CMD_DB_URL: postgres://hedgedoc:${POSTGRES_PASSWORD}@hedgedoc-db/hedgedoc
CMD_DOMAIN: docs.yourdomain.com
CMD_URL_PATH: /
CMD_PROTOCOL_USESSL: "true"
CMD_ALLOW_ANONYMOUS: "false" # Require login to create notes
CMD_ALLOW_ANONYMOUS_EDITS: "false"
CMD_ALLOW_FREEURL: "true" # Custom slugs: /docs.yourdomain.com/my-note
CMD_DEFAULT_PERMISSION: private
CMD_SESSION_SECRET: ${SESSION_SECRET}
CMD_EMAIL: "true" # Email/password login
CMD_ALLOW_EMAIL_REGISTER: "true"
# SMTP
CMD_SMTP_HOST: smtp.mailgun.org
CMD_SMTP_PORT: 587
CMD_SMTP_TLS: "true"
CMD_SMTP_USER: [email protected]
CMD_SMTP_PASS: ${SMTP_PASSWORD}
CMD_SMTP_FROM: [email protected]
# GitHub OAuth (optional)
CMD_GITHUB_CLIENTID: ${GITHUB_CLIENT_ID:-}
CMD_GITHUB_CLIENTSECRET: ${GITHUB_CLIENT_SECRET:-}
volumes:
- hedgedoc_uploads:/hedgedoc/public/uploads
depends_on:
hedgedoc-db:
condition: service_healthy
hedgedoc-db:
image: postgres:16-alpine
restart: always
environment:
POSTGRES_DB: hedgedoc
POSTGRES_USER: hedgedoc
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- hedgedoc_db:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U hedgedoc"]
interval: 10s
timeout: 5s
retries: 5
volumes:
hedgedoc_uploads:
hedgedoc_db:
<code">cat > .env << 'EOF' POSTGRES_PASSWORD=StrongHedgeDocDbPassword! SESSION_SECRET=$(openssl rand -hex 32) SMTP_PASSWORD=your_mailgun_password EOF chmod 600 .env docker compose up -d
Step 2: Nginx Reverse Proxy
<code">sudo nano /etc/nginx/sites-available/hedgedoc
<code">server {
listen 443 ssl http2;
server_name docs.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/docs.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/docs.yourdomain.com/privkey.pem;
client_max_body_size 50M;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}
<code">sudo certbot --nginx -d docs.yourdomain.com sudo ln -s /etc/nginx/sites-available/hedgedoc /etc/nginx/sites-enabled/ sudo systemctl reload nginx
Step 3: Creating and Sharing Notes
<code"># Create a note: # https://docs.yourdomain.com → New Note → start typing Markdown # Share for collaboration: # Share → anyone with link can view/edit (based on permission settings) # Permissions: Owner, Signed-in users, Everyone (anonymous) # Custom URL: # If CMD_ALLOW_FREEURL=true: visit https://docs.yourdomain.com/my-meeting-2025-01-15 # Creates a note at that URL # Collaboration: # Share the URL → collaborators open it → all see each other's edits in real-time # Edit mode: shows individual cursors with author names
Step 4: Presentation Mode
<code"># Create slides with HedgeDoc:
---
# Slide 1 Title
Content for slide 1
---
# Slide 2
- Bullet 1
- Bullet 2
---
## Code on Slide 3
```python
def hello():
return "world"
```
---
# Red Background Slide
# View as presentation:
# Click "Present" button → reveal.js slideshow
# Navigate: arrow keys or spacebar
Step 5: Diagram Integration
<code"># Mermaid diagrams inline:
```mermaid
graph LR
A[Client] --> B[Nginx]
B --> C[PHP-FPM]
C --> D[PostgreSQL]
```
# PlantUML:
```plantuml
@startuml
Alice -> Bob: Hello
Bob --> Alice: Hi!
@enduml
```
# Vega-Lite chart:
```vega-lite
{
"data": {"values": [{"x": 1, "y": 2}, {"x": 2, "y": 4}]},
"mark": "line",
"encoding": {
"x": {"field": "x", "type": "quantitative"},
"y": {"field": "y", "type": "quantitative"}
}
}
```
Getting Started
HedgeDoc uses 200–400 MB RAM. A 2 GB Ubuntu VPS at VPS.DO runs it comfortably alongside other services. For engineering teams that use Markdown extensively — README files, runbooks, architecture docs — HedgeDoc provides the collaborative editing experience of Google Docs without leaving the Markdown ecosystem. Notes can be exported as Markdown for version control in Git.
Conclusion
HedgeDoc transforms Markdown from a solo writing format into a real-time collaborative medium — multiple editors, live preview, diagram rendering, and presentation mode in one self-hosted application. For teams that value Markdown over rich-text editors, self-hosted HedgeDoc provides privacy-first document collaboration with no per-seat pricing and full data ownership.