Skip to content

TLS Configuration

TLS Certificate Setup for MazeVault Deployment

Document Version: 1.0.0
Last Updated: 2026-10-28


1. Certificate Requirements

Certificate Purpose Format Minimum Key Size
Server TLS HTTPS for Web Interface + API PEM RSA 2048 / ECDSA P-256
OCSP TLS HTTPS for OCSP Responder (optional) PEM RSA 2048 / ECDSA P-256
Database SSL PostgreSQL connection encryption PEM RSA 2048
Agent mTLS CA CA for agent client certificates PEM RSA 2048

2. Certificate Options

Option A: MazeVault Internal CA

Use MazeVault's built-in Certificate Authority to issue server certificates for internal deployments:

  1. Create a Root CA in MazeVault (Settings → Certificate Authorities → Create CA)
  2. Issue a server certificate for your domain
  3. Distribute the Root CA certificate to all clients as a trusted CA

Option B: Let's Encrypt (Public Internet)

For internet-facing deployments, use Let's Encrypt with cert-manager (Kubernetes) or certbot (on-premise):

Kubernetes (cert-manager):

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: mazevault-tls
  namespace: mazevault
spec:
  secretName: mazevault-tls
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
    - vault.example.com

On-Premise (certbot):

sudo certbot certonly --nginx -d vault.example.com
# Certificates stored in /etc/letsencrypt/live/vault.example.com/

Option C: Enterprise CA (Internal PKI)

Use your organization's existing PKI infrastructure to issue certificates:

  1. Generate a CSR on the MazeVault server
  2. Submit to your enterprise CA (Microsoft ADCS, Venafi, etc.)
  3. Install the issued certificate and CA chain

3. TLS Configuration — On-Premise

Certificate File Placement

/opt/mazevault/certs/
├── server.crt          # Server certificate + intermediate CA chain
├── server.key          # Private key (chmod 600)
└── ca.crt              # Root CA certificate (for verification)

File Permissions

chmod 644 /opt/mazevault/certs/server.crt
chmod 600 /opt/mazevault/certs/server.key
chmod 644 /opt/mazevault/certs/ca.crt
chown root:root /opt/mazevault/certs/*

Edge TLS Settings

In the Compose kit the edge container terminates TLS (TLS 1.2 and 1.3) with server.crt and server.key; you do not configure nginx yourself. If you put your own reverse proxy in front of it, the recommended TLS configuration is:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;

4. TLS Configuration — Kubernetes

TLS Secret

kubectl create secret tls mazevault-tls \
  --namespace mazevault \
  --cert=server.crt \
  --key=server.key

Ingress TLS

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mazevault-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  tls:
    - hosts:
        - vault.example.com
      secretName: mazevault-tls

5. Database SSL

PostgreSQL SSL Configuration

For standalone PostgreSQL:

# postgresql.conf
ssl = on
ssl_cert_file = '/var/lib/postgresql/certs/server.crt'
ssl_key_file = '/var/lib/postgresql/certs/server.key'
ssl_ca_file = '/var/lib/postgresql/certs/ca.crt'
ssl_min_protocol_version = 'TLSv1.2'

For Azure Database for PostgreSQL Flexible Server, SSL is enforced by default.

The PostgreSQL bundled with the Docker Compose kit runs with ssl=on using the certificate in the certs volume (server.crt / server.key, generated by init-certs or imported by you); the backend and OCSP responder connect with sslmode=require over the kit's internal network. import-cert.sh and renew-certs.sh restart postgres, backend, ocsp, frontend, edge and docs after replacing the certificate (compose project MAZEVAULT_COMPOSE_PROJECT, default mazevault).

An imported certificate needs its CA chain

The web interface server (BFF) verifies the backend through /certs/ca-bundle.crt (NODE_EXTRA_CA_CERTS). import-cert.sh and renew-certs.sh build this file as the leaf certificate followed by the CA chain, and warn when no chain was given (the bundle is then the leaf only and the web interface cannot verify the backend). Import with the chain: ./import-cert.sh cert.pem key.pem ca-chain.pem. An existing ca-bundle.crt is kept when the kit starts.

The certificate must name NUXT_CORE_API_SERVERNAME

The BFF checks the backend certificate against NUXT_CORE_API_SERVERNAME (default MAZEVAULT_DOMAIN). An IP address matches only an IP entry of the certificate's subject alternative names, never a DNS entry. When MAZEVAULT_DOMAIN is an IP address, the installers and upgrade-mazevault.sh therefore add NUXT_CORE_API_SERVERNAME=localhost to .env (every certificate generated by init-certs names localhost), and init-certs adds IP:<MAZEVAULT_DOMAIN> to new certificates. An imported certificate must name the value of NUXT_CORE_API_SERVERNAME, or every sign-in fails with 502. upgrade-mazevault.sh checks this against the running installation's server.crt before it switches anything and stops with the old stack running when the name is missing.

Connection String

postgresql://user:password@host:5432/mazevault?sslmode=verify-full&sslrootcert=/path/to/ca.crt
SSL Mode Description Recommended
disable No SSL ❌
require SSL required, no CA verification ⚠️ Development only
verify-ca SSL + CA certificate verification ✅
verify-full SSL + CA + hostname verification ✅ Production

6. Certificate Renewal

Monitoring Expiry

MazeVault monitors TLS certificate expiry and raises alerts:

Threshold Alert Level
30 days before expiry Warning
7 days before expiry Critical

Renewal Procedures

Let's Encrypt (auto-renewal):

# Certbot auto-renewal (cron)
0 0 * * * certbot renew --quiet --post-hook "docker compose -f /opt/mazevault/docker-compose.yml restart edge"

Manual renewal: 1. Obtain new certificate from your CA 2. Import it with import-cert.sh (including the CA chain), which replaces the files in /opt/mazevault/certs/ and restarts the affected services including edge; if you replace the files by hand, restart the edge: docker compose restart edge

Kubernetes (cert-manager): Renewal is automatic.

7. Verification

# Verify TLS configuration
openssl s_client -connect vault.example.com:443 -servername vault.example.com < /dev/null 2>/dev/null | openssl x509 -noout -dates -subject

# Check certificate chain
openssl s_client -connect vault.example.com:443 -showcerts < /dev/null

# Test with curl
curl -v https://vault.example.com/api/v1/health

8. Custom CA for Outgoing Connections (SMTP, LDAP, etc.)

If your SMTP server, LDAP directory, or other external service uses a certificate signed by a private / corporate CA, MazeVault's backend container must trust that CA. Without it, outgoing TLS connections will fail with:

x509: certificate signed by unknown authority

Docker Compose

  1. Place your CA certificate (PEM format) in a path accessible to the host, e.g. ./certs/corporate-ca.crt.
  2. Mount the certificate and update the trust store via an entrypoint override:
services:
  mazevault-backend:
    volumes:
      - ./certs/corporate-ca.crt:/usr/local/share/ca-certificates/corporate-ca.crt:ro
    entrypoint: ["/bin/sh", "-c", "update-ca-certificates && exec ./main"]
  1. Restart the service: docker compose up -d mazevault-backend.

Kubernetes

Create a ConfigMap from the CA file and mount it:

apiVersion: v1
kind: ConfigMap
metadata:
  name: corporate-ca
data:
  corporate-ca.crt: |
    -----BEGIN CERTIFICATE-----
    <your CA certificate content>
    -----END CERTIFICATE-----
---
# In the backend Deployment spec:
volumes:
  - name: corporate-ca
    configMap:
      name: corporate-ca
containers:
  - name: mazevault-backend
    volumeMounts:
      - name: corporate-ca
        mountPath: /usr/local/share/ca-certificates/corporate-ca.crt
        subPath: corporate-ca.crt
        readOnly: true
    command: ["/bin/sh", "-c", "update-ca-certificates && exec ./main"]

Verification

# From inside the running container:
docker exec mazevault-backend openssl s_client -connect smtp.example.com:587 -starttls smtp < /dev/null 2>&1 | head -20

A successful connection shows Verify return code: 0 (ok).