Introduction

While browsing Daily.dev earlier, I discovered an interesting project called DocuSeal. This project is developed with a Ruby backend, open-sourced on Github, and supports self-hosting.

Later, due to business needs, I considered using this solution as a foundation to integrate with existing business processes, creating contract signing services for users through APIs!

Next, I’ll share some experiences about service deployment, integration, and challenges encountered.

Deployment

The official documentation provides concise and intuitive instructions. Here I mainly use Docker Compose for deployment:

curl https://raw.githubusercontent.com/docusealco/docuseal/master/docker-compose.yml > docker-compose.yml

The official docker-compose.yaml content is as follows:

version: '3'

services:
  app:
    depends_on:
      postgres:
        condition: service_healthy
    image: docuseal/docuseal:latest
    ports:
      - 3000:3000
    volumes:
      - .:/data
    environment:
      - FORCE_SSL=${HOST}
      - DATABASE_URL=postgresql://postgres:postgres@postgres:5432/docuseal

  postgres:
    image: postgres:15
    volumes:
      - './pg_data:/var/lib/postgresql/data'
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: docuseal
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  caddy:
    image: caddy:latest
    command: caddy reverse-proxy --from $HOST --to app:3000
    ports:
      - 80:80
      - 443:443
      - 443:443/udp
    volumes:
      - .:/data
    environment:
      - HOST=${HOST}

If you don’t plan to assign a domain name to the service and only use it for local development, you can delete the caddy container and remove the FORCE_SSL environment variable from the app container!

docker compose up -d

After startup, you can access DocuSeal through http://localhost:3000!

Sign-In

Setup

Template

Creating a template:

Create Template

Edit Template

Get Template

Get API Key

API Calls

For calling methods, refer to the official API documentation. The main API used here is Create a submission:

curl --location 'https://app.docuseal.orb.local/api/submissions' \
--header 'X-Auth-Token: cfKXy7c6PyciBqrZJsAiAEiCxXqMMfidEkvzTzkhZEH' \
--header 'Content-Type: application/json' \
--data-raw '{
    "template_id": 1,
    "send_email": true,
    "submitters": [
        {
            "name": "Betterde Inc.",
            "role": "Party A",
            "email": "[email protected]",
            "fields": [
                {
                    "name": "Company Name",
                    "default_value": "Betterde Inc."
                },
                {
                    "name": "Representative",
                    "default_value": "George"
                },
                {
                    "name": "Contact Phone",
                    "default_value": "021-3828272"
                }
            ]
        }
    ]
}'

Submissions

After successful creation, if the SMTP configuration is correct, Party A should receive an email. If they don’t receive it, you can also copy the link from the backend and send it privately!

After the end user completes the signing, the following content will be displayed:

Completed

Challenges Encountered

Due to font issues, the content entered by signers cannot include Chinese characters, otherwise it will cause the backend to fail when creating PDFs, which prevents users from downloading the signed content!

Currently, my solution is to integrate Chinese fonts in the Dockerfile:

FROM ruby:3.2.2-alpine3.18 as fonts

WORKDIR /fonts

COPY PingFang-zh-CN.ttf /fonts
COPY PingFang-zh-TW.ttf /fonts

RUN apk --no-cache add fontforge wget ttf-liberation &&  cp /usr/share/fonts/liberation/LiberationSans-Regular.ttf /usr/share/fonts/liberation/LiberationSans-Bold.ttf . && wget https://cdn.jsdelivr.net/gh/notofonts/notofonts.github.io/fonts/NotoSansArabic/hinted/ttf/NotoSansArabic-Regular.ttf && wget https://github.com/impallari/DancingScript/raw/master/fonts/DancingScript-Regular.otf && wget https://github.com/impallari/DancingScript/raw/master/OFL.txt

RUN fontforge -lang=py -c 'font1 = fontforge.open("LiberationSans-Regular.ttf"); font2 = fontforge.open("NotoSansArabic-Regular.ttf"); font3 = fontforge.open("PingFang-zh-CN.ttf"); font4 = fontforge.open("PingFang-zh-TW.ttf"); font1.mergeFonts(font2); font1.mergeFonts(font3); font1.mergeFonts(font4); font1.generate("LiberationSans-Regular.ttf")'

Then build your own Docker Image!

I hope this is helpful, Happy hacking…