Improve documentation for ACME/Let's Encrypt
This commit is contained in:
parent
c9dc0226fd
commit
eef3ca0295
8 changed files with 303 additions and 6 deletions
4
docs/content/https/.markdownlint.json
Normal file
4
docs/content/https/.markdownlint.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"extends": "../../.markdownlint.json",
|
||||||
|
"MD041": false
|
||||||
|
}
|
|
@ -8,6 +8,45 @@ You can configure Traefik to use an ACME provider (like Let's Encrypt) for autom
|
||||||
!!! warning "Let's Encrypt and Rate Limiting"
|
!!! warning "Let's Encrypt and Rate Limiting"
|
||||||
Note that Let's Encrypt API has [rate limiting](https://letsencrypt.org/docs/rate-limits).
|
Note that Let's Encrypt API has [rate limiting](https://letsencrypt.org/docs/rate-limits).
|
||||||
|
|
||||||
|
Use Let's Encrypt staging server with the [`caServer`](#caserver) configuration option
|
||||||
|
when experimenting to avoid hitting this limit too fast.
|
||||||
|
|
||||||
|
## Certificate Resolvers
|
||||||
|
|
||||||
|
Traefik requires you to define "Certificate Resolvers" in the [static configuration](../getting-started/configuration-overview.md#the-static-configuration),
|
||||||
|
which are responsible for retrieving certificates from an ACME server.
|
||||||
|
|
||||||
|
Then, each ["router"](../routing/routers/index.md) is configured to enable TLS,
|
||||||
|
and is associated to a certificate resolver through the [`tls.certresolver` configuration option](../routing/routers/index.md#certresolver).
|
||||||
|
|
||||||
|
Certificates are requested for domain names retrieved from the router's [dynamic configuration](../getting-started/configuration-overview.md#the-dynamic-configuration).
|
||||||
|
|
||||||
|
You can read more about this retrieval mechanism in the following section: [ACME Domain Definition](#domain-definition).
|
||||||
|
|
||||||
|
## Domain Definition
|
||||||
|
|
||||||
|
Certificate resolvers request certificates for a set of the domain names
|
||||||
|
inferred from routers, with the following logic:
|
||||||
|
|
||||||
|
- If the router has a [`tls.domains`](../routing/routers/index.md#domains) option set,
|
||||||
|
then the certificate resolver uses the `main` (and optionally `sans`) option of `tls.domains` to know the domain names for this router.
|
||||||
|
|
||||||
|
- If no [`tls.domains`](../routing/routers/index.md#domains) option is set,
|
||||||
|
then the certificate resolver uses the [router's rule](../routing/routers/index.md#rule),
|
||||||
|
by checking the `Host()` matchers.
|
||||||
|
Please note that [multiple `Host()` matchers can be used](../routing/routers/index.md#certresolver)) for specifying multiple domain names for this router.
|
||||||
|
|
||||||
|
Please note that:
|
||||||
|
|
||||||
|
- When multiple domain names are inferred from a given router,
|
||||||
|
only **one** certificate is requested with the first domain name as the main domain,
|
||||||
|
and the other domains as ["SANs" (Subject Alternative Name)](https://en.wikipedia.org/wiki/Subject_Alternative_Name).
|
||||||
|
|
||||||
|
- As [ACME V2 supports "wildcard domains"](#wildcard-domains),
|
||||||
|
any router can provide a [wildcard domain](https://en.wikipedia.org/wiki/Wildcard_certificate) name, as "main" domain or as "SAN" domain.
|
||||||
|
|
||||||
|
Please check the [configuration examples below](#configuration-examples) for more details.
|
||||||
|
|
||||||
## Configuration Examples
|
## Configuration Examples
|
||||||
|
|
||||||
??? example "Enabling ACME"
|
??? example "Enabling ACME"
|
||||||
|
@ -75,6 +114,26 @@ You can configure Traefik to use an ACME provider (like Let's Encrypt) for autom
|
||||||
--8<-- "content/https/ref-acme.txt"
|
--8<-- "content/https/ref-acme.txt"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
??? example "Single Domain from Router's Rule Example"
|
||||||
|
|
||||||
|
* A certificate for the domain `company.com` is requested:
|
||||||
|
|
||||||
|
--8<-- "content/https/include-acme-single-domain-example.md"
|
||||||
|
|
||||||
|
??? example "Multiple Domains from Router's Rule Example"
|
||||||
|
|
||||||
|
* A certificate for the domains `company.com` (main) and `blog.company.org`
|
||||||
|
is requested:
|
||||||
|
|
||||||
|
--8<-- "content/https/include-acme-multiple-domains-from-rule-example.md"
|
||||||
|
|
||||||
|
??? example "Multiple Domains from Router's `tls.domain` Example"
|
||||||
|
|
||||||
|
* A certificate for the domains `company.com` (main) and `*.company.org` (SAN)
|
||||||
|
is requested:
|
||||||
|
|
||||||
|
--8<-- "content/https/include-acme-multiple-domains-example.md"
|
||||||
|
|
||||||
## Automatic Renewals
|
## Automatic Renewals
|
||||||
|
|
||||||
Traefik automatically tracks the expiry date of ACME certificates it generates.
|
Traefik automatically tracks the expiry date of ACME certificates it generates.
|
||||||
|
@ -327,7 +386,9 @@ certificatesResolvers:
|
||||||
[ACME V2](https://community.letsencrypt.org/t/acme-v2-and-wildcard-certificate-support-is-live/55579) supports wildcard certificates.
|
[ACME V2](https://community.letsencrypt.org/t/acme-v2-and-wildcard-certificate-support-is-live/55579) supports wildcard certificates.
|
||||||
As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/staging-endpoint-for-acme-v2/49605) wildcard certificates can only be generated through a [`DNS-01` challenge](#dnschallenge).
|
As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/staging-endpoint-for-acme-v2/49605) wildcard certificates can only be generated through a [`DNS-01` challenge](#dnschallenge).
|
||||||
|
|
||||||
## `caServer`
|
## More Configuration
|
||||||
|
|
||||||
|
### `caServer`
|
||||||
|
|
||||||
??? example "Using the Let's Encrypt staging server"
|
??? example "Using the Let's Encrypt staging server"
|
||||||
|
|
||||||
|
@ -353,7 +414,7 @@ As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/stagi
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
## `storage`
|
### `storage`
|
||||||
|
|
||||||
The `storage` option sets the location where your ACME certificates are saved to.
|
The `storage` option sets the location where your ACME certificates are saved to.
|
||||||
|
|
||||||
|
@ -383,7 +444,7 @@ The value can refer to some kinds of storage:
|
||||||
|
|
||||||
- a JSON file
|
- a JSON file
|
||||||
|
|
||||||
### In a File
|
#### In a File
|
||||||
|
|
||||||
ACME certificates can be stored in a JSON file that needs to have a `600` file mode .
|
ACME certificates can be stored in a JSON file that needs to have a `600` file mode .
|
||||||
|
|
||||||
|
|
88
docs/content/https/include-acme-multiple-domains-example.md
Normal file
88
docs/content/https/include-acme-multiple-domains-example.md
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
|
||||||
|
```yaml tab="Docker"
|
||||||
|
## Dynamic configuration
|
||||||
|
labels:
|
||||||
|
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||||
|
- traefik.http.routers.blog.tls=true
|
||||||
|
- traefik.http.routers.blog.tls.certresolver=le
|
||||||
|
- traefik.http.routers.blog.tls.domains[0].main=company.org
|
||||||
|
- traefik.http.routers.blog.tls.domains[0].sans=*.company.org
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Docker (Swarm)"
|
||||||
|
## Dynamic configuration
|
||||||
|
deploy:
|
||||||
|
labels:
|
||||||
|
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||||
|
- traefik.http.services.blog-svc.loadbalancer.server.port=8080"
|
||||||
|
- traefik.http.routers.blog.tls=true
|
||||||
|
- traefik.http.routers.blog.tls.certresolver=le
|
||||||
|
- traefik.http.routers.blog.tls.domains[0].main=company.org
|
||||||
|
- traefik.http.routers.blog.tls.domains[0].sans=*.company.org
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Kubernetes"
|
||||||
|
---
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: blogtls
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
routes:
|
||||||
|
- match: Host(`company.com`) && Path(`/blog`)
|
||||||
|
kind: Rule
|
||||||
|
services:
|
||||||
|
- name: blog
|
||||||
|
port: 8080
|
||||||
|
tls:
|
||||||
|
certResolver: le
|
||||||
|
```
|
||||||
|
|
||||||
|
```json tab="Marathon"
|
||||||
|
labels: {
|
||||||
|
"traefik.http.routers.blog.rule": "Host(`company.com`) && Path(`/blog`)",
|
||||||
|
"traefik.http.routers.blog.tls": "true",
|
||||||
|
"traefik.http.routers.blog.tls.certresolver": "le",
|
||||||
|
"traefik.http.routers.blog.tls.domains[0].main": "company.com",
|
||||||
|
"traefik.http.routers.blog.tls.domains[0].sans": "*.company.com",
|
||||||
|
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Rancher"
|
||||||
|
## Dynamic configuration
|
||||||
|
labels:
|
||||||
|
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||||
|
- traefik.http.routers.blog.tls=true
|
||||||
|
- traefik.http.routers.blog.tls.certresolver=le
|
||||||
|
- traefik.http.routers.blog.tls.domains[0].main=company.org
|
||||||
|
- traefik.http.routers.blog.tls.domains[0].sans=*.company.org
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml tab="File (TOML)"
|
||||||
|
## Dynamic configuration
|
||||||
|
[http.routers]
|
||||||
|
[http.routers.blog]
|
||||||
|
rule = "Host(`company.com`) && Path(`/blog`)"
|
||||||
|
[http.routers.blog.tls]
|
||||||
|
certResolver = "le" # From static configuration
|
||||||
|
[[http.routers.blog.tls.domains]]
|
||||||
|
main = "company.org"
|
||||||
|
sans = ["*.company.org"]
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
## Dynamic configuration
|
||||||
|
http:
|
||||||
|
routers:
|
||||||
|
blog:
|
||||||
|
rule: "Host(`company.com`) && Path(`/blog`)"
|
||||||
|
tls:
|
||||||
|
certResolver: le
|
||||||
|
domains:
|
||||||
|
- main: "company.org"
|
||||||
|
sans:
|
||||||
|
- "*.company.org"
|
||||||
|
```
|
|
@ -0,0 +1,72 @@
|
||||||
|
|
||||||
|
```yaml tab="Docker"
|
||||||
|
## Dynamic configuration
|
||||||
|
labels:
|
||||||
|
- traefik.http.routers.blog.rule=(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)
|
||||||
|
- traefik.http.routers.blog.tls=true
|
||||||
|
- traefik.http.routers.blog.tls.certresolver=le
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Docker (Swarm)"
|
||||||
|
## Dynamic configuration
|
||||||
|
deploy:
|
||||||
|
labels:
|
||||||
|
- traefik.http.routers.blog.rule=(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)
|
||||||
|
- traefik.http.services.blog-svc.loadbalancer.server.port=8080"
|
||||||
|
- traefik.http.routers.blog.tls=true
|
||||||
|
- traefik.http.routers.blog.tls.certresolver=le
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Kubernetes"
|
||||||
|
---
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: blogtls
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
routes:
|
||||||
|
- match: (Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)
|
||||||
|
kind: Rule
|
||||||
|
services:
|
||||||
|
- name: blog
|
||||||
|
port: 8080
|
||||||
|
tls: {}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json tab="Marathon"
|
||||||
|
labels: {
|
||||||
|
"traefik.http.routers.blog.rule": "(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)",
|
||||||
|
"traefik.http.routers.blog.tls": "true",
|
||||||
|
"traefik.http.routers.blog.tls.certresolver": "le",
|
||||||
|
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Rancher"
|
||||||
|
## Dynamic configuration
|
||||||
|
labels:
|
||||||
|
- traefik.http.routers.blog.rule=(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)
|
||||||
|
- traefik.http.routers.blog.tls=true
|
||||||
|
- traefik.http.routers.blog.tls.certresolver=le
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml tab="File (TOML)"
|
||||||
|
## Dynamic configuration
|
||||||
|
[http.routers]
|
||||||
|
[http.routers.blog]
|
||||||
|
rule = "(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)"
|
||||||
|
[http.routers.blog.tls]
|
||||||
|
certResolver = "le" # From static configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
## Dynamic configuration
|
||||||
|
http:
|
||||||
|
routers:
|
||||||
|
blog:
|
||||||
|
rule: "(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)"
|
||||||
|
tls:
|
||||||
|
certResolver: le
|
||||||
|
```
|
72
docs/content/https/include-acme-single-domain-example.md
Normal file
72
docs/content/https/include-acme-single-domain-example.md
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
|
||||||
|
```yaml tab="Docker"
|
||||||
|
## Dynamic configuration
|
||||||
|
labels:
|
||||||
|
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||||
|
- traefik.http.routers.blog.tls=true
|
||||||
|
- traefik.http.routers.blog.tls.certresolver=le
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Docker (Swarm)"
|
||||||
|
## Dynamic configuration
|
||||||
|
deploy:
|
||||||
|
labels:
|
||||||
|
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||||
|
- traefik.http.services.blog-svc.loadbalancer.server.port=8080"
|
||||||
|
- traefik.http.routers.blog.tls=true
|
||||||
|
- traefik.http.routers.blog.tls.certresolver=le
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Kubernetes"
|
||||||
|
---
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: blogtls
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
routes:
|
||||||
|
- match: Host(`company.com`) && Path(`/blog`)
|
||||||
|
kind: Rule
|
||||||
|
services:
|
||||||
|
- name: blog
|
||||||
|
port: 8080
|
||||||
|
tls: {}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json tab="Marathon"
|
||||||
|
labels: {
|
||||||
|
"traefik.http.routers.blog.rule": "Host(`company.com`) && Path(`/blog`)",
|
||||||
|
"traefik.http.routers.blog.tls": "true",
|
||||||
|
"traefik.http.routers.blog.tls.certresolver": "le",
|
||||||
|
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Rancher"
|
||||||
|
## Dynamic configuration
|
||||||
|
labels:
|
||||||
|
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||||
|
- traefik.http.routers.blog.tls=true
|
||||||
|
- traefik.http.routers.blog.tls.certresolver=le
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml tab="Single Domain"
|
||||||
|
## Dynamic configuration
|
||||||
|
[http.routers]
|
||||||
|
[http.routers.blog]
|
||||||
|
rule = "Host(`company.com`) && Path(`/blog`)"
|
||||||
|
[http.routers.blog.tls]
|
||||||
|
certResolver = "le" # From static configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
## Dynamic configuration
|
||||||
|
http:
|
||||||
|
routers:
|
||||||
|
blog:
|
||||||
|
rule: "Host(`company.com`) && Path(`/blog`)"
|
||||||
|
tls:
|
||||||
|
certResolver: le
|
||||||
|
```
|
|
@ -20,4 +20,4 @@ Developing Traefik, our main goal is to make it simple to use, and we're sure yo
|
||||||
|
|
||||||
!!! info
|
!!! info
|
||||||
|
|
||||||
If you're a business running critical services behind Traefik, know that [Containous](https://containo.us), the company that sponsors Traefik's development, can provide [commercial support](https://containo.us/services/#commercial-support) and develops an [Enterprise Edition](https://containo.us/traefikee/) of Traefik.
|
If you're a business running critical services behind Traefik, know that [Containous](https://containo.us), the company that sponsors Traefik's development, can provide [commercial support](https://info.containo.us/commercial-services) and develops an [Enterprise Edition](https://containo.us/traefikee/) of Traefik.
|
||||||
|
|
|
@ -91,7 +91,7 @@ For example, to change the routing rule, you could add the label ```"traefik.htt
|
||||||
See [tls](../routers/index.md#tls) for more information.
|
See [tls](../routers/index.md#tls) for more information.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"traefik.http.routers.myrouter>.tls": "true"
|
"traefik.http.routers.myrouter.tls": "true"
|
||||||
```
|
```
|
||||||
|
|
||||||
??? info "`traefik.http.routers.<router_name>.tls.certresolver`"
|
??? info "`traefik.http.routers.<router_name>.tls.certresolver`"
|
||||||
|
|
|
@ -44,7 +44,7 @@ plugins:
|
||||||
- search
|
- search
|
||||||
- exclude:
|
- exclude:
|
||||||
glob:
|
glob:
|
||||||
- include-*.md
|
- "**/include-*.md"
|
||||||
|
|
||||||
# https://squidfunk.github.io/mkdocs-material/extensions/admonition/
|
# https://squidfunk.github.io/mkdocs-material/extensions/admonition/
|
||||||
# https://facelessuser.github.io/pymdown-extensions/
|
# https://facelessuser.github.io/pymdown-extensions/
|
||||||
|
|
Loading…
Reference in a new issue