> ## Documentation Index
> Fetch the complete documentation index at: https://help.draftable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API Self-Hosted v3 – Using a private or internal CA (TLS to RabbitMQ and Redis)

> How to make Draftable API Self-Hosted v3 trust a private or internal certificate authority so its services can connect to TLS-enabled RabbitMQ and Redis.

This guide explains how to make Draftable API Self-Hosted v3 trust a **private or internal certificate authority (CA)** so its services can connect to **TLS-enabled RabbitMQ and Redis**.

You need this 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.

<Note>
  If your broker or cache uses a **publicly trusted** certificate (for example Amazon MQ's default certificate or AWS ACM), no extra steps are needed. The steps below apply only when the certificate is issued by a private or internal CA.
</Note>

## Why this is required

Draftable's services perform **full TLS certificate validation** on their outbound connections to RabbitMQ and Redis. They verify both:

1. **The certificate chain** — the issuing CA must be trusted by the container.
2. **The hostname** — the certificate's Subject Alternative Name (SAN) must match the hostname the service connects to.

A privately issued certificate is valid, but the container has no reason to trust the issuer until you install your CA. If the CA is not trusted, or the SAN does not match the hostname, the connection is rejected.

<Note>
  TLS support for the compare service (RabbitMQ) and the converter (Redis) requires **apish-compare** and **apish-converter** version **3.0.3 or later**. Ensure your images are current before configuring TLS.
</Note>

## Which services need the CA

Install your CA in **every application container that connects to RabbitMQ or Redis over TLS**:

| Service       | RabbitMQ (TLS) | Redis (TLS) |
| ------------- | :------------: | :---------: |
| web           |        ✅       |      ✅      |
| celery-worker |        ✅       |      ✅      |
| celery-beat   |        ✅       |      ✅      |
| compare       |        ✅       |      ✅      |
| converter     |        —       |      ✅      |

The simplest approach is to install the CA in all of the application containers.

## 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.

<Steps>
  <Step title="Option A — Add the CA to the image (recommended)">
    Extend the relevant Draftable images to add your CA to the OS trust store. This is persistent and applies automatically wherever the image runs:

    ```dockerfile theme={null}
    FROM draftable/apish-web:latest
    COPY your-internal-ca.crt /usr/local/share/ca-certificates/your-internal-ca.crt
    RUN update-ca-certificates
    ```

    Repeat for `draftable/apish-compare` and `draftable/apish-converter`. Include the full chain (root plus any intermediate CAs).
  </Step>

  <Step title="Option B — Mount the CA and point the runtime at it">
    If you prefer not to rebuild the images, mount your CA bundle into the pods and set the standard OpenSSL environment variables, which Draftable's services honour on Linux:

    ```yaml theme={null}
    SSL_CERT_FILE: /etc/ssl/certs/ca-bundle-including-your-ca.crt
    ```

    (or `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>
</Steps>

## Step 2 — Enable TLS on the connections

Set the TLS environment variables on the services. See the [Docker Compose guide](/hc/en-us/articles/51141426113049-Draftable-API-Self-Hosted-v3-Docker-Compose-Guide#amqp-rabbitmq) for the full variable reference.

```yaml theme={null}
# RabbitMQ over TLS
AMQP_PORT: "5671"
AMQP_TLS:  "true"

# Redis over TLS (e.g. ElastiCache with in-transit encryption)
REDIS_PORT: "6380"
REDIS_TLS:  "true"
```

<Warning>
  The hostname you connect to (`AMQP_HOST` / `REDIS_HOST`) must be present in the certificate's **Subject Alternative Name (SAN)**. If your certificate was issued for a different name, the connection will fail certificate validation even when the CA is trusted.
</Warning>

## Step 3 — Verify

From inside one of the application pods (or any pod in the same namespace that has `openssl`), confirm the certificate is trusted and the name matches:

```bash theme={null}
# RabbitMQ
openssl s_client -connect <your-rabbitmq-host>:5671 -servername <your-rabbitmq-host>

# Redis
openssl s_client -connect <your-redis-host>:6380 -servername <your-redis-host>
```

Check two things in the output:

* **Verify return code: 0 (ok)** — the certificate chain is trusted in that container. `unable to get local issuer certificate` means the CA is not trusted there (revisit Step 1).
* **Subject Alternative Name** — confirm it lists the exact hostname you connect to.

## Troubleshooting

<AccordionGroup>
  <Accordion title="A service cannot connect, but openssl from the pod succeeds">
    Confirm the CA is installed in **that specific service's** container, not only in some of them. Each container has its own trust store, so the CA must be present in every service that connects over TLS (see the table above).
  </Accordion>

  <Accordion title="unable to get local issuer certificate">
    The CA chain is not trusted inside the container. Make sure you included the **full chain** (root plus intermediates) and that `update-ca-certificates` ran (Option A), or that `SSL_CERT_FILE` / `SSL_CERT_DIR` points at a bundle that includes your CA (Option B).
  </Accordion>

  <Accordion title="Certificate name mismatch">
    The hostname in `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.
  </Accordion>
</AccordionGroup>
