GuidesBusiness and monitoringTeam wiki with Docmost

Run a Docmost wiki with rootless Podman

Docmost on Debian 13, the open-source wiki where a team writes together in real time, with spaces, comments, page history and diagrams, in rootless Podman with PostgreSQL and Valkey under a user of its own behind Caddy, invite-only from the first minute.

Tested on Docmost 0.96.0 on Debian 13 (trixie) on a Melonslab server Updated October 14, 2026

Recommended server for this guide

SSD RAID 1 · ECC DDR4 · 10 Gbit

VC-P Alloy · 2 vCPU · 8 GB Memory · 60 GB Storage

Month to month, no lock-in 7-day money-back guarantee

€8.99/mo

Deploy now
On this page

What you will set up

Docmost is a wiki for a team's documentation, much like Confluence or Notion: routines, onboarding, meeting notes, how-tos. Pages live in spaces, each with its own members, and can be nested inside each other. Several people can edit the same page at once and see each other's cursors. The editor has tables, code blocks, callouts, file attachments and three kinds of diagrams, and every page keeps its history.

Docmost is developed in the open on GitHub by Docmost, Inc., a company under Delaware law in the United States, which also sells it as a hosted service. It comes in editions:

  • The core, which this guide sets up, is open source under the AGPL 3.0 licence and free.
  • Some features are in the same image but are locked until you add a paid licence key, for the Business or Enterprise edition. In version 0.96 they are: single sign-on (SAML, OpenID Connect, LDAP), two-factor authentication, permissions on single pages, API keys, the AI features and MCP, import from Confluence, Word and PDF, export to Word, search inside attached PDF and Word files, resolving comments, templates, personal spaces, letting viewers comment, switching off public sharing, audit logs, SCIM, page verification, and the Bases and Kanban boards. The code for them is under Docmost's own enterprise licence, not the AGPL.

Docmost has no Swedish interface. Each user can pick one of 12 languages, among them English, German, French, Spanish and Dutch, under Settings > Preferences > Language.

Here Docmost runs as a pod under a user of its own called docmost, with PostgreSQL for its data and Valkey for its queues, behind Caddy from the Podman guide.

Every step below was run on a fresh Melonslab VC-P Alloy (2 vCPU, 8 GB) with Debian 13:

  • Docmost 0.96.0 started with PostgreSQL 18 and Valkey 9. The workspace and its owner were created over an SSH tunnel before Caddy was set up, and a second attempt to create a workspace was refused.
  • Nobody could sign up: the only way in was an invite. Invites and a password reset arrived by email, and without email the invite link could be copied by hand. A deactivated member was signed out at once and could not sign in again.
  • A space was shared with a member who could only read it, and another space was hidden from him, including from search.
  • Two people edited the same page at once, in two browsers, and each saw the other's text and cursor as they typed. A comment from one showed up for the other.
  • A page got an image and a PDF, which could not be opened without signing in, a Mermaid diagram and an Excalidraw drawing. Search found a word in a page. A page's history showed two versions, and the older one was restored.
  • A Markdown file was imported as a page, and a page and a whole space were exported as Markdown and HTML.
  • Sign-ins were stored with the visitor's real address, and a forged X-Forwarded-For header was ignored. A capture of the server's traffic showed which outside services Docmost calls, in step 11.
  • An update from Docmost 0.95.0 to 0.96.0, by changing the tag, kept every page. The wiki was restored from a backup into empty volumes, and everything came back by itself after a reboot, including an edit made seconds before it.

The pod used about 400 MB of memory at rest and 520 MB after an hour of use, most of it Docmost itself.

Before you start

You need:

  • a server set up as in the Podman guide, with Caddy running;
  • an A record and an AAAA record for docs.example.com pointing at your server;
  • for invites and password resets by email, an email account that can send through your email provider's SMTP server, such as docs@example.com. Docmost works without it, as step 10 explains.

