Self-Hosting DocuSeal: Open Source Document Signing Platform

If you’ve ever paid $25/month for DocuSign just to get a few contracts signed, you know the pain. DocuSeal is an open source alternative that handles document creation, filling, and signing — all self-hosted on your own server. No per-envelope fees, no subscription tiers, no sending your sensitive contracts through someone else’s infrastructure.

It’s a Ruby on Rails app with a clean, mobile-optimized interface that works surprisingly well for something you can spin up in five minutes with Docker.


What DocuSeal Does

  • WYSIWYG PDF form builder — drag and drop fields onto any PDF
  • 12 field types — signature, date, text, checkbox, file upload, initials, and more
  • Multiple signers per document — assign fields to different parties
  • Automated email delivery — send documents for signature via SMTP
  • Bulk sending — import recipients from CSV or XLSX spreadsheets
  • Template system — create reusable document templates
  • API and webhooks — integrate signing into your own apps
  • Embedded signing — React, Vue, Angular, and vanilla JS components
  • PDF signature verification — cryptographic verification of completed documents
  • White-label — custom logo and branding
  • SSO/SAML support — enterprise identity providers
  • Conditional fields and formulas — dynamic forms that adapt
  • SMS verification — identity verification via text message
  • 14 signing languages — international support out of the box

DocuSeal vs The Alternatives

FeatureDocuSealDocuSignSignWellOpenSign
Self-hosted✅ Yes❌ No❌ No✅ Yes
Open source✅ AGPLv3❌ No❌ No✅ AGPLv3
Form builder✅ WYSIWYG✅ Yes✅ Yes⚠️ Basic
Multiple signers✅ Yes✅ Yes✅ Yes✅ Yes
API✅ REST API✅ Yes✅ Yes⚠️ Limited
Embedded signing✅ React/Vue/JS✅ Yes✅ Yes❌ No
Bulk send✅ CSV/XLSX✅ Yes✅ Yes❌ No
Template HTML API✅ Yes❌ No❌ No❌ No
SMS verification✅ Yes✅ Yes❌ No❌ No
PriceFree (self-hosted)$25+/mo$8+/moFree (self-hosted)
Storage optionsDisk/S3/GCS/AzureCloud onlyCloud onlyCloud/S3

DocuSeal wins on features-per-dollar. The embedded signing components and HTML template API make it particularly strong for developers integrating document signing into their own products.


Prerequisites

  • A Linux server (VPS or home server) with at least 1GB RAM
  • Docker and Docker Compose installed (our Docker guide)
  • A domain name pointed at your server (for HTTPS)
  • SMTP credentials for sending signature request emails (optional but recommended)

Installation with Docker Compose

Create a directory for DocuSeal:

mkdir -p ~/docuseal && cd ~/docuseal

Create your compose.yaml:

services:
  docuseal:
    image: docuseal/docuseal:latest
    container_name: docuseal
    ports:
      - "3000:3000"
    volumes:
      - docuseal-data:/data
    environment:
      - SECRET_KEY_BASE=your-secret-key-here
      # Uncomment for PostgreSQL instead of SQLite:
      # - DATABASE_URL=postgresql://docuseal:password@db:5432/docuseal
    restart: unless-stopped

volumes:
  docuseal-data:

Generate a secret key:

openssl rand -hex 64

Replace your-secret-key-here with the generated key.

Start the container:

docker compose up -d

DocuSeal will be available at http://your-server-ip:3000. The first user to sign up becomes the admin.


Production Setup with PostgreSQL

For production use, swap SQLite for PostgreSQL:

services:
  docuseal:
    image: docuseal/docuseal:latest
    container_name: docuseal
    ports:
      - "3000:3000"
    volumes:
      - docuseal-data:/data
    environment:
      - DATABASE_URL=postgresql://docuseal:${DB_PASSWORD}@db:5432/docuseal
      - SECRET_KEY_BASE=${SECRET_KEY}
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

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

volumes:
  docuseal-data:
  docuseal-db:

Create a .env file:

DB_PASSWORD=$(openssl rand -hex 24)
SECRET_KEY=$(openssl rand -hex 64)
echo "DB_PASSWORD=$DB_PASSWORD" > .env
echo "SECRET_KEY=$SECRET_KEY" >> .env

SMTP Configuration

DocuSeal needs SMTP to email signature requests. Go to Settings → Email in the web UI after your first login, or set environment variables:

environment:
  - SMTP_ADDRESS=smtp.gmail.com
  - SMTP_PORT=587
  - [email protected]
  - SMTP_PASSWORD=your-app-password
  - [email protected]
  - SMTP_DOMAIN=yourdomain.com

For Gmail, use an app password. For production, services like Amazon SES, Resend, or Mailgun are more reliable.


Creating Your First Template

  1. Log in and click New Template
  2. Upload a PDF document (contract, NDA, invoice, etc.)
  3. Use the WYSIWYG builder to place fields:
    • Signature — draw or type signature fields
    • Date — auto-populated or manual date fields
    • Text — free-form text input
    • Checkbox — agreement checkboxes
    • Initials — initial fields for multi-page documents
    • File — attachment upload fields
    • Select — dropdown selections
    • Radio — multiple choice options
    • Stamp — image/stamp uploads
    • Cells — structured data entry
    • Phone — phone number fields
    • Payment — Stripe payment fields
  4. Assign fields to submitters (First Party, Second Party, etc.)
  5. Save the template

Using the HTML API for Templates

For programmatic template creation, DocuSeal supports an HTML-to-PDF API:

curl -X POST "http://localhost:3000/api/templates/html" \
  -H "X-Auth-Token: YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<h1>Service Agreement</h1><p>This agreement is between {{company}} and {{client}}.</p><p>Signature: {{signature}}</p>",
    "name": "Service Agreement"
  }'

This is incredibly powerful for generating dynamic documents from your own application.


Sending Documents for Signature

  1. Open a template and click Send
  2. Add submitter email addresses
  3. Customize the email message (optional)
  4. Click Send — each signer receives an email with a unique signing link

Bulk Sending

For high-volume signing (onboarding, compliance forms):

  1. Open a template
  2. Click Bulk Send
  3. Upload a CSV or XLSX with columns matching your template fields
  4. DocuSeal sends individual signing requests to each row

Storage Configuration

By default, files are stored on the local disk in the /data volume. For production, configure cloud storage:

AWS S3

environment:
  - AWS_ACCESS_KEY_ID=your-key
  - AWS_SECRET_ACCESS_KEY=your-secret
  - AWS_REGION=us-east-1
  - AWS_S3_BUCKET=your-docuseal-bucket

Google Cloud Storage

environment:
  - GCS_BUCKET=your-docuseal-bucket
  - GCS_CREDENTIALS={"type":"service_account",...}

Azure Blob Storage

environment:
  - AZURE_STORAGE_ACCOUNT_NAME=youraccount
  - AZURE_STORAGE_ACCESS_KEY=your-key
  - AZURE_STORAGE_CONTAINER=docuseal

Reverse Proxy Configuration

Add to your Caddyfile:

d}ocs.ryeovuerrdsoem_apirno.xcyomdo{cuseal:3000

If running DocuSeal with Caddy in the same Docker network, remove the ports mapping and use Docker networking instead. See our Caddy reverse proxy guide for details.

Nginx

server {
    listen 443 ssl http2;
    server_name docs.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/docs.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/docs.yourdomain.com/privkey.pem;

    client_max_body_size 50M;

    location / {
        proxy_pass http://docuseal:3000;
        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;
    }
}

Note the client_max_body_size 50M — you’ll need this for uploading large PDF documents.


API Integration

DocuSeal’s REST API lets you integrate document signing into any application. Get your API token from Settings → API.

Create a Submission via API

curl -X POST "http://localhost:3000/api/submissions" \
  -H "X-Auth-Token: YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "template_id": 1,
    "send_email": true,
    "submitters": [
      {
        "role": "First Party",
        "email": "[email protected]"
      }
    ]
  }'

Embedded Signing with React

npm install @docuseal/react
import { DocusealForm } from '@docuseal/react'

function SigningPage({ submissionId }) {
  return (
    <DocusealForm
      src={`https://docs.yourdomain.com/s/${submissionId}`}
      onComplete={(data) => console.log('Signed!', data)}
    />
  )
}

Components are also available for Vue, Angular, and vanilla JavaScript.

Webhooks

Configure webhooks in Settings → Webhooks to receive notifications when documents are:

  • Viewed by a signer
  • Completed and signed
  • All parties have finished signing

User Management

DocuSeal supports role-based access:

  • Admin — full access, manage users and settings
  • Editor — create and manage templates, send documents
  • Viewer — view completed submissions only

Go to Settings → Users to invite team members.


Backup and Restore

SQLite (Default)

The SQLite database lives in the /data volume:

# Backup
docker cp docuseal:/data ./docuseal-backup-$(date +%Y%m%d)

# Restore
docker compose down
docker cp ./docuseal-backup-20260321/. docuseal:/data/
docker compose up -d

PostgreSQL

# Backup database
docker exec docuseal-db pg_dump -U docuseal docuseal > backup-$(date +%Y%m%d).sql

# Backup uploaded files
docker cp docuseal:/data ./docuseal-files-backup

# Restore
docker exec -i docuseal-db psql -U docuseal docuseal < backup-20260321.sql
docker cp ./docuseal-files-backup/. docuseal:/data/

For automated backups, check our Kopia backup guide.


Updating

cd ~/docuseal
docker compose pull
docker compose up -d

DocuSeal handles database migrations automatically on startup.


Troubleshooting

Emails Not Sending

  • Verify SMTP settings in Settings → Email
  • Check container logs: docker logs docuseal
  • Test with a simple SMTP provider first (Gmail app password works for testing)
  • Some providers block port 25 — use 587 (TLS) or 465 (SSL) instead

Large PDF Upload Fails

  • Increase Nginx client_max_body_size (default 1M is too small)
  • For Caddy, there’s no default limit — check available disk space
  • Ensure your /data volume has enough storage

Signature Fonts Not Rendering

  • DocuSeal bundles its own fonts, but custom fonts need the /data/fonts directory
  • Restart the container after adding fonts: docker compose restart

Database Connection Errors (PostgreSQL)

  • Ensure the db container is healthy before DocuSeal starts (use depends_on with healthcheck)
  • Check PostgreSQL logs: docker logs docuseal-db
  • Verify DATABASE_URL format: postgresql://user:password@host:5432/database

Container Runs Out of Memory

  • DocuSeal with SQLite runs fine on 512MB RAM
  • PostgreSQL adds ~256MB overhead
  • Large PDF processing can spike memory — allocate at least 1GB total
  • Set memory limits in compose: deploy.resources.limits.memory: 1g

API Authentication Fails

  • API tokens are per-user — check you’re using the right one
  • Token header is X-Auth-Token, not Authorization: Bearer
  • Regenerate the token in Settings if it stops working

Power User Tips

  • Custom branding — upload your logo in Settings for white-labeled signing pages
  • Template tags — use text tags in PDFs ({{field_name}}) to auto-place fields via the API, skipping the WYSIWYG builder entirely
  • DOCX templates — upload Word documents with field tags for dynamic document generation
  • Conditional fields — show/hide fields based on other field values (great for complex contracts)
  • Formulas — auto-calculate values (totals, dates, concatenated strings)
  • Stripe payments — add payment fields to collect money alongside signatures
  • Audit trail — every completed document includes a certificate of completion with timestamps, IP addresses, and signature hashes

Wrapping Up

DocuSeal hits the sweet spot for self-hosted document signing. The WYSIWYG form builder makes it accessible to non-technical users, while the REST API and embedded components make it a developer’s dream for building signing workflows into custom applications.

For most self-hosters, the Docker + SQLite setup is plenty. Scale up to PostgreSQL and S3 storage when you’re processing hundreds of documents. Either way, you’re looking at zero per-envelope costs and full control over your sensitive documents.

Useful links: