Skip to content

How to Deploy Docmost on a VPS

Updated Sep 2026

verified on Ubuntu 26.04 · Sep 2026
We earn commissions when you shop through the links below. Full disclosure →

Self-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.

Before you start
  • 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)
Need a box for this guide? Kamatera's free tier lets you spin one up now.Start free on Kamatera → (opens in new tab)

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
Where to host itaffiliate disclosure
Hetzner Cloudrun it on
2 vCPU · 4 GB RAM · 80 GB SSD · $23.59/mo
Get Hetzner Cloud (opens in new tab)
Kamaterafree trial
1 vCPU · 1 GB RAM · 20 GB SSD · $4.00/mo
Start free on Kamatera → (opens in new tab)
DigitalOceanalso works on
1 vCPU · 1 GB RAM · 25 GB SSD · $6.00/mo
Deploy on DigitalOcean → (opens in new tab)

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_LIMIT raises the per-file upload limit.
  • STORAGE_DRIVER=s3 (plus the AWS_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.

Next steps

How to self-host Docmost →More self-hosted wiki & docs tools →Automatic HTTPS with Caddy →Run Claude Code with Ollama on Your Own VPS →Deploy Coolify on a VPS →How to Deploy Actual Budget on a VPS →How to Deploy AnythingLLM on a VPS →How to Deploy Appwrite on a VPS →How to Deploy Audiobookshelf on a VPS →How to Deploy Authelia on a VPS →How to Deploy authentik on a VPS →How to Deploy Baserow on a VPS →How to Deploy Beszel on a VPS →How to Deploy Bitwarden on a VPS →How to Deploy BookStack on a VPS →How to Deploy CapRover on a VPS →How to Deploy Checkmate on a VPS →How to Deploy Directus on a VPS →How to Deploy docker-mailserver on a VPS →How to Deploy Dokku on a VPS →How to Deploy Dokploy on a VPS →How to Deploy Firefly III on a VPS →How to Deploy Forgejo on a VPS →How to Deploy Gatus on a VPS →How to Deploy Ghostfolio on a VPS →How to Deploy Gitea on a VPS →How to Deploy GitLab on a VPS →How to Deploy GlitchTip on a VPS →How to Deploy Grafana on a VPS →How to Deploy Graylog on a VPS →How to Deploy Headscale on a VPS →How to Deploy Healthchecks on a VPS →How to Deploy Home Assistant on a VPS →How to Deploy Immich on a VPS →How to Deploy Jan on a VPS →How to Deploy Jellyfin on a VPS →How to Deploy Karakeep on a VPS →How to Deploy Keycloak on a VPS →How to Deploy Leantime on a VPS →How to Deploy LibreChat on a VPS →How to Deploy Linkwarden on a VPS →How to Deploy LocalAI on a VPS →How to Deploy Mailcow on a VPS →How to Deploy Mailu on a VPS →How to Deploy Matomo on a VPS →How to Deploy Mattermost on a VPS →How to Deploy Meilisearch on a VPS →How to Deploy Memos on a VPS →How to Deploy n8n on a VPS →How to Deploy Navidrome on a VPS →How to Deploy NetBird on a VPS →How to Deploy Netdata on a VPS →How to Deploy Nextcloud on a VPS →How to Deploy Next.js to a VPS →How to Deploy Nginx Proxy Manager on a VPS →How to Deploy NocoDB on a VPS →How to Deploy ntfy on a VPS →How to Deploy Ollama on a VPS →How to Deploy Open WebUI on a VPS →How to Deploy OpenHands on a VPS →How to Deploy OpenObserve on a VPS →How to Deploy OpenProject on a VPS →How to Deploy Outline on a VPS →How to Deploy Pangolin on a VPS →How to Deploy Paperless-ngx on a VPS →How to Deploy Passbolt on a VPS →How to Deploy Plane on a VPS →How to Deploy Plausible Analytics on a VPS →How to Deploy Pocket ID on a VPS →How to Deploy PocketBase on a VPS →How to Deploy Prometheus on a VPS →How to Deploy Psono on a VPS →How to Deploy Radarr on a VPS →How to Deploy Rocket.Chat on a VPS →How to Deploy SigNoz on a VPS →How to Deploy Sonarr on a VPS →How to Deploy Stalwart on a VPS →How to Deploy Stirling-PDF on a VPS →How to Deploy Supabase on a VPS →How to Deploy Synapse on a VPS →How to Deploy Taiga on a VPS →How to Deploy TeamPass on a VPS →How to Deploy Tinyauth on a VPS →How to Deploy Traefik on a VPS →How to Deploy Trilium on a VPS →How to Deploy Twenty CRM on a VPS →How to Deploy Umami on a VPS →How to Deploy Uptime Kuma on a VPS →How to Deploy Vaultwarden on a VPS →How to Deploy Vikunja on a VPS →How to Deploy wg-easy on a VPS →How to Deploy Wiki.js on a VPS →How to Deploy Zabbix on a VPS →How to Deploy Zitadel on a VPS →How to Deploy Zulip on a VPS →Docker & Compose on Ubuntu 26.04 →Building AI Workflows with n8n →Install Open WebUI with Ollama →Adding AI-Powered Insights to Plausible Analytics →Building AI-Powered Apps with Supabase and pgvector →

We use analytics cookies (Google Analytics, PostHog) to see which guides are useful. No ad networks, no cross-site tracking. See our privacy policy.