Self-Hosting Documenso with Docker Compose

Why Documenso

Documenso is an MIT-licensed document signing platform built with TypeScript and React Router. Upload PDFs, drag signature fields onto them, send to signers, collect legally-binding e-signatures. It handles audit trails, email notifications, and digital certificate signing — all from infrastructure you control.

What sets Documenso apart from other self-hosted signing tools is its focus on digital signatures using .p12 certificates, giving documents cryptographic proof of integrity. The MIT license (rather than AGPL) also makes it more permissive for embedding in commercial applications.

Prerequisites

  • Linux server with Docker and Docker Compose (setup guide)
  • 2 GB RAM minimum (Node.js + PostgreSQL)
  • 5 GB disk space plus document storage
  • SMTP server or Resend account for sending signing requests
  • A .p12 signing certificate (optional — for digital signatures with cryptographic verification)

Docker Compose Setup

Create a project directory:

mkdir -p ~/documenso && cd ~/documenso

Create a .env file with your configuration:

# Generate secrets
NEXTAUTH_SECRET=$(openssl rand -hex 32)
NEXT_PRIVATE_ENCRYPTION_KEY=$(openssl rand -hex 32)
NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY=$(openssl rand -hex 32)

# Application
NEXT_PUBLIC_WEBAPP_URL=https://sign.example.com
PORT=3000

# Database
POSTGRES_USER=documenso
POSTGRES_PASSWORD=change-this-strong-password
POSTGRES_DB=documenso
NEXT_PRIVATE_DATABASE_URL=postgresql://documenso:change-this-strong-password@database:5432/documenso

# Email (SMTP example — also supports Resend and MailChannels)
NEXT_PRIVATE_SMTP_TRANSPORT=smtp-auth
NEXT_PRIVATE_SMTP_HOST=smtp.example.com
NEXT_PRIVATE_SMTP_PORT=587
NEXT_PRIVATE_SMTP_USERNAME=your-smtp-username
NEXT_PRIVATE_SMTP_PASSWORD=your-smtp-password
NEXT_PRIVATE_SMTP_FROM_NAME=Documenso
NEXT_PRIVATE_SMTP_FROM_ADDRESS=[email protected]

Create docker-compose.yml:

services:
  documenso:
    image: documenso/documenso:v2.6.1
    restart: unless-stopped
    depends_on:
      database:
        condition: service_healthy
    ports:
      - "${PORT:-3000}:${PORT:-3000}"
    env_file: .env
    environment:
      - NEXT_PRIVATE_DIRECT_DATABASE_URL=${NEXT_PRIVATE_DATABASE_URL}
      - NEXT_PRIVATE_INTERNAL_WEBAPP_URL=http://localhost:${PORT:-3000}
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/health"]
      interval: 15s
      timeout: 5s
      retries: 3

  database:
    image: postgres:15
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

Start the stack:

docker compose up -d

Initial Configuration

  1. Open http://your-server:3000 — the login page appears immediately
  2. Create your admin account through the signup form
  3. Upload a PDF, place signature fields, and send your first document

Adding a Signing Certificate

For documents with verifiable digital signatures, mount a .p12 certificate:

# Add to the documenso service in docker-compose.yml
volumes:
  - ./cert.p12:/opt/documenso/cert.p12:ro
environment:
  - NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH=/opt/documenso/cert.p12
  - NEXT_PRIVATE_SIGNING_PASSPHRASE=your-certificate-passphrase

Generate a self-signed certificate for testing:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
openssl pkcs12 -export -out cert.p12 -inkey key.pem -in cert.pem

Configuration Options

VariablePurposeDefault
NEXT_PUBLIC_WEBAPP_URLPublic URL (shown in emails)Required
NEXT_PUBLIC_UPLOAD_TRANSPORTFile storage: database or s3database
NEXT_PUBLIC_DISABLE_SIGNUPBlock new user registrationNot set
NEXT_PRIVATE_SMTP_TRANSPORTsmtp-auth, smtp-api, resend, mailchannelsRequired

S3 Document Storage

By default, Documenso stores uploaded documents in PostgreSQL. For large volumes of documents, switch to S3:

# Add to .env
NEXT_PUBLIC_UPLOAD_TRANSPORT=s3
NEXT_PRIVATE_UPLOAD_ENDPOINT=https://s3.amazonaws.com
NEXT_PRIVATE_UPLOAD_BUCKET=documenso-docs
NEXT_PRIVATE_UPLOAD_REGION=us-east-1
NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID=your-key
NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY=your-secret

Works with AWS S3, MinIO, DigitalOcean Spaces, and any S3-compatible provider.

Reverse Proxy

For SSL termination with Caddy:

sign.example.com {
    reverse_proxy localhost:3000
}

See Reverse Proxy Setup for Nginx and Traefik configurations.

Backup

The Documenso application container is stateless — all data lives in PostgreSQL (and optionally S3).

# Database backup
docker compose exec database pg_dump -U documenso documenso > documenso-backup.sql

# Restore
cat documenso-backup.sql | docker compose exec -T database psql -U documenso documenso

If using the default database upload transport, document files are also in PostgreSQL and included in the dump. If using S3, back up the bucket separately.

See Backup Strategy for automated approaches.

Troubleshooting

Health check fails after startup

Symptom: Container restarts with health check failures Fix: Documenso runs database migrations on first start, which can take 30-60 seconds. Increase the health check start_period to 60s if the container keeps restarting during initial setup.

”Invalid encryption key” error

Symptom: Application crashes with encryption key validation error Fix: NEXT_PRIVATE_ENCRYPTION_KEY and NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY must each be at least 32 characters. Generate with openssl rand -hex 32. Once set, do not change these — existing signed documents will become unreadable.

Emails not being sent

Symptom: Signers don’t receive signing requests Fix: Verify SMTP credentials. Documenso requires NEXT_PRIVATE_SMTP_TRANSPORT to be explicitly set — it won’t fall back to another method silently. Test your SMTP server independently first. If using Resend, set the transport to resend and add NEXT_PRIVATE_RESEND_API_KEY.

Resource Requirements

ResourceMinimumRecommended
RAM1 GB2 GB
CPU1 vCPU2 vCPUs
Disk3 GB + documents10 GB + documents

Verdict

Documenso is the best choice if you need verifiable digital signatures with .p12 certificates and want permissive MIT licensing. The setup is more involved than DocuSeal (more environment variables, mandatory SMTP), but the signing workflow and API are solid.

For most small teams just replacing DocuSign, DocuSeal is simpler to get running. Choose Documenso when you need: digital certificate signing, OAuth/SSO integration, or when the MIT license matters for your use case. See the full comparison.

Comments