---
url: /guide/domains.md
description: >-
  Route hosts and paths to services, automatic Let's Encrypt certificates,
  domain ownership and gRPC.
---

# Domains and TLS

```toml
[services.web]
port = 8080
domains = [
  { host = "shop.example.com" },
  { host = "example.com", path = "/shop", strip_prefix = true },
]
```

| Key | Default | Meaning |
|---|---|---|
| `host` | — | Hostname, lowercased |
| `path` | `/` | Path prefix routed to this service |
| `strip_prefix` | `false` | Remove `path` before forwarding |
| `port` | the service `port` | Send this domain to another container port |
| `protocol` | `http1` | `h2c` for plaintext HTTP/2 to the backend (gRPC) |

Only `web` services take domains. The same host and path twice in one org is
an error.

## DNS and certificates

Point the host at Duploy; `duploy project ingress` prints the address or
CNAME target to use. Once DNS resolves, Duploy issues a Let's Encrypt
certificate and redirects HTTP to HTTPS. Follow it with:

```bash
duploy domains
duploy until domain.tls.issued --host shop.example.com
```

## Ownership

A host belongs to the org that claimed it first. Claiming a host another org
already holds does not fail: it stays `pending`, gets no route and no
certificate, until you prove ownership with a TXT record:

```
_duploy.shop.example.com  TXT  "duploy-verify=<your org token>"
```

Duploy checks public resolvers on its own; `duploy domain verify
shop.example.com` checks right away. The token is shown in the panel.

## Two ports, one container

Some images serve two things on two ports, such as an S3 API and its console:

```toml
[services.storage]
source = { image = "rustfs/rustfs:1.0.1" }
port = 9000
domains = [
  { host = "files.example.com" },
  { host = "console.example.com", port = 9001 },
]
```

Health checks still use the service `port`.

## gRPC

Clients reach the edge over TLS and negotiate HTTP/2. Behind the edge, gRPC
needs HTTP/2 end to end because trailers do not survive an HTTP/1.1 hop:

```toml
domains = [{ host = "otel.example.com", port = 4317, protocol = "h2c" }]
```
