Documenso

Docker

Run Documenso as a standalone Docker container with an external database. Ideal for container platforms like AWS ECS, Google Cloud Run, or Azure Container Instances.

Prerequisites

For a self-contained setup that includes PostgreSQL, see Docker Compose Deployment.

Before starting, ensure you have:

  • Docker 20.10 or later installed
  • A PostgreSQL 14+ database accessible from your Docker host
  • SMTP credentials for sending emails
  • At least 1GB of available RAM

Verify Docker is installed:

docker --version

Pulling the Docker Image

docker pull documenso/documenso:latest

Available Tags

TagDescription
latestLatest stable release
x.y.zSpecific version (e.g., 1.5.0)
releaseLatest release branch build

Pin to a specific version tag in production to avoid unexpected updates.

Environment Variables

Required Variables

These variables must be set for Documenso to start:

VariableDescriptionDefault
NEXTAUTH_SECRETSecret key for session encryption. Generate with openssl rand -base64 32-
NEXT_PRIVATE_ENCRYPTION_KEYPrimary encryption key (minimum 32 characters)-
NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEYSecondary encryption key (minimum 32 characters)-
NEXT_PUBLIC_WEBAPP_URLPublic URL where Documenso is accessible (e.g., https://sign.example.com)-
NEXT_PRIVATE_INTERNAL_WEBAPP_URLInternal URL the app uses to call itself (for background jobs)Same as NEXT_PUBLIC_WEBAPP_URL
NEXT_PRIVATE_DATABASE_URLPostgreSQL connection string-
NEXT_PRIVATE_SMTP_TRANSPORTEmail transport: smtp-auth, smtp-api, resend, or mailchannelssmtp-auth
NEXT_PRIVATE_SMTP_FROM_NAMESender name for outgoing emails-
NEXT_PRIVATE_SMTP_FROM_ADDRESSSender email address-

Database Connection

Documenso requires two database connection strings:

VariableRequiredDefaultDescription
NEXT_PRIVATE_DATABASE_URLYes-Pooled connection for app queries
NEXT_PRIVATE_DIRECT_DATABASE_URLWhen poolingNEXT_PRIVATE_DATABASE_URLDirect connection for migrations

Connection string format:

postgresql://user:password@host:5432/database

If you're not using a connection pooler like PgBouncer, both variables can use the same connection string.

SMTP Configuration

For smtp-auth transport:

VariableRequiredDefaultDescription
NEXT_PRIVATE_SMTP_HOSTYes127.0.0.1SMTP server hostname
NEXT_PRIVATE_SMTP_PORTYes587SMTP server port (usually 587 or 465)
NEXT_PRIVATE_SMTP_USERNAMEYes-SMTP username
NEXT_PRIVATE_SMTP_PASSWORDYes-SMTP password
NEXT_PRIVATE_SMTP_SECURENofalseSet to true to force TLS

See Email Configuration for other transport options.

Optional Variables

VariableDescriptionDefault
PORTPort the application listens on3000
NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATHPath to signing certificate inside container/opt/documenso/cert.p12
NEXT_PRIVATE_SIGNING_PASSPHRASEPassphrase for the signing certificate-
NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTSBase64-encoded .p12 certificate (alternative to file path)-
NEXT_PUBLIC_UPLOAD_TRANSPORTDocument storage: database or s3database
NEXT_PUBLIC_DISABLE_SIGNUPDisable public signupsfalse

For the complete list, see Environment Variables.

Running with Docker

Minimum Example

docker run -d \
  --name documenso \
  -p 3000:3000 \
  -v /path/to/cert.p12:/opt/documenso/cert.p12:ro \
  -e NEXTAUTH_SECRET="$(openssl rand -base64 32)" \
  -e NEXT_PRIVATE_ENCRYPTION_KEY="your-encryption-key-min-32-chars" \
  -e NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY="your-secondary-key-min-32-chars" \
  -e NEXT_PUBLIC_WEBAPP_URL="https://sign.example.com" \
  -e NEXT_PRIVATE_INTERNAL_WEBAPP_URL="http://localhost:3000" \
  -e NEXT_PRIVATE_DATABASE_URL="postgresql://user:password@db-host:5432/documenso" \
  -e NEXT_PRIVATE_SIGNING_PASSPHRASE="your-certificate-password" \
  -e NEXT_PRIVATE_SMTP_TRANSPORT="smtp-auth" \
  -e NEXT_PRIVATE_SMTP_HOST="smtp.example.com" \
  -e NEXT_PRIVATE_SMTP_PORT="587" \
  -e NEXT_PRIVATE_SMTP_USERNAME="your-smtp-user" \
  -e NEXT_PRIVATE_SMTP_PASSWORD="your-smtp-password" \
  -e NEXT_PRIVATE_SMTP_FROM_NAME="Documenso" \
  -e NEXT_PRIVATE_SMTP_FROM_ADDRESS="noreply@example.com" \
  documenso/documenso:latest

Signing Certificate

A signing certificate is required for document signing. You have two options for providing one:

  • Volume mount — mount a .p12 file from the host into the container at /opt/documenso/cert.p12 (shown above). This is the simplest approach for small to moderate deployments.
  • Base64-encoded contents — set NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS with the base64-encoded certificate string. Use this when file mounting is not available (e.g., Railway, Vercel).

For production deployments that require Adobe Approved Trust List recognition, consider using a Google Cloud HSM or another external HSM.

Do not generate or store the signing certificate inside the container. If the container is destroyed and rebuilt, or if you run multiple instances, the certificate will be lost or inconsistent. Always provide the certificate externally.

See Signing Certificate Configuration for generating certificates and detailed setup.

Using an Environment File

For easier management, use an environment file:

Create .env:

NEXTAUTH_SECRET=your-secret-here
NEXT_PRIVATE_ENCRYPTION_KEY=your-encryption-key-min-32-chars
NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY=your-secondary-key-min-32-chars
NEXT_PUBLIC_WEBAPP_URL=https://sign.example.com
NEXT_PRIVATE_INTERNAL_WEBAPP_URL=http://localhost:3000
NEXT_PRIVATE_DATABASE_URL=postgresql://user:password@db-host:5432/documenso
NEXT_PRIVATE_DIRECT_DATABASE_URL=postgresql://user:password@db-host:5432/documenso
NEXT_PRIVATE_SIGNING_PASSPHRASE=your-certificate-password
NEXT_PRIVATE_SMTP_TRANSPORT=smtp-auth
NEXT_PRIVATE_SMTP_HOST=smtp.example.com
NEXT_PRIVATE_SMTP_PORT=587
NEXT_PRIVATE_SMTP_USERNAME=your-smtp-user
NEXT_PRIVATE_SMTP_PASSWORD=your-smtp-password
NEXT_PRIVATE_SMTP_FROM_NAME=Documenso
NEXT_PRIVATE_SMTP_FROM_ADDRESS=noreply@example.com

Run with the environment file:

docker run -d \
  --name documenso \
  -p 3000:3000 \
  --env-file .env \
  -v /path/to/cert.p12:/opt/documenso/cert.p12:ro \
  documenso/documenso:latest

Health Checks

Documenso provides health check endpoints for monitoring:

EndpointPurpose
/api/healthChecks database connectivity and certificate status
/api/certificate-statusReturns whether a signing certificate is configured and usable

Docker Health Check

Add a health check to your container:

docker run -d \
  --name documenso \
  -p 3000:3000 \
  --health-cmd="curl -f http://localhost:3000/api/health || exit 1" \
  --health-interval=30s \
  --health-timeout=10s \
  --health-retries=3 \
  --env-file .env \
  documenso/documenso:latest

Check container health status:

docker inspect --format='{{.State.Health.Status}}' documenso

Updating the Container

To update Documenso to a new version:

Pull the new image

docker pull documenso/documenso:latest

Stop and remove the existing container

docker stop documenso
docker rm documenso

Start a new container with the same configuration

docker run -d \
  --name documenso \
  -p 3000:3000 \
  --env-file .env \
  -v /path/to/cert.p12:/opt/documenso/cert.p12:ro \
  documenso/documenso:latest

Database migrations run automatically when the container starts. Back up your database before upgrading.

Persistence

The Documenso container is stateless. All persistent data is stored in the PostgreSQL database.

By default, documents are also stored in the database. For high-volume deployments, configure S3-compatible storage instead. See Storage Configuration for S3 setup.

Troubleshooting


See Also

On this page