Most self-hosted document apps answer one question: where's that letter? Mayan EDMS answers a harder set: who approved this contract, which version did legal sign off on, who's allowed to see it, and when can we legally destroy it?

Mayan is an electronic document management system in the enterprise sense. It has OCR and search like the others, but its real strengths are structure and control: document types with required metadata, multi-step approval workflows, version history, digital signatures and permissions down to a single document. It's free and open source (GPL-2.0), written in Python on Django, has been developed for more than a decade, and is on the 4.12 release line.

The mental model

Mayan has more moving parts than a home-scanning app, and they make sense once you see how they fit together. Everything hangs off the document type:

DOCUMENT TYPE   "Invoice", "Contract", "HR Record"
  ├─ metadata types   vendor, amount, due date (required or optional)
  ├─ OCR + parsing    on/off, language
  ├─ workflows        which processes this type goes through
  ├─ retention        trash after N days, delete after N more
  └─ antivirus        scan uploads with ClamAV or not

Then, on top of documents:
  TAGS       colored labels
  CABINETS   hand-made folder trees (a document can be in several)
  INDEXES    folder trees Mayan builds for you from templates
  ACLs       who can do what, per document, type or object

The distinction between cabinets and indexes is the most important one to grasp. Cabinets are folders you curate by hand. Indexes are generated automatically: you write a template once, and Mayan sorts every document into a virtual folder tree from its metadata, updating it as documents change.

Feature tour

  • Metadata. Typed fields per document type, with defaults, lookups and validation. "Invoice" can require a vendor and an amount, while "Contract" requires parties and an expiry date.
  • OCR and parsing. Tesseract is built in, and the work can be spread across several worker machines. Text from born-digital files is parsed directly. Built-in file metadata (author, camera settings, GPS) is extracted automatically.
  • Workflows. Real state machines with states, transitions, actions on entry and exit, and automatic expiry and escalation. Every change is logged.
  • Versions. Multiple versions of a document, each of which can be downloaded or restored, with an audit trail.
  • Check-out and check-in, so two people don't edit the same document at once.
  • Signatures. Verify embedded cryptographic signatures, attach detached ones, and record captured handwritten signatures.
  • Smart links that connect related documents automatically by their metadata, such as a purchase order and its invoices.
  • Duplicate detection, with exact-file and exact-label matching out of the box.
  • Search. Full-text search over content and metadata. A built-in backend is the default, and Elasticsearch is available for big archives.
  • Access control. Unlimited roles, a permission for every single operation, and ACLs on individual objects, with LDAP, OpenID Connect and other single sign-on options.
  • Antivirus. Optional ClamAV scanning of uploads, switched on per document type.
  • A full REST API with OpenAPI documentation, so other systems can push documents in and pull them out.

Install it with Docker

The official route is Docker Compose, and getting started really is three commands:

curl https://gitlab.com/mayan-edms/mayan-edms/-/raw/master/docker/docker-compose.yml -O
curl https://gitlab.com/mayan-edms/mayan-edms/-/raw/master/docker/.env -O
docker compose up --detach

Read this before you run the last command. The compose file falls back to default passwords for its database, message queue and cache (mayandbpass and friends). Set your own in .env before the first start, because they're baked into the database when it's created:

# add to .env
MAYAN_DATABASE_PASSWORD=a-long-random-string
MAYAN_RABBITMQ_PASSWORD=another-long-random-string
MAYAN_REDIS_PASSWORD=and-another-one

# the web UI listens on port 80 by default; move it if 80 is taken
MAYAN_FRONTEND_HTTP_PORT=8080

The stack is assembled with Compose profiles. The default in .env is:

COMPOSE_PROFILES=all_in_one,postgresql,rabbitmq,redis

That runs the Mayan app (web interface and workers in one container) with PostgreSQL for data, RabbitMQ for the task queue and Redis for locking and caching. Add profiles as you need them:

