HedgeDoc is an open-source collaborative Markdown editor. Think Google Docs for Markdown: multiple people can edit the same note in real-time, with support for diagrams, math, polls, and slide decks. In this post we’ll walk through setting up your own instance on a server, secured with HTTPS.


Prerequisites

  • A Linux server with Docker and Docker Compose
  • A domain name pointing to your server (e.g. notes.alipourimjourneys.ir)
  • Nginx installed for reverse proxying
  • Certbot for Let’s Encrypt certificates

1. Create the project directory

mkdir ~/hedgedoc && cd ~/hedgedoc

2. Create .env

POSTGRES_PASSWORD=ChangeThisStrongPassword
HD_DOMAIN=notes.alipourimjourneys.ir

Generate a strong password with:

openssl rand -base64 32

3. Create docker-compose.yml

version: "3.9"

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

  hedgedoc:
    image: quay.io/hedgedoc/hedgedoc:1.10.2
    depends_on:
      - db
    environment:
      CMD_DB_URL: postgres://hedgedoc:${POSTGRES_PASSWORD}@db:5432/hedgedoc
      CMD_DOMAIN: ${HD_DOMAIN}
      CMD_PROTOCOL_USESSL: "true"
      CMD_URL_ADDPORT: "false"
      CMD_PORT: "3000"
      CMD_EMAIL: "true"
      CMD_ALLOW_EMAIL_REGISTER: "false"
    volumes:
      - uploads:/hedgedoc/public/uploads
    ports:
      - "127.0.0.1:3000:3000"
    restart: unless-stopped

volumes:
  db:
  uploads:

Bring it up:

docker compose up -d

4. Get a Let’s Encrypt certificate

Request a cert with a DNS challenge:

sudo certbot certonly   --manual   --preferred-challenges dns   -d notes.alipourimjourneys.ir   -m you@example.com   --agree-tos --no-eff-email

Add the TXT record certbot asks for, wait for DNS to propagate, then continue.
Certificates will be in:

/etc/letsencrypt/live/notes.alipourimjourneys.ir/

5. Configure Nginx

Create /etc/nginx/sites-available/notes.alipourimjourneys.ir:

server {
  server_name notes.alipourimjourneys.ir;

  listen 80;
  listen [::]:80;
  return 301 https://$host$request_uri;
}

server {
  server_name notes.alipourimjourneys.ir;

  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  ssl_certificate     /etc/letsencrypt/live/notes.alipourimjourneys.ir/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/notes.alipourimjourneys.ir/privkey.pem;

  location / {
    proxy_pass http://127.0.0.1:3000;
    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 https;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }
}

Enable the config and reload Nginx:

sudo ln -s /etc/nginx/sites-available/notes.alipourimjourneys.ir /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

6. Create users

Because we disabled self-registration, create accounts manually:

docker compose exec hedgedoc ./bin/manage_users --add alice@example.com

You’ll be prompted for a password.
To reset a password later:

docker compose exec hedgedoc ./bin/manage_users --reset alice@example.com

7. Done!

Visit https://notes.alipourimjourneys.ir and log in with the user you created. You now have your own collaborative Markdown editor 🎉


Extras:

  • Backups: dump the PostgreSQL database and save the uploads volume.
  • Upgrades: docker pull quay.io/hedgedoc/hedgedoc:latest && docker compose up -d.
  • Integrations: HedgeDoc supports S3/MinIO image storage, GitHub/GitLab/Google login, and more.