# Bus TLS — self-signed CA and server certificate

The unibus data plane (NATS) is encrypted with TLS using the project's own
self-signed CA. The bus is exposed publicly, protected by auth + TLS, so the CA
is private (not Let's Encrypt) and every client we control embeds the public
`ca.crt`; the server presents `server.crt`/`server.key`.

## Files

| File | Secret? | Goes where |
|---|---|---|
| `ca.crt` | no (public) | versioned in git; embedded/distributed to every client |
| `ca.key` | **yes** | stays on the machine that mints certs; gitignored |
| `server.crt` | no | deployed to the bus host; gitignored (deploy-specific SANs) |
| `server.key` | **yes** | deployed to the bus host over a secure channel; gitignored |

Only `ca.crt` is committed. `ca.key`, `server.key`, `server.crt`, and any
`*.csr`/`*.srl` are gitignored — see `.gitignore`.

## Generate

```bash
cd deploy/tls
./generate-certs.sh                 # CA (if missing) + server cert with default SANs
./generate-certs.sh --force         # also regenerate the CA (invalidates pinned clients)
```

The server certificate's SANs cover the public IP, the WireGuard IP, the om
hostname, plus `localhost`/`127.0.0.1` for on-host smoke tests. Override the
defaults via environment variables:

```bash
UNIBUS_PUBLIC_IP=135.125.201.30 UNIBUS_WG_IP=10.42.0.1 UNIBUS_HOSTNAME=om ./generate-certs.sh
```

Verify the SANs:

```bash
openssl x509 -in server.crt -noout -text | grep -A1 'Subject Alternative Name'
```

## Use

- **Server** (`membershipd`, phase 0001e): point it at `server.crt`/`server.key`
  so the embedded NATS presents the certificate and requires TLS. Built with
  `busauth.ServerTLSConfig(certPath, keyPath)`.
- **Clients** (Go peers, mobile binding, gateway): pin `ca.crt` with
  `busauth.LoadCATLSConfig(caPath)` and pass the result as `client.Options.TLS`.

## Rotation

The CA is long-lived (10 years). Rotate the server certificate (825 days) by
re-running `generate-certs.sh` (without `--force`) and redeploying
`server.crt`/`server.key`; clients are unaffected because they pin the CA, not
the server cert. Rotating the CA (`--force`) requires redistributing `ca.crt` to
every client.
