Self-Signed Certificate in Certificate Chain Error on Strapi Deployment with DigitalOcean Managed PostgreSQL Database

System Information
  • Strapi Version: 4.25.8
  • Operating System: Ubuntu 22.04 stack
  • Database: Postgres 16
  • Node Version: 20.x
  • NPM Version: 10.9.0

I’m facing an issue with deploying my Strapi application on the DigitalOcean App Platform. Despite extensive troubleshooting, I keep encountering the following error during deployment:

Server wasn't able to start properly.
Error: self-signed certificate in certificate chain
    at TLSSocket.onConnectSecure (node:_tls_wrap:1674:34)
    at TLSSocket.emit (node:events:519:28)
    at TLSSocket.emit (node:domain:488:12)
    at TLSSocket._finishInit (node:_tls_wrap:1085:8)
    at ssl.onhandshakedone (node:_tls_wrap:871:12)

Setup and What I’ve Tried

1. Application Setup

  • I’m deploying a Strapi application using the DigitalOcean App Platform.
  • The application connects to a DigitalOcean Managed PostgreSQL Cluster.

2. Database Details

  • Cluster Name: db-cluster-name
  • PostgreSQL Version: 16
  • Cluster Type: Primary-only, 1 GB RAM / 1 vCPU, 10 GB Disk.
  • Location: NYC1.

3. Environment Variables

Here are the relevant .env variables used in the App Platform:

APP_URL=mach1-backend-ejgaf.ondigitalocean.app
DATABASE_HOST=${db-cluster-name.HOSTNAME}
DATABASE_PORT=${db-cluster-name.PORT}
DATABASE_NAME=${db-cluster-name.DATABASE}
DATABASE_USERNAME=${db-cluster-name.USERNAME}
DATABASE_PASSWORD=${db-cluster-name.password}
DATABASE_CLIENT=postgres
DATABASE_SSL_REJECT_UNAUTHORIZED=false
DATABASE_SSL=true
DATABASE_SSL_CA=./database/ca-certificate.crt
CA_CERT=${db-cluster-name.CA_CERT}

4. Certificate Setup

  • I’ve downloaded the CA certificate for the database cluster and placed it in the database folder of my project as ca-certificate.crt.
  • The same setup works perfectly when I run the app locally with yarn develop. It connects to the DigitalOcean database without any issues.

5. Strapi Database Configuration

Here is my config/database.js:

import fs from 'fs';
import path from 'path';

module.exports = ({ env }) => ({
  connection: {
    client: 'postgres',
    connection: {
      host: env('DATABASE_HOST'),
      port: env.int('DATABASE_PORT'),
      database: env('DATABASE_NAME'),
      user: env('DATABASE_USERNAME'),
      password: env('DATABASE_PASSWORD'),
      ssl: {
        rejectUnauthorized: env.bool('DATABASE_SSL_REJECT_UNAUTHORIZED', false),
        ca: fs.readFileSync(path.join(__dirname, '..', '..', env('DATABASE_SSL_CA'))).toString(),
      },
    },
  },
});

6. What Works

  • Local Development: Using yarn develop locally, my app connects successfully to the DigitalOcean database cluster.
  • Database Testing: I can connect to the database using psql and tools like Navicat, with the same credentials and CA certificate.

Steps I’ve Tried to Resolve the Issue

  1. Checked the Environment Variables:
  • Verified that the App Platform correctly substitutes the ${db-cluster-name.*} variables.
  • Verified that the correct paths and credentials are being used.
  1. Tried Removing the DATABASE_URL:
  • I removed the DATABASE_URL to avoid conflicts and relied solely on individual environment variables for the connection configuration.
  1. Updated sslmode in the Database Connection:
  • I tried various sslmode values (require, verify-ca) but the issue persists.
  1. Debugged the Certificate:
  • Added debugging to ensure the CA certificate is loaded correctly in the App Platform environment.
  1. Increased Connection Timeouts:
  • Adjusted the connection timeout settings to rule out transient connection issues.

Why does this setup work locally but fail on the App Platform with the “self-signed certificate in certificate chain” error? Is there a specific configuration required for deploying Strapi with a DigitalOcean Managed PostgreSQL database on the App Platform?