How to Self-Host HedgeDoc in 2026: WebSockets, OAuth and Uploaded Files
Deploy HedgeDoc with the right port, durable storage, TLS, authentication and backups. Troubleshoot when real-time edits fail because WebSockets in production.
There are two versions of “running HedgeDoc”: a container exists, or the service completes its real job. Only the second matters. Here the proof is to create a note, edit it simultaneously from two browsers, upload an image and authenticate through the selected provider.
HedgeDoc serves this purpose: real-time collaborative Markdown notes. The deployment has to preserve the pieces behind that behavior; a port, a volume and a certificate are inputs, not the result.
Back up the state HedgeDoc cannot recreate
Define recovery point and recovery time for HedgeDoc in terms of database, uploaded files and authentication configuration. Mount /hedgedoc/public/uploads before bootstrap, write harmless sample data and replace the container to prove that path is actually persistent. A named volume solves redeploy persistence; it does not solve compromise or server loss.
Build a clean restore environment, use the same pinned application version and prove that notes, revisions, users and uploads return and two browsers can collaborate on the restored note. Record commands, ownership fixes and elapsed time. The backup guide is a useful standard: a backup is trusted after restoration, not after upload.
Separate HedgeDoc from its dependencies
Process health and product health are separate for HedgeDoc. Port 3000 may answer while the user-facing transaction still fails. The network contract for HedgeDoc is Postgres plus optional OAuth and SMTP providers. Keep private endpoints on internal DNS, permit only required outbound calls and give HedgeDoc a scoped service credential.
Use this readiness exercise after meaningful configuration changes: create a note, edit it simultaneously from two browsers, upload an image and authenticate through the selected provider. Keep expensive external checks out of liveness probes so a provider outage does not cause a restart loop. Capacity work should track WebSocket connections, database writes, uploaded media and document history, which is closer to HedgeDoc's real pressure than page requests.
Five checks stronger than container health
Convert the HedgeDoc smoke test into a repeatable release command or short runbook. Its output must demonstrate this outcome: create a note, edit it simultaneously from two browsers, upload an image and authenticate through the selected provider. Record the application version, container digest, route hostname and test-data identifier with the result.
Run the same check after a routine container swap and after restoring database, uploaded files and authentication configuration elsewhere. The restore has succeeded when notes, revisions, users and uploads return and two browsers can collaborate on the restored note. Compare timing and consumption related to WebSocket connections, database writes, uploaded media and document history; a large change is worth investigation even when the final action still passes.
Then exercise a safe failure: temporarily deny the test identity access to Postgres plus optional OAuth and SMTP providers. Confirm that HedgeDoc surfaces the fault and returns to normal without destructive manual edits. Preserve only the necessary, redacted log excerpt. This four-part gate covers startup, persistence, recovery and failure handling.
Start HedgeDoc without hiding the moving parts
A minimal command is useful when it reveals what the platform will later manage.
docker run -d \
--name hedgedoc \
--restart unless-stopped \
-p 127.0.0.1:3000:3000 \
-v hedgedoc-data:/hedgedoc/public/uploads \
-e CMD_SESSION_SECRET=replace-with-a-long-random-value \
-e CMD_DOMAIN=app.example.com \
-e CMD_PROTOCOL_USESSL=true \
-e CMD_DB_URL=postgres://hedgedoc:replace-password@postgres.internal:5432/hedgedoc \
quay.io/hedgedoc/hedgedoc:latest
Here port 3000 remains host-private and every required path is explicit. Add the reviewed connection settings for Postgres plus optional OAuth and SMTP providers; use private names for private services. Verify startup with both logs and the application-specific proof: create a note, edit it simultaneously from two browsers, upload an image and authenticate through the selected provider. Once verified, lock the image version so a routine replacement does not silently change behavior.
Do not give HedgeDoc the whole host
For HedgeDoc, the valuable surface is not necessarily the landing page. The main mistake is using an example session secret or permitting anonymous note creation unintentionally. Counter it deliberately: use a stable session secret, decide whether anonymous note creation is acceptable and restrict private-note access.
Generate CMD_SESSION_SECRET as a long random value; rotating it normally invalidates sessions or tokens, so plan the user impact rather than calling it an encryption migration. Use an unprivileged container user when the image supports it and mount no unrelated credentials. Apply rate or size limits at ingress where untrusted work can consume WebSocket connections, database writes, uploaded media and document history.
Test HedgeDoc from outside the server
Choose the final HedgeDoc hostname before users save callbacks or client settings, then set CMD_DOMAIN and CMD_PROTOCOL_USESSL for the public URL. The platform route should terminate TLS once and target private port 3000.
Run the acceptance transaction externally. If the client never reaches HedgeDoc, use the SSL validation checklist for DNS and certificate checks. If the request reaches HedgeDoc but real-time edits fail because WebSockets or domain settings are wrong, stop changing proxy redirects and inspect the application-specific boundary instead.
Operate HedgeDoc around its real bottleneck
Use create a note, edit it simultaneously from two browsers, upload an image and authenticate through the selected provider as the HedgeDoc smoke test after every deployment. Its supporting metrics are WebSocket connections, database writes, uploaded media and document history; alert where those resources approach a point that degrades the user action.
The main change risk is that HedgeDoc database migrations, OAuth settings and plugin or renderer changes need a staged release. A safe release starts from a restorable snapshot and validates any one-way state change before traffic moves. When real-time edits fail because WebSockets or domain settings are wrong, keep the failed container long enough to read its configuration and first error.
Where Dockup removes work for HedgeDoc
Dockup can own the replaceable platform pieces: route traffic to port 3000, issue the domain and certificate, inject secrets, attach persistent storage and connect HedgeDoc to managed or privately attached services. It can do this on Dockup infrastructure or on a server you attach.
The HedgeDoc acceptance work remains explicit. After the one-click deployment, set CMD_DOMAIN and CMD_PROTOCOL_USESSL for the public URL, connect and test Postgres plus optional OAuth and SMTP providers and run this scenario: create a note, edit it simultaneously from two browsers, upload an image and authenticate through the selected provider. That division is intentional: Dockup removes repetitive infrastructure setup without pretending that application roles, provider credentials or restore policy choose themselves.
Frequently asked questions
What does HedgeDoc need for a production deployment?
Route the HedgeDoc container on port 3000 through one HTTPS origin. The supporting network requirement is Postgres plus optional OAuth and SMTP providers. Do not call HedgeDoc ready until you can create a note, edit it simultaneously from two browsers, upload an image and authenticate through the selected provider.
Which HedgeDoc data belongs in a backup?
Persist /hedgedoc/public/uploads and include database, uploaded files and authentication configuration in the same recovery manifest. A clean HedgeDoc restore passes only when notes, revisions, users and uploads return and two browsers can collaborate on the restored note.
Does HedgeDoc require HTTPS behind a reverse proxy?
Use HTTPS for the public HedgeDoc origin and keep port 3000 on the internal route. Apply the HedgeDoc setting correctly: set CMD_DOMAIN and CMD_PROTOCOL_USESSL for the public URL. For HedgeDoc, HTTPS protects credentials or user content in transit and keeps origin-sensitive client behavior consistent.
How should a HedgeDoc upgrade be tested?
Restore current HedgeDoc state into an isolated deployment, apply the candidate version and repeat its acceptance transaction. Pay particular attention because HedgeDoc database migrations, OAuth settings and plugin or renderer changes need a staged release. Keep the previous HedgeDoc image until its data-migration and rollback boundary are understood.
