Git-style history for .docx — without asking anyone to learn Git.
Open-source, self-hostable version control for Word documents. Every save becomes an immutable, numbered version. Two people editing at once branch instead of overwriting each other, and merge in one click. You get a real redline between any two versions even if nobody ever turned Track Changes on.
Two front doors: a web UI for the people who just need to work on the document, and a REST API for
developers — the same surface, not a subset. One stack, docker compose up.
easydocs exists because Simuldocs, the hosted service this way of working lived in, shut down. This project is an independent reimplementation of that workflow — not affiliated with Simuldocs — built so the people who relied on it don't lose it. Self-hostable and AGPL-3.0 on purpose: those are exactly the guarantees a discontinued service can't take away.
Download the compose bundle from the latest release — no clone, no build, the image is pinned by version and signed with cosign:
mkdir easydocs && tar xzf easydocs-*-compose.tar.gz -C easydocs && cd easydocs
cp .env.example .env # then edit it — two secrets, see below
docker compose up -dThen open http://localhost:8080 and register. The first account you create also creates your organization, and you are its owner. Invite colleagues from Settings → Organization (or from a document's Members panel) and send them the invitation link; someone who belongs to more than one organization gets a switcher in the header.
From there, the User guide walks every screen and action — uploading, editing, branching and merging, publishing, approvals, sharing — and the API does everything the UI does.
Two things to set in .env:
Jwt__Secretships deliberately too short to boot — the app fails fast under 32 bytes. Generate a real one withopenssl rand -base64 48. (A placeholder that worked would mean every install that took the quickstart literally signed its sessions with a secret published in this repository.)POSTGRES_PASSWORD— anything non-placeholder.
The stack is three containers: the app (with LibreOffice bundled for PDF rendering), PostgreSQL 16, and Collabora Online for in-browser editing.
⚠️ Plain HTTP beyond localhost silently breaks login. The session cookie isSecure, so a browser only sends it over HTTPS — or tolocalhost, which is why the quickstart works. Serve easydocs athttp://192.168.1.50:8080orhttp://easydocs.internaland login will appear to succeed, the browser will discard the cookie, and you land back on the sign-in screen with no error. Terminate TLS at a reverse proxy in front of the app — see the self-hosting guide.
Using Claude Code, Cursor, Copilot or any other coding agent? Paste this — it carries every footgun so the agent lands a working install on the first try:
Set up easydocs (https://github.com/Robertzu43/easydocs) on this machine. Docker must be running.
1. Download the easydocs-*-compose.tar.gz asset from the latest GitHub release
(https://github.com/Robertzu43/easydocs/releases/latest) and extract it into a new
directory called easydocs. Do NOT build from source.
2. In that directory: cp .env.example .env, then edit .env — set Jwt__Secret to the output
of `openssl rand -base64 48` (the placeholder is deliberately too short to boot), and set
POSTGRES_PASSWORD to a random value (update it in ConnectionStrings__Postgres too, where
the same password appears).
3. Run `docker compose up -d`, then poll http://localhost:8080/health until it returns
{"status":"ok"} (first boot pulls images and runs migrations — allow a few minutes).
4. Tell me to open http://localhost:8080 and register: the first account created also
creates the organization and owns it. Point me at the user guide:
https://robertzu43.github.io/easydocs/user-guide/
5. If this machine is a remote server rather than my laptop: STOP before exposing anything.
The session cookie is Secure-only, so login silently fails over plain HTTP anywhere but
localhost — TLS at a reverse proxy is required first, per
https://robertzu43.github.io/easydocs/self-hosting/
git clone https://github.com/Robertzu43/easydocs && cd easydocs/deploy/compose
cp .env.example .env # same two secrets
docker compose up --build- Every save is a version. Immutable, numbered
X.Y.Z, attributed to an author, with a change summary. Nothing is ever silently overwritten. - Edit in the browser. Collabora Online via a WOPI host — no upload/download dance, no Word install.
- Branch on stale, merge in one click. Two people editing the same version produce two branches rather than a lost edit. The console shows the branch indented under the main line with a Merge button, and the merge attributes the incoming author's changes.
- Real redlines, Track Changes or not. Compare any two versions and get insertions and deletions computed from the documents themselves.
- Publish, PDF, approve. Publish minor or major, get renumbering plus a rendered PDF, then request approval from named document members — one immutable decision each, cancellable while open.
- Client copies with push-back review. Fork a version into an isolated copy with its own members and its own history. When the copy pushes work back, a member of the original reviews it: accept and it lands as a clearly-labelled incoming branch, reject and it never enters the history.
- Share links. Version-scoped, expiring, revocable, and audited — an anonymous view lands on the audit trail with a view count. The recipient needs no account and sees a plain download page: no app chrome, no sign-up wall.
- Folders, members, revert, trash, and an audit trail for every one of the above.
The whole lifecycle is doable in a browser without ever touching an HTTP client — which is what the Playwright suite asserts, against the shipped container image rather than a dev server.
- OIDC/SSO — point three env keys at any OpenID Connect provider and the login screen grows a "Sign in with SSO" entry. MFA — opt-in TOTP with single-use recovery codes, per account.
- Desktop "Open in Word" — a version action hands desktop Word an
ms-word:URL over WebDAV; saving in Word commits a new version through the same write path as everything else. - Full-text content search — the dashboard search box matches document content, not just names.
- Graphical revision graph — a List/Graph toggle on the History tab.
- S3-compatible blob storage, blob garbage collection, a durable job queue, and configurable trusted proxies — see the self-hosting guide.
Before exposing an install to anyone, read the
known limitations in SECURITY.md — notably
that per-IP rate limiting behind a reverse proxy needs ASPNETCORE_FORWARDEDHEADERS_ENABLED=true
(and, since v1.1, ForwardedHeaders__KnownProxies__N to narrow the trust).
Everything the UI does, the API does — it is the same surface, not a subset.
- Interactive docs:
/docson your install (self-contained, no external CDN) - OpenAPI 3.1:
/openapi/v1.json - Auth:
ed_-prefixed personal access tokens asAuthorization: Bearer ed_…, or the session cookie for the browser. A token can never exceed the role of the user who minted it. - Live updates: server-sent events per document at
/api/v1/documents/{id}/events.
Worked end-to-end examples: automation recipes.
ASP.NET Core (.NET 10) minimal APIs · PostgreSQL 16 · EF Core · React 19 + Vite 8 + react-router ·
Collabora Online (WOPI) · LibreOffice for PDF · content-addressed filesystem blobs. One container for
the app; the SPA is built into it and served from wwwroot.
Guides are published at https://robertzu43.github.io/easydocs/:
- Getting started — one
.docxfrom upload to a second version - User guide — task-by-task instructions for every screen of the web UI, plus the API
- Concepts — the mental model: numbering, branches, redlines, approvals
- Self-hosting guide — TLS,
.env, proxies, backups, upgrades - Automation recipes — the full lifecycle over the REST API
And in the repo:
- ROADMAP.md — what's planned next, and how to influence it
- SECURITY.md — private disclosure, and the known v1 limitations
- GOVERNANCE.md — how decisions get made, the RFC process, release versioning
- CHANGELOG.md — what each release delivered, most recently v1.1.0
- Design specs and conformance profile:
docs/superpowers/specs/
If you try easydocs, say how it went — that's the most useful thing you can do for the project right now.
- Something broke, or something's missing? Open an issue. "This felt wrong" is a valid report; describe the problem, not the solution.
- Questions and ideas live in Discussions.
- Want a roadmap item sooner? A 👍 or a "here's how I'd use it" comment on its issue is exactly the signal that decides ordering — see ROADMAP.md.
- Want to write code? Start with CONTRIBUTING.md and the
good first issuelabel. Schema and public-API changes need agreement in an issue first (GOVERNANCE.md); everything else, just open a PR.
easydocs exists because a closed service took a workflow down with it. It stays healthy the same way it started: people who need it, keeping it alive.
Everything in this repository today is AGPL-3.0 (LICENSE) — server, SPA, tests, deploy files, docs.
| Path | License |
|---|---|
| Everything in this repo | AGPL-3.0 — the whole repository right now |
packages/* — future API client SDKs |
MIT, when written. The directory does not exist yet. |
AGPL is the right licence for a self-hostable server — it keeps modifications to a hosted easydocs
available to its users. It is the wrong licence for a thin client library, so future SDKs will live
under packages/* with their own MIT LICENSE. Until that directory exists, assume AGPL-3.0 for
anything you take from here. Full reasoning:
spec §14.
Contributions are under the Developer Certificate of Origin — sign off every commit with
git commit -s. No CLA, and you keep the copyright to your contributions. Start with
CONTRIBUTING.md; conduct is governed by the
Code of Conduct (Contributor Covenant 2.1).