Self-Hosting OpenSign with Docker Compose

What OpenSign Does

OpenSign is an open-source e-signing platform with reusable document templates, multi-signer workflows, audit trails, and a built-in document drive. It runs as two containers (React frontend and Node.js/Parse Server backend) with MongoDB for storage.

OpenSign targets teams that need template-based signing at scale — create a contract template once, then reuse it for every new client or employee. The API supports programmatic document creation and signing for automation.

Prerequisites

  • Linux server with Docker and Docker Compose (setup guide)
  • 2 GB RAM minimum (MongoDB + Node.js + React)
  • 5 GB disk space plus document storage
  • An SMTP server or Mailgun account for sending signing requests
  • A domain name (Caddy provides automatic SSL)

Docker Compose Configuration

Create a project directory:

mkdir -p ~/opensign && cd ~/opensign

Create a .env file:

# Application
APP_ID=opensignapp1
MASTER_KEY=change-this-to-a-random-12-char-key
HOST_URL=https://sign.example.com

# MongoDB
MONGO_INITDB_ROOT_USERNAME=opensign
MONGO_INITDB_ROOT_PASSWORD=change-this-strong-password

# Email — configure one of these options:
# Option A: SMTP
SMTP_ENABLE=true
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER_EMAIL=[email protected]
SMTP_PASS=your-smtp-password

# Option B: Mailgun (comment out SMTP vars above)
# MAILGUN_API_KEY=your-mailgun-key
# MAILGUN_DOMAIN=mail.example.com
# [email protected]

# Storage — set USE_LOCAL=TRUE for local file storage
USE_LOCAL=TRUE

Create a Caddyfile:

{$HOST_URL:localhost:3001} {
    handle /api/* {
        reverse_proxy server:8080
    }
    handle {
        reverse_proxy client:3000
    }
}

Create docker-compose.yml:

services:
  server:
    image: opensign/opensignserver:main
    restart: unless-stopped
    depends_on:
      - mongo
    environment:
      - NODE_ENV=production
      - APP_ID=${APP_ID}
      - appName=OpenSign
      - MASTER_KEY=${MASTER_KEY}
      - MONGODB_URI=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongo:27017/opensign?authSource=admin
      - PARSE_MOUNT=/app
      - SERVER_URL=${HOST_URL}/api/app
      - USE_LOCAL=${USE_LOCAL:-TRUE}
      - SMTP_ENABLE=${SMTP_ENABLE:-}
      - SMTP_HOST=${SMTP_HOST:-}
      - SMTP_PORT=${SMTP_PORT:-}
      - SMTP_USER_EMAIL=${SMTP_USER_EMAIL:-}
      - SMTP_PASS=${SMTP_PASS:-}
      - MAILGUN_API_KEY=${MAILGUN_API_KEY:-}
      - MAILGUN_DOMAIN=${MAILGUN_DOMAIN:-}
      - MAILGUN_SENDER=${MAILGUN_SENDER:-}
    volumes:
      - opensign-files:/usr/src/app/files

  client:
    image: opensign/opensign:main
    restart: unless-stopped
    depends_on:
      - server
    environment:
      - REACT_APP_SERVERURL=${HOST_URL}/api/app
      - REACT_APP_APPID=${APP_ID}
      - PUBLIC_URL=${HOST_URL}

  mongo:
    image: mongo:7.0
    restart: unless-stopped
    environment:
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD}
    volumes:
      - mongo-data:/data/db

  caddy:
    image: caddy:2.9
    restart: unless-stopped
    depends_on:
      - server
      - client
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    environment:
      - HOST_URL=${HOST_URL}
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy-data:/data
      - caddy-config:/config

volumes:
  opensign-files:
  mongo-data:
  caddy-data:
  caddy-config:

Note on image tags: OpenSign does not publish version-numbered Docker tags — only main, staging, and docker_beta. The main tag tracks stable releases. This is a known limitation (GitHub issue #1052). We’ve pinned MongoDB and Caddy to specific versions for reproducibility.

Start the stack:

docker compose up -d

First-Time Setup

  1. Visit https://sign.example.com (or http://localhost:3001 for local testing)
  2. Caddy handles SSL automatically if you’ve pointed your domain at the server
  3. Create your admin account
  4. Create a document template or upload a PDF directly

Feature Comparison

FeatureOpenSignDocuSealDocumenso
LicenseAGPL-3.0AGPL-3.0MIT
Document templatesYes — reusableYes — form builderYes — basic
Multi-signerSequential + parallelSequentialSequential
Audit trailYesYesYes
APIParse Server APIREST APItRPC API
DatabaseMongoDBPostgreSQL/SQLitePostgreSQL
File storageLocal or S3Local or S3Database or S3
Built-in reverse proxyCaddy includedOptional CaddyNo

Without Caddy (External Reverse Proxy)

If you already run a reverse proxy like Nginx Proxy Manager or Traefik, remove the caddy service from the compose file and expose the ports directly:

services:
  server:
    ports:
      - "8080:8080"
  client:
    ports:
      - "3000:3000"

Then proxy /api/* to port 8080 and everything else to port 3000. See Reverse Proxy Setup.

Backup Strategy

Critical data to back up:

# MongoDB dump
docker compose exec mongo mongodump --uri="mongodb://opensign:password@localhost:27017/opensign?authSource=admin" --out=/data/db/backup

# Document files (if using local storage)
docker compose cp server:/usr/src/app/files ./opensign-files-backup

See Backup Strategy for automated scheduling.

Troubleshooting

Server returns “unauthorized” on API calls

Symptom: Frontend shows connection errors or 401 responses Fix: Ensure APP_ID matches exactly between REACT_APP_APPID (client) and APP_ID (server). Also verify SERVER_URL and REACT_APP_SERVERURL point to the same endpoint.

MongoDB authentication failure

Symptom: Server container crashes with “Authentication failed” Fix: The MongoDB URI must include ?authSource=admin when using root credentials. If you change credentials after first start, delete the mongo-data volume — MongoDB bakes credentials into the data directory on first boot.

Documents not sending via email

Symptom: Signing requests created but no email arrives Fix: Either Mailgun or SMTP must be configured — there is no fallback. Check container logs: docker compose logs server | grep -i mail. For SMTP, ensure SMTP_ENABLE is explicitly set (not just truthy).

Resource Requirements

ResourceMinimumRecommended
RAM1.5 GB3 GB
CPU2 vCPUs4 vCPUs
Disk5 GB + documents10 GB + documents

OpenSign is heavier than alternatives because it runs four containers (server, client, MongoDB, Caddy). MongoDB in particular needs at least 500 MB RAM for stable operation.

Verdict

OpenSign is the most feature-rich self-hosted signing platform — reusable templates and parallel multi-signer workflows put it ahead of DocuSeal and Documenso for teams processing high volumes of recurring documents. The trade-off is complexity: four containers, MongoDB, and no version-pinned Docker tags.

Pick OpenSign for template-heavy workflows (hiring, contracts, onboarding). Pick DocuSeal for simpler one-off signing. Pick Documenso if you need MIT licensing or .p12 digital certificates.

Comments