The examples use docs.example.com for the wiki, 203.0.113.10 for your server's IPv4 address, smtp.example.com for your provider's SMTP server and anna@example.com for you. Replace them throughout.

1. Create the user

As root:

useradd -m -s /bin/bash docmost
loginctl enable-linger docmost
machinectl shell docmost@

Everything up to step 5 runs as docmost.

2. Create the secrets

openssl rand -hex 32 | tr -d '\n' | podman secret create docmost-app-secret -
DB_PASSWORD=$(openssl rand -hex 24)
printf %s "$DB_PASSWORD" | podman secret create docmost-db-password -
printf %s "postgresql://docmost:$DB_PASSWORD@127.0.0.1:5432/docmost" | podman secret create docmost-db-url -
unset DB_PASSWORD

The first is Docmost's APP_SECRET, which signs sign-in sessions and encrypts the secrets Docmost stores, such as the settings of a sign-in provider. Step 12 saves a copy. The second is the database password, and the third is the address Docmost connects to the database with, which has the same password in it. Docmost only reads the password as part of that address. All three are stored by Podman, not in the files below.

3. Define the pod

mkdir -p ~/.config/containers/systemd
cd ~/.config/containers/systemd

Create docmost.pod:

[Pod]
PodName=docmost
# Only Caddy, on this server, can reach Docmost: the port is not open to the internet.
PublishPort=127.0.0.1:8187:3000

[Install]
WantedBy=default.target

Create docmost-db.container:

[Container]
ContainerName=docmost-db
Image=docker.io/library/postgres:18-alpine
Pod=docmost.pod
Volume=docmost-db:/var/lib/postgresql
Environment=POSTGRES_USER=docmost POSTGRES_DB=docmost
Secret=docmost-db-password,type=env,target=POSTGRES_PASSWORD
HealthCmd=pg_isready -U docmost
HealthInterval=10s
Notify=healthy
AutoUpdate=registry

[Service]
Restart=always

Create docmost-valkey.container:

[Container]
ContainerName=docmost-valkey
Image=docker.io/valkey/valkey:9-alpine
Pod=docmost.pod
Volume=docmost-valkey:/data
Exec=valkey-server --appendonly yes --maxmemory-policy noeviction
AutoUpdate=registry

[Service]
Restart=always

And docmost-app.container:

[Unit]
Requires=docmost-db.service docmost-valkey.service
After=docmost-db.service docmost-valkey.service

[Container]
ContainerName=docmost-app
Image=docker.io/docmost/docmost:0.96
Pod=docmost.pod
Volume=docmost-storage:/app/data/storage
Environment=APP_URL=https://docs.example.com
Environment=REDIS_URL=redis://127.0.0.1:6379
Environment=STORAGE_DRIVER=local DISABLE_TELEMETRY=true
Secret=docmost-app-secret,type=env,target=APP_SECRET
Secret=docmost-db-url,type=env,target=DATABASE_URL
# Run Node directly, so it gets the stop signal and saves open pages first.
Environment=NODE_ENV=production
WorkingDir=/app/apps/server
Exec=node dist/main
AutoUpdate=registry

[Service]
Restart=always

What the settings do:

  • APP_URL is the address Docmost puts in every link and email. It must be the public https:// address.
  • Docmost's documentation and its own example use Redis. Valkey, a fork of Redis under an open-source licence, works in its place: Docmost only needs a server that speaks the Redis protocol, and its developers say so. It holds Docmost's job queues, such as emails waiting to be sent and the next version of each page's history, and passes live edits between Docmost's processes. --appendonly yes keeps the queues on disk across a restart, and noeviction stops Valkey from dropping jobs when it is short of memory, as Docmost's own setup does.
  • STORAGE_DRIVER=local keeps uploaded images and files in the docmost-storage volume. Docmost can keep them in S3 storage instead, such as Garage, with STORAGE_DRIVER=s3 and the AWS_S3_ settings in its documentation. We did not test that.
  • DISABLE_TELEMETRY=true stops a daily report to Docmost, step 11 has the details.
  • The last three lines start Docmost's server directly instead of through the image's own start command, which does not pass on the stop signal. Docmost saves an open page about 10 seconds after the last change. Without these lines, an edit made just before a restart or a reboot was lost in our tests; with them, it was saved.
  • The tag 0.96 follows the patch releases of Docmost 0.96, which AutoUpdate=registry installs by itself. Step 13 covers moving to the next version.

Start it:

systemctl --user daemon-reload
systemctl --user start docmost-pod
systemctl --user enable --now podman-auto-update.timer

The first start downloads images that take about 1.25 GB on disk, and Docmost then sets up its database. It is ready when this prints {"status":"ok" followed by the state of the database and Valkey:

curl -s http://127.0.0.1:8187/api/health

4. Create the workspace

Until a workspace exists, Docmost shows a setup page that lets the first visitor create it, and become its owner. Do that before the wiki is online, over an SSH tunnel from your own computer. In a new terminal on your computer, run:

ssh -L 8187:127.0.0.1:8187 root@203.0.113.10

Keep it open, and open http://localhost:8187 in your browser. The Create workspace page asks for a Workspace Name, Your Name, Your Email and a Password. Fill them in, choose Create workspace, and you are signed in as the owner. Then close the tunnel with exit.

From now on, the setup page sends visitors to the login page, and a request to create another workspace gets Workspace setup already completed.

5. Put Caddy in front

Go back to root with exit, switch to machinectl shell caddy@, and add this block at the end of ~/Caddyfile:

docs.example.com {
    reverse_proxy 127.0.0.1:8187
}

Restart Caddy with systemctl --user restart caddy, open https://docs.example.com, and sign in with the email address and password from step 4.

Live editing runs over a WebSocket, which Caddy passes on without any extra setting. Caddy also passes on each visitor's address in the X-Forwarded-For header, and Docmost trusts it. That is safe here because only Caddy can reach Docmost's port, and Caddy replaces any such header a visitor sends.

6. Invite your team

Docmost has no sign-up page: people get in only by invite. Open Settings at the bottom left, then Members and Invite members. Enter one or more email addresses, choose a role, and Send invitation:

  • Member can work in the spaces they are added to.
  • Admin can also invite people, create spaces and change every workspace setting.

The owner, you, is an admin who can also delete the workspace.

Each person gets an email, "Anna Svensson invited you to Docmost", with a link to a page where they set their name and password. Until email works (step 10), Docmost shows "Invitation sent" but sends nothing: open the Pending tab, choose the three dots next to the person, then Copy link, and send them the link yourself. It works only for the address you invited.

Everyone who joins is put in the Everyone group, which can edit the General space created with the workspace. When someone leaves, choose the three dots next to them under Members, then Deactivate member. That signs them out at once, and their password no longer works.

Every page has a Share button, where Share to web publishes it on the internet with a link that needs no sign-in. Anyone who can edit a page can do that, and switching it off for the whole wiki needs a paid licence. If the wiki is for internal use only, tell your team.

7. Spaces and permissions

A space is a section of the wiki with its own members, such as IT or Management. Only the members of a space see its pages, also in search. To create one, open Settings > Spaces > Create space, give it a Space name and a Space slug, the short name in its address, and Create.

To give people access, choose the space under Settings > Spaces, then the Members tab and Add space members. Pick people or groups, and a role:

  • Full access can also change the space's settings and members.
  • Can edit can create and edit pages.
  • Can view can read pages, but not change them or comment.

Groups, under Settings > Groups, save you adding the same people to every space. Permissions are set per space: limiting a single page to some members needs a paid licence.

8. Pages, live editing and history

Open a space, and choose New page. The first line is the title. Type / on an empty line for the list of blocks: headings, lists, to-do lists, tables, code blocks, callouts, Image and File attachment, which upload from your computer, and the diagrams in step 9. You can also paste or drag images in. Markdown shortcuts such as # and ** work as you type. A page can hold other pages, which you create with the + next to it in the sidebar.

Changes save as you type. When others open the same page, they see your cursor with your name, and your text as you write it. To comment, select some text and choose Comment in the menu that appears; the comments show in the panel that opens with the speech-bubble button at the top right, where others can answer.

Page history, in the page menu (the three dots at the top right), lists earlier versions. Choose one to see it, and Restore to go back to it. A new version is saved about five minutes after the last change, or one minute for a page that is still new, so the latest edits take a few minutes to show up there.

The Search box at the top searches titles and text in every space you can see.

9. Diagrams and attachments

The / menu has three kinds of diagram:

  • Mermaid diagram draws a diagram from text, such as graph LR followed by lines like Router --> Switch. It is drawn in the browser.
  • Excalidraw (Whiteboard) is a whiteboard for sketches, which opens when you double-click it, and is saved as an image in the page with Save & Exit. It is built into Docmost, but text in a drawing loads its handwriting font from esm.sh, a public package service.
  • Draw.io (diagrams.net) opens the draw.io editor from embed.diagrams.net, run by JGraph Ltd in the United Kingdom, in the user's browser. To run the editor yourself instead, start the docker.io/jgraph/drawio image and set DRAWIO_URL to its address. We did not test that.

Images, files and diagrams are stored in the docmost-storage volume, up to 50 MB each; FILE_UPLOAD_SIZE_LIMIT=100mb in docmost-app.container raises that. A visitor who is not signed in gets an error for a file's address, even if they know it.

10. Import, export and email

Import and export

The space menu, the three dots next to Pages in the sidebar, has Import pages. Markdown and HTML import single files, Notion imports the ZIP file that Notion's own export gives you, and Upload file imports a ZIP file of Markdown and HTML files. Word, PDF and Confluence are greyed out without a paid licence. We tested Markdown, not Notion.

Export in the page menu gives you the page as Markdown or HTML, with its subpages and attachments if you choose. Export space in the space menu exports every page in it as a ZIP file. That is a good copy to read without Docmost, but not a backup: users, permissions, comments and history are not in it.

Email

Docmost sends email for invites, password resets, and notifications about pages people watch, mentions and comments. Out of the box it sends nothing, and without email:

  • invites say "Invitation sent", but arrive only if you copy the link as in step 6;
  • Forgot your password? says a reset link has been sent, but nothing arrives;
  • nobody gets notifications by email.

Accounts and sign-in with a password keep working.

To send email through your email provider, as docmost, store the account's password as a secret:

printf %s 'the-smtp-password' | podman secret create docmost-smtp-password -

Add these lines to docmost-app.container, with your own server, account and sender address:

Environment=MAIL_DRIVER=smtp SMTP_HOST=smtp.example.com SMTP_PORT=587 SMTP_SECURE=false
Environment=SMTP_USERNAME=docs@example.com MAIL_FROM_ADDRESS=docs@example.com MAIL_FROM_NAME=Docs
Secret=docmost-smtp-password,type=env,target=SMTP_PASSWORD

And restart:

systemctl --user daemon-reload
systemctl --user restart docmost-app

Port 587 with SMTP_SECURE=false connects without TLS and switches to STARTTLS as soon as the server offers it. For port 465, which uses TLS from the start, use SMTP_PORT=465 SMTP_SECURE=true. Most providers require MAIL_FROM_ADDRESS to be the same as the account. We tested the emails with a test mail server on the same machine, not through a real provider: the invite and the password reset arrived with links to https://docs.example.com.

11. Outside services

We captured the server's DNS lookups and outgoing connections while Docmost was set up and used. Docmost itself contacted one outside service, and has a second one switched off in step 3:

  • api.github.com, run by GitHub in the United States, each time someone opens the settings, to show New update next to the version number when a newer release exists. It sends nothing about the wiki. It has no setting to switch it off.
  • tel.docmost.com, Docmost's own service, once a day from 24 hours after the start, unless DISABLE_TELEMETRY=true is set. The report has Docmost's version, the number of users, pages, spaces and workspaces, and an ID made from the workspace's ID with your APP_SECRET, so it cannot be traced back. We read this in Docmost's code; our test did not run long enough to see a report.

In the users' browsers, the draw.io editor loads from embed.diagrams.net and Excalidraw loads its font from esm.sh, as step 9 says. Embeds that users add to pages, such as YouTube, Loom or Miro, load from those sites, as on any web page.

With a licence, single sign-on through authentik or Keycloak on this same server needs one of the fixes in step 8 of the Podman guide.

12. Back up

As docmost:

umask 077
mkdir -p ~/backup
podman exec docmost-db pg_dump -U docmost -d docmost > ~/backup/docmost-db.sql
podman volume export docmost-storage > ~/backup/docmost-storage.tar
podman secret inspect --showsecret --format '{{.SecretData}}' docmost-app-secret > ~/backup/app-secret.txt

That saves the database, with all pages, history, comments, users and permissions; the uploaded images, files and diagrams; and the APP_SECRET from step 2. The dump runs while Docmost keeps working. Valkey needs no backup. Copy ~/backup to another machine, for example with restic, and store it safely: it holds all your content and the secret.

To restore into an empty pod, as docmost, with the backup in ~/backup:

systemctl --user stop docmost-pod
podman volume rm docmost-db docmost-storage
podman volume create docmost-storage
podman volume import docmost-storage ~/backup/docmost-storage.tar
systemctl --user start docmost-db
podman exec -i docmost-db psql -q -U docmost -d docmost < ~/backup/docmost-db.sql
systemctl --user start docmost-pod

Starting only the database first loads the backup before Docmost sets up an empty one. On a new server, create the APP_SECRET from the backup instead of a new one in step 2:

tr -d '\n' < ~/backup/app-secret.txt | podman secret create docmost-app-secret -

13. Update

podman auto-update checks once a day for new images of Docmost, PostgreSQL and Valkey, and restarts the pod when one has changed. Docmost updates its database when it starts. To update now:

podman auto-update

Docmost publishes a new version, such as 0.97, every month or two. Everyone sees New update next to the version number at the bottom of the settings. Read the release notes on GitHub, make a backup, then change the tag in docmost-app.container, such as 0.96 to 0.97, and restart:

systemctl --user daemon-reload
systemctl --user restart docmost-app

The restart downloads the new image first, which takes a minute, and Docmost updates its database as it starts.

Troubleshooting

The page header says "Real-time editor connection lost. Retrying...", and other people's changes do not show up. The WebSocket to /collab does not get through. With the Caddy block from step 5 it does; a different proxy in front, such as a CDN, has to pass on WebSockets too.

An invite or a password reset never arrives. As docmost, run journalctl --user -u docmost-app | grep -i -E 'mail|smtp'. A line with "Error processing send-email job" has the email server's answer, or the reason it could not be reached. If there is no such line, the MAIL_DRIVER=smtp line is missing, and Docmost discards every email.

Docmost does not start, and the log says something about APP_SECRET. The secret is missing or shorter than 32 characters. Check it with podman secret ls, and create it again as in step 2.

Stopping or restarting Docmost takes 10 seconds. Docmost saves open pages when it stops and then waits, and Podman stops it after 10 seconds. That is expected with the settings in step 3.

Run it on your own server

SSD RAID 1 · ECC DDR4 · 10 Gbit

VC-P Alloy

€8.99/mo

vCPU
2
Memory
8 GB
Storage
60 GB
Transfer
10 TB
Performance
SSD · RAID 1
  • Full root access
  • Native /64 IPv6
  • RAID-protected storage
  • Malmö, Sweden
  • Month to month, no lock-in
  • 7-day money-back guarantee
All guides