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.
Updated March 2026: Verified with latest Docker images and configurations.
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=noreply@example.com
SMTP_PASS=your-smtp-password
# Option B: Mailgun (comment out SMTP vars above)
# MAILGUN_API_KEY=your-mailgun-key
# MAILGUN_DOMAIN=mail.example.com
# MAILGUN_SENDER=noreply@example.com
# 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 # OpenSign does not publish versioned Docker tags — :main is the only option
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 # No versioned tags available
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.11.2
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
- Visit
https://sign.example.com(orhttp://localhost:3001for local testing) - Caddy handles SSL automatically if you’ve pointed your domain at the server
- Create your admin account
- Create a document template or upload a PDF directly
Feature Comparison
| Feature | OpenSign | DocuSeal | Documenso |
|---|---|---|---|
| License | AGPL-3.0 | AGPL-3.0 | MIT |
| Document templates | Yes — reusable | Yes — form builder | Yes — basic |
| Multi-signer | Sequential + parallel | Sequential | Sequential |
| Audit trail | Yes | Yes | Yes |
| API | Parse Server API | REST API | tRPC API |
| Database | MongoDB | PostgreSQL/SQLite | PostgreSQL |
| File storage | Local or S3 | Local or S3 | Database or S3 |
| Built-in reverse proxy | Caddy included | Optional Caddy | No |
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
| Resource | Minimum | Recommended |
|---|---|---|
| RAM | 1.5 GB | 3 GB |
| CPU | 2 vCPUs | 4 vCPUs |
| Disk | 5 GB + documents | 10 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.
Frequently Asked Questions
How does OpenSign compare to DocuSeal?
OpenSign excels at template-based workflows — create a contract template once and reuse it for every new client. DocuSeal is simpler to deploy (2 containers vs 4) and better for one-off signing tasks. OpenSign supports parallel multi-signer workflows natively, while DocuSeal uses sequential signing. Choose OpenSign for high-volume recurring document workflows; choose DocuSeal for occasional signing.
Is OpenSign legally binding?
E-signatures collected through OpenSign are legally binding in most jurisdictions under laws like the US ESIGN Act, EU eIDAS Regulation, and similar legislation worldwide. OpenSign generates audit trails with timestamps, IP addresses, and signer authentication records. For regulated industries requiring qualified electronic signatures (QES), you may need additional identity verification services that OpenSign doesn’t currently provide.
Does OpenSign work without email?
You must configure either Mailgun or SMTP for sending signing requests — there is no fallback or manual workaround for notifying signers via email. Without email configuration, you can create documents but cannot send them for signing. The email service sends the signing link to each designated signer.
Why doesn’t OpenSign use pinned Docker image tags?
OpenSign publishes images with :latest tags only — no versioned releases. This means docker compose pull can change your deployment without warning. To work around this, use Docker image digests (@sha256:...) instead of tags. This is a known limitation of the project and has been discussed in their GitHub issues.
Can OpenSign integrate with my application via API?
Yes. OpenSign provides a REST API for programmatic document creation, template management, and signing workflows. You can create documents, add signers, and send signing requests from any application. The API uses the same Parse Server authentication as the web interface. API documentation is available in the OpenSign GitHub repository.
How do I migrate from DocuSign to OpenSign?
There is no automated migration tool. Documents signed in DocuSign remain in DocuSign — you export them as PDFs. For new workflows, recreate your templates in OpenSign’s template builder. OpenSign’s template system supports drag-and-drop field placement similar to DocuSign. Contact records and signing history do not transfer.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments