Self-Hosting DocuSeal with Docker Compose

What DocuSeal Does

DocuSeal is an open-source document signing platform that lets you create PDF forms with a drag-and-drop builder, send them to recipients, and collect e-signatures through a mobile-optimized interface. It replaces services like DocuSign, Adobe Sign, and HelloSign with something you control entirely.

Built with Ruby on Rails, DocuSeal supports 12 field types (signature, date, file, checkbox, and more), multiple submitters per document, and SMTP-based email notifications. It stores files on disk or optionally in S3-compatible cloud storage.

Prerequisites

  • A Linux server (Ubuntu 22.04+ or Debian 12+)
  • Docker and Docker Compose installed (Docker Compose guide)
  • 1 GB RAM minimum (2 GB recommended with PostgreSQL)
  • 2 GB of free disk space, plus storage for uploaded documents
  • A domain name for remote access (optional but recommended)

Docker Compose Configuration

Create a directory for DocuSeal and a docker-compose.yml file:

mkdir -p ~/docuseal && cd ~/docuseal
services:
  app:
    image: docuseal/docuseal:2.3.5
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    ports:
      - "3000:3000"
    volumes:
      - docuseal-data:/data/docuseal
    environment:
      - DATABASE_URL=postgresql://docuseal:changeme-db-password@postgres:5432/docuseal
      - SECRET_KEY_BASE=generate-a-64-char-random-string-here-use-openssl-rand-hex-32

  postgres:
    image: postgres:16
    restart: unless-stopped
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: docuseal
      POSTGRES_PASSWORD: changeme-db-password  # Must match DATABASE_URL above
      POSTGRES_DB: docuseal
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U docuseal"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  docuseal-data:
  postgres-data:

Generate a secret key before starting:

openssl rand -hex 32

Replace generate-a-64-char-random-string-here-use-openssl-rand-hex-32 with the output, and change changeme-db-password to a strong password in both the app and postgres service sections.

Start the stack:

docker compose up -d

DocuSeal will be available at http://your-server-ip:3000.

Initial Setup

  1. Open http://your-server-ip:3000 in your browser
  2. Create an admin account on first visit
  3. Navigate to Settings → Email to configure SMTP for sending signing requests (SMTP is configured through the web UI, not environment variables)
  4. Upload your first PDF document and use the form builder to add signature fields

Key Features

FeatureDetails
Form builderWYSIWYG drag-and-drop with 12 field types
Multi-signerMultiple submitters per document with configurable order
File storageLocal disk (default) or S3-compatible cloud storage
APIREST API and webhooks for automation
EmbeddingReact, Vue, Angular, and JavaScript SDKs for embedded signing
LanguagesUI in 7 languages, signing interface in 14 languages
DatabasePostgreSQL (recommended), MySQL, or SQLite

S3 Storage Configuration

To store documents in S3-compatible storage instead of local disk, add these environment variables to the app service:

environment:
  - AWS_ACCESS_KEY_ID=your-access-key
  - AWS_SECRET_ACCESS_KEY=your-secret-key
  - AWS_REGION=us-east-1
  - AWS_BUCKET=your-bucket-name

This works with AWS S3, MinIO, DigitalOcean Spaces, and other S3-compatible providers.

Reverse Proxy

Place DocuSeal behind a reverse proxy for SSL termination. With Caddy:

sign.example.com {
    reverse_proxy localhost:3000
}

See the full Reverse Proxy Setup Guide for Nginx Proxy Manager and Traefik configurations.

Backup

Back up these volumes regularly:

  • docuseal-data — uploaded documents and application data
  • postgres-data — the PostgreSQL database
# Database backup
docker compose exec postgres pg_dump -U docuseal docuseal > backup.sql

See Backup Strategy for automated backup approaches.

Troubleshooting

Container fails to start with database connection error

Symptom: PG::ConnectionBad: could not connect to server Fix: Ensure POSTGRES_PASSWORD in the postgres service matches the password in DATABASE_URL. Wait for the health check — the depends_on condition ensures PostgreSQL is ready.

Emails not sending

Symptom: Signing requests don’t arrive via email Fix: Configure SMTP through the DocuSeal admin UI at Settings → Email. SMTP is not set via environment variables — it’s managed in the web interface.

Permission denied on volume mount

Symptom: Permission denied errors on /data/docuseal Fix: The container runs as a non-root user. Ensure the volume directory is writable: sudo chown -R 1000:1000 ./docuseal if using bind mounts.

Resource Requirements

ResourceMinimumRecommended
RAM512 MB (with SQLite)1 GB (with PostgreSQL)
CPU1 vCPU2 vCPUs
Disk2 GB + document storage5 GB + document storage

Verdict

DocuSeal is the most polished self-hosted document signing platform available. The WYSIWYG form builder is genuinely good — better than most commercial alternatives at the basic tier. It handles the common document signing workflow (upload PDF, place fields, send for signature) without any rough edges.

Choose DocuSeal if you sign documents regularly and want to stop paying DocuSign’s per-envelope pricing. The PostgreSQL setup is straightforward, SMTP configuration through the web UI is convenient, and the API is solid for automation. If you need a simpler setup with fewer features, look at DocuSeal vs Documenso for a comparison.

Comments