# HTTPS (/docs/guides/https)



`[proxy.http]` in `config.toml` is the host's one HTTP listener. It routes each request by the
hostname it carries to the `httpPort` of the app that names that hostname:

```json
"hostnames": [{ "hostname": "app-1.example.com", "kind": "platform" }]
```

`kind` is `platform` or `custom`: a label for whatever writes the document, routed the same.
An app nothing outside needs to reach by name has an empty `hostnames`.

A request for a sleeping app wakes it. A document that names a hostname on a host with no
`[proxy.http]` is refused by name, and the instance is reported `failed` saying so.
[The reference](/docs/reference/config) is every key under `[proxy]`.

## Behind an edge [#behind-an-edge]

The installer writes plain HTTP, which is what a host behind an edge that terminates TLS —
Cloudflare, a load balancer, a reverse proxy of your own — wants:

```toml
[proxy.http]
listen_address = "0.0.0.0"
port = 80
```

## TLS on this host [#tls-on-this-host]

Add `[proxy.http.tls]` with a certificate and key, both PEM:

```toml
[proxy.http]
listen_address = "0.0.0.0"
port = 443

[proxy.http.tls]
certificate = "/etc/nibrunner/tls/origin.crt"
key = "/etc/nibrunner/tls/origin.key"
```

* **One certificate covers the whole host.** There is no SNI selection, so every hostname an
  app holds must be covered by it — a wildcard, in practice, which matches one label deep:
  `app.example.com` but not `a.b.example.com`.
* **The daemon does not obtain certificates.** ACME and renewal belong to certbot or to the
  edge. The files are read once, at startup, so a renewed certificate needs
  `systemctl restart nibrunnerd` — which stops no app.
* **There is one listener, not a plain one and a TLS one.** Nothing redirects, so two would
  serve every app both ways forever.

## Only through the edge [#only-through-the-edge]

Add `[proxy.http.tls.client_ca]` to require a client certificate on every handshake. On an
origin whose IP is discoverable, this is what keeps it reachable only through the edge:

```toml
[proxy.http.tls.client_ca]
certificate = "/etc/nibrunner/tls/origin-pull-ca.pem"
```

`certificate` is a PEM holding every certificate the pool trusts. You cannot reach the host
yourself without one, so turn this on after the plain path is proven.

<Callout title="Good to know">
  A connection whose handshake named one app and whose request names another gets a `421`. That
  is what keeps two apps that share a certificate apart.
</Callout>