elasticsearch       a faster search backend for large archives
traefik             reverse proxy with automatic Let's Encrypt HTTPS
postgresql-backup   scheduled database dumps
index_mirror        expose an index as a read-only folder tree on the host
cabinet_mirror      the same, for a cabinet
extra_worker_*      split workers out to scale up

On first load, the login page shows automatically generated admin credentials. Log in with them, change the password straight away (the notice disappears once you do), and create real user accounts.

Be realistic about resources. Even the all-in-one setup runs four services, including a database and a message broker. Plan on a few gigabytes of RAM and a few CPU cores, more if you'll OCR a lot. This is a VPS or homelab-server app, not a Raspberry Pi one.

A worked example: invoice approval

Here's what Mayan is built for. Say invoices arrive by email, need a manager's approval, and must be kept for seven years.

1. The document type

Create an Invoice document type with required metadata types vendor, amount and due_date. Under its retention settings, keep files for seven years before they move to the trash. Turn on ClamAV for it, since email attachments are where malware arrives.

2. The source

Add an email source (IMAP or POP3) pointed at invoices@, assigned to the Invoice type. Attachments come in typed and ready for metadata. For paper, a watch folder that your scanner drops into works the same way, and a staging folder lets you preview files before uploading them.

3. The workflow

[Received] --submit--> [Awaiting approval] --approve--> [Approved] --pay--> [Paid]
                               |
                               +--reject--> [Rejected]

Awaiting approval: escalate to the finance lead if untouched for 3 days
Approved:          action = add tag "approved", email accounts payable

Each transition can be limited to specific roles: only managers can approve, and only finance can mark something paid. Every step is recorded in the document's workflow log with who did it and when.

4. The index

Finally, an index that files invoices automatically by year, then vendor. Each level is a small template:

Level 1:  {{ document.date_added|date:"Y" }}
Level 2:  {{ document.metadata_value_of.vendor }}

Browse the index and you see 2026 / Electric Co / …, rebuilt live as invoices arrive. Turn on the index_mirror profile and the same tree appears as a read-only folder on the server, which is handy for backup tools or a file share.

Things to know before you commit

  • There's a learning curve. Document types, metadata types, indexes, smart links and workflows are each separate screens. Budget an afternoon to model your documents before you upload anything, because restructuring later is much harder.
  • The interface is functional, not fancy. It's a dense admin-style UI built for daily office work, not a slick consumer app.
  • Back up two things: the PostgreSQL database (the postgresql-backup profile helps) and the app volume at /var/lib/mayan, which holds the files themselves. One without the other is useless.
  • Keep it private. Like any archive of sensitive paperwork, run it behind a VPN or an authenticated reverse proxy. The traefik profile handles HTTPS, but HTTPS alone doesn't make it safe to expose to the internet.
  • The docs are thorough, and the project also publishes books and a knowledge base if you're deploying it seriously.

Mayan EDMS or Paperless-ngx?

I covered Paperless-ngx in a separate transmission today, and they're the two names that come up every time. They solve different problems:

                    PAPERLESS-NGX            MAYAN EDMS
Built for           homes, small offices     teams, organizations
Organizing          tags, auto-classifier    types, metadata, indexes
Workflows           automation rules         approval state machines
Versions            yes                      yes, with check-out/in
Signatures          no                       verify and capture
Permissions         per user and document    roles and ACLs
Setup effort        an evening               a weekend of planning
Hardware            Raspberry Pi is fine     a real server
License             GPL-3.0                  GPL-2.0

If your goal is "make the paper pile searchable and stop thinking about it", choose Paperless-ngx. If you're running a small business, a nonprofit or a club, where documents have owners, approvals, versions and retention rules, Mayan is the one built for that, and it's hard to beat for free software.

Verdict

Mayan EDMS is what you reach for when documents are part of a process rather than just a pile. It asks more of you up front, in planning and in hardware, and gives you something few open-source tools offer in return: a document system with real structure, audit trails and access control, running entirely on your own server.

Start with the documentation and the GitLab repository. Links are also in the downloads directory and the resource index.

End of transmission.