TLS to RabbitMQ and Redis
This section applies when your RabbitMQ broker or Redis cache presents a TLS certificate issued by a CA that is not publicly trusted. Common examples are an internal enterprise CA (such as Venafi or an internal PKI), a self-managed RabbitMQ with an internally issued certificate, or AWS ElastiCache with in-transit encryption enabled.Why this is required
Draftable’s services perform full TLS certificate validation on their outbound connections to RabbitMQ and Redis. They verify both:- The certificate chain — the issuing CA must be trusted by the container.
- The hostname — the certificate’s Subject Alternative Name (SAN) must match the hostname the service connects to.
Which services need the CA
Install your CA in every application container that connects to RabbitMQ or Redis over TLS:Step 1 — Trust your CA in the containers
Draftable’s containers run on Linux and use the operating system trust store. There are two supported approaches.Option A — Add the CA to the image (recommended)
draftable/apish-compare and draftable/apish-converter. Include the full chain (root plus any intermediate CAs).Option B — Mount the CA and point the runtime at it
SSL_CERT_DIR pointing at a directory that includes your CA). On Kubernetes this is commonly done with an init container that appends your CA to the system bundle in a shared volume.Step 2 — Enable TLS on the connections
Set the TLS environment variables on the services. See the Docker Compose guide for the full variable reference.Step 3 — Verify
From inside one of the application pods (or any pod in the same namespace that hasopenssl), confirm the certificate is trusted and the name matches:
- Verify return code: 0 (ok) — the certificate chain is trusted in that container.
unable to get local issuer certificatemeans the CA is not trusted there (revisit Step 1). - Subject Alternative Name — confirm it lists the exact hostname you connect to.
Outbound HTTPS and licence activation
This section applies when Draftable’s own outbound HTTPS requests are intercepted and re-signed by an internal CA. This is common in enterprise networks that run TLS inspection on egress traffic, or that force all outbound traffic through an inspecting proxy.The symptom
Licence activation fails, and the logs contain a certificate verification error:Why it happens
API Self-Hosted contacts Draftable’s licensing service over HTTPS to activate your licence, and again periodically to revalidate it:The step that catches everyone out
Draftable’s licensing client is written in Python and uses therequests library. requests does not read the operating system trust store. It uses its own bundled CA list.
This means that adding your CA with update-ca-certificates alone, which is sufficient for RabbitMQ and Redis, will not fix licence activation. You must also point the Python HTTP stack at a bundle that includes your CA.
Fix
Obtain your internal CA certificate
https://draftable.com from a machine on the affected network, inspect the certificate, and export every certificate in the chain. On an inspected network these will be your internal CA’s certificates rather than Draftable’s public ones, which is itself confirmation that inspection is in play.Install the CA in the trust store
Point the Python HTTP stack at the system bundle
REQUESTS_CA_BUNDLE on every service that makes outbound HTTPS requests:/etc/ssl/certs/ca-certificates.crt is the combined bundle that update-ca-certificates writes, so it now contains both the public CAs and yours.Set these on the web, celery-worker and celery-beat services at minimum. Setting them on all application services is simplest and does no harm.Recreate the containers and activate
Verify
From inside a running container, confirm the chain is trusted:SSLCertVerificationError means REQUESTS_CA_BUNDLE is not set or is not pointing at a bundle containing your CA.
Other outbound HTTPS
The same fix applies to any other outbound HTTPS request your instance makes. The most common is fetching documents supplied as asource_url when that URL is served by an internal web server using an internally issued certificate.
draftable.com, no CA installation is needed for licence activation. See the network requirements article for the full list of endpoints.Troubleshooting
Licence activation fails with 'unable to get local issuer certificate' even though I installed the CA
Licence activation fails with 'unable to get local issuer certificate' even though I installed the CA
REQUESTS_CA_BUNDLE variable. Installing the CA in the OS trust store is not enough for licence activation, because the Python HTTP client does not read the OS trust store. See Outbound HTTPS and licence activation.Also confirm you recreated the containers rather than restarting them, since environment variables are only read at start-up.Activation worked, then started failing weeks later
Activation worked, then started failing weeks later
A service cannot connect, but openssl from the pod succeeds
A service cannot connect, but openssl from the pod succeeds
unable to get local issuer certificate
unable to get local issuer certificate
update-ca-certificates ran (Option A), or that SSL_CERT_FILE / SSL_CERT_DIR points at a bundle that includes your CA (Option B).Certificate name mismatch
Certificate name mismatch
AMQP_HOST / REDIS_HOST is not in the certificate’s SAN. Reissue the certificate with a SAN that includes the exact hostname your services use to connect.
