Self-Hosting CryptPad with Docker Compose

End-to-End Encrypted Documents

Most self-hosted office suites encrypt data at rest. CryptPad encrypts it before it ever leaves the browser. The server stores only ciphertext — even as the admin, you can’t read your users’ documents. CryptPad supports rich text documents, spreadsheets, presentations, Kanban boards, whiteboards, forms, and code editing, all with real-time collaboration and zero-knowledge encryption.

It’s AGPL-3.0 licensed, requires no external database, and runs on modest hardware. If privacy is your primary concern, CryptPad is the only serious option.

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 512 MB RAM minimum (2 GB recommended)
  • 10 GB free disk space
  • Two domains or subdomains (security requirement — see below)
ResourceMinimumRecommended
RAM512 MB2 GB
CPU1 core2 cores
Disk200 MB (app)10+ GB (grows with docs)
Idle RAM~150 MB~300 MB

CryptPad is lightweight. It’s a Node.js application with file-based storage — no PostgreSQL, no Redis, no external dependencies.

The Dual-Domain Requirement

CryptPad’s security model requires two separate origins (different domains or subdomains):

  • Main domain (cryptpad.example.com) — handles account authentication and cryptographic operations
  • Sandbox domain (sandbox.example.com) — loads the editing UI in an isolated context

This prevents XSS attacks in the editor from accessing your encryption keys. Both domains must point to the same server and be served via HTTPS.

Example DNS setup:

cryptpad.example.com    A    your-server-ip
sandbox.example.com     A    your-server-ip

Docker Compose Configuration

Create the data directories first — CryptPad runs as UID 4001 inside the container:

mkdir -p data/{blob,block,files,data} customize
chown -R 4001:4001 data/

Create a docker-compose.yml:

services:
  cryptpad:
    image: cryptpad/cryptpad:2026.2.0
    container_name: cryptpad
    environment:
      - CPAD_MAIN_DOMAIN=https://cryptpad.example.com
      - CPAD_SANDBOX_DOMAIN=https://sandbox.example.com
      - CPAD_CONF=/cryptpad/config/config.js
    ports:
      - "3000:3000"     # HTTP
      - "3003:3003"     # WebSocket (real-time sync)
    volumes:
      - ./data/blob:/cryptpad/blob
      - ./data/block:/cryptpad/block
      - ./data/files:/cryptpad/datastore
      - ./data/data:/cryptpad/data
      - ./customize:/cryptpad/customize
    ulimits:
      nofile:
        soft: 1000000
        hard: 1000000
    restart: unless-stopped

Start it:

docker compose up -d

No .env file needed — CryptPad’s configuration is minimal. The domains are the only required settings.

Reverse Proxy Configuration

CryptPad needs a reverse proxy that:

  1. Serves HTTPS on both domains
  2. Forwards HTTP to port 3000
  3. Forwards WebSocket connections (/cryptpad_websocket) to port 3003

Caddy (simplest — auto-SSL for both domains):

cryptpad.example.com, sandbox.example.com {
    reverse_proxy cryptpad:3000

    @websocket {
        path /cryptpad_websocket
    }
    reverse_proxy @websocket cryptpad:3003
}

Nginx Proxy Manager: Create two proxy hosts (one per domain) pointing to port 3000. Add a custom Nginx location for WebSocket forwarding:

location /cryptpad_websocket {
    proxy_pass http://cryptpad:3003;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

See Reverse Proxy Setup for detailed configuration.

Initial Setup

  1. Open https://cryptpad.example.com in your browser
  2. Click Register to create the first account
  3. Important: The first registered account is NOT automatically an admin. To grant admin access, edit config.js

Setting Up Admin Access

Get the public signing key of your account:

  1. Log in to CryptPad
  2. Open User Menu → Settings → Account
  3. Copy the Public Signing Key (starts with a bracket, like [cryptpad-user1@...])

Then add it to the config:

docker exec -it cryptpad vi /cryptpad/config/config.js

Find adminKeys and add your key:

adminKeys: [
    "[your-public-signing-key-here]",
],

Restart the container:

docker compose restart cryptpad

What You Can Create

Document TypeDescriptionCollaboration
Rich TextWord processor with formattingReal-time, multi-cursor
SpreadsheetExcel-like with formulasReal-time
PresentationSlide decks with themesReal-time
Code/MarkdownSyntax-highlighted editorReal-time
KanbanTask boards with columnsReal-time
WhiteboardDrawing and diagrammingReal-time
FormSurveys and questionnairesCreator + respondents
File DriveEncrypted file storageUpload/download

All document types support sharing via links with configurable permissions (view, edit, or no access).

Configuration

Storage Limits

By default, registered users get unlimited storage. To set limits, edit config.js:

defaultStorageLimit: 50 * 1024 * 1024,  // 50 MB per user

Admins can set per-user quotas through the admin panel.

Registration Controls

Disable open registration (invite-only mode):

restrictRegistration: true,

Existing admins can then generate invitation links.

Inactive Pad Cleanup

CryptPad stores every document version forever by default. To auto-expire unused documents:

inactiveTime: 90,          // Days before a pad is considered inactive
archiveRetentionTime: 15,  // Days to keep archived pads before deletion

OnlyOffice Integration

For better Office format compatibility, enable the ONLYOFFICE integration:

environment:
  - CPAD_INSTALL_ONLYOFFICE=yes
volumes:
  - ./onlyoffice-dist:/cryptpad/www/common/onlyoffice/dist
  - ./onlyoffice-conf:/cryptpad/onlyoffice-conf

This embeds OnlyOffice editors inside CryptPad while maintaining CryptPad’s encryption layer.

Backup

CryptPad uses file-based storage. Back up the entire data/ directory:

tar czf cryptpad-backup-$(date +%Y%m%d).tar.gz data/

The data/block/ directory is the most critical — it contains document history. data/blob/ contains uploaded files.

Since there’s no database, backups are straightforward. See Backup Strategy for scheduling and rotation.

Troubleshooting

”This CryptPad instance is not configured correctly”

Symptom: Warning banner appears on every page.

Fix: The CPAD_MAIN_DOMAIN and CPAD_SANDBOX_DOMAIN must use https:// URLs and point to two different origins. If you’re using http:// or both domains resolve to the same origin, CryptPad flags a security misconfiguration. Set up your reverse proxy with SSL first.

Real-time sync not working

Symptom: Multiple users editing the same document don’t see each other’s changes.

Fix: The WebSocket connection on port 3003 must be forwarded through your reverse proxy. Check that /cryptpad_websocket requests reach port 3003. Test:

curl -i -N \
  -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  https://cryptpad.example.com/cryptpad_websocket

You should get a 101 Switching Protocols response.

Permission denied errors on startup

Symptom: Container crashes with “EACCES” errors.

Fix: CryptPad runs as UID 4001 inside the container. The data directories must be owned by this user:

chown -R 4001:4001 data/

Large file uploads silently fail

Symptom: File uploads in the Drive just stop without error.

Fix: The default max upload size is 20 MB. Increase it in config.js:

maxUploadSize: 100 * 1024 * 1024,  // 100 MB

Also check your reverse proxy’s client_max_body_size (Nginx) or equivalent.

Storage grows indefinitely

Symptom: Disk usage keeps climbing even though users delete documents.

Fix: Deleted documents go to a server-side archive, not true deletion. Configure archiveRetentionTime in config.js to auto-purge after a set number of days. Run the built-in eviction script to clean up immediately.

CryptPad vs ONLYOFFICE

FeatureCryptPadONLYOFFICE
EncryptionEnd-to-end (zero-knowledge)At-rest only
Office format supportLimited (.docx import/export)Excellent (native .docx/.xlsx/.pptx)
RAM requirement512 MB4 GB
External dependenciesNonePostgreSQL + RabbitMQ
Best forPrivacy-first teamsOffice format compatibility
Real-time collaborationYesYes
Kanban/WhiteboardBuilt-inNo

Verdict

CryptPad is the only self-hosted office suite with true end-to-end encryption. The server never sees your data in plaintext — not even the admin. If privacy is non-negotiable, nothing else comes close. The trade-off is Office format compatibility: CryptPad uses its own format internally, with import/export support for common formats but without pixel-perfect fidelity.

Use CryptPad if: Privacy is your top priority, you don’t need heavy .docx/.xlsx editing, or you want built-in Kanban/whiteboard/forms alongside documents.

Look elsewhere if: You need seamless Microsoft Office compatibility (ONLYOFFICE is better), need to integrate with Nextcloud’s file management, or need a full-featured spreadsheet (CryptPad’s spreadsheet is functional but basic compared to ONLYOFFICE or Collabora).