TLS Configuration
Database TLS and ingress TLS for AGLedger self-hosted deployments. Configure once, rotate predictably.
Database TLS
AGLedger connects to PostgreSQL via a single DATABASE_URL. TLS is controlled by the sslmode query parameter in that URL plus NODE_EXTRA_CA_CERTS for the trust anchor.
AWS RDS / Aurora PostgreSQL
The Docker image ships with the AWS RDS global CA bundle at /etc/ssl/certs/rds-global-bundle.pem. Use it directly:
DATABASE_URL=postgresql://agledger:<password>@<cluster>.cluster-<id>.<region>.rds.amazonaws.com:5432/agledger?sslmode=verify-full
NODE_EXTRA_CA_CERTS=/etc/ssl/certs/rds-global-bundle.pem
verify-full validates the server certificate AND the hostname. Accept nothing weaker in production.
No additional mounts required — the CA bundle is baked into the image. AWS rotates the RDS CA periodically; refresh the image when AWS publishes a new global bundle (see AWS RDS certificate rotation).
Google Cloud SQL
Mount your Cloud SQL server certificate into the container and point NODE_EXTRA_CA_CERTS at it:
# Helm values.yaml excerpt
config:
nodeExtraCaCerts: /certs/server-ca.pem
# Mount a Secret containing server-ca.pem to /certs
DATABASE_URL=postgresql://agledger:<password>@<private-ip>:5432/agledger?sslmode=verify-full
For public-IP Cloud SQL instances, use the Cloud SQL Auth Proxy as a sidecar and connect to localhost. The proxy terminates TLS externally; inside the pod use sslmode=disable against the proxy.
Azure Database for PostgreSQL (Flexible Server)
Azure Flexible Server presents certificates issued under DigiCert Global Root CA. Mount a CA bundle that includes it:
DATABASE_URL=postgresql://agledger:<password>@<server>.postgres.database.azure.com:5432/agledger?sslmode=verify-full
NODE_EXTRA_CA_CERTS=/certs/DigiCertGlobalRootCA.crt.pem
Self-managed PostgreSQL with a private CA
Mount your CA into the container (Kubernetes Secret or bind mount) and set the path:
NODE_EXTRA_CA_CERTS=/certs/ca.pem
DATABASE_URL=postgresql://agledger:<password>@pg.internal:5432/agledger?sslmode=verify-full
sslmode options
| Value | Verifies server cert? | Verifies hostname? | Recommendation |
|-------|----------------------|--------------------|-----------------|
| disable | No | No | Never in production |
| require | No | No | Minimum — traffic encrypted but MITM-able |
| verify-ca | Yes | No | Acceptable with private DNS |
| verify-full | Yes | Yes | Recommended |
If you must disable DB TLS temporarily for local testing, set ALLOW_DB_WITHOUT_SSL=true. Never set this in production.
Ingress TLS (Kubernetes)
Ingress TLS terminates at the load balancer or ingress controller. AGLedger listens on HTTP inside the cluster — it does not terminate TLS itself.
AWS ALB + ACM (tested)
Provision a certificate in ACM, then configure the Helm values with the ACM ARN:
# values.yaml
ingress:
enabled: true
className: alb
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:<account>:certificate/<cert-id>
alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS13-1-2-2021-06
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
alb.ingress.kubernetes.io/healthcheck-path: /health
hosts:
- host: api.agledger.your-company.com
paths:
- path: /
pathType: Prefix
ACM handles renewal automatically; no manual rotation required. This is the path validated by the AGLedger testbed.
cert-manager + Let's Encrypt (untested)
The Helm chart supports cert-manager via the standard ingress.tls[] field. AGLedger has not validated this path — adopt it with your own verification.
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: api.agledger.your-company.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: agledger-tls
hosts:
- api.agledger.your-company.com
cert-manager issues and rotates certificates automatically. If you use this path, verify that your ClusterIssuer is configured and that the ACME HTTP-01 or DNS-01 solver can reach Let's Encrypt from inside the cluster.
Trust proxy
Whichever ingress path you use, set:
config:
trustProxy: true
This tells AGLedger to honor X-Forwarded-For and X-Forwarded-Proto from the load balancer. Without it, rate limiting counts the load balancer's IP instead of the real client, and redirects may drop the https:// scheme.
Ingress TLS (Docker Compose)
Docker Compose deployments expose AGLedger on 127.0.0.1:3001. Terminate TLS at a reverse proxy (Caddy, nginx, Traefik) running on the same host or in front of it. The configuration reference has complete Caddy and nginx examples with headers, client-body limits, and rate limiting.
Certificate rotation
| Scenario | Rotation |
|----------|----------|
| RDS/Aurora CA bundle | Image refresh when AWS publishes a new bundle |
| ACM cert | Auto-renewal; ACM handles it |
| cert-manager + Let's Encrypt | Auto-renewal; cert-manager handles it |
| Self-managed cert behind reverse proxy | Replace the mounted cert, caddy reload / nginx -s reload |
AGLedger itself does not need to restart when the upstream proxy's TLS cert rotates. For DB CA rotation, restart the API pods so they pick up the new trust anchor.
Verify TLS is active
From outside the cluster:
curl -vvI https://api.agledger.your-company.com/health 2>&1 | grep -iE "tls|ssl|subject"
From inside the cluster, check that the DB connection uses TLS:
kubectl exec -n agledger deploy/agledger-api -- \
node -e "
const { Client } = require('pg');
const c = new Client({ connectionString: process.env.DATABASE_URL });
c.connect().then(() => c.query('SHOW ssl')).then(r => console.log(r.rows));
"
ssl=on means TLS is active between AGLedger and PostgreSQL.
Related
- Configuration Reference —
NODE_EXTRA_CA_CERTS,sslmode,ALLOW_DB_WITHOUT_SSL, proxy configuration - Installation — Helm values for ingress and pod setup
- Version Matrix — tested infrastructure
Verified against install repo + Helm chart v0.19.17 on 2026-04-21. AWS ALB + ACM is the tested ingress path; cert-manager is documented but untested.