Documenso

Local Certificate

Generate or convert a .p12 certificate and configure it for document signing.

Generating a Self-Signed Certificate

Create a self-signed certificate using OpenSSL. These commands work on Linux, macOS, and Windows Subsystem for Linux (WSL).

Generate a private key

Create a 2048-bit RSA private key:

openssl genrsa -out private.key 2048

Create a self-signed certificate

Generate a certificate valid for one year:

openssl req -new -x509 -key private.key -out certificate.crt -days 365

When prompted, enter your organisation details:

FieldExample
Country NameUS
State or ProvinceCalifornia
Locality NameSan Francisco
Organization NameYour Company Inc
Organizational UnitEngineering
Common NameYour Company Signing CA
Email Addressadmin@example.com

Create the .p12 certificate

Combine the private key and certificate into a PKCS#12 (.p12) file:

openssl pkcs12 -export -out certificate.p12 -inkey private.key -in certificate.crt

You must set a password when prompted. Certificates without passwords cause signing failures with the error "Failed to get private key bags".

To set the password non-interactively:

# Set password securely (won't appear in command history)
read -s -p "Enter certificate password: " CERT_PASS
echo

openssl pkcs12 -export -out certificate.p12 -inkey private.key -in certificate.crt \
    -password env:CERT_PASS

Clean up

Remove the intermediate files:

rm private.key certificate.crt

Keep certificate.p12 and the password secure.

Using an Existing Certificate

If you have an existing certificate from a CA, convert it to PKCS#12 format.

If you have separate certificate and key files:

openssl pkcs12 -export -out certificate.p12 \
    -inkey private.key \
    -in certificate.crt \
    -certfile chain.crt

Include -certfile chain.crt if you have intermediate certificates.

Convert from DER to PEM first:

openssl x509 -inform DER -in certificate.der -out certificate.crt
openssl rsa -inform DER -in private.der -out private.key

PFX files are the same format as P12. You can use them directly by renaming to .p12.

Certificate Validation

Verify your certificate is valid:

# Check certificate details
openssl pkcs12 -in certificate.p12 -info -nokeys

# Verify password works
openssl pkcs12 -in certificate.p12 -noout

Environment Variables

VariableDescription
NEXT_PRIVATE_SIGNING_TRANSPORTSet to local (default)
NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATHPath to the .p12 certificate file
NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTSBase64-encoded .p12 file contents (alternative to file path)
NEXT_PRIVATE_SIGNING_PASSPHRASEPassphrase for the certificate

Using File Path

Mount the certificate file and set the path:

NEXT_PRIVATE_SIGNING_TRANSPORT=local
NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH=/opt/documenso/cert.p12
NEXT_PRIVATE_SIGNING_PASSPHRASE=your-certificate-password

Docker example:

docker run -d \
  -v /path/to/certificate.p12:/opt/documenso/cert.p12:ro \
  -e NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH=/opt/documenso/cert.p12 \
  -e NEXT_PRIVATE_SIGNING_PASSPHRASE="your-certificate-password" \
  documenso/documenso:latest

Using Base64-Encoded Contents

For environments where file mounting is not available (e.g., Railway, Vercel):

# Encode the certificate
base64 -i certificate.p12

Set the encoded string as an environment variable:

NEXT_PRIVATE_SIGNING_TRANSPORT=local
NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS=MIIKEQIBAzCCCdcGCSqGSIb3DQEHAaCCCcg...
NEXT_PRIVATE_SIGNING_PASSPHRASE=your-certificate-password

The NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS variable takes precedence over NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH if both are set.

Docker File Permissions

When running in Docker, the application runs as user 1001. The certificate file must be readable:

# On the host, before mounting
sudo chown 1001 certificate.p12
chmod 400 certificate.p12

Or mount as read-only and ensure group readability:

chmod 440 certificate.p12

On this page