Merge 'v2.1' into master
This commit is contained in:
commit
e9d0a16a3b
67 changed files with 827 additions and 329 deletions
34
CHANGELOG.md
34
CHANGELOG.md
|
@ -1,3 +1,37 @@
|
||||||
|
## [v2.1.6](https://github.com/containous/traefik/tree/v2.1.6) (2020-02-28)
|
||||||
|
[All Commits](https://github.com/containous/traefik/compare/v2.1.4...v2.1.6)
|
||||||
|
|
||||||
|
**Bug fixes:**
|
||||||
|
- **[acme]** Update go-acme/lego to v3.4.0 ([#6376](https://github.com/containous/traefik/pull/6376) by [ldez](https://github.com/ldez))
|
||||||
|
- **[api]** Return an error when ping is not enabled. ([#6304](https://github.com/containous/traefik/pull/6304) by [ldez](https://github.com/ldez))
|
||||||
|
- **[consulcatalog]** Early filter of the catalog services. ([#6307](https://github.com/containous/traefik/pull/6307) by [ldez](https://github.com/ldez))
|
||||||
|
- **[consulcatalog]** fix: consul-catalog uses port from label instead of item port. ([#6345](https://github.com/containous/traefik/pull/6345) by [ldez](https://github.com/ldez))
|
||||||
|
- **[file]** fix: YML example of template for the file provider. ([#6402](https://github.com/containous/traefik/pull/6402) by [ldez](https://github.com/ldez))
|
||||||
|
- **[file]** Allow fsnotify to reload config files on k8s (or symlinks) ([#5037](https://github.com/containous/traefik/pull/5037) by [dtomcej](https://github.com/dtomcej))
|
||||||
|
- **[healthcheck]** Launch healthcheck only one time instead of two ([#6372](https://github.com/containous/traefik/pull/6372) by [juliens](https://github.com/juliens))
|
||||||
|
- **[k8s,k8s/crd,k8s/ingress]** Fix secret informer load ([#6364](https://github.com/containous/traefik/pull/6364) by [mmatur](https://github.com/mmatur))
|
||||||
|
- **[k8s,k8s/crd]** Use consistent protocol determination ([#6365](https://github.com/containous/traefik/pull/6365) by [dtomcej](https://github.com/dtomcej))
|
||||||
|
- **[k8s,k8s/crd]** fix: use the right error in the log ([#6311](https://github.com/containous/traefik/pull/6311) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||||
|
- **[provider]** Don't throw away valid configuration updates ([#5952](https://github.com/containous/traefik/pull/5952) by [zaphod42](https://github.com/zaphod42))
|
||||||
|
- **[tls]** Consider SSLv2 as TLS in order to close the handshake correctly ([#6371](https://github.com/containous/traefik/pull/6371) by [juliens](https://github.com/juliens))
|
||||||
|
- **[tracing]** Fix docs and code to match in haystack tracing. ([#6352](https://github.com/containous/traefik/pull/6352) by [evanlurvey](https://github.com/evanlurvey))
|
||||||
|
|
||||||
|
**Documentation:**
|
||||||
|
- **[acme]** Improve documentation. ([#6324](https://github.com/containous/traefik/pull/6324) by [ldez](https://github.com/ldez))
|
||||||
|
- **[file]** Add information about filename and directory options. ([#6333](https://github.com/containous/traefik/pull/6333) by [ldez](https://github.com/ldez))
|
||||||
|
- **[k8s,k8s/ingress]** Docs: Clarifying format of ingress endpoint service name ([#6306](https://github.com/containous/traefik/pull/6306) by [BretFisher](https://github.com/BretFisher))
|
||||||
|
- **[k8s/crd]** fix: dashboard example with k8s CRD. ([#6330](https://github.com/containous/traefik/pull/6330) by [ldez](https://github.com/ldez))
|
||||||
|
- **[middleware,k8s]** Fix formatting in "Kubernetes Namespace" block ([#6305](https://github.com/containous/traefik/pull/6305) by [berekuk](https://github.com/berekuk))
|
||||||
|
- **[tls]** Remove TLS cipher suites for TLS minVersion 1.3 ([#6328](https://github.com/containous/traefik/pull/6328) by [rYR79435](https://github.com/rYR79435))
|
||||||
|
- **[tls]** Fix typo in the godoc of TLS option MaxVersion ([#6347](https://github.com/containous/traefik/pull/6347) by [pschaub](https://github.com/pschaub))
|
||||||
|
- Use explicitly the word Kubernetes in the migration guide. ([#6380](https://github.com/containous/traefik/pull/6380) by [ldez](https://github.com/ldez))
|
||||||
|
- Minor readme improvements ([#6293](https://github.com/containous/traefik/pull/6293) by [Rowayda-Khayri](https://github.com/Rowayda-Khayri))
|
||||||
|
- Added link to community forum ([#6283](https://github.com/containous/traefik/pull/6283) by [isaacnewtonfx](https://github.com/isaacnewtonfx))
|
||||||
|
|
||||||
|
## [v2.1.5](https://github.com/containous/traefik/tree/v2.1.5) (2020-02-28)
|
||||||
|
|
||||||
|
Skipped.
|
||||||
|
|
||||||
## [v2.1.4](https://github.com/containous/traefik/tree/v2.1.4) (2020-02-06)
|
## [v2.1.4](https://github.com/containous/traefik/tree/v2.1.4) (2020-02-06)
|
||||||
[All Commits](https://github.com/containous/traefik/compare/v2.1.3...v2.1.4)
|
[All Commits](https://github.com/containous/traefik/compare/v2.1.3...v2.1.4)
|
||||||
|
|
||||||
|
|
|
@ -414,13 +414,13 @@ func stats(staticConfiguration *static.Configuration) {
|
||||||
logger.Info(`Stats collection is enabled.`)
|
logger.Info(`Stats collection is enabled.`)
|
||||||
logger.Info(`Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.`)
|
logger.Info(`Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.`)
|
||||||
logger.Info(`Help us improve Traefik by leaving this feature on :)`)
|
logger.Info(`Help us improve Traefik by leaving this feature on :)`)
|
||||||
logger.Info(`More details on: https://docs.traefik.io/v2.0/contributing/data-collection/`)
|
logger.Info(`More details on: https://docs.traefik.io/contributing/data-collection/`)
|
||||||
collect(staticConfiguration)
|
collect(staticConfiguration)
|
||||||
} else {
|
} else {
|
||||||
logger.Info(`
|
logger.Info(`
|
||||||
Stats collection is disabled.
|
Stats collection is disabled.
|
||||||
Help us improve Traefik by turning this feature on :)
|
Help us improve Traefik by turning this feature on :)
|
||||||
More details on: https://docs.traefik.io/v2.0/contributing/data-collection/
|
More details on: https://docs.traefik.io/contributing/data-collection/
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ traefik --help
|
||||||
# or
|
# or
|
||||||
|
|
||||||
docker run traefik[:version] --help
|
docker run traefik[:version] --help
|
||||||
# ex: docker run traefik:2.0 --help
|
# ex: docker run traefik:2.1 --help
|
||||||
```
|
```
|
||||||
|
|
||||||
All available arguments can also be found [here](../reference/static-configuration/cli.md).
|
All available arguments can also be found [here](../reference/static-configuration/cli.md).
|
||||||
|
|
|
@ -9,11 +9,11 @@ You can install Traefik with the following flavors:
|
||||||
|
|
||||||
## Use the Official Docker Image
|
## Use the Official Docker Image
|
||||||
|
|
||||||
Choose one of the [official Docker images](https://hub.docker.com/_/traefik) and run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/v2.0/traefik.sample.toml):
|
Choose one of the [official Docker images](https://hub.docker.com/_/traefik) and run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/v2.1/traefik.sample.toml):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d -p 8080:8080 -p 80:80 \
|
docker run -d -p 8080:8080 -p 80:80 \
|
||||||
-v $PWD/traefik.toml:/etc/traefik/traefik.toml traefik:v2.0
|
-v $PWD/traefik.toml:/etc/traefik/traefik.toml traefik:v2.1
|
||||||
```
|
```
|
||||||
|
|
||||||
For more details, go to the [Docker provider documentation](../providers/docker.md)
|
For more details, go to the [Docker provider documentation](../providers/docker.md)
|
||||||
|
@ -21,7 +21,7 @@ For more details, go to the [Docker provider documentation](../providers/docker.
|
||||||
!!! tip
|
!!! tip
|
||||||
|
|
||||||
* Prefer a fixed version than the latest that could be an unexpected version.
|
* Prefer a fixed version than the latest that could be an unexpected version.
|
||||||
ex: `traefik:v2.0.0`
|
ex: `traefik:v2.1.4`
|
||||||
* Docker images are based from the [Alpine Linux Official image](https://hub.docker.com/_/alpine).
|
* Docker images are based from the [Alpine Linux Official image](https://hub.docker.com/_/alpine).
|
||||||
* Any orchestrator using docker images can fetch the official Traefik docker image.
|
* Any orchestrator using docker images can fetch the official Traefik docker image.
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ version: '3'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
reverse-proxy:
|
reverse-proxy:
|
||||||
# The official v2.0 Traefik docker image
|
# The official v2 Traefik docker image
|
||||||
image: traefik:v2.0
|
image: traefik:v2.1
|
||||||
# Enables the web UI and tells Traefik to listen to docker
|
# Enables the web UI and tells Traefik to listen to docker
|
||||||
command: --api.insecure=true --providers.docker
|
command: --api.insecure=true --providers.docker
|
||||||
ports:
|
ports:
|
||||||
|
|
|
@ -23,6 +23,25 @@ Certificates are requested for domain names retrieved from the router's [dynamic
|
||||||
|
|
||||||
You can read more about this retrieval mechanism in the following section: [ACME Domain Definition](#domain-definition).
|
You can read more about this retrieval mechanism in the following section: [ACME Domain Definition](#domain-definition).
|
||||||
|
|
||||||
|
!!! important "Defining a certificates resolver does not result in all routers automatically using it. Each router that is supposed to use the resolver must [reference](../routing/routers/index.md#certresolver) it."
|
||||||
|
|
||||||
|
??? note "Configuration Reference"
|
||||||
|
|
||||||
|
There are many available options for ACME.
|
||||||
|
For a quick glance at what's possible, browse the configuration reference:
|
||||||
|
|
||||||
|
```toml tab="File (TOML)"
|
||||||
|
--8<-- "content/https/ref-acme.toml"
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
--8<-- "content/https/ref-acme.yaml"
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="CLI"
|
||||||
|
--8<-- "content/https/ref-acme.txt"
|
||||||
|
```
|
||||||
|
|
||||||
## Domain Definition
|
## Domain Definition
|
||||||
|
|
||||||
Certificate resolvers request certificates for a set of the domain names
|
Certificate resolvers request certificates for a set of the domain names
|
||||||
|
@ -59,10 +78,10 @@ Please check the [configuration examples below](#configuration-examples) for mor
|
||||||
[entryPoints.websecure]
|
[entryPoints.websecure]
|
||||||
address = ":443"
|
address = ":443"
|
||||||
|
|
||||||
[certificatesResolvers.le.acme]
|
[certificatesResolvers.myresolver.acme]
|
||||||
email = "your-email@your-domain.org"
|
email = "your-email@your-domain.org"
|
||||||
storage = "acme.json"
|
storage = "acme.json"
|
||||||
[certificatesResolvers.le.acme.httpChallenge]
|
[certificatesResolvers.myresolver.acme.httpChallenge]
|
||||||
# used during the challenge
|
# used during the challenge
|
||||||
entryPoint = "web"
|
entryPoint = "web"
|
||||||
```
|
```
|
||||||
|
@ -76,7 +95,7 @@ Please check the [configuration examples below](#configuration-examples) for mor
|
||||||
address: ":443"
|
address: ":443"
|
||||||
|
|
||||||
certificatesResolvers:
|
certificatesResolvers:
|
||||||
sample:
|
myresolver:
|
||||||
acme:
|
acme:
|
||||||
email: your-email@your-domain.org
|
email: your-email@your-domain.org
|
||||||
storage: acme.json
|
storage: acme.json
|
||||||
|
@ -89,31 +108,14 @@ Please check the [configuration examples below](#configuration-examples) for mor
|
||||||
--entryPoints.web.address=:80
|
--entryPoints.web.address=:80
|
||||||
--entryPoints.websecure.address=:443
|
--entryPoints.websecure.address=:443
|
||||||
# ...
|
# ...
|
||||||
--certificatesResolvers.le.acme.email=your-email@your-domain.org
|
--certificatesResolvers.myresolver.acme.email=your-email@your-domain.org
|
||||||
--certificatesResolvers.le.acme.storage=acme.json
|
--certificatesResolvers.myresolver.acme.storage=acme.json
|
||||||
# used during the challenge
|
# used during the challenge
|
||||||
--certificatesResolvers.le.acme.httpChallenge.entryPoint=web
|
--certificatesResolvers.myresolver.acme.httpChallenge.entryPoint=web
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! important "Defining a certificates resolver does not result in all routers automatically using it. Each router that is supposed to use the resolver must [reference](../routing/routers/index.md#certresolver) it."
|
!!! important "Defining a certificates resolver does not result in all routers automatically using it. Each router that is supposed to use the resolver must [reference](../routing/routers/index.md#certresolver) it."
|
||||||
|
|
||||||
??? note "Configuration Reference"
|
|
||||||
|
|
||||||
There are many available options for ACME.
|
|
||||||
For a quick glance at what's possible, browse the configuration reference:
|
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
|
||||||
--8<-- "content/https/ref-acme.toml"
|
|
||||||
```
|
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
|
||||||
--8<-- "content/https/ref-acme.yaml"
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash tab="CLI"
|
|
||||||
--8<-- "content/https/ref-acme.txt"
|
|
||||||
```
|
|
||||||
|
|
||||||
??? example "Single Domain from Router's Rule Example"
|
??? example "Single Domain from Router's Rule Example"
|
||||||
|
|
||||||
* A certificate for the domain `company.com` is requested:
|
* A certificate for the domain `company.com` is requested:
|
||||||
|
@ -164,14 +166,14 @@ when using the `TLS-ALPN-01` challenge, Traefik must be reachable by Let's Encry
|
||||||
??? example "Configuring the `tlsChallenge`"
|
??? example "Configuring the `tlsChallenge`"
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[certificatesResolvers.le.acme]
|
[certificatesResolvers.myresolver.acme]
|
||||||
# ...
|
# ...
|
||||||
[certificatesResolvers.le.acme.tlsChallenge]
|
[certificatesResolvers.myresolver.acme.tlsChallenge]
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
certificatesResolvers:
|
certificatesResolvers:
|
||||||
sample:
|
myresolver:
|
||||||
acme:
|
acme:
|
||||||
# ...
|
# ...
|
||||||
tlsChallenge: {}
|
tlsChallenge: {}
|
||||||
|
@ -179,7 +181,7 @@ when using the `TLS-ALPN-01` challenge, Traefik must be reachable by Let's Encry
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
# ...
|
# ...
|
||||||
--certificatesResolvers.le.acme.tlsChallenge=true
|
--certificatesResolvers.myresolver.acme.tlsChallenge=true
|
||||||
```
|
```
|
||||||
|
|
||||||
### `httpChallenge`
|
### `httpChallenge`
|
||||||
|
@ -187,7 +189,7 @@ when using the `TLS-ALPN-01` challenge, Traefik must be reachable by Let's Encry
|
||||||
Use the `HTTP-01` challenge to generate and renew ACME certificates by provisioning an HTTP resource under a well-known URI.
|
Use the `HTTP-01` challenge to generate and renew ACME certificates by provisioning an HTTP resource under a well-known URI.
|
||||||
|
|
||||||
As described on the Let's Encrypt [community forum](https://community.letsencrypt.org/t/support-for-ports-other-than-80-and-443/3419/72),
|
As described on the Let's Encrypt [community forum](https://community.letsencrypt.org/t/support-for-ports-other-than-80-and-443/3419/72),
|
||||||
when using the `HTTP-01` challenge, `certificatesResolvers.le.acme.httpChallenge.entryPoint` must be reachable by Let's Encrypt through port 80.
|
when using the `HTTP-01` challenge, `certificatesResolvers.myresolver.acme.httpChallenge.entryPoint` must be reachable by Let's Encrypt through port 80.
|
||||||
|
|
||||||
??? example "Using an EntryPoint Called http for the `httpChallenge`"
|
??? example "Using an EntryPoint Called http for the `httpChallenge`"
|
||||||
|
|
||||||
|
@ -199,9 +201,9 @@ when using the `HTTP-01` challenge, `certificatesResolvers.le.acme.httpChallenge
|
||||||
[entryPoints.websecure]
|
[entryPoints.websecure]
|
||||||
address = ":443"
|
address = ":443"
|
||||||
|
|
||||||
[certificatesResolvers.le.acme]
|
[certificatesResolvers.myresolver.acme]
|
||||||
# ...
|
# ...
|
||||||
[certificatesResolvers.le.acme.httpChallenge]
|
[certificatesResolvers.myresolver.acme.httpChallenge]
|
||||||
entryPoint = "web"
|
entryPoint = "web"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -214,7 +216,7 @@ when using the `HTTP-01` challenge, `certificatesResolvers.le.acme.httpChallenge
|
||||||
address: ":443"
|
address: ":443"
|
||||||
|
|
||||||
certificatesResolvers:
|
certificatesResolvers:
|
||||||
sample:
|
myresolver:
|
||||||
acme:
|
acme:
|
||||||
# ...
|
# ...
|
||||||
httpChallenge:
|
httpChallenge:
|
||||||
|
@ -225,7 +227,7 @@ when using the `HTTP-01` challenge, `certificatesResolvers.le.acme.httpChallenge
|
||||||
--entryPoints.web.address=:80
|
--entryPoints.web.address=:80
|
||||||
--entryPoints.websecure.address=:443
|
--entryPoints.websecure.address=:443
|
||||||
# ...
|
# ...
|
||||||
--certificatesResolvers.le.acme.httpChallenge.entryPoint=web
|
--certificatesResolvers.myresolver.acme.httpChallenge.entryPoint=web
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! info ""
|
!!! info ""
|
||||||
|
@ -238,9 +240,9 @@ Use the `DNS-01` challenge to generate and renew ACME certificates by provisioni
|
||||||
??? example "Configuring a `dnsChallenge` with the DigitalOcean Provider"
|
??? example "Configuring a `dnsChallenge` with the DigitalOcean Provider"
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[certificatesResolvers.le.acme]
|
[certificatesResolvers.myresolver.acme]
|
||||||
# ...
|
# ...
|
||||||
[certificatesResolvers.le.acme.dnsChallenge]
|
[certificatesResolvers.myresolver.acme.dnsChallenge]
|
||||||
provider = "digitalocean"
|
provider = "digitalocean"
|
||||||
delayBeforeCheck = 0
|
delayBeforeCheck = 0
|
||||||
# ...
|
# ...
|
||||||
|
@ -248,7 +250,7 @@ Use the `DNS-01` challenge to generate and renew ACME certificates by provisioni
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
certificatesResolvers:
|
certificatesResolvers:
|
||||||
sample:
|
myresolver:
|
||||||
acme:
|
acme:
|
||||||
# ...
|
# ...
|
||||||
dnsChallenge:
|
dnsChallenge:
|
||||||
|
@ -259,8 +261,8 @@ Use the `DNS-01` challenge to generate and renew ACME certificates by provisioni
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
# ...
|
# ...
|
||||||
--certificatesResolvers.le.acme.dnsChallenge.provider=digitalocean
|
--certificatesResolvers.myresolver.acme.dnsChallenge.provider=digitalocean
|
||||||
--certificatesResolvers.le.acme.dnsChallenge.delayBeforeCheck=0
|
--certificatesResolvers.myresolver.acme.dnsChallenge.delayBeforeCheck=0
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -290,6 +292,7 @@ For example, `CF_API_EMAIL_FILE=/run/secrets/traefik_cf-api-email` could be used
|
||||||
| [Cloudflare](https://www.cloudflare.com) | `cloudflare` | `CF_API_EMAIL`, `CF_API_KEY` [^5] or `CF_DNS_API_TOKEN`, `[CF_ZONE_API_TOKEN]` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudflare) |
|
| [Cloudflare](https://www.cloudflare.com) | `cloudflare` | `CF_API_EMAIL`, `CF_API_KEY` [^5] or `CF_DNS_API_TOKEN`, `[CF_ZONE_API_TOKEN]` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudflare) |
|
||||||
| [CloudXNS](https://www.cloudxns.net) | `cloudxns` | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudxns) |
|
| [CloudXNS](https://www.cloudxns.net) | `cloudxns` | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudxns) |
|
||||||
| [ConoHa](https://www.conoha.jp) | `conoha` | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/conoha) |
|
| [ConoHa](https://www.conoha.jp) | `conoha` | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/conoha) |
|
||||||
|
| [Constellix](https://constellix.com) | `constellix` | `CONSTELLIX_API_KEY`, `CONSTELLIX_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/constellix) |
|
||||||
| [DigitalOcean](https://www.digitalocean.com) | `digitalocean` | `DO_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/digitalocean) |
|
| [DigitalOcean](https://www.digitalocean.com) | `digitalocean` | `DO_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/digitalocean) |
|
||||||
| [DNSimple](https://dnsimple.com) | `dnsimple` | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/dnsimple) |
|
| [DNSimple](https://dnsimple.com) | `dnsimple` | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/dnsimple) |
|
||||||
| [DNS Made Easy](https://dnsmadeeasy.com) | `dnsmadeeasy` | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX` | [Additional configuration](https://go-acme.github.io/lego/dns/dnsmadeeasy) |
|
| [DNS Made Easy](https://dnsmadeeasy.com) | `dnsmadeeasy` | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX` | [Additional configuration](https://go-acme.github.io/lego/dns/dnsmadeeasy) |
|
||||||
|
@ -333,7 +336,9 @@ For example, `CF_API_EMAIL_FILE=/run/secrets/traefik_cf-api-email` could be used
|
||||||
| [RFC2136](https://tools.ietf.org/html/rfc2136) | `rfc2136` | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER` | [Additional configuration](https://go-acme.github.io/lego/dns/rfc2136) |
|
| [RFC2136](https://tools.ietf.org/html/rfc2136) | `rfc2136` | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER` | [Additional configuration](https://go-acme.github.io/lego/dns/rfc2136) |
|
||||||
| [Route 53](https://aws.amazon.com/route53/) | `route53` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile. | [Additional configuration](https://go-acme.github.io/lego/dns/route53) |
|
| [Route 53](https://aws.amazon.com/route53/) | `route53` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile. | [Additional configuration](https://go-acme.github.io/lego/dns/route53) |
|
||||||
| [Sakura Cloud](https://cloud.sakura.ad.jp/) | `sakuracloud` | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/sakuracloud) |
|
| [Sakura Cloud](https://cloud.sakura.ad.jp/) | `sakuracloud` | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/sakuracloud) |
|
||||||
|
| [Scaleway](https://www.scaleway.com) | `scaleway` | `SCALEWAY_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/scaleway) |
|
||||||
| [Selectel](https://selectel.ru/en/) | `selectel` | `SELECTEL_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/selectel) |
|
| [Selectel](https://selectel.ru/en/) | `selectel` | `SELECTEL_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/selectel) |
|
||||||
|
| [Servercow](https://servercow.de) | `servercow` | `SERVERCOW_USERNAME`, `SERVERCOW_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/servercow) |
|
||||||
| [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath) |
|
| [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath) |
|
||||||
| [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/transip) |
|
| [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/transip) |
|
||||||
| [VegaDNS](https://github.com/shupp/VegaDNS-API) | `vegadns` | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/vegadns) |
|
| [VegaDNS](https://github.com/shupp/VegaDNS-API) | `vegadns` | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/vegadns) |
|
||||||
|
@ -358,16 +363,16 @@ For example, `CF_API_EMAIL_FILE=/run/secrets/traefik_cf-api-email` could be used
|
||||||
Use custom DNS servers to resolve the FQDN authority.
|
Use custom DNS servers to resolve the FQDN authority.
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[certificatesResolvers.le.acme]
|
[certificatesResolvers.myresolver.acme]
|
||||||
# ...
|
# ...
|
||||||
[certificatesResolvers.le.acme.dnsChallenge]
|
[certificatesResolvers.myresolver.acme.dnsChallenge]
|
||||||
# ...
|
# ...
|
||||||
resolvers = ["1.1.1.1:53", "8.8.8.8:53"]
|
resolvers = ["1.1.1.1:53", "8.8.8.8:53"]
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
certificatesResolvers:
|
certificatesResolvers:
|
||||||
sample:
|
myresolver:
|
||||||
acme:
|
acme:
|
||||||
# ...
|
# ...
|
||||||
dnsChallenge:
|
dnsChallenge:
|
||||||
|
@ -379,7 +384,7 @@ certificatesResolvers:
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
# ...
|
# ...
|
||||||
--certificatesResolvers.le.acme.dnsChallenge.resolvers=1.1.1.1:53,8.8.8.8:53
|
--certificatesResolvers.myresolver.acme.dnsChallenge.resolvers=1.1.1.1:53,8.8.8.8:53
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Wildcard Domains
|
#### Wildcard Domains
|
||||||
|
@ -394,7 +399,7 @@ As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/stagi
|
||||||
??? example "Using the Let's Encrypt staging server"
|
??? example "Using the Let's Encrypt staging server"
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[certificatesResolvers.le.acme]
|
[certificatesResolvers.myresolver.acme]
|
||||||
# ...
|
# ...
|
||||||
caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"
|
caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
# ...
|
# ...
|
||||||
|
@ -402,7 +407,7 @@ As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/stagi
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
certificatesResolvers:
|
certificatesResolvers:
|
||||||
sample:
|
myresolver:
|
||||||
acme:
|
acme:
|
||||||
# ...
|
# ...
|
||||||
caServer: https://acme-staging-v02.api.letsencrypt.org/directory
|
caServer: https://acme-staging-v02.api.letsencrypt.org/directory
|
||||||
|
@ -411,7 +416,7 @@ As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/stagi
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
# ...
|
# ...
|
||||||
--certificatesResolvers.le.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory
|
--certificatesResolvers.myresolver.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -420,7 +425,7 @@ As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/stagi
|
||||||
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.
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[certificatesResolvers.le.acme]
|
[certificatesResolvers.myresolver.acme]
|
||||||
# ...
|
# ...
|
||||||
storage = "acme.json"
|
storage = "acme.json"
|
||||||
# ...
|
# ...
|
||||||
|
@ -428,7 +433,7 @@ The `storage` option sets the location where your ACME certificates are saved to
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
certificatesResolvers:
|
certificatesResolvers:
|
||||||
sample:
|
myresolver:
|
||||||
acme:
|
acme:
|
||||||
# ...
|
# ...
|
||||||
storage: acme.json
|
storage: acme.json
|
||||||
|
@ -437,7 +442,7 @@ certificatesResolvers:
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
# ...
|
# ...
|
||||||
--certificatesResolvers.le.acme.storage=acme.json
|
--certificatesResolvers.myresolver.acme.storage=acme.json
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
labels:
|
labels:
|
||||||
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||||
- traefik.http.routers.blog.tls=true
|
- traefik.http.routers.blog.tls=true
|
||||||
- traefik.http.routers.blog.tls.certresolver=le
|
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||||
- traefik.http.routers.blog.tls.domains[0].main=company.org
|
- traefik.http.routers.blog.tls.domains[0].main=company.org
|
||||||
- traefik.http.routers.blog.tls.domains[0].sans=*.company.org
|
- traefik.http.routers.blog.tls.domains[0].sans=*.company.org
|
||||||
```
|
```
|
||||||
|
@ -16,7 +16,7 @@ deploy:
|
||||||
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||||
- traefik.http.services.blog-svc.loadbalancer.server.port=8080"
|
- traefik.http.services.blog-svc.loadbalancer.server.port=8080"
|
||||||
- traefik.http.routers.blog.tls=true
|
- traefik.http.routers.blog.tls=true
|
||||||
- traefik.http.routers.blog.tls.certresolver=le
|
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||||
- traefik.http.routers.blog.tls.domains[0].main=company.org
|
- traefik.http.routers.blog.tls.domains[0].main=company.org
|
||||||
- traefik.http.routers.blog.tls.domains[0].sans=*.company.org
|
- traefik.http.routers.blog.tls.domains[0].sans=*.company.org
|
||||||
```
|
```
|
||||||
|
@ -36,14 +36,14 @@ spec:
|
||||||
- name: blog
|
- name: blog
|
||||||
port: 8080
|
port: 8080
|
||||||
tls:
|
tls:
|
||||||
certResolver: le
|
certResolver: myresolver
|
||||||
```
|
```
|
||||||
|
|
||||||
```json tab="Marathon"
|
```json tab="Marathon"
|
||||||
labels: {
|
labels: {
|
||||||
"traefik.http.routers.blog.rule": "Host(`company.com`) && Path(`/blog`)",
|
"traefik.http.routers.blog.rule": "Host(`company.com`) && Path(`/blog`)",
|
||||||
"traefik.http.routers.blog.tls": "true",
|
"traefik.http.routers.blog.tls": "true",
|
||||||
"traefik.http.routers.blog.tls.certresolver": "le",
|
"traefik.http.routers.blog.tls.certresolver": "myresolver",
|
||||||
"traefik.http.routers.blog.tls.domains[0].main": "company.com",
|
"traefik.http.routers.blog.tls.domains[0].main": "company.com",
|
||||||
"traefik.http.routers.blog.tls.domains[0].sans": "*.company.com",
|
"traefik.http.routers.blog.tls.domains[0].sans": "*.company.com",
|
||||||
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
|
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
|
||||||
|
@ -55,7 +55,7 @@ labels: {
|
||||||
labels:
|
labels:
|
||||||
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||||
- traefik.http.routers.blog.tls=true
|
- traefik.http.routers.blog.tls=true
|
||||||
- traefik.http.routers.blog.tls.certresolver=le
|
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||||
- traefik.http.routers.blog.tls.domains[0].main=company.org
|
- traefik.http.routers.blog.tls.domains[0].main=company.org
|
||||||
- traefik.http.routers.blog.tls.domains[0].sans=*.company.org
|
- traefik.http.routers.blog.tls.domains[0].sans=*.company.org
|
||||||
```
|
```
|
||||||
|
@ -66,7 +66,7 @@ labels:
|
||||||
[http.routers.blog]
|
[http.routers.blog]
|
||||||
rule = "Host(`company.com`) && Path(`/blog`)"
|
rule = "Host(`company.com`) && Path(`/blog`)"
|
||||||
[http.routers.blog.tls]
|
[http.routers.blog.tls]
|
||||||
certResolver = "le" # From static configuration
|
certResolver = "myresolver" # From static configuration
|
||||||
[[http.routers.blog.tls.domains]]
|
[[http.routers.blog.tls.domains]]
|
||||||
main = "company.org"
|
main = "company.org"
|
||||||
sans = ["*.company.org"]
|
sans = ["*.company.org"]
|
||||||
|
@ -79,7 +79,7 @@ http:
|
||||||
blog:
|
blog:
|
||||||
rule: "Host(`company.com`) && Path(`/blog`)"
|
rule: "Host(`company.com`) && Path(`/blog`)"
|
||||||
tls:
|
tls:
|
||||||
certResolver: le
|
certResolver: myresolver
|
||||||
domains:
|
domains:
|
||||||
- main: "company.org"
|
- main: "company.org"
|
||||||
sans:
|
sans:
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
labels:
|
labels:
|
||||||
- traefik.http.routers.blog.rule=(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)
|
- 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=true
|
||||||
- traefik.http.routers.blog.tls.certresolver=le
|
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="Docker (Swarm)"
|
```yaml tab="Docker (Swarm)"
|
||||||
|
@ -13,7 +13,7 @@ deploy:
|
||||||
labels:
|
labels:
|
||||||
- traefik.http.routers.blog.rule=(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)
|
- 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=true
|
||||||
- traefik.http.routers.blog.tls.certresolver=le
|
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||||
- traefik.http.services.blog-svc.loadbalancer.server.port=8080"
|
- traefik.http.services.blog-svc.loadbalancer.server.port=8080"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -32,14 +32,14 @@ spec:
|
||||||
- name: blog
|
- name: blog
|
||||||
port: 8080
|
port: 8080
|
||||||
tls:
|
tls:
|
||||||
certresolver: le
|
certresolver: myresolver
|
||||||
```
|
```
|
||||||
|
|
||||||
```json tab="Marathon"
|
```json tab="Marathon"
|
||||||
labels: {
|
labels: {
|
||||||
"traefik.http.routers.blog.rule": "(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)",
|
"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": "true",
|
||||||
"traefik.http.routers.blog.tls.certresolver": "le",
|
"traefik.http.routers.blog.tls.certresolver": "myresolver",
|
||||||
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
|
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -49,7 +49,7 @@ labels: {
|
||||||
labels:
|
labels:
|
||||||
- traefik.http.routers.blog.rule=(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)
|
- 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=true
|
||||||
- traefik.http.routers.blog.tls.certresolver=le
|
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||||
```
|
```
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
|
@ -58,7 +58,7 @@ labels:
|
||||||
[http.routers.blog]
|
[http.routers.blog]
|
||||||
rule = "(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)"
|
rule = "(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)"
|
||||||
[http.routers.blog.tls]
|
[http.routers.blog.tls]
|
||||||
certResolver = "le"
|
certResolver = "myresolver"
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
|
@ -68,5 +68,5 @@ http:
|
||||||
blog:
|
blog:
|
||||||
rule: "(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)"
|
rule: "(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)"
|
||||||
tls:
|
tls:
|
||||||
certResolver: le
|
certResolver: myresolver
|
||||||
```
|
```
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
labels:
|
labels:
|
||||||
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||||
- traefik.http.routers.blog.tls=true
|
- traefik.http.routers.blog.tls=true
|
||||||
- traefik.http.routers.blog.tls.certresolver=le
|
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="Docker (Swarm)"
|
```yaml tab="Docker (Swarm)"
|
||||||
|
@ -13,7 +13,7 @@ deploy:
|
||||||
labels:
|
labels:
|
||||||
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||||
- traefik.http.routers.blog.tls=true
|
- traefik.http.routers.blog.tls=true
|
||||||
- traefik.http.routers.blog.tls.certresolver=le
|
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||||
- traefik.http.services.blog-svc.loadbalancer.server.port=8080"
|
- traefik.http.services.blog-svc.loadbalancer.server.port=8080"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -32,14 +32,14 @@ spec:
|
||||||
- name: blog
|
- name: blog
|
||||||
port: 8080
|
port: 8080
|
||||||
tls:
|
tls:
|
||||||
certresolver: le
|
certresolver: myresolver
|
||||||
```
|
```
|
||||||
|
|
||||||
```json tab="Marathon"
|
```json tab="Marathon"
|
||||||
labels: {
|
labels: {
|
||||||
"traefik.http.routers.blog.rule": "Host(`company.com`) && Path(`/blog`)",
|
"traefik.http.routers.blog.rule": "Host(`company.com`) && Path(`/blog`)",
|
||||||
"traefik.http.routers.blog.tls": "true",
|
"traefik.http.routers.blog.tls": "true",
|
||||||
"traefik.http.routers.blog.tls.certresolver": "le",
|
"traefik.http.routers.blog.tls.certresolver": "myresolver",
|
||||||
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
|
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -49,7 +49,7 @@ labels: {
|
||||||
labels:
|
labels:
|
||||||
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||||
- traefik.http.routers.blog.tls=true
|
- traefik.http.routers.blog.tls=true
|
||||||
- traefik.http.routers.blog.tls.certresolver=le
|
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||||
```
|
```
|
||||||
|
|
||||||
```toml tab="Single Domain"
|
```toml tab="Single Domain"
|
||||||
|
@ -58,7 +58,7 @@ labels:
|
||||||
[http.routers.blog]
|
[http.routers.blog]
|
||||||
rule = "Host(`company.com`) && Path(`/blog`)"
|
rule = "Host(`company.com`) && Path(`/blog`)"
|
||||||
[http.routers.blog.tls]
|
[http.routers.blog.tls]
|
||||||
certResolver = "le"
|
certResolver = "myresolver"
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
|
@ -68,5 +68,5 @@ http:
|
||||||
blog:
|
blog:
|
||||||
rule: "Host(`company.com`) && Path(`/blog`)"
|
rule: "Host(`company.com`) && Path(`/blog`)"
|
||||||
tls:
|
tls:
|
||||||
certResolver: le
|
certResolver: myresolver
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Enable ACME (Let's Encrypt): automatic SSL.
|
# Enable ACME (Let's Encrypt): automatic SSL.
|
||||||
[certificatesResolvers.sample.acme]
|
[certificatesResolvers.myresolver.acme]
|
||||||
|
|
||||||
# Email address used for registration.
|
# Email address used for registration.
|
||||||
#
|
#
|
||||||
|
@ -35,13 +35,13 @@
|
||||||
#
|
#
|
||||||
# Optional (but recommended)
|
# Optional (but recommended)
|
||||||
#
|
#
|
||||||
[certificatesResolvers.le.acme.tlsChallenge]
|
[certificatesResolvers.myresolver.acme.tlsChallenge]
|
||||||
|
|
||||||
# Use a HTTP-01 ACME challenge.
|
# Use a HTTP-01 ACME challenge.
|
||||||
#
|
#
|
||||||
# Optional
|
# Optional
|
||||||
#
|
#
|
||||||
# [certificatesResolvers.le.acme.httpChallenge]
|
# [certificatesResolvers.myresolver.acme.httpChallenge]
|
||||||
|
|
||||||
# EntryPoint to use for the HTTP-01 challenges.
|
# EntryPoint to use for the HTTP-01 challenges.
|
||||||
#
|
#
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
#
|
#
|
||||||
# Optional
|
# Optional
|
||||||
#
|
#
|
||||||
# [certificatesResolvers.le.acme.dnsChallenge]
|
# [certificatesResolvers.myresolver.acme.dnsChallenge]
|
||||||
|
|
||||||
# DNS provider used.
|
# DNS provider used.
|
||||||
#
|
#
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
#
|
#
|
||||||
# Required
|
# Required
|
||||||
#
|
#
|
||||||
--certificatesResolvers.le.acme.email=test@traefik.io
|
--certificatesResolvers.myresolver.acme.email=test@traefik.io
|
||||||
|
|
||||||
# File or key used for certificates storage.
|
# File or key used for certificates storage.
|
||||||
#
|
#
|
||||||
# Required
|
# Required
|
||||||
#
|
#
|
||||||
--certificatesResolvers.le.acme.storage=acme.json
|
--certificatesResolvers.myresolver.acme.storage=acme.json
|
||||||
|
|
||||||
# CA server to use.
|
# CA server to use.
|
||||||
# Uncomment the line to use Let's Encrypt's staging server,
|
# Uncomment the line to use Let's Encrypt's staging server,
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
# Optional
|
# Optional
|
||||||
# Default: "https://acme-v02.api.letsencrypt.org/directory"
|
# Default: "https://acme-v02.api.letsencrypt.org/directory"
|
||||||
#
|
#
|
||||||
--certificatesResolvers.le.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory
|
--certificatesResolvers.myresolver.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory
|
||||||
|
|
||||||
# KeyType to use.
|
# KeyType to use.
|
||||||
#
|
#
|
||||||
|
@ -28,38 +28,38 @@
|
||||||
#
|
#
|
||||||
# Available values : "EC256", "EC384", "RSA2048", "RSA4096", "RSA8192"
|
# Available values : "EC256", "EC384", "RSA2048", "RSA4096", "RSA8192"
|
||||||
#
|
#
|
||||||
--certificatesResolvers.le.acme.keyType=RSA4096
|
--certificatesResolvers.myresolver.acme.keyType=RSA4096
|
||||||
|
|
||||||
# Use a TLS-ALPN-01 ACME challenge.
|
# Use a TLS-ALPN-01 ACME challenge.
|
||||||
#
|
#
|
||||||
# Optional (but recommended)
|
# Optional (but recommended)
|
||||||
#
|
#
|
||||||
--certificatesResolvers.le.acme.tlsChallenge=true
|
--certificatesResolvers.myresolver.acme.tlsChallenge=true
|
||||||
|
|
||||||
# Use a HTTP-01 ACME challenge.
|
# Use a HTTP-01 ACME challenge.
|
||||||
#
|
#
|
||||||
# Optional
|
# Optional
|
||||||
#
|
#
|
||||||
--certificatesResolvers.le.acme.httpChallenge=true
|
--certificatesResolvers.myresolver.acme.httpChallenge=true
|
||||||
|
|
||||||
# EntryPoint to use for the HTTP-01 challenges.
|
# EntryPoint to use for the HTTP-01 challenges.
|
||||||
#
|
#
|
||||||
# Required
|
# Required
|
||||||
#
|
#
|
||||||
--certificatesResolvers.le.acme.httpChallenge.entryPoint=web
|
--certificatesResolvers.myresolver.acme.httpChallenge.entryPoint=web
|
||||||
|
|
||||||
# Use a DNS-01 ACME challenge rather than HTTP-01 challenge.
|
# Use a DNS-01 ACME challenge rather than HTTP-01 challenge.
|
||||||
# Note: mandatory for wildcard certificate generation.
|
# Note: mandatory for wildcard certificate generation.
|
||||||
#
|
#
|
||||||
# Optional
|
# Optional
|
||||||
#
|
#
|
||||||
--certificatesResolvers.le.acme.dnsChallenge=true
|
--certificatesResolvers.myresolver.acme.dnsChallenge=true
|
||||||
|
|
||||||
# DNS provider used.
|
# DNS provider used.
|
||||||
#
|
#
|
||||||
# Required
|
# Required
|
||||||
#
|
#
|
||||||
--certificatesResolvers.le.acme.dnsChallenge.provider=digitalocean
|
--certificatesResolvers.myresolver.acme.dnsChallenge.provider=digitalocean
|
||||||
|
|
||||||
# By default, the provider will verify the TXT DNS challenge record before letting ACME verify.
|
# By default, the provider will verify the TXT DNS challenge record before letting ACME verify.
|
||||||
# If delayBeforeCheck is greater than zero, this check is delayed for the configured duration in seconds.
|
# If delayBeforeCheck is greater than zero, this check is delayed for the configured duration in seconds.
|
||||||
|
@ -68,14 +68,14 @@
|
||||||
# Optional
|
# Optional
|
||||||
# Default: 0
|
# Default: 0
|
||||||
#
|
#
|
||||||
--certificatesResolvers.le.acme.dnsChallenge.delayBeforeCheck=0
|
--certificatesResolvers.myresolver.acme.dnsChallenge.delayBeforeCheck=0
|
||||||
|
|
||||||
# Use following DNS servers to resolve the FQDN authority.
|
# Use following DNS servers to resolve the FQDN authority.
|
||||||
#
|
#
|
||||||
# Optional
|
# Optional
|
||||||
# Default: empty
|
# Default: empty
|
||||||
#
|
#
|
||||||
--certificatesResolvers.le.acme.dnsChallenge.resolvers=1.1.1.1:53,8.8.8.8:53
|
--certificatesResolvers.myresolver.acme.dnsChallenge.resolvers=1.1.1.1:53,8.8.8.8:53
|
||||||
|
|
||||||
# Disable the DNS propagation checks before notifying ACME that the DNS challenge is ready.
|
# Disable the DNS propagation checks before notifying ACME that the DNS challenge is ready.
|
||||||
#
|
#
|
||||||
|
@ -85,4 +85,4 @@
|
||||||
# Optional
|
# Optional
|
||||||
# Default: false
|
# Default: false
|
||||||
#
|
#
|
||||||
--certificatesResolvers.le.acme.dnsChallenge.disablePropagationCheck=true
|
--certificatesResolvers.myresolver.acme.dnsChallenge.disablePropagationCheck=true
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
certificatesResolvers:
|
certificatesResolvers:
|
||||||
le:
|
myresolver:
|
||||||
# Enable ACME (Let's Encrypt): automatic SSL.
|
# Enable ACME (Let's Encrypt): automatic SSL.
|
||||||
acme:
|
acme:
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,132 @@ RedirectScheme redirect request from a scheme to another.
|
||||||
|
|
||||||
## Configuration Examples
|
## Configuration Examples
|
||||||
|
|
||||||
|
```yaml tab="Docker"
|
||||||
|
# Redirect to https
|
||||||
|
labels:
|
||||||
|
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https"
|
||||||
|
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true"
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Kubernetes"
|
||||||
|
# Redirect to https
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: test-redirectscheme
|
||||||
|
spec:
|
||||||
|
redirectScheme:
|
||||||
|
scheme: https
|
||||||
|
permanent: true
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Consul Catalog"
|
||||||
|
# Redirect to https
|
||||||
|
labels:
|
||||||
|
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https"
|
||||||
|
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true"
|
||||||
|
```
|
||||||
|
|
||||||
|
```json tab="Marathon"
|
||||||
|
"labels": {
|
||||||
|
"traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme": "https"
|
||||||
|
"traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent": "true"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Rancher"
|
||||||
|
# Redirect to https
|
||||||
|
labels:
|
||||||
|
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https"
|
||||||
|
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true"
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml tab="File (TOML)"
|
||||||
|
# Redirect to https
|
||||||
|
[http.middlewares]
|
||||||
|
[http.middlewares.test-redirectscheme.redirectScheme]
|
||||||
|
scheme = "https"
|
||||||
|
permanent = true
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
# Redirect to https
|
||||||
|
http:
|
||||||
|
middlewares:
|
||||||
|
test-redirectscheme:
|
||||||
|
redirectScheme:
|
||||||
|
scheme: https
|
||||||
|
permanent: true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration Options
|
||||||
|
|
||||||
|
### `permanent`
|
||||||
|
|
||||||
|
Set the `permanent` option to `true` to apply a permanent redirection.
|
||||||
|
|
||||||
|
```yaml tab="Docker"
|
||||||
|
# Redirect to https
|
||||||
|
labels:
|
||||||
|
# ...
|
||||||
|
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true"
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Kubernetes"
|
||||||
|
# Redirect to https
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: test-redirectscheme
|
||||||
|
spec:
|
||||||
|
redirectScheme:
|
||||||
|
# ...
|
||||||
|
permanent: true
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Consul Catalog"
|
||||||
|
# Redirect to https
|
||||||
|
labels:
|
||||||
|
# ...
|
||||||
|
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true"
|
||||||
|
```
|
||||||
|
|
||||||
|
```json tab="Marathon"
|
||||||
|
"labels": {
|
||||||
|
|
||||||
|
"traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent": "true"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Rancher"
|
||||||
|
# Redirect to https
|
||||||
|
labels:
|
||||||
|
# ...
|
||||||
|
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true"
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml tab="File (TOML)"
|
||||||
|
# Redirect to https
|
||||||
|
[http.middlewares]
|
||||||
|
[http.middlewares.test-redirectscheme.redirectScheme]
|
||||||
|
# ...
|
||||||
|
permanent = true
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
# Redirect to https
|
||||||
|
http:
|
||||||
|
middlewares:
|
||||||
|
test-redirectscheme:
|
||||||
|
redirectScheme:
|
||||||
|
# ...
|
||||||
|
permanent: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### `scheme`
|
||||||
|
|
||||||
|
The `scheme` option defines the scheme of the new url.
|
||||||
|
|
||||||
```yaml tab="Docker"
|
```yaml tab="Docker"
|
||||||
# Redirect to https
|
# Redirect to https
|
||||||
labels:
|
labels:
|
||||||
|
@ -62,16 +188,64 @@ http:
|
||||||
scheme: https
|
scheme: https
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration Options
|
|
||||||
|
|
||||||
### `permanent`
|
|
||||||
|
|
||||||
Set the `permanent` option to `true` to apply a permanent redirection.
|
|
||||||
|
|
||||||
### `scheme`
|
|
||||||
|
|
||||||
The `scheme` option defines the scheme of the new url.
|
|
||||||
|
|
||||||
### `port`
|
### `port`
|
||||||
|
|
||||||
The `port` option defines the port of the new url.
|
The `port` option defines the port of the new url.
|
||||||
|
|
||||||
|
```yaml tab="Docker"
|
||||||
|
# Redirect to https
|
||||||
|
labels:
|
||||||
|
# ...
|
||||||
|
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443"
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Kubernetes"
|
||||||
|
# Redirect to https
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: test-redirectscheme
|
||||||
|
spec:
|
||||||
|
redirectScheme:
|
||||||
|
# ...
|
||||||
|
port: 443
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Consul Catalog"
|
||||||
|
# Redirect to https
|
||||||
|
labels:
|
||||||
|
# ...
|
||||||
|
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443"
|
||||||
|
```
|
||||||
|
|
||||||
|
```json tab="Marathon"
|
||||||
|
"labels": {
|
||||||
|
|
||||||
|
"traefik.http.middlewares.test-redirectscheme.redirectscheme.port": "443"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Rancher"
|
||||||
|
# Redirect to https
|
||||||
|
labels:
|
||||||
|
# ...
|
||||||
|
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443"
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml tab="File (TOML)"
|
||||||
|
# Redirect to https
|
||||||
|
[http.middlewares]
|
||||||
|
[http.middlewares.test-redirectscheme.redirectScheme]
|
||||||
|
# ...
|
||||||
|
port = 443
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
# Redirect to https
|
||||||
|
http:
|
||||||
|
middlewares:
|
||||||
|
test-redirectscheme:
|
||||||
|
redirectScheme:
|
||||||
|
# ...
|
||||||
|
port: 443
|
||||||
|
```
|
||||||
|
|
|
@ -236,11 +236,8 @@ Then, a [router's TLS field](../routing/routers/index.md#tls) can refer to one o
|
||||||
keyFile = "/path/to/domain.key"
|
keyFile = "/path/to/domain.key"
|
||||||
|
|
||||||
[tls.options]
|
[tls.options]
|
||||||
[tls.options.default]
|
|
||||||
minVersion = "VersionTLS12"
|
|
||||||
|
|
||||||
[tls.options.myTLSOptions]
|
[tls.options.myTLSOptions]
|
||||||
minVersion = "VersionTLS13"
|
minVersion = "VersionTLS12"
|
||||||
cipherSuites = [
|
cipherSuites = [
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||||
|
@ -267,7 +264,7 @@ Then, a [router's TLS field](../routing/routers/index.md#tls) can refer to one o
|
||||||
keyFile: /path/to/domain.key
|
keyFile: /path/to/domain.key
|
||||||
options:
|
options:
|
||||||
myTLSOptions:
|
myTLSOptions:
|
||||||
minVersion: VersionTLS13
|
minVersion: VersionTLS12
|
||||||
cipherSuites:
|
cipherSuites:
|
||||||
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||||
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
|
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
|
||||||
|
@ -286,7 +283,7 @@ Then, a [router's TLS field](../routing/routers/index.md#tls) can refer to one o
|
||||||
namespace: default
|
namespace: default
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
minVersion: VersionTLS13
|
minVersion: VersionTLS12
|
||||||
cipherSuites:
|
cipherSuites:
|
||||||
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||||
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
|
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
|
||||||
|
@ -681,7 +678,7 @@ To apply a redirection, one of the redirect middlewares, [RedirectRegex](../midd
|
||||||
With the new core notions of v2 (introduced earlier in the section
|
With the new core notions of v2 (introduced earlier in the section
|
||||||
["Frontends and Backends Are Dead... Long Live Routers, Middlewares, and Services"](#frontends-and-backends-are-dead-long-live-routers-middlewares-and-services)),
|
["Frontends and Backends Are Dead... Long Live Routers, Middlewares, and Services"](#frontends-and-backends-are-dead-long-live-routers-middlewares-and-services)),
|
||||||
transforming the URL path prefix of incoming requests is configured with [middlewares](../middlewares/overview.md),
|
transforming the URL path prefix of incoming requests is configured with [middlewares](../middlewares/overview.md),
|
||||||
after the routing step with [router rule `PathPrefix`](https://docs.traefik.io/v2.0/routing/routers/#rule).
|
after the routing step with [router rule `PathPrefix`](../routing/routers/index.md#rule).
|
||||||
|
|
||||||
Use Case: Incoming requests to `http://company.org/admin` are forwarded to the webapplication "admin",
|
Use Case: Incoming requests to `http://company.org/admin` are forwarded to the webapplication "admin",
|
||||||
with the path `/admin` stripped, e.g. to `http://<IP>:<port>/`. In this case, you must:
|
with the path `/admin` stripped, e.g. to `http://<IP>:<port>/`. In this case, you must:
|
||||||
|
@ -826,7 +823,7 @@ with the path `/admin` stripped, e.g. to `http://<IP>:<port>/`. In this case, yo
|
||||||
entryPoint = "webs"
|
entryPoint = "webs"
|
||||||
[entryPoints.websecure]
|
[entryPoints.websecure]
|
||||||
address = ":443"
|
address = ":443"
|
||||||
[entryPoints.https.tls]
|
[entryPoints.websecure.tls]
|
||||||
|
|
||||||
[acme]
|
[acme]
|
||||||
email = "your-email-here@my-awesome-app.org"
|
email = "your-email-here@my-awesome-app.org"
|
||||||
|
@ -859,10 +856,10 @@ with the path `/admin` stripped, e.g. to `http://<IP>:<port>/`. In this case, yo
|
||||||
[entryPoints.websecure]
|
[entryPoints.websecure]
|
||||||
address = ":443"
|
address = ":443"
|
||||||
|
|
||||||
[certificatesResolvers.sample.acme]
|
[certificatesResolvers.myresolver.acme]
|
||||||
email = "your-email@your-domain.org"
|
email = "your-email@your-domain.org"
|
||||||
storage = "acme.json"
|
storage = "acme.json"
|
||||||
[certificatesResolvers.sample.acme.httpChallenge]
|
[certificatesResolvers.myresolver.acme.httpChallenge]
|
||||||
# used during the challenge
|
# used during the challenge
|
||||||
entryPoint = "web"
|
entryPoint = "web"
|
||||||
```
|
```
|
||||||
|
@ -876,7 +873,7 @@ with the path `/admin` stripped, e.g. to `http://<IP>:<port>/`. In this case, yo
|
||||||
address: ":443"
|
address: ":443"
|
||||||
|
|
||||||
certificatesResolvers:
|
certificatesResolvers:
|
||||||
sample:
|
myresolver:
|
||||||
acme:
|
acme:
|
||||||
email: your-email@your-domain.org
|
email: your-email@your-domain.org
|
||||||
storage: acme.json
|
storage: acme.json
|
||||||
|
@ -888,9 +885,9 @@ with the path `/admin` stripped, e.g. to `http://<IP>:<port>/`. In this case, yo
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
--entryPoints.web.address=:80
|
--entryPoints.web.address=:80
|
||||||
--entryPoints.websecure.address=:443
|
--entryPoints.websecure.address=:443
|
||||||
--certificatesResolvers.sample.acme.email=your-email@your-domain.org
|
--certificatesResolvers.myresolver.acme.email=your-email@your-domain.org
|
||||||
--certificatesResolvers.sample.acme.storage=acme.json
|
--certificatesResolvers.myresolver.acme.storage=acme.json
|
||||||
--certificatesResolvers.sample.acme.httpChallenge.entryPoint=web
|
--certificatesResolvers.myresolver.acme.httpChallenge.entryPoint=web
|
||||||
```
|
```
|
||||||
|
|
||||||
## Traefik Logs
|
## Traefik Logs
|
||||||
|
|
|
@ -2,8 +2,11 @@
|
||||||
|
|
||||||
## v2.0 to v2.1
|
## v2.0 to v2.1
|
||||||
|
|
||||||
In v2.1, a new CRD called `TraefikService` was added. While updating an installation to v2.1,
|
### Kubernetes CRD
|
||||||
it is required to apply that CRD before as well as enhance the existing `ClusterRole` definition to allow Traefik to use that CRD.
|
|
||||||
|
In v2.1, a new Kubernetes CRD called `TraefikService` was added.
|
||||||
|
While updating an installation to v2.1,
|
||||||
|
one should apply that CRD, and update the existing `ClusterRole` definition to allow Traefik to use that CRD.
|
||||||
|
|
||||||
To add that CRD and enhance the permissions, following definitions need to be applied to the cluster.
|
To add that CRD and enhance the permissions, following definitions need to be applied to the cluster.
|
||||||
|
|
||||||
|
|
|
@ -40,24 +40,24 @@ tracing:
|
||||||
|
|
||||||
#### `localAgentPort`
|
#### `localAgentPort`
|
||||||
|
|
||||||
_Require, Default=42699_
|
_Require, Default=35000_
|
||||||
|
|
||||||
Local Agent port instructs reporter to send spans to the haystack-agent at this port.
|
Local Agent port instructs reporter to send spans to the haystack-agent at this port.
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[tracing]
|
[tracing]
|
||||||
[tracing.haystack]
|
[tracing.haystack]
|
||||||
localAgentPort = 42699
|
localAgentPort = 35000
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
tracing:
|
tracing:
|
||||||
haystack:
|
haystack:
|
||||||
localAgentPort: 42699
|
localAgentPort: 35000
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
--tracing.haystack.localAgentPort=42699
|
--tracing.haystack.localAgentPort=35000
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `globalTag`
|
#### `globalTag`
|
||||||
|
@ -91,61 +91,61 @@ Specifies the header name that will be used to store the trace ID.
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[tracing]
|
[tracing]
|
||||||
[tracing.haystack]
|
[tracing.haystack]
|
||||||
traceIDHeaderName = "sample"
|
traceIDHeaderName = "Trace-ID"
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
tracing:
|
tracing:
|
||||||
haystack:
|
haystack:
|
||||||
traceIDHeaderName: sample
|
traceIDHeaderName: Trace-ID
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
--tracing.haystack.traceIDHeaderName=sample
|
--tracing.haystack.traceIDHeaderName=Trace-ID
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `parentIDHeaderName`
|
#### `parentIDHeaderName`
|
||||||
|
|
||||||
_Optional, Default=empty_
|
_Optional, Default=empty_
|
||||||
|
|
||||||
|
Specifies the header name that will be used to store the parent ID.
|
||||||
|
|
||||||
|
```toml tab="File (TOML)"
|
||||||
|
[tracing]
|
||||||
|
[tracing.haystack]
|
||||||
|
parentIDHeaderName = "Parent-Message-ID"
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
tracing:
|
||||||
|
haystack:
|
||||||
|
parentIDHeaderName: Parent-Message-ID
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="CLI"
|
||||||
|
--tracing.haystack.parentIDHeaderName=Parent-Message-ID
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `spanIDHeaderName`
|
||||||
|
|
||||||
|
_Optional, Default=empty_
|
||||||
|
|
||||||
Specifies the header name that will be used to store the span ID.
|
Specifies the header name that will be used to store the span ID.
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[tracing]
|
[tracing]
|
||||||
[tracing.haystack]
|
[tracing.haystack]
|
||||||
parentIDHeaderName = "sample"
|
spanIDHeaderName = "Message-ID"
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
tracing:
|
tracing:
|
||||||
haystack:
|
haystack:
|
||||||
parentIDHeaderName: "sample"
|
spanIDHeaderName: Message-ID
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
--tracing.haystack.parentIDHeaderName=sample
|
--tracing.haystack.spanIDHeaderName=Message-ID
|
||||||
```
|
|
||||||
|
|
||||||
#### `spanIDHeaderName`
|
|
||||||
|
|
||||||
_Optional, Default=empty_
|
|
||||||
|
|
||||||
Apply shared tag in a form of Key:Value to all the traces.
|
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
|
||||||
[tracing]
|
|
||||||
[tracing.haystack]
|
|
||||||
spanIDHeaderName = "sample:test"
|
|
||||||
```
|
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
|
||||||
tracing:
|
|
||||||
haystack:
|
|
||||||
spanIDHeaderName: "sample:test"
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash tab="CLI"
|
|
||||||
--tracing.haystack.spanIDHeaderName=sample:test
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `baggagePrefixHeaderName`
|
#### `baggagePrefixHeaderName`
|
||||||
|
|
|
@ -31,6 +31,8 @@ spec:
|
||||||
services:
|
services:
|
||||||
- name: api@internal
|
- name: api@internal
|
||||||
kind: TraefikService
|
kind: TraefikService
|
||||||
|
middlewares:
|
||||||
|
- name: auth
|
||||||
---
|
---
|
||||||
apiVersion: traefik.containo.us/v1alpha1
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
kind: Middleware
|
kind: Middleware
|
||||||
|
|
|
@ -565,7 +565,7 @@ Constraints is an expression that Traefik matches against the service's tags to
|
||||||
That is to say, if none of the service's tags match the expression, no route for that service is created.
|
That is to say, if none of the service's tags match the expression, no route for that service is created.
|
||||||
If the expression is empty, all detected services are included.
|
If the expression is empty, all detected services are included.
|
||||||
|
|
||||||
The expression syntax is based on the `Tag("tag")`, and `TagRegex("tag")` functions,
|
The expression syntax is based on the ```Tag(`tag`)```, and ```TagRegex(`tag`)``` functions,
|
||||||
as well as the usual boolean logic, as shown in examples below.
|
as well as the usual boolean logic, as shown in examples below.
|
||||||
|
|
||||||
??? example "Constraints Expression Examples"
|
??? example "Constraints Expression Examples"
|
||||||
|
|
|
@ -261,7 +261,7 @@ See the sections [Docker API Access](#docker-api-access) and [Docker Swarm API A
|
||||||
|
|
||||||
services:
|
services:
|
||||||
traefik:
|
traefik:
|
||||||
image: traefik:v2.0 # The official v2.0 Traefik docker image
|
image: traefik:v2.1 # The official v2 Traefik docker image
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "80:80"
|
||||||
volumes:
|
volumes:
|
||||||
|
|
|
@ -118,27 +118,35 @@ If you're in a hurry, maybe you'd rather go through the [dynamic configuration](
|
||||||
|
|
||||||
### `filename`
|
### `filename`
|
||||||
|
|
||||||
Defines the path of the configuration file.
|
Defines the path to the configuration file.
|
||||||
|
|
||||||
|
!!! warning ""
|
||||||
|
`filename` and `directory` are mutually exclusive.
|
||||||
|
The recommendation is to use `directory`.
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[providers]
|
[providers]
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "dynamic_conf.toml"
|
filename = "/path/to/config/dynamic_conf.toml"
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
providers:
|
providers:
|
||||||
file:
|
file:
|
||||||
filename: dynamic_conf.yml
|
filename: /path/to/config/dynamic_conf.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
--providers.file.filename=dynamic_conf.toml
|
--providers.file.filename=/path/to/config/dynamic_conf.toml
|
||||||
```
|
```
|
||||||
|
|
||||||
### `directory`
|
### `directory`
|
||||||
|
|
||||||
Defines the directory that contains the configuration files.
|
Defines the path to the directory that contains the configuration files.
|
||||||
|
|
||||||
|
!!! warning ""
|
||||||
|
`filename` and `directory` are mutually exclusive.
|
||||||
|
The recommendation is to use `directory`.
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[providers]
|
[providers]
|
||||||
|
@ -186,8 +194,11 @@ providers:
|
||||||
Go Templating only works along with dedicated dynamic configuration files.
|
Go Templating only works along with dedicated dynamic configuration files.
|
||||||
Templating does not work in the Traefik main static configuration file.
|
Templating does not work in the Traefik main static configuration file.
|
||||||
|
|
||||||
Traefik allows using Go templating.
|
Traefik allows using Go templating,
|
||||||
Thus, it's possible to define easily lot of routers, services and TLS certificates as described in the file `template-rules.toml` :
|
it must be a valid [Go template](https://golang.org/pkg/text/template/),
|
||||||
|
augmented with the [sprig template functions](http://masterminds.github.io/sprig/).
|
||||||
|
|
||||||
|
Thus, it's possible to define easily lot of routers, services and TLS certificates as described in the following examples:
|
||||||
|
|
||||||
??? example "Configuring Using Templating"
|
??? example "Configuring Using Templating"
|
||||||
|
|
||||||
|
@ -197,7 +208,7 @@ Thus, it's possible to define easily lot of routers, services and TLS certificat
|
||||||
|
|
||||||
[http.routers]
|
[http.routers]
|
||||||
{{ range $i, $e := until 100 }}
|
{{ range $i, $e := until 100 }}
|
||||||
[http.routers.router{{ $e }}]
|
[http.routers.router{{ $e }}-{{ env "MY_ENV_VAR" }}]
|
||||||
# ...
|
# ...
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
@ -239,36 +250,34 @@ Thus, it's possible to define easily lot of routers, services and TLS certificat
|
||||||
|
|
||||||
```yaml tab="YAML"
|
```yaml tab="YAML"
|
||||||
http:
|
http:
|
||||||
|
|
||||||
{{range $i, $e := until 100 }}
|
|
||||||
routers:
|
routers:
|
||||||
router{{ $e }:
|
{{range $i, $e := until 100 }}
|
||||||
|
router{{ $e }}-{{ env "MY_ENV_VAR" }}:
|
||||||
# ...
|
# ...
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{range $i, $e := until 100 }}
|
|
||||||
services:
|
services:
|
||||||
|
{{range $i, $e := until 100 }}
|
||||||
application{{ $e }}:
|
application{{ $e }}:
|
||||||
# ...
|
# ...
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
tcp:
|
tcp:
|
||||||
|
|
||||||
{{range $i, $e := until 100 }}
|
|
||||||
routers:
|
routers:
|
||||||
router{{ $e }:
|
{{range $i, $e := until 100 }}
|
||||||
|
router{{ $e }}:
|
||||||
# ...
|
# ...
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{range $i, $e := until 100 }}
|
|
||||||
services:
|
services:
|
||||||
|
{{range $i, $e := until 100 }}
|
||||||
service{{ $e }}:
|
service{{ $e }}:
|
||||||
# ...
|
# ...
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{ range $i, $e := until 10 }}
|
|
||||||
tls:
|
tls:
|
||||||
certificates:
|
certificates:
|
||||||
|
{{ range $i, $e := until 10 }}
|
||||||
- certFile: "/etc/traefik/cert-{{ $e }}.pem"
|
- certFile: "/etc/traefik/cert-{{ $e }}.pem"
|
||||||
keyFile: "/etc/traefik/cert-{{ $e }}.key"
|
keyFile: "/etc/traefik/cert-{{ $e }}.key"
|
||||||
store:
|
store:
|
||||||
|
|
|
@ -31,6 +31,51 @@ The provider then watches for incoming ingresses events, such as the example bel
|
||||||
and derives the corresponding dynamic configuration from it,
|
and derives the corresponding dynamic configuration from it,
|
||||||
which in turn will create the resulting routers, services, handlers, etc.
|
which in turn will create the resulting routers, services, handlers, etc.
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
kind: Ingress
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: "foo"
|
||||||
|
namespace: production
|
||||||
|
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: foo.com
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /bar
|
||||||
|
backend:
|
||||||
|
serviceName: service1
|
||||||
|
servicePort: 80
|
||||||
|
- path: /foo
|
||||||
|
backend:
|
||||||
|
serviceName: service1
|
||||||
|
servicePort: 80
|
||||||
|
```
|
||||||
|
|
||||||
|
## LetsEncrypt Support with the Ingress Provider
|
||||||
|
|
||||||
|
By design, Traefik is a stateless application,
|
||||||
|
meaning that it only derives its configuration from the environment it runs in,
|
||||||
|
without additional configuration.
|
||||||
|
For this reason, users can run multiple instances of Traefik at the same time to achieve HA,
|
||||||
|
as is a common pattern in the kubernetes ecosystem.
|
||||||
|
|
||||||
|
When using a single instance of Traefik with LetsEncrypt, no issues should be encountered,
|
||||||
|
however this could be a single point of failure.
|
||||||
|
Unfortunately, it is not possible to run multiple instances of Traefik 2.0 with LetsEncrypt enabled,
|
||||||
|
because there is no way to ensure that the correct instance of Traefik will receive the challenge request, and subsequent responses.
|
||||||
|
Previous versions of Traefik used a [KV store](https://docs.traefik.io/v1.7/configuration/acme/#storage) to attempt to achieve this,
|
||||||
|
but due to sub-optimal performance was dropped as a feature in 2.0.
|
||||||
|
|
||||||
|
If you require LetsEncrypt with HA in a kubernetes environment,
|
||||||
|
we recommend using [TraefikEE](https://containo.us/traefikee/) where distributed LetsEncrypt is a supported feature.
|
||||||
|
|
||||||
|
If you are wanting to continue to run Traefik Community Edition,
|
||||||
|
LetsEncrypt HA can be achieved by using a Certificate Controller such as [Cert-Manager](https://docs.cert-manager.io/en/latest/index.html).
|
||||||
|
When using Cert-Manager to manage certificates,
|
||||||
|
it will create secrets in your namespaces that can be referenced as TLS secrets in your [ingress objects](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls).
|
||||||
|
|
||||||
## Provider Configuration
|
## Provider Configuration
|
||||||
|
|
||||||
### `endpoint`
|
### `endpoint`
|
||||||
|
@ -63,7 +108,8 @@ They are both provided automatically as mounts in the pod where Traefik is deplo
|
||||||
|
|
||||||
When the environment variables are not found, Traefik tries to connect to the Kubernetes API server with an external-cluster client.
|
When the environment variables are not found, Traefik tries to connect to the Kubernetes API server with an external-cluster client.
|
||||||
In which case, the endpoint is required.
|
In which case, the endpoint is required.
|
||||||
Specifically, it may be set to the URL used by `kubectl proxy` to connect to a Kubernetes cluster using the granted authentication and authorization of the associated kubeconfig.
|
Specifically, it may be set to the URL used by `kubectl proxy` to connect to a Kubernetes cluster using the granted authentication
|
||||||
|
and authorization of the associated kubeconfig.
|
||||||
|
|
||||||
### `token`
|
### `token`
|
||||||
|
|
||||||
|
@ -268,7 +314,7 @@ _Optional, Default: empty_
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[providers.kubernetesIngress.ingressEndpoint]
|
[providers.kubernetesIngress.ingressEndpoint]
|
||||||
publishedService = "foo-service"
|
publishedService = "namespace/foo-service"
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -276,15 +322,16 @@ _Optional, Default: empty_
|
||||||
providers:
|
providers:
|
||||||
kubernetesIngress:
|
kubernetesIngress:
|
||||||
ingressEndpoint:
|
ingressEndpoint:
|
||||||
publishedService: "foo-service"
|
publishedService: "namespace/foo-service"
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
--providers.kubernetesingress.ingressendpoint.publishedservice=foo-service
|
--providers.kubernetesingress.ingressendpoint.publishedservice=namespace/foo-service
|
||||||
```
|
```
|
||||||
|
|
||||||
Published Kubernetes Service to copy status from.
|
Published Kubernetes Service to copy status from.
|
||||||
|
Format: `namespace/servicename`.
|
||||||
|
|
||||||
### `throttleDuration`
|
### `throttleDuration`
|
||||||
|
|
||||||
|
@ -309,7 +356,8 @@ providers:
|
||||||
|
|
||||||
### Further
|
### Further
|
||||||
|
|
||||||
If one wants to know more about the various aspects of the Ingress spec that Traefik supports, many examples of Ingresses definitions are located in the tests [data](https://github.com/containous/traefik/tree/v2.0/pkg/provider/kubernetes/ingress/fixtures) of the Traefik repository.
|
If one wants to know more about the various aspects of the Ingress spec that Traefik supports,
|
||||||
|
many examples of Ingresses definitions are located in the tests [data](https://github.com/containous/traefik/tree/v2.1/pkg/provider/kubernetes/ingress/fixtures) of the Traefik repository.
|
||||||
|
|
||||||
## LetsEncrypt Support with the Ingress Provider
|
## LetsEncrypt Support with the Ingress Provider
|
||||||
|
|
||||||
|
|
|
@ -712,7 +712,7 @@ Specifies the header name prefix that will be used to store baggage items in a m
|
||||||
Key:Value tag to be set on all the spans.
|
Key:Value tag to be set on all the spans.
|
||||||
|
|
||||||
`--tracing.haystack.localagenthost`:
|
`--tracing.haystack.localagenthost`:
|
||||||
Set haystack-agent's host that the reporter will used. (Default: ```LocalAgentHost```)
|
Set haystack-agent's host that the reporter will used. (Default: ```127.0.0.1```)
|
||||||
|
|
||||||
`--tracing.haystack.localagentport`:
|
`--tracing.haystack.localagentport`:
|
||||||
Set haystack-agent's port that the reporter will used. (Default: ```35000```)
|
Set haystack-agent's port that the reporter will used. (Default: ```35000```)
|
||||||
|
|
|
@ -712,7 +712,7 @@ Specifies the header name prefix that will be used to store baggage items in a m
|
||||||
Key:Value tag to be set on all the spans.
|
Key:Value tag to be set on all the spans.
|
||||||
|
|
||||||
`TRAEFIK_TRACING_HAYSTACK_LOCALAGENTHOST`:
|
`TRAEFIK_TRACING_HAYSTACK_LOCALAGENTHOST`:
|
||||||
Set haystack-agent's host that the reporter will used. (Default: ```LocalAgentHost```)
|
Set haystack-agent's host that the reporter will used. (Default: ```127.0.0.1```)
|
||||||
|
|
||||||
`TRAEFIK_TRACING_HAYSTACK_LOCALAGENTPORT`:
|
`TRAEFIK_TRACING_HAYSTACK_LOCALAGENTPORT`:
|
||||||
Set haystack-agent's port that the reporter will used. (Default: ```35000```)
|
Set haystack-agent's port that the reporter will used. (Default: ```35000```)
|
||||||
|
|
|
@ -457,6 +457,16 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
|
||||||
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=
|
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=
|
||||||
```
|
```
|
||||||
|
|
||||||
|
!!! important "Configuring Backend Protocol"
|
||||||
|
|
||||||
|
There are 3 ways to configure the backend protocol for communication between Traefik and your pods:
|
||||||
|
|
||||||
|
- Setting the scheme explicitly (http/https/h2c)
|
||||||
|
- Configuring the name of the kubernetes service port to start with https (https)
|
||||||
|
- Setting the kubernetes service port to use port 443 (https)
|
||||||
|
|
||||||
|
If you do not configure the above, Traefik will assume an http connection.
|
||||||
|
|
||||||
### Kind: `Middleware`
|
### Kind: `Middleware`
|
||||||
|
|
||||||
`Middleware` is the CRD implementation of a [Traefik middleware](../../middlewares/overview.md).
|
`Middleware` is the CRD implementation of a [Traefik middleware](../../middlewares/overview.md).
|
||||||
|
|
|
@ -26,19 +26,19 @@ spec:
|
||||||
serviceAccountName: traefik-ingress-controller
|
serviceAccountName: traefik-ingress-controller
|
||||||
containers:
|
containers:
|
||||||
- name: traefik
|
- name: traefik
|
||||||
image: traefik:v2.0
|
image: traefik:v2.1
|
||||||
args:
|
args:
|
||||||
- --api.insecure
|
- --api.insecure
|
||||||
- --accesslog
|
- --accesslog
|
||||||
- --entrypoints.web.Address=:8000
|
- --entrypoints.web.Address=:8000
|
||||||
- --entrypoints.websecure.Address=:4443
|
- --entrypoints.websecure.Address=:4443
|
||||||
- --providers.kubernetescrd
|
- --providers.kubernetescrd
|
||||||
- --certificatesresolvers.default.acme.tlschallenge
|
- --certificatesresolvers.myresolver.acme.tlschallenge
|
||||||
- --certificatesresolvers.default.acme.email=foo@you.com
|
- --certificatesresolvers.myresolver.acme.email=foo@you.com
|
||||||
- --certificatesresolvers.default.acme.storage=acme.json
|
- --certificatesresolvers.myresolver.acme.storage=acme.json
|
||||||
# Please note that this is the staging Let's Encrypt server.
|
# Please note that this is the staging Let's Encrypt server.
|
||||||
# Once you get things working, you should remove that whole line altogether.
|
# Once you get things working, you should remove that whole line altogether.
|
||||||
- --certificatesresolvers.default.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
|
- --certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
|
||||||
ports:
|
ports:
|
||||||
- name: web
|
- name: web
|
||||||
containerPort: 8000
|
containerPort: 8000
|
||||||
|
|
|
@ -29,4 +29,4 @@ spec:
|
||||||
- name: whoami
|
- name: whoami
|
||||||
port: 80
|
port: 80
|
||||||
tls:
|
tls:
|
||||||
certResolver: default
|
certResolver: myresolver
|
||||||
|
|
|
@ -26,5 +26,5 @@ node:
|
||||||
- K3S_CLUSTER_SECRET=somethingtotallyrandom
|
- K3S_CLUSTER_SECRET=somethingtotallyrandom
|
||||||
volumes:
|
volumes:
|
||||||
# this is where you would place a alternative traefik image (saved as a .tar file with
|
# this is where you would place a alternative traefik image (saved as a .tar file with
|
||||||
# 'docker save'), if you want to use it, instead of the traefik:v2.0 image.
|
# 'docker save'), if you want to use it, instead of the traefik:v2.1 image.
|
||||||
- /sowewhere/on/your/host/custom-image:/var/lib/rancher/k3s/agent/images
|
- /sowewhere/on/your/host/custom-image:/var/lib/rancher/k3s/agent/images
|
||||||
|
|
|
@ -3,7 +3,7 @@ version: "3.3"
|
||||||
services:
|
services:
|
||||||
|
|
||||||
traefik:
|
traefik:
|
||||||
image: "traefik:v2.0.0-rc3"
|
image: "traefik:v2.1"
|
||||||
container_name: "traefik"
|
container_name: "traefik"
|
||||||
command:
|
command:
|
||||||
#- "--log.level=DEBUG"
|
#- "--log.level=DEBUG"
|
||||||
|
@ -12,11 +12,11 @@ services:
|
||||||
- "--providers.docker.exposedbydefault=false"
|
- "--providers.docker.exposedbydefault=false"
|
||||||
- "--entrypoints.web.address=:80"
|
- "--entrypoints.web.address=:80"
|
||||||
- "--entrypoints.websecure.address=:443"
|
- "--entrypoints.websecure.address=:443"
|
||||||
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge=true"
|
- "--certificatesresolvers.myresolver.acme.dnschallenge=true"
|
||||||
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge.provider=ovh"
|
- "--certificatesresolvers.myresolver.acme.dnschallenge.provider=ovh"
|
||||||
#- "--certificatesresolvers.mydnschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
- "--certificatesresolvers.mydnschallenge.acme.email=postmaster@mydomain.com"
|
- "--certificatesresolvers.myresolver.acme.email=postmaster@mydomain.com"
|
||||||
- "--certificatesresolvers.mydnschallenge.acme.storage=/letsencrypt/acme.json"
|
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "80:80"
|
||||||
- "443:443"
|
- "443:443"
|
||||||
|
@ -37,4 +37,4 @@ services:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
||||||
- "traefik.http.routers.whoami.entrypoints=websecure"
|
- "traefik.http.routers.whoami.entrypoints=websecure"
|
||||||
- "traefik.http.routers.whoami.tls.certresolver=mydnschallenge"
|
- "traefik.http.routers.whoami.tls.certresolver=myresolver"
|
||||||
|
|
|
@ -13,7 +13,7 @@ secrets:
|
||||||
services:
|
services:
|
||||||
|
|
||||||
traefik:
|
traefik:
|
||||||
image: "traefik:v2.0.0-rc3"
|
image: "traefik:v2.1"
|
||||||
container_name: "traefik"
|
container_name: "traefik"
|
||||||
command:
|
command:
|
||||||
#- "--log.level=DEBUG"
|
#- "--log.level=DEBUG"
|
||||||
|
@ -22,11 +22,11 @@ services:
|
||||||
- "--providers.docker.exposedbydefault=false"
|
- "--providers.docker.exposedbydefault=false"
|
||||||
- "--entrypoints.web.address=:80"
|
- "--entrypoints.web.address=:80"
|
||||||
- "--entrypoints.websecure.address=:443"
|
- "--entrypoints.websecure.address=:443"
|
||||||
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge=true"
|
- "--certificatesresolvers.myresolver.acme.dnschallenge=true"
|
||||||
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge.provider=ovh"
|
- "--certificatesresolvers.myresolver.acme.dnschallenge.provider=ovh"
|
||||||
#- "--certificatesresolvers.mydnschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
- "--certificatesresolvers.mydnschallenge.acme.email=postmaster@mydomain.com"
|
- "--certificatesresolvers.myresolver.acme.email=postmaster@mydomain.com"
|
||||||
- "--certificatesresolvers.mydnschallenge.acme.storage=/letsencrypt/acme.json"
|
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "80:80"
|
||||||
- "443:443"
|
- "443:443"
|
||||||
|
@ -52,4 +52,4 @@ services:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
||||||
- "traefik.http.routers.whoami.entrypoints=websecure"
|
- "traefik.http.routers.whoami.entrypoints=websecure"
|
||||||
- "traefik.http.routers.whoami.tls.certresolver=mydnschallenge"
|
- "traefik.http.routers.whoami.tls.certresolver=myresolver"
|
||||||
|
|
|
@ -7,7 +7,7 @@ Please also read the [basic example](../basic-example) for details on how to exp
|
||||||
|
|
||||||
For the DNS challenge, you'll need:
|
For the DNS challenge, you'll need:
|
||||||
|
|
||||||
- A working [provider](https://docs.traefik.io/v2.0/https/acme/#providers) along with the credentials allowing to create and remove DNS records.
|
- A working [provider](../../../https/acme.md#providers) along with the credentials allowing to create and remove DNS records.
|
||||||
|
|
||||||
!!! info "Variables may vary depending on the Provider."
|
!!! info "Variables may vary depending on the Provider."
|
||||||
Please note this guide may vary depending on the provider you use.
|
Please note this guide may vary depending on the provider you use.
|
||||||
|
@ -32,13 +32,13 @@ For the DNS challenge, you'll need:
|
||||||
- "OVH_CONSUMER_KEY=[YOUR_OWN_VALUE]"
|
- "OVH_CONSUMER_KEY=[YOUR_OWN_VALUE]"
|
||||||
```
|
```
|
||||||
|
|
||||||
- Replace `postmaster@mydomain.com` by your **own email** within the `certificatesresolvers.mydnschallenge.acme.email` command line argument of the `traefik` service.
|
- Replace `postmaster@mydomain.com` by your **own email** within the `certificatesresolvers.myresolver.acme.email` command line argument of the `traefik` service.
|
||||||
- Replace `whoami.mydomain.com` by your **own domain** within the `traefik.http.routers.whoami.rule` label of the `whoami` service.
|
- Replace `whoami.mydomain.com` by your **own domain** within the `traefik.http.routers.whoami.rule` label of the `whoami` service.
|
||||||
- Optionally uncomment the following lines if you want to test/debug:
|
- Optionally uncomment the following lines if you want to test/debug:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
#- "--log.level=DEBUG"
|
#- "--log.level=DEBUG"
|
||||||
#- "--certificatesresolvers.mydnschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
```
|
```
|
||||||
|
|
||||||
- Run `docker-compose up -d` within the folder where you created the previous file.
|
- Run `docker-compose up -d` within the folder where you created the previous file.
|
||||||
|
@ -68,12 +68,12 @@ ports:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
command:
|
command:
|
||||||
# Enable a dns challenge named "mydnschallenge"
|
# Enable a dns challenge named "myresolver"
|
||||||
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge=true"
|
- "--certificatesresolvers.myresolver.acme.dnschallenge=true"
|
||||||
# Tell which provider to use
|
# Tell which provider to use
|
||||||
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge.provider=ovh"
|
- "--certificatesresolvers.myresolver.acme.dnschallenge.provider=ovh"
|
||||||
# The email to provide to let's encrypt
|
# The email to provide to let's encrypt
|
||||||
- "--certificatesresolvers.mydnschallenge.acme.email=postmaster@mydomain.com"
|
- "--certificatesresolvers.myresolver.acme.email=postmaster@mydomain.com"
|
||||||
```
|
```
|
||||||
|
|
||||||
- We provide the required configuration to our provider via environment variables:
|
- We provide the required configuration to our provider via environment variables:
|
||||||
|
@ -101,14 +101,14 @@ volumes:
|
||||||
|
|
||||||
command:
|
command:
|
||||||
# Tell to store the certificate on a path under our volume
|
# Tell to store the certificate on a path under our volume
|
||||||
- "--certificatesresolvers.mydnschallenge.acme.storage=/letsencrypt/acme.json"
|
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
|
||||||
```
|
```
|
||||||
|
|
||||||
- We configure the `whoami` service to tell Traefik to use the certificate resolver named `mydnschallenge` we just configured:
|
- We configure the `whoami` service to tell Traefik to use the certificate resolver named `myresolver` we just configured:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
labels:
|
labels:
|
||||||
- "traefik.http.routers.whoami.tls.certresolver=mydnschallenge" # Uses the Host rule to define which certificate to issue
|
- "traefik.http.routers.whoami.tls.certresolver=myresolver" # Uses the Host rule to define which certificate to issue
|
||||||
```
|
```
|
||||||
|
|
||||||
## Use Secrets
|
## Use Secrets
|
||||||
|
|
|
@ -3,7 +3,7 @@ version: "3.3"
|
||||||
services:
|
services:
|
||||||
|
|
||||||
traefik:
|
traefik:
|
||||||
image: "traefik:v2.0.0-rc3"
|
image: "traefik:v2.1"
|
||||||
container_name: "traefik"
|
container_name: "traefik"
|
||||||
command:
|
command:
|
||||||
#- "--log.level=DEBUG"
|
#- "--log.level=DEBUG"
|
||||||
|
@ -12,11 +12,11 @@ services:
|
||||||
- "--providers.docker.exposedbydefault=false"
|
- "--providers.docker.exposedbydefault=false"
|
||||||
- "--entrypoints.web.address=:80"
|
- "--entrypoints.web.address=:80"
|
||||||
- "--entrypoints.websecure.address=:443"
|
- "--entrypoints.websecure.address=:443"
|
||||||
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true"
|
- "--certificatesresolvers.myresolver.acme.httpchallenge=true"
|
||||||
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web"
|
- "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
|
||||||
#- "--certificatesresolvers.myhttpchallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
- "--certificatesresolvers.myhttpchallenge.acme.email=postmaster@mydomain.com"
|
- "--certificatesresolvers.myresolver.acme.email=postmaster@mydomain.com"
|
||||||
- "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json"
|
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "80:80"
|
||||||
- "443:443"
|
- "443:443"
|
||||||
|
@ -32,4 +32,4 @@ services:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
||||||
- "traefik.http.routers.whoami.entrypoints=websecure"
|
- "traefik.http.routers.whoami.entrypoints=websecure"
|
||||||
- "traefik.http.routers.whoami.tls.certresolver=myhttpchallenge"
|
- "traefik.http.routers.whoami.tls.certresolver=myresolver"
|
||||||
|
|
|
@ -18,13 +18,13 @@ For the HTTP challenge you will need:
|
||||||
--8<-- "content/user-guides/docker-compose/acme-http/docker-compose.yml"
|
--8<-- "content/user-guides/docker-compose/acme-http/docker-compose.yml"
|
||||||
```
|
```
|
||||||
|
|
||||||
- Replace `postmaster@mydomain.com` by your **own email** within the `certificatesresolvers.myhttpchallenge.acme.email` command line argument of the `traefik` service.
|
- Replace `postmaster@mydomain.com` by your **own email** within the `certificatesresolvers.myresolver.acme.email` command line argument of the `traefik` service.
|
||||||
- Replace `whoami.mydomain.com` by your **own domain** within the `traefik.http.routers.whoami.rule` label of the `whoami` service.
|
- Replace `whoami.mydomain.com` by your **own domain** within the `traefik.http.routers.whoami.rule` label of the `whoami` service.
|
||||||
- Optionally uncomment the following lines if you want to test/debug:
|
- Optionally uncomment the following lines if you want to test/debug:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
#- "--log.level=DEBUG"
|
#- "--log.level=DEBUG"
|
||||||
#- "--certificatesresolvers.myhttpchallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
```
|
```
|
||||||
|
|
||||||
- Run `docker-compose up -d` within the folder where you created the previous file.
|
- Run `docker-compose up -d` within the folder where you created the previous file.
|
||||||
|
@ -54,12 +54,12 @@ ports:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
command:
|
command:
|
||||||
# Enable a http challenge named "myhttpchallenge"
|
# Enable a http challenge named "myresolver"
|
||||||
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true"
|
- "--certificatesresolvers.myresolver.acme.httpchallenge=true"
|
||||||
# Tell it to use our predefined entrypoint named "web"
|
# Tell it to use our predefined entrypoint named "web"
|
||||||
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web"
|
- "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
|
||||||
# The email to provide to let's encrypt
|
# The email to provide to let's encrypt
|
||||||
- "--certificatesresolvers.myhttpchallenge.acme.email=postmaster@mydomain.com"
|
- "--certificatesresolvers.myresolver.acme.email=postmaster@mydomain.com"
|
||||||
```
|
```
|
||||||
|
|
||||||
- We add a volume to store our certificates:
|
- We add a volume to store our certificates:
|
||||||
|
@ -71,13 +71,13 @@ volumes:
|
||||||
|
|
||||||
command:
|
command:
|
||||||
# Tell to store the certificate on a path under our volume
|
# Tell to store the certificate on a path under our volume
|
||||||
- "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json"
|
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
|
||||||
```
|
```
|
||||||
|
|
||||||
- We configure the `whoami` service to tell Traefik to use the certificate resolver named `myhttpchallenge` we just configured:
|
- We configure the `whoami` service to tell Traefik to use the certificate resolver named `myresolver` we just configured:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
labels:
|
labels:
|
||||||
# Uses the Host rule to define which certificate to issue
|
# Uses the Host rule to define which certificate to issue
|
||||||
- "traefik.http.routers.whoami.tls.certresolver=myhttpchallenge"
|
- "traefik.http.routers.whoami.tls.certresolver=myresolver"
|
||||||
```
|
```
|
|
@ -3,7 +3,7 @@ version: "3.3"
|
||||||
services:
|
services:
|
||||||
|
|
||||||
traefik:
|
traefik:
|
||||||
image: "traefik:v2.0.0-rc3"
|
image: "traefik:v2.1"
|
||||||
container_name: "traefik"
|
container_name: "traefik"
|
||||||
command:
|
command:
|
||||||
#- "--log.level=DEBUG"
|
#- "--log.level=DEBUG"
|
||||||
|
@ -11,10 +11,10 @@ services:
|
||||||
- "--providers.docker=true"
|
- "--providers.docker=true"
|
||||||
- "--providers.docker.exposedbydefault=false"
|
- "--providers.docker.exposedbydefault=false"
|
||||||
- "--entrypoints.websecure.address=:443"
|
- "--entrypoints.websecure.address=:443"
|
||||||
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
|
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
|
||||||
#- "--certificatesresolvers.mytlschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
- "--certificatesresolvers.mytlschallenge.acme.email=postmaster@mydomain.com"
|
- "--certificatesresolvers.myresolver.acme.email=postmaster@mydomain.com"
|
||||||
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
|
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
|
||||||
ports:
|
ports:
|
||||||
- "443:443"
|
- "443:443"
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
|
@ -29,4 +29,4 @@ services:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
||||||
- "traefik.http.routers.whoami.entrypoints=websecure"
|
- "traefik.http.routers.whoami.entrypoints=websecure"
|
||||||
- "traefik.http.routers.whoami.tls.certresolver=mytlschallenge"
|
- "traefik.http.routers.whoami.tls.certresolver=myresolver"
|
||||||
|
|
|
@ -18,13 +18,13 @@ For the TLS challenge you will need:
|
||||||
--8<-- "content/user-guides/docker-compose/acme-tls/docker-compose.yml"
|
--8<-- "content/user-guides/docker-compose/acme-tls/docker-compose.yml"
|
||||||
```
|
```
|
||||||
|
|
||||||
- Replace `postmaster@mydomain.com` by your **own email** within the `certificatesresolvers.mytlschallenge.acme.email` command line argument of the `traefik` service.
|
- Replace `postmaster@mydomain.com` by your **own email** within the `certificatesresolvers.myresolver.acme.email` command line argument of the `traefik` service.
|
||||||
- Replace `whoami.mydomain.com` by your **own domain** within the `traefik.http.routers.whoami.rule` label of the `whoami` service.
|
- Replace `whoami.mydomain.com` by your **own domain** within the `traefik.http.routers.whoami.rule` label of the `whoami` service.
|
||||||
- Optionally uncomment the following lines if you want to test/debug:
|
- Optionally uncomment the following lines if you want to test/debug:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
#- "--log.level=DEBUG"
|
#- "--log.level=DEBUG"
|
||||||
#- "--certificatesresolvers.mytlschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
```
|
```
|
||||||
|
|
||||||
- Run `docker-compose up -d` within the folder where you created the previous file.
|
- Run `docker-compose up -d` within the folder where you created the previous file.
|
||||||
|
@ -54,8 +54,8 @@ ports:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
command:
|
command:
|
||||||
# Enable a tls challenge named "mytlschallenge"
|
# Enable a tls challenge named "myresolver"
|
||||||
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
|
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
|
||||||
```
|
```
|
||||||
|
|
||||||
- We add a volume to store our certificates:
|
- We add a volume to store our certificates:
|
||||||
|
@ -67,13 +67,13 @@ volumes:
|
||||||
|
|
||||||
command:
|
command:
|
||||||
# Tell to store the certificate on a path under our volume
|
# Tell to store the certificate on a path under our volume
|
||||||
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
|
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
|
||||||
```
|
```
|
||||||
|
|
||||||
- We configure the `whoami` service to tell Traefik to use the certificate resolver named `mytlschallenge` we just configured:
|
- We configure the `whoami` service to tell Traefik to use the certificate resolver named `myresolver` we just configured:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
labels:
|
labels:
|
||||||
# Uses the Host rule to define which certificate to issue
|
# Uses the Host rule to define which certificate to issue
|
||||||
- "traefik.http.routers.whoami.tls.certresolver=mytlschallenge"
|
- "traefik.http.routers.whoami.tls.certresolver=myresolver"
|
||||||
```
|
```
|
||||||
|
|
|
@ -3,7 +3,7 @@ version: "3.3"
|
||||||
services:
|
services:
|
||||||
|
|
||||||
traefik:
|
traefik:
|
||||||
image: "traefik:v2.0.0-rc3"
|
image: "traefik:v2.1"
|
||||||
container_name: "traefik"
|
container_name: "traefik"
|
||||||
command:
|
command:
|
||||||
#- "--log.level=DEBUG"
|
#- "--log.level=DEBUG"
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -16,7 +16,7 @@ require (
|
||||||
github.com/abbot/go-http-auth v0.0.0-00010101000000-000000000000
|
github.com/abbot/go-http-auth v0.0.0-00010101000000-000000000000
|
||||||
github.com/abronan/valkeyrie v0.0.0-20200127174252-ef4277a138cd
|
github.com/abronan/valkeyrie v0.0.0-20200127174252-ef4277a138cd
|
||||||
github.com/c0va23/go-proxyprotocol v0.9.1
|
github.com/c0va23/go-proxyprotocol v0.9.1
|
||||||
github.com/cenkalti/backoff/v3 v3.2.2
|
github.com/cenkalti/backoff/v4 v4.0.0
|
||||||
github.com/containerd/containerd v1.3.2 // indirect
|
github.com/containerd/containerd v1.3.2 // indirect
|
||||||
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd
|
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd
|
||||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
||||||
|
@ -36,7 +36,7 @@ require (
|
||||||
github.com/fatih/structs v1.1.0
|
github.com/fatih/structs v1.1.0
|
||||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
|
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
|
||||||
github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2
|
github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2
|
||||||
github.com/go-acme/lego/v3 v3.3.0
|
github.com/go-acme/lego/v3 v3.4.0
|
||||||
github.com/go-check/check v0.0.0-00010101000000-000000000000
|
github.com/go-check/check v0.0.0-00010101000000-000000000000
|
||||||
github.com/go-kit/kit v0.9.0
|
github.com/go-kit/kit v0.9.0
|
||||||
github.com/gogo/protobuf v1.3.0 // indirect
|
github.com/gogo/protobuf v1.3.0 // indirect
|
||||||
|
|
14
go.sum
14
go.sum
|
@ -119,10 +119,8 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
|
||||||
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/c0va23/go-proxyprotocol v0.9.1 h1:5BCkp0fDJOhzzH1lhjUgHhmZz9VvRMMif1U2D31hb34=
|
github.com/c0va23/go-proxyprotocol v0.9.1 h1:5BCkp0fDJOhzzH1lhjUgHhmZz9VvRMMif1U2D31hb34=
|
||||||
github.com/c0va23/go-proxyprotocol v0.9.1/go.mod h1:TNjUV+llvk8TvWJxlPYAeAYZgSzT/iicNr3nWBWX320=
|
github.com/c0va23/go-proxyprotocol v0.9.1/go.mod h1:TNjUV+llvk8TvWJxlPYAeAYZgSzT/iicNr3nWBWX320=
|
||||||
github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c=
|
github.com/cenkalti/backoff/v4 v4.0.0 h1:6VeaLF9aI+MAUQ95106HwWzYZgJJpZ4stumjj6RFYAU=
|
||||||
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
|
github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
|
||||||
github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M=
|
|
||||||
github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
|
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4=
|
github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||||
|
@ -248,8 +246,8 @@ github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2/go.mod h1:GLy
|
||||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-acme/lego/v3 v3.3.0 h1:6BePZsOiYA4/w+M7QDytxQtMfCipMPGnWAHs9pWks98=
|
github.com/go-acme/lego/v3 v3.4.0 h1:deB9NkelA+TfjGHVw8J7iKl/rMtffcGMWSMmptvMv0A=
|
||||||
github.com/go-acme/lego/v3 v3.3.0/go.mod h1:iGSY2vQrvQs3WezicSB/oVbO2eCrD88dpWPwb1qLqu0=
|
github.com/go-acme/lego/v3 v3.4.0/go.mod h1:xYbLDuxq3Hy4bMUT1t9JIuz6GWIWb3m5X+TeTHYaT7M=
|
||||||
github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=
|
github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=
|
||||||
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||||
|
@ -535,8 +533,8 @@ github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy
|
||||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||||
github.com/nrdcg/auroradns v1.0.0 h1:b+NpSqNG6HzMqX2ohGQe4Q/G0WQq8pduWCiZ19vdLY8=
|
github.com/nrdcg/auroradns v1.0.0 h1:b+NpSqNG6HzMqX2ohGQe4Q/G0WQq8pduWCiZ19vdLY8=
|
||||||
github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/HzqidhOhjw=
|
github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/HzqidhOhjw=
|
||||||
github.com/nrdcg/dnspod-go v0.3.0 h1:EbYggdEGFGq17Vp7sUwd9PyHZv5mMxJwX7nBPukKNoU=
|
github.com/nrdcg/dnspod-go v0.4.0 h1:c/jn1mLZNKF3/osJ6mz3QPxTudvPArXTjpkmYj0uK6U=
|
||||||
github.com/nrdcg/dnspod-go v0.3.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ=
|
github.com/nrdcg/dnspod-go v0.4.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ=
|
||||||
github.com/nrdcg/goinwx v0.6.1 h1:AJnjoWPELyCtofhGcmzzcEMFd9YdF2JB/LgutWsWt/s=
|
github.com/nrdcg/goinwx v0.6.1 h1:AJnjoWPELyCtofhGcmzzcEMFd9YdF2JB/LgutWsWt/s=
|
||||||
github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ=
|
github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ=
|
||||||
github.com/nrdcg/namesilo v0.2.1 h1:kLjCjsufdW/IlC+iSfAqj0iQGgKjlbUUeDJio5Y6eMg=
|
github.com/nrdcg/namesilo v0.2.1 h1:kLjCjsufdW/IlC+iSfAqj0iQGgKjlbUUeDJio5Y6eMg=
|
||||||
|
|
|
@ -128,7 +128,18 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
req.Host = "whoami"
|
req.Host = "whoami"
|
||||||
|
|
||||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("Hostname: whoami1", "Hostname: whoami2", "Hostname: whoami3"))
|
err = try.Request(req, 2*time.Second,
|
||||||
|
try.StatusCodeIs(200),
|
||||||
|
try.BodyContainsOr("Hostname: whoami1", "Hostname: whoami2", "Hostname: whoami3"))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||||
|
try.StatusCodeIs(200),
|
||||||
|
try.BodyContains(
|
||||||
|
fmt.Sprintf(`"http://%s:80":"UP"`, reg1.Address),
|
||||||
|
fmt.Sprintf(`"http://%s:80":"UP"`, reg2.Address),
|
||||||
|
fmt.Sprintf(`"http://%s:80":"UP"`, reg3.Address),
|
||||||
|
))
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
err = s.deregisterService("whoami1", false)
|
err = s.deregisterService("whoami1", false)
|
||||||
|
|
|
@ -483,6 +483,11 @@ func (in *Headers) DeepCopy() *Headers {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *HealthCheck) DeepCopyInto(out *HealthCheck) {
|
func (in *HealthCheck) DeepCopyInto(out *HealthCheck) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
if in.FollowRedirects != nil {
|
||||||
|
in, out := &in.FollowRedirects, &out.FollowRedirects
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
if in.Headers != nil {
|
if in.Headers != nil {
|
||||||
in, out := &in.Headers, &out.Headers
|
in, out := &in.Headers, &out.Headers
|
||||||
*out = make(map[string]string, len(*in))
|
*out = make(map[string]string, len(*in))
|
||||||
|
|
|
@ -3,7 +3,7 @@ package job
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v3"
|
"github.com/cenkalti/backoff/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v3"
|
"github.com/cenkalti/backoff/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestJobBackOff(t *testing.T) {
|
func TestJobBackOff(t *testing.T) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v3"
|
"github.com/cenkalti/backoff/v4"
|
||||||
"github.com/containous/traefik/v2/pkg/log"
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/safe"
|
"github.com/containous/traefik/v2/pkg/safe"
|
||||||
"github.com/go-acme/lego/v3/challenge"
|
"github.com/go-acme/lego/v3/challenge"
|
||||||
|
|
|
@ -184,15 +184,19 @@ func (p *Provider) addServerTCP(ctx context.Context, item itemData, loadBalancer
|
||||||
return errors.New("load-balancer is not defined")
|
return errors.New("load-balancer is not defined")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var port string
|
||||||
|
if len(loadBalancer.Servers) > 0 {
|
||||||
|
port = loadBalancer.Servers[0].Port
|
||||||
|
}
|
||||||
|
|
||||||
if len(loadBalancer.Servers) == 0 {
|
if len(loadBalancer.Servers) == 0 {
|
||||||
loadBalancer.Servers = []dynamic.TCPServer{{}}
|
loadBalancer.Servers = []dynamic.TCPServer{{}}
|
||||||
}
|
}
|
||||||
|
|
||||||
var port string
|
if item.Port != "" && port == "" {
|
||||||
if item.Port != "" {
|
|
||||||
port = item.Port
|
port = item.Port
|
||||||
loadBalancer.Servers[0].Port = ""
|
|
||||||
}
|
}
|
||||||
|
loadBalancer.Servers[0].Port = ""
|
||||||
|
|
||||||
if port == "" {
|
if port == "" {
|
||||||
return errors.New("port is missing")
|
return errors.New("port is missing")
|
||||||
|
@ -250,10 +254,10 @@ func (p *Provider) addServer(ctx context.Context, item itemData, loadBalancer *d
|
||||||
loadBalancer.Servers = []dynamic.Server{server}
|
loadBalancer.Servers = []dynamic.Server{server}
|
||||||
}
|
}
|
||||||
|
|
||||||
if item.Port != "" {
|
if item.Port != "" && port == "" {
|
||||||
port = item.Port
|
port = item.Port
|
||||||
loadBalancer.Servers[0].Port = ""
|
|
||||||
}
|
}
|
||||||
|
loadBalancer.Servers[0].Port = ""
|
||||||
|
|
||||||
if port == "" {
|
if port == "" {
|
||||||
return errors.New("port is missing")
|
return errors.New("port is missing")
|
||||||
|
|
|
@ -1479,7 +1479,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "h2c://127.0.0.1:80",
|
URL: "h2c://127.0.0.1:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: Bool(true),
|
||||||
|
@ -1531,7 +1531,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: Bool(true),
|
||||||
|
|
|
@ -4,14 +4,16 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v3"
|
"github.com/cenkalti/backoff/v4"
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/containous/traefik/v2/pkg/job"
|
"github.com/containous/traefik/v2/pkg/job"
|
||||||
"github.com/containous/traefik/v2/pkg/log"
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/provider"
|
"github.com/containous/traefik/v2/pkg/provider"
|
||||||
|
"github.com/containous/traefik/v2/pkg/provider/constraints"
|
||||||
"github.com/containous/traefik/v2/pkg/safe"
|
"github.com/containous/traefik/v2/pkg/safe"
|
||||||
"github.com/containous/traefik/v2/pkg/types"
|
"github.com/containous/traefik/v2/pkg/types"
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/api"
|
||||||
|
@ -151,7 +153,7 @@ func (p *Provider) getConsulServicesData(ctx context.Context) ([]itemData, error
|
||||||
}
|
}
|
||||||
|
|
||||||
var data []itemData
|
var data []itemData
|
||||||
for name := range consulServiceNames {
|
for _, name := range consulServiceNames {
|
||||||
consulServices, healthServices, err := p.fetchService(ctx, name)
|
consulServices, healthServices, err := p.fetchService(ctx, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -204,10 +206,55 @@ func (p *Provider) fetchService(ctx context.Context, name string) ([]*api.Catalo
|
||||||
return consulServices, healthServices, err
|
return consulServices, healthServices, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) fetchServices(ctx context.Context) (map[string][]string, error) {
|
func (p *Provider) fetchServices(ctx context.Context) ([]string, error) {
|
||||||
|
// The query option "Filter" is not supported by /catalog/services.
|
||||||
|
// https://www.consul.io/api/catalog.html#list-services
|
||||||
opts := &api.QueryOptions{AllowStale: p.Stale, RequireConsistent: p.RequireConsistent, UseCache: p.Cache}
|
opts := &api.QueryOptions{AllowStale: p.Stale, RequireConsistent: p.RequireConsistent, UseCache: p.Cache}
|
||||||
serviceNames, _, err := p.client.Catalog().Services(opts)
|
serviceNames, _, err := p.client.Catalog().Services(opts)
|
||||||
return serviceNames, err
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The keys are the service names, and the array values provide all known tags for a given service.
|
||||||
|
// https://www.consul.io/api/catalog.html#list-services
|
||||||
|
var filtered []string
|
||||||
|
for svcName, tags := range serviceNames {
|
||||||
|
logger := log.FromContext(log.With(ctx, log.Str("serviceName", svcName)))
|
||||||
|
|
||||||
|
if !p.ExposedByDefault && !contains(tags, p.Prefix+".enable=true") {
|
||||||
|
logger.Debug("Filtering disabled item")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if contains(tags, p.Prefix+".enable=false") {
|
||||||
|
logger.Debug("Filtering disabled item")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
matches, err := constraints.MatchTags(tags, p.Constraints)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Error matching constraints expression: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !matches {
|
||||||
|
logger.Debugf("Container pruned by constraint expression: %q", p.Constraints)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
filtered = append(filtered, svcName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func contains(values []string, val string) bool {
|
||||||
|
for _, value := range values {
|
||||||
|
if strings.EqualFold(value, val) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func createClient(cfg *EndpointConfig) (*api.Client, error) {
|
func createClient(cfg *EndpointConfig) (*api.Client, error) {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v3"
|
"github.com/cenkalti/backoff/v4"
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/containous/traefik/v2/pkg/job"
|
"github.com/containous/traefik/v2/pkg/job"
|
||||||
"github.com/containous/traefik/v2/pkg/log"
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
|
|
|
@ -110,6 +110,19 @@ func (p *Provider) addWatcher(pool *safe.Pool, directory string, configurationCh
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
case evt := <-watcher.Events:
|
case evt := <-watcher.Events:
|
||||||
|
if evt.Op == fsnotify.Remove {
|
||||||
|
err = watcher.Remove(evt.Name)
|
||||||
|
if err != nil {
|
||||||
|
log.WithoutContext().WithField(log.ProviderName, providerName).
|
||||||
|
Errorf("Could not remove watcher for %s: %s", directory, err)
|
||||||
|
}
|
||||||
|
err = watcher.Add(directory)
|
||||||
|
if err != nil {
|
||||||
|
log.WithoutContext().WithField(log.ProviderName, providerName).
|
||||||
|
Errorf("Could not re-add watcher for %s: %s", directory, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if p.Directory == "" {
|
if p.Directory == "" {
|
||||||
_, evtFileName := filepath.Split(evt.Name)
|
_, evtFileName := filepath.Split(evt.Name)
|
||||||
_, confFileName := filepath.Split(p.Filename)
|
_, confFileName := filepath.Split(p.Filename)
|
||||||
|
|
|
@ -169,6 +169,7 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
|
||||||
factoryKube.Extensions().V1beta1().Ingresses().Informer().AddEventHandler(eventHandler)
|
factoryKube.Extensions().V1beta1().Ingresses().Informer().AddEventHandler(eventHandler)
|
||||||
factoryKube.Core().V1().Services().Informer().AddEventHandler(eventHandler)
|
factoryKube.Core().V1().Services().Informer().AddEventHandler(eventHandler)
|
||||||
factoryKube.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler)
|
factoryKube.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler)
|
||||||
|
factoryKube.Core().V1().Secrets().Informer().AddEventHandler(eventHandler)
|
||||||
|
|
||||||
c.factoriesCrd[ns] = factoryCrd
|
c.factoriesCrd[ns] = factoryCrd
|
||||||
c.factoriesKube[ns] = factoryKube
|
c.factoriesKube[ns] = factoryKube
|
||||||
|
@ -193,15 +194,6 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not wait for the Secrets store to get synced since we cannot rely on
|
|
||||||
// users having granted RBAC permissions for this object.
|
|
||||||
// https://github.com/containous/traefik/issues/1784 should improve the
|
|
||||||
// situation here in the future.
|
|
||||||
for _, ns := range namespaces {
|
|
||||||
c.factoriesKube[ns].Core().V1().Secrets().Informer().AddEventHandler(eventHandler)
|
|
||||||
c.factoriesKube[ns].Start(stopCh)
|
|
||||||
}
|
|
||||||
|
|
||||||
return eventCh, nil
|
return eventCh, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v3"
|
"github.com/cenkalti/backoff/v4"
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/containous/traefik/v2/pkg/job"
|
"github.com/containous/traefik/v2/pkg/job"
|
||||||
"github.com/containous/traefik/v2/pkg/log"
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
|
|
|
@ -100,7 +100,7 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli
|
||||||
|
|
||||||
errBuild := cb.buildServicesLB(ctx, ingressRoute.Namespace, spec, serviceName, conf.Services)
|
errBuild := cb.buildServicesLB(ctx, ingressRoute.Namespace, spec, serviceName, conf.Services)
|
||||||
if errBuild != nil {
|
if errBuild != nil {
|
||||||
logger.Error(err)
|
logger.Error(errBuild)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else if len(route.Services) == 1 {
|
} else if len(route.Services) == 1 {
|
||||||
|
@ -307,9 +307,9 @@ func (c configBuilder) loadServers(fallbackNamespace string, svc v1alpha1.LoadBa
|
||||||
|
|
||||||
var servers []dynamic.Server
|
var servers []dynamic.Server
|
||||||
if service.Spec.Type == corev1.ServiceTypeExternalName {
|
if service.Spec.Type == corev1.ServiceTypeExternalName {
|
||||||
protocol := "http"
|
protocol, err := parseServiceProtocol(svc.Scheme, portSpec.Name, portSpec.Port)
|
||||||
if portSpec.Port == 443 || strings.HasPrefix(portSpec.Name, "https") {
|
if err != nil {
|
||||||
protocol = "https"
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return append(servers, dynamic.Server{
|
return append(servers, dynamic.Server{
|
||||||
|
@ -341,17 +341,9 @@ func (c configBuilder) loadServers(fallbackNamespace string, svc v1alpha1.LoadBa
|
||||||
return nil, fmt.Errorf("cannot define a port for %s/%s", namespace, sanitizedName)
|
return nil, fmt.Errorf("cannot define a port for %s/%s", namespace, sanitizedName)
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol := httpProtocol
|
protocol, err := parseServiceProtocol(svc.Scheme, portSpec.Name, portSpec.Port)
|
||||||
scheme := svc.Scheme
|
if err != nil {
|
||||||
switch scheme {
|
return nil, err
|
||||||
case httpProtocol, httpsProtocol, "h2c":
|
|
||||||
protocol = scheme
|
|
||||||
case "":
|
|
||||||
if portSpec.Port == 443 || strings.HasPrefix(portSpec.Name, httpsProtocol) {
|
|
||||||
protocol = httpsProtocol
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("invalid scheme %q specified", scheme)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, addr := range subset.Addresses {
|
for _, addr := range subset.Addresses {
|
||||||
|
@ -448,3 +440,19 @@ func getTLSHTTP(ctx context.Context, ingressRoute *v1alpha1.IngressRoute, k8sCli
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseServiceProtocol parses the scheme, port name, and number to determine the correct protocol.
|
||||||
|
// an error is returned if the scheme provided is invalid.
|
||||||
|
func parseServiceProtocol(providedScheme string, portName string, portNumber int32) (string, error) {
|
||||||
|
switch providedScheme {
|
||||||
|
case httpProtocol, httpsProtocol, "h2c":
|
||||||
|
return providedScheme, nil
|
||||||
|
case "":
|
||||||
|
if portNumber == 443 || strings.HasPrefix(portName, httpsProtocol) {
|
||||||
|
return httpsProtocol, nil
|
||||||
|
}
|
||||||
|
return httpProtocol, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("invalid scheme %q specified", providedScheme)
|
||||||
|
}
|
||||||
|
|
|
@ -3186,3 +3186,72 @@ func TestLoadIngressRouteUDPs(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseServiceProtocol(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
scheme string
|
||||||
|
portName string
|
||||||
|
portNumber int32
|
||||||
|
expected string
|
||||||
|
expectedError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "Empty scheme and name",
|
||||||
|
scheme: "",
|
||||||
|
portName: "",
|
||||||
|
portNumber: 1000,
|
||||||
|
expected: "http",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "h2c scheme and emptyname",
|
||||||
|
scheme: "h2c",
|
||||||
|
portName: "",
|
||||||
|
portNumber: 1000,
|
||||||
|
expected: "h2c",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "invalid scheme",
|
||||||
|
scheme: "foo",
|
||||||
|
portName: "",
|
||||||
|
portNumber: 1000,
|
||||||
|
expectedError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Empty scheme and https name",
|
||||||
|
scheme: "",
|
||||||
|
portName: "https-secure",
|
||||||
|
portNumber: 1000,
|
||||||
|
expected: "https",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Empty scheme and port number",
|
||||||
|
scheme: "",
|
||||||
|
portName: "",
|
||||||
|
portNumber: 443,
|
||||||
|
expected: "https",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "https scheme",
|
||||||
|
scheme: "https",
|
||||||
|
portName: "",
|
||||||
|
portNumber: 1000,
|
||||||
|
expected: "https",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
test := test
|
||||||
|
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
protocol, err := parseServiceProtocol(test.scheme, test.portName, test.portNumber)
|
||||||
|
if test.expectedError {
|
||||||
|
assert.Error(t, err)
|
||||||
|
} else {
|
||||||
|
assert.Equal(t, test.expected, protocol)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -138,6 +138,7 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
|
||||||
factory.Extensions().V1beta1().Ingresses().Informer().AddEventHandler(eventHandler)
|
factory.Extensions().V1beta1().Ingresses().Informer().AddEventHandler(eventHandler)
|
||||||
factory.Core().V1().Services().Informer().AddEventHandler(eventHandler)
|
factory.Core().V1().Services().Informer().AddEventHandler(eventHandler)
|
||||||
factory.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler)
|
factory.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler)
|
||||||
|
factory.Core().V1().Secrets().Informer().AddEventHandler(eventHandler)
|
||||||
c.factories[ns] = factory
|
c.factories[ns] = factory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,15 +154,6 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not wait for the Secrets store to get synced since we cannot rely on
|
|
||||||
// users having granted RBAC permissions for this object.
|
|
||||||
// https://github.com/containous/traefik/issues/1784 should improve the
|
|
||||||
// situation here in the future.
|
|
||||||
for _, ns := range namespaces {
|
|
||||||
c.factories[ns].Core().V1().Secrets().Informer().AddEventHandler(eventHandler)
|
|
||||||
c.factories[ns].Start(stopCh)
|
|
||||||
}
|
|
||||||
|
|
||||||
return eventCh, nil
|
return eventCh, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v3"
|
"github.com/cenkalti/backoff/v4"
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/containous/traefik/v2/pkg/job"
|
"github.com/containous/traefik/v2/pkg/job"
|
||||||
"github.com/containous/traefik/v2/pkg/log"
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
etcdv3 "github.com/abronan/valkeyrie/store/etcd/v3"
|
etcdv3 "github.com/abronan/valkeyrie/store/etcd/v3"
|
||||||
"github.com/abronan/valkeyrie/store/redis"
|
"github.com/abronan/valkeyrie/store/redis"
|
||||||
"github.com/abronan/valkeyrie/store/zookeeper"
|
"github.com/abronan/valkeyrie/store/zookeeper"
|
||||||
"github.com/cenkalti/backoff/v3"
|
"github.com/cenkalti/backoff/v4"
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/containous/traefik/v2/pkg/config/kv"
|
"github.com/containous/traefik/v2/pkg/config/kv"
|
||||||
"github.com/containous/traefik/v2/pkg/job"
|
"github.com/containous/traefik/v2/pkg/job"
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v3"
|
"github.com/cenkalti/backoff/v4"
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/containous/traefik/v2/pkg/job"
|
"github.com/containous/traefik/v2/pkg/job"
|
||||||
"github.com/containous/traefik/v2/pkg/log"
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v3"
|
"github.com/cenkalti/backoff/v4"
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/containous/traefik/v2/pkg/job"
|
"github.com/containous/traefik/v2/pkg/job"
|
||||||
"github.com/containous/traefik/v2/pkg/log"
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v3"
|
"github.com/cenkalti/backoff/v4"
|
||||||
"github.com/containous/traefik/v2/pkg/log"
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v3"
|
"github.com/cenkalti/backoff/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewPoolContext(t *testing.T) {
|
func TestNewPoolContext(t *testing.T) {
|
||||||
|
|
|
@ -143,8 +143,6 @@ func (c *ConfigurationWatcher) loadMessage(configMsg dynamic.Message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConfigurationWatcher) preLoadConfiguration(configMsg dynamic.Message) {
|
func (c *ConfigurationWatcher) preLoadConfiguration(configMsg dynamic.Message) {
|
||||||
currentConfigurations := c.currentConfigurations.Get().(dynamic.Configurations)
|
|
||||||
|
|
||||||
logger := log.WithoutContext().WithField(log.ProviderName, configMsg.ProviderName)
|
logger := log.WithoutContext().WithField(log.ProviderName, configMsg.ProviderName)
|
||||||
if log.GetLevel() == logrus.DebugLevel {
|
if log.GetLevel() == logrus.DebugLevel {
|
||||||
copyConf := configMsg.Configuration.DeepCopy()
|
copyConf := configMsg.Configuration.DeepCopy()
|
||||||
|
@ -172,11 +170,6 @@ func (c *ConfigurationWatcher) preLoadConfiguration(configMsg dynamic.Message) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if reflect.DeepEqual(currentConfigurations[configMsg.ProviderName], configMsg.Configuration) {
|
|
||||||
logger.Infof("Skipping same configuration for provider %s", configMsg.ProviderName)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
providerConfigUpdateCh, ok := c.providerConfigUpdateMap[configMsg.ProviderName]
|
providerConfigUpdateCh, ok := c.providerConfigUpdateMap[configMsg.ProviderName]
|
||||||
if !ok {
|
if !ok {
|
||||||
providerConfigUpdateCh = make(chan dynamic.Message)
|
providerConfigUpdateCh = make(chan dynamic.Message)
|
||||||
|
@ -211,11 +204,18 @@ func (c *ConfigurationWatcher) throttleProviderConfigReload(ctx context.Context,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var previousConfig dynamic.Message
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
case nextConfig := <-in:
|
case nextConfig := <-in:
|
||||||
|
if reflect.DeepEqual(previousConfig, nextConfig) {
|
||||||
|
logger := log.WithoutContext().WithField(log.ProviderName, nextConfig.ProviderName)
|
||||||
|
logger.Info("Skipping same configuration")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
previousConfig = nextConfig
|
||||||
ring.In() <- nextConfig
|
ring.In() <- nextConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,6 +179,70 @@ func TestListenProvidersSkipsSameConfigurationForProvider(t *testing.T) {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestListenProvidersDoesNotSkipFlappingConfiguration(t *testing.T) {
|
||||||
|
routinesPool := safe.NewPool(context.Background())
|
||||||
|
|
||||||
|
configuration := &dynamic.Configuration{
|
||||||
|
HTTP: th.BuildConfiguration(
|
||||||
|
th.WithRouters(th.WithRouter("foo")),
|
||||||
|
th.WithLoadBalancerServices(th.WithService("bar")),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
transientConfiguration := &dynamic.Configuration{
|
||||||
|
HTTP: th.BuildConfiguration(
|
||||||
|
th.WithRouters(th.WithRouter("bad")),
|
||||||
|
th.WithLoadBalancerServices(th.WithService("bad")),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
pvd := &mockProvider{
|
||||||
|
wait: 5 * time.Millisecond, // The last message needs to be received before the second has been fully processed
|
||||||
|
messages: []dynamic.Message{
|
||||||
|
{ProviderName: "mock", Configuration: configuration},
|
||||||
|
{ProviderName: "mock", Configuration: transientConfiguration},
|
||||||
|
{ProviderName: "mock", Configuration: configuration},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
watcher := NewConfigurationWatcher(routinesPool, pvd, 15*time.Millisecond)
|
||||||
|
|
||||||
|
var lastConfig dynamic.Configuration
|
||||||
|
watcher.AddListener(func(conf dynamic.Configuration) {
|
||||||
|
lastConfig = conf
|
||||||
|
})
|
||||||
|
|
||||||
|
watcher.Start()
|
||||||
|
defer watcher.Stop()
|
||||||
|
|
||||||
|
// give some time so that the configuration can be processed
|
||||||
|
time.Sleep(40 * time.Millisecond)
|
||||||
|
|
||||||
|
expected := dynamic.Configuration{
|
||||||
|
HTTP: th.BuildConfiguration(
|
||||||
|
th.WithRouters(th.WithRouter("foo@mock")),
|
||||||
|
th.WithLoadBalancerServices(th.WithService("bar@mock")),
|
||||||
|
th.WithMiddlewares(),
|
||||||
|
),
|
||||||
|
TCP: &dynamic.TCPConfiguration{
|
||||||
|
Routers: map[string]*dynamic.TCPRouter{},
|
||||||
|
Services: map[string]*dynamic.TCPService{},
|
||||||
|
},
|
||||||
|
UDP: &dynamic.UDPConfiguration{
|
||||||
|
Routers: map[string]*dynamic.UDPRouter{},
|
||||||
|
Services: map[string]*dynamic.UDPService{},
|
||||||
|
},
|
||||||
|
TLS: &dynamic.TLSConfiguration{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
|
"default": {},
|
||||||
|
},
|
||||||
|
Stores: map[string]tls.Store{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, expected, lastConfig)
|
||||||
|
}
|
||||||
|
|
||||||
func TestListenProvidersPublishesConfigForEachProvider(t *testing.T) {
|
func TestListenProvidersPublishesConfigForEachProvider(t *testing.T) {
|
||||||
routinesPool := safe.NewPool(context.Background())
|
routinesPool := safe.NewPool(context.Background())
|
||||||
|
|
||||||
|
|
|
@ -109,8 +109,6 @@ func (m *Manager) BuildHandlers(rootCtx context.Context, entryPoints []string, t
|
||||||
entryPointHandlers[entryPointName] = handlerWithMiddlewares
|
entryPointHandlers[entryPointName] = handlerWithMiddlewares
|
||||||
}
|
}
|
||||||
|
|
||||||
m.serviceManager.LaunchHealthCheck()
|
|
||||||
|
|
||||||
return entryPointHandlers
|
return entryPointHandlers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,8 @@ func (f *RouterFactory) CreateRouters(conf dynamic.Configuration) (map[string]*t
|
||||||
handlersNonTLS := routerManager.BuildHandlers(ctx, f.entryPointsTCP, false)
|
handlersNonTLS := routerManager.BuildHandlers(ctx, f.entryPointsTCP, false)
|
||||||
handlersTLS := routerManager.BuildHandlers(ctx, f.entryPointsTCP, true)
|
handlersTLS := routerManager.BuildHandlers(ctx, f.entryPointsTCP, true)
|
||||||
|
|
||||||
|
serviceManager.LaunchHealthCheck()
|
||||||
|
|
||||||
// TCP
|
// TCP
|
||||||
svcTCPManager := tcp.NewManager(rtConf)
|
svcTCPManager := tcp.NewManager(rtConf)
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,12 @@ func NewManagerFactory(staticConfiguration static.Configuration, routinesPool *s
|
||||||
factory.metricsHandler = metrics.PrometheusHandler()
|
factory.metricsHandler = metrics.PrometheusHandler()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This check is necessary because even when staticConfiguration.Ping == nil ,
|
||||||
|
// the affectation would make factory.pingHandle become a typed nil, which does not pass the nil test,
|
||||||
|
// and would break things elsewhere.
|
||||||
|
if staticConfiguration.Ping != nil {
|
||||||
factory.pingHandler = staticConfiguration.Ping
|
factory.pingHandler = staticConfiguration.Ping
|
||||||
|
}
|
||||||
|
|
||||||
return factory
|
return factory
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,9 +203,17 @@ func clientHelloServerName(br *bufio.Reader) (string, bool, string, error) {
|
||||||
return "", false, "", err
|
return "", false, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No valid TLS record has a type of 0x80, however SSLv2 handshakes
|
||||||
|
// start with a uint16 length where the MSB is set and the first record
|
||||||
|
// is always < 256 bytes long. Therefore typ == 0x80 strongly suggests
|
||||||
|
// an SSLv2 client.
|
||||||
|
const recordTypeSSLv2 = 0x80
|
||||||
const recordTypeHandshake = 0x16
|
const recordTypeHandshake = 0x16
|
||||||
if hdr[0] != recordTypeHandshake {
|
if hdr[0] != recordTypeHandshake {
|
||||||
// log.Errorf("Error not tls")
|
if hdr[0] == recordTypeSSLv2 {
|
||||||
|
// we consider SSLv2 as TLS and it will be refuse by real TLS handshake.
|
||||||
|
return "", true, getPeeked(br), nil
|
||||||
|
}
|
||||||
return "", false, getPeeked(br), nil // Not TLS.
|
return "", false, getPeeked(br), nil // Not TLS.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ var (
|
||||||
`VersionTLS13`: tls.VersionTLS13,
|
`VersionTLS13`: tls.VersionTLS13,
|
||||||
}
|
}
|
||||||
|
|
||||||
// MaxVersion Map of allowed TLS minimum versions
|
// MaxVersion Map of allowed TLS maximum versions
|
||||||
MaxVersion = map[string]uint16{
|
MaxVersion = map[string]uint16{
|
||||||
`VersionTLS10`: tls.VersionTLS10,
|
`VersionTLS10`: tls.VersionTLS10,
|
||||||
`VersionTLS11`: tls.VersionTLS11,
|
`VersionTLS11`: tls.VersionTLS11,
|
||||||
|
|
|
@ -26,7 +26,7 @@ type Config struct {
|
||||||
|
|
||||||
// SetDefaults sets the default values.
|
// SetDefaults sets the default values.
|
||||||
func (c *Config) SetDefaults() {
|
func (c *Config) SetDefaults() {
|
||||||
c.LocalAgentHost = "LocalAgentHost"
|
c.LocalAgentHost = "127.0.0.1"
|
||||||
c.LocalAgentPort = 35000
|
c.LocalAgentPort = 35000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue