How to Deploy Docmost on a VPS
Updated Sep 2026
verified on Ubuntu 26.04 · Sep 2026Self-host Docmost, the collaborative wiki positioned as an open-source Confluence and Notion alternative, with PostgreSQL, Redis, HTTPS through Caddy, email for invites, and backups.
- A VPS with 1 GB RAM minimum — 2 GB is the comfortable size
- A fresh Ubuntu 24.04 or 26.04 server with root/sudo SSH access
- A domain or subdomain you can point at the server
- An SMTP account (or Postmark) if you want to invite people by email
- Docker Engine + Compose installed (see the base guide below)
What Docmost is
Docmost is a collaborative wiki and documentation tool. Several people can edit the same page at once, content is organized into spaces with groups and permissions, and pages have comments, history, search, attachments and built-in Draw.io, Excalidraw and Mermaid diagrams. It positions itself as an open-source alternative to Confluence and Notion.
The core is AGPL-3.0 and runs as one Node.js container next to PostgreSQL and Redis. Some features are licensed Business/Enterprise features rather than part of the open-source core: Bases (databases), SSO, AI features, audit logs and SCIM. Check that the features you need are in the edition you plan to run before you commit.
How it compares: Docmost vs Outline covers the other real-time editor, and Docmost vs BookStack the more structured, simpler option.
Server sizing
The catalog lists a 1 GB RAM floor. On our install-verification run (GCP e2-standard-2, Ubuntu 26.04) the three containers idled at about 592 MB of RAM together and used about 1.9 GB of disk — noticeably more than a single-container wiki, because PostgreSQL and Redis come along.
- 1 GB RAM / 1 vCPU — works for a small team, with little headroom.
- 2 GB RAM / 1–2 vCPU — the comfortable choice, especially with several people editing at once.
Plan 20 GB+ of disk; attachments are stored on local disk by default.
Prepare the server
This guide assumes Docker Engine and the Compose plugin are installed, along
with a non-root user and a ufw firewall. If not, work through
Docker & Compose on Ubuntu first.
Only SSH, 80 and 443 should be reachable:
sudo ufw status verbose
Paid link — we earn a commission if you shop through it.
Install Docmost (Docker Compose)
Docmost's installation docs download the project's docker-compose.yml and
ask you to replace three placeholders. This guide writes the same file with
the values filled in from a .env file. Start with the directory:
mkdir -p ~/docmost && cd ~/docmost
Generate the secrets once. Upstream requires APP_SECRET to be at least 32
characters and says the app fails to start if you leave the default; the
guard stops a re-run from changing secrets under an existing database:
if [ ! -f .env ]; then
cat > .env <<EOF
APP_URL=https://docs.example.com
APP_SECRET=$(openssl rand -hex 32)
DB_PASS=$(openssl rand -hex 16)
EOF
chmod 600 .env
fi
Set APP_URL to the address people will use. Upstream's example is the HTTPS
domain, and it's used for links in emails.
Now the compose file — upstream's services and images, with values read from
.env and the app port bound to loopback:
cat > docker-compose.yml <<'YAML'
services:
docmost:
image: docmost/docmost:latest
depends_on:
- db
- redis
environment:
APP_URL: ${APP_URL}
APP_SECRET: ${APP_SECRET}
DATABASE_URL: postgresql://docmost:${DB_PASS}@db:5432/docmost
REDIS_URL: redis://redis:6379
ports:
# Loopback only: Caddy is the only way in from outside.
- "127.0.0.1:3000:3000"
restart: unless-stopped
volumes:
- docmost:/app/data/storage
db:
image: postgres:18
environment:
POSTGRES_DB: docmost
POSTGRES_USER: docmost
POSTGRES_PASSWORD: ${DB_PASS}
restart: unless-stopped
volumes:
- db_data:/var/lib/postgresql
redis:
image: redis:8
command: ["redis-server", "--appendonly", "yes", "--maxmemory-policy", "noeviction"]
restart: unless-stopped
volumes:
- redis_data:/data
volumes:
docmost:
db_data:
redis_data:
YAML
Start the stack and poll the health endpoint upstream documents,
/api/health:
docker compose up -d
for i in $(seq 1 60); do
code=$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/api/health)
[ "$code" = "200" ] && break
sleep 5
done
docker compose ps
echo "Docmost health: HTTP $code"
[ "$code" = "200" ]
The docmost volume holds uploaded files (the default local storage driver);
db_data holds everything else. Upstream pins nothing — latest is what its
compose file uses — so if you want upgrades on your schedule, replace latest
with a release tag from the Docmost GitHub releases page.
HTTPS + domain
Point an A record for docs.example.com at the server, wait for it to
resolve, then terminate TLS in front of 127.0.0.1:3000 — see
Automatic HTTPS with Caddy:
docs.example.com {
reverse_proxy 127.0.0.1:3000
}
Real-time editing runs over WebSockets. Upstream's Caddy page notes that Caddy
handles WebSocket connections automatically, so the block above is complete.
If you'd rather run Caddy inside the same compose file, upstream documents
that layout too, proxying to docmost:3000; in that case remove the host port
publish.
Make sure APP_URL in .env is the HTTPS address, then apply it:
cd ~/docmost && docker compose up -d
First run: create the workspace
Open https://docs.example.com. A new install shows a setup page where you
create the workspace and the first (owner) account. Whoever submits it first
owns the instance, so do this as soon as DNS points at the server.
After that, people join by invitation from workspace settings, which
needs email. Add a mail driver to the docmost service's environment — for
SMTP, upstream's variables are:
MAIL_DRIVER=smtp
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=...
SMTP_PASSWORD=...
SMTP_SECURE=false
MAIL_FROM_ADDRESS=docs@example.com
MAIL_FROM_NAME=Docmost
(SMTP_SECURE=true is typically for port 465; Postmark is supported with
MAIL_DRIVER=postmark and POSTMARK_TOKEN.) Put the secrets in .env and
reference them from the compose file the same way as APP_SECRET, then
docker compose up -d.
Other settings worth knowing from the configuration docs:
FILE_UPLOAD_SIZE_LIMITraises the per-file upload limit.STORAGE_DRIVER=s3(plus theAWS_S3_*variables) moves attachments to S3-compatible storage such as Backblaze, Wasabi or MinIO.- Multi-factor authentication (TOTP) exists, but upstream's docs say it needs a Business or Enterprise license — on the open-source core, long unique passwords and a private instance are what you have.
Backups
Two things to keep: the PostgreSQL database and the attachments volume,
plus .env — losing APP_SECRET breaks existing sessions and anything it
signs.
Dump the database from inside its container:
cd ~/docmost
docker compose exec -T db pg_dump -U docmost docmost > docmost-db-$(date +%F).sql
test -s docmost-db-$(date +%F).sql && ls -lh docmost-db-*.sql
Archive the attachments volume with a throwaway container (Compose prefixes
volume names with the project directory, so it's docmost_docmost here —
confirm with docker volume ls):
cd ~/docmost
docker run --rm -v docmost_docmost:/data -v "$PWD":/backup alpine \
tar czf /backup/docmost-files-$(date +%F).tar.gz -C /data .
ls -lh docmost-files-*.tar.gz
Copy both archives and .env off the server. To restore, bring up only
db, load the dump with docker compose exec -T db psql -U docmost docmost < docmost-db-DATE.sql, extract the files archive into the docmost_docmost
volume, then start everything.
Upgrades
cd ~/docmost
docker compose pull
docker compose up -d
Docmost applies its database migrations when the new container starts. Take both backups first and read the release notes on GitHub — the project moves quickly. If you pinned a version tag, change it before pulling.
Troubleshooting
The docmost container exits right after starting. Read
docker compose logs docmost. The documented cause is an APP_SECRET left at
its default or shorter than 32 characters; the catalog install also found it
exits when APP_URL isn't a real URL.
Database authentication errors. The password in DATABASE_URL and
POSTGRES_PASSWORD must match. Both come from DB_PASS; PostgreSQL only reads
POSTGRES_PASSWORD when the data volume is first created, so changing it later
doesn't change the stored password.
Pages load but edits don't appear for other people. Something between the browser and Docmost isn't passing WebSockets. Caddy does by default; check any CDN or extra proxy in front of it.
Invitations never arrive. No mail driver is configured, or the SMTP values are wrong. Check the container logs after sending an invite.
Verification + next steps
You're done when https://docs.example.com loads with a valid certificate, the
setup page is gone and you're signed in as the owner, an invited colleague can
join and see your edits appear live, and a database dump plus a files archive
are stored off the box.
Next: set up email, decide whether attachments belong in S3, and schedule the backup commands with cron. If you'd like the simpler, single-editor model, the BookStack guide and the Wiki.js guide cover those. For host picks, see Best VPS for Self-Hosting.