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

# TLS certificates

> Supply, mount and renew the TLS certificates that serve a self-hosted Cymph deployment.

Cymph is always served over HTTPS. TLS is terminated by the `nginx` service, which reads a certificate and a private key from paths on the host that you supply during [installation](/deployment/self-hosted/installation).

<Note>
  The certificates must exist on the host **before** you run `env.sh`. There is no HTTP fallback and no built-in certificate provisioning.
</Note>

## What you need

Two files on the host running Docker:

| File               | Contents                                                                                                               |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| Certificate bundle | Your server certificate, followed by any intermediate certificates, in PEM format. Default path `/etc/ssl/bundle.crt`. |
| Private key        | The matching unencrypted private key in PEM format. Default path `/etc/ssl/cert.key`.                                  |

The certificate's common name or a subject alternative name must match the domain or IP address you give during setup — that value is written into the nginx `server_name`.

Any certificate authority works. Common choices:

* **A public CA via certbot / ACME**, when the deployment has a resolvable public domain name.
* **Your internal PKI**, which is typical for deployments on a private network. Include the full chain in the bundle so clients that already trust your internal root validate cleanly.
* **A self-signed certificate via openssl**, for evaluation. Browsers will warn on every visit.

## Supplying the paths

`env.sh` prompts for both locations:

```text theme={"system"}
Enter the location of the SSL certificate (default: /etc/ssl/bundle.crt):
Enter the location of the SSL certificate key (default: /etc/ssl/cert.key):
```

The answers are stored in `.env` as `SSL_CERTIFICATE` and `SSL_CERTIFICATE_KEY`, and Compose bind-mounts each file into the nginx container at `/etc/ssl/bundle.crt` and `/etc/ssl/cert.key`.

Because these are bind mounts to host paths, the files stay under your control — Cymph never copies them into an image or a volume.

## Renewing or replacing a certificate

The mount points do not change, so renewal is a file replacement plus an nginx restart:

1. Write the new certificate and key to the same host paths already recorded in `.env`.

2. Restart nginx to pick them up:

```bash theme={"system"}
sudo docker compose restart nginx
```

Only the `nginx` service needs to restart — the application, API and database keep running, so there is no data-path downtime beyond the few seconds nginx takes to come back.

<Tip>
  If you renew with certbot, point its `--deploy-hook` at the restart command so renewal and reload happen together:

  ```bash theme={"system"}
  certbot renew --deploy-hook "docker compose -f /path/to/cymph/compose.yaml restart nginx"
  ```
</Tip>

To move to different paths instead of overwriting in place, edit `SSL_CERTIFICATE` and `SSL_CERTIFICATE_KEY` in `.env` and then recreate the container so the new bind mounts take effect:

```bash theme={"system"}
sudo docker compose up -d --force-recreate nginx
```

## Checking what is being served

Confirm the certificate nginx has loaded, substituting your own address and port:

```bash theme={"system"}
openssl s_client -connect your-cymph-host:443 -servername your-cymph-host </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates
```

If the connection fails or serves an unexpected certificate, check the nginx logs:

```bash theme={"system"}
sudo docker compose logs nginx
```

A missing or unreadable file at either mounted path stops nginx from starting — see [Common issues](/deployment/self-hosted/troubleshooting).
