mirror of
https://github.com/documenso/documenso.git
synced 2025-11-09 20:12:31 +10:00
chore: self hosting docs update and certificate issues (#1847)
This commit is contained in:
19
SIGNING.md
19
SIGNING.md
@ -10,13 +10,24 @@ For the digital signature of your documents you need a signing certificate in .p
|
||||
|
||||
`openssl req -new -x509 -key private.key -out certificate.crt -days 365`
|
||||
|
||||
This will prompt you to enter some information, such as the Common Name (CN) for the certificate. Make sure you enter the correct information. The -days parameter sets the number of days for which the certificate is valid.
|
||||
This will prompt you to enter some information, such as the Common Name (CN) for the certificate. Make sure you enter the correct information. The `-days` parameter sets the number of days for which the certificate is valid.
|
||||
|
||||
3. Combine the private key and the self-signed certificate to create the p12 certificate. You can run the following command to do this:
|
||||
3. Combine the private key and the self-signed certificate to create the p12 certificate. You can run the following commands to do this:
|
||||
|
||||
`openssl pkcs12 -export -out certificate.p12 -inkey private.key -in certificate.crt`
|
||||
```bash
|
||||
# Set certificate password securely (won't appear in command history)
|
||||
read -s -p "Enter certificate password: " CERT_PASS
|
||||
echo
|
||||
|
||||
4. You will be prompted to enter a password for the p12 file. Choose a strong password and remember it, as you will need it to use the certificate (**can be empty for dev certificates**)
|
||||
# Create the p12 certificate using the environment variable
|
||||
openssl pkcs12 -export -out certificate.p12 -inkey private.key -in certificate.crt \
|
||||
-password env:CERT_PASS \
|
||||
-keypbe PBE-SHA1-3DES \
|
||||
-certpbe PBE-SHA1-3DES \
|
||||
-macalg sha1
|
||||
```
|
||||
|
||||
4. **IMPORTANT**: A certificate password is required to prevent signing failures. Make sure to use a strong password (minimum 4 characters) when prompted. Certificates without passwords will cause "Failed to get private key bags" errors during document signing.
|
||||
|
||||
5. Place the certificate `/apps/remix/resources/certificate.p12` (If the path does not exist, it needs to be created)
|
||||
|
||||
|
||||
@ -119,16 +119,89 @@ NEXT_PRIVATE_SMTP_USERNAME="<your-username>"
|
||||
NEXT_PRIVATE_SMTP_PASSWORD="<your-password>"
|
||||
```
|
||||
|
||||
### Update the Volume Binding
|
||||
### Set Up Your Signing Certificate
|
||||
|
||||
The `cert.p12` file is required to sign and encrypt documents, so you must provide your key file. Update the volume binding in the `compose.yml` file to point to your key file:
|
||||
<Callout type="warning">
|
||||
This is the most common source of issues for self-hosters. Please follow these steps carefully.
|
||||
</Callout>
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- /path/to/your/keyfile.p12:/opt/documenso/cert.p12
|
||||
```
|
||||
The `cert.p12` file is required to sign and encrypt documents. You have three options:
|
||||
|
||||
After updating the volume binding, save the `compose.yml` file and run the following command to start the containers:
|
||||
#### Option A: Generate Certificate Inside Container (Recommended)
|
||||
|
||||
This method avoids file permission issues by creating the certificate directly inside the Docker container:
|
||||
|
||||
1. Start your containers:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
2. Set certificate password securely and generate certificate inside the container:
|
||||
|
||||
```bash
|
||||
# Set certificate password securely (won't appear in command history)
|
||||
read -s -p "Enter certificate password: " CERT_PASS
|
||||
echo
|
||||
|
||||
# Generate certificate inside container using environment variable
|
||||
docker exec -e CERT_PASS="$CERT_PASS" -it documenso-production-documenso-1 bash -c "
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||
-keyout /tmp/private.key \
|
||||
-out /tmp/certificate.crt \
|
||||
-subj '/C=US/ST=State/L=City/O=Organization/CN=localhost' && \
|
||||
openssl pkcs12 -export -out /app/certs/cert.p12 \
|
||||
-inkey /tmp/private.key -in /tmp/certificate.crt \
|
||||
-passout env:CERT_PASS && \
|
||||
rm /tmp/private.key /tmp/certificate.crt
|
||||
"
|
||||
```
|
||||
|
||||
3. Add the certificate passphrase to your `.env` file:
|
||||
|
||||
```bash
|
||||
NEXT_PRIVATE_SIGNING_PASSPHRASE="your_password_here"
|
||||
```
|
||||
|
||||
4. Restart the container to apply changes:
|
||||
```bash
|
||||
docker-compose restart documenso
|
||||
```
|
||||
|
||||
#### Option B: Use an Existing Certificate File
|
||||
|
||||
If you have an existing `.p12` certificate file:
|
||||
|
||||
1. **Place your certificate file** in an accessible location on your host system
|
||||
2. **Set proper permissions:**
|
||||
|
||||
```bash
|
||||
# Make sure the certificate is readable
|
||||
chmod 644 /path/to/your/cert.p12
|
||||
|
||||
# For Docker, ensure proper ownership
|
||||
chown 1001:1001 /path/to/your/cert.p12
|
||||
```
|
||||
|
||||
3. **Update the volume binding** in the `compose.yml` file:
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- /path/to/your/cert.p12:/opt/documenso/cert.p12:ro
|
||||
```
|
||||
|
||||
4. **Add certificate configuration** to your `.env` file:
|
||||
```bash
|
||||
NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH=/opt/documenso/cert.p12
|
||||
NEXT_PRIVATE_SIGNING_PASSPHRASE=your_certificate_password
|
||||
```
|
||||
|
||||
<Callout type="warning">
|
||||
Your certificate MUST have a password. Certificates without passwords will cause "Failed to get
|
||||
private key bags" errors.
|
||||
</Callout>
|
||||
|
||||
After setting up your certificate, save the `compose.yml` file and run the following command to start the containers:
|
||||
|
||||
```bash
|
||||
docker-compose --env-file ./.env up -d
|
||||
|
||||
20
apps/remix/app/routes/api+/certificate-status.ts
Normal file
20
apps/remix/app/routes/api+/certificate-status.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { getCertificateStatus } from '@documenso/lib/server-only/cert/cert-status';
|
||||
|
||||
export const loader = () => {
|
||||
try {
|
||||
const certStatus = getCertificateStatus();
|
||||
|
||||
return Response.json({
|
||||
isAvailable: certStatus.isAvailable,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
} catch {
|
||||
return Response.json(
|
||||
{
|
||||
isAvailable: false,
|
||||
timestamp: new Date().toISOString(),
|
||||
},
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -1,22 +1,47 @@
|
||||
import { getCertificateStatus } from '@documenso/lib/server-only/cert/cert-status';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
export async function loader() {
|
||||
type CheckStatus = 'ok' | 'warning' | 'error';
|
||||
|
||||
export const loader = async () => {
|
||||
const checks: {
|
||||
database: { status: CheckStatus };
|
||||
certificate: { status: CheckStatus };
|
||||
} = {
|
||||
database: { status: 'ok' },
|
||||
certificate: { status: 'ok' },
|
||||
};
|
||||
|
||||
let overallStatus: CheckStatus = 'ok';
|
||||
|
||||
try {
|
||||
await prisma.$queryRaw`SELECT 1`;
|
||||
|
||||
return Response.json({
|
||||
status: 'ok',
|
||||
message: 'All systems operational',
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
status: 'error',
|
||||
message: err instanceof Error ? err.message : 'Unknown error',
|
||||
},
|
||||
{ status: 500 },
|
||||
);
|
||||
} catch {
|
||||
checks.database = { status: 'error' };
|
||||
overallStatus = 'error';
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const certStatus = getCertificateStatus();
|
||||
if (certStatus.isAvailable) {
|
||||
checks.certificate = { status: 'ok' };
|
||||
} else {
|
||||
checks.certificate = { status: 'warning' };
|
||||
if (overallStatus === 'ok') {
|
||||
overallStatus = 'warning';
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
checks.certificate = { status: 'error' };
|
||||
overallStatus = 'error';
|
||||
}
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
status: overallStatus,
|
||||
timestamp: new Date().toISOString(),
|
||||
checks,
|
||||
},
|
||||
{ status: overallStatus === 'error' ? 500 : 200 },
|
||||
);
|
||||
};
|
||||
|
||||
@ -109,7 +109,7 @@ COPY --from=installer --chown=nodejs:nodejs /app/packages/prisma/migrations ./pa
|
||||
RUN npx prisma generate --schema ./packages/prisma/schema.prisma
|
||||
|
||||
|
||||
# Get the start script from docker/start.sh
|
||||
# Get the start script from docker/
|
||||
COPY --chown=nodejs:nodejs ./docker/start.sh /app/apps/remix/start.sh
|
||||
|
||||
WORKDIR /app/apps/remix
|
||||
|
||||
147
docker/README.md
147
docker/README.md
@ -18,27 +18,66 @@ This setup includes a PostgreSQL database and the Documenso application. You wil
|
||||
3. Create a `.env` file in the same directory and add your SMTP details as well as a few extra environment variables, following the example below:
|
||||
|
||||
```
|
||||
# Generate random secrets (you can use: openssl rand -hex 32)
|
||||
NEXTAUTH_SECRET="<your-secret>"
|
||||
NEXT_PRIVATE_ENCRYPTION_KEY="<your-key>"
|
||||
NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY="<your-secondary-key>"
|
||||
|
||||
# Your application URL
|
||||
NEXT_PUBLIC_WEBAPP_URL="<your-url>"
|
||||
|
||||
# SMTP Configuration
|
||||
NEXT_PRIVATE_SMTP_TRANSPORT="smtp-auth"
|
||||
NEXT_PRIVATE_SMTP_HOST="<your-host>"
|
||||
NEXT_PRIVATE_SMTP_PORT=<your-port>
|
||||
NEXT_PRIVATE_SMTP_USERNAME="<your-username>"
|
||||
NEXT_PRIVATE_SMTP_PASSWORD="<your-password>"
|
||||
NEXT_PRIVATE_SMTP_FROM_NAME="<your-from-name>"
|
||||
NEXT_PRIVATE_SMTP_FROM_ADDRESS="<your-from-email>"
|
||||
|
||||
# Certificate passphrase (required)
|
||||
NEXT_PRIVATE_SIGNING_PASSPHRASE="<your-certificate-password>"
|
||||
```
|
||||
|
||||
4. Update the volume binding for the cert file in the `compose.yml` file to point to your own key file:
|
||||
4. Set up your signing certificate. You have three options:
|
||||
|
||||
Since the `cert.p12` file is required for signing and encrypting documents, you will need to provide your own key file. Update the volume binding in the `compose.yml` file to point to your key file:
|
||||
**Option A: Generate Certificate Inside Container (Recommended)**
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- /path/to/your/keyfile.p12:/opt/documenso/cert.p12
|
||||
```
|
||||
Start your containers first, then generate a self-signed certificate:
|
||||
```bash
|
||||
# Start containers
|
||||
docker-compose up -d
|
||||
|
||||
1. Run the following command to start the containers:
|
||||
# Set certificate password securely (won't appear in command history)
|
||||
read -s -p "Enter certificate password: " CERT_PASS
|
||||
echo
|
||||
|
||||
# Generate certificate inside container using environment variable
|
||||
docker exec -e CERT_PASS="$CERT_PASS" -it documenso-production-documenso-1 bash -c "
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||
-keyout /tmp/private.key \
|
||||
-out /tmp/certificate.crt \
|
||||
-subj '/C=US/ST=State/L=City/O=Organization/CN=localhost' && \
|
||||
openssl pkcs12 -export -out /app/certs/cert.p12 \
|
||||
-inkey /tmp/private.key -in /tmp/certificate.crt \
|
||||
-passout env:CERT_PASS && \
|
||||
rm /tmp/private.key /tmp/certificate.crt
|
||||
"
|
||||
|
||||
# Restart container
|
||||
docker-compose restart documenso
|
||||
```
|
||||
|
||||
**Option B: Use Existing Certificate**
|
||||
|
||||
If you have an existing `.p12` certificate, update the volume binding in `compose.yml`:
|
||||
```yaml
|
||||
volumes:
|
||||
- /path/to/your/cert.p12:/opt/documenso/cert.p12:ro
|
||||
```
|
||||
|
||||
|
||||
5. Run the following command to start the containers:
|
||||
|
||||
```
|
||||
docker-compose --env-file ./.env up -d
|
||||
@ -46,7 +85,7 @@ docker-compose --env-file ./.env up -d
|
||||
|
||||
This will start the PostgreSQL database and the Documenso application containers.
|
||||
|
||||
5. Access the Documenso application by visiting `http://localhost:3000` in your web browser.
|
||||
6. Access the Documenso application by visiting `http://localhost:3000` in your web browser.
|
||||
|
||||
## Option 2: Standalone Docker Container
|
||||
|
||||
@ -69,27 +108,93 @@ docker pull ghcr.io/documenso/documenso
|
||||
```
|
||||
docker run -d \
|
||||
-p 3000:3000 \
|
||||
-e NEXTAUTH_SECRET="<your-nextauth-secret>"
|
||||
-e NEXT_PRIVATE_ENCRYPTION_KEY="<your-next-private-encryption-key>"
|
||||
-e NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY="<your-next-private-encryption-secondary-key>"
|
||||
-e NEXT_PUBLIC_WEBAPP_URL="<your-next-public-webapp-url>"
|
||||
-e NEXT_PRIVATE_INTERNAL_WEBAPP_URL="http://localhost:3000"
|
||||
-e NEXT_PRIVATE_DATABASE_URL="<your-next-private-database-url>"
|
||||
-e NEXT_PRIVATE_DIRECT_DATABASE_URL="<your-next-private-database-url>"
|
||||
-e NEXT_PRIVATE_SMTP_TRANSPORT="<your-next-private-smtp-transport>"
|
||||
-e NEXT_PRIVATE_SMTP_FROM_NAME="<your-next-private-smtp-from-name>"
|
||||
-e NEXT_PRIVATE_SMTP_FROM_ADDRESS="<your-next-private-smtp-from-address>"
|
||||
-v /path/to/your/keyfile.p12:/opt/documenso/cert.p12
|
||||
-e NEXTAUTH_SECRET="<your-nextauth-secret>" \
|
||||
-e NEXT_PRIVATE_ENCRYPTION_KEY="<your-next-private-encryption-key>" \
|
||||
-e NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY="<your-next-private-encryption-secondary-key>" \
|
||||
-e NEXT_PUBLIC_WEBAPP_URL="<your-next-public-webapp-url>" \
|
||||
-e NEXT_PRIVATE_INTERNAL_WEBAPP_URL="http://localhost:3000" \
|
||||
-e NEXT_PRIVATE_DATABASE_URL="<your-next-private-database-url>" \
|
||||
-e NEXT_PRIVATE_DIRECT_DATABASE_URL="<your-next-private-database-url>" \
|
||||
-e NEXT_PRIVATE_SMTP_TRANSPORT="<your-next-private-smtp-transport>" \
|
||||
-e NEXT_PRIVATE_SMTP_FROM_NAME="<your-next-private-smtp-from-name>" \
|
||||
-e NEXT_PRIVATE_SMTP_FROM_ADDRESS="<your-next-private-smtp-from-address>" \
|
||||
-e NEXT_PRIVATE_SIGNING_PASSPHRASE="<your-certificate-password>" \
|
||||
-v /path/to/your/cert.p12:/opt/documenso/cert.p12:ro \
|
||||
documenso/documenso
|
||||
```
|
||||
|
||||
Replace the placeholders with your actual database and SMTP details.
|
||||
|
||||
1. Access the Documenso application by visiting the URL you provided in the `NEXT_PUBLIC_WEBAPP_URL` environment variable in your web browser.
|
||||
3. Access the Documenso application by visiting the URL you provided in the `NEXT_PUBLIC_WEBAPP_URL` environment variable in your web browser.
|
||||
|
||||
## Success
|
||||
|
||||
You have now successfully set up Documenso using Docker. You can start organizing and managing your documents efficiently. If you encounter any issues or have further questions, please refer to the official Documenso documentation or seek assistance from the community.
|
||||
You have now successfully set up Documenso using Docker. You can start organizing and managing your documents efficiently.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Certificate Permission Issues
|
||||
|
||||
If you encounter errors related to certificate access, here are common solutions:
|
||||
|
||||
#### Error: "Failed to read signing certificate"
|
||||
|
||||
1. **Check file exists:**
|
||||
|
||||
```bash
|
||||
ls -la /path/to/your/cert.p12
|
||||
```
|
||||
|
||||
2. **Fix permissions:**
|
||||
|
||||
```bash
|
||||
chmod 644 /path/to/your/cert.p12
|
||||
chown 1001:1001 /path/to/your/cert.p12
|
||||
```
|
||||
|
||||
3. **Verify Docker mount:**
|
||||
```bash
|
||||
docker exec -it <container_name> ls -la /opt/documenso/cert.p12
|
||||
```
|
||||
|
||||
|
||||
### Container Logs
|
||||
|
||||
Check application logs for detailed error information:
|
||||
|
||||
```bash
|
||||
# For Docker Compose
|
||||
docker-compose logs -f documenso
|
||||
|
||||
# For standalone container
|
||||
docker logs -f <container_name>
|
||||
```
|
||||
|
||||
### Health Checks
|
||||
|
||||
Check the status of your Documenso instance:
|
||||
|
||||
```bash
|
||||
# Basic health check (database + certificate)
|
||||
curl http://localhost:3000/api/health
|
||||
|
||||
# Detailed certificate status
|
||||
curl http://localhost:3000/api/certificate-status
|
||||
```
|
||||
|
||||
The health endpoint will show:
|
||||
|
||||
- `status: "ok"` - Everything working properly
|
||||
- `status: "warning"` - App running but certificate issues
|
||||
- `status: "error"` - Critical issues (database down, etc.)
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Port already in use:** Change the port mapping in compose.yml or your docker run command
|
||||
2. **Database connection issues:** Ensure your database is running and accessible
|
||||
3. **SMTP errors:** Verify your email server settings in the .env file
|
||||
|
||||
If you encounter any issues or have further questions, please refer to the official Documenso documentation or seek assistance from the community.
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
|
||||
@ -63,7 +63,7 @@ services:
|
||||
ports:
|
||||
- ${PORT:-3000}:${PORT:-3000}
|
||||
volumes:
|
||||
- /opt/documenso/cert.p12:/opt/documenso/cert.p12
|
||||
- /opt/documenso/cert.p12:/opt/documenso/cert.p12:ro
|
||||
|
||||
volumes:
|
||||
database:
|
||||
|
||||
@ -1,7 +1,31 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
# 🚀 Starting Documenso...
|
||||
printf "🚀 Starting Documenso...\n\n"
|
||||
|
||||
# 🔐 Check certificate configuration
|
||||
printf "🔐 Checking certificate configuration...\n"
|
||||
|
||||
CERT_PATH="${NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH:-/opt/documenso/cert.p12}"
|
||||
|
||||
if [ -f "$CERT_PATH" ] && [ -r "$CERT_PATH" ]; then
|
||||
printf "✅ Certificate file found and readable - document signing is ready!\n"
|
||||
else
|
||||
printf "⚠️ Certificate not found or not readable\n"
|
||||
printf "💡 Tip: Documenso will still start, but document signing will be unavailable\n"
|
||||
printf "🔧 Check: http://localhost:3000/api/certificate-status for detailed status\n"
|
||||
fi
|
||||
|
||||
printf "\n📚 Useful Links:\n"
|
||||
printf "📖 Documentation: https://docs.documenso.com\n"
|
||||
printf "🐳 Self-hosting guide: https://docs.documenso.com/developers/self-hosting\n"
|
||||
printf "🔐 Certificate setup: https://docs.documenso.com/developers/self-hosting/signing-certificate\n"
|
||||
printf "🏥 Health check: http://localhost:3000/api/health\n"
|
||||
printf "📊 Certificate status: http://localhost:3000/api/certificate-status\n"
|
||||
printf "👥 Community: https://github.com/documenso/documenso\n\n"
|
||||
|
||||
printf "🗄️ Running database migrations...\n"
|
||||
npx prisma migrate deploy --schema ../../packages/prisma/schema.prisma
|
||||
|
||||
printf "🌟 Starting Documenso server...\n"
|
||||
HOSTNAME=0.0.0.0 node build/server/main.js
|
||||
|
||||
21
packages/lib/server-only/cert/cert-status.ts
Normal file
21
packages/lib/server-only/cert/cert-status.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import * as fs from 'node:fs';
|
||||
|
||||
import { env } from '@documenso/lib/utils/env';
|
||||
|
||||
export type CertificateStatus = {
|
||||
isAvailable: boolean;
|
||||
};
|
||||
|
||||
export const getCertificateStatus = (): CertificateStatus => {
|
||||
const defaultPath =
|
||||
env('NODE_ENV') === 'production' ? '/opt/documenso/cert.p12' : './example/cert.p12';
|
||||
const filePath = env('NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH') || defaultPath;
|
||||
|
||||
try {
|
||||
fs.accessSync(filePath, fs.constants.F_OK | fs.constants.R_OK);
|
||||
const stats = fs.statSync(filePath);
|
||||
return { isAvailable: stats.size > 0 };
|
||||
} catch {
|
||||
return { isAvailable: false };
|
||||
}
|
||||
};
|
||||
@ -1,5 +1,6 @@
|
||||
import fs from 'node:fs';
|
||||
import * as fs from 'node:fs';
|
||||
|
||||
import { getCertificateStatus } from '@documenso/lib/server-only/cert/cert-status';
|
||||
import { env } from '@documenso/lib/utils/env';
|
||||
import { signWithP12 } from '@documenso/pdf-sign';
|
||||
|
||||
@ -22,12 +23,23 @@ export const signWithLocalCert = async ({ pdf }: SignWithLocalCertOptions) => {
|
||||
|
||||
const signatureLength = byteRange[2] - byteRange[1];
|
||||
|
||||
const certStatus = getCertificateStatus();
|
||||
|
||||
if (!certStatus.isAvailable) {
|
||||
console.error('Certificate error: Certificate not available for document signing');
|
||||
throw new Error('Document signing failed: Certificate not available');
|
||||
}
|
||||
|
||||
let cert: Buffer | null = null;
|
||||
|
||||
const localFileContents = env('NEXT_PRIVATE_SIGNING_LOCAL_FILE_CONTENTS');
|
||||
|
||||
if (localFileContents) {
|
||||
cert = Buffer.from(localFileContents, 'base64');
|
||||
try {
|
||||
cert = Buffer.from(localFileContents, 'base64');
|
||||
} catch {
|
||||
throw new Error('Failed to decode certificate contents');
|
||||
}
|
||||
}
|
||||
|
||||
if (!cert) {
|
||||
@ -42,7 +54,12 @@ export const signWithLocalCert = async ({ pdf }: SignWithLocalCertOptions) => {
|
||||
certPath = env('NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH') || './example/cert.p12';
|
||||
}
|
||||
|
||||
cert = Buffer.from(fs.readFileSync(certPath));
|
||||
try {
|
||||
cert = Buffer.from(fs.readFileSync(certPath));
|
||||
} catch {
|
||||
console.error('Certificate error: Failed to read certificate file');
|
||||
throw new Error('Document signing failed: Certificate file not accessible');
|
||||
}
|
||||
}
|
||||
|
||||
const signature = signWithP12({
|
||||
|
||||
Reference in New Issue
Block a user