Caption: Self-hosted Docmost runs the wiki app with PostgreSQL, Redis, and local file storage behind HTTPS on infrastructure you control.
Introduction
Docmost is an open-source collaborative documentation platform for teams that want a Notion-style wiki experience without sending every internal page to a hosted SaaS product. It provides spaces, pages, permissions, real-time editing, search, and file attachments in a self-hosted stack that you can run next to the rest of your homelab or agency tooling.
Self-hosting Docmost makes sense when runbooks, onboarding guides, architecture notes, and client documentation should stay on your VPS. It is also a practical alternative when you already operate Docker services such as Authentik, MinIO, or Gitea and want a wiki that fits the same operational model: Compose files, named volumes, reverse-proxy TLS, and scheduled backups.
This guide installs Docmost on Ubuntu 24.04 LTS using the official Docker Compose template. PostgreSQL stores application data, Redis supports real-time collaboration, local storage holds uploads, and Caddy terminates HTTPS with WebSocket support. The example uses https://docmost.example.com. Replace domains, passwords, and secrets before production use.
Why Choose Docmost?
- Collaborative wiki UX: Spaces, nested pages, and a real-time editor make it approachable for writers who are not comfortable living in raw Markdown repositories.
- Self-hosted by design: Official Docker images and Compose templates keep the app, database, and Redis under your control.
- WebSocket-aware editing: Multiple people can edit together when the reverse proxy correctly forwards upgrade headers.
- Flexible storage: Local volumes work out of the box; S3-compatible or Azure Blob storage is available when you outgrow a single disk.
- Invite-ready email: SMTP or Postmark configuration lets you invite teammates without sharing a single admin password.
- Health endpoint:
/api/healthgives reverse proxies and monitors a clear readiness check. - Straightforward upgrades: Pull the latest
docmost/docmostimage and recreate the app service.
Treat Docmost as a production service. A leaked APP_SECRET or weak database password is enough to expose your workspace. Plan disk for PostgreSQL growth and attachment storage before the wiki becomes the team source of truth.
Prerequisites
Hardware Recommendations:
- Minimum: 1 CPU core, 2 GB RAM, 20 GB SSD for a personal or small-team deploy
- Recommended: 2+ CPU cores, 4 GB RAM, 40 GB+ SSD for active collaboration and attachments
- Extra headroom if you enable AI features or move storage to a remote S3 endpoint
- Off-server backup storage for database dumps and the Docmost storage volume
Software and Accounts:
- Ubuntu 24.04 LTS with sudo access
- Domain DNS
A/AAAArecords fordocmost.example.com - Docker Engine with the Compose v2 plugin
- OpenSSL for secret generation
- Optional SMTP provider for invitations and notifications
- A password manager for
APP_SECRET, Postgres passwords, and mail credentials
Security Notes:
- Replace every placeholder in
docker-compose.ymlbefore the firstup APP_SECRETmust be at least 32 characters; generate it withopenssl rand -hex 32- Prefer publishing only ports
80and443through Caddy; avoid exposing Postgres or Redis publicly - Keep Compose files mode
600if they contain secrets, and keep them out of public Git remotes - Enable WebSockets on the reverse proxy or the editor falls back to read-only behavior
Patch the host and open only what you need:
sudo apt update
sudo apt upgrade -y
sudo apt install -y ca-certificates curl gnupg openssl ufw
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status
Installation Guide
This deployment follows the official Docker path: download the upstream docker-compose.yml, replace secrets and APP_URL, then add Caddy for HTTPS. Keep the project under /opt/docmost.
1. Install Docker Engine
Install Docker from Docker's official Ubuntu packages, matching the Docmost prerequisites:
sudo apt-get update -qqy
sudo apt-get install ca-certificates curl -qqy
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update -qqy
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin -qqy
sudo usermod -aG docker "$USER"
newgrp docker
docker --version
docker compose version
If docker compose version fails, fix Docker before continuing. Docmost expects Compose v2.
2. Download the Official Compose File
sudo mkdir -p /opt
sudo chown "$USER":"$USER" /opt
cd /opt
mkdir docmost
cd docmost
curl -O https://raw.githubusercontent.com/docmost/docmost/main/docker-compose.yml
chmod 600 docker-compose.yml
The official template defines three services: docmost, db (postgres:18), and redis (redis:8 with AOF and noeviction). Named volumes persist application storage, Postgres data, and Redis data.
Caption: The Docmost Compose stack runs the app with PostgreSQL 18 and Redis 8, each backed by a named volume.
3. Generate Secrets and Edit Compose
Generate a long application secret and a strong database password:
openssl rand -hex 32
openssl rand -base64 24
Open docker-compose.yml and replace the placeholders. For a production hostname behind Caddy, set APP_URL to HTTPS and keep the same Postgres password in both POSTGRES_PASSWORD and DATABASE_URL:
services:
docmost:
image: docmost/docmost:latest
depends_on:
- db
- redis
environment:
APP_URL: "https://docmost.example.com"
APP_SECRET: "PASTE_OPENSSL_HEX_SECRET_HERE"
DATABASE_URL: "postgresql://docmost:YOUR_STRONG_DB_PASSWORD@db:5432/docmost"
REDIS_URL: "redis://redis:6379"
MAIL_DRIVER: "smtp"
SMTP_HOST: "smtp.example.com"
SMTP_PORT: "587"
SMTP_USERNAME: "docs@example.com"
SMTP_PASSWORD: "YOUR_SMTP_PASSWORD"
SMTP_SECURE: "false"
MAIL_FROM_ADDRESS: "docs@example.com"
MAIL_FROM_NAME: "Docmost"
DISABLE_TELEMETRY: "true"
# Bound only for local checks; Caddy will reach docmost:3000 on the Docker network
ports:
- "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: YOUR_STRONG_DB_PASSWORD
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:
URL-encode special characters in the database password inside DATABASE_URL if the password contains @, #, /, or similar characters. Leaving APP_SECRET as REPLACE_WITH_LONG_SECRET causes startup failure.
Optional mail variables are shown so invitations work on day one. If you skip SMTP for a lab, remove those keys and create the first owner account during setup; invite flows will not work until mail is configured.
4. Add Caddy for HTTPS and WebSockets
Create a Caddyfile beside Compose. Caddy obtains and renews Let's Encrypt certificates automatically and forwards WebSockets without extra headers:
cat > /opt/docmost/Caddyfile <<'EOF'
docmost.example.com {
reverse_proxy docmost:3000
}
EOF
Extend docker-compose.yml with the official Caddy service pattern. Add these keys under services: and under volumes::
caddy:
image: caddy:2
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
depends_on:
- docmost
restart: unless-stopped
caddy_data:
caddy_config:
Confirm DNS for docmost.example.com points at the server before the first start so certificate issuance succeeds.
Caption: Caddy terminates TLS on 443 and proxies to Docmost on the Docker network so the collaborative editor can use WebSockets.
5. Start the Stack
cd /opt/docmost
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=80 docmost
curl -sS http://127.0.0.1:3000/api/health
Open https://docmost.example.com. You should see the Docmost setup page. Create the first workspace and owner account; that user becomes the workspace owner and can invite others after SMTP is working.
Configuration
Public URL: APP_URL must match the browser URL scheme and host. A mismatch breaks cookies, invites, and shared links.
Secrets: Treat APP_SECRET like an encryption key. Rotate it only with a deliberate plan and a fresh backup. Do not change POSTGRES_PASSWORD on an existing volume without also updating the database role; for a clean reset in a lab, docker compose down -v destroys volumes.
Email: Invitations need MAIL_DRIVER=smtp (or Postmark) plus host, credentials, and MAIL_FROM_ADDRESS. Test with a second account after the owner setup.
Storage: The default STORAGE_DRIVER is local storage on the docmost volume. For S3-compatible backends, set STORAGE_DRIVER=s3 plus AWS_S3_* variables from the official configuration docs. For Azure, use STORAGE_DRIVER=azure and the Azure storage variables.
Upload limits: Adjust FILE_UPLOAD_SIZE_LIMIT and FILE_IMPORT_SIZE_LIMIT if teams import large archives.
Telemetry: Set DISABLE_TELEMETRY=true if you prefer not to send anonymous version and usage counts.
Health checks: Point Uptime Kuma or similar at https://docmost.example.com/api/health.
After editing environment variables:
cd /opt/docmost
docker compose up -d
docker compose logs --tail=100 docmost
Usage
- Complete the first-run workspace setup as the owner.
- Create a Space for a team or project and nest pages for runbooks, onboarding, and meeting notes.
- Invite a colleague by email and confirm the invite arrives.
- Open the same page in two browsers and verify live editing works; if the editor is read-only, fix WebSocket proxying.
- Upload a small attachment and confirm it survives a container recreate.
- Hit
/api/healthfrom outside the server and confirm HTTPS redirects cleanly.
Testing checklist:
- HTTPS loads without certificate warnings
- Owner login and logout succeed
- Collaborative edit stays writable with two sessions
- Invite email arrives when SMTP is configured
- Storage files remain after
docker compose up -d --force-recreate docmost - Health endpoint returns a healthy response for monitoring
Screenshots and Visuals
The visuals in this guide are original architecture diagrams rather than scraped product screenshots. They show the Compose topology, the HTTPS path, and the backup workflow you should rehearse before the wiki holds production knowledge.
Caption: Useful Docmost backups capture a Postgres dump, the storage volume, Compose secrets, an off-server copy, a restore drill, and a planned image upgrade.
Troubleshooting
- App exits because of APP_SECRET: Generate at least 32 characters with
openssl rand -hex 32and recreate the container. - password authentication failed for user docmost:
POSTGRES_PASSWORDand the password inDATABASE_URLdo not match, or the volume was initialized with an older password. Align both values or recreate volumes in a non-production lab withdocker compose down -v. - Editor is read-only / real-time fails: The reverse proxy is not forwarding WebSockets. Prefer Caddy's
reverse_proxyor ensure Nginx/Traefik forwardsUpgradeandConnection. - Setup page never loads: Check
docker compose logs docmost, DNS, firewall ports80/443, andcurl -sS http://127.0.0.1:3000/api/health. - Invites never arrive: Confirm SMTP variables, TLS settings for your provider, and that
MAIL_FROM_ADDRESSis allowed by the mail host. - Wrong public links or login redirects: Set
APP_URLexactly tohttps://docmost.example.comwith no trailing slash mismatch relative to how users access the site. - Disk fills quickly: Attachments live on the
docmostvolume and Postgres grows with page history. Monitordocker system dfand volume sizes. - Certificate errors on first boot: DNS must already point at the server; wait for Caddy logs to show successful issuance, then retry HTTPS.
Scaling, Securing, and Next Steps
Backups must include PostgreSQL and the Docmost storage volume. Compose alone is not a backup. A simple script can dump the database and archive named volumes:
sudo tee /opt/docmost/backup.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
cd /opt/docmost
stamp="$(date -u +%Y%m%dT%H%M%SZ)"
mkdir -p backups
docker compose exec -T db pg_dump -U docmost docmost | gzip > "backups/docmost-db-${stamp}.sql.gz"
docker run --rm \
-v docmost_docmost:/data:ro \
-v /opt/docmost/backups:/backups \
alpine:3.20 \
tar -czf "/backups/docmost-storage-${stamp}.tar.gz" -C /data .
mkdir -p "backups/docmost-config-${stamp}"
cp -a docker-compose.yml Caddyfile "backups/docmost-config-${stamp}/"
find backups -type f -mtime +14 -delete
EOF
sudo chmod 700 /opt/docmost/backup.sh
/opt/docmost/backup.sh
rsync -avz /opt/docmost/backups/ backup-user@backup.example.net:/srv/backups/docmost/
Test a restore on a separate machine: restore Postgres into a fresh db volume, unpack storage into the Docmost volume, start Compose, log in, and open a page with an attachment. A dump without storage leaves broken uploads. Storage without Postgres leaves an empty wiki.
For upgrades, follow the official recreate flow after a fresh backup:
cd /opt/docmost
/opt/docmost/backup.sh
docker pull docmost/docmost:latest
docker compose up --force-recreate --build docmost -d
docker compose logs --tail=120 docmost
curl -sS http://127.0.0.1:3000/api/health
Pinning an image digest or version tag instead of latest keeps upgrades deliberate for shared workspaces. When you outgrow a single VPS disk, move attachments to S3-compatible storage and keep Postgres dumps on a separate backup host. Enterprise features such as SSO and audit logs are available through Docmost's commercial offerings if your compliance needs exceed the community setup.
The outcome of this guide is a private, HTTPS-secured Docmost workspace with PostgreSQL, Redis, local attachment storage, Caddy WebSocket proxying, SMTP invitations, and a backup path you can restore. From here, create spaces for each team, document the restore steps inside the wiki itself, watch disk usage, and keep an upgrade log so the knowledge base remains rebuildable when a new image lands.
Need this done on your server?
I deploy and harden Laravel, CodeCanyon, and open-source apps on cPanel or VPS, and offer monthly Server Watch retainers. Hire for deploy · Care plan