Files
captable/SELF-HOSTING.md
zooqueen e155a2bfef Send email through Hanzo notify
sendMail posts to /v1/notify/send/email as the app's own IAM identity
(client credentials), and notify delivers with the email provider and
sender configured for that org. SMTP settings and nodemailer are gone.
notify carries no attachments, so the e-sign completion email links the
signed document with a seven-day presigned URL instead of attaching it.
2026-09-15 12:06:01 -07:00

3.3 KiB

🚀 Self hosting

Hanzo Captable is an open-source project that you can host on your own server. This gives you full control over your data.

If you like to self-host Hanzo Captable, please schedule a call with us, and we will help you set up your own instance.

Book us

  • Prerequisites:

    • Docker
    • Postgres database (RDS, Cloud SQL, Supabase, Neon etc.)
    • SMTP provider (Resend, AWS SES, Mailgun, Sendgrid etc.)
    • S3 Compatible storage (AWS S3, R2, Minio, Backblaze etc.)
  • Official Docker Images:

  • Environment Variables:
    Following envrionment variables are required

NODE_ENV="production"
DATABASE_URL="postgres://user:password@host:port/dbname"
NEXTAUTH_SECRET="xxx" # Generated by `openssl rand -base64 32`
NEXTAUTH_URL="https://your-domain.com"
NEXT_PUBLIC_BASE_URL="https://your-domain.com"

# Hanzo IAM application: sign-in, and the identity that sends email through
# Hanzo notify with the org's email provider
IAM_URL="https://hanzo.id"
IAM_CLIENT_ID="xxx"
IAM_CLIENT_SECRET="xxx"

# File uplod environment variables
UPLOAD_REGION="us-west-1" # auto when using Cloudflare R2
UPLOAD_ENDPOINT="https://xxx.r2.cloudflarestorage.com"
UPLOAD_ACCESS_KEY_ID="xxx"
UPLOAD_SECRET_ACCESS_KEY="xxx"
UPLOAD_BUCKET_PUBLIC="public-bucket-name"
UPLOAD_BUCKET_PRIVATE="private-bucket-name"

Following environment variables are optional

# If you are using custom domain, especially with Cloudflare R2, AWAS S3 with custom domain.
NEXT_PUBLIC_UPLOAD_DOMAIN="https://custom.your-domain.com" 
  • Run the docker container:
docker run -d \
  -e NODE_ENV="replace" \
  -e DATABASE_URL="replace" \
  -e NEXTAUTH_SECRET="replace" \
  -e NEXTAUTH_URL="replace" \
  -e NEXT_PUBLIC_BASE_URL="replace" \
  -e IAM_URL="replace" \
  -e IAM_CLIENT_ID="replace" \
  -e IAM_CLIENT_SECRET="replace" \
  -e UPLOAD_REGION="replace" \
  -e UPLOAD_ENDPOINT="replace" \
  -e NEXT_PUBLIC_UPLOAD_DOMAIN="replace" \
  -e UPLOAD_ACCESS_KEY_ID="replace" \
  -e UPLOAD_SECRET_ACCESS_KEY="replace" \
  -e UPLOAD_BUCKET_PUBLIC="replace" \
  -e UPLOAD_BUCKET_PRIVATE="replace" \
  -p 3000:3000 \
  hanzoai/captable
  • Setup CORS for file uploads:
    Some of the services including Cloudflare R2 may require you to setup CORS for file uploads.\

    Here is an sample CORS configuration for Cloudflare R2.

[
  {
    "AllowedOrigins": [
      "https://your-domain.com"
    ],
    "AllowedMethods": [
      "HEAD",
      "GET",
      "POST",
      "PUT",
      "DELETE"
    ],
    "AllowedHeaders": [
      "*"
    ]
  }
]
  • Run database migrations:
docker exec -it <container_id> npx prisma migrate deploy
  • Access the application:
    Open your browser and navigate to https://your-domain.com

  • Questions?
    If you have any questions, please schedule a call with us, and we will help you set up your own instance.

    Book us