Skip to main content
Local signing uses a .p12 (PKCS#12) certificate file to sign PDF documents. This is the simplest method to get started and works well for most deployments.

Prerequisites

You’ll need a .p12 certificate file. You can either:
  • Use your own certificate from a Certificate Authority
  • Generate a self-signed certificate for testing/development

Generating a Self-Signed Certificate

For development or testing, you can create a self-signed certificate using OpenSSL:
# Generate a private key and certificate
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes

# Convert to .p12 format (you'll be prompted for a passphrase)
openssl pkcs12 -export -out certificate.p12 -inkey key.pem -in cert.pem
When prompted, enter:
  • Common Name (CN): Your organization or app name (e.g., “Documenso”)
  • Export Password: A strong passphrase (you’ll need this for configuration)
Self-signed certificates work but won’t show as “trusted” in PDF viewers. For production, consider purchasing a certificate from a trusted CA like DigiCert or GlobalSign.

Configuration Methods

Documenso supports two ways to provide the certificate:
  1. File path - Store the .p12 file on disk
  2. Base64-encoded - Store the certificate as an environment variable (recommended for containers)

Method 1: File Path

Place your .p12 file somewhere accessible to the application:
# Signing configuration
NEXT_PRIVATE_SIGNING_TRANSPORT="local"
NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH="/path/to/certificate.p12"
NEXT_PRIVATE_SIGNING_PASSPHRASE="your-certificate-passphrase"
Example with Docker:
# Mount the certificate file
docker run -d \
  -v /host/path/to/certificate.p12:/app/certificate.p12 \
  -e NEXT_PRIVATE_SIGNING_TRANSPORT="local" \
  -e NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH="/app/certificate.p12" \
  -e NEXT_PRIVATE_SIGNING_PASSPHRASE="your-passphrase" \
  documenso/documenso
Convert your .p12 file to base64 and store it as an environment variable:
# Convert certificate to base64
base64 -i certificate.p12 | tr -d '\n' > certificate.base64.txt

# Or on macOS:
base64 -i certificate.p12 | pbcopy
Then configure:
NEXT_PRIVATE_SIGNING_TRANSPORT="local"
NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS="MIIKPAIBAzCCCgYGCSqGSIb3DQEHA..."
NEXT_PRIVATE_SIGNING_PASSPHRASE="your-certificate-passphrase"
The base64 method is ideal for serverless environments (Vercel, AWS Lambda) and container platforms where mounting files is inconvenient.

Environment Variables Reference

NEXT_PRIVATE_SIGNING_TRANSPORT
string
required
Set to "local" to use file-based signing.
NEXT_PRIVATE_SIGNING_TRANSPORT="local"
NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH
string
Path to the .p12 certificate file. Use this OR NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS.
NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH="/app/certs/certificate.p12"
NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS
string
Base64-encoded contents of the .p12 file. Use this OR NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH.
NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS="MIIKPAIBAzCCC..."
NEXT_PRIVATE_SIGNING_PASSPHRASE
string
Passphrase for the .p12 certificate. Leave empty if the certificate has no password.
NEXT_PRIVATE_SIGNING_PASSPHRASE="my-secure-passphrase"

Complete Configuration Example

.env
# Signing configuration
NEXT_PRIVATE_SIGNING_TRANSPORT="local"
NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH="/app/certs/certificate.p12"
NEXT_PRIVATE_SIGNING_PASSPHRASE="your-passphrase"

# Optional: Add timestamp authorities for LTV
NEXT_PRIVATE_SIGNING_TIMESTAMP_AUTHORITY="http://timestamp.digicert.com,http://timestamp.globalsign.com/tsa/r6advanced1"

# Optional: Customize contact info
NEXT_PUBLIC_SIGNING_CONTACT_INFO="support@example.com"

Development Mode

In non-production environments, if no certificate is configured, Documenso will automatically use an example certificate located at ./example/cert.p12.
The example certificate is only for development. Always configure your own certificate for production deployments.

Security Best Practices

1

Secure the Certificate File

Set restrictive file permissions on the .p12 file:
chmod 600 certificate.p12
chown app-user:app-group certificate.p12
2

Use Strong Passphrases

Always protect your .p12 file with a strong passphrase (minimum 16 characters).
3

Store Secrets Securely

Never commit certificates or passphrases to version control. Use:
  • Environment variables
  • Secret management services (AWS Secrets Manager, HashiCorp Vault)
  • Encrypted configuration files
4

Rotate Certificates Regularly

Replace certificates before they expire. Most CAs issue certificates valid for 1-2 years.
5

Monitor Certificate Expiration

Set up alerts to notify you before certificate expiration.

Troubleshooting

”No certificate found for local signing”

Cause: Neither NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH nor NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS is set. Solution: Provide the certificate using one of the two methods above.

”Failed to load certificate”

Possible causes:
  • Incorrect passphrase
  • Corrupted .p12 file
  • Invalid base64 encoding
Solution: Verify the passphrase and re-encode the certificate:
# Test the certificate with OpenSSL
openssl pkcs12 -info -in certificate.p12 -noout

# Re-encode to base64
base64 -i certificate.p12 | tr -d '\n'

“Signature not trusted” in PDF viewer

Cause: Self-signed certificate or certificate not in Adobe Approved Trust List (AATL). Solution: This is expected behavior for self-signed certificates. To show as “trusted”:
  • Purchase a certificate from an AATL-approved CA (DigiCert, GlobalSign, etc.)
  • Or users can manually trust your certificate in their PDF viewer

Migrating to Google Cloud KMS

If you need enhanced security later, you can migrate from local signing to Google Cloud KMS without changing your documents:
  1. Set up Google Cloud KMS (see Google Cloud KMS Setup)
  2. Update your environment variables to use gcloud-hsm transport
  3. Restart your application
All new signatures will use the KMS key, while existing signatures remain valid.

Next Steps

Environment Variables

View all configuration options

Google Cloud KMS

Upgrade to hardware-secured signing