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)
|
||||
[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(`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(`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)
|
||||
} else {
|
||||
logger.Info(`
|
||||
Stats collection is disabled.
|
||||
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
|
||||
|
||||
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).
|
||||
|
|
|
@ -9,11 +9,11 @@ You can install Traefik with the following flavors:
|
|||
|
||||
## 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
|
||||
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)
|
||||
|
@ -21,7 +21,7 @@ For more details, go to the [Docker provider documentation](../providers/docker.
|
|||
!!! tip
|
||||
|
||||
* 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).
|
||||
* Any orchestrator using docker images can fetch the official Traefik docker image.
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ version: '3'
|
|||
|
||||
services:
|
||||
reverse-proxy:
|
||||
# The official v2.0 Traefik docker image
|
||||
image: traefik:v2.0
|
||||
# The official v2 Traefik docker image
|
||||
image: traefik:v2.1
|
||||
# Enables the web UI and tells Traefik to listen to docker
|
||||
command: --api.insecure=true --providers.docker
|
||||
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).
|
||||
|
||||
!!! 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
|
||||
|
||||
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]
|
||||
address = ":443"
|
||||
|
||||
[certificatesResolvers.le.acme]
|
||||
[certificatesResolvers.myresolver.acme]
|
||||
email = "your-email@your-domain.org"
|
||||
storage = "acme.json"
|
||||
[certificatesResolvers.le.acme.httpChallenge]
|
||||
[certificatesResolvers.myresolver.acme.httpChallenge]
|
||||
# used during the challenge
|
||||
entryPoint = "web"
|
||||
```
|
||||
|
@ -76,7 +95,7 @@ Please check the [configuration examples below](#configuration-examples) for mor
|
|||
address: ":443"
|
||||
|
||||
certificatesResolvers:
|
||||
sample:
|
||||
myresolver:
|
||||
acme:
|
||||
email: your-email@your-domain.org
|
||||
storage: acme.json
|
||||
|
@ -89,31 +108,14 @@ Please check the [configuration examples below](#configuration-examples) for mor
|
|||
--entryPoints.web.address=:80
|
||||
--entryPoints.websecure.address=:443
|
||||
# ...
|
||||
--certificatesResolvers.le.acme.email=your-email@your-domain.org
|
||||
--certificatesResolvers.le.acme.storage=acme.json
|
||||
--certificatesResolvers.myresolver.acme.email=your-email@your-domain.org
|
||||
--certificatesResolvers.myresolver.acme.storage=acme.json
|
||||
# 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."
|
||||
|
||||
??? 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"
|
||||
|
||||
* 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`"
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[certificatesResolvers.le.acme]
|
||||
[certificatesResolvers.myresolver.acme]
|
||||
# ...
|
||||
[certificatesResolvers.le.acme.tlsChallenge]
|
||||
[certificatesResolvers.myresolver.acme.tlsChallenge]
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
certificatesResolvers:
|
||||
sample:
|
||||
myresolver:
|
||||
acme:
|
||||
# ...
|
||||
tlsChallenge: {}
|
||||
|
@ -179,7 +181,7 @@ when using the `TLS-ALPN-01` challenge, Traefik must be reachable by Let's Encry
|
|||
|
||||
```bash tab="CLI"
|
||||
# ...
|
||||
--certificatesResolvers.le.acme.tlsChallenge=true
|
||||
--certificatesResolvers.myresolver.acme.tlsChallenge=true
|
||||
```
|
||||
|
||||
### `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.
|
||||
|
||||
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`"
|
||||
|
||||
|
@ -199,9 +201,9 @@ when using the `HTTP-01` challenge, `certificatesResolvers.le.acme.httpChallenge
|
|||
[entryPoints.websecure]
|
||||
address = ":443"
|
||||
|
||||
[certificatesResolvers.le.acme]
|
||||
[certificatesResolvers.myresolver.acme]
|
||||
# ...
|
||||
[certificatesResolvers.le.acme.httpChallenge]
|
||||
[certificatesResolvers.myresolver.acme.httpChallenge]
|
||||
entryPoint = "web"
|
||||
```
|
||||
|
||||
|
@ -214,7 +216,7 @@ when using the `HTTP-01` challenge, `certificatesResolvers.le.acme.httpChallenge
|
|||
address: ":443"
|
||||
|
||||
certificatesResolvers:
|
||||
sample:
|
||||
myresolver:
|
||||
acme:
|
||||
# ...
|
||||
httpChallenge:
|
||||
|
@ -225,7 +227,7 @@ when using the `HTTP-01` challenge, `certificatesResolvers.le.acme.httpChallenge
|
|||
--entryPoints.web.address=:80
|
||||
--entryPoints.websecure.address=:443
|
||||
# ...
|
||||
--certificatesResolvers.le.acme.httpChallenge.entryPoint=web
|
||||
--certificatesResolvers.myresolver.acme.httpChallenge.entryPoint=web
|
||||
```
|
||||
|
||||
!!! 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"
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[certificatesResolvers.le.acme]
|
||||
[certificatesResolvers.myresolver.acme]
|
||||
# ...
|
||||
[certificatesResolvers.le.acme.dnsChallenge]
|
||||
[certificatesResolvers.myresolver.acme.dnsChallenge]
|
||||
provider = "digitalocean"
|
||||
delayBeforeCheck = 0
|
||||
# ...
|
||||
|
@ -248,7 +250,7 @@ Use the `DNS-01` challenge to generate and renew ACME certificates by provisioni
|
|||
|
||||
```yaml tab="File (YAML)"
|
||||
certificatesResolvers:
|
||||
sample:
|
||||
myresolver:
|
||||
acme:
|
||||
# ...
|
||||
dnsChallenge:
|
||||
|
@ -259,8 +261,8 @@ Use the `DNS-01` challenge to generate and renew ACME certificates by provisioni
|
|||
|
||||
```bash tab="CLI"
|
||||
# ...
|
||||
--certificatesResolvers.le.acme.dnsChallenge.provider=digitalocean
|
||||
--certificatesResolvers.le.acme.dnsChallenge.delayBeforeCheck=0
|
||||
--certificatesResolvers.myresolver.acme.dnsChallenge.provider=digitalocean
|
||||
--certificatesResolvers.myresolver.acme.dnsChallenge.delayBeforeCheck=0
|
||||
# ...
|
||||
```
|
||||
|
||||
|
@ -287,9 +289,10 @@ For example, `CF_API_EMAIL_FILE=/run/secrets/traefik_cf-api-email` could be used
|
|||
| [Blue Cat](https://www.bluecatnetworks.com/) | `bluecat` | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW` | [Additional configuration](https://go-acme.github.io/lego/dns/bluecat) |
|
||||
| [Checkdomain](https://www.checkdomain.de/) | `checkdomain` | `CHECKDOMAIN_TOKEN`, | [Additional configuration](https://go-acme.github.io/lego/dns/checkdomain/) |
|
||||
| [ClouDNS](https://www.cloudns.net/) | `cloudns` | `CLOUDNS_AUTH_ID`, `CLOUDNS_AUTH_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudns) |
|
||||
| [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) |
|
||||
| [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) |
|
||||
| [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) |
|
||||
|
@ -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) |
|
||||
| [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) |
|
||||
| [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) |
|
||||
| [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) |
|
||||
| [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) |
|
||||
|
@ -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.
|
||||
|
||||
```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"]
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
certificatesResolvers:
|
||||
sample:
|
||||
myresolver:
|
||||
acme:
|
||||
# ...
|
||||
dnsChallenge:
|
||||
|
@ -379,7 +384,7 @@ certificatesResolvers:
|
|||
|
||||
```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
|
||||
|
@ -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"
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[certificatesResolvers.le.acme]
|
||||
[certificatesResolvers.myresolver.acme]
|
||||
# ...
|
||||
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)"
|
||||
certificatesResolvers:
|
||||
sample:
|
||||
myresolver:
|
||||
acme:
|
||||
# ...
|
||||
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"
|
||||
# ...
|
||||
--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.
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[certificatesResolvers.le.acme]
|
||||
[certificatesResolvers.myresolver.acme]
|
||||
# ...
|
||||
storage = "acme.json"
|
||||
# ...
|
||||
|
@ -428,7 +433,7 @@ The `storage` option sets the location where your ACME certificates are saved to
|
|||
|
||||
```yaml tab="File (YAML)"
|
||||
certificatesResolvers:
|
||||
sample:
|
||||
myresolver:
|
||||
acme:
|
||||
# ...
|
||||
storage: acme.json
|
||||
|
@ -437,7 +442,7 @@ certificatesResolvers:
|
|||
|
||||
```bash tab="CLI"
|
||||
# ...
|
||||
--certificatesResolvers.le.acme.storage=acme.json
|
||||
--certificatesResolvers.myresolver.acme.storage=acme.json
|
||||
# ...
|
||||
```
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
labels:
|
||||
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||
- traefik.http.routers.blog.tls=true
|
||||
- traefik.http.routers.blog.tls.certresolver=le
|
||||
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||
- traefik.http.routers.blog.tls.domains[0].main=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.services.blog-svc.loadbalancer.server.port=8080"
|
||||
- traefik.http.routers.blog.tls=true
|
||||
- traefik.http.routers.blog.tls.certresolver=le
|
||||
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||
- traefik.http.routers.blog.tls.domains[0].main=company.org
|
||||
- traefik.http.routers.blog.tls.domains[0].sans=*.company.org
|
||||
```
|
||||
|
@ -36,14 +36,14 @@ spec:
|
|||
- name: blog
|
||||
port: 8080
|
||||
tls:
|
||||
certResolver: le
|
||||
certResolver: myresolver
|
||||
```
|
||||
|
||||
```json tab="Marathon"
|
||||
labels: {
|
||||
"traefik.http.routers.blog.rule": "Host(`company.com`) && Path(`/blog`)",
|
||||
"traefik.http.routers.blog.tls": "true",
|
||||
"traefik.http.routers.blog.tls.certresolver": "le",
|
||||
"traefik.http.routers.blog.tls.certresolver": "myresolver",
|
||||
"traefik.http.routers.blog.tls.domains[0].main": "company.com",
|
||||
"traefik.http.routers.blog.tls.domains[0].sans": "*.company.com",
|
||||
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
|
||||
|
@ -55,7 +55,7 @@ labels: {
|
|||
labels:
|
||||
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||
- traefik.http.routers.blog.tls=true
|
||||
- traefik.http.routers.blog.tls.certresolver=le
|
||||
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||
- traefik.http.routers.blog.tls.domains[0].main=company.org
|
||||
- traefik.http.routers.blog.tls.domains[0].sans=*.company.org
|
||||
```
|
||||
|
@ -66,7 +66,7 @@ labels:
|
|||
[http.routers.blog]
|
||||
rule = "Host(`company.com`) && Path(`/blog`)"
|
||||
[http.routers.blog.tls]
|
||||
certResolver = "le" # From static configuration
|
||||
certResolver = "myresolver" # From static configuration
|
||||
[[http.routers.blog.tls.domains]]
|
||||
main = "company.org"
|
||||
sans = ["*.company.org"]
|
||||
|
@ -79,7 +79,7 @@ http:
|
|||
blog:
|
||||
rule: "Host(`company.com`) && Path(`/blog`)"
|
||||
tls:
|
||||
certResolver: le
|
||||
certResolver: myresolver
|
||||
domains:
|
||||
- main: "company.org"
|
||||
sans:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
labels:
|
||||
- traefik.http.routers.blog.rule=(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)
|
||||
- traefik.http.routers.blog.tls=true
|
||||
- traefik.http.routers.blog.tls.certresolver=le
|
||||
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||
```
|
||||
|
||||
```yaml tab="Docker (Swarm)"
|
||||
|
@ -13,7 +13,7 @@ deploy:
|
|||
labels:
|
||||
- traefik.http.routers.blog.rule=(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)
|
||||
- traefik.http.routers.blog.tls=true
|
||||
- traefik.http.routers.blog.tls.certresolver=le
|
||||
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||
- traefik.http.services.blog-svc.loadbalancer.server.port=8080"
|
||||
```
|
||||
|
||||
|
@ -32,14 +32,14 @@ spec:
|
|||
- name: blog
|
||||
port: 8080
|
||||
tls:
|
||||
certresolver: le
|
||||
certresolver: myresolver
|
||||
```
|
||||
|
||||
```json tab="Marathon"
|
||||
labels: {
|
||||
"traefik.http.routers.blog.rule": "(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)",
|
||||
"traefik.http.routers.blog.tls": "true",
|
||||
"traefik.http.routers.blog.tls.certresolver": "le",
|
||||
"traefik.http.routers.blog.tls.certresolver": "myresolver",
|
||||
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
|
||||
}
|
||||
```
|
||||
|
@ -49,7 +49,7 @@ labels: {
|
|||
labels:
|
||||
- traefik.http.routers.blog.rule=(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)
|
||||
- traefik.http.routers.blog.tls=true
|
||||
- traefik.http.routers.blog.tls.certresolver=le
|
||||
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
|
@ -58,7 +58,7 @@ labels:
|
|||
[http.routers.blog]
|
||||
rule = "(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)"
|
||||
[http.routers.blog.tls]
|
||||
certResolver = "le"
|
||||
certResolver = "myresolver"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
|
@ -68,5 +68,5 @@ http:
|
|||
blog:
|
||||
rule: "(Host(`company.com`) && Path(`/blog`)) || Host(`blog.company.org`)"
|
||||
tls:
|
||||
certResolver: le
|
||||
certResolver: myresolver
|
||||
```
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
labels:
|
||||
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||
- traefik.http.routers.blog.tls=true
|
||||
- traefik.http.routers.blog.tls.certresolver=le
|
||||
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||
```
|
||||
|
||||
```yaml tab="Docker (Swarm)"
|
||||
|
@ -13,7 +13,7 @@ deploy:
|
|||
labels:
|
||||
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||
- traefik.http.routers.blog.tls=true
|
||||
- traefik.http.routers.blog.tls.certresolver=le
|
||||
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||
- traefik.http.services.blog-svc.loadbalancer.server.port=8080"
|
||||
```
|
||||
|
||||
|
@ -32,14 +32,14 @@ spec:
|
|||
- name: blog
|
||||
port: 8080
|
||||
tls:
|
||||
certresolver: le
|
||||
certresolver: myresolver
|
||||
```
|
||||
|
||||
```json tab="Marathon"
|
||||
labels: {
|
||||
"traefik.http.routers.blog.rule": "Host(`company.com`) && Path(`/blog`)",
|
||||
"traefik.http.routers.blog.tls": "true",
|
||||
"traefik.http.routers.blog.tls.certresolver": "le",
|
||||
"traefik.http.routers.blog.tls.certresolver": "myresolver",
|
||||
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
|
||||
}
|
||||
```
|
||||
|
@ -49,7 +49,7 @@ labels: {
|
|||
labels:
|
||||
- traefik.http.routers.blog.rule=Host(`company.com`) && Path(`/blog`)
|
||||
- traefik.http.routers.blog.tls=true
|
||||
- traefik.http.routers.blog.tls.certresolver=le
|
||||
- traefik.http.routers.blog.tls.certresolver=myresolver
|
||||
```
|
||||
|
||||
```toml tab="Single Domain"
|
||||
|
@ -58,7 +58,7 @@ labels:
|
|||
[http.routers.blog]
|
||||
rule = "Host(`company.com`) && Path(`/blog`)"
|
||||
[http.routers.blog.tls]
|
||||
certResolver = "le"
|
||||
certResolver = "myresolver"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
|
@ -68,5 +68,5 @@ http:
|
|||
blog:
|
||||
rule: "Host(`company.com`) && Path(`/blog`)"
|
||||
tls:
|
||||
certResolver: le
|
||||
certResolver: myresolver
|
||||
```
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Enable ACME (Let's Encrypt): automatic SSL.
|
||||
[certificatesResolvers.sample.acme]
|
||||
[certificatesResolvers.myresolver.acme]
|
||||
|
||||
# Email address used for registration.
|
||||
#
|
||||
|
@ -35,13 +35,13 @@
|
|||
#
|
||||
# Optional (but recommended)
|
||||
#
|
||||
[certificatesResolvers.le.acme.tlsChallenge]
|
||||
[certificatesResolvers.myresolver.acme.tlsChallenge]
|
||||
|
||||
# Use a HTTP-01 ACME challenge.
|
||||
#
|
||||
# Optional
|
||||
#
|
||||
# [certificatesResolvers.le.acme.httpChallenge]
|
||||
# [certificatesResolvers.myresolver.acme.httpChallenge]
|
||||
|
||||
# EntryPoint to use for the HTTP-01 challenges.
|
||||
#
|
||||
|
@ -54,7 +54,7 @@
|
|||
#
|
||||
# Optional
|
||||
#
|
||||
# [certificatesResolvers.le.acme.dnsChallenge]
|
||||
# [certificatesResolvers.myresolver.acme.dnsChallenge]
|
||||
|
||||
# DNS provider used.
|
||||
#
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
#
|
||||
# Required
|
||||
#
|
||||
--certificatesResolvers.le.acme.email=test@traefik.io
|
||||
--certificatesResolvers.myresolver.acme.email=test@traefik.io
|
||||
|
||||
# File or key used for certificates storage.
|
||||
#
|
||||
# Required
|
||||
#
|
||||
--certificatesResolvers.le.acme.storage=acme.json
|
||||
--certificatesResolvers.myresolver.acme.storage=acme.json
|
||||
|
||||
# CA server to use.
|
||||
# Uncomment the line to use Let's Encrypt's staging server,
|
||||
|
@ -19,7 +19,7 @@
|
|||
# Optional
|
||||
# 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.
|
||||
#
|
||||
|
@ -28,38 +28,38 @@
|
|||
#
|
||||
# Available values : "EC256", "EC384", "RSA2048", "RSA4096", "RSA8192"
|
||||
#
|
||||
--certificatesResolvers.le.acme.keyType=RSA4096
|
||||
--certificatesResolvers.myresolver.acme.keyType=RSA4096
|
||||
|
||||
# Use a TLS-ALPN-01 ACME challenge.
|
||||
#
|
||||
# Optional (but recommended)
|
||||
#
|
||||
--certificatesResolvers.le.acme.tlsChallenge=true
|
||||
--certificatesResolvers.myresolver.acme.tlsChallenge=true
|
||||
|
||||
# Use a HTTP-01 ACME challenge.
|
||||
#
|
||||
# Optional
|
||||
#
|
||||
--certificatesResolvers.le.acme.httpChallenge=true
|
||||
--certificatesResolvers.myresolver.acme.httpChallenge=true
|
||||
|
||||
# EntryPoint to use for the HTTP-01 challenges.
|
||||
#
|
||||
# Required
|
||||
#
|
||||
--certificatesResolvers.le.acme.httpChallenge.entryPoint=web
|
||||
--certificatesResolvers.myresolver.acme.httpChallenge.entryPoint=web
|
||||
|
||||
# Use a DNS-01 ACME challenge rather than HTTP-01 challenge.
|
||||
# Note: mandatory for wildcard certificate generation.
|
||||
#
|
||||
# Optional
|
||||
#
|
||||
--certificatesResolvers.le.acme.dnsChallenge=true
|
||||
--certificatesResolvers.myresolver.acme.dnsChallenge=true
|
||||
|
||||
# DNS provider used.
|
||||
#
|
||||
# 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.
|
||||
# If delayBeforeCheck is greater than zero, this check is delayed for the configured duration in seconds.
|
||||
|
@ -68,14 +68,14 @@
|
|||
# Optional
|
||||
# Default: 0
|
||||
#
|
||||
--certificatesResolvers.le.acme.dnsChallenge.delayBeforeCheck=0
|
||||
--certificatesResolvers.myresolver.acme.dnsChallenge.delayBeforeCheck=0
|
||||
|
||||
# Use following DNS servers to resolve the FQDN authority.
|
||||
#
|
||||
# Optional
|
||||
# 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.
|
||||
#
|
||||
|
@ -85,4 +85,4 @@
|
|||
# Optional
|
||||
# Default: false
|
||||
#
|
||||
--certificatesResolvers.le.acme.dnsChallenge.disablePropagationCheck=true
|
||||
--certificatesResolvers.myresolver.acme.dnsChallenge.disablePropagationCheck=true
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
certificatesResolvers:
|
||||
le:
|
||||
myresolver:
|
||||
# Enable ACME (Let's Encrypt): automatic SSL.
|
||||
acme:
|
||||
|
||||
|
|
|
@ -143,11 +143,11 @@ then you'll have to append to the middleware name, the `@` separator, followed b
|
|||
|
||||
!!! important "Kubernetes Namespace"
|
||||
|
||||
As Kubernetes also has its own notion of namespace, one should not confuse the "provider namespace"
|
||||
with the "kubernetes namespace" of a resource when in the context of a cross-provider usage.
|
||||
In this case, since the definition of the middleware is not in kubernetes,
|
||||
specifying a "kubernetes namespace" when referring to the resource does not make any sense,
|
||||
and therefore this specification would be ignored even if present.
|
||||
As Kubernetes also has its own notion of namespace, one should not confuse the "provider namespace"
|
||||
with the "kubernetes namespace" of a resource when in the context of a cross-provider usage.
|
||||
In this case, since the definition of the middleware is not in kubernetes,
|
||||
specifying a "kubernetes namespace" when referring to the resource does not make any sense,
|
||||
and therefore this specification would be ignored even if present.
|
||||
|
||||
!!! abstract "Referencing a Middleware from Another Provider"
|
||||
|
||||
|
|
|
@ -11,6 +11,132 @@ RedirectScheme redirect request from a scheme to another.
|
|||
|
||||
## 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"
|
||||
# Redirect to https
|
||||
labels:
|
||||
|
@ -31,7 +157,7 @@ spec:
|
|||
```yaml tab="Consul Catalog"
|
||||
# Redirect to https
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https"
|
||||
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https"
|
||||
```
|
||||
|
||||
```json tab="Marathon"
|
||||
|
@ -62,16 +188,64 @@ http:
|
|||
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`
|
||||
|
||||
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"
|
||||
|
||||
[tls.options]
|
||||
[tls.options.default]
|
||||
minVersion = "VersionTLS12"
|
||||
|
||||
[tls.options.myTLSOptions]
|
||||
minVersion = "VersionTLS13"
|
||||
minVersion = "VersionTLS12"
|
||||
cipherSuites = [
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"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
|
||||
options:
|
||||
myTLSOptions:
|
||||
minVersion: VersionTLS13
|
||||
minVersion: VersionTLS12
|
||||
cipherSuites:
|
||||
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||
- 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
|
||||
|
||||
spec:
|
||||
minVersion: VersionTLS13
|
||||
minVersion: VersionTLS12
|
||||
cipherSuites:
|
||||
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||
- 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
|
||||
["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),
|
||||
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",
|
||||
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"
|
||||
[entryPoints.websecure]
|
||||
address = ":443"
|
||||
[entryPoints.https.tls]
|
||||
[entryPoints.websecure.tls]
|
||||
|
||||
[acme]
|
||||
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]
|
||||
address = ":443"
|
||||
|
||||
[certificatesResolvers.sample.acme]
|
||||
[certificatesResolvers.myresolver.acme]
|
||||
email = "your-email@your-domain.org"
|
||||
storage = "acme.json"
|
||||
[certificatesResolvers.sample.acme.httpChallenge]
|
||||
[certificatesResolvers.myresolver.acme.httpChallenge]
|
||||
# used during the challenge
|
||||
entryPoint = "web"
|
||||
```
|
||||
|
@ -876,7 +873,7 @@ with the path `/admin` stripped, e.g. to `http://<IP>:<port>/`. In this case, yo
|
|||
address: ":443"
|
||||
|
||||
certificatesResolvers:
|
||||
sample:
|
||||
myresolver:
|
||||
acme:
|
||||
email: your-email@your-domain.org
|
||||
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"
|
||||
--entryPoints.web.address=:80
|
||||
--entryPoints.websecure.address=:443
|
||||
--certificatesResolvers.sample.acme.email=your-email@your-domain.org
|
||||
--certificatesResolvers.sample.acme.storage=acme.json
|
||||
--certificatesResolvers.sample.acme.httpChallenge.entryPoint=web
|
||||
--certificatesResolvers.myresolver.acme.email=your-email@your-domain.org
|
||||
--certificatesResolvers.myresolver.acme.storage=acme.json
|
||||
--certificatesResolvers.myresolver.acme.httpChallenge.entryPoint=web
|
||||
```
|
||||
|
||||
## Traefik Logs
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
|
||||
## v2.0 to v2.1
|
||||
|
||||
In v2.1, a new CRD called `TraefikService` was added. While updating an installation to v2.1,
|
||||
it is required to apply that CRD before as well as enhance the existing `ClusterRole` definition to allow Traefik to use that CRD.
|
||||
### Kubernetes 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.
|
||||
|
||||
|
|
|
@ -40,24 +40,24 @@ tracing:
|
|||
|
||||
#### `localAgentPort`
|
||||
|
||||
_Require, Default=42699_
|
||||
_Require, Default=35000_
|
||||
|
||||
Local Agent port instructs reporter to send spans to the haystack-agent at this port.
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[tracing]
|
||||
[tracing.haystack]
|
||||
localAgentPort = 42699
|
||||
localAgentPort = 35000
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
tracing:
|
||||
haystack:
|
||||
localAgentPort: 42699
|
||||
localAgentPort: 35000
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--tracing.haystack.localAgentPort=42699
|
||||
--tracing.haystack.localAgentPort=35000
|
||||
```
|
||||
|
||||
#### `globalTag`
|
||||
|
@ -91,61 +91,61 @@ Specifies the header name that will be used to store the trace ID.
|
|||
```toml tab="File (TOML)"
|
||||
[tracing]
|
||||
[tracing.haystack]
|
||||
traceIDHeaderName = "sample"
|
||||
traceIDHeaderName = "Trace-ID"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
tracing:
|
||||
haystack:
|
||||
traceIDHeaderName: sample
|
||||
traceIDHeaderName: Trace-ID
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--tracing.haystack.traceIDHeaderName=sample
|
||||
--tracing.haystack.traceIDHeaderName=Trace-ID
|
||||
```
|
||||
|
||||
#### `parentIDHeaderName`
|
||||
|
||||
_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.
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[tracing]
|
||||
[tracing.haystack]
|
||||
parentIDHeaderName = "sample"
|
||||
spanIDHeaderName = "Message-ID"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
tracing:
|
||||
haystack:
|
||||
parentIDHeaderName: "sample"
|
||||
spanIDHeaderName: Message-ID
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--tracing.haystack.parentIDHeaderName=sample
|
||||
```
|
||||
|
||||
#### `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
|
||||
--tracing.haystack.spanIDHeaderName=Message-ID
|
||||
```
|
||||
|
||||
#### `baggagePrefixHeaderName`
|
||||
|
|
|
@ -31,6 +31,8 @@ spec:
|
|||
services:
|
||||
- name: api@internal
|
||||
kind: TraefikService
|
||||
middlewares:
|
||||
- name: auth
|
||||
---
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
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.
|
||||
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.
|
||||
|
||||
??? example "Constraints Expression Examples"
|
||||
|
|
|
@ -261,7 +261,7 @@ See the sections [Docker API Access](#docker-api-access) and [Docker Swarm API A
|
|||
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v2.0 # The official v2.0 Traefik docker image
|
||||
image: traefik:v2.1 # The official v2 Traefik docker image
|
||||
ports:
|
||||
- "80:80"
|
||||
volumes:
|
||||
|
|
|
@ -118,27 +118,35 @@ If you're in a hurry, maybe you'd rather go through the [dynamic configuration](
|
|||
|
||||
### `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)"
|
||||
[providers]
|
||||
[providers.file]
|
||||
filename = "dynamic_conf.toml"
|
||||
filename = "/path/to/config/dynamic_conf.toml"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
file:
|
||||
filename: dynamic_conf.yml
|
||||
filename: /path/to/config/dynamic_conf.yml
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--providers.file.filename=dynamic_conf.toml
|
||||
--providers.file.filename=/path/to/config/dynamic_conf.toml
|
||||
```
|
||||
|
||||
### `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)"
|
||||
[providers]
|
||||
|
@ -186,8 +194,11 @@ providers:
|
|||
Go Templating only works along with dedicated dynamic configuration files.
|
||||
Templating does not work in the Traefik main static configuration file.
|
||||
|
||||
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` :
|
||||
Traefik allows using Go templating,
|
||||
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"
|
||||
|
||||
|
@ -197,7 +208,7 @@ Thus, it's possible to define easily lot of routers, services and TLS certificat
|
|||
|
||||
[http.routers]
|
||||
{{ range $i, $e := until 100 }}
|
||||
[http.routers.router{{ $e }}]
|
||||
[http.routers.router{{ $e }}-{{ env "MY_ENV_VAR" }}]
|
||||
# ...
|
||||
{{ end }}
|
||||
|
||||
|
@ -239,40 +250,38 @@ Thus, it's possible to define easily lot of routers, services and TLS certificat
|
|||
|
||||
```yaml tab="YAML"
|
||||
http:
|
||||
|
||||
{{range $i, $e := until 100 }}
|
||||
routers:
|
||||
router{{ $e }:
|
||||
{{range $i, $e := until 100 }}
|
||||
router{{ $e }}-{{ env "MY_ENV_VAR" }}:
|
||||
# ...
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range $i, $e := until 100 }}
|
||||
services:
|
||||
{{range $i, $e := until 100 }}
|
||||
application{{ $e }}:
|
||||
# ...
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
tcp:
|
||||
|
||||
{{range $i, $e := until 100 }}
|
||||
routers:
|
||||
router{{ $e }:
|
||||
{{range $i, $e := until 100 }}
|
||||
router{{ $e }}:
|
||||
# ...
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range $i, $e := until 100 }}
|
||||
services:
|
||||
{{range $i, $e := until 100 }}
|
||||
service{{ $e }}:
|
||||
# ...
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{ range $i, $e := until 10 }}
|
||||
tls:
|
||||
certificates:
|
||||
{{ range $i, $e := until 10 }}
|
||||
- certFile: "/etc/traefik/cert-{{ $e }}.pem"
|
||||
keyFile: "/etc/traefik/cert-{{ $e }}.key"
|
||||
store:
|
||||
- "my-store-foo-{{ $e }}"
|
||||
- "my-store-bar-{{ $e }}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
```
|
||||
|
|
|
@ -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,
|
||||
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
|
||||
|
||||
### `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.
|
||||
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`
|
||||
|
||||
|
@ -268,7 +314,7 @@ _Optional, Default: empty_
|
|||
|
||||
```toml tab="File (TOML)"
|
||||
[providers.kubernetesIngress.ingressEndpoint]
|
||||
publishedService = "foo-service"
|
||||
publishedService = "namespace/foo-service"
|
||||
# ...
|
||||
```
|
||||
|
||||
|
@ -276,15 +322,16 @@ _Optional, Default: empty_
|
|||
providers:
|
||||
kubernetesIngress:
|
||||
ingressEndpoint:
|
||||
publishedService: "foo-service"
|
||||
publishedService: "namespace/foo-service"
|
||||
# ...
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--providers.kubernetesingress.ingressendpoint.publishedservice=foo-service
|
||||
--providers.kubernetesingress.ingressendpoint.publishedservice=namespace/foo-service
|
||||
```
|
||||
|
||||
Published Kubernetes Service to copy status from.
|
||||
Format: `namespace/servicename`.
|
||||
|
||||
### `throttleDuration`
|
||||
|
||||
|
@ -309,7 +356,8 @@ providers:
|
|||
|
||||
### 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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
`--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`:
|
||||
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.
|
||||
|
||||
`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`:
|
||||
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=
|
||||
```
|
||||
|
||||
!!! 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`
|
||||
|
||||
`Middleware` is the CRD implementation of a [Traefik middleware](../../middlewares/overview.md).
|
||||
|
|
|
@ -26,19 +26,19 @@ spec:
|
|||
serviceAccountName: traefik-ingress-controller
|
||||
containers:
|
||||
- name: traefik
|
||||
image: traefik:v2.0
|
||||
image: traefik:v2.1
|
||||
args:
|
||||
- --api.insecure
|
||||
- --accesslog
|
||||
- --entrypoints.web.Address=:8000
|
||||
- --entrypoints.websecure.Address=:4443
|
||||
- --providers.kubernetescrd
|
||||
- --certificatesresolvers.default.acme.tlschallenge
|
||||
- --certificatesresolvers.default.acme.email=foo@you.com
|
||||
- --certificatesresolvers.default.acme.storage=acme.json
|
||||
- --certificatesresolvers.myresolver.acme.tlschallenge
|
||||
- --certificatesresolvers.myresolver.acme.email=foo@you.com
|
||||
- --certificatesresolvers.myresolver.acme.storage=acme.json
|
||||
# Please note that this is the staging Let's Encrypt server.
|
||||
# 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:
|
||||
- name: web
|
||||
containerPort: 8000
|
||||
|
|
|
@ -29,4 +29,4 @@ spec:
|
|||
- name: whoami
|
||||
port: 80
|
||||
tls:
|
||||
certResolver: default
|
||||
certResolver: myresolver
|
||||
|
|
|
@ -26,5 +26,5 @@ node:
|
|||
- K3S_CLUSTER_SECRET=somethingtotallyrandom
|
||||
volumes:
|
||||
# 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
|
||||
|
|
|
@ -3,7 +3,7 @@ version: "3.3"
|
|||
services:
|
||||
|
||||
traefik:
|
||||
image: "traefik:v2.0.0-rc3"
|
||||
image: "traefik:v2.1"
|
||||
container_name: "traefik"
|
||||
command:
|
||||
#- "--log.level=DEBUG"
|
||||
|
@ -12,11 +12,11 @@ services:
|
|||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge=true"
|
||||
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge.provider=ovh"
|
||||
#- "--certificatesresolvers.mydnschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.mydnschallenge.acme.email=postmaster@mydomain.com"
|
||||
- "--certificatesresolvers.mydnschallenge.acme.storage=/letsencrypt/acme.json"
|
||||
- "--certificatesresolvers.myresolver.acme.dnschallenge=true"
|
||||
- "--certificatesresolvers.myresolver.acme.dnschallenge.provider=ovh"
|
||||
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.myresolver.acme.email=postmaster@mydomain.com"
|
||||
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
|
@ -37,4 +37,4 @@ services:
|
|||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
||||
- "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:
|
||||
|
||||
traefik:
|
||||
image: "traefik:v2.0.0-rc3"
|
||||
image: "traefik:v2.1"
|
||||
container_name: "traefik"
|
||||
command:
|
||||
#- "--log.level=DEBUG"
|
||||
|
@ -22,11 +22,11 @@ services:
|
|||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge=true"
|
||||
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge.provider=ovh"
|
||||
#- "--certificatesresolvers.mydnschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.mydnschallenge.acme.email=postmaster@mydomain.com"
|
||||
- "--certificatesresolvers.mydnschallenge.acme.storage=/letsencrypt/acme.json"
|
||||
- "--certificatesresolvers.myresolver.acme.dnschallenge=true"
|
||||
- "--certificatesresolvers.myresolver.acme.dnschallenge.provider=ovh"
|
||||
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.myresolver.acme.email=postmaster@mydomain.com"
|
||||
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
|
@ -52,4 +52,4 @@ services:
|
|||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
||||
- "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:
|
||||
|
||||
- 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."
|
||||
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]"
|
||||
```
|
||||
|
||||
- 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.
|
||||
- Optionally uncomment the following lines if you want to test/debug:
|
||||
|
||||
```yaml
|
||||
#- "--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.
|
||||
|
@ -68,12 +68,12 @@ ports:
|
|||
|
||||
```yaml
|
||||
command:
|
||||
# Enable a dns challenge named "mydnschallenge"
|
||||
- "--certificatesresolvers.mydnschallenge.acme.dnschallenge=true"
|
||||
# Enable a dns challenge named "myresolver"
|
||||
- "--certificatesresolvers.myresolver.acme.dnschallenge=true"
|
||||
# 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
|
||||
- "--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:
|
||||
|
@ -101,14 +101,14 @@ volumes:
|
|||
|
||||
command:
|
||||
# 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
|
||||
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
|
||||
|
|
|
@ -3,7 +3,7 @@ version: "3.3"
|
|||
services:
|
||||
|
||||
traefik:
|
||||
image: "traefik:v2.0.0-rc3"
|
||||
image: "traefik:v2.1"
|
||||
container_name: "traefik"
|
||||
command:
|
||||
#- "--log.level=DEBUG"
|
||||
|
@ -12,11 +12,11 @@ services:
|
|||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--entrypoints.web.address=:80"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true"
|
||||
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web"
|
||||
#- "--certificatesresolvers.myhttpchallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.myhttpchallenge.acme.email=postmaster@mydomain.com"
|
||||
- "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json"
|
||||
- "--certificatesresolvers.myresolver.acme.httpchallenge=true"
|
||||
- "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
|
||||
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.myresolver.acme.email=postmaster@mydomain.com"
|
||||
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
|
@ -32,4 +32,4 @@ services:
|
|||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
||||
- "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"
|
||||
```
|
||||
|
||||
- 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.
|
||||
- Optionally uncomment the following lines if you want to test/debug:
|
||||
|
||||
```yaml
|
||||
#- "--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.
|
||||
|
@ -54,12 +54,12 @@ ports:
|
|||
|
||||
```yaml
|
||||
command:
|
||||
# Enable a http challenge named "myhttpchallenge"
|
||||
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true"
|
||||
# Enable a http challenge named "myresolver"
|
||||
- "--certificatesresolvers.myresolver.acme.httpchallenge=true"
|
||||
# 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
|
||||
- "--certificatesresolvers.myhttpchallenge.acme.email=postmaster@mydomain.com"
|
||||
- "--certificatesresolvers.myresolver.acme.email=postmaster@mydomain.com"
|
||||
```
|
||||
|
||||
- We add a volume to store our certificates:
|
||||
|
@ -71,13 +71,13 @@ volumes:
|
|||
|
||||
command:
|
||||
# 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
|
||||
labels:
|
||||
# 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:
|
||||
|
||||
traefik:
|
||||
image: "traefik:v2.0.0-rc3"
|
||||
image: "traefik:v2.1"
|
||||
container_name: "traefik"
|
||||
command:
|
||||
#- "--log.level=DEBUG"
|
||||
|
@ -11,10 +11,10 @@ services:
|
|||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
|
||||
#- "--certificatesresolvers.mytlschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.mytlschallenge.acme.email=postmaster@mydomain.com"
|
||||
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
|
||||
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
|
||||
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
- "--certificatesresolvers.myresolver.acme.email=postmaster@mydomain.com"
|
||||
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
|
||||
ports:
|
||||
- "443:443"
|
||||
- "8080:8080"
|
||||
|
@ -29,4 +29,4 @@ services:
|
|||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.whoami.rule=Host(`whoami.mydomain.com`)"
|
||||
- "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"
|
||||
```
|
||||
|
||||
- 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.
|
||||
- Optionally uncomment the following lines if you want to test/debug:
|
||||
|
||||
```yaml
|
||||
#- "--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.
|
||||
|
@ -54,8 +54,8 @@ ports:
|
|||
|
||||
```yaml
|
||||
command:
|
||||
# Enable a tls challenge named "mytlschallenge"
|
||||
- "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
|
||||
# Enable a tls challenge named "myresolver"
|
||||
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
|
||||
```
|
||||
|
||||
- We add a volume to store our certificates:
|
||||
|
@ -67,13 +67,13 @@ volumes:
|
|||
|
||||
command:
|
||||
# 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
|
||||
labels:
|
||||
# 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:
|
||||
|
||||
traefik:
|
||||
image: "traefik:v2.0.0-rc3"
|
||||
image: "traefik:v2.1"
|
||||
container_name: "traefik"
|
||||
command:
|
||||
#- "--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/abronan/valkeyrie v0.0.0-20200127174252-ef4277a138cd
|
||||
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/containous/alice v0.0.0-20181107144136-d83ebdd94cbd
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
||||
|
@ -36,7 +36,7 @@ require (
|
|||
github.com/fatih/structs v1.1.0
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
|
||||
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-kit/kit v0.9.0
|
||||
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/c0va23/go-proxyprotocol v0.9.1 h1:5BCkp0fDJOhzzH1lhjUgHhmZz9VvRMMif1U2D31hb34=
|
||||
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/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
|
||||
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/cenkalti/backoff/v4 v4.0.0 h1:6VeaLF9aI+MAUQ95106HwWzYZgJJpZ4stumjj6RFYAU=
|
||||
github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
|
||||
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/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 v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
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.3.0/go.mod h1:iGSY2vQrvQs3WezicSB/oVbO2eCrD88dpWPwb1qLqu0=
|
||||
github.com/go-acme/lego/v3 v3.4.0 h1:deB9NkelA+TfjGHVw8J7iKl/rMtffcGMWSMmptvMv0A=
|
||||
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-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||
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/nrdcg/auroradns v1.0.0 h1:b+NpSqNG6HzMqX2ohGQe4Q/G0WQq8pduWCiZ19vdLY8=
|
||||
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.3.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ=
|
||||
github.com/nrdcg/dnspod-go v0.4.0 h1:c/jn1mLZNKF3/osJ6mz3QPxTudvPArXTjpkmYj0uK6U=
|
||||
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/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ=
|
||||
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)
|
||||
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)
|
||||
|
||||
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.
|
||||
func (in *HealthCheck) DeepCopyInto(out *HealthCheck) {
|
||||
*out = *in
|
||||
if in.FollowRedirects != nil {
|
||||
in, out := &in.FollowRedirects, &out.FollowRedirects
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.Headers != nil {
|
||||
in, out := &in.Headers, &out.Headers
|
||||
*out = make(map[string]string, len(*in))
|
||||
|
|
|
@ -3,7 +3,7 @@ package job
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff/v3"
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff/v3"
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
)
|
||||
|
||||
func TestJobBackOff(t *testing.T) {
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff/v3"
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
"github.com/containous/traefik/v2/pkg/log"
|
||||
"github.com/containous/traefik/v2/pkg/safe"
|
||||
"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")
|
||||
}
|
||||
|
||||
var port string
|
||||
if len(loadBalancer.Servers) > 0 {
|
||||
port = loadBalancer.Servers[0].Port
|
||||
}
|
||||
|
||||
if len(loadBalancer.Servers) == 0 {
|
||||
loadBalancer.Servers = []dynamic.TCPServer{{}}
|
||||
}
|
||||
|
||||
var port string
|
||||
if item.Port != "" {
|
||||
if item.Port != "" && port == "" {
|
||||
port = item.Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
}
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
if port == "" {
|
||||
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}
|
||||
}
|
||||
|
||||
if item.Port != "" {
|
||||
if item.Port != "" && port == "" {
|
||||
port = item.Port
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
}
|
||||
loadBalancer.Servers[0].Port = ""
|
||||
|
||||
if port == "" {
|
||||
return errors.New("port is missing")
|
||||
|
|
|
@ -1479,7 +1479,7 @@ func Test_buildConfiguration(t *testing.T) {
|
|||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "h2c://127.0.0.1:80",
|
||||
URL: "h2c://127.0.0.1:8080",
|
||||
},
|
||||
},
|
||||
PassHostHeader: Bool(true),
|
||||
|
@ -1531,7 +1531,7 @@ func Test_buildConfiguration(t *testing.T) {
|
|||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "http://127.0.0.1:80",
|
||||
URL: "http://127.0.0.1:8080",
|
||||
},
|
||||
},
|
||||
PassHostHeader: Bool(true),
|
||||
|
|
|
@ -4,14 +4,16 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
"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/job"
|
||||
"github.com/containous/traefik/v2/pkg/log"
|
||||
"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/types"
|
||||
"github.com/hashicorp/consul/api"
|
||||
|
@ -151,7 +153,7 @@ func (p *Provider) getConsulServicesData(ctx context.Context) ([]itemData, error
|
|||
}
|
||||
|
||||
var data []itemData
|
||||
for name := range consulServiceNames {
|
||||
for _, name := range consulServiceNames {
|
||||
consulServices, healthServices, err := p.fetchService(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -204,10 +206,55 @@ func (p *Provider) fetchService(ctx context.Context, name string) ([]*api.Catalo
|
|||
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}
|
||||
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) {
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"text/template"
|
||||
"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/job"
|
||||
"github.com/containous/traefik/v2/pkg/log"
|
||||
|
|
|
@ -110,6 +110,19 @@ func (p *Provider) addWatcher(pool *safe.Pool, directory string, configurationCh
|
|||
case <-ctx.Done():
|
||||
return
|
||||
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 == "" {
|
||||
_, evtFileName := filepath.Split(evt.Name)
|
||||
_, 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.Core().V1().Services().Informer().AddEventHandler(eventHandler)
|
||||
factoryKube.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler)
|
||||
factoryKube.Core().V1().Secrets().Informer().AddEventHandler(eventHandler)
|
||||
|
||||
c.factoriesCrd[ns] = factoryCrd
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"strings"
|
||||
"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/job"
|
||||
"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)
|
||||
if errBuild != nil {
|
||||
logger.Error(err)
|
||||
logger.Error(errBuild)
|
||||
continue
|
||||
}
|
||||
} else if len(route.Services) == 1 {
|
||||
|
@ -307,9 +307,9 @@ func (c configBuilder) loadServers(fallbackNamespace string, svc v1alpha1.LoadBa
|
|||
|
||||
var servers []dynamic.Server
|
||||
if service.Spec.Type == corev1.ServiceTypeExternalName {
|
||||
protocol := "http"
|
||||
if portSpec.Port == 443 || strings.HasPrefix(portSpec.Name, "https") {
|
||||
protocol = "https"
|
||||
protocol, err := parseServiceProtocol(svc.Scheme, portSpec.Name, portSpec.Port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
protocol := httpProtocol
|
||||
scheme := svc.Scheme
|
||||
switch scheme {
|
||||
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)
|
||||
protocol, err := parseServiceProtocol(svc.Scheme, portSpec.Name, portSpec.Port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, addr := range subset.Addresses {
|
||||
|
@ -448,3 +440,19 @@ func getTLSHTTP(ctx context.Context, ingressRoute *v1alpha1.IngressRoute, k8sCli
|
|||
|
||||
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.Core().V1().Services().Informer().AddEventHandler(eventHandler)
|
||||
factory.Core().V1().Endpoints().Informer().AddEventHandler(eventHandler)
|
||||
factory.Core().V1().Secrets().Informer().AddEventHandler(eventHandler)
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"strings"
|
||||
"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/job"
|
||||
"github.com/containous/traefik/v2/pkg/log"
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
etcdv3 "github.com/abronan/valkeyrie/store/etcd/v3"
|
||||
"github.com/abronan/valkeyrie/store/redis"
|
||||
"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/kv"
|
||||
"github.com/containous/traefik/v2/pkg/job"
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"text/template"
|
||||
"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/job"
|
||||
"github.com/containous/traefik/v2/pkg/log"
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"text/template"
|
||||
"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/job"
|
||||
"github.com/containous/traefik/v2/pkg/log"
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"runtime/debug"
|
||||
"sync"
|
||||
|
||||
"github.com/cenkalti/backoff/v3"
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
"github.com/containous/traefik/v2/pkg/log"
|
||||
)
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff/v3"
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
)
|
||||
|
||||
func TestNewPoolContext(t *testing.T) {
|
||||
|
|
|
@ -143,8 +143,6 @@ func (c *ConfigurationWatcher) loadMessage(configMsg dynamic.Message) {
|
|||
}
|
||||
|
||||
func (c *ConfigurationWatcher) preLoadConfiguration(configMsg dynamic.Message) {
|
||||
currentConfigurations := c.currentConfigurations.Get().(dynamic.Configurations)
|
||||
|
||||
logger := log.WithoutContext().WithField(log.ProviderName, configMsg.ProviderName)
|
||||
if log.GetLevel() == logrus.DebugLevel {
|
||||
copyConf := configMsg.Configuration.DeepCopy()
|
||||
|
@ -172,11 +170,6 @@ func (c *ConfigurationWatcher) preLoadConfiguration(configMsg dynamic.Message) {
|
|||
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]
|
||||
if !ok {
|
||||
providerConfigUpdateCh = make(chan dynamic.Message)
|
||||
|
@ -211,11 +204,18 @@ func (c *ConfigurationWatcher) throttleProviderConfigReload(ctx context.Context,
|
|||
}
|
||||
})
|
||||
|
||||
var previousConfig dynamic.Message
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -179,6 +179,70 @@ func TestListenProvidersSkipsSameConfigurationForProvider(t *testing.T) {
|
|||
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) {
|
||||
routinesPool := safe.NewPool(context.Background())
|
||||
|
||||
|
|
|
@ -109,8 +109,6 @@ func (m *Manager) BuildHandlers(rootCtx context.Context, entryPoints []string, t
|
|||
entryPointHandlers[entryPointName] = handlerWithMiddlewares
|
||||
}
|
||||
|
||||
m.serviceManager.LaunchHealthCheck()
|
||||
|
||||
return entryPointHandlers
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,8 @@ func (f *RouterFactory) CreateRouters(conf dynamic.Configuration) (map[string]*t
|
|||
handlersNonTLS := routerManager.BuildHandlers(ctx, f.entryPointsTCP, false)
|
||||
handlersTLS := routerManager.BuildHandlers(ctx, f.entryPointsTCP, true)
|
||||
|
||||
serviceManager.LaunchHealthCheck()
|
||||
|
||||
// TCP
|
||||
svcTCPManager := tcp.NewManager(rtConf)
|
||||
|
||||
|
|
|
@ -49,7 +49,12 @@ func NewManagerFactory(staticConfiguration static.Configuration, routinesPool *s
|
|||
factory.metricsHandler = metrics.PrometheusHandler()
|
||||
}
|
||||
|
||||
factory.pingHandler = staticConfiguration.Ping
|
||||
// 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
|
||||
}
|
||||
|
||||
return factory
|
||||
}
|
||||
|
|
|
@ -203,9 +203,17 @@ func clientHelloServerName(br *bufio.Reader) (string, bool, string, error) {
|
|||
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
|
||||
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.
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ var (
|
|||
`VersionTLS13`: tls.VersionTLS13,
|
||||
}
|
||||
|
||||
// MaxVersion Map of allowed TLS minimum versions
|
||||
// MaxVersion Map of allowed TLS maximum versions
|
||||
MaxVersion = map[string]uint16{
|
||||
`VersionTLS10`: tls.VersionTLS10,
|
||||
`VersionTLS11`: tls.VersionTLS11,
|
||||
|
|
|
@ -26,7 +26,7 @@ type Config struct {
|
|||
|
||||
// SetDefaults sets the default values.
|
||||
func (c *Config) SetDefaults() {
|
||||
c.LocalAgentHost = "LocalAgentHost"
|
||||
c.LocalAgentHost = "127.0.0.1"
|
||||
c.LocalAgentPort = 35000
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue