StackGres enables SSL/TLS encryption by default for all PostgreSQL connections, protecting data in transit between clients and the database.
By default, StackGres:
No configuration is required for basic SSL/TLS protection.
To disable SSL (not recommended for production):
apiVersion: stackgres.io/v1
kind: SGCluster
metadata:
name: my-cluster
spec:
postgres:
ssl:
enabled: false
Change the auto-generated certificate duration using ISO 8601 format:
apiVersion: stackgres.io/v1
kind: SGCluster
metadata:
name: my-cluster
spec:
postgres:
ssl:
enabled: true
duration: P365D # 365 days
Duration format examples:
P30D - 30 daysP6M - 6 monthsP1Y - 1 yearP1Y6M - 1 year and 6 monthsFor production environments, you may want to use certificates from your organization’s PKI or a trusted CA.
Generate or obtain your certificate and private key. For example, using OpenSSL:
# Generate private key
openssl genrsa -out server.key 4096
# Generate certificate signing request
openssl req -new -key server.key -out server.csr \
-subj "/CN=my-cluster.default.svc.cluster.local"
# Self-sign the certificate (or submit CSR to your CA)
openssl x509 -req -in server.csr -signkey server.key \
-out server.crt -days 365
For proper hostname verification, include Subject Alternative Names:
# Create a config file for SANs
cat > san.cnf <<EOF
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
CN = my-cluster
[v3_req]
subjectAltName = @alt_names
[alt_names]
DNS.1 = my-cluster
DNS.2 = my-cluster.default
DNS.3 = my-cluster.default.svc
DNS.4 = my-cluster.default.svc.cluster.local
DNS.5 = my-cluster-primary
DNS.6 = my-cluster-replicas
EOF
# Generate with SANs
openssl req -new -key server.key -out server.csr -config san.cnf
openssl x509 -req -in server.csr -signkey server.key \
-out server.crt -days 365 -extensions v3_req -extfile san.cnf
kubectl create secret generic my-cluster-ssl \
--from-file=tls.crt=server.crt \
--from-file=tls.key=server.key
Or using a YAML manifest:
apiVersion: v1
kind: Secret
metadata:
name: my-cluster-ssl
type: Opaque
data:
tls.crt: <base64-encoded-certificate>
tls.key: <base64-encoded-private-key>
apiVersion: stackgres.io/v1
kind: SGCluster
metadata:
name: my-cluster
spec:
postgres:
ssl:
enabled: true
certificateSecretKeySelector:
name: my-cluster-ssl
key: tls.crt
privateKeySecretKeySelector:
name: my-cluster-ssl
key: tls.key
For automated certificate management, integrate with cert-manager:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-cluster-cert
spec:
secretName: my-cluster-ssl
duration: 8760h # 1 year
renewBefore: 720h # 30 days
subject:
organizations:
- my-organization
commonName: my-cluster
dnsNames:
- my-cluster
- my-cluster.default
- my-cluster.default.svc
- my-cluster.default.svc.cluster.local
- my-cluster-primary
- my-cluster-replicas
issuerRef:
name: my-issuer
kind: ClusterIssuer
apiVersion: stackgres.io/v1
kind: SGCluster
metadata:
name: my-cluster
spec:
postgres:
ssl:
enabled: true
certificateSecretKeySelector:
name: my-cluster-ssl
key: tls.crt
privateKeySecretKeySelector:
name: my-cluster-ssl
key: tls.key
cert-manager will automatically renew the certificate before expiration.
Connect and check the connection:
kubectl exec -it my-cluster-0 -c postgres-util -- psql -c "SHOW ssl"
# Require SSL
psql "host=my-cluster port=5432 dbname=postgres user=postgres sslmode=require"
# Verify server certificate
psql "host=my-cluster port=5432 dbname=postgres user=postgres sslmode=verify-full sslrootcert=/path/to/ca.crt"
| Mode | Description |
|---|---|
disable |
No SSL |
allow |
Try non-SSL, then SSL |
prefer |
Try SSL, then non-SSL (default) |
require |
Require SSL, don’t verify certificate |
verify-ca |
Require SSL, verify CA |
verify-full |
Require SSL, verify CA and hostname |
For production, use verify-full when possible.
If using auto-generated certificates and you need the CA for client verification:
# Get the certificate from the cluster
kubectl exec my-cluster-0 -c postgres-util -- \
cat /etc/ssl/server.crt > server.crt
Auto-generated certificates are automatically rotated before expiration. PostgreSQL will reload the new certificates without restart.
For custom certificates:
# Update the secret
kubectl create secret generic my-cluster-ssl \
--from-file=tls.crt=new-server.crt \
--from-file=tls.key=new-server.key \
--dry-run=client -o yaml | kubectl apply -f -