Documenso

Docker Compose

Deploy Documenso with Docker Compose, including PostgreSQL. This production-ready setup is suitable for most self-hosted deployments.

Prerequisites

Before starting, ensure you have:

  • Docker 20.10 or later
  • Docker Compose v2.0 or later
  • SMTP credentials for sending emails
  • At least 2GB of available RAM
  • A domain name (for production deployments)

Verify your installation:

docker --version
docker compose version

Clone and Configure

Download the compose file

Download the production Docker Compose file:

mkdir documenso && cd documenso
curl -O https://raw.githubusercontent.com/documenso/documenso/release/docker/production/compose.yml

Alternatively, clone the full repository:

git clone https://github.com/documenso/documenso.git
cd documenso/docker/production

Create environment file

Create a .env file in the same directory as compose.yml:

touch .env

Add the required configuration (see Environment Configuration below).

The compose.yml in the repository may be outdated. Use it as a starting point and verify the configuration against the environment variables documented here.

Docker Compose File Overview

The production compose.yml includes two services:

name: documenso-production

services:
  database:
    image: postgres:15
    environment:
      - POSTGRES_USER=${POSTGRES_USER:?err}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?err}
      - POSTGRES_DB=${POSTGRES_DB:?err}
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER}']
      interval: 10s
      timeout: 5s
      retries: 5
    volumes:
      - database:/var/lib/postgresql/data

  documenso:
    image: documenso/documenso:latest
    depends_on:
      database:
        condition: service_healthy
    environment:
      # See environment configuration below
    ports:
      - ${PORT:-3000}:${PORT:-3000}
    volumes:
      - /opt/documenso/cert.p12:/opt/documenso/cert.p12:ro

volumes:
  database:
ServicePurpose
databasePostgreSQL 15 database with persistent storage
documensoMain application container, waits for database to be healthy

The Documenso container waits for the database health check to pass before starting.

Environment Configuration

Create a .env file with the following variables:

Required Variables

# Database (used by both database and documenso services)
POSTGRES_USER=documenso
POSTGRES_PASSWORD=your-secure-database-password
POSTGRES_DB=documenso

# Application secrets (generate with: openssl rand -base64 32)
NEXTAUTH_SECRET=your-nextauth-secret
NEXT_PRIVATE_ENCRYPTION_KEY=your-encryption-key-min-32-characters
NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY=your-secondary-key-min-32-characters

# Public URL where Documenso is accessible
NEXT_PUBLIC_WEBAPP_URL=https://sign.example.com
NEXT_PRIVATE_INTERNAL_WEBAPP_URL=http://localhost:3000

# Database connection (uses Docker service name)
NEXT_PRIVATE_DATABASE_URL=postgresql://documenso:your-secure-database-password@database:5432/documenso

# Email configuration
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=noreply@example.com

Optional Variables

# Application port (default: 3000)
PORT=3000

# Signing certificate (see Signing Certificate section)
NEXT_PRIVATE_SIGNING_PASSPHRASE=your-certificate-password

# Disable public signups
NEXT_PUBLIC_DISABLE_SIGNUP=false
Generate secure secrets using: openssl rand -base64 32

For the complete list of environment variables, see Environment Variables.

Generating Secrets

Generate the required secrets:

# Generate NEXTAUTH_SECRET
echo "NEXTAUTH_SECRET=$(openssl rand -base64 32)"

# Generate encryption keys
echo "NEXT_PRIVATE_ENCRYPTION_KEY=$(openssl rand -base64 32)"
echo "NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY=$(openssl rand -base64 32)"

# Generate database password
echo "POSTGRES_PASSWORD=$(openssl rand -base64 24)"

Signing Certificate

A signing certificate is required for document signing. Generate a .p12 certificate on your host machine and mount it into the container. See Local Certificate for how to generate one.

Place the certificate on the host and set permissions so the container can read it (UID 1001):

sudo mkdir -p /opt/documenso
sudo cp /path/to/your/cert.p12 /opt/documenso/cert.p12
sudo chown 1001:1001 /opt/documenso/cert.p12
sudo chmod 400 /opt/documenso/cert.p12

The compose.yml mounts this path into the container. Add the passphrase to your .env file:

NEXT_PRIVATE_SIGNING_PASSPHRASE=your-certificate-password

If file mounting is not available, you can set NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS with the base64-encoded certificate string instead.

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.

Starting Services

Start all services:

docker compose --env-file .env up -d

Check that containers are running:

docker compose ps

Expected output:

NAME                             STATUS              PORTS
documenso-production-database-1  running (healthy)   5432/tcp
documenso-production-documenso-1 running             0.0.0.0:3000->3000/tcp

Wait for the database to be healthy and for migrations to complete. Check the logs:

docker compose logs -f documenso

Look for "Ready" or "Listening on port 3000" in the output.

Accessing Documenso

Once the containers are running:

  • Local access: Open http://localhost:3000
  • Remote access: Use the URL configured in NEXT_PUBLIC_WEBAPP_URL

First Account Setup

Navigate to the signup page and create your account. Verify your email address — if emails are not being delivered, check the container logs for SMTP errors.

All accounts created through signup are regular user accounts. Admin access must be granted directly in the database. Once your accounts are set up, consider disabling public signups by setting NEXT_PUBLIC_DISABLE_SIGNUP=true.

Managing Services

View Logs

View all service logs:

docker compose logs -f

View logs for a specific service:

docker compose logs -f documenso
docker compose logs -f database

Restart Services

Restart all services:

docker compose --env-file .env restart

Restart a specific service:

docker compose --env-file .env restart documenso

Stop Services

Stop without removing containers:

docker compose stop

Stop and remove containers (preserves volumes):

docker compose down

Stop, remove containers, and delete data:

docker compose down -v

Using down -v deletes the database volume. Back up your data first.

Update Documenso

Pull the latest image:

docker compose pull

Recreate containers:

docker compose --env-file .env up -d

Database migrations run automatically on container startup.

Back up your database before upgrading. See Backups.

Production Considerations

Reverse Proxy

For production, place Documenso behind a reverse proxy for SSL termination:

nginx example:

server {
    listen 443 ssl http2;
    server_name sign.example.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }
}

Caddy example:

sign.example.com {
    reverse_proxy localhost:3000
}

Database Backups

Set up automated database backups:

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

# Restore from backup
docker compose exec -T database psql -U documenso documenso < backup.sql

See Backups for automated backup strategies.

Resource Limits

Add resource limits to prevent container resource exhaustion:

services:
  documenso:
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          cpus: '0.5'
          memory: 512M

External Database

For production, consider using a managed PostgreSQL service:

Remove the database service from compose.yml

Update environment variables:

NEXT_PRIVATE_DATABASE_URL=postgresql://user:password@your-db-host:5432/documenso
NEXT_PRIVATE_DIRECT_DATABASE_URL=postgresql://user:password@your-db-host:5432/documenso

S3 Storage

For high-volume deployments, configure S3-compatible storage:

NEXT_PUBLIC_UPLOAD_TRANSPORT=s3
NEXT_PRIVATE_UPLOAD_BUCKET=your-bucket
NEXT_PRIVATE_UPLOAD_REGION=us-east-1
NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID=your-access-key
NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY=your-secret-key

See Storage Configuration.

Troubleshooting


See Also

On this page