mirror of
				https://github.com/containous/traefik.git
				synced 2025-10-30 20:24:28 +03:00 
			
		
		
		
	Compare commits
	
		
			163 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 74ad83f05a | ||
|  | d707c8ba93 | ||
|  | 640eb62ca1 | ||
|  | 216710864e | ||
|  | 226f20b626 | ||
|  | 151be83bce | ||
|  | d1a8c7fa78 | ||
|  | 254dc38c3d | ||
|  | 24d084d7e6 | ||
|  | df5f530058 | ||
|  | 753d173965 | ||
|  | ffd1f122de | ||
|  | f98b57fdf4 | ||
|  | 2d37f08864 | ||
|  | a7dbcc282c | ||
|  | f4f62e7fb3 | ||
|  | 4cae8bcb10 | ||
|  | bee370ec6b | ||
|  | f1d016b893 | ||
|  | 4defbbe848 | ||
|  | f397342f16 | ||
|  | 989a59cc29 | ||
|  | c5b71592c8 | ||
|  | 9de3129a55 | ||
|  | 40ab1f325c | ||
|  | 73e0561610 | ||
|  | 0a89cccdc0 | ||
|  | b102e6de5a | ||
|  | 2064a6f805 | ||
|  | 72e2ddff98 | ||
|  | 7db41967c6 | ||
|  | a8680a8719 | ||
|  | 7e11fa1193 | ||
|  | 489b5a6150 | ||
|  | 8027e8ee23 | ||
|  | d35d5bd2e8 | ||
|  | 8e47bdedc6 | ||
|  | 51419a9235 | ||
|  | 32fd52c698 | ||
|  | 468e4ebd98 | ||
|  | 92a57384a4 | ||
|  | 2067a433cd | ||
|  | 16f1f851cc | ||
|  | 8e992c7cfb | ||
|  | 9da0bcf3aa | ||
|  | 51287d9316 | ||
|  | 29307fe9fa | ||
|  | 52772c9642 | ||
|  | 8f135fdb0a | ||
|  | 7722a41270 | ||
|  | cd11b1aab4 | ||
|  | e7564d4cf8 | ||
|  | cc130fb673 | ||
|  | 4106cf647b | ||
|  | 8a1c3510ea | ||
|  | 787b0a3ac7 | ||
|  | a6d86cdddb | ||
|  | 9559a56011 | ||
|  | 07e8042192 | ||
|  | edd8e36dcc | ||
|  | e291dcb8d1 | ||
|  | de6e365b74 | ||
|  | 98a5e08553 | ||
|  | ba44619828 | ||
|  | 86d700c845 | ||
|  | b2f11afcc2 | ||
|  | cfb356c68e | ||
|  | 266f5d18a8 | ||
|  | 305af43fb9 | ||
|  | 30545808d9 | ||
|  | 358f125a58 | ||
|  | 57ae9a80d5 | ||
|  | e32c021f16 | ||
|  | 0db2a9aadd | ||
|  | 4f4dab3ca5 | ||
|  | eaee39e534 | ||
|  | d85eb0495c | ||
|  | 8aa618775d | ||
|  | f6b7e333be | ||
|  | 108d9dbb3f | ||
|  | 2a1fa32950 | ||
|  | ee7aa77833 | ||
|  | fcc4cab614 | ||
|  | 1206cd52fc | ||
|  | 5cdba752a4 | ||
|  | b48ea1e173 | ||
|  | 373040f552 | ||
|  | 443902a0f0 | ||
|  | 9eb02d9b03 | ||
|  | 2eb651645d | ||
|  | 630571fdc8 | ||
|  | 00fc43ebce | ||
|  | 6d906fa4c8 | ||
|  | 6a4c7796e3 | ||
|  | 67704e333d | ||
|  | 76c9cea856 | ||
|  | 0366fb9bc2 | ||
|  | 5fed947eaa | ||
|  | c289279d24 | ||
|  | 418dca1113 | ||
|  | ed293e3058 | ||
|  | 40bb0cd879 | ||
|  | 32f5e0df8f | ||
|  | 40b8a93930 | ||
|  | b52b0f58b9 | ||
|  | 0016db0856 | ||
|  | 5aeca4507e | ||
|  | 11bfb49e65 | ||
|  | d0cdb5608f | ||
|  | 8bb8ad5e02 | ||
|  | b488d8365c | ||
|  | e2bd7b45d1 | ||
|  | c8ea2ce703 | ||
|  | 7d1edcd735 | ||
|  | 9660c31d3d | ||
|  | 37ac19583a | ||
|  | ca60c52199 | ||
|  | 9cddf5616a | ||
|  | f8ba843ad2 | ||
|  | e598d6bcca | ||
|  | 52ec0e8d34 | ||
|  | 13c32dee11 | ||
|  | 6db120fd8e | ||
|  | b6b3a9ed7f | ||
|  | b5a4d0797a | ||
|  | 9ec2887494 | ||
|  | 94de6eb7f2 | ||
|  | 0e643f06a3 | ||
|  | 4db0dd9a7f | ||
|  | ee19e66aba | ||
|  | 16ed13ba6f | ||
|  | 8f5e972843 | ||
|  | 4b70ff82b9 | ||
|  | 1468e1f697 | ||
|  | 7a963e75fd | ||
|  | 9203ba5f95 | ||
|  | 302849282c | ||
|  | 2a227fa4c7 | ||
|  | 31b80683c8 | ||
|  | 6aa040ad9f | ||
|  | 617de78d14 | ||
|  | 44605731dc | ||
|  | 9d26839e54 | ||
|  | 7a93bcc869 | ||
|  | 0840fd0f96 | ||
|  | 4a5f5440d7 | ||
|  | 479ee9af49 | ||
|  | ef6c1fac4b | ||
|  | 53201b65b0 | ||
|  | 9cb4d56c03 | ||
|  | f25ebc7e3d | ||
|  | 4c25cda55f | ||
|  | 18962b61d6 | ||
|  | d0aa993661 | ||
|  | df688dba0e | ||
|  | 69585c58cd | ||
|  | b889b0191c | ||
|  | 9b0586cba7 | ||
|  | a20f5bda0b | ||
|  | 28d5731b87 | ||
|  | 66486eacdc | ||
|  | 2b82ed054c | ||
|  | cd6f0c0ded | 
							
								
								
									
										2
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							| @@ -1 +1 @@ | ||||
| # vendor/github.com/xenolf/lego/providers/dns/cloudxns/cloudxns.go eol=crlf | ||||
| # vendor/github.com/go-acme/lego/providers/dns/cloudxns/cloudxns.go eol=crlf | ||||
|   | ||||
							
								
								
									
										18
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,15 +1,17 @@ | ||||
| /dist | ||||
| /autogen/genstatic/gen.go | ||||
| .idea/ | ||||
| .intellij/ | ||||
| *.iml | ||||
| /traefik | ||||
| /traefik.toml | ||||
| /static/ | ||||
| /webui/.tmp/ | ||||
| .vscode/ | ||||
| .DS_Store | ||||
| /static/ | ||||
| /autogen/genstatic/gen.go | ||||
| /webui/.tmp/ | ||||
| /examples/acme/acme.json | ||||
| /site/ | ||||
| /docs/site/ | ||||
| /traefik.toml | ||||
| /dist | ||||
| /traefik | ||||
| *.log | ||||
| *.exe | ||||
| .DS_Store | ||||
| /examples/acme/acme.json | ||||
| cover.out | ||||
|   | ||||
							
								
								
									
										20
									
								
								.semaphoreci/golang.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										20
									
								
								.semaphoreci/golang.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| set -e | ||||
|  | ||||
| curl -O https://dl.google.com/go/go1.12.linux-amd64.tar.gz | ||||
|  | ||||
| tar -xvf go1.12.linux-amd64.tar.gz | ||||
| rm -rf go1.12.linux-amd64.tar.gz | ||||
|  | ||||
| sudo mkdir -p /usr/local/golang/1.12/go | ||||
| sudo mv go /usr/local/golang/1.12/ | ||||
|  | ||||
| sudo rm /usr/local/bin/go | ||||
| sudo chmod +x /usr/local/golang/1.12/go/bin/go | ||||
| sudo ln -s /usr/local/golang/1.12/go/bin/go /usr/local/bin/go | ||||
|  | ||||
| export GOROOT="/usr/local/golang/1.12/go" | ||||
| export GOTOOLDIR="/usr/local/golang/1.12/go/pkg/tool/linux_amd64" | ||||
|  | ||||
| go version | ||||
| @@ -1,7 +1,7 @@ | ||||
| #!/usr/bin/env bash | ||||
| set -e | ||||
|  | ||||
| export DOCKER_VERSION=17.03.1 | ||||
| export DOCKER_VERSION=18.09.7 | ||||
|  | ||||
| source .semaphoreci/vars | ||||
|  | ||||
|   | ||||
							
								
								
									
										11
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -13,6 +13,7 @@ env: | ||||
|     - VERSION: $TRAVIS_TAG | ||||
|     - CODENAME: maroilles | ||||
|     - N_MAKE_JOBS: 2 | ||||
|     - DOCS_VERIFY_SKIP: true | ||||
|  | ||||
| script: | ||||
| - echo "Skipping tests... (Tests are executed on SemaphoreCI)" | ||||
| @@ -30,9 +31,8 @@ before_deploy: | ||||
|         make -j${N_MAKE_JOBS} crossbinary-parallel; | ||||
|         tar cfz dist/traefik-${VERSION}.src.tar.gz --exclude-vcs --exclude dist .; | ||||
|       fi; | ||||
|       curl -sI https://github.com/containous/structor/releases/latest | grep -Fi Location  | tr -d '\r' | sed "s/tag/download/g" | awk -F " " '{ print $2 "/structor_linux-amd64"}' | wget --output-document=$GOPATH/bin/structor -i -; | ||||
|       chmod +x $GOPATH/bin/structor; | ||||
|       structor -o containous -r traefik --dockerfile-url="https://raw.githubusercontent.com/containous/traefik/master/docs.Dockerfile" --menu.js-url="https://raw.githubusercontent.com/containous/structor/master/traefik-menu.js.gotmpl" --rqts-url="https://raw.githubusercontent.com/containous/structor/master/requirements-override.txt" --exp-branch=master --debug; | ||||
|       curl -sfL https://raw.githubusercontent.com/containous/structor/master/godownloader.sh | bash -s -- -b "${GOPATH}/bin" ${STRUCTOR_VERSION} | ||||
|       structor -o containous -r traefik --dockerfile-url="https://raw.githubusercontent.com/containous/traefik/v1.7/docs.Dockerfile" --menu.js-url="https://raw.githubusercontent.com/containous/structor/master/traefik-menu.js.gotmpl" --rqts-url="https://raw.githubusercontent.com/containous/structor/master/requirements-override.txt" --exp-branch=master --force-edit-url --debug; | ||||
|     fi | ||||
| deploy: | ||||
|   - provider: releases | ||||
| @@ -49,11 +49,6 @@ deploy: | ||||
|     on: | ||||
|       repo: containous/traefik | ||||
|       tags: true | ||||
|   - provider: script | ||||
|     script: sh script/deploy-docker.sh | ||||
|     skip_cleanup: true | ||||
|     on: | ||||
|       repo: containous/traefik | ||||
|   - provider: pages | ||||
|     edge: false | ||||
|     github_token: ${GITHUB_TOKEN} | ||||
|   | ||||
							
								
								
									
										236
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										236
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,5 +1,237 @@ | ||||
| # Change Log | ||||
|  | ||||
| ## [v1.7.18](https://github.com/containous/traefik/tree/v1.7.18) (2019-09-23) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.17...v1.7.18) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[go,security]** This version is compiled with [Go 1.12.10](https://groups.google.com/d/msg/golang-announce/cszieYyuL9Q/g4Z7pKaqAgAJ), which fixes a vulnerability in previous versions. See the [CVE](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-16276) about it for more details. | ||||
|  | ||||
| ## [v1.7.17](https://github.com/containous/traefik/tree/v1.7.17) (2019-09-23) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.16...v1.7.17) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[logs,middleware]** Avoid closing stdout when the accesslog handler is closed ([#5459](https://github.com/containous/traefik/pull/5459) by [nrwiersma](https://github.com/nrwiersma)) | ||||
| - **[middleware]** Actually send header and code during WriteHeader, if needed ([#5404](https://github.com/containous/traefik/pull/5404) by [mpl](https://github.com/mpl)) | ||||
|  | ||||
| **Documentation:** | ||||
| - **[k8s]** Add note clarifying client certificate header ([#5362](https://github.com/containous/traefik/pull/5362) by [bradjones1](https://github.com/bradjones1)) | ||||
| - **[webui]** Update docs links. ([#5412](https://github.com/containous/traefik/pull/5412) by [ldez](https://github.com/ldez)) | ||||
| - Update Traefik image version. ([#5399](https://github.com/containous/traefik/pull/5399) by [ldez](https://github.com/ldez)) | ||||
|  | ||||
| ## [v1.7.16](https://github.com/containous/traefik/tree/v1.7.16) (2019-09-13) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.15...v1.7.16) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[middleware,websocket]** implement Flusher and Hijacker for codeCatcher ([#5376](https://github.com/containous/traefik/pull/5376) by [mpl](https://github.com/mpl)) | ||||
|  | ||||
| ## [v1.7.15](https://github.com/containous/traefik/tree/v1.7.15) (2019-09-12) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.14...v1.7.15) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[authentication,k8s/ingress]** Kubernetes support for Auth.HeaderField ([#5235](https://github.com/containous/traefik/pull/5235) by [ErikWegner](https://github.com/ErikWegner)) | ||||
| - **[k8s,k8s/ingress]** Finish kubernetes throttling refactoring ([#5269](https://github.com/containous/traefik/pull/5269) by [mpl](https://github.com/mpl)) | ||||
| - **[k8s]** Throttle Kubernetes config refresh ([#4716](https://github.com/containous/traefik/pull/4716) by [benweissmann](https://github.com/benweissmann)) | ||||
| - **[k8s]** Fix wrong handling of insecure tls auth forward ingress annotation ([#5319](https://github.com/containous/traefik/pull/5319) by [majkrzak](https://github.com/majkrzak)) | ||||
| - **[middleware]** error pages: do not buffer response when it's not an error ([#5285](https://github.com/containous/traefik/pull/5285) by [mpl](https://github.com/mpl)) | ||||
| - **[tls]** Consider default cert domain in certificate store ([#5353](https://github.com/containous/traefik/pull/5353) by [nrwiersma](https://github.com/nrwiersma)) | ||||
| - **[tls]** Add TLS minversion constraint ([#5356](https://github.com/containous/traefik/pull/5356) by [dtomcej](https://github.com/dtomcej)) | ||||
|  | ||||
| **Documentation:** | ||||
| - **[acme]** Update Acme doc - Vultr Wildcard & Root ([#5320](https://github.com/containous/traefik/pull/5320) by [ddymko](https://github.com/ddymko)) | ||||
| - **[consulcatalog]** Typo in basic auth usersFile label consul-catalog ([#5230](https://github.com/containous/traefik/pull/5230) by [pitan](https://github.com/pitan)) | ||||
| - **[logs]** Improve Access Logs Documentation page ([#5238](https://github.com/containous/traefik/pull/5238) by [dduportal](https://github.com/dduportal)) | ||||
|  | ||||
| ## [v1.7.14](https://github.com/containous/traefik/tree/v1.7.14) (2019-08-14) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.13...v1.7.14) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - Update to go1.12.8 ([#5201](https://github.com/containous/traefik/pull/5201) by [ldez](https://github.com/ldez)). HTTP/2 Denial of Service [CVE-2019-9512](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9512) and [CVE-2019-9514](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9514) | ||||
| - **[server]** Make hijackConnectionTracker.Close thread safe ([#5194](https://github.com/containous/traefik/pull/5194) by [jlevesy](https://github.com/jlevesy)) | ||||
|  | ||||
| ## [v1.7.13](https://github.com/containous/traefik/tree/v1.7.13) (2019-08-07) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.12...v1.7.13) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[acme]** Update lego ([#5166](https://github.com/containous/traefik/pull/5166) by [dabeck](https://github.com/dabeck)) | ||||
| - **[consulcatalog]** warning should not be a fail status ([#4537](https://github.com/containous/traefik/pull/4537) by [saez0pub](https://github.com/saez0pub)) | ||||
| - **[docker]** Update docker api version ([#4909](https://github.com/containous/traefik/pull/4909) by [dtomcej](https://github.com/dtomcej)) | ||||
| - **[dynamodb]** Use dynamodbav tags to override json tags. ([#5002](https://github.com/containous/traefik/pull/5002) by [ldez](https://github.com/ldez)) | ||||
| - **[healthcheck]** Wrr loadbalancer honors old weight on recovered servers ([#5051](https://github.com/containous/traefik/pull/5051) by [DougWagner](https://github.com/DougWagner)) | ||||
| - **[k8s]** Check for multiport services on Global Backend Ingress ([#5021](https://github.com/containous/traefik/pull/5021) by [dtomcej](https://github.com/dtomcej)) | ||||
| - **[logs]** Allows logs to use local time zone instead of UTC ([#4954](https://github.com/containous/traefik/pull/4954) by [dduportal](https://github.com/dduportal)) | ||||
| - **[middleware]** Clear TLS client headers if TLSMutualAuth is optional ([#4963](https://github.com/containous/traefik/pull/4963) by [stffabi](https://github.com/stffabi)) | ||||
| - **[tls]** Add missing KeyUsages for default generated certificate ([#5150](https://github.com/containous/traefik/pull/5150) by [dtomcej](https://github.com/dtomcej)) | ||||
|  | ||||
| **Documentation:** | ||||
| - **[acme]** Fixed doc link for AlibabaCloud ([#5109](https://github.com/containous/traefik/pull/5109) by [ddymko](https://github.com/ddymko)) | ||||
| - **[docker]** Add example for CLI ([#5131](https://github.com/containous/traefik/pull/5131) by [alvarezbruned](https://github.com/alvarezbruned)) | ||||
| - **[docker]** Use the latest stable version of traefik in the docs ([#4927](https://github.com/containous/traefik/pull/4927) by [kolaente](https://github.com/kolaente)) | ||||
| - **[logs]** Update documentation to clarify the default format for logs ([#4953](https://github.com/containous/traefik/pull/4953) by [dduportal](https://github.com/dduportal)) | ||||
| - **[rancher]** Add remarks about Rancher 2 ([#4999](https://github.com/containous/traefik/pull/4999) by [ldez](https://github.com/ldez)) | ||||
| - **[tls]** Fixes the TLS Mutual Authentication documentation ([#5085](https://github.com/containous/traefik/pull/5085) by [jbdoumenjou](https://github.com/jbdoumenjou)) | ||||
| - Format YAML example on user guide ([#5067](https://github.com/containous/traefik/pull/5067) by [gurayyildirim](https://github.com/gurayyildirim)) | ||||
| - Update Slack support channel references to Discourse community forum ([#5014](https://github.com/containous/traefik/pull/5014) by [dduportal](https://github.com/dduportal)) | ||||
| - Updating Service Fabric documentation ([#5160](https://github.com/containous/traefik/pull/5160) by [gheibia](https://github.com/gheibia)) | ||||
| - Improve API / Dashboard wording in documentation ([#4929](https://github.com/containous/traefik/pull/4929) by [dduportal](https://github.com/dduportal)) | ||||
|  | ||||
| ## [v1.7.12](https://github.com/containous/traefik/tree/v1.7.12) (2019-05-29) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.11...v1.7.12) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[acme]** Allow SANs for wildcards domain. ([#4821](https://github.com/containous/traefik/pull/4821) by [vizv](https://github.com/vizv)) | ||||
| - **[acme]** fix: update lego. ([#4910](https://github.com/containous/traefik/pull/4910) by [ldez](https://github.com/ldez)) | ||||
| - **[api,authentication]** Remove authentication hashes from API ([#4918](https://github.com/containous/traefik/pull/4918) by [ldez](https://github.com/ldez)) | ||||
| - **[consul]** Enhance KV logs. ([#4877](https://github.com/containous/traefik/pull/4877) by [ldez](https://github.com/ldez)) | ||||
| - **[k8s]** Fix kubernetes template for backend responseforwarding flushinterval setting ([#4901](https://github.com/containous/traefik/pull/4901) by [ravilr](https://github.com/ravilr)) | ||||
| - **[metrics]** Upgraded DataDog tracing library to 1.13.0 ([#4878](https://github.com/containous/traefik/pull/4878) by [aantono](https://github.com/aantono)) | ||||
| - **[server]** Add missing callback on close of hijacked connections ([#4900](https://github.com/containous/traefik/pull/4900) by [ravilr](https://github.com/ravilr)) | ||||
|  | ||||
| **Documentation:** | ||||
| - **[docker]** Docs: Troubleshooting help for Docker Swarm labels ([#4751](https://github.com/containous/traefik/pull/4751) by [gregberns](https://github.com/gregberns)) | ||||
| - **[logs]** Adds a log fields documentation. ([#4890](https://github.com/containous/traefik/pull/4890) by [ldez](https://github.com/ldez)) | ||||
|  | ||||
| ## [v1.7.11](https://github.com/containous/traefik/tree/v1.7.11) (2019-04-26) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.10...v1.7.11) | ||||
|  | ||||
| **Enhancements:** | ||||
| - **[k8s,k8s/ingress]** Enhance k8s tests maintainability ([#4696](https://github.com/containous/traefik/pull/4696) by [ldez](https://github.com/ldez)) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[acme]** fix: update lego. ([#4800](https://github.com/containous/traefik/pull/4800) by [ldez](https://github.com/ldez)) | ||||
| - **[authentication,middleware]** Forward all header values from forward auth response ([#4515](https://github.com/containous/traefik/pull/4515) by [ctas582](https://github.com/ctas582)) | ||||
| - **[cluster]** Remove usage of github.com/satori/go.uuid ([#4722](https://github.com/containous/traefik/pull/4722) by [aaslamin](https://github.com/aaslamin)) | ||||
| - **[kv]** Enhance KV client error management ([#4819](https://github.com/containous/traefik/pull/4819) by [jbdoumenjou](https://github.com/jbdoumenjou)) | ||||
| - **[tls]** Improve log message about redundant TLS certificate ([#4765](https://github.com/containous/traefik/pull/4765) by [mpl](https://github.com/mpl)) | ||||
| - **[tracing]** Update zipkin-go-opentracing. ([#4720](https://github.com/containous/traefik/pull/4720) by [ldez](https://github.com/ldez)) | ||||
|  | ||||
| **Documentation:** | ||||
| - **[acme]** Documentation Update: Hosting.de wildcard support tested ([#4747](https://github.com/containous/traefik/pull/4747) by [martinhoefling](https://github.com/martinhoefling)) | ||||
| - **[acme]** Update Wildcard Domain documentation ([#4682](https://github.com/containous/traefik/pull/4682) by [DWSR](https://github.com/DWSR)) | ||||
| - **[middleware]** Keep consistent order ([#4690](https://github.com/containous/traefik/pull/4690) by [maxifom](https://github.com/maxifom)) | ||||
|  | ||||
| ## [v1.7.10](https://github.com/containous/traefik/tree/v1.7.10) (2019-03-28) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.9...v1.7.10) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[acme]** fix: update lego. ([#4670](https://github.com/containous/traefik/pull/4670) by [ldez](https://github.com/ldez)) | ||||
| - **[acme]** Migrate to go-acme/lego. ([#4577](https://github.com/containous/traefik/pull/4577) by [ldez](https://github.com/ldez)) | ||||
| - **[authentication,middleware]** Reorder Auth and TLSClientHeaders middleware ([#4557](https://github.com/containous/traefik/pull/4557) by [tomberek](https://github.com/tomberek)) | ||||
| - **[k8s/ingress]** Support external name service on global default backend ([#4564](https://github.com/containous/traefik/pull/4564) by [kippandrew](https://github.com/kippandrew)) | ||||
| - **[k8s/ingress]** Loop through service ports for global backend ([#4486](https://github.com/containous/traefik/pull/4486) by [dtomcej](https://github.com/dtomcej)) | ||||
| - **[k8s]** Add entrypoints prefix in kubernetes frontend/backend id  ([#4679](https://github.com/containous/traefik/pull/4679) by [juliens](https://github.com/juliens)) | ||||
| - **[websocket]** Exclude websocket connections from Average Response Time ([#4313](https://github.com/containous/traefik/pull/4313) by [siyu6974](https://github.com/siyu6974)) | ||||
| - **[middleware]** Added support for configuring trace headers for DataDog tracing ([#4516](https://github.com/containous/traefik/pull/4516) by [aantono](https://github.com/aantono)) | ||||
|  | ||||
| **Documentation:** | ||||
| - **[acme]** Add _FILE Environment Variable Documentation ([#4643](https://github.com/containous/traefik/pull/4643) by [dargmuesli](https://github.com/dargmuesli)) | ||||
| - **[docker]** Add TraefikEE as security workaround ([#4606](https://github.com/containous/traefik/pull/4606) by [emilevauge](https://github.com/emilevauge)) | ||||
|  | ||||
| ## [v1.7.9](https://github.com/containous/traefik/tree/v1.7.9) (2019-02-11) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.8...v1.7.9) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[acme]** Updates of Lego. ([#4480](https://github.com/containous/traefik/pull/4480) by [ldez](https://github.com/ldez)) | ||||
| - **[k8s]** app-root on non-explicit path include "/" in the redirect ([#4458](https://github.com/containous/traefik/pull/4458) by [doctori](https://github.com/doctori)) | ||||
| - **[middleware]** Missing trailers with retry ([#4442](https://github.com/containous/traefik/pull/4442) by [juliens](https://github.com/juliens)) | ||||
| - **[rancher]** Handle errors when working with rancher ([#4378](https://github.com/containous/traefik/pull/4378) by [apsifly](https://github.com/apsifly)) | ||||
| - **[servicefabric]** Add support for specifying the name of the endpoint. ([#4479](https://github.com/containous/traefik/pull/4479) by [ldez](https://github.com/ldez)) | ||||
| - **[tls]** insecureSkipVerify for the passTLSCert transport ([#4438](https://github.com/containous/traefik/pull/4438) by [jbdoumenjou](https://github.com/jbdoumenjou)) | ||||
| - **[tracing]** Add Tracing Header Context Name option for Jaeger ([#4459](https://github.com/containous/traefik/pull/4459) by [gadoor](https://github.com/gadoor)) | ||||
|  | ||||
| **Documentation:** | ||||
| - **[metrics]** Update default value of buckets for Prometheus ([#4468](https://github.com/containous/traefik/pull/4468) by [adam-golab](https://github.com/adam-golab)) | ||||
| - **[rules]** Fixes the display of the associativity rules. ([#4478](https://github.com/containous/traefik/pull/4478) by [ldez](https://github.com/ldez)) | ||||
| - Fixed curl example ([#4471](https://github.com/containous/traefik/pull/4471) by [rgarrigue](https://github.com/rgarrigue)) | ||||
|  | ||||
| ## [v1.7.8](https://github.com/containous/traefik/tree/v1.7.8) (2019-01-29) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.7...v1.7.8) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[acme]** Updates lego. ([#4428](https://github.com/containous/traefik/pull/4428) by [ldez](https://github.com/ldez)) | ||||
| - **[acme]** Updates lego. ([#4376](https://github.com/containous/traefik/pull/4376) by [ldez](https://github.com/ldez)) | ||||
| - **[docker]** Fixes docker swarm mode refresh second for KV. ([#4420](https://github.com/containous/traefik/pull/4420) by [ldez](https://github.com/ldez)) | ||||
| - **[ecs]** Generic awsvpc support, not just Fargate ([#4360](https://github.com/containous/traefik/pull/4360) by [maartenvanderhoef](https://github.com/maartenvanderhoef)) | ||||
| - **[ecs]** Cache exising task definitions to avoid rate limiting ([#4177](https://github.com/containous/traefik/pull/4177) by [hwhelan-CB](https://github.com/hwhelan-CB)) | ||||
| - **[tls]** Check for dynamic tls updates on configuration preload ([#4022](https://github.com/containous/traefik/pull/4022) by [ffilippopoulos](https://github.com/ffilippopoulos)) | ||||
| - **[tracing]** Support Datadog tracer priority sampling ([#4359](https://github.com/containous/traefik/pull/4359) by [jcassee](https://github.com/jcassee)) | ||||
| - Update to Go 1.11.5 [CVE-2019-6486](https://nvd.nist.gov/vuln/detail/CVE-2019-6486) | ||||
|  | ||||
| **Documentation:** | ||||
| - **[acme]** More detailed info about Google Cloud DNS. ([#4395](https://github.com/containous/traefik/pull/4395) by [ldez](https://github.com/ldez)) | ||||
| - **[acme]** Tested wildcard ACME challenge with DNSimple ([#4384](https://github.com/containous/traefik/pull/4384) by [tstackhouse](https://github.com/tstackhouse)) | ||||
| - **[docker]** Note about quotes for entrypoint definition with docker-compose ([#4390](https://github.com/containous/traefik/pull/4390) by [Dragnucs](https://github.com/Dragnucs)) | ||||
| - **[k8s]** Allow Træfik to update Ingress status ([#4397](https://github.com/containous/traefik/pull/4397) by [rbq](https://github.com/rbq)) | ||||
| - **[k8s]** Minor formatting fixes ([#4394](https://github.com/containous/traefik/pull/4394) by [dbirks](https://github.com/dbirks)) | ||||
| - **[metrics]** Missing information about statistics parameter ([#4393](https://github.com/containous/traefik/pull/4393) by [decima](https://github.com/decima)) | ||||
| - **[rules]** Route priorities: document minimum priority value ([#4374](https://github.com/containous/traefik/pull/4374) by [tw-360vier](https://github.com/tw-360vier)) | ||||
| - Removed repeated entryPoints.http from grpc.md ([#4370](https://github.com/containous/traefik/pull/4370) by [ishaanbahal](https://github.com/ishaanbahal)) | ||||
| - Happy 2019 ([#4367](https://github.com/containous/traefik/pull/4367) by [emilevauge](https://github.com/emilevauge)) | ||||
|  | ||||
| **Misc:** | ||||
| - Assert that test timeout service is ready. ([#4398](https://github.com/containous/traefik/pull/4398) by [timoreimann](https://github.com/timoreimann)) | ||||
|  | ||||
| ## [v1.7.7](https://github.com/containous/traefik/tree/v1.7.7) (2019-01-08) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.6...v1.7.7) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[acme]** Update Lego ([#4277](https://github.com/containous/traefik/pull/4277) by [ldez](https://github.com/ldez)) | ||||
| - **[k8s]** Check for watched namespace before getting kubernetes objects ([#4327](https://github.com/containous/traefik/pull/4327) by [dtomcej](https://github.com/dtomcej)) | ||||
| - **[k8s]** Allow empty path with App-root annotation ([#4326](https://github.com/containous/traefik/pull/4326) by [dtomcej](https://github.com/dtomcej)) | ||||
| - **[k8s]** kubernetes: sort and uniq TLS secrets ([#4307](https://github.com/containous/traefik/pull/4307) by [zarqman](https://github.com/zarqman)) | ||||
| - **[k8s]** Skip TLS section with no secret in Kubernetes ingress ([#4340](https://github.com/containous/traefik/pull/4340) by [dtomcej](https://github.com/dtomcej)) | ||||
| - **[middleware,consul,consulcatalog,docker,ecs,k8s,marathon,mesos,rancher]** Add Pass TLS Cert Issuer and Domain Component ([#4298](https://github.com/containous/traefik/pull/4298) by [jbdoumenjou](https://github.com/jbdoumenjou)) | ||||
| - **[middleware]** Retry middleware : store headers per attempts and propagate them when responding. ([#4299](https://github.com/containous/traefik/pull/4299) by [jlevesy](https://github.com/jlevesy)) | ||||
| - **[middleware]** Redirection status codes for methods different than GET ([#4116](https://github.com/containous/traefik/pull/4116) by [r--w](https://github.com/r--w)) | ||||
| - Test and exit for jq error before domain loop ([#4347](https://github.com/containous/traefik/pull/4347) by [muhlemmer](https://github.com/muhlemmer)) | ||||
|  | ||||
| **Documentation:** | ||||
| - **[acme]** Letsencrypt - Add info on httpreq format ([#4355](https://github.com/containous/traefik/pull/4355) by [goetas](https://github.com/goetas)) | ||||
| - **[docker]** Update broken link for Docker service constraints ([#4289](https://github.com/containous/traefik/pull/4289) by [clrech](https://github.com/clrech)) | ||||
| - **[middleware]** Add extractorfunc values ([#4351](https://github.com/containous/traefik/pull/4351) by [hsmade](https://github.com/hsmade)) | ||||
| - **[provider]** Rephrase the `traefik.backend` definition in documentation ([#4317](https://github.com/containous/traefik/pull/4317) by [dduportal](https://github.com/dduportal)) | ||||
| - Harden Traefik systemd service ([#4302](https://github.com/containous/traefik/pull/4302) by [jacksgt](https://github.com/jacksgt)) | ||||
|  | ||||
| ## [v1.7.6](https://github.com/containous/traefik/tree/v1.7.6) (2018-12-07) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.5...v1.7.6) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[consulcatalog]** Fix label segmentation when using custom prefix ([#4272](https://github.com/containous/traefik/pull/4272) by [hsmade](https://github.com/hsmade)) | ||||
| - Update to Go 1.11.3 [CVE-2018-16875](https://nvd.nist.gov/vuln/detail/CVE-2018-16875) | ||||
|  | ||||
| ## [v1.7.5](https://github.com/containous/traefik/tree/v1.7.5) (2018-12-03) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.4...v1.7.5) | ||||
|  | ||||
| **Enhancements:** | ||||
| - **[docker]** [docker backend] - Add config flag to set refreshSeconds for swarmmode ticker ([#4105](https://github.com/containous/traefik/pull/4105) by [WTFKr0](https://github.com/WTFKr0)) | ||||
| - **[k8s]** Support canary weight for external name service ([#4135](https://github.com/containous/traefik/pull/4135) by [yue9944882](https://github.com/yue9944882)) | ||||
|  | ||||
| **Bug fixes:** | ||||
| - **[acme]** Fix ACME spec and Cloudflare. ([#4201](https://github.com/containous/traefik/pull/4201) by [ldez](https://github.com/ldez)) | ||||
| - **[authentication,middleware]** Remove X-Forwarded-Uri and X-Forwarded-Method from untrusted IP ([#4036](https://github.com/containous/traefik/pull/4036) by [stffabi](https://github.com/stffabi)) | ||||
| - **[authentication,middleware]** Allow usersFile comments ([#4159](https://github.com/containous/traefik/pull/4159) by [thde](https://github.com/thde)) | ||||
| - **[authentication]** Fix partial declaration of authentication. ([#4212](https://github.com/containous/traefik/pull/4212) by [ldez](https://github.com/ldez)) | ||||
| - **[docker]** Verify ctx when we send configuration message in docker provider ([#4185](https://github.com/containous/traefik/pull/4185) by [juliens](https://github.com/juliens)) | ||||
| - **[ecs]** Filter ECS tasks by LastStatus before adding to list of service tasks ([#4255](https://github.com/containous/traefik/pull/4255) by [hwhelan-CB](https://github.com/hwhelan-CB)) | ||||
| - **[healthcheck]** Query params in health check ([#4188](https://github.com/containous/traefik/pull/4188) by [mmatur](https://github.com/mmatur)) | ||||
| - **[metrics]** Upgraded DD APM library ([#4189](https://github.com/containous/traefik/pull/4189) by [aantono](https://github.com/aantono)) | ||||
| - **[middleware]** Fix ssl force host secure middleware ([#4138](https://github.com/containous/traefik/pull/4138) by [mmatur](https://github.com/mmatur)) | ||||
| - **[oxy]** Fix unannonced trailers problem when body is empty ([#4258](https://github.com/containous/traefik/pull/4258) by [juliens](https://github.com/juliens)) | ||||
| - **[provider,server]** Log configuration errors from providers and keeps listening ([#4230](https://github.com/containous/traefik/pull/4230) by [geraldcroes](https://github.com/geraldcroes)) | ||||
| - **[tls]** Implement Case-insensitive SNI matching ([#4132](https://github.com/containous/traefik/pull/4132) by [dtomcej](https://github.com/dtomcej)) | ||||
| - Use ParseInt instead of Atoi for parsing durations ([#4263](https://github.com/containous/traefik/pull/4263) by [mmatur](https://github.com/mmatur)) | ||||
|  | ||||
| **Documentation:** | ||||
| - **[acme]** ACME DNS provider is called `acme-dns` ([#4166](https://github.com/containous/traefik/pull/4166) by [robsdedude](https://github.com/robsdedude)) | ||||
| - **[docker]** Add a "Security Consideration" section in the Docker's backend section of the documentation ([#4225](https://github.com/containous/traefik/pull/4225) by [dduportal](https://github.com/dduportal)) | ||||
| - **[docker]** Clarify swarm loadbalancer documentation ([#4194](https://github.com/containous/traefik/pull/4194) by [jlevesy](https://github.com/jlevesy)) | ||||
| - **[docker]** Fix spelling in comment ([#4169](https://github.com/containous/traefik/pull/4169) by [giocomai](https://github.com/giocomai)) | ||||
| - **[docker]** Update swarm mode endpoint ([#4208](https://github.com/containous/traefik/pull/4208) by [siyu6974](https://github.com/siyu6974)) | ||||
| - **[k8s]** Include an explicit list of kubernetes protocol annotations in docs. ([#4170](https://github.com/containous/traefik/pull/4170) by [shanna](https://github.com/shanna)) | ||||
| - **[k8s]** Improve kubernetes TLS user guide ([#4175](https://github.com/containous/traefik/pull/4175) by [mterring](https://github.com/mterring)) | ||||
| - **[k8s]** frame-deny should be set to true to enable the header ([#4171](https://github.com/containous/traefik/pull/4171) by [swestcott](https://github.com/swestcott)) | ||||
| - **[rules]** Matcher associativity rule. ([#4244](https://github.com/containous/traefik/pull/4244) by [ldez](https://github.com/ldez)) | ||||
| - Documentation: Rename "admin panel" to "dashboard ([#4156](https://github.com/containous/traefik/pull/4156) by [thernstig](https://github.com/thernstig)) | ||||
|  | ||||
| ## [v1.7.4](https://github.com/containous/traefik/tree/v1.7.4) (2018-10-30) | ||||
| [All Commits](https://github.com/containous/traefik/compare/v1.7.3...v1.7.4) | ||||
|  | ||||
| @@ -1018,7 +1250,7 @@ | ||||
| - **[acme,tls]** Rename TLSConfigurations to TLS. ([#2744](https://github.com/containous/traefik/pull/2744) by [ldez](https://github.com/ldez)) | ||||
| - **[acme,provider,docker,tls]** Make the TLS certificates management dynamic. ([#2233](https://github.com/containous/traefik/pull/2233) by [nmengin](https://github.com/nmengin)) | ||||
| - **[acme]** Add Let's Encrypt HTTP Challenge ([#2701](https://github.com/containous/traefik/pull/2701) by [Juliens](https://github.com/Juliens)) | ||||
| - **[acme]** Update github.com/xenolf/lego to 0.4.1 ([#2304](https://github.com/containous/traefik/pull/2304) by [oldmantaiter](https://github.com/oldmantaiter)) | ||||
| - **[acme]** Update github.com/go-acme/lego to 0.4.1 ([#2304](https://github.com/containous/traefik/pull/2304) by [oldmantaiter](https://github.com/oldmantaiter)) | ||||
| - **[api,healthcheck,metrics,provider,webui]** Split Web into API/Dashboard, ping, metric and Rest Provider ([#2335](https://github.com/containous/traefik/pull/2335) by [Juliens](https://github.com/Juliens)) | ||||
| - **[authentication]** Pass through certain forward auth negative response headers ([#2127](https://github.com/containous/traefik/pull/2127) by [wheresmysocks](https://github.com/wheresmysocks)) | ||||
| - **[cluster,consul,file]** Add file to storeconfig ([#2419](https://github.com/containous/traefik/pull/2419) by [emilevauge](https://github.com/emilevauge)) | ||||
| @@ -1297,7 +1529,7 @@ | ||||
|  | ||||
| **Enhancements:** | ||||
| - **[acme,provider,docker,tls]** Make the TLS certificates management dynamic. ([#2233](https://github.com/containous/traefik/pull/2233) by [nmengin](https://github.com/nmengin)) | ||||
| - **[acme]** Update github.com/xenolf/lego to 0.4.1 ([#2304](https://github.com/containous/traefik/pull/2304) by [oldmantaiter](https://github.com/oldmantaiter)) | ||||
| - **[acme]** Update github.com/go-acme/lego to 0.4.1 ([#2304](https://github.com/containous/traefik/pull/2304) by [oldmantaiter](https://github.com/oldmantaiter)) | ||||
| - **[api,healthcheck,metrics,provider,webui]** Split Web into API/Dashboard, ping, metric and Rest Provider ([#2335](https://github.com/containous/traefik/pull/2335) by [Juliens](https://github.com/Juliens)) | ||||
| - **[authentication]** Pass through certain forward auth negative response headers ([#2127](https://github.com/containous/traefik/pull/2127) by [wheresmysocks](https://github.com/wheresmysocks)) | ||||
| - **[cluster,consul,file]** Add file to storeconfig ([#2419](https://github.com/containous/traefik/pull/2419) by [emilevauge](https://github.com/emilevauge)) | ||||
|   | ||||
| @@ -13,7 +13,7 @@ You need to run the `binary` target. This will create binaries for Linux platfor | ||||
| $ make binary | ||||
| docker build -t "traefik-dev:no-more-godep-ever" -f build.Dockerfile . | ||||
| Sending build context to Docker daemon 295.3 MB | ||||
| Step 0 : FROM golang:1.11-alpine | ||||
| Step 0 : FROM golang:1.12-alpine | ||||
|  ---> 8c6473912976 | ||||
| Step 1 : RUN go get github.com/golang/dep/cmd/dep | ||||
| [...] | ||||
| @@ -87,7 +87,7 @@ If you happen to update the provider templates (in `/templates`), you need to ru | ||||
|  | ||||
| [dep](https://github.com/golang/dep) is not required for building; however, it is necessary to modify dependencies (i.e., add, update, or remove third-party packages) | ||||
|  | ||||
| You need to use [dep](https://github.com/golang/dep) >= O.4.1. | ||||
| You need to use [dep](https://github.com/golang/dep) >= 0.5.0. | ||||
|  | ||||
| If you want to add a dependency, use `dep ensure -add` to have [dep](https://github.com/golang/dep) put it into the vendor folder and update the dep manifest/lock files (`Gopkg.toml` and `Gopkg.lock`, respectively). | ||||
|  | ||||
| @@ -158,7 +158,7 @@ Integration tests must be run from the `integration/` directory and require the | ||||
|  | ||||
| ## Documentation | ||||
|  | ||||
| The [documentation site](http://docs.traefik.io/) is built with [mkdocs](http://mkdocs.org/) | ||||
| The [documentation site](https://docs.traefik.io/v1.7/) is built with [mkdocs](https://mkdocs.org/) | ||||
|  | ||||
| ### Building Documentation | ||||
|  | ||||
| @@ -236,6 +236,14 @@ $ make docs-clean docs-verify | ||||
| ... | ||||
| ``` | ||||
|  | ||||
| Please note that verification can be disabled by setting the environment variable `DOCS_VERIFY_SKIP` to `true`: | ||||
|  | ||||
| ```shell | ||||
| DOCS_VERIFY_SKIP=true make docs-verify | ||||
| ... | ||||
| DOCS_LINT_SKIP is true: no linting done. | ||||
| ``` | ||||
|  | ||||
| ## How to Write a Good Issue | ||||
|  | ||||
| Please keep in mind that the GitHub issue tracker is not intended as a general support forum, but for reporting bugs and feature requests. | ||||
|   | ||||
							
								
								
									
										1244
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1244
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										62
									
								
								Gopkg.toml
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								Gopkg.toml
									
									
									
									
									
								
							| @@ -19,6 +19,11 @@ | ||||
| #  name = "github.com/x/y" | ||||
| #  version = "2.4.0" | ||||
|  | ||||
| [prune] | ||||
|   non-go = true | ||||
|   go-tests = true | ||||
|   unused-packages = true | ||||
|  | ||||
| [[constraint]] | ||||
|   branch = "master" | ||||
|   name = "github.com/ArthurHlt/go-eureka-client" | ||||
| @@ -31,6 +36,10 @@ | ||||
|   branch = "master" | ||||
|   name = "github.com/BurntSushi/ty" | ||||
|  | ||||
| [[constraint]] | ||||
|   name = "github.com/Masterminds/sprig" | ||||
|   version = "2.19.0" | ||||
|  | ||||
| [[constraint]] | ||||
|   branch = "master" | ||||
|   name = "github.com/NYTimes/gziphandler" | ||||
| @@ -40,6 +49,11 @@ | ||||
|   name = "github.com/abbot/go-http-auth" | ||||
|   source = "github.com/containous/go-http-auth" | ||||
|  | ||||
| [[constraint]] | ||||
|   name = "github.com/thoas/stats" | ||||
|   # related to https://github.com/thoas/stats/pull/32 | ||||
|   revision = "4975baf6a358ed3ddaa42133996e1959f96c9300" | ||||
|  | ||||
| [[constraint]] | ||||
|   branch = "master" | ||||
|   name = "github.com/armon/go-proxyproto" | ||||
| @@ -49,12 +63,12 @@ | ||||
|   version = "1.13.11" | ||||
|  | ||||
| [[constraint]] | ||||
|   branch = "master" | ||||
|   name = "github.com/cenk/backoff" | ||||
|   version = "v2.1.1" | ||||
|  | ||||
| [[constraint]] | ||||
|   name = "github.com/containous/flaeg" | ||||
|   version = "1.3.0" | ||||
|   version = "1.4.1" | ||||
|  | ||||
| [[constraint]] | ||||
|   branch = "master" | ||||
| @@ -66,7 +80,7 @@ | ||||
|  | ||||
| [[constraint]] | ||||
|   name = "github.com/containous/traefik-extra-service-fabric" | ||||
|   version = "1.3.0" | ||||
|   version = "v1.5.0" | ||||
|  | ||||
| [[constraint]] | ||||
|   name = "github.com/coreos/go-systemd" | ||||
| @@ -112,8 +126,8 @@ | ||||
|   version = "1.3.7" | ||||
|  | ||||
| [[constraint]] | ||||
|   branch = "master" | ||||
|   name = "github.com/jjcollinge/servicefabric" | ||||
|   revision = "8eebe170fa1ba25d3dfb928b3f86a7313b13b9fe" | ||||
|  | ||||
| [[constraint]] | ||||
|   branch = "master" | ||||
| @@ -123,18 +137,6 @@ | ||||
|   name = "github.com/mesosphere/mesos-dns" | ||||
|   source = "https://github.com/containous/mesos-dns.git" | ||||
|  | ||||
| [[constraint]] | ||||
|   branch = "master" | ||||
|   name = "github.com/mitchellh/copystructure" | ||||
|  | ||||
| [[constraint]] | ||||
|   branch = "master" | ||||
|   name = "github.com/mitchellh/hashstructure" | ||||
|  | ||||
| [[constraint]] | ||||
|   branch = "master" | ||||
|   name = "github.com/mitchellh/mapstructure" | ||||
|  | ||||
| [[constraint]] | ||||
|   name = "github.com/opentracing/opentracing-go" | ||||
|   version = "1.0.2" | ||||
| @@ -148,10 +150,6 @@ | ||||
|   branch = "master" | ||||
|   name = "github.com/ryanuber/go-glob" | ||||
|  | ||||
| [[constraint]] | ||||
|   name = "github.com/satori/go.uuid" | ||||
|   version = "1.1.0" | ||||
|  | ||||
| [[constraint]] | ||||
|   branch = "master" | ||||
|   name = "github.com/stvp/go-udp-testing" | ||||
| @@ -162,7 +160,7 @@ | ||||
|  | ||||
| [[constraint]] | ||||
|   name = "github.com/uber/jaeger-client-go" | ||||
|   version = "2.9.0" | ||||
|   version = "2.15.0" | ||||
|  | ||||
| [[constraint]] | ||||
|   name = "github.com/uber/jaeger-lib" | ||||
| @@ -181,9 +179,12 @@ | ||||
|   name = "github.com/vulcand/oxy" | ||||
|  | ||||
| [[constraint]] | ||||
|   branch = "master" | ||||
|   name = "github.com/xenolf/lego" | ||||
| #  version = "1.0.0" | ||||
|   name = "github.com/go-acme/lego" | ||||
|   version = "2.7.2" | ||||
|  | ||||
| [[constraint]] | ||||
|   name = "github.com/golang/protobuf" | ||||
|   version = "v1.3.0" | ||||
|  | ||||
| [[constraint]] | ||||
|   name = "google.golang.org/grpc" | ||||
| @@ -249,18 +250,17 @@ | ||||
|   revision = "7e6055773c5137efbeb3bd2410d705fe10ab6bfd" | ||||
|  | ||||
| [[override]] | ||||
|   branch = "master" | ||||
|   version = "v1.1.1" | ||||
|   name = "github.com/miekg/dns" | ||||
|  | ||||
| [prune] | ||||
|   non-go = true | ||||
|   go-tests = true | ||||
|   unused-packages = true | ||||
|  | ||||
| [[constraint]] | ||||
|   name = "github.com/patrickmn/go-cache" | ||||
|   version = "2.1.0" | ||||
|  | ||||
| [[constraint]] | ||||
|   name = "gopkg.in/DataDog/dd-trace-go.v1" | ||||
|   version = "1.0.0" | ||||
|   version = "1.13.0" | ||||
|  | ||||
| [[constraint]] | ||||
|   name = "github.com/google/uuid" | ||||
|   version = "0.2.0" | ||||
|   | ||||
							
								
								
									
										11
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								Makefile
									
									
									
									
									
								
							| @@ -23,6 +23,7 @@ TRAEFIK_IMAGE := $(if $(REPONAME),$(REPONAME),"containous/traefik") | ||||
| INTEGRATION_OPTS := $(if $(MAKE_DOCKER_HOST),-e "DOCKER_HOST=$(MAKE_DOCKER_HOST)", -e "TEST_CONTAINER=1" -v "/var/run/docker.sock:/var/run/docker.sock") | ||||
| TRAEFIK_DOC_IMAGE := traefik-docs | ||||
| TRAEFIK_DOC_VERIFY_IMAGE := $(TRAEFIK_DOC_IMAGE)-verify | ||||
| DOCS_VERIFY_SKIP ?= false | ||||
|  | ||||
| DOCKER_BUILD_ARGS := $(if $(DOCKER_VERSION), "--build-arg=DOCKER_VERSION=$(DOCKER_VERSION)",) | ||||
| DOCKER_RUN_OPTS := $(TRAEFIK_ENVS) $(TRAEFIK_MOUNT) "$(TRAEFIK_DEV_IMAGE)" | ||||
| @@ -75,7 +76,7 @@ test-integration: build ## run the integration tests | ||||
| 	TEST_HOST=1 ./script/make.sh test-integration | ||||
|  | ||||
| validate: build  ## validate code, vendor and autogen | ||||
| 	$(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-gofmt validate-govet validate-golint validate-misspell validate-vendor validate-autogen | ||||
| 	$(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-gofmt validate-golint validate-misspell validate-vendor validate-autogen | ||||
|  | ||||
| build: dist | ||||
| 	docker build $(DOCKER_BUILD_ARGS) -t "$(TRAEFIK_DEV_IMAGE)" -f build.Dockerfile . | ||||
| @@ -104,8 +105,12 @@ docs: docs-image | ||||
| docs-build: site | ||||
|  | ||||
| docs-verify: site | ||||
| 	docker build -t $(TRAEFIK_DOC_VERIFY_IMAGE) ./script/docs-verify-docker-image ## Build Validator image | ||||
| 	docker run --rm -v $(CURDIR):/app $(TRAEFIK_DOC_VERIFY_IMAGE) ## Check for dead links and w3c compliance | ||||
| ifeq ($(DOCS_VERIFY_SKIP),false) | ||||
| 	docker build -t $(TRAEFIK_DOC_VERIFY_IMAGE) ./script/docs-verify-docker-image | ||||
| 	docker run --rm -v $(CURDIR):/app $(TRAEFIK_DOC_VERIFY_IMAGE) | ||||
| else | ||||
| 	@echo "DOCS_LINT_SKIP is true: no linting done." | ||||
| endif | ||||
|  | ||||
| site: docs-image | ||||
| 	docker run  $(DOCKER_RUN_DOC_OPTS) $(TRAEFIK_DOC_IMAGE) mkdocs build | ||||
|   | ||||
							
								
								
									
										36
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								README.md
									
									
									
									
									
								
							| @@ -4,7 +4,7 @@ | ||||
| </p> | ||||
|  | ||||
| [](https://semaphoreci.com/containous/traefik) | ||||
| [](https://docs.traefik.io) | ||||
| [](https://docs.traefik.io/v1.7) | ||||
| [](http://goreportcard.com/report/containous/traefik) | ||||
| [](https://microbadger.com/images/traefik) | ||||
| [](https://github.com/containous/traefik/blob/master/LICENSE.md) | ||||
| @@ -70,22 +70,22 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t | ||||
|  | ||||
| ## Supported Backends | ||||
|  | ||||
| - [Docker](https://docs.traefik.io/configuration/backends/docker) / [Swarm mode](https://docs.traefik.io/configuration/backends/docker#docker-swarm-mode) | ||||
| - [Kubernetes](https://docs.traefik.io/configuration/backends/kubernetes) | ||||
| - [Mesos](https://docs.traefik.io/configuration/backends/mesos) / [Marathon](https://docs.traefik.io/configuration/backends/marathon) | ||||
| - [Rancher](https://docs.traefik.io/configuration/backends/rancher) (API, Metadata) | ||||
| - [Azure Service Fabric](https://docs.traefik.io/configuration/backends/servicefabric) | ||||
| - [Consul Catalog](https://docs.traefik.io/configuration/backends/consulcatalog) | ||||
| - [Consul](https://docs.traefik.io/configuration/backends/consul) / [Etcd](https://docs.traefik.io/configuration/backends/etcd) / [Zookeeper](https://docs.traefik.io/configuration/backends/zookeeper) / [BoltDB](https://docs.traefik.io/configuration/backends/boltdb) | ||||
| - [Eureka](https://docs.traefik.io/configuration/backends/eureka) | ||||
| - [Amazon ECS](https://docs.traefik.io/configuration/backends/ecs) | ||||
| - [Amazon DynamoDB](https://docs.traefik.io/configuration/backends/dynamodb) | ||||
| - [File](https://docs.traefik.io/configuration/backends/file) | ||||
| - [Rest](https://docs.traefik.io/configuration/backends/rest) | ||||
| - [Docker](https://docs.traefik.io/v1.7/configuration/backends/docker) / [Swarm mode](https://docs.traefik.io/v1.7/configuration/backends/docker#docker-swarm-mode) | ||||
| - [Kubernetes](https://docs.traefik.io/v1.7/configuration/backends/kubernetes) | ||||
| - [Mesos](https://docs.traefik.io/v1.7/configuration/backends/mesos) / [Marathon](https://docs.traefik.io/v1.7/configuration/backends/marathon) | ||||
| - [Rancher](https://docs.traefik.io/v1.7/configuration/backends/rancher) (API, Metadata) | ||||
| - [Azure Service Fabric](https://docs.traefik.io/v1.7/configuration/backends/servicefabric) | ||||
| - [Consul Catalog](https://docs.traefik.io/v1.7/configuration/backends/consulcatalog) | ||||
| - [Consul](https://docs.traefik.io/v1.7/configuration/backends/consul) / [Etcd](https://docs.traefik.io/v1.7/configuration/backends/etcd) / [Zookeeper](https://docs.traefik.io/v1.7/configuration/backends/zookeeper) / [BoltDB](https://docs.traefik.io/v1.7/configuration/backends/boltdb) | ||||
| - [Eureka](https://docs.traefik.io/v1.7/configuration/backends/eureka) | ||||
| - [Amazon ECS](https://docs.traefik.io/v1.7/configuration/backends/ecs) | ||||
| - [Amazon DynamoDB](https://docs.traefik.io/v1.7/configuration/backends/dynamodb) | ||||
| - [File](https://docs.traefik.io/v1.7/configuration/backends/file) | ||||
| - [Rest](https://docs.traefik.io/v1.7/configuration/backends/rest) | ||||
|  | ||||
| ## Quickstart | ||||
|  | ||||
| To get your hands on Traefik, you can use the [5-Minute Quickstart](http://docs.traefik.io/#the-traefik-quickstart-using-docker) in our documentation (you will need Docker). | ||||
| To get your hands on Traefik, you can use the [5-Minute Quickstart](http://docs.traefik.io/v1.7/#the-traefik-quickstart-using-docker) in our documentation (you will need Docker). | ||||
|  | ||||
| Alternatively, if you don't want to install anything on your computer, you can try Traefik online in this great [Katacoda tutorial](https://www.katacoda.com/courses/traefik/deploy-load-balancer) that shows how to load balance requests between multiple Docker containers.  | ||||
|  | ||||
| @@ -100,7 +100,7 @@ You can access the simple HTML frontend of Traefik. | ||||
|  | ||||
| ## Documentation | ||||
|  | ||||
| You can find the complete documentation at [https://docs.traefik.io](https://docs.traefik.io). | ||||
| You can find the complete documentation at [https://docs.traefik.io/v1.7](https://docs.traefik.io/v1.7). | ||||
| A collection of contributions around Traefik can be found at [https://awesome.traefik.io](https://awesome.traefik.io). | ||||
|  | ||||
| ## Support | ||||
| @@ -113,13 +113,13 @@ If you need commercial support, please contact [Containo.us](https://containo.us | ||||
|  | ||||
| ## Download | ||||
|  | ||||
| - Grab the latest binary from the [releases](https://github.com/containous/traefik/releases) page and run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/master/traefik.sample.toml): | ||||
| - Grab the latest binary from the [releases](https://github.com/containous/traefik/releases) page and run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/v1.7/traefik.sample.toml): | ||||
|  | ||||
| ```shell | ||||
| ./traefik --configFile=traefik.toml | ||||
| ``` | ||||
|  | ||||
| - Or use the official tiny Docker image and run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/master/traefik.sample.toml): | ||||
| - Or use the official tiny Docker image and run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/v1.7/traefik.sample.toml): | ||||
|  | ||||
| ```shell | ||||
| docker run -d -p 8080:8080 -p 80:80 -v $PWD/traefik.toml:/etc/traefik/traefik.toml traefik | ||||
| @@ -133,7 +133,7 @@ git clone https://github.com/containous/traefik | ||||
|  | ||||
| ## Introductory Videos | ||||
|  | ||||
| Here is a talk given by [Emile Vauge](https://github.com/emilevauge) at [GopherCon 2017](https://gophercon.com/). | ||||
| Here is a talk given by [Emile Vauge](https://github.com/emilevauge) at GopherCon 2017. | ||||
| You will learn Traefik basics in less than 10 minutes. | ||||
|  | ||||
| [](https://www.youtube.com/watch?v=RgudiksfL-k) | ||||
|   | ||||
| @@ -17,15 +17,16 @@ import ( | ||||
| 	"github.com/containous/traefik/log" | ||||
| 	acmeprovider "github.com/containous/traefik/provider/acme" | ||||
| 	"github.com/containous/traefik/types" | ||||
| 	"github.com/xenolf/lego/acme" | ||||
| 	"github.com/go-acme/lego/certcrypto" | ||||
| 	"github.com/go-acme/lego/registration" | ||||
| ) | ||||
|  | ||||
| // Account is used to store lets encrypt registration info | ||||
| type Account struct { | ||||
| 	Email              string | ||||
| 	Registration       *acme.RegistrationResource | ||||
| 	Registration       *registration.Resource | ||||
| 	PrivateKey         []byte | ||||
| 	KeyType            acme.KeyType | ||||
| 	KeyType            certcrypto.KeyType | ||||
| 	DomainsCertificate DomainsCertificates | ||||
| 	ChallengeCerts     map[string]*ChallengeCert | ||||
| 	HTTPChallenge      map[string]map[string][]byte | ||||
| @@ -100,7 +101,7 @@ func (a *Account) GetEmail() string { | ||||
| } | ||||
|  | ||||
| // GetRegistration returns lets encrypt registration resource | ||||
| func (a *Account) GetRegistration() *acme.RegistrationResource { | ||||
| func (a *Account) GetRegistration() *registration.Resource { | ||||
| 	return a.Registration | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										106
									
								
								acme/acme.go
									
									
									
									
									
								
							
							
						
						
									
										106
									
								
								acme/acme.go
									
									
									
									
									
								
							| @@ -27,14 +27,19 @@ import ( | ||||
| 	"github.com/containous/traefik/types" | ||||
| 	"github.com/containous/traefik/version" | ||||
| 	"github.com/eapache/channels" | ||||
| 	"github.com/go-acme/lego/certificate" | ||||
| 	"github.com/go-acme/lego/challenge" | ||||
| 	"github.com/go-acme/lego/challenge/dns01" | ||||
| 	"github.com/go-acme/lego/challenge/http01" | ||||
| 	"github.com/go-acme/lego/lego" | ||||
| 	legolog "github.com/go-acme/lego/log" | ||||
| 	"github.com/go-acme/lego/providers/dns" | ||||
| 	"github.com/go-acme/lego/registration" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/xenolf/lego/acme" | ||||
| 	legolog "github.com/xenolf/lego/log" | ||||
| 	"github.com/xenolf/lego/providers/dns" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// OSCPMustStaple enables OSCP stapling as from https://github.com/xenolf/lego/issues/270 | ||||
| 	// OSCPMustStaple enables OSCP stapling as from https://github.com/go-acme/lego/issues/270 | ||||
| 	OSCPMustStaple = false | ||||
| ) | ||||
|  | ||||
| @@ -57,7 +62,7 @@ type ACME struct { | ||||
| 	DelayDontCheckDNS     flaeg.Duration              `description:"(Deprecated) Assume DNS propagates after a delay in seconds rather than finding and querying nameservers."` // Deprecated | ||||
| 	ACMELogging           bool                        `description:"Enable debug logging of ACME actions."` | ||||
| 	OverrideCertificates  bool                        `description:"Enable to override certificates in key-value store when using storeconfig"` | ||||
| 	client                *acme.Client | ||||
| 	client                *lego.Client | ||||
| 	store                 cluster.Store | ||||
| 	challengeHTTPProvider *challengeHTTPProvider | ||||
| 	challengeTLSProvider  *challengeTLSProvider | ||||
| @@ -70,8 +75,6 @@ type ACME struct { | ||||
| } | ||||
|  | ||||
| func (a *ACME) init() error { | ||||
| 	acme.UserAgent = fmt.Sprintf("containous-traefik/%s", version.Version) | ||||
|  | ||||
| 	if a.ACMELogging { | ||||
| 		legolog.Logger = fmtlog.New(log.WriterLevel(logrus.InfoLevel), "legolog: ", 0) | ||||
| 	} else { | ||||
| @@ -89,7 +92,7 @@ func (a *ACME) init() error { | ||||
| // AddRoutes add routes on internal router | ||||
| func (a *ACME) AddRoutes(router *mux.Router) { | ||||
| 	router.Methods(http.MethodGet). | ||||
| 		Path(acme.HTTP01ChallengePath("{token}")). | ||||
| 		Path(http01.ChallengePath("{token}")). | ||||
| 		Handler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { | ||||
| 			if a.challengeHTTPProvider == nil { | ||||
| 				rw.WriteHeader(http.StatusNotFound) | ||||
| @@ -222,7 +225,7 @@ func (a *ACME) leadershipListener(elected bool) error { | ||||
| 			// New users will need to register; be sure to save it | ||||
| 			log.Debug("Register...") | ||||
|  | ||||
| 			reg, err := a.client.Register(true) | ||||
| 			reg, err := a.client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true}) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| @@ -367,7 +370,7 @@ func (a *ACME) renewCertificates() { | ||||
| } | ||||
|  | ||||
| func (a *ACME) renewACMECertificate(certificateResource *DomainsCertificate) (*Certificate, error) { | ||||
| 	renewedCert, err := a.client.RenewCertificate(acme.CertificateResource{ | ||||
| 	renewedCert, err := a.client.Certificate.Renew(certificate.Resource{ | ||||
| 		Domain:        certificateResource.Certificate.Domain, | ||||
| 		CertURL:       certificateResource.Certificate.CertURL, | ||||
| 		CertStableURL: certificateResource.Certificate.CertStableURL, | ||||
| @@ -416,28 +419,19 @@ func (a *ACME) storeRenewedCertificate(certificateResource *DomainsCertificate, | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func dnsOverrideDelay(delay flaeg.Duration) error { | ||||
| 	var err error | ||||
| 	if delay > 0 { | ||||
| 		log.Debugf("Delaying %d rather than validating DNS propagation", delay) | ||||
| 		acme.PreCheckDNS = func(_, _ string) (bool, error) { | ||||
| 			time.Sleep(time.Duration(delay)) | ||||
| 			return true, nil | ||||
| 		} | ||||
| 	} else if delay < 0 { | ||||
| 		err = fmt.Errorf("invalid negative DelayBeforeCheck: %d", delay) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (a *ACME) buildACMEClient(account *Account) (*acme.Client, error) { | ||||
| func (a *ACME) buildACMEClient(account *Account) (*lego.Client, error) { | ||||
| 	log.Debug("Building ACME client...") | ||||
| 	caServer := "https://acme-v02.api.letsencrypt.org/directory" | ||||
| 	if len(a.CAServer) > 0 { | ||||
| 		caServer = a.CAServer | ||||
| 	} | ||||
|  | ||||
| 	client, err := acme.NewClient(caServer, account, account.KeyType) | ||||
| 	config := lego.NewConfig(account) | ||||
| 	config.CADirURL = caServer | ||||
| 	config.Certificate.KeyType = account.KeyType | ||||
| 	config.UserAgent = fmt.Sprintf("containous-traefik/%s", version.Version) | ||||
|  | ||||
| 	client, err := lego.NewClient(config) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -446,22 +440,23 @@ func (a *ACME) buildACMEClient(account *Account) (*acme.Client, error) { | ||||
| 	if a.DNSChallenge != nil && len(a.DNSChallenge.Provider) > 0 { | ||||
| 		log.Debugf("Using DNS Challenge provider: %s", a.DNSChallenge.Provider) | ||||
|  | ||||
| 		err = dnsOverrideDelay(a.DNSChallenge.DelayBeforeCheck) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		acmeprovider.SetRecursiveNameServers(a.DNSChallenge.Resolvers) | ||||
| 		acmeprovider.SetPropagationCheck(a.DNSChallenge.DisablePropagationCheck) | ||||
|  | ||||
| 		var provider acme.ChallengeProvider | ||||
| 		var provider challenge.Provider | ||||
| 		provider, err = dns.NewDNSChallengeProviderByName(a.DNSChallenge.Provider) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.TLSALPN01}) | ||||
| 		err = client.SetChallengeProvider(acme.DNS01, provider) | ||||
| 		err = client.Challenge.SetDNS01Provider(provider, | ||||
| 			dns01.CondOption(len(a.DNSChallenge.Resolvers) > 0, dns01.AddRecursiveNameservers(a.DNSChallenge.Resolvers)), | ||||
| 			dns01.CondOption(a.DNSChallenge.DisablePropagationCheck || a.DNSChallenge.DelayBeforeCheck > 0, | ||||
| 				dns01.AddPreCheck(func(_, _ string) (bool, error) { | ||||
| 					if a.DNSChallenge.DelayBeforeCheck > 0 { | ||||
| 						log.Debugf("Delaying %d rather than validating DNS propagation now.", a.DNSChallenge.DelayBeforeCheck) | ||||
| 						time.Sleep(time.Duration(a.DNSChallenge.DelayBeforeCheck)) | ||||
| 					} | ||||
| 					return true, nil | ||||
| 				})), | ||||
| 		) | ||||
| 		return client, err | ||||
| 	} | ||||
|  | ||||
| @@ -469,17 +464,16 @@ func (a *ACME) buildACMEClient(account *Account) (*acme.Client, error) { | ||||
| 	if a.HTTPChallenge != nil && len(a.HTTPChallenge.EntryPoint) > 0 { | ||||
| 		log.Debug("Using HTTP Challenge provider.") | ||||
|  | ||||
| 		client.ExcludeChallenges([]acme.Challenge{acme.DNS01, acme.TLSALPN01}) | ||||
| 		a.challengeHTTPProvider = &challengeHTTPProvider{store: a.store} | ||||
| 		err = client.SetChallengeProvider(acme.HTTP01, a.challengeHTTPProvider) | ||||
| 		err = client.Challenge.SetHTTP01Provider(a.challengeHTTPProvider) | ||||
| 		return client, err | ||||
| 	} | ||||
|  | ||||
| 	// TLS Challenge | ||||
| 	if a.TLSChallenge != nil { | ||||
| 		log.Debug("Using TLS Challenge provider.") | ||||
| 		client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.DNS01}) | ||||
| 		err = client.SetChallengeProvider(acme.TLSALPN01, a.challengeTLSProvider) | ||||
|  | ||||
| 		err = client.Challenge.SetTLSALPN01Provider(a.challengeTLSProvider) | ||||
| 		return client, err | ||||
| 	} | ||||
|  | ||||
| @@ -551,7 +545,7 @@ func (a *ACME) LoadCertificateForDomains(domains []string) { | ||||
| 		a.addResolvingDomains(uncheckedDomains) | ||||
| 		defer a.removeResolvingDomains(uncheckedDomains) | ||||
|  | ||||
| 		certificate, err := a.getDomainsCertificates(uncheckedDomains) | ||||
| 		cert, err := a.getDomainsCertificates(uncheckedDomains) | ||||
| 		if err != nil { | ||||
| 			log.Errorf("Error getting ACME certificates %+v : %v", uncheckedDomains, err) | ||||
| 			return | ||||
| @@ -570,7 +564,7 @@ func (a *ACME) LoadCertificateForDomains(domains []string) { | ||||
| 			domain = types.Domain{Main: uncheckedDomains[0]} | ||||
| 		} | ||||
| 		account = object.(*Account) | ||||
| 		_, err = account.DomainsCertificate.addCertificateForDomains(certificate, domain) | ||||
| 		_, err = account.DomainsCertificate.addCertificateForDomains(cert, domain) | ||||
| 		if err != nil { | ||||
| 			log.Errorf("Error adding ACME certificates %+v : %v", uncheckedDomains, err) | ||||
| 			return | ||||
| @@ -698,7 +692,7 @@ func (a *ACME) getDomainsCertificates(domains []string) (*Certificate, error) { | ||||
| 	var cleanDomains []string | ||||
| 	for _, domain := range domains { | ||||
| 		canonicalDomain := types.CanonicalDomain(domain) | ||||
| 		cleanDomain := acme.UnFqdn(canonicalDomain) | ||||
| 		cleanDomain := dns01.UnFqdn(canonicalDomain) | ||||
| 		if canonicalDomain != cleanDomain { | ||||
| 			log.Warnf("FQDN detected, please remove the trailing dot: %s", canonicalDomain) | ||||
| 		} | ||||
| @@ -708,18 +702,24 @@ func (a *ACME) getDomainsCertificates(domains []string) (*Certificate, error) { | ||||
| 	log.Debugf("Loading ACME certificates %s...", cleanDomains) | ||||
| 	bundle := true | ||||
|  | ||||
| 	certificate, err := a.client.ObtainCertificate(cleanDomains, bundle, nil, OSCPMustStaple) | ||||
| 	request := certificate.ObtainRequest{ | ||||
| 		Domains:    cleanDomains, | ||||
| 		Bundle:     bundle, | ||||
| 		MustStaple: OSCPMustStaple, | ||||
| 	} | ||||
|  | ||||
| 	cert, err := a.client.Certificate.Obtain(request) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("cannot obtain certificates: %+v", err) | ||||
| 	} | ||||
|  | ||||
| 	log.Debugf("Loaded ACME certificates %s", cleanDomains) | ||||
| 	return &Certificate{ | ||||
| 		Domain:        certificate.Domain, | ||||
| 		CertURL:       certificate.CertURL, | ||||
| 		CertStableURL: certificate.CertStableURL, | ||||
| 		PrivateKey:    certificate.PrivateKey, | ||||
| 		Certificate:   certificate.Certificate, | ||||
| 		Domain:        cert.Domain, | ||||
| 		CertURL:       cert.CertURL, | ||||
| 		CertStableURL: cert.CertStableURL, | ||||
| 		PrivateKey:    cert.PrivateKey, | ||||
| 		Certificate:   cert.Certificate, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| @@ -751,12 +751,6 @@ func (a *ACME) getValidDomains(domains []string, wildcardAllowed bool) ([]string | ||||
| 			return nil, fmt.Errorf("unable to generate a wildcard certificate for domain %q : ACME does not allow '*.*' wildcard domain", strings.Join(domains, ",")) | ||||
| 		} | ||||
| 	} | ||||
| 	for _, san := range domains[1:] { | ||||
| 		if strings.HasPrefix(san, "*") { | ||||
| 			return nil, fmt.Errorf("unable to generate a certificate for domains %q: SANs can not be a wildcard domain", strings.Join(domains, ",")) | ||||
|  | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	domains = fun.Map(types.CanonicalDomain, domains).([]string) | ||||
| 	return domains, nil | ||||
|   | ||||
| @@ -15,7 +15,6 @@ import ( | ||||
| 	"github.com/containous/traefik/tls/generate" | ||||
| 	"github.com/containous/traefik/types" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/xenolf/lego/acme" | ||||
| ) | ||||
|  | ||||
| func TestDomainsSet(t *testing.T) { | ||||
| @@ -258,39 +257,10 @@ func TestRemoveDuplicates(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestNoPreCheckOverride(t *testing.T) { | ||||
| 	acme.PreCheckDNS = nil // Irreversable - but not expecting real calls into this during testing process | ||||
| 	err := dnsOverrideDelay(0) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("Error in dnsOverrideDelay :%v", err) | ||||
| 	} | ||||
| 	if acme.PreCheckDNS != nil { | ||||
| 		t.Error("Unexpected change to acme.PreCheckDNS when leaving DNS verification as is.") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestSillyPreCheckOverride(t *testing.T) { | ||||
| 	err := dnsOverrideDelay(-5) | ||||
| 	if err == nil { | ||||
| 		t.Error("Missing expected error in dnsOverrideDelay!") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestPreCheckOverride(t *testing.T) { | ||||
| 	acme.PreCheckDNS = nil // Irreversable - but not expecting real calls into this during testing process | ||||
| 	err := dnsOverrideDelay(5) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("Error in dnsOverrideDelay :%v", err) | ||||
| 	} | ||||
| 	if acme.PreCheckDNS == nil { | ||||
| 		t.Error("No change to acme.PreCheckDNS when meant to be adding enforcing override function.") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestAcmeClientCreation(t *testing.T) { | ||||
| 	acme.PreCheckDNS = nil // Irreversable - but not expecting real calls into this during testing process | ||||
| 	// Lengthy setup to avoid external web requests - oh for easier golang testing! | ||||
| 	account := &Account{Email: "f@f"} | ||||
|  | ||||
| 	account.PrivateKey, _ = base64.StdEncoding.DecodeString(` | ||||
| MIIBPAIBAAJBAMp2Ni92FfEur+CAvFkgC12LT4l9D53ApbBpDaXaJkzzks+KsLw9zyAxvlrfAyTCQ | ||||
| 7tDnEnIltAXyQ0uOFUUdcMCAwEAAQJAK1FbipATZcT9cGVa5x7KD7usytftLW14heQUPXYNV80r/3 | ||||
| @@ -298,8 +268,9 @@ lmnpvjL06dffRpwkYeN8DATQF/QOcy3NNNGDw/4QIhAPAKmiZFxA/qmRXsuU8Zhlzf16WrNZ68K64 | ||||
| asn/h3qZrAiEA1+wFR3WXCPIolOvd7AHjfgcTKQNkoMPywU4FYUNQ1AkCIQDv8yk0qPjckD6HVCPJ | ||||
| llJh9MC0svjevGtNlxJoE3lmEQIhAKXy1wfZ32/XtcrnENPvi6lzxI0T94X7s5pP3aCoPPoJAiEAl | ||||
| cijFkALeQp/qyeXdFld2v9gUN3eCgljgcl0QweRoIc=---`) | ||||
|  | ||||
| 	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| 		w.Write([]byte(`{ | ||||
| 		_, err := w.Write([]byte(`{ | ||||
|   "GPHhmRVEDas": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417", | ||||
|   "keyChange": "https://foo/acme/key-change", | ||||
|   "meta": { | ||||
| @@ -310,9 +281,20 @@ cijFkALeQp/qyeXdFld2v9gUN3eCgljgcl0QweRoIc=---`) | ||||
|   "newOrder": "https://foo/acme/new-order", | ||||
|   "revokeCert": "https://foo/acme/revoke-cert" | ||||
| }`)) | ||||
| 		if err != nil { | ||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) | ||||
| 		} | ||||
| 	})) | ||||
| 	defer ts.Close() | ||||
| 	a := ACME{DNSChallenge: &acmeprovider.DNSChallenge{Provider: "manual", DelayBeforeCheck: 10}, CAServer: ts.URL} | ||||
|  | ||||
| 	a := ACME{ | ||||
| 		CAServer: ts.URL, | ||||
| 		DNSChallenge: &acmeprovider.DNSChallenge{ | ||||
| 			Provider:                "manual", | ||||
| 			DelayBeforeCheck:        10, | ||||
| 			DisablePropagationCheck: true, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	client, err := a.buildACMEClient(account) | ||||
| 	if err != nil { | ||||
| @@ -321,9 +303,6 @@ cijFkALeQp/qyeXdFld2v9gUN3eCgljgcl0QweRoIc=---`) | ||||
| 	if client == nil { | ||||
| 		t.Error("No client from buildACMEClient!") | ||||
| 	} | ||||
| 	if acme.PreCheckDNS == nil { | ||||
| 		t.Error("No change to acme.PreCheckDNS when meant to be adding enforcing override function.") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestAcme_getUncheckedCertificates(t *testing.T) { | ||||
| @@ -440,12 +419,12 @@ func TestAcme_getValidDomain(t *testing.T) { | ||||
| 			expectedDomains: []string{"*.traefik.wtf", "traefik.wtf"}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc:            "unexpected SANs", | ||||
| 			desc:            "wildcard SANs", | ||||
| 			domains:         []string{"*.traefik.wtf", "*.acme.wtf"}, | ||||
| 			dnsChallenge:    &acmeprovider.DNSChallenge{}, | ||||
| 			wildcardAllowed: true, | ||||
| 			expectedErr:     "unable to generate a certificate for domains \"*.traefik.wtf,*.acme.wtf\": SANs can not be a wildcard domain", | ||||
| 			expectedDomains: nil, | ||||
| 			expectedErr:     "", | ||||
| 			expectedDomains: []string{"*.traefik.wtf", "*.acme.wtf"}, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, test := range testCases { | ||||
|   | ||||
| @@ -9,10 +9,10 @@ import ( | ||||
| 	"github.com/containous/traefik/cluster" | ||||
| 	"github.com/containous/traefik/log" | ||||
| 	"github.com/containous/traefik/safe" | ||||
| 	"github.com/xenolf/lego/acme" | ||||
| 	"github.com/go-acme/lego/challenge" | ||||
| ) | ||||
|  | ||||
| var _ acme.ChallengeProviderTimeout = (*challengeHTTPProvider)(nil) | ||||
| var _ challenge.ProviderTimeout = (*challengeHTTPProvider)(nil) | ||||
|  | ||||
| type challengeHTTPProvider struct { | ||||
| 	store cluster.Store | ||||
|   | ||||
| @@ -11,10 +11,11 @@ import ( | ||||
| 	"github.com/containous/traefik/cluster" | ||||
| 	"github.com/containous/traefik/log" | ||||
| 	"github.com/containous/traefik/safe" | ||||
| 	"github.com/xenolf/lego/acme" | ||||
| 	"github.com/go-acme/lego/challenge" | ||||
| 	"github.com/go-acme/lego/challenge/tlsalpn01" | ||||
| ) | ||||
|  | ||||
| var _ acme.ChallengeProviderTimeout = (*challengeTLSProvider)(nil) | ||||
| var _ challenge.ProviderTimeout = (*challengeTLSProvider)(nil) | ||||
|  | ||||
| type challengeTLSProvider struct { | ||||
| 	store cluster.Store | ||||
| @@ -113,7 +114,7 @@ func (c *challengeTLSProvider) Timeout() (timeout, interval time.Duration) { | ||||
| } | ||||
|  | ||||
| func tlsALPN01ChallengeCert(domain, keyAuth string) (*ChallengeCert, error) { | ||||
| 	tempCertPEM, rsaPrivPEM, err := acme.TLSALPNChallengeBlocks(domain, keyAuth) | ||||
| 	tempCertPEM, rsaPrivPEM, err := tlsalpn01.ChallengeBlocks(domain, keyAuth) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|   | ||||
| @@ -31,7 +31,7 @@ import ( | ||||
| 	"github.com/containous/traefik/safe" | ||||
| 	traefiktls "github.com/containous/traefik/tls" | ||||
| 	"github.com/containous/traefik/types" | ||||
| 	"github.com/elazarl/go-bindata-assetfs" | ||||
| 	assetfs "github.com/elazarl/go-bindata-assetfs" | ||||
| 	"github.com/thoas/stats" | ||||
| ) | ||||
|  | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/containous/mux" | ||||
| 	"github.com/containous/traefik/log" | ||||
| 	"github.com/elazarl/go-bindata-assetfs" | ||||
| 	assetfs "github.com/elazarl/go-bindata-assetfs" | ||||
| ) | ||||
|  | ||||
| // DashboardHandler expose dashboard routes | ||||
|   | ||||
| @@ -9,7 +9,7 @@ import ( | ||||
| 	"github.com/containous/traefik/safe" | ||||
| 	"github.com/containous/traefik/types" | ||||
| 	"github.com/containous/traefik/version" | ||||
| 	"github.com/elazarl/go-bindata-assetfs" | ||||
| 	assetfs "github.com/elazarl/go-bindata-assetfs" | ||||
| 	thoas_stats "github.com/thoas/stats" | ||||
| 	"github.com/unrolled/render" | ||||
| ) | ||||
|   | ||||
| @@ -236,6 +236,18 @@ var _templatesConsul_catalogTmpl = []byte(`[backends] | ||||
|           organization = {{ $subject.Organization }} | ||||
|           commonName = {{ $subject.CommonName }} | ||||
|           serialNumber = {{ $subject.SerialNumber }} | ||||
|           domainComponent = {{ $subject.DomainComponent }} | ||||
|         {{end}} | ||||
|         {{ $issuer := $infos.Subject }} | ||||
|         {{if $issuer }} | ||||
|         [frontends."frontend-{{ $service.ServiceName }}".passTLSClientCert.infos.issuer] | ||||
|           country = {{ $issuer.Country }} | ||||
|           province = {{ $issuer.Province }} | ||||
|           locality = {{ $issuer.Locality }} | ||||
|           organization = {{ $issuer.Organization }} | ||||
|           commonName = {{ $issuer.CommonName }} | ||||
|           serialNumber = {{ $issuer.SerialNumber }} | ||||
|           domainComponent = {{ $issuer.DomainComponent }} | ||||
|         {{end}} | ||||
|       {{end}} | ||||
|     {{end}} | ||||
| @@ -719,6 +731,18 @@ var _templatesDockerTmpl = []byte(`{{$backendServers := .Servers}} | ||||
|           organization = {{ $subject.Organization }} | ||||
|           commonName = {{ $subject.CommonName }} | ||||
|           serialNumber = {{ $subject.SerialNumber }} | ||||
|           domainComponent = {{ $subject.DomainComponent }} | ||||
|         {{end}} | ||||
|         {{ $issuer := $infos.Issuer }} | ||||
|         {{if $issuer }} | ||||
|         [frontends."frontend-{{ $frontendName }}".passTLSClientCert.infos.issuer] | ||||
|           country = {{ $issuer.Country }} | ||||
|           province = {{ $issuer.Province }} | ||||
|           locality = {{ $issuer.Locality }} | ||||
|           organization = {{ $issuer.Organization }} | ||||
|           commonName = {{ $issuer.CommonName }} | ||||
|           serialNumber = {{ $issuer.SerialNumber }} | ||||
|           domainComponent = {{ $issuer.DomainComponent }} | ||||
|         {{end}} | ||||
|       {{end}} | ||||
|     {{end}} | ||||
| @@ -1055,6 +1079,18 @@ var _templatesEcsTmpl = []byte(`[backends] | ||||
|           organization = {{ $subject.Organization }} | ||||
|           commonName = {{ $subject.CommonName }} | ||||
|           serialNumber = {{ $subject.SerialNumber }} | ||||
|           domainComponent = {{ $subject.DomainComponent }} | ||||
|         {{end}} | ||||
|         {{ $issuer := $infos.Issuer }} | ||||
|         {{if $issuer }} | ||||
|         [frontends."frontend-{{ $frontendName }}".passTLSClientCert.infos.issuer] | ||||
|           country = {{ $issuer.Country }} | ||||
|           province = {{ $issuer.Province }} | ||||
|           locality = {{ $issuer.Locality }} | ||||
|           organization = {{ $issuer.Organization }} | ||||
|           commonName = {{ $issuer.CommonName }} | ||||
|           serialNumber = {{ $issuer.SerialNumber }} | ||||
|           domainComponent = {{ $issuer.DomainComponent }} | ||||
|         {{end}} | ||||
|       {{end}} | ||||
|     {{end}} | ||||
| @@ -1280,7 +1316,7 @@ var _templatesKubernetesTmpl = []byte(`[backends] | ||||
|  | ||||
|     {{if $backend.ResponseForwarding }} | ||||
|     [backends."{{ $backendName }}".responseForwarding] | ||||
|       flushInterval = "{{ $backend.responseForwarding.FlushInterval }}" | ||||
|       flushInterval = "{{ $backend.ResponseForwarding.FlushInterval }}" | ||||
|     {{end}} | ||||
|  | ||||
|     [backends."{{ $backendName }}".loadBalancer] | ||||
| @@ -1329,7 +1365,9 @@ var _templatesKubernetesTmpl = []byte(`[backends] | ||||
|  | ||||
|     {{if $frontend.Auth }} | ||||
|     [frontends."{{ $frontendName }}".auth] | ||||
|       headerField = "X-WebAuth-User" | ||||
|       {{if $frontend.Auth.HeaderField }} | ||||
|       headerField = "{{ $frontend.Auth.HeaderField }}" | ||||
|       {{end}} | ||||
|  | ||||
|       {{if $frontend.Auth.Basic }} | ||||
|       [frontends."{{ $frontendName }}".auth.basic] | ||||
| @@ -1422,6 +1460,18 @@ var _templatesKubernetesTmpl = []byte(`[backends] | ||||
|           organization = {{ $subject.Organization }} | ||||
|           commonName = {{ $subject.CommonName }} | ||||
|           serialNumber = {{ $subject.SerialNumber }} | ||||
|           domainComponent = {{ $subject.DomainComponent }} | ||||
|         {{end}} | ||||
|         {{ $issuer := $infos.Subject }} | ||||
|         {{if $issuer }} | ||||
|         [frontends."{{ $frontendName }}".passTLSClientCert.infos.issuer] | ||||
|           country = {{ $issuer.Country }} | ||||
|           province = {{ $issuer.Province }} | ||||
|           locality = {{ $issuer.Locality }} | ||||
|           organization = {{ $issuer.Organization }} | ||||
|           commonName = {{ $issuer.CommonName }} | ||||
|           serialNumber = {{ $issuer.SerialNumber }} | ||||
|           domainComponent = {{ $issuer.DomainComponent }} | ||||
|         {{end}} | ||||
|       {{end}} | ||||
|     {{end}} | ||||
| @@ -1609,6 +1659,18 @@ var _templatesKvTmpl = []byte(`[backends] | ||||
|           organization = {{ $subject.Organization }} | ||||
|           commonName = {{ $subject.CommonName }} | ||||
|           serialNumber = {{ $subject.SerialNumber }} | ||||
|           domainComponent = {{ $subject.DomainComponent }} | ||||
|         {{end}} | ||||
|         {{ $issuer := $infos.Subject }} | ||||
|         {{if $issuer }} | ||||
|         [frontends."{{ $frontendName }}".passTLSClientCert.infos.issuer] | ||||
|           country = {{ $issuer.Country }} | ||||
|           province = {{ $issuer.Province }} | ||||
|           locality = {{ $issuer.Locality }} | ||||
|           organization = {{ $issuer.Organization }} | ||||
|           commonName = {{ $issuer.CommonName }} | ||||
|           serialNumber = {{ $issuer.SerialNumber }} | ||||
|           domainComponent = {{ $issuer.DomainComponent }} | ||||
|         {{end}} | ||||
|       {{end}} | ||||
|     {{end}} | ||||
| @@ -1985,6 +2047,18 @@ var _templatesMarathonTmpl = []byte(`{{ $apps := .Applications }} | ||||
|           organization = {{ $subject.Organization }} | ||||
|           commonName = {{ $subject.CommonName }} | ||||
|           serialNumber = {{ $subject.SerialNumber }} | ||||
|           domainComponent = {{ $subject.DomainComponent }} | ||||
|         {{end}} | ||||
|         {{ $issuer := $infos.Subject }} | ||||
|         {{if $issuer }} | ||||
|         [frontends."{{ $frontendName }}".passTLSClientCert.infos.issuer] | ||||
|           country = {{ $issuer.Country }} | ||||
|           province = {{ $issuer.Province }} | ||||
|           locality = {{ $issuer.Locality }} | ||||
|           organization = {{ $issuer.Organization }} | ||||
|           commonName = {{ $issuer.CommonName }} | ||||
|           serialNumber = {{ $issuer.SerialNumber }} | ||||
|           domainComponent = {{ $issuer.DomainComponent }} | ||||
|         {{end}} | ||||
|       {{end}} | ||||
|     {{end}} | ||||
| @@ -2305,6 +2379,18 @@ var _templatesMesosTmpl = []byte(`[backends] | ||||
|           organization = {{ $subject.Organization }} | ||||
|           commonName = {{ $subject.CommonName }} | ||||
|           serialNumber = {{ $subject.SerialNumber }} | ||||
|           domainComponent = {{ $subject.DomainComponent }} | ||||
|         {{end}} | ||||
|         {{ $issuer := $infos.Subject }} | ||||
|         {{if $issuer }} | ||||
|         [frontends."frontend-{{ $frontendName }}".passTLSClientCert.infos.issuer] | ||||
|           country = {{ $issuer.Country }} | ||||
|           province = {{ $issuer.Province }} | ||||
|           locality = {{ $issuer.Locality }} | ||||
|           organization = {{ $issuer.Organization }} | ||||
|           commonName = {{ $issuer.CommonName }} | ||||
|           serialNumber = {{ $issuer.SerialNumber }} | ||||
|           domainComponent = {{ $issuer.DomainComponent }} | ||||
|         {{end}} | ||||
|       {{end}} | ||||
|     {{end}} | ||||
| @@ -2678,6 +2764,18 @@ var _templatesRancherTmpl = []byte(`{{ $backendServers := .Backends }} | ||||
|           organization = {{ $subject.Organization }} | ||||
|           commonName = {{ $subject.CommonName }} | ||||
|           serialNumber = {{ $subject.SerialNumber }} | ||||
|           domainComponent = {{ $subject.DomainComponent }} | ||||
|         {{end}} | ||||
|         {{ $issuer := $infos.Subject }} | ||||
|         {{if $issuer }} | ||||
|         [frontends."frontend-{{ $frontendName }}".passTLSClientCert.infos.issuer] | ||||
|           country = {{ $issuer.Country }} | ||||
|           province = {{ $issuer.Province }} | ||||
|           locality = {{ $issuer.Locality }} | ||||
|           organization = {{ $issuer.Organization }} | ||||
|           commonName = {{ $issuer.CommonName }} | ||||
|           serialNumber = {{ $issuer.SerialNumber }} | ||||
|           domainComponent = {{ $issuer.DomainComponent }} | ||||
|         {{end}} | ||||
|       {{end}} | ||||
|     {{end}} | ||||
|   | ||||
| @@ -1,17 +1,21 @@ | ||||
| FROM golang:1.11-alpine | ||||
| FROM golang:1.12-alpine | ||||
|  | ||||
| RUN apk --update upgrade \ | ||||
| && apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar \ | ||||
| && rm -rf /var/cache/apk/* | ||||
|     && apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \ | ||||
|     && update-ca-certificates \ | ||||
|     && rm -rf /var/cache/apk/* | ||||
|  | ||||
| RUN go get github.com/containous/go-bindata/... \ | ||||
| && go get golang.org/x/lint/golint \ | ||||
| && go get github.com/kisielk/errcheck \ | ||||
| RUN go get golang.org/x/lint/golint \ | ||||
| && go get github.com/client9/misspell/cmd/misspell | ||||
|  | ||||
| # Which docker version to test on | ||||
| ARG DOCKER_VERSION=17.03.2 | ||||
| ARG DEP_VERSION=0.4.1 | ||||
| ARG DOCKER_VERSION=18.09.7 | ||||
| ARG DEP_VERSION=0.5.1 | ||||
|  | ||||
| # Download go-bindata binary to bin folder in $GOPATH | ||||
| RUN mkdir -p /usr/local/bin \ | ||||
|     && curl -fsSL -o /usr/local/bin/go-bindata https://github.com/containous/go-bindata/releases/download/v1.0.0/go-bindata \ | ||||
|     && chmod +x /usr/local/bin/go-bindata | ||||
|  | ||||
| # Download dep binary to bin folder in $GOPATH | ||||
| RUN mkdir -p /usr/local/bin \ | ||||
| @@ -20,7 +24,7 @@ RUN mkdir -p /usr/local/bin \ | ||||
|  | ||||
| # Download docker | ||||
| RUN mkdir -p /usr/local/bin \ | ||||
|     && curl -fL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}-ce.tgz \ | ||||
|     && curl -fL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz \ | ||||
|     | tar -xzC /usr/local/bin --transform 's#^.+/##x' | ||||
|  | ||||
| WORKDIR /go/src/github.com/containous/traefik | ||||
|   | ||||
| @@ -13,7 +13,7 @@ import ( | ||||
| 	"github.com/containous/traefik/job" | ||||
| 	"github.com/containous/traefik/log" | ||||
| 	"github.com/containous/traefik/safe" | ||||
| 	"github.com/satori/go.uuid" | ||||
| 	"github.com/google/uuid" | ||||
| ) | ||||
|  | ||||
| // Metadata stores Object plus metadata | ||||
| @@ -125,7 +125,7 @@ func (d *Datastore) reload() error { | ||||
|  | ||||
| // Begin creates a transaction with the KV store. | ||||
| func (d *Datastore) Begin() (Transaction, Object, error) { | ||||
| 	id := uuid.NewV4().String() | ||||
| 	id := uuid.New().String() | ||||
| 	log.Debugf("Transaction %s begins", id) | ||||
| 	remoteLock, err := d.kv.NewLock(d.lockKey, &store.LockOptions{TTL: 20 * time.Second, Value: []byte(id)}) | ||||
| 	if err != nil { | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/containous/flaeg" | ||||
| 	"github.com/containous/traefik-extra-service-fabric" | ||||
| 	servicefabric "github.com/containous/traefik-extra-service-fabric" | ||||
| 	"github.com/containous/traefik/api" | ||||
| 	"github.com/containous/traefik/configuration" | ||||
| 	"github.com/containous/traefik/middlewares/accesslog" | ||||
| @@ -46,6 +46,7 @@ func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration { | ||||
| 	defaultDocker.ExposedByDefault = true | ||||
| 	defaultDocker.Endpoint = "unix:///var/run/docker.sock" | ||||
| 	defaultDocker.SwarmMode = false | ||||
| 	defaultDocker.SwarmModeRefreshSeconds = 15 | ||||
|  | ||||
| 	// default File | ||||
| 	var defaultFile file.Provider | ||||
| @@ -110,6 +111,7 @@ func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration { | ||||
| 	defaultConsulCatalog.Prefix = "traefik" | ||||
| 	defaultConsulCatalog.FrontEndRule = "Host:{{.ServiceName}}.{{.Domain}}" | ||||
| 	defaultConsulCatalog.Stale = false | ||||
| 	defaultConsulCatalog.StrictChecks = true | ||||
|  | ||||
| 	// default Etcd | ||||
| 	var defaultEtcd etcd.Provider | ||||
| @@ -223,10 +225,11 @@ func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration { | ||||
| 		ServiceName:   "traefik", | ||||
| 		SpanNameLimit: 0, | ||||
| 		Jaeger: &jaeger.Config{ | ||||
| 			SamplingServerURL:  "http://localhost:5778/sampling", | ||||
| 			SamplingType:       "const", | ||||
| 			SamplingParam:      1.0, | ||||
| 			LocalAgentHostPort: "127.0.0.1:6831", | ||||
| 			SamplingServerURL:      "http://localhost:5778/sampling", | ||||
| 			SamplingType:           "const", | ||||
| 			SamplingParam:          1.0, | ||||
| 			LocalAgentHostPort:     "127.0.0.1:6831", | ||||
| 			TraceContextHeaderName: "uber-trace-id", | ||||
| 		}, | ||||
| 		Zipkin: &zipkin.Config{ | ||||
| 			HTTPEndpoint: "http://localhost:9411/api/v1/spans", | ||||
| @@ -238,6 +241,7 @@ func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration { | ||||
| 			LocalAgentHostPort: "localhost:8126", | ||||
| 			GlobalTag:          "", | ||||
| 			Debug:              false, | ||||
| 			PrioritySampling:   false, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -34,7 +34,7 @@ import ( | ||||
| 	"github.com/containous/traefik/types" | ||||
| 	"github.com/containous/traefik/version" | ||||
| 	"github.com/coreos/go-systemd/daemon" | ||||
| 	"github.com/elazarl/go-bindata-assetfs" | ||||
| 	assetfs "github.com/elazarl/go-bindata-assetfs" | ||||
| 	"github.com/ogier/pflag" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/vulcand/oxy/roundrobin" | ||||
| @@ -352,14 +352,14 @@ func stats(globalConfiguration *configuration.GlobalConfiguration) { | ||||
| Stats collection is enabled. | ||||
| Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration. | ||||
| Help us improve Traefik by leaving this feature on :) | ||||
| More details on: https://docs.traefik.io/basics/#collected-data | ||||
| More details on: https://docs.traefik.io/v1.7/basics/#collected-data | ||||
| `) | ||||
| 		collect(globalConfiguration) | ||||
| 	} else { | ||||
| 		log.Info(` | ||||
| Stats collection is disabled. | ||||
| Help us improve Traefik by turning this feature on :) | ||||
| More details on: https://docs.traefik.io/basics/#collected-data | ||||
| More details on: https://docs.traefik.io/v1.7/basics/#collected-data | ||||
| `) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -6,7 +6,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/containous/flaeg" | ||||
| 	"github.com/containous/traefik-extra-service-fabric" | ||||
| 	servicefabric "github.com/containous/traefik-extra-service-fabric" | ||||
| 	"github.com/containous/traefik/acme" | ||||
| 	"github.com/containous/traefik/api" | ||||
| 	"github.com/containous/traefik/log" | ||||
| @@ -33,8 +33,9 @@ import ( | ||||
| 	"github.com/containous/traefik/provider/zk" | ||||
| 	"github.com/containous/traefik/tls" | ||||
| 	"github.com/containous/traefik/types" | ||||
| 	"github.com/go-acme/lego/challenge/dns01" | ||||
| 	"github.com/pkg/errors" | ||||
| 	lego "github.com/xenolf/lego/acme" | ||||
| 	jaegercli "github.com/uber/jaeger-client-go" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| @@ -211,6 +212,12 @@ func (gc *GlobalConfiguration) SetEffectiveConfiguration(configFile string) { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// Thanks to SSLv3 being enabled by mistake in golang 1.12, | ||||
| 		// If no minVersion is set, apply TLS1.0 as the minimum. | ||||
| 		if entryPoint.TLS != nil && len(entryPoint.TLS.MinVersion) == 0 { | ||||
| 			entryPoint.TLS.MinVersion = "VersionTLS10" | ||||
| 		} | ||||
|  | ||||
| 		if entryPoint.TLS != nil && entryPoint.TLS.DefaultCertificate == nil && len(entryPoint.TLS.Certificates) > 0 { | ||||
| 			log.Infof("No tls.defaultCertificate given for %s: using the first item in tls.certificates as a fallback.", entryPointName) | ||||
| 			entryPoint.TLS.DefaultCertificate = &entryPoint.TLS.Certificates[0] | ||||
| @@ -235,6 +242,10 @@ func (gc *GlobalConfiguration) SetEffectiveConfiguration(configFile string) { | ||||
| 		} else { | ||||
| 			gc.Docker.TemplateVersion = 2 | ||||
| 		} | ||||
|  | ||||
| 		if gc.Docker.SwarmModeRefreshSeconds <= 0 { | ||||
| 			gc.Docker.SwarmModeRefreshSeconds = 15 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if gc.Marathon != nil { | ||||
| @@ -331,10 +342,11 @@ func (gc *GlobalConfiguration) initTracing() { | ||||
| 		case jaeger.Name: | ||||
| 			if gc.Tracing.Jaeger == nil { | ||||
| 				gc.Tracing.Jaeger = &jaeger.Config{ | ||||
| 					SamplingServerURL:  "http://localhost:5778/sampling", | ||||
| 					SamplingType:       "const", | ||||
| 					SamplingParam:      1.0, | ||||
| 					LocalAgentHostPort: "127.0.0.1:6831", | ||||
| 					SamplingServerURL:      "http://localhost:5778/sampling", | ||||
| 					SamplingType:           "const", | ||||
| 					SamplingParam:          1.0, | ||||
| 					LocalAgentHostPort:     "127.0.0.1:6831", | ||||
| 					TraceContextHeaderName: jaegercli.TraceContextHeaderName, | ||||
| 				} | ||||
| 			} | ||||
| 			if gc.Tracing.Zipkin != nil { | ||||
| @@ -368,6 +380,7 @@ func (gc *GlobalConfiguration) initTracing() { | ||||
| 					LocalAgentHostPort: "localhost:8126", | ||||
| 					GlobalTag:          "", | ||||
| 					Debug:              false, | ||||
| 					PrioritySampling:   false, | ||||
| 				} | ||||
| 			} | ||||
| 			if gc.Tracing.Zipkin != nil { | ||||
| @@ -405,11 +418,11 @@ func (gc *GlobalConfiguration) initACMEProvider() { | ||||
| 		} | ||||
|  | ||||
| 		for _, domain := range gc.ACME.Domains { | ||||
| 			if domain.Main != lego.UnFqdn(domain.Main) { | ||||
| 			if domain.Main != dns01.UnFqdn(domain.Main) { | ||||
| 				log.Warnf("FQDN detected, please remove the trailing dot: %s", domain.Main) | ||||
| 			} | ||||
| 			for _, san := range domain.SANs { | ||||
| 				if san != lego.UnFqdn(san) { | ||||
| 				if san != dns01.UnFqdn(san) { | ||||
| 					log.Warnf("FQDN detected, please remove the trailing dot: %s", san) | ||||
| 				} | ||||
| 			} | ||||
|   | ||||
| @@ -12,6 +12,7 @@ import ( | ||||
| 	"github.com/containous/traefik/provider" | ||||
| 	acmeprovider "github.com/containous/traefik/provider/acme" | ||||
| 	"github.com/containous/traefik/provider/file" | ||||
| 	"github.com/containous/traefik/tls" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| @@ -142,10 +143,11 @@ func TestSetEffectiveConfigurationTracing(t *testing.T) { | ||||
| 			expected: &tracing.Tracing{ | ||||
| 				Backend: "jaeger", | ||||
| 				Jaeger: &jaeger.Config{ | ||||
| 					SamplingServerURL:  "http://localhost:5778/sampling", | ||||
| 					SamplingType:       "const", | ||||
| 					SamplingParam:      1.0, | ||||
| 					LocalAgentHostPort: "127.0.0.1:6831", | ||||
| 					SamplingServerURL:      "http://localhost:5778/sampling", | ||||
| 					SamplingType:           "const", | ||||
| 					SamplingParam:          1.0, | ||||
| 					LocalAgentHostPort:     "127.0.0.1:6831", | ||||
| 					TraceContextHeaderName: "uber-trace-id", | ||||
| 				}, | ||||
| 				Zipkin: nil, | ||||
| 			}, | ||||
| @@ -155,10 +157,11 @@ func TestSetEffectiveConfigurationTracing(t *testing.T) { | ||||
| 			tracing: &tracing.Tracing{ | ||||
| 				Backend: "zipkin", | ||||
| 				Jaeger: &jaeger.Config{ | ||||
| 					SamplingServerURL:  "http://localhost:5778/sampling", | ||||
| 					SamplingType:       "const", | ||||
| 					SamplingParam:      1.0, | ||||
| 					LocalAgentHostPort: "127.0.0.1:6831", | ||||
| 					SamplingServerURL:      "http://localhost:5778/sampling", | ||||
| 					SamplingType:           "const", | ||||
| 					SamplingParam:          1.0, | ||||
| 					LocalAgentHostPort:     "127.0.0.1:6831", | ||||
| 					TraceContextHeaderName: "uber-trace-id", | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: &tracing.Tracing{ | ||||
| @@ -177,10 +180,11 @@ func TestSetEffectiveConfigurationTracing(t *testing.T) { | ||||
| 			tracing: &tracing.Tracing{ | ||||
| 				Backend: "zipkin", | ||||
| 				Jaeger: &jaeger.Config{ | ||||
| 					SamplingServerURL:  "http://localhost:5778/sampling", | ||||
| 					SamplingType:       "const", | ||||
| 					SamplingParam:      1.0, | ||||
| 					LocalAgentHostPort: "127.0.0.1:6831", | ||||
| 					SamplingServerURL:      "http://localhost:5778/sampling", | ||||
| 					SamplingType:           "const", | ||||
| 					SamplingParam:          1.0, | ||||
| 					LocalAgentHostPort:     "127.0.0.1:6831", | ||||
| 					TraceContextHeaderName: "uber-trace-id", | ||||
| 				}, | ||||
| 				Zipkin: &zipkin.Config{ | ||||
| 					HTTPEndpoint: "http://powpow:9411/api/v1/spans", | ||||
| @@ -266,3 +270,69 @@ func TestInitACMEProvider(t *testing.T) { | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestSetEffectiveConfigurationTLSMinVersion(t *testing.T) { | ||||
| 	testCases := []struct { | ||||
| 		desc     string | ||||
| 		provided EntryPoint | ||||
| 		expected EntryPoint | ||||
| 	}{ | ||||
| 		{ | ||||
| 			desc: "Entrypoint with no TLS", | ||||
| 			provided: EntryPoint{ | ||||
| 				Address: ":80", | ||||
| 			}, | ||||
| 			expected: EntryPoint{ | ||||
| 				Address:          ":80", | ||||
| 				ForwardedHeaders: &ForwardedHeaders{Insecure: true}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc: "Entrypoint with TLS Specifying MinVersion", | ||||
| 			provided: EntryPoint{ | ||||
| 				Address: ":443", | ||||
| 				TLS: &tls.TLS{ | ||||
| 					MinVersion: "VersionTLS12", | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: EntryPoint{ | ||||
| 				Address:          ":443", | ||||
| 				ForwardedHeaders: &ForwardedHeaders{Insecure: true}, | ||||
| 				TLS: &tls.TLS{ | ||||
| 					MinVersion: "VersionTLS12", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc: "Entrypoint with TLS without Specifying MinVersion", | ||||
| 			provided: EntryPoint{ | ||||
| 				Address: ":443", | ||||
| 				TLS:     &tls.TLS{}, | ||||
| 			}, | ||||
| 			expected: EntryPoint{ | ||||
| 				Address:          ":443", | ||||
| 				ForwardedHeaders: &ForwardedHeaders{Insecure: true}, | ||||
| 				TLS: &tls.TLS{ | ||||
| 					MinVersion: "VersionTLS10", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range testCases { | ||||
| 		test := test | ||||
| 		t.Run(test.desc, func(t *testing.T) { | ||||
| 			t.Parallel() | ||||
|  | ||||
| 			gc := &GlobalConfiguration{ | ||||
| 				EntryPoints: map[string]*EntryPoint{ | ||||
| 					"foo": &test.provided, | ||||
| 				}, | ||||
| 			} | ||||
|  | ||||
| 			gc.SetEffectiveConfiguration(defaultConfigFile) | ||||
|  | ||||
| 			assert.Equal(t, &test.expected, gc.EntryPoints["foo"]) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -155,7 +155,8 @@ echo -e "-----BEGIN RSA PRIVATE KEY-----\n${priv}\n-----END RSA PRIVATE KEY----- | ||||
|    | openssl rsa -inform pem -out "${pdir}/letsencrypt.key" | ||||
|  | ||||
| # Process the certificates for each of the domains in acme.json | ||||
| for domain in $(jq -r '.Certificates[].Domain.Main' ${acmefile}); do | ||||
| domains=$(jq -r '.Certificates[].Domain.Main' ${acmefile}) || bad_acme | ||||
| for domain in $domains; do | ||||
| 	# Traefik stores a cert bundle for each domain.  Within this cert | ||||
| 	# bundle there is both proper the certificate and the Let's Encrypt CA | ||||
| 	echo "Extracting cert bundle for ${domain}" | ||||
|   | ||||
| @@ -1,11 +1,41 @@ | ||||
| [Unit] | ||||
| Description=Traefik | ||||
| Documentation=https://docs.traefik.io/v1.7 | ||||
| #After=network-online.target | ||||
| #AssertFileIsExecutable=/usr/bin/traefik | ||||
| #AssertPathExists=/etc/traefik/traefik.toml | ||||
|  | ||||
| [Service] | ||||
| # Run traefik as its own user (create new user with: useradd -r -s /bin/false -U -M traefik) | ||||
| #User=traefik | ||||
| #AmbientCapabilities=CAP_NET_BIND_SERVICE | ||||
|  | ||||
| # configure service behavior | ||||
| Type=notify | ||||
| ExecStart=/usr/bin/traefik --configFile=/etc/traefik.toml | ||||
| #ExecStart=/usr/bin/traefik --configFile=/etc/traefik/traefik.toml | ||||
| Restart=always | ||||
| WatchdogSec=1s | ||||
|  | ||||
| # lock down system access | ||||
| # prohibit any operating system and configuration modification | ||||
| #ProtectSystem=strict | ||||
| # create separate, new (and empty) /tmp and /var/tmp filesystems | ||||
| #PrivateTmp=true | ||||
| # make /home directories inaccessible | ||||
| #ProtectHome=true | ||||
| # turns off access to physical devices (/dev/...) | ||||
| #PrivateDevices=true | ||||
| # make kernel settings (procfs and sysfs) read-only | ||||
| #ProtectKernelTunables=true | ||||
| # make cgroups /sys/fs/cgroup read-only | ||||
| #ProtectControlGroups=true | ||||
|  | ||||
| # allow writing of acme.json | ||||
| #ReadWritePaths=/etc/traefik/acme.json | ||||
| # depending on log and entrypoint configuration, you may need to allow writing to other paths, too | ||||
|  | ||||
| # limit number of processes in this unit | ||||
| #LimitNPROC=1 | ||||
|  | ||||
| [Install] | ||||
| WantedBy=multi-user.target | ||||
|   | ||||
| @@ -94,10 +94,13 @@ Following is the list of existing modifier rules: | ||||
|  | ||||
| Matcher rules determine if a particular request should be forwarded to a backend. | ||||
|  | ||||
| Separate multiple rule values by `,` (comma) in order to enable ANY semantics (i.e., forward a request if any rule matches). | ||||
| Does not work for `Headers` and `HeadersRegexp`. | ||||
| The associativity rule is the following: | ||||
|  | ||||
| Separate multiple rule values by `;` (semicolon) in order to enable ALL semantics (i.e., forward a request if all rules match). | ||||
| - `,` is the `OR` operator (works **only inside a matcher**, ex: `Host:foo.com,bar.com`). | ||||
|     - i.e., forward a request if any rule matches. | ||||
|     - Does not work for `Headers` and `HeadersRegexp`. | ||||
| - `;` is the `AND` operator (works **only between matchers**, ex: `Host:foo.com;Path:/bar`)  | ||||
|     - i.e., forward a request if all rules match | ||||
|  | ||||
| Following is the list of existing matcher rules along with examples: | ||||
|  | ||||
| @@ -234,7 +237,8 @@ The following rules are both `Matchers` and `Modifiers`, so the `Matcher` portio | ||||
| #### Priorities | ||||
|  | ||||
| By default, routes will be sorted (in descending order) using rules length (to avoid path overlap): | ||||
| `PathPrefix:/foo;Host:foo.com` (length == 28) will be matched before `PathPrefixStrip:/foobar` (length == 23) will be matched before `PathPrefix:/foo,/bar` (length == 20). | ||||
| - `PathPrefix:/foo;Host:foo.com` (length == 28) will be matched before `PathPrefixStrip:/foobar` (length == 23) will be matched before `PathPrefix:/foo,/bar` (length == 20).   | ||||
| - A priority value of 0 will be ignored, so the default value will be calculated (rules length). | ||||
|  | ||||
| You can customize priority by frontend. The priority value override the rule length during sorting: | ||||
|  | ||||
| @@ -742,12 +746,10 @@ Once a day (the first call begins 10 minutes after the start of Traefik), we col | ||||
|  | ||||
| ### Show me the code ! | ||||
|  | ||||
| If you want to dig into more details, here is the source code of the collecting system: [collector.go](https://github.com/containous/traefik/blob/master/collector/collector.go) | ||||
| If you want to dig into more details, here is the source code of the collecting system: [collector.go](https://github.com/containous/traefik/blob/v1.7/collector/collector.go) | ||||
|  | ||||
| By default we anonymize all configuration fields, except fields tagged with `export=true`. | ||||
|  | ||||
| You can check all fields in the [godoc](https://godoc.org/github.com/containous/traefik/configuration#GlobalConfiguration). | ||||
|  | ||||
| ### How to enable this ? | ||||
|  | ||||
| You can enable the collecting system by: | ||||
|   | ||||
| @@ -271,58 +271,90 @@ Useful if internal networks block external DNS queries. | ||||
|  | ||||
| ##### `provider` | ||||
|  | ||||
| Here is a list of supported `provider`s, that can automate the DNS verification, along with the required environment variables and their [wildcard & root domain support](/configuration/acme/#wildcard-domains) for each. Do not hesitate to complete it. | ||||
| Here is a list of supported `provider`s, that can automate the DNS verification, along with the required environment variables and their [wildcard & root domain support](/configuration/acme/#wildcard-domains) for each. | ||||
| Do not hesitate to complete it. | ||||
| Every lego environment variable can be overridden by their respective `_FILE` counterpart, which should have a filepath to a file that contains the secret as its value. | ||||
| For example, `CF_API_EMAIL_FILE=/run/secrets/traefik_cf-api-email` could be used to provide a Cloudflare API email address as a Docker secret named `traefik_cf-api-email`. | ||||
|  | ||||
| | Provider Name                                          | Provider Code  | Environment Variables                                                                                                                     | Wildcard & Root Domain Support | | ||||
| |--------------------------------------------------------|----------------|-------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------| | ||||
| | [ACME DNS](https://github.com/joohoi/acme-dns)         | `acmedns`      | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH`                                                                                              | Not tested yet                 | | ||||
| | [Alibaba Cloud](https://www.vultr.com)                 | `alidns`       | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID`                                                                        | Not tested yet                 | | ||||
| | [Auroradns](https://www.pcextreme.com/aurora/dns)      | `auroradns`    | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT`                                                                                         | Not tested yet                 | | ||||
| | [Azure](https://azure.microsoft.com/services/dns/)     | `azure`        | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_METADATA_ENDPOINT]` | Not tested yet                 | | ||||
| | [Blue Cat](https://www.bluecatnetworks.com/)           | `bluecat`      | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW`                                  | Not tested yet                 | | ||||
| | [Cloudflare](https://www.cloudflare.com)               | `cloudflare`   | `CF_API_EMAIL`, `CF_API_KEY` - The `Global API Key` needs to be used, not the `Origin CA Key`                                             | YES                            | | ||||
| | [CloudXNS](https://www.cloudxns.net)                   | `cloudxns`     | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY`                                                                                                 | Not tested yet                 | | ||||
| | [DigitalOcean](https://www.digitalocean.com)           | `digitalocean` | `DO_AUTH_TOKEN`                                                                                                                           | YES                            | | ||||
| | [DNSimple](https://dnsimple.com)                       | `dnsimple`     | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL`                                                                                               | Not tested yet                 | | ||||
| | [DNS Made Easy](https://dnsmadeeasy.com)               | `dnsmadeeasy`  | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX`                                                                    | Not tested yet                 | | ||||
| | [DNSPod](http://www.dnspod.net/)                       | `dnspod`       | `DNSPOD_API_KEY`                                                                                                                          | Not tested yet                 | | ||||
| | [DreamHost](https://www.dreamhost.com/)                | `dreamhost`    | `DREAMHOST_API_KEY`                                                                                                                       | YES                            | | ||||
| | [Duck DNS](https://www.duckdns.org/)                   | `duckdns`      | `DUCKDNS_TOKEN`                                                                                                                           | No                             | | ||||
| | [Dyn](https://dyn.com)                                 | `dyn`          | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD`                                                                                      | Not tested yet                 | | ||||
| | External Program                                       | `exec`         | `EXEC_PATH`                                                                                                                               | Not tested yet                 | | ||||
| | [Exoscale](https://www.exoscale.com)                   | `exoscale`     | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT`                                                                            | YES                            | | ||||
| | [Fast DNS](https://www.akamai.com/)                    | `fastdns`      | `AKAMAI_CLIENT_TOKEN`,  `AKAMAI_CLIENT_SECRET`,  `AKAMAI_ACCESS_TOKEN`                                                                    | Not tested yet                 | | ||||
| | [Gandi](https://www.gandi.net)                         | `gandi`        | `GANDI_API_KEY`                                                                                                                           | Not tested yet                 | | ||||
| | [Gandi v5](http://doc.livedns.gandi.net)               | `gandiv5`      | `GANDIV5_API_KEY`                                                                                                                         | YES                            | | ||||
| | [Glesys](https://glesys.com/)                          | `glesys`       | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN`                                                                                      | Not tested yet                 | | ||||
| | [GoDaddy](https://godaddy.com/domains)                 | `godaddy`      | `GODADDY_API_KEY`, `GODADDY_API_SECRET`                                                                                                   | Not tested yet                 | | ||||
| | [Google Cloud DNS](https://cloud.google.com/dns/docs/) | `gcloud`       | `GCE_PROJECT`, `GCE_SERVICE_ACCOUNT_FILE`                                                                                                 | YES                            | | ||||
| | [hosting.de](https://www.hosting.de)                   | `hostingde`    | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME`                                                                                                | Not tested yet                 | | ||||
| | [IIJ](https://www.iij.ad.jp/)                          | `iij`          | `IIJ_API_ACCESS_KEY`, `IIJ_API_SECRET_KEY`, `IIJ_DO_SERVICE_CODE`                                                                         | Not tested yet                 | | ||||
| | [Lightsail](https://aws.amazon.com/lightsail/)         | `lightsail`    | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `DNS_ZONE`                                                                                  | Not tested yet                 | | ||||
| | [Linode](https://www.linode.com)                       | `linode`       | `LINODE_API_KEY`                                                                                                                          | Not tested yet                 | | ||||
| | [Linode v4](https://www.linode.com)                    | `linodev4`     | `LINODE_TOKEN`                                                                                                                            | Not tested yet                 | | ||||
| | manual                                                 | -              | none, but you need to run Traefik interactively, turn on `acmeLogging` to see instructions and press <kbd>Enter</kbd>.                    | YES                            | | ||||
| | [Namecheap](https://www.namecheap.com)                 | `namecheap`    | `NAMECHEAP_API_USER`, `NAMECHEAP_API_KEY`                                                                                                 | YES                            | | ||||
| | [name.com](https://www.name.com/)                      | `namedotcom`   | `NAMECOM_USERNAME`, `NAMECOM_API_TOKEN`, `NAMECOM_SERVER`                                                                                 | Not tested yet                 | | ||||
| | [Netcup](https://www.netcup.eu/)                       | `netcup`       | `NETCUP_CUSTOMER_NUMBER`, `NETCUP_API_KEY`, `NETCUP_API_PASSWORD`                                                                         | Not tested yet                 | | ||||
| | [NIFCloud](https://cloud.nifty.com/service/dns.htm)    | `nifcloud`     | `NIFCLOUD_ACCESS_KEY_ID`, `NIFCLOUD_SECRET_ACCESS_KEY`                                                                                    | Not tested yet                 | | ||||
| | [Ns1](https://ns1.com/)                                | `ns1`          | `NS1_API_KEY`                                                                                                                             | Not tested yet                 | | ||||
| | [Open Telekom Cloud](https://cloud.telekom.de)         | `otc`          | `OTC_DOMAIN_NAME`, `OTC_USER_NAME`, `OTC_PASSWORD`, `OTC_PROJECT_NAME`, `OTC_IDENTITY_ENDPOINT`                                           | Not tested yet                 | | ||||
| | [OVH](https://www.ovh.com)                             | `ovh`          | `OVH_ENDPOINT`, `OVH_APPLICATION_KEY`, `OVH_APPLICATION_SECRET`, `OVH_CONSUMER_KEY`                                                       | YES                            | | ||||
| | [PowerDNS](https://www.powerdns.com)                   | `pdns`         | `PDNS_API_KEY`, `PDNS_API_URL`                                                                                                            | Not tested yet                 | | ||||
| | [Rackspace](https://www.rackspace.com/cloud/dns)       | `rackspace`    | `RACKSPACE_USER`, `RACKSPACE_API_KEY`                                                                                                     | Not tested yet                 | | ||||
| | [RFC2136](https://tools.ietf.org/html/rfc2136)         | `rfc2136`      | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER`                                                 | Not tested yet                 | | ||||
| | [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.           | YES                            | | ||||
| | [Sakura Cloud](https://cloud.sakura.ad.jp/)            | `sakuracloud`  | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET`                                                                             | Not tested yet                 | | ||||
| | [Stackpath](https://www.stackpath.com/)                | `stackpath`    | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID`                                                                    | Not tested yet                 | | ||||
| | [VegaDNS](https://github.com/shupp/VegaDNS-API)        | `vegadns`      | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL`                                                                              | Not tested yet                 | | ||||
| | [VULTR](https://www.vultr.com)                         | `vultr`        | `VULTR_API_KEY`                                                                                                                           | Not tested yet                 | | ||||
| | Provider Name                                               | Provider Code  | Environment Variables                                                                                                                       | Wildcard & Root Domain Support | | ||||
| |-------------------------------------------------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------| | ||||
| | [ACME DNS](https://github.com/joohoi/acme-dns)              | `acme-dns`     | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH`                                                                                                | Not tested yet                 | | ||||
| | [Alibaba Cloud](https://www.alibabacloud.com)               | `alidns`       | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID`                                                                          | Not tested yet                 | | ||||
| | [Auroradns](https://www.pcextreme.com/aurora/dns)           | `auroradns`    | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT`                                                                                           | Not tested yet                 | | ||||
| | [Azure](https://azure.microsoft.com/services/dns/)          | `azure`        | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_METADATA_ENDPOINT]`   | Not tested yet                 | | ||||
| | [Bindman](https://github.com/labbsr0x/bindman-dns-webhook)  | `bindman`      | `BINDMAN_MANAGER_ADDRESS`                                                                                                                   | YES                            | | ||||
| | [Blue Cat](https://www.bluecatnetworks.com/)                | `bluecat`      | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW`                                    | Not tested yet                 | | ||||
| | [ClouDNS](https://www.cloudns.net/)                         | `cloudns`      | `CLOUDNS_AUTH_ID`, `CLOUDNS_AUTH_PASSWORD`                                                                                                  | YES                            | | ||||
| | [Cloudflare](https://www.cloudflare.com)                    | `cloudflare`   | `CF_API_EMAIL`, `CF_API_KEY` - The `Global API Key` needs to be used, not the `Origin CA Key`                                               | YES                            | | ||||
| | [CloudXNS](https://www.cloudxns.net)                        | `cloudxns`     | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY`                                                                                                   | Not tested yet                 | | ||||
| | [ConoHa](https://www.conoha.jp)                             | `conoha`       | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD`                                                                            | YES                            | | ||||
| | [DigitalOcean](https://www.digitalocean.com)                | `digitalocean` | `DO_AUTH_TOKEN`                                                                                                                             | YES                            | | ||||
| | [DNSimple](https://dnsimple.com)                            | `dnsimple`     | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL`                                                                                                 | YES                            | | ||||
| | [DNS Made Easy](https://dnsmadeeasy.com)                    | `dnsmadeeasy`  | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX`                                                                      | Not tested yet                 | | ||||
| | [DNSPod](https://www.dnspod.com/)                           | `dnspod`       | `DNSPOD_API_KEY`                                                                                                                            | Not tested yet                 | | ||||
| | [Domain Offensive (do.de)](https://www.do.de/)              | `dode`         | `DODE_TOKEN`                                                                                                                                | YES                            | | ||||
| | [DreamHost](https://www.dreamhost.com/)                     | `dreamhost`    | `DREAMHOST_API_KEY`                                                                                                                         | YES                            | | ||||
| | [Duck DNS](https://www.duckdns.org/)                        | `duckdns`      | `DUCKDNS_TOKEN`                                                                                                                             | YES                            | | ||||
| | [Dyn](https://dyn.com)                                      | `dyn`          | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD`                                                                                        | Not tested yet                 | | ||||
| | [EasyDNS](https://easydns.com/)                             | `easydns`      | `EASYDNS_TOKEN`, `EASYDNS_KEY`                                                                                                              | YES                            | | ||||
| | External Program                                            | `exec`         | `EXEC_PATH`                                                                                                                                 | YES                            | | ||||
| | [Exoscale](https://www.exoscale.com)                        | `exoscale`     | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT`                                                                              | YES                            | | ||||
| | [Fast DNS](https://www.akamai.com/)                         | `fastdns`      | `AKAMAI_CLIENT_TOKEN`,  `AKAMAI_CLIENT_SECRET`,  `AKAMAI_ACCESS_TOKEN`                                                                      | YES                            | | ||||
| | [Gandi](https://www.gandi.net)                              | `gandi`        | `GANDI_API_KEY`                                                                                                                             | Not tested yet                 | | ||||
| | [Gandi v5](http://doc.livedns.gandi.net)                    | `gandiv5`      | `GANDIV5_API_KEY`                                                                                                                           | YES                            | | ||||
| | [Glesys](https://glesys.com/)                               | `glesys`       | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN`                                                                                        | Not tested yet                 | | ||||
| | [GoDaddy](https://godaddy.com/domains)                      | `godaddy`      | `GODADDY_API_KEY`, `GODADDY_API_SECRET`                                                                                                     | Not tested yet                 | | ||||
| | [Google Cloud DNS](https://cloud.google.com/dns/docs/)      | `gcloud`       | `GCE_PROJECT`, Application Default Credentials (2) (3), [`GCE_SERVICE_ACCOUNT_FILE`]                                                        | YES                            | | ||||
| | [hosting.de](https://www.hosting.de)                        | `hostingde`    | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME`                                                                                                  | YES                            | | ||||
| | HTTP request                                                | `httpreq`      | `HTTPREQ_ENDPOINT`, `HTTPREQ_MODE`, `HTTPREQ_USERNAME`, `HTTPREQ_PASSWORD` (1)                                                              | YES                            | | ||||
| | [IIJ](https://www.iij.ad.jp/)                               | `iij`          | `IIJ_API_ACCESS_KEY`, `IIJ_API_SECRET_KEY`, `IIJ_DO_SERVICE_CODE`                                                                           | Not tested yet                 | | ||||
| | [INWX](https://www.inwx.de/en)                              | `inwx`         | `INWX_USERNAME`, `INWX_PASSWORD`                                                                                                            | YES                            | | ||||
| | [Joker.com](https://joker.com)                              | `joker`        | `JOKER_API_KEY` or `JOKER_USERNAME`, `JOKER_PASSWORD`                                                                                       | YES                            | | ||||
| | [Lightsail](https://aws.amazon.com/lightsail/)              | `lightsail`    | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `DNS_ZONE`                                                                                    | Not tested yet                 | | ||||
| | [Linode](https://www.linode.com)                            | `linode`       | `LINODE_API_KEY`                                                                                                                            | Not tested yet                 | | ||||
| | [Linode v4](https://www.linode.com)                         | `linodev4`     | `LINODE_TOKEN`                                                                                                                              | Not tested yet                 | | ||||
| | manual                                                      | -              | none, but you need to run Traefik interactively, turn on `acmeLogging` to see instructions and press <kbd>Enter</kbd>.                      | YES                            | | ||||
| | [MyDNS.jp](https://www.mydns.jp/)                           | `mydnsjp`      | `MYDNSJP_MASTER_ID`, `MYDNSJP_PASSWORD`                                                                                                     | YES                            | | ||||
| | [Namecheap](https://www.namecheap.com)                      | `namecheap`    | `NAMECHEAP_API_USER`, `NAMECHEAP_API_KEY`                                                                                                   | YES                            | | ||||
| | [Namesilo](https://www.namesilo.com/)                       | `namesilo`     | `NAMESILO_API_KEY`                                                                                                                          | YES                            | | ||||
| | [name.com](https://www.name.com/)                           | `namedotcom`   | `NAMECOM_USERNAME`, `NAMECOM_API_TOKEN`, `NAMECOM_SERVER`                                                                                   | Not tested yet                 | | ||||
| | [Netcup](https://www.netcup.eu/)                            | `netcup`       | `NETCUP_CUSTOMER_NUMBER`, `NETCUP_API_KEY`, `NETCUP_API_PASSWORD`                                                                           | Not tested yet                 | | ||||
| | [NIFCloud](https://cloud.nifty.com/service/dns.htm)         | `nifcloud`     | `NIFCLOUD_ACCESS_KEY_ID`, `NIFCLOUD_SECRET_ACCESS_KEY`                                                                                      | Not tested yet                 | | ||||
| | [Ns1](https://ns1.com/)                                     | `ns1`          | `NS1_API_KEY`                                                                                                                               | Not tested yet                 | | ||||
| | [Open Telekom Cloud](https://cloud.telekom.de)              | `otc`          | `OTC_DOMAIN_NAME`, `OTC_USER_NAME`, `OTC_PASSWORD`, `OTC_PROJECT_NAME`, `OTC_IDENTITY_ENDPOINT`                                             | Not tested yet                 | | ||||
| | [OVH](https://www.ovh.com)                                  | `ovh`          | `OVH_ENDPOINT`, `OVH_APPLICATION_KEY`, `OVH_APPLICATION_SECRET`, `OVH_CONSUMER_KEY`                                                         | YES                            | | ||||
| | [Openstack Designate](https://docs.openstack.org/designate) | `designate`    | `OS_AUTH_URL`, `OS_USERNAME`, `OS_PASSWORD`, `OS_TENANT_NAME`, `OS_REGION_NAME`                                                             | YES                            | | ||||
| | [Oracle Cloud](https://cloud.oracle.com/home)               | `oraclecloud`  | `OCI_COMPARTMENT_OCID`, `OCI_PRIVKEY_FILE`, `OCI_PRIVKEY_PASS`, `OCI_PUBKEY_FINGERPRINT`, `OCI_REGION`, `OCI_TENANCY_OCID`, `OCI_USER_OCID` | YES                            | | ||||
| | [PowerDNS](https://www.powerdns.com)                        | `pdns`         | `PDNS_API_KEY`, `PDNS_API_URL`                                                                                                              | Not tested yet                 | | ||||
| | [Rackspace](https://www.rackspace.com/cloud/dns)            | `rackspace`    | `RACKSPACE_USER`, `RACKSPACE_API_KEY`                                                                                                       | Not tested yet                 | | ||||
| | [RFC2136](https://tools.ietf.org/html/rfc2136)              | `rfc2136`      | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER`                                                   | Not tested yet                 | | ||||
| | [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.             | YES                            | | ||||
| | [Sakura Cloud](https://cloud.sakura.ad.jp/)                 | `sakuracloud`  | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET`                                                                               | Not tested yet                 | | ||||
| | [Selectel](https://selectel.ru/en/)                         | `selectel`     | `SELECTEL_API_TOKEN`                                                                                                                        | YES                            | | ||||
| | [Stackpath](https://www.stackpath.com/)                     | `stackpath`    | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID`                                                                      | Not tested yet                 | | ||||
| | [TransIP](https://www.transip.nl/)                          | `transip`      | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH`                                                                                          | YES                            | | ||||
| | [VegaDNS](https://github.com/shupp/VegaDNS-API)             | `vegadns`      | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL`                                                                                | Not tested yet                 | | ||||
| | [Versio](https://www.versio.nl/domeinnamen)                 | `versio`       | `VERSIO_USERNAME`, `VERSIO_PASSWORD`                                                                                                        | YES                            | | ||||
| | [Vscale](https://vscale.io/)                                | `vscale`       | `VSCALE_API_TOKEN`                                                                                                                          | YES                            | | ||||
| | [VULTR](https://www.vultr.com)                              | `vultr`        | `VULTR_API_KEY`                                                                                                                             | YES                            | | ||||
| | [Zone.ee](https://www.zone.ee)                              | `zoneee`       | `ZONEEE_API_USER`, `ZONEEE_API_KEY`                                                                                                         | YES                            | | ||||
|  | ||||
| - (1): more information about the HTTP message format can be found [here](https://go-acme.github.io/lego/dns/httpreq/) | ||||
| - (2): https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application | ||||
| - (3): https://github.com/golang/oauth2/blob/36a7019397c4c86cf59eeab3bc0d188bac444277/google/default.go#L61-L76 | ||||
|  | ||||
| #### `resolvers` | ||||
|  | ||||
| Use custom DNS servers to resolve the FQDN authority. | ||||
|  | ||||
| ```toml | ||||
| [acme] | ||||
| # ... | ||||
| [acme.dnsChallenge] | ||||
|   # ... | ||||
|   resolvers = ["1.1.1.1:53", "8.8.8.8:53"] | ||||
| ``` | ||||
|  | ||||
| ### `domains` | ||||
|  | ||||
| You can provide SANs (alternative domains) to each main domain. | ||||
| @@ -367,11 +399,10 @@ As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/stagi | ||||
| ``` | ||||
|  | ||||
| It is not possible to request a double wildcard certificate for a domain (for example `*.*.local.com`). | ||||
| Due to ACME limitation it is not possible to define wildcards in SANs (alternative domains). Thus, the wildcard domain has to be defined as a main domain. | ||||
| Most likely the root domain should receive a certificate too, so it needs to be specified as SAN and 2 `DNS-01` challenges are executed. | ||||
| In this case the generated DNS TXT record for both domains is the same. | ||||
| Even though this behaviour is [DNS RFC](https://community.letsencrypt.org/t/wildcard-issuance-two-txt-records-for-the-same-name/54528/2) compliant, it can lead to problems as all DNS providers keep DNS records cached for a certain time (TTL) and this TTL can be superior to the challenge timeout making the `DNS-01` challenge fail. | ||||
| The Traefik ACME client library [LEGO](https://github.com/xenolf/lego) supports some but not all DNS providers to work around this issue. | ||||
| The Traefik ACME client library [LEGO](https://github.com/go-acme/lego) supports some but not all DNS providers to work around this issue. | ||||
| The [`provider` table](/configuration/acme/#provider) indicates if they allow generating certificates for a wildcard domain and its root domain. | ||||
|  | ||||
| ### `onDemand` (Deprecated) | ||||
|   | ||||
| @@ -35,7 +35,7 @@ | ||||
|  | ||||
| For more customization, see [entry points](/configuration/entrypoints/) documentation and the examples below. | ||||
|  | ||||
| ## Web UI | ||||
| ## Dashboard (Web UI) | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -106,10 +106,10 @@ entryPoint = "foo" | ||||
| entryPoint = "bar" | ||||
| ``` | ||||
|  | ||||
| In the above example, you would access a regular path, administration panel, and health-check as follows: | ||||
| In the above example, you would access a regular path, dashboard, and health-check as follows: | ||||
|  | ||||
| * Regular path: `http://hostname:80/path` | ||||
| * Admin Panel: `http://hostname:8083/` | ||||
| * Dashboard: `http://hostname:8083/` | ||||
| * Ping URL: `http://hostname:8082/ping` | ||||
|  | ||||
| In the above example, it is _very_ important to create a named dedicated entry point, and do **not** include it in `defaultEntryPoints`. | ||||
| @@ -301,7 +301,7 @@ curl -s "http://localhost:8080/health" | jq . | ||||
|   // average response time in seconds | ||||
|   "average_response_time_sec": 0.8648016000000001, | ||||
|  | ||||
|   // request statistics [requires --statistics to be set] | ||||
|   // request statistics [requires --api.statistics to be set] | ||||
|   // ten most recent requests with 4xx and 5xx status codes | ||||
|   "recent_errors": [ | ||||
|     { | ||||
| @@ -322,9 +322,12 @@ curl -s "http://localhost:8080/health" | jq . | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Metrics | ||||
| ## Dashboard Statistics | ||||
|  | ||||
| You can enable Traefik to export internal metrics to different monitoring systems. | ||||
| You can control how the Traefik's internal metrics are shown in the Dashboard. | ||||
|  | ||||
| If you want to export internal metrics to different monitoring systems, | ||||
| please check the page [Metrics](./metrics.md). | ||||
|  | ||||
| ```toml | ||||
| [api] | ||||
|   | ||||
| @@ -37,6 +37,15 @@ stale = false | ||||
| # | ||||
| domain = "consul.localhost" | ||||
|  | ||||
| # Keep a Consul node only if all checks status are passing | ||||
| # If true, only the Consul nodes with checks status 'passing' will be kept. | ||||
| # if false, only the Consul nodes with checks status 'passing' or 'warning' will be kept. | ||||
| # | ||||
| # Optional | ||||
| # Default: true | ||||
| # | ||||
| strictChecks = true | ||||
|  | ||||
| # Prefix for Consul catalog tags. | ||||
| # | ||||
| # Optional | ||||
| @@ -94,74 +103,82 @@ Additional settings can be defined using Consul Catalog tags. | ||||
| !!! note | ||||
|     The default prefix is `traefik`. | ||||
|  | ||||
| | Label                                                                | Description                                                                                                                                                                                                                   | | ||||
| |----------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `<prefix>.enable=false`                                              | Disables this container in Traefik.                                                                                                                                                                                            | | ||||
| | `<prefix>.protocol=https`                                            | Overrides the default `http` protocol.                                                                                                                                                                                        | | ||||
| | `<prefix>.weight=10`                                                 | Assigns this weight to the container.                                                                                                                                                                                         | | ||||
| | `traefik.backend.buffering.maxRequestBodyBytes=0`                    | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.maxResponseBodyBytes=0`                   | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memRequestBodyBytes=0`                    | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memResponseBodyBytes=0`                   | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.retryExpression=EXPR`                     | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `<prefix>.backend.circuitbreaker.expression=EXPR`                    | Creates a [circuit breaker](/basics/#backends) to be used against the backend. ex: `NetworkErrorRatio() > 0.`                                                                                                                 | | ||||
| | `<prefix>.backend.responseForwarding.flushInterval=10ms`             | Defines the interval between two flushes when forwarding response from backend to client.                                                                                                                                     | | ||||
| | `<prefix>.backend.healthcheck.path=/health`                          | Enables health check for the backend, hitting the container at `path`.                                                                                                                                                        | | ||||
| | `<prefix>.backend.healthcheck.interval=1s`                           | Defines the health check interval.                                                                                                                                                                                            | | ||||
| | `<prefix>.backend.healthcheck.port=8080`                             | Sets a different port for the health check.                                                                                                                                                                                   | | ||||
| | `traefik.backend.healthcheck.scheme=http`                            | Overrides the server URL scheme.                                                                                                                                                                                              | | ||||
| | `<prefix>.backend.healthcheck.hostname=foobar.com`                   | Defines the health check hostname.                                                                                                                                                                                            | | ||||
| | `<prefix>.backend.healthcheck.headers=EXPR`                          | Defines the health check request headers <br>Format:  <code>HEADER:value||HEADER2:value2</code>                                                                                                                     | | ||||
| | `<prefix>.backend.loadbalancer.method=drr`                           | Overrides the default `wrr` load balancer algorithm.                                                                                                                                                                          | | ||||
| | `<prefix>.backend.loadbalancer.stickiness=true`                      | Enables backend sticky sessions.                                                                                                                                                                                              | | ||||
| | `<prefix>.backend.loadbalancer.stickiness.cookieName=NAME`           | Sets the cookie name manually for sticky sessions.                                                                                                                                                                            | | ||||
| | `<prefix>.backend.loadbalancer.sticky=true`                          | Enables backend sticky sessions. (DEPRECATED)                                                                                                                                                                                 | | ||||
| | `<prefix>.backend.maxconn.amount=10`                                 | Sets a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect.                                                                                                      | | ||||
| | `<prefix>.backend.maxconn.extractorfunc=client.ip`                   | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.<br>Must be used in conjunction with the above label to take effect.                                        | | ||||
| | `<prefix>.frontend.auth.basic=EXPR`                                  | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED).                                                                                                                                 | | ||||
| | `<prefix>.frontend.auth.basic.removeHeader=true`                     | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `<prefix>.frontend.auth.basic.users=EXPR`                            | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash`.                                                                                                                                              | | ||||
| | `<prefix>.frontend.auth.basic.usersfile=/path/.htpasswd`             | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                         | | ||||
| | `<prefix>.frontend.auth.digest.removeHeader=true`                    | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `<prefix>.frontend.auth.digest.users=EXPR`                           | Sets digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`.                                                                                                                                 | | ||||
| | `<prefix>.frontend.auth.digest.usersfile=/path/.htdigest`            | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                        | | ||||
| | `<prefix>.frontend.auth.forward.address=https://example.com`         | Sets the URL of the authentication server.                                                                                                                                                                                    | | ||||
| | `<prefix>.frontend.auth.forward.authResponseHeaders=EXPR`            | Sets the forward authentication authResponseHeaders in CSV format: `X-Auth-User,X-Auth-Header`                                                                                                                                | | ||||
| | `<prefix>.frontend.auth.forward.tls.ca=/path/ca.pem`                 | Sets the Certificate Authority (CA) for the TLS connection with the authentication server.                                                                                                                                    | | ||||
| | `<prefix>.frontend.auth.forward.tls.caOptional=true`                 | Checks the certificates if present but do not force to be signed by a specified Certificate Authority (CA).                                                                                                                   | | ||||
| | `<prefix>.frontend.auth.forward.tls.cert=/path/server.pem`           | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `<prefix>.frontend.auth.forward.tls.insecureSkipVerify=true`         | If set to true invalid SSL certificates are accepted.                                                                                                                                                                         | | ||||
| | `<prefix>.frontend.auth.forward.tls.key=/path/server.key`            | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `<prefix>.frontend.auth.forward.trustForwardHeader=true`             | Trusts X-Forwarded-* headers.                                                                                                                                                                                                 | | ||||
| | `<prefix>.frontend.auth.headerField=X-WebAuth-User`                  | Sets the header used to pass the authenticated user to the application.                                                                                                                                                       | | ||||
| | `<prefix>.frontend.entryPoints=http,https`                           | Assigns this frontend to entry points `http` and `https`.<br>Overrides `defaultEntryPoints`                                                                                                                                   | | ||||
| | `<prefix>.frontend.errors.<name>.backend=NAME`                       | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `<prefix>.frontend.errors.<name>.query=PATH`                         | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `<prefix>.frontend.errors.<name>.status=RANGE`                       | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `<prefix>.frontend.passHostHeader=true`                              | Forwards client `Host` header to the backend.                                                                                                                                                                                 | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.notAfter=true`            | Add the noAfter field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                            | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.notBefore=true`           | Add the noBefore field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                           | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.sans=true`                | Add the sans field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                               | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.subject.commonName=true`  | Add the subject.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                 | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.subject.country=true`     | Add the subject.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.subject.locality=true`    | Add the subject.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.subject.organization=true`| Add the subject.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.subject.province=true`    | Add the subject.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.subject.serialNumber=true`| Add the subject.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `<prefix>.frontend.passTLSClientCert.pem=true`                       | Pass the escaped pem in the `X-Forwarded-Ssl-Client-Cert` header.                                                                                                                                                             | | ||||
| | `<prefix>.frontend.passTLSCert=true`                                 | Forwards TLS Client certificates to the backend.                                                                                                                                                                              | | ||||
| | `<prefix>.frontend.priority=10`                                      | Overrides default frontend priority.                                                                                                                                                                                          | | ||||
| | `<prefix>.frontend.rateLimit.extractorFunc=EXP`                      | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `<prefix>.frontend.rateLimit.rateSet.<name>.period=6`                | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `<prefix>.frontend.rateLimit.rateSet.<name>.average=6`               | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `<prefix>.frontend.rateLimit.rateSet.<name>.burst=6`                 | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `<prefix>.frontend.redirect.entryPoint=https`                        | Enables Redirect to another entryPoint to this frontend (e.g. HTTPS).                                                                                                                                                         | | ||||
| | `<prefix>.frontend.redirect.regex=^http://localhost/(.*)`            | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.replacement`.                                                                                                                       | | ||||
| | `<prefix>.frontend.redirect.replacement=http://mydomain/$1`          | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.regex`.                                                                                                                             | | ||||
| | `<prefix>.frontend.redirect.permanent=true`                          | Returns 301 instead of 302.                                                                                                                                                                                                   | | ||||
| | `<prefix>.frontend.rule=EXPR`                                        | Overrides the default frontend rule. Default: `Host:{{.ServiceName}}.{{.Domain}}`.                                                                                                                                            | | ||||
| | `<prefix>.frontend.whiteList.sourceRange=RANGE`                      | Sets a list of IP-Ranges which are allowed to access.<br>An unset or empty list allows all Source-IPs to access. If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. | | ||||
| | `<prefix>.frontend.whiteList.useXForwardedFor=true`                  | Uses `X-Forwarded-For` header as valid source of IP for the white list.                                                                                                                                                       | | ||||
| | Label                                                                    | Description                                                                                                                                                                                                                   | | ||||
| |--------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `<prefix>.enable=false`                                                  | Disables this container in Traefik.                                                                                                                                                                                           | | ||||
| | `<prefix>.protocol=https`                                                | Overrides the default `http` protocol.                                                                                                                                                                                        | | ||||
| | `<prefix>.weight=10`                                                     | Assigns this weight to the container.                                                                                                                                                                                         | | ||||
| | `traefik.backend.buffering.maxRequestBodyBytes=0`                        | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.maxResponseBodyBytes=0`                       | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memRequestBodyBytes=0`                        | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memResponseBodyBytes=0`                       | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.retryExpression=EXPR`                         | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `<prefix>.backend.circuitbreaker.expression=EXPR`                        | Creates a [circuit breaker](/basics/#backends) to be used against the backend. ex: `NetworkErrorRatio() > 0.`                                                                                                                 | | ||||
| | `<prefix>.backend.responseForwarding.flushInterval=10ms`                 | Defines the interval between two flushes when forwarding response from backend to client.                                                                                                                                     | | ||||
| | `<prefix>.backend.healthcheck.path=/health`                              | Enables health check for the backend, hitting the container at `path`.                                                                                                                                                        | | ||||
| | `<prefix>.backend.healthcheck.interval=1s`                               | Defines the health check interval.                                                                                                                                                                                            | | ||||
| | `<prefix>.backend.healthcheck.port=8080`                                 | Sets a different port for the health check.                                                                                                                                                                                   | | ||||
| | `traefik.backend.healthcheck.scheme=http`                                | Overrides the server URL scheme.                                                                                                                                                                                              | | ||||
| | `<prefix>.backend.healthcheck.hostname=foobar.com`                       | Defines the health check hostname.                                                                                                                                                                                            | | ||||
| | `<prefix>.backend.healthcheck.headers=EXPR`                              | Defines the health check request headers <br>Format:  <code>HEADER:value||HEADER2:value2</code>                                                                                                                     | | ||||
| | `<prefix>.backend.loadbalancer.method=drr`                               | Overrides the default `wrr` load balancer algorithm.                                                                                                                                                                          | | ||||
| | `<prefix>.backend.loadbalancer.stickiness=true`                          | Enables backend sticky sessions.                                                                                                                                                                                              | | ||||
| | `<prefix>.backend.loadbalancer.stickiness.cookieName=NAME`               | Sets the cookie name manually for sticky sessions.                                                                                                                                                                            | | ||||
| | `<prefix>.backend.loadbalancer.sticky=true`                              | Enables backend sticky sessions. (DEPRECATED)                                                                                                                                                                                 | | ||||
| | `<prefix>.backend.maxconn.amount=10`                                     | Sets a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect.                                                                                                      | | ||||
| | `<prefix>.backend.maxconn.extractorfunc=client.ip`                       | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.<br>Must be used in conjunction with the above label to take effect.                                        | | ||||
| | `<prefix>.frontend.auth.basic=EXPR`                                      | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED).                                                                                                                                 | | ||||
| | `<prefix>.frontend.auth.basic.removeHeader=true`                         | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `<prefix>.frontend.auth.basic.users=EXPR`                                | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash`.                                                                                                                                              | | ||||
| | `<prefix>.frontend.auth.basic.usersFile=/path/.htpasswd`                 | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                         | | ||||
| | `<prefix>.frontend.auth.digest.removeHeader=true`                        | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `<prefix>.frontend.auth.digest.users=EXPR`                               | Sets digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`.                                                                                                                                 | | ||||
| | `<prefix>.frontend.auth.digest.usersFile=/path/.htdigest`                | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                        | | ||||
| | `<prefix>.frontend.auth.forward.address=https://example.com`             | Sets the URL of the authentication server.                                                                                                                                                                                    | | ||||
| | `<prefix>.frontend.auth.forward.authResponseHeaders=EXPR`                | Sets the forward authentication authResponseHeaders in CSV format: `X-Auth-User,X-Auth-Header`                                                                                                                                | | ||||
| | `<prefix>.frontend.auth.forward.tls.ca=/path/ca.pem`                     | Sets the Certificate Authority (CA) for the TLS connection with the authentication server.                                                                                                                                    | | ||||
| | `<prefix>.frontend.auth.forward.tls.caOptional=true`                     | Checks the certificates if present but do not force to be signed by a specified Certificate Authority (CA).                                                                                                                   | | ||||
| | `<prefix>.frontend.auth.forward.tls.cert=/path/server.pem`               | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `<prefix>.frontend.auth.forward.tls.insecureSkipVerify=true`             | If set to true invalid SSL certificates are accepted.                                                                                                                                                                         | | ||||
| | `<prefix>.frontend.auth.forward.tls.key=/path/server.key`                | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `<prefix>.frontend.auth.forward.trustForwardHeader=true`                 | Trusts X-Forwarded-* headers.                                                                                                                                                                                                 | | ||||
| | `<prefix>.frontend.auth.headerField=X-WebAuth-User`                      | Sets the header used to pass the authenticated user to the application.                                                                                                                                                       | | ||||
| | `<prefix>.frontend.entryPoints=http,https`                               | Assigns this frontend to entry points `http` and `https`.<br>Overrides `defaultEntryPoints`                                                                                                                                   | | ||||
| | `<prefix>.frontend.errors.<name>.backend=NAME`                           | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `<prefix>.frontend.errors.<name>.query=PATH`                             | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `<prefix>.frontend.errors.<name>.status=RANGE`                           | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `<prefix>.frontend.passHostHeader=true`                                  | Forwards client `Host` header to the backend.                                                                                                                                                                                 | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.issuer.commonName=true`       | Add the issuer.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                  | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.issuer.country=true`          | Add the issuer.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                     | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.issuer.domainComponent=true`  | Add the issuer.domainComponent field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                             | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.issuer.locality=true`         | Add the issuer.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.issuer.organization=true`     | Add the issuer.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.issuer.province=true`         | Add the issuer.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.issuer.serialNumber=true`     | Add the subject.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.notAfter=true`                | Add the noAfter field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                            | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.notBefore=true`               | Add the noBefore field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                           | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.sans=true`                    | Add the sans field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                               | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.subject.commonName=true`      | Add the subject.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                 | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.subject.country=true`         | Add the subject.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.subject.domainComponent=true` | Add the subject.domainComponent field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                            | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.subject.locality=true`        | Add the subject.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.subject.organization=true`    | Add the subject.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.subject.province=true`        | Add the subject.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `<prefix>.frontend.passTLSClientCert.infos.subject.serialNumber=true`    | Add the subject.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `<prefix>.frontend.passTLSClientCert.pem=true`                           | Pass the escaped pem in the `X-Forwarded-Ssl-Client-Cert` header.                                                                                                                                                             | | ||||
| | `<prefix>.frontend.passTLSCert=true`                                     | Forwards TLS Client certificates to the backend.                                                                                                                                                                              | | ||||
| | `<prefix>.frontend.priority=10`                                          | Overrides default frontend priority.                                                                                                                                                                                          | | ||||
| | `<prefix>.frontend.rateLimit.extractorFunc=EXP`                          | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `<prefix>.frontend.rateLimit.rateSet.<name>.period=6`                    | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `<prefix>.frontend.rateLimit.rateSet.<name>.average=6`                   | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `<prefix>.frontend.rateLimit.rateSet.<name>.burst=6`                     | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `<prefix>.frontend.redirect.entryPoint=https`                            | Enables Redirect to another entryPoint to this frontend (e.g. HTTPS).                                                                                                                                                         | | ||||
| | `<prefix>.frontend.redirect.regex=^http://localhost/(.*)`                | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.replacement`.                                                                                                                       | | ||||
| | `<prefix>.frontend.redirect.replacement=http://mydomain/$1`              | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.regex`.                                                                                                                             | | ||||
| | `<prefix>.frontend.redirect.permanent=true`                              | Returns 301 instead of 302.                                                                                                                                                                                                   | | ||||
| | `<prefix>.frontend.rule=EXPR`                                            | Overrides the default frontend rule. Default: `Host:{{.ServiceName}}.{{.Domain}}`.                                                                                                                                            | | ||||
| | `<prefix>.frontend.whiteList.sourceRange=RANGE`                          | Sets a list of IP-Ranges which are allowed to access.<br>An unset or empty list allows all Source-IPs to access. If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. | | ||||
| | `<prefix>.frontend.whiteList.useXForwardedFor=true`                      | Uses `X-Forwarded-For` header as valid source of IP for the white list.                                                                                                                                                       | | ||||
|  | ||||
| ### Multiple frontends for a single service | ||||
|  | ||||
|   | ||||
| @@ -57,7 +57,7 @@ watch = true | ||||
| exposedByDefault = true | ||||
|  | ||||
| # Use the IP address from the binded port instead of the inner network one. | ||||
| #  | ||||
| # | ||||
| # In case no IP address is attached to the binded port (or in case  | ||||
| # there is no bind), the inner network one will be used as a fallback.      | ||||
| # | ||||
| @@ -73,6 +73,13 @@ usebindportip = true | ||||
| # | ||||
| swarmMode = false | ||||
|  | ||||
| # Polling interval (in seconds) for Swarm Mode. | ||||
| # | ||||
| # Optional | ||||
| # Default: 15 | ||||
| # | ||||
| swarmModeRefreshSeconds = 15 | ||||
|  | ||||
| # Define a default docker network to use for connections to all containers. | ||||
| # Can be overridden by the traefik.docker.network label. | ||||
| # | ||||
| @@ -93,7 +100,6 @@ network = "web" | ||||
|  | ||||
| To enable constraints see [provider-specific constraints section](/configuration/commons/#provider-specific). | ||||
|  | ||||
|  | ||||
| ## Docker Swarm Mode | ||||
|  | ||||
| ```toml | ||||
| @@ -110,7 +116,10 @@ To enable constraints see [provider-specific constraints section](/configuration | ||||
| # Required | ||||
| # Default: "unix:///var/run/docker.sock" | ||||
| # | ||||
| endpoint = "tcp://127.0.0.1:2375" | ||||
| # swarm classic (1.12-) | ||||
| # endpoint = "tcp://127.0.0.1:2375" | ||||
| # docker swarm mode (1.12+) | ||||
| endpoint = "tcp://127.0.0.1:2377" | ||||
|  | ||||
| # Default base domain used for the frontend rules. | ||||
| # Can be overridden by setting the "traefik.domain" label on a services. | ||||
| @@ -177,6 +186,61 @@ exposedByDefault = false | ||||
|  | ||||
| To enable constraints see [provider-specific constraints section](/configuration/commons/#provider-specific). | ||||
|  | ||||
| ## Security Considerations | ||||
|  | ||||
| ### Security Challenge with the Docker Socket | ||||
|  | ||||
| Traefik requires access to the docker socket to get its dynamic configuration, | ||||
| by watching the Docker API through this socket. | ||||
|  | ||||
| !!! important | ||||
|     Depending on your context and your usage, accessing the Docker API without any restriction might be a security concern. | ||||
|  | ||||
| As explained on the Docker documentation: ([Docker Daemon Attack Surface page](https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface)): | ||||
|  | ||||
| `[...] only **trusted** users should be allowed to control your Docker daemon [...]` | ||||
|  | ||||
| If the Traefik processes (handling requests from the outside world) is attacked, | ||||
| then the attacker can access the Docker (or Swarm Mode) backend. | ||||
|  | ||||
| Also, when using Swarm Mode, it is mandatory to schedule Traefik's containers on the Swarm manager nodes, | ||||
| to let Traefik accessing the Docker Socket of the Swarm manager node. | ||||
|  | ||||
| More information about Docker's security: | ||||
|  | ||||
| - [KubeCon EU 2018 Keynote, Running with Scissors, from Liz Rice](https://www.youtube.com/watch?v=ltrV-Qmh3oY) | ||||
| - [Don't expose the Docker socket (not even to a container)](https://www.lvh.io/posts/dont-expose-the-docker-socket-not-even-to-a-container.html) | ||||
| - [A thread on Stack Overflow about sharing the `/var/run/docker.sock` file](https://news.ycombinator.com/item?id=17983623) | ||||
| - [To Dind or not to DinD](https://blog.loof.fr/2018/01/to-dind-or-not-do-dind.html) | ||||
|  | ||||
| ### Workarounds | ||||
|  | ||||
| !!! note "Improved Security" | ||||
|  | ||||
|     [TraefikEE](https://containo.us/traefikee) solves this problem by separating the control plane (connected to Docker) and the data plane (handling the requests). | ||||
|  | ||||
| Another possible workaround is to expose the Docker socket over TCP, instead of the default Unix socket file. | ||||
| It allows different implementation levels of the [AAA (Authentication, Authorization, Accounting) concepts](https://en.wikipedia.org/wiki/AAA_(computer_security)), depending on your security assessment: | ||||
|  | ||||
| - Authentication with Client Certificates as described in [the "Protect the Docker daemon socket" page of Docker's documentation](https://docs.docker.com/engine/security/https/) | ||||
|  | ||||
| - Authorization with the [Docker Authorization Plugin Mechanism](https://docs.docker.com/engine/extend/plugins_authorization/) | ||||
|  | ||||
| - Accounting at networking level, by exposing the socket only inside a Docker private network, only available for Traefik. | ||||
|  | ||||
| - Accounting at container level, by exposing the socket on a another container than Traefik's. | ||||
|   With Swarm mode, it allows scheduling of Traefik on worker nodes, with only the "socket exposer" container on the manager nodes. | ||||
|  | ||||
| - Accounting at kernel level, by enforcing kernel calls with mechanisms like [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux), | ||||
|   to only allows an identified set of actions for Traefik's process (or the "socket exposer" process). | ||||
|  | ||||
| Use the following ressources to get started: | ||||
|  | ||||
| - [Traefik issue GH-4174 about security with Docker socket](https://github.com/containous/traefik/issues/4174) | ||||
| - [Inspecting Docker Activity with Socat](https://developers.redhat.com/blog/2015/02/25/inspecting-docker-activity-with-socat/) | ||||
| - [Letting Traefik run on Worker Nodes](https://blog.mikesir87.io/2018/07/letting-traefik-run-on-worker-nodes/) | ||||
| - [Docker Socket Proxy from Tecnativa](https://github.com/Tecnativa/docker-socket-proxy) | ||||
|  | ||||
| ## Labels: overriding default behavior | ||||
|  | ||||
| ### Using Docker with Swarm Mode | ||||
| @@ -193,6 +257,20 @@ services: | ||||
|         traefik.docker.network: traefik | ||||
| ``` | ||||
|  | ||||
| Required labels: | ||||
|  | ||||
| - `traefik.frontend.rule` | ||||
| - `traefik.port` - Without this the debug logs will show this service is deliberately filtered out. | ||||
| - `traefik.docker.network` - Without this a 504 may occur. | ||||
|  | ||||
| #### Troubleshooting | ||||
|  | ||||
| If service doesn't show up in the dashboard, check the debug logs to see if the port is missing: | ||||
| `Filtering container without port, <SERVICE_NAME>: port label is missing, ...')` | ||||
|  | ||||
| If `504 Gateway Timeout` occurs and there are networks used, ensure that `traefik.docker.network` is defined.  | ||||
| The complete name is required, meaning if the network is internal the name needs to be `<project_name>_<network_name>`. | ||||
|  | ||||
| ### Using Docker Compose | ||||
|  | ||||
| If you are intending to use only Docker Compose commands (e.g. `docker-compose up --scale whoami=2 -d`), labels should be under your service, otherwise they will be ignored. | ||||
| @@ -209,97 +287,109 @@ services: | ||||
|  | ||||
| Labels can be used on containers to override default behavior. | ||||
|  | ||||
| | Label                                                               | Description                                                                                                                                                                                                                      | | ||||
| |---------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `traefik.docker.network`                                            | Overrides the default docker network to use for connections to the container. [1]                                                                                                                                                | | ||||
| | `traefik.domain`                                                    | Sets the default base domain for the frontend rules. For more information, check the [Container Labels section's of the user guide "Let's Encrypt & Docker"](/user-guide/docker-and-lets-encrypt/#container-labels)              | | ||||
| | `traefik.enable=false`                                              | Disables this container in Traefik.                                                                                                                                                                                              | | ||||
| | `traefik.port=80`                                                   | Registers this port. Useful when the container exposes multiples ports.                                                                                                                                                          | | ||||
| | `traefik.tags=foo,bar,myTag`                                        | Adds Traefik tags to the Docker container/service to be used in [constraints](/configuration/commons/#constraints).                                                                                                              | | ||||
| | `traefik.protocol=https`                                            | Overrides the default `http` protocol                                                                                                                                                                                            | | ||||
| | `traefik.weight=10`                                                 | Assigns this weight to the container                                                                                                                                                                                             | | ||||
| | `traefik.backend=foo`                                               | Gives the name `foo` to the generated backend for this container.                                                                                                                                                                | | ||||
| | `traefik.backend.buffering.maxRequestBodyBytes=0`                   | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.maxResponseBodyBytes=0`                  | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.memRequestBodyBytes=0`                   | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.memResponseBodyBytes=0`                  | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.retryExpression=EXPR`                    | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.circuitbreaker.expression=EXPR`                    | Creates a [circuit breaker](/basics/#backends) to be used against the backend                                                                                                                                                    | | ||||
| | `traefik.backend.responseForwarding.flushInterval=10ms`             | Defines the interval between two flushes when forwarding response from backend to client.                                                                                                                                        | | ||||
| | `traefik.backend.healthcheck.path=/health`                          | Enables health check for the backend, hitting the container at `path`.                                                                                                                                                           | | ||||
| | `traefik.backend.healthcheck.interval=1s`                           | Defines the health check interval.                                                                                                                                                                                               | | ||||
| | `traefik.backend.healthcheck.port=8080`                             | Sets a different port for the health check.                                                                                                                                                                                      | | ||||
| | `traefik.backend.healthcheck.scheme=http`                           | Overrides the server URL scheme.                                                                                                                                                                                                 | | ||||
| | `traefik.backend.healthcheck.hostname=foobar.com`                   | Defines the health check hostname.                                                                                                                                                                                               | | ||||
| | `traefik.backend.healthcheck.headers=EXPR`                          | Defines the health check request headers <br>Format:  <code>HEADER:value||HEADER2:value2</code>                                                                                                                        | | ||||
| | `traefik.backend.loadbalancer.method=drr`                           | Overrides the default `wrr` load balancer algorithm                                                                                                                                                                              | | ||||
| | `traefik.backend.loadbalancer.stickiness=true`                      | Enables backend sticky sessions                                                                                                                                                                                                  | | ||||
| | `traefik.backend.loadbalancer.stickiness.cookieName=NAME`           | Sets the cookie name manually for sticky sessions                                                                                                                                                                                | | ||||
| | `traefik.backend.loadbalancer.sticky=true`                          | Enables backend sticky sessions (DEPRECATED)                                                                                                                                                                                     | | ||||
| | `traefik.backend.loadbalancer.swarm=true`                           | Uses Swarm's inbuilt load balancer (only relevant under Swarm Mode).                                                                                                                                                             | | ||||
| | `traefik.backend.maxconn.amount=10`                                 | Sets a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect.                                                                                                         | | ||||
| | `traefik.backend.maxconn.extractorfunc=client.ip`                   | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.<br>Must be used in conjunction with the above label to take effect.                                           | | ||||
| | `traefik.frontend.auth.basic=EXPR`                                  | Sets the basic authentication to this frontend in CSV format: `User:Hash,User:Hash` [2] (DEPRECATED).                                                                                                                            | | ||||
| | `traefik.frontend.auth.basic.removeHeader=true`                     | If set to `true`, removes the `Authorization` header.                                                                                                                                                                            | | ||||
| | `traefik.frontend.auth.basic.users=EXPR`                            | Sets the basic authentication to this frontend in CSV format: `User:Hash,User:Hash` [2].                                                                                                                                         | | ||||
| | `traefik.frontend.auth.basic.usersFile=/path/.htpasswd`             | Sets the basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                        | | ||||
| | `traefik.frontend.auth.digest.removeHeader=true`                    | If set to `true`, removes the `Authorization` header.                                                                                                                                                                            | | ||||
| | `traefik.frontend.auth.digest.users=EXPR`                           | Sets the digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`.                                                                                                                                | | ||||
| | `traefik.frontend.auth.digest.usersFile=/path/.htdigest`            | Sets the digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                       | | ||||
| | `traefik.frontend.auth.forward.address=https://example.com`         | Sets the URL of the authentication server.                                                                                                                                                                                       | | ||||
| | `traefik.frontend.auth.forward.authResponseHeaders=EXPR`            | Sets the forward authentication authResponseHeaders in CSV format: `X-Auth-User,X-Auth-Header`                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.ca=/path/ca.pem`                 | Sets the Certificate Authority (CA) for the TLS connection with the authentication server.                                                                                                                                       | | ||||
| | `traefik.frontend.auth.forward.tls.caOptional=true`                 | Checks the certificates if present but do not force to be signed by a specified Certificate Authority (CA).                                                                                                                      | | ||||
| | `traefik.frontend.auth.forward.tls.cert=/path/server.pem`           | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                      | | ||||
| | `traefik.frontend.auth.forward.tls.insecureSkipVerify=true`         | If set to true invalid SSL certificates are accepted.                                                                                                                                                                            | | ||||
| | `traefik.frontend.auth.forward.tls.key=/path/server.key`            | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                      | | ||||
| | `traefik.frontend.auth.forward.trustForwardHeader=true`             | Trusts X-Forwarded-* headers.                                                                                                                                                                                                    | | ||||
| | `traefik.frontend.auth.headerField=X-WebAuth-User`                  | Sets the header user to pass the authenticated user to the application.                                                                                                                                                          | | ||||
| | `traefik.frontend.entryPoints=http,https`                           | Assigns this frontend to entry points `http` and `https`.<br>Overrides `defaultEntryPoints`                                                                                                                                      | | ||||
| | `traefik.frontend.errors.<name>.backend=NAME`                       | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                    | | ||||
| | `traefik.frontend.errors.<name>.query=PATH`                         | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                    | | ||||
| | `traefik.frontend.errors.<name>.status=RANGE`                       | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                    | | ||||
| | `traefik.frontend.passHostHeader=true`                              | Forwards client `Host` header to the backend.                                                                                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notAfter=true`            | Add the noAfter field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notBefore=true`           | Add the noBefore field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                              | | ||||
| | `traefik.frontend.passTLSClientCert.infos.sans=true`                | Add the sans field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.commonName=true`  | Add the subject.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.country=true`     | Add the subject.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                       | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.locality=true`    | Add the subject.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                      | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.organization=true`| Add the subject.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.province=true`    | Add the subject.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                      | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.serialNumber=true`| Add the subject.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.pem=true`                       | Pass the escaped pem in the `X-Forwarded-Ssl-Client-Cert` header.                                                                                                                                                                | | ||||
| | `traefik.frontend.passTLSCert=true`                                 | Forwards TLS Client certificates to the backend (DEPRECATED).                                                                                                                                                                    | | ||||
| | `traefik.frontend.priority=10`                                      | Overrides default frontend priority                                                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.extractorFunc=EXP`                      | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.period=6`                | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.average=6`               | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.burst=6`                 | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.redirect.entryPoint=https`                        | Enables Redirect to another entryPoint to this frontend (e.g. HTTPS)                                                                                                                                                             | | ||||
| | `traefik.frontend.redirect.regex=^http://localhost/(.*)`            | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.replacement`.                                                                                                                          | | ||||
| | `traefik.frontend.redirect.replacement=http://mydomain/$1`          | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.regex`.                                                                                                                                | | ||||
| | `traefik.frontend.redirect.permanent=true`                          | Returns 301 instead of 302.                                                                                                                                                                                                      | | ||||
| | `traefik.frontend.rule=EXPR`                                        | Overrides the default frontend rule. Default: `Host:{containerName}.{domain}` or `Host:{service}.{project_name}.{domain}` if you are using `docker-compose`.                                                                     | | ||||
| | `traefik.frontend.whiteList.sourceRange=RANGE`                      | Sets a list of IP-Ranges which are allowed to access.<br>An unset or empty list allows all Source-IPs to access.<br>If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. | | ||||
| | `traefik.frontend.whiteList.useXForwardedFor=true`                  | Uses `X-Forwarded-For` header as valid source of IP for the white list.                                                                                                                                                          | | ||||
| | Label                                                                   | Description                                                                                                                                                                                                                      | | ||||
| |-------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `traefik.docker.network`                                                | Overrides the default docker network to use for connections to the container. [1]                                                                                                                                                | | ||||
| | `traefik.domain`                                                        | Sets the default base domain for the frontend rules. For more information, check the [Container Labels section's of the user guide "Let's Encrypt & Docker"](/user-guide/docker-and-lets-encrypt/#container-labels)              | | ||||
| | `traefik.enable=false`                                                  | Disables this container in Traefik.                                                                                                                                                                                              | | ||||
| | `traefik.port=80`                                                       | Registers this port. Useful when the container exposes multiples ports.                                                                                                                                                          | | ||||
| | `traefik.tags=foo,bar,myTag`                                            | Adds Traefik tags to the Docker container/service to be used in [constraints](/configuration/commons/#constraints).                                                                                                              | | ||||
| | `traefik.protocol=https`                                                | Overrides the default `http` protocol                                                                                                                                                                                            | | ||||
| | `traefik.weight=10`                                                     | Assigns this weight to the container                                                                                                                                                                                             | | ||||
| | `traefik.backend=foo`                                                   | Overrides the container name by `foo` in the generated name of the backend.                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.maxRequestBodyBytes=0`                       | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.maxResponseBodyBytes=0`                      | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.memRequestBodyBytes=0`                       | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.memResponseBodyBytes=0`                      | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.retryExpression=EXPR`                        | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.circuitbreaker.expression=EXPR`                        | Creates a [circuit breaker](/basics/#backends) to be used against the backend                                                                                                                                                    | | ||||
| | `traefik.backend.responseForwarding.flushInterval=10ms`                 | Defines the interval between two flushes when forwarding response from backend to client.                                                                                                                                        | | ||||
| | `traefik.backend.healthcheck.path=/health`                              | Enables health check for the backend, hitting the container at `path`.                                                                                                                                                           | | ||||
| | `traefik.backend.healthcheck.interval=1s`                               | Defines the health check interval.                                                                                                                                                                                               | | ||||
| | `traefik.backend.healthcheck.port=8080`                                 | Sets a different port for the health check.                                                                                                                                                                                      | | ||||
| | `traefik.backend.healthcheck.scheme=http`                               | Overrides the server URL scheme.                                                                                                                                                                                                 | | ||||
| | `traefik.backend.healthcheck.hostname=foobar.com`                       | Defines the health check hostname.                                                                                                                                                                                               | | ||||
| | `traefik.backend.healthcheck.headers=EXPR`                              | Defines the health check request headers <br>Format:  <code>HEADER:value||HEADER2:value2</code>                                                                                                                        | | ||||
| | `traefik.backend.loadbalancer.method=drr`                               | Overrides the default `wrr` load balancer algorithm                                                                                                                                                                              | | ||||
| | `traefik.backend.loadbalancer.stickiness=true`                          | Enables backend sticky sessions                                                                                                                                                                                                  | | ||||
| | `traefik.backend.loadbalancer.stickiness.cookieName=NAME`               | Sets the cookie name manually for sticky sessions                                                                                                                                                                                | | ||||
| | `traefik.backend.loadbalancer.sticky=true`                              | Enables backend sticky sessions (DEPRECATED)                                                                                                                                                                                     | | ||||
| | `traefik.backend.loadbalancer.swarm=true`                               | Uses Swarm's inbuilt load balancer (only relevant under Swarm Mode) [3].                                                                                                                                                         | | ||||
| | `traefik.backend.maxconn.amount=10`                                     | Sets a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect.                                                                                                         | | ||||
| | `traefik.backend.maxconn.extractorfunc=client.ip`                       | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.<br>Must be used in conjunction with the above label to take effect.                                           | | ||||
| | `traefik.frontend.auth.basic=EXPR`                                      | Sets the basic authentication to this frontend in CSV format: `User:Hash,User:Hash` [2] (DEPRECATED).                                                                                                                            | | ||||
| | `traefik.frontend.auth.basic.removeHeader=true`                         | If set to `true`, removes the `Authorization` header.                                                                                                                                                                            | | ||||
| | `traefik.frontend.auth.basic.users=EXPR`                                | Sets the basic authentication to this frontend in CSV format: `User:Hash,User:Hash` [2].                                                                                                                                         | | ||||
| | `traefik.frontend.auth.basic.usersFile=/path/.htpasswd`                 | Sets the basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                        | | ||||
| | `traefik.frontend.auth.digest.removeHeader=true`                        | If set to `true`, removes the `Authorization` header.                                                                                                                                                                            | | ||||
| | `traefik.frontend.auth.digest.users=EXPR`                               | Sets the digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`.                                                                                                                                | | ||||
| | `traefik.frontend.auth.digest.usersFile=/path/.htdigest`                | Sets the digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                       | | ||||
| | `traefik.frontend.auth.forward.address=https://example.com`             | Sets the URL of the authentication server.                                                                                                                                                                                       | | ||||
| | `traefik.frontend.auth.forward.authResponseHeaders=EXPR`                | Sets the forward authentication authResponseHeaders in CSV format: `X-Auth-User,X-Auth-Header`                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.ca=/path/ca.pem`                     | Sets the Certificate Authority (CA) for the TLS connection with the authentication server.                                                                                                                                       | | ||||
| | `traefik.frontend.auth.forward.tls.caOptional=true`                     | Checks the certificates if present but do not force to be signed by a specified Certificate Authority (CA).                                                                                                                      | | ||||
| | `traefik.frontend.auth.forward.tls.cert=/path/server.pem`               | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                      | | ||||
| | `traefik.frontend.auth.forward.tls.insecureSkipVerify=true`             | If set to true invalid SSL certificates are accepted.                                                                                                                                                                            | | ||||
| | `traefik.frontend.auth.forward.tls.key=/path/server.key`                | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                      | | ||||
| | `traefik.frontend.auth.forward.trustForwardHeader=true`                 | Trusts X-Forwarded-* headers.                                                                                                                                                                                                    | | ||||
| | `traefik.frontend.auth.headerField=X-WebAuth-User`                      | Sets the header user to pass the authenticated user to the application.                                                                                                                                                          | | ||||
| | `traefik.frontend.entryPoints=http,https`                               | Assigns this frontend to entry points `http` and `https`.<br>Overrides `defaultEntryPoints`                                                                                                                                      | | ||||
| | `traefik.frontend.errors.<name>.backend=NAME`                           | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                    | | ||||
| | `traefik.frontend.errors.<name>.query=PATH`                             | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                    | | ||||
| | `traefik.frontend.errors.<name>.status=RANGE`                           | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                    | | ||||
| | `traefik.frontend.passHostHeader=true`                                  | Forwards client `Host` header to the backend.                                                                                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.commonName=true`       | Add the issuer.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                     | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.country=true`          | Add the issuer.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                        | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.domainComponent=true`  | Add the issuer.domainComponent field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.locality=true`         | Add the issuer.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                       | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.organization=true`     | Add the issuer.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.province=true`         | Add the issuer.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                       | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.serialNumber=true`     | Add the issuer.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notAfter=true`                | Add the noAfter field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notBefore=true`               | Add the noBefore field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                              | | ||||
| | `traefik.frontend.passTLSClientCert.infos.sans=true`                    | Add the sans field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.commonName=true`      | Add the subject.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.country=true`         | Add the subject.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                       | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.domainComponent=true` | Add the subject.domainComponent field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.locality=true`        | Add the subject.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                      | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.organization=true`    | Add the subject.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.province=true`        | Add the subject.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                      | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.serialNumber=true`    | Add the subject.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.pem=true`                           | Pass the escaped pem in the `X-Forwarded-Ssl-Client-Cert` header.                                                                                                                                                                | | ||||
| | `traefik.frontend.passTLSCert=true`                                     | Forwards TLS Client certificates to the backend (DEPRECATED).                                                                                                                                                                    | | ||||
| | `traefik.frontend.priority=10`                                          | Overrides default frontend priority                                                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.extractorFunc=EXP`                          | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.period=6`                    | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.average=6`                   | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.burst=6`                     | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.redirect.entryPoint=https`                            | Enables Redirect to another entryPoint to this frontend (e.g. HTTPS)                                                                                                                                                             | | ||||
| | `traefik.frontend.redirect.regex=^http://localhost/(.*)`                | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.replacement`.                                                                                                                          | | ||||
| | `traefik.frontend.redirect.replacement=http://mydomain/$1`              | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.regex`.                                                                                                                                | | ||||
| | `traefik.frontend.redirect.permanent=true`                              | Returns 301 instead of 302.                                                                                                                                                                                                      | | ||||
| | `traefik.frontend.rule=EXPR`                                            | Overrides the default frontend rule. Default: `Host:{containerName}.{domain}` or `Host:{service}.{project_name}.{domain}` if you are using `docker-compose`.                                                                     | | ||||
| | `traefik.frontend.whiteList.sourceRange=RANGE`                          | Sets a list of IP-Ranges which are allowed to access.<br>An unset or empty list allows all Source-IPs to access.<br>If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. | | ||||
| | `traefik.frontend.whiteList.useXForwardedFor=true`                      | Uses `X-Forwarded-For` header as valid source of IP for the white list.                                                                                                                                                          | | ||||
|  | ||||
| [1] `traefik.docker.network`: | ||||
| If a container is linked to several networks, be sure to set the proper network name (you can check with `docker inspect <container_id>`) otherwise it will randomly pick one (depending on how docker is returning them). | ||||
| [1] `traefik.docker.network`:   | ||||
| If a container is linked to several networks, be sure to set the proper network name (you can check with `docker inspect <container_id>`) otherwise it will randomly pick one (depending on how docker is returning them).   | ||||
| For instance when deploying docker `stack` from compose files, the compose defined networks will be prefixed with the `stack` name. | ||||
| Or if your service references external network use it's name instead. | ||||
|  | ||||
| [2] `traefik.frontend.auth.basic.users=EXPR `:   | ||||
| [2] `traefik.frontend.auth.basic.users=EXPR`:   | ||||
| To create `user:password` pair, it's possible to use this command:   | ||||
| `echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g`.   | ||||
| The result will be `user:$$apr1$$9Cv/OMGj$$ZomWQzuQbL.3TRCS81A1g/`, note additional symbol `$` makes escaping. | ||||
|  | ||||
| [3] `traefik.backend.loadbalancer.swarm`:   | ||||
| If you enable this option, Traefik will use the virtual IP provided by docker swarm instead of the containers IPs. | ||||
| Which means that Traefik will not perform any kind of load balancing and will delegate this task to swarm.   | ||||
| It also means that Traefik will manipulate only one backend, not one backend per container. | ||||
|  | ||||
| #### Custom Headers | ||||
|  | ||||
| | Label                                                 | Description                                                                                                                                                                         | | ||||
| |-------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `traefik.frontend.headers.customRequestHeaders=EXPR ` | Provides the container with custom request headers that will be appended to each request forwarded to the container.<br>Format: <code>HEADER:value||HEADER2:value2</code> | | ||||
| | `traefik.frontend.headers.customRequestHeaders=EXPR`  | Provides the container with custom request headers that will be appended to each request forwarded to the container.<br>Format: <code>HEADER:value||HEADER2:value2</code> | | ||||
| | `traefik.frontend.headers.customResponseHeaders=EXPR` | Appends the headers to each response returned by the container, before forwarding the response to the client.<br>Format: <code>HEADER:value||HEADER2:value2</code>        | | ||||
|  | ||||
| #### Security Headers | ||||
| @@ -314,7 +404,7 @@ The result will be `user:$$apr1$$9Cv/OMGj$$ZomWQzuQbL.3TRCS81A1g/`, note additio | ||||
| | `traefik.frontend.headers.customFrameOptionsValue=VALUE` | Overrides the `X-Frame-Options` header with the custom value.                                                                                                                                       | | ||||
| | `traefik.frontend.headers.forceSTSHeader=false`          | Adds the STS  header to non-SSL requests.                                                                                                                                                           | | ||||
| | `traefik.frontend.headers.frameDeny=false`               | Adds the `X-Frame-Options` header with the value of `DENY`.                                                                                                                                         | | ||||
| | `traefik.frontend.headers.hostsProxyHeaders=EXPR `       | Provides a list of headers that the proxied hostname may be stored.<br>Format: `HEADER1,HEADER2`                                                                                                    | | ||||
| | `traefik.frontend.headers.hostsProxyHeaders=EXPR`        | Provides a list of headers that the proxied hostname may be stored.<br>Format: `HEADER1,HEADER2`                                                                                                    | | ||||
| | `traefik.frontend.headers.isDevelopment=false`           | This will cause the `AllowedHosts`, `SSLRedirect`, and `STSSeconds`/`STSIncludeSubdomains` options to be ignored during development.<br>When deploying to production, be sure to set this to false. | | ||||
| | `traefik.frontend.headers.publicKey=VALUE`               | Adds HPKP header.                                                                                                                                                                                   | | ||||
| | `traefik.frontend.headers.referrerPolicy=VALUE`          | Adds referrer policy  header.                                                                                                                                                                       | | ||||
| @@ -335,63 +425,71 @@ You can define as many segments as ports exposed in a container. | ||||
|  | ||||
| Segment labels override the default behavior. | ||||
|  | ||||
| | Label                                                                              | Description                                                            | | ||||
| |------------------------------------------------------------------------------------|------------------------------------------------------------------------| | ||||
| | `traefik.<segment_name>.backend=BACKEND`                                           | Same as `traefik.backend`                                              | | ||||
| | `traefik.<segment_name>.domain=DOMAIN`                                             | Same as `traefik.domain`                                               | | ||||
| | `traefik.<segment_name>.port=PORT`                                                 | Same as `traefik.port`                                                 | | ||||
| | `traefik.<segment_name>.protocol=http`                                             | Same as `traefik.protocol`                                             | | ||||
| | `traefik.<segment_name>.weight=10`                                                 | Same as `traefik.weight`                                               | | ||||
| | `traefik.<segment_name>.frontend.auth.basic=EXPR`                                  | Same as `traefik.frontend.auth.basic`                                  | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.removeHeader=true`                     | Same as `traefik.frontend.auth.basic.removeHeader`                     | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.users=EXPR`                            | Same as `traefik.frontend.auth.basic.users`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.usersFile=/path/.htpasswd`             | Same as `traefik.frontend.auth.basic.usersFile`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.removeHeader=true`                    | Same as `traefik.frontend.auth.digest.removeHeader`                    | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.users=EXPR`                           | Same as `traefik.frontend.auth.digest.users`                           | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.usersFile=/path/.htdigest`            | Same as `traefik.frontend.auth.digest.usersFile`                       | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.address=https://example.com`         | Same as `traefik.frontend.auth.forward.address`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.authResponseHeaders=EXPR`            | Same as `traefik.frontend.auth.forward.authResponseHeaders`            | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.ca=/path/ca.pem`                 | Same as `traefik.frontend.auth.forward.tls.ca`                         | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.caOptional=true`                 | Same as `traefik.frontend.auth.forward.tls.caOptional`                 | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.cert=/path/server.pem`           | Same as `traefik.frontend.auth.forward.tls.cert`                       | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.insecureSkipVerify=true`         | Same as `traefik.frontend.auth.forward.tls.insecureSkipVerify`         | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.key=/path/server.key`            | Same as `traefik.frontend.auth.forward.tls.key`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.trustForwardHeader=true`             | Same as `traefik.frontend.auth.forward.trustForwardHeader`             | | ||||
| | `traefik.<segment_name>.frontend.auth.headerField=X-WebAuth-User`                  | Same as `traefik.frontend.auth.headerField`                            | | ||||
| | `traefik.<segment_name>.frontend.entryPoints=https`                                | Same as `traefik.frontend.entryPoints`                                 | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.backend=NAME`                       | Same as `traefik.frontend.errors.<name>.backend`                       | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.query=PATH`                         | Same as `traefik.frontend.errors.<name>.query`                         | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.status=RANGE`                       | Same as `traefik.frontend.errors.<name>.status`                        | | ||||
| | `traefik.<segment_name>.frontend.passHostHeader=true`                              | Same as `traefik.frontend.passHostHeader`                              | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notAfter=true`            | Same as `traefik.frontend.passTLSClientCert.infos.notAfter`            | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notBefore=true`           | Same as `traefik.frontend.passTLSClientCert.infos.notBefore`           | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.sans=true`                | Same as `traefik.frontend.passTLSClientCert.infos.sans`                | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.commonName=true`  | Same as `traefik.frontend.passTLSClientCert.infos.subject.commonName`  | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.country=true`     | Same as `traefik.frontend.passTLSClientCert.infos.subject.country`     | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.locality=true`    | Same as `traefik.frontend.passTLSClientCert.infos.subject.locality`    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.organization=true`| Same as `traefik.frontend.passTLSClientCert.infos.subject.organization`| | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.province=true`    | Same as `traefik.frontend.passTLSClientCert.infos.subject.province`    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.serialNumber=true`| Same as `traefik.frontend.passTLSClientCert.infos.subject.serialNumber`| | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.pem=true`                       | Same as `traefik.frontend.passTLSClientCert.infos.pem`                 | | ||||
| | `traefik.<segment_name>.frontend.passTLSCert=true`                                 | Same as `traefik.frontend.passTLSCert`                                 | | ||||
| | `traefik.<segment_name>.frontend.priority=10`                                      | Same as `traefik.frontend.priority`                                    | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.extractorFunc=EXP`                      | Same as `traefik.frontend.rateLimit.extractorFunc`                     | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.period=6`                | Same as `traefik.frontend.rateLimit.rateSet.<name>.period`             | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.average=6`               | Same as `traefik.frontend.rateLimit.rateSet.<name>.average`            | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.burst=6`                 | Same as `traefik.frontend.rateLimit.rateSet.<name>.burst`              | | ||||
| | `traefik.<segment_name>.frontend.redirect.entryPoint=https`                        | Same as `traefik.frontend.redirect.entryPoint`                         | | ||||
| | `traefik.<segment_name>.frontend.redirect.regex=^http://localhost/(.*)`            | Same as `traefik.frontend.redirect.regex`                              | | ||||
| | `traefik.<segment_name>.frontend.redirect.replacement=http://mydomain/$1`          | Same as `traefik.frontend.redirect.replacement`                        | | ||||
| | `traefik.<segment_name>.frontend.redirect.permanent=true`                          | Same as `traefik.frontend.redirect.permanent`                          | | ||||
| | `traefik.<segment_name>.frontend.rule=EXP`                                         | Same as `traefik.frontend.rule`                                        | | ||||
| | `traefik.<segment_name>.frontend.whiteList.sourceRange=RANGE`                      | Same as `traefik.frontend.whiteList.sourceRange`                       | | ||||
| | `traefik.<segment_name>.frontend.whiteList.useXForwardedFor=true`                  | Same as `traefik.frontend.whiteList.useXForwardedFor`                  | | ||||
| | Label                                                                                  | Description                                                                | | ||||
| |----------------------------------------------------------------------------------------|----------------------------------------------------------------------------| | ||||
| | `traefik.<segment_name>.backend=BACKEND`                                               | Same as `traefik.backend`                                                  | | ||||
| | `traefik.<segment_name>.domain=DOMAIN`                                                 | Same as `traefik.domain`                                                   | | ||||
| | `traefik.<segment_name>.port=PORT`                                                     | Same as `traefik.port`                                                     | | ||||
| | `traefik.<segment_name>.protocol=http`                                                 | Same as `traefik.protocol`                                                 | | ||||
| | `traefik.<segment_name>.weight=10`                                                     | Same as `traefik.weight`                                                   | | ||||
| | `traefik.<segment_name>.frontend.auth.basic=EXPR`                                      | Same as `traefik.frontend.auth.basic`                                      | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.removeHeader=true`                         | Same as `traefik.frontend.auth.basic.removeHeader`                         | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.users=EXPR`                                | Same as `traefik.frontend.auth.basic.users`                                | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.usersFile=/path/.htpasswd`                 | Same as `traefik.frontend.auth.basic.usersFile`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.removeHeader=true`                        | Same as `traefik.frontend.auth.digest.removeHeader`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.users=EXPR`                               | Same as `traefik.frontend.auth.digest.users`                               | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.usersFile=/path/.htdigest`                | Same as `traefik.frontend.auth.digest.usersFile`                           | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.address=https://example.com`             | Same as `traefik.frontend.auth.forward.address`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.authResponseHeaders=EXPR`                | Same as `traefik.frontend.auth.forward.authResponseHeaders`                | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.ca=/path/ca.pem`                     | Same as `traefik.frontend.auth.forward.tls.ca`                             | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.caOptional=true`                     | Same as `traefik.frontend.auth.forward.tls.caOptional`                     | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.cert=/path/server.pem`               | Same as `traefik.frontend.auth.forward.tls.cert`                           | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.insecureSkipVerify=true`             | Same as `traefik.frontend.auth.forward.tls.insecureSkipVerify`             | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.key=/path/server.key`                | Same as `traefik.frontend.auth.forward.tls.key`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.trustForwardHeader=true`                 | Same as `traefik.frontend.auth.forward.trustForwardHeader`                 | | ||||
| | `traefik.<segment_name>.frontend.auth.headerField=X-WebAuth-User`                      | Same as `traefik.frontend.auth.headerField`                                | | ||||
| | `traefik.<segment_name>.frontend.entryPoints=https`                                    | Same as `traefik.frontend.entryPoints`                                     | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.backend=NAME`                           | Same as `traefik.frontend.errors.<name>.backend`                           | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.query=PATH`                             | Same as `traefik.frontend.errors.<name>.query`                             | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.status=RANGE`                           | Same as `traefik.frontend.errors.<name>.status`                            | | ||||
| | `traefik.<segment_name>.frontend.passHostHeader=true`                                  | Same as `traefik.frontend.passHostHeader`                                  | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.commonName=true`       | Same as `traefik.frontend.passTLSClientCert.infos.issuer.commonName`       | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.country=true`          | Same as `traefik.frontend.passTLSClientCert.infos.issuer.country`          | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.domainComponent=true`  | Same as `traefik.frontend.passTLSClientCert.infos.issuer.domainComponent`  | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.locality=true`         | Same as `traefik.frontend.passTLSClientCert.infos.issuer.locality`         | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.organization=true`     | Same as `traefik.frontend.passTLSClientCert.infos.issuer.organization`     | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.province=true`         | Same as `traefik.frontend.passTLSClientCert.infos.issuer.province`         | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.serialNumber=true`     | Same as `traefik.frontend.passTLSClientCert.infos.issuer.serialNumber`     | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notAfter=true`                | Same as `traefik.frontend.passTLSClientCert.infos.notAfter`                | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notBefore=true`               | Same as `traefik.frontend.passTLSClientCert.infos.notBefore`               | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.sans=true`                    | Same as `traefik.frontend.passTLSClientCert.infos.sans`                    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.commonName=true`      | Same as `traefik.frontend.passTLSClientCert.infos.subject.commonName`      | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.country=true`         | Same as `traefik.frontend.passTLSClientCert.infos.subject.country`         | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.domainComponent=true` | Same as `traefik.frontend.passTLSClientCert.infos.subject.domainComponent` | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.locality=true`        | Same as `traefik.frontend.passTLSClientCert.infos.subject.locality`        | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.organization=true`    | Same as `traefik.frontend.passTLSClientCert.infos.subject.organization`    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.province=true`        | Same as `traefik.frontend.passTLSClientCert.infos.subject.province`        | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.serialNumber=true`    | Same as `traefik.frontend.passTLSClientCert.infos.subject.serialNumber`    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.pem=true`                           | Same as `traefik.frontend.passTLSClientCert.infos.pem`                     | | ||||
| | `traefik.<segment_name>.frontend.passTLSCert=true`                                     | Same as `traefik.frontend.passTLSCert`                                     | | ||||
| | `traefik.<segment_name>.frontend.priority=10`                                          | Same as `traefik.frontend.priority`                                        | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.extractorFunc=EXP`                          | Same as `traefik.frontend.rateLimit.extractorFunc`                         | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.period=6`                    | Same as `traefik.frontend.rateLimit.rateSet.<name>.period`                 | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.average=6`                   | Same as `traefik.frontend.rateLimit.rateSet.<name>.average`                | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.burst=6`                     | Same as `traefik.frontend.rateLimit.rateSet.<name>.burst`                  | | ||||
| | `traefik.<segment_name>.frontend.redirect.entryPoint=https`                            | Same as `traefik.frontend.redirect.entryPoint`                             | | ||||
| | `traefik.<segment_name>.frontend.redirect.regex=^http://localhost/(.*)`                | Same as `traefik.frontend.redirect.regex`                                  | | ||||
| | `traefik.<segment_name>.frontend.redirect.replacement=http://mydomain/$1`              | Same as `traefik.frontend.redirect.replacement`                            | | ||||
| | `traefik.<segment_name>.frontend.redirect.permanent=true`                              | Same as `traefik.frontend.redirect.permanent`                              | | ||||
| | `traefik.<segment_name>.frontend.rule=EXP`                                             | Same as `traefik.frontend.rule`                                            | | ||||
| | `traefik.<segment_name>.frontend.whiteList.sourceRange=RANGE`                          | Same as `traefik.frontend.whiteList.sourceRange`                           | | ||||
| | `traefik.<segment_name>.frontend.whiteList.useXForwardedFor=true`                      | Same as `traefik.frontend.whiteList.useXForwardedFor`                      | | ||||
|  | ||||
| #### Custom Headers | ||||
|  | ||||
| | Label                                                                | Description                                              | | ||||
| |----------------------------------------------------------------------|----------------------------------------------------------| | ||||
| | `traefik.<segment_name>.frontend.headers.customRequestHeaders=EXPR ` | Same as `traefik.frontend.headers.customRequestHeaders`  | | ||||
| | `traefik.<segment_name>.frontend.headers.customRequestHeaders=EXPR`  | Same as `traefik.frontend.headers.customRequestHeaders`  | | ||||
| | `traefik.<segment_name>.frontend.headers.customResponseHeaders=EXPR` | Same as `traefik.frontend.headers.customResponseHeaders` | | ||||
|  | ||||
| #### Security Headers | ||||
|   | ||||
| @@ -136,78 +136,86 @@ Traefik needs the following policy to read ECS information: | ||||
|  | ||||
| Labels can be used on task containers to override default behaviour: | ||||
|  | ||||
| | Label                                                               | Description                                                                                                                                                                                                                   | | ||||
| |---------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `traefik.domain`                                                    | Sets the default base domain for frontend rules.                                                                                                                                                                                   | | ||||
| | `traefik.enable=false`                                              | Disables this container in Traefik.                                                                                                                                                                                            | | ||||
| | `traefik.port=80`                                                   | Overrides the default `port` value. Overrides `NetworkBindings` from Docker Container                                                                                                                                         | | ||||
| | `traefik.protocol=https`                                            | Overrides the default `http` protocol                                                                                                                                                                                         | | ||||
| | `traefik.weight=10`                                                 | Assigns this weight to the container                                                                                                                                                                                          | | ||||
| | `traefik.backend=foo`                                               | Gives the name `foo` to the generated backend for this container.                                                                                                                                                             | | ||||
| | `traefik.backend.buffering.maxRequestBodyBytes=0`                   | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.maxResponseBodyBytes=0`                  | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memRequestBodyBytes=0`                   | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memResponseBodyBytes=0`                  | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.retryExpression=EXPR`                    | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.circuitbreaker.expression=EXPR`                    | Creates a [circuit breaker](/basics/#backends) to be used against the backend                                                                                                                                                 | | ||||
| | `traefik.backend.responseForwarding.flushInterval=10ms`            | Defines the interval between two flushes when forwarding response from backend to client.                                                                                                                                     | | ||||
| | `traefik.backend.healthcheck.path=/health`                          | Enables health check for the backend, hitting the container at `path`.                                                                                                                                                        | | ||||
| | `traefik.backend.healthcheck.interval=1s`                           | Defines the health check interval. (Default: 30s)                                                                                                                                                                             | | ||||
| | `traefik.backend.healthcheck.scheme=http`                           | Overrides the server URL scheme.                                                                                                                                                                                              | | ||||
| | `traefik.backend.healthcheck.port=8080`                             | Sets a different port for the health check.                                                                                                                                                                                   | | ||||
| | `traefik.backend.healthcheck.hostname=foobar.com`                   | Defines the health check hostname.                                                                                                                                                                                            | | ||||
| | `traefik.backend.healthcheck.headers=EXPR`                          | Defines the health check request headers <br>Format:  <code>HEADER:value||HEADER2:value2</code>                                                                                                                     | | ||||
| | `traefik.backend.loadbalancer.method=drr`                           | Overrides the default `wrr` load balancer algorithm                                                                                                                                                                           | | ||||
| | `traefik.backend.loadbalancer.stickiness=true`                      | Enables backend sticky sessions                                                                                                                                                                                               | | ||||
| | `traefik.backend.loadbalancer.stickiness.cookieName=NAME`           | Sets the cookie manually  name for sticky sessions                                                                                                                                                                            | | ||||
| | `traefik.backend.loadbalancer.sticky=true`                          | Enables backend sticky sessions (DEPRECATED)                                                                                                                                                                                  | | ||||
| | `traefik.backend.maxconn.amount=10`                                 | Sets a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect.                                                                                                      | | ||||
| | `traefik.backend.maxconn.extractorfunc=client.ip`                   | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.<br>Must be used in conjunction with the above label to take effect.                                        | | ||||
| | `traefik.frontend.auth.basic=EXPR`                                  | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED).                                                                                                                                 | | ||||
| | `traefik.frontend.auth.basic.removeHeader=true`                     | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.basic.users=EXPR`                            | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash`.                                                                                                                                              | | ||||
| | `traefik.frontend.auth.basic.usersFile=/path/.htpasswd`             | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                         | | ||||
| | `traefik.frontend.auth.digest.removeHeader=true`                    | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.digest.users=EXPR`                           | Sets digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`.                                                                                                                                 | | ||||
| | `traefik.frontend.auth.digest.usersFile=/path/.htdigest`            | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                        | | ||||
| | `traefik.frontend.auth.forward.address=https://example.com`         | Sets the URL of the authentication server.                                                                                                                                                                                    | | ||||
| | `traefik.frontend.auth.forward.authResponseHeaders=EXPR`            | Sets the forward authentication authResponseHeaders in CSV format: `X-Auth-User,X-Auth-Header`                                                                                                                                | | ||||
| | `traefik.frontend.auth.forward.tls.ca=/path/ca.pem`                 | Sets the Certificate Authority (CA) for the TLS connection with the authentication server.                                                                                                                                    | | ||||
| | `traefik.frontend.auth.forward.tls.caOptional=true`                 | Checks the certificates if present but do not force to be signed by a specified Certificate Authority (CA).                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.cert=/path/server.pem`           | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.insecureSkipVerify=true`         | If set to true invalid SSL certificates are accepted.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.forward.tls.key=/path/server.key`            | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.trustForwardHeader=true`             | Trusts X-Forwarded-* headers.                                                                                                                                                                                                 | | ||||
| | `traefik.frontend.auth.headerField=X-WebAuth-User`                  | Sets the header used to pass the authenticated user to the application.                                                                                                                                                       | | ||||
| | `traefik.frontend.auth.removeHeader=true`                           | If set to true, removes the Authorization header.                                                                                                                                                                             | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notAfter=true`            | Add the noAfter field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                            | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notBefore=true`           | Add the noBefore field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                           | | ||||
| | `traefik.frontend.passTLSClientCert.infos.sans=true`                | Add the sans field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.commonName=true`  | Add the subject.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                 | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.country=true`     | Add the subject.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.locality=true`    | Add the subject.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.organization=true`| Add the subject.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.province=true`    | Add the subject.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.serialNumber=true`| Add the subject.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.pem=true`                       | Pass the escaped pem in the `X-Forwarded-Ssl-Client-Cert` header.                                                                                                                                                           | | ||||
| | `traefik.frontend.entryPoints=http,https`                           | Assigns this frontend to entry points `http` and `https`.<br>Overrides `defaultEntryPoints`                                                                                                                               | | ||||
| | `traefik.frontend.errors.<name>.backend=NAME`                       | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.errors.<name>.query=PATH`                         | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.errors.<name>.status=RANGE`                       | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.passHostHeader=true`                              | Forwards client `Host` header to the backend.                                                                                                                                                                                 | | ||||
| | `traefik.frontend.passTLSCert=true`                                 | Forwards TLS Client certificates to the backend.                                                                                                                                                                              | | ||||
| | `traefik.frontend.priority=10`                                      | Overrides default frontend priority                                                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.extractorFunc=EXP`                      | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.period=6`                | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.average=6`               | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.burst=6`                 | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.redirect.entryPoint=https`                        | Enables Redirect to another entryPoint to this frontend (e.g. HTTPS)                                                                                                                                                          | | ||||
| | `traefik.frontend.redirect.regex=^http://localhost/(.*)`            | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.replacement`.                                                                                                                       | | ||||
| | `traefik.frontend.redirect.replacement=http://mydomain/$1`          | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.regex`.                                                                                                                             | | ||||
| | `traefik.frontend.redirect.permanent=true`                          | Returns 301 instead of 302.                                                                                                                                                                                                   | | ||||
| | `traefik.frontend.rule=EXPR`                                        | Overrides the default frontend rule. Default: `Host:{instance_name}.{domain}`.                                                                                                                                                | | ||||
| | `traefik.frontend.whiteList.sourceRange=RANGE`                      | Sets a list of IP-Ranges which are allowed to access.<br>An unset or empty list allows all Source-IPs to access. If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. | | ||||
| | `traefik.frontend.whiteList.useXForwardedFor=true`                  | Uses `X-Forwarded-For` header as valid source of IP for the white list.                                                                                                                                                       | | ||||
| | Label                                                                   | Description                                                                                                                                                                                                                   | | ||||
| |-------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `traefik.domain`                                                        | Sets the default base domain for frontend rules.                                                                                                                                                                              | | ||||
| | `traefik.enable=false`                                                  | Disables this container in Traefik.                                                                                                                                                                                           | | ||||
| | `traefik.port=80`                                                       | Overrides the default `port` value. Overrides `NetworkBindings` from Docker Container                                                                                                                                         | | ||||
| | `traefik.protocol=https`                                                | Overrides the default `http` protocol                                                                                                                                                                                         | | ||||
| | `traefik.weight=10`                                                     | Assigns this weight to the container                                                                                                                                                                                          | | ||||
| | `traefik.backend=foo`                                                   | Overrides the service name by `foo` in the generated name of the backend.                                                                                                                                                     | | ||||
| | `traefik.backend.buffering.maxRequestBodyBytes=0`                       | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.maxResponseBodyBytes=0`                      | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memRequestBodyBytes=0`                       | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memResponseBodyBytes=0`                      | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.retryExpression=EXPR`                        | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.circuitbreaker.expression=EXPR`                        | Creates a [circuit breaker](/basics/#backends) to be used against the backend                                                                                                                                                 | | ||||
| | `traefik.backend.responseForwarding.flushInterval=10ms`                 | Defines the interval between two flushes when forwarding response from backend to client.                                                                                                                                     | | ||||
| | `traefik.backend.healthcheck.path=/health`                              | Enables health check for the backend, hitting the container at `path`.                                                                                                                                                        | | ||||
| | `traefik.backend.healthcheck.interval=1s`                               | Defines the health check interval. (Default: 30s)                                                                                                                                                                             | | ||||
| | `traefik.backend.healthcheck.scheme=http`                               | Overrides the server URL scheme.                                                                                                                                                                                              | | ||||
| | `traefik.backend.healthcheck.port=8080`                                 | Sets a different port for the health check.                                                                                                                                                                                   | | ||||
| | `traefik.backend.healthcheck.hostname=foobar.com`                       | Defines the health check hostname.                                                                                                                                                                                            | | ||||
| | `traefik.backend.healthcheck.headers=EXPR`                              | Defines the health check request headers <br>Format:  <code>HEADER:value||HEADER2:value2</code>                                                                                                                     | | ||||
| | `traefik.backend.loadbalancer.method=drr`                               | Overrides the default `wrr` load balancer algorithm                                                                                                                                                                           | | ||||
| | `traefik.backend.loadbalancer.stickiness=true`                          | Enables backend sticky sessions                                                                                                                                                                                               | | ||||
| | `traefik.backend.loadbalancer.stickiness.cookieName=NAME`               | Sets the cookie manually  name for sticky sessions                                                                                                                                                                            | | ||||
| | `traefik.backend.loadbalancer.sticky=true`                              | Enables backend sticky sessions (DEPRECATED)                                                                                                                                                                                  | | ||||
| | `traefik.backend.maxconn.amount=10`                                     | Sets a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect.                                                                                                      | | ||||
| | `traefik.backend.maxconn.extractorfunc=client.ip`                       | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.<br>Must be used in conjunction with the above label to take effect.                                        | | ||||
| | `traefik.frontend.auth.basic=EXPR`                                      | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED).                                                                                                                                 | | ||||
| | `traefik.frontend.auth.basic.removeHeader=true`                         | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.basic.users=EXPR`                                | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash`.                                                                                                                                              | | ||||
| | `traefik.frontend.auth.basic.usersFile=/path/.htpasswd`                 | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                         | | ||||
| | `traefik.frontend.auth.digest.removeHeader=true`                        | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.digest.users=EXPR`                               | Sets digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`.                                                                                                                                 | | ||||
| | `traefik.frontend.auth.digest.usersFile=/path/.htdigest`                | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                        | | ||||
| | `traefik.frontend.auth.forward.address=https://example.com`             | Sets the URL of the authentication server.                                                                                                                                                                                    | | ||||
| | `traefik.frontend.auth.forward.authResponseHeaders=EXPR`                | Sets the forward authentication authResponseHeaders in CSV format: `X-Auth-User,X-Auth-Header`                                                                                                                                | | ||||
| | `traefik.frontend.auth.forward.tls.ca=/path/ca.pem`                     | Sets the Certificate Authority (CA) for the TLS connection with the authentication server.                                                                                                                                    | | ||||
| | `traefik.frontend.auth.forward.tls.caOptional=true`                     | Checks the certificates if present but do not force to be signed by a specified Certificate Authority (CA).                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.cert=/path/server.pem`               | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.insecureSkipVerify=true`             | If set to true invalid SSL certificates are accepted.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.forward.tls.key=/path/server.key`                | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.trustForwardHeader=true`                 | Trusts X-Forwarded-* headers.                                                                                                                                                                                                 | | ||||
| | `traefik.frontend.auth.headerField=X-WebAuth-User`                      | Sets the header used to pass the authenticated user to the application.                                                                                                                                                       | | ||||
| | `traefik.frontend.auth.removeHeader=true`                               | If set to true, removes the Authorization header.                                                                                                                                                                             | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.commonName=true`       | Add the issuer.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.country=true`          | Add the issuer.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                     | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.domainComponent=true`  | Add the issuer.domainComponent field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                            | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.locality=true`         | Add the issuer.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.organization=true`     | Add the issuer.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.province=true`         | Add the issuer.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.serialNumber=true`     | Add the issuer.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notAfter=true`                | Add the noAfter field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                            | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notBefore=true`               | Add the noBefore field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                           | | ||||
| | `traefik.frontend.passTLSClientCert.infos.sans=true`                    | Add the sans field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.commonName=true`      | Add the subject.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                 | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.country=true`         | Add the subject.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.domainComponent=true` | Add the subject.domainComponent field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                           | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.locality=true`        | Add the subject.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.organization=true`    | Add the subject.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.province=true`        | Add the subject.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.serialNumber=true`    | Add the subject.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.pem=true`                           | Pass the escaped pem in the `X-Forwarded-Ssl-Client-Cert` header.                                                                                                                                                             | | ||||
| | `traefik.frontend.entryPoints=http,https`                               | Assigns this frontend to entry points `http` and `https`.<br>Overrides `defaultEntryPoints`                                                                                                                                   | | ||||
| | `traefik.frontend.errors.<name>.backend=NAME`                           | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.errors.<name>.query=PATH`                             | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.errors.<name>.status=RANGE`                           | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.passHostHeader=true`                                  | Forwards client `Host` header to the backend.                                                                                                                                                                                 | | ||||
| | `traefik.frontend.passTLSCert=true`                                     | Forwards TLS Client certificates to the backend.                                                                                                                                                                              | | ||||
| | `traefik.frontend.priority=10`                                          | Overrides default frontend priority                                                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.extractorFunc=EXP`                          | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.period=6`                    | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.average=6`                   | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.burst=6`                     | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.redirect.entryPoint=https`                            | Enables Redirect to another entryPoint to this frontend (e.g. HTTPS)                                                                                                                                                          | | ||||
| | `traefik.frontend.redirect.regex=^http://localhost/(.*)`                | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.replacement`.                                                                                                                       | | ||||
| | `traefik.frontend.redirect.replacement=http://mydomain/$1`              | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.regex`.                                                                                                                             | | ||||
| | `traefik.frontend.redirect.permanent=true`                              | Returns 301 instead of 302.                                                                                                                                                                                                   | | ||||
| | `traefik.frontend.rule=EXPR`                                            | Overrides the default frontend rule. Default: `Host:{instance_name}.{domain}`.                                                                                                                                                | | ||||
| | `traefik.frontend.whiteList.sourceRange=RANGE`                          | Sets a list of IP-Ranges which are allowed to access.<br>An unset or empty list allows all Source-IPs to access. If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. | | ||||
| | `traefik.frontend.whiteList.useXForwardedFor=true`                      | Uses `X-Forwarded-For` header as valid source of IP for the white list.                                                                                                                                                       | | ||||
|  | ||||
| ### Custom Headers | ||||
|  | ||||
| @@ -249,58 +257,66 @@ You can define as many segments as ports exposed in an application. | ||||
|  | ||||
| Segment labels override the default behavior. | ||||
|  | ||||
| | Label                                                                               | Description                                                             | | ||||
| |-------------------------------------------------------------------------------------|-------------------------------------------------------------------------| | ||||
| | `traefik.<segment_name>.backend=BACKEND`                                            | Same as `traefik.backend`                                               | | ||||
| | `traefik.<segment_name>.domain=DOMAIN`                                              | Same as `traefik.domain`                                                | | ||||
| | `traefik.<segment_name>.port=PORT`                                                  | Same as `traefik.port`                                                  | | ||||
| | `traefik.<segment_name>.protocol=http`                                              | Same as `traefik.protocol`                                              | | ||||
| | `traefik.<segment_name>.weight=10`                                                  | Same as `traefik.weight`                                                | | ||||
| | `traefik.<segment_name>.frontend.auth.basic=EXPR`                                   | Same as `traefik.frontend.auth.basic`                                   | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.removeHeader=true`                      | Same as `traefik.frontend.auth.basic.removeHeader`                      | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.users=EXPR`                             | Same as `traefik.frontend.auth.basic.users`                             | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.usersFile=/path/.htpasswd`              | Same as `traefik.frontend.auth.basic.usersFile`                         | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.removeHeader=true`                     | Same as `traefik.frontend.auth.digest.removeHeader`                     | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.users=EXPR`                            | Same as `traefik.frontend.auth.digest.users`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.usersFile=/path/.htdigest`             | Same as `traefik.frontend.auth.digest.usersFile`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.address=https://example.com`          | Same as `traefik.frontend.auth.forward.address`                         | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.authResponseHeaders=EXPR`             | Same as `traefik.frontend.auth.forward.authResponseHeaders`             | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.ca=/path/ca.pem`                  | Same as `traefik.frontend.auth.forward.tls.ca`                          | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.caOptional=true`                  | Same as `traefik.frontend.auth.forward.tls.caOptional`                  | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.cert=/path/server.pem`            | Same as `traefik.frontend.auth.forward.tls.cert`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.insecureSkipVerify=true`          | Same as `traefik.frontend.auth.forward.tls.insecureSkipVerify`          | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.key=/path/server.key`             | Same as `traefik.frontend.auth.forward.tls.key`                         | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.trustForwardHeader=true`              | Same as `traefik.frontend.auth.forward.trustForwardHeader`              | | ||||
| | `traefik.<segment_name>.frontend.auth.headerField=X-WebAuth-User`                   | Same as `traefik.frontend.auth.headerField`                             | | ||||
| | `traefik.<segment_name>.frontend.auth.removeHeader=true`                            | Same as `traefik.frontend.auth.removeHeader`                            | | ||||
| | `traefik.<segment_name>.frontend.entryPoints=https`                                 | Same as `traefik.frontend.entryPoints`                                  | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.backend=NAME`                        | Same as `traefik.frontend.errors.<name>.backend`                        | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.query=PATH`                          | Same as `traefik.frontend.errors.<name>.query`                          | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.status=RANGE`                        | Same as `traefik.frontend.errors.<name>.status`                         | | ||||
| | `traefik.<segment_name>.frontend.passHostHeader=true`                               | Same as `traefik.frontend.passHostHeader`                               | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notAfter=true`             | Same as `traefik.frontend.passTLSClientCert.infos.notAfter`             | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notBefore=true`            | Same as `traefik.frontend.passTLSClientCert.infos.notBefore`            | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.sans=true`                 | Same as `traefik.frontend.passTLSClientCert.infos.sans`                 | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.commonName=true`   | Same as `traefik.frontend.passTLSClientCert.infos.subject.commonName`   | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.country=true`      | Same as `traefik.frontend.passTLSClientCert.infos.subject.country`      | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.locality=true`     | Same as `traefik.frontend.passTLSClientCert.infos.subject.locality`     | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.organization=true` | Same as `traefik.frontend.passTLSClientCert.infos.subject.organization` | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.province=true`     | Same as `traefik.frontend.passTLSClientCert.infos.subject.province`     | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.serialNumber=true` | Same as `traefik.frontend.passTLSClientCert.infos.subject.serialNumber` | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.pem=true`                        | Same as `traefik.frontend.passTLSClientCert.infos.pem`                  | | ||||
| | `traefik.<segment_name>.frontend.passTLSCert=true`                                  | Same as `traefik.frontend.passTLSCert`                                  | | ||||
| | `traefik.<segment_name>.frontend.priority=10`                                       | Same as `traefik.frontend.priority`                                     | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.extractorFunc=EXP`                       | Same as `traefik.frontend.rateLimit.extractorFunc`                      | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.period=6`                 | Same as `traefik.frontend.rateLimit.rateSet.<name>.period`              | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.average=6`                | Same as `traefik.frontend.rateLimit.rateSet.<name>.average`             | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.burst=6`                  | Same as `traefik.frontend.rateLimit.rateSet.<name>.burst`               | | ||||
| | `traefik.<segment_name>.frontend.redirect.entryPoint=https`                         | Same as `traefik.frontend.redirect.entryPoint`                          | | ||||
| | `traefik.<segment_name>.frontend.redirect.regex=^http://localhost/(.*)`             | Same as `traefik.frontend.redirect.regex`                               | | ||||
| | `traefik.<segment_name>.frontend.redirect.replacement=http://mydomain/$1`           | Same as `traefik.frontend.redirect.replacement`                         | | ||||
| | `traefik.<segment_name>.frontend.redirect.permanent=true`                           | Same as `traefik.frontend.redirect.permanent`                           | | ||||
| | `traefik.<segment_name>.frontend.rule=EXP`                                          | Same as `traefik.frontend.rule`                                         | | ||||
| | `traefik.<segment_name>.frontend.whiteList.sourceRange=RANGE`                       | Same as `traefik.frontend.whiteList.sourceRange`                        | | ||||
| | `traefik.<segment_name>.frontend.whiteList.useXForwardedFor=true`                   | Same as `traefik.frontend.whiteList.useXForwardedFor`                   | | ||||
| | Label                                                                                  | Description                                                                | | ||||
| |----------------------------------------------------------------------------------------|----------------------------------------------------------------------------| | ||||
| | `traefik.<segment_name>.backend=BACKEND`                                               | Same as `traefik.backend`                                                  | | ||||
| | `traefik.<segment_name>.domain=DOMAIN`                                                 | Same as `traefik.domain`                                                   | | ||||
| | `traefik.<segment_name>.port=PORT`                                                     | Same as `traefik.port`                                                     | | ||||
| | `traefik.<segment_name>.protocol=http`                                                 | Same as `traefik.protocol`                                                 | | ||||
| | `traefik.<segment_name>.weight=10`                                                     | Same as `traefik.weight`                                                   | | ||||
| | `traefik.<segment_name>.frontend.auth.basic=EXPR`                                      | Same as `traefik.frontend.auth.basic`                                      | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.removeHeader=true`                         | Same as `traefik.frontend.auth.basic.removeHeader`                         | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.users=EXPR`                                | Same as `traefik.frontend.auth.basic.users`                                | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.usersFile=/path/.htpasswd`                 | Same as `traefik.frontend.auth.basic.usersFile`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.removeHeader=true`                        | Same as `traefik.frontend.auth.digest.removeHeader`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.users=EXPR`                               | Same as `traefik.frontend.auth.digest.users`                               | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.usersFile=/path/.htdigest`                | Same as `traefik.frontend.auth.digest.usersFile`                           | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.address=https://example.com`             | Same as `traefik.frontend.auth.forward.address`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.authResponseHeaders=EXPR`                | Same as `traefik.frontend.auth.forward.authResponseHeaders`                | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.ca=/path/ca.pem`                     | Same as `traefik.frontend.auth.forward.tls.ca`                             | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.caOptional=true`                     | Same as `traefik.frontend.auth.forward.tls.caOptional`                     | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.cert=/path/server.pem`               | Same as `traefik.frontend.auth.forward.tls.cert`                           | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.insecureSkipVerify=true`             | Same as `traefik.frontend.auth.forward.tls.insecureSkipVerify`             | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.key=/path/server.key`                | Same as `traefik.frontend.auth.forward.tls.key`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.trustForwardHeader=true`                 | Same as `traefik.frontend.auth.forward.trustForwardHeader`                 | | ||||
| | `traefik.<segment_name>.frontend.auth.headerField=X-WebAuth-User`                      | Same as `traefik.frontend.auth.headerField`                                | | ||||
| | `traefik.<segment_name>.frontend.auth.removeHeader=true`                               | Same as `traefik.frontend.auth.removeHeader`                               | | ||||
| | `traefik.<segment_name>.frontend.entryPoints=https`                                    | Same as `traefik.frontend.entryPoints`                                     | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.backend=NAME`                           | Same as `traefik.frontend.errors.<name>.backend`                           | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.query=PATH`                             | Same as `traefik.frontend.errors.<name>.query`                             | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.status=RANGE`                           | Same as `traefik.frontend.errors.<name>.status`                            | | ||||
| | `traefik.<segment_name>.frontend.passHostHeader=true`                                  | Same as `traefik.frontend.passHostHeader`                                  | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.commonName=true`       | Same as `traefik.frontend.passTLSClientCert.infos.issuer.commonName`       | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.country=true`          | Same as `traefik.frontend.passTLSClientCert.infos.issuer.country`          | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.domainComponent=true`  | Same as `traefik.frontend.passTLSClientCert.infos.issuer.domainComponent`  | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.locality=true`         | Same as `traefik.frontend.passTLSClientCert.infos.issuer.locality`         | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.organization=true`     | Same as `traefik.frontend.passTLSClientCert.infos.issuer.organization`     | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.province=true`         | Same as `traefik.frontend.passTLSClientCert.infos.issuer.province`         | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.serialNumber=true`     | Same as `traefik.frontend.passTLSClientCert.infos.issuer.serialNumber`     | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notAfter=true`                | Same as `traefik.frontend.passTLSClientCert.infos.notAfter`                | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notBefore=true`               | Same as `traefik.frontend.passTLSClientCert.infos.notBefore`               | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.sans=true`                    | Same as `traefik.frontend.passTLSClientCert.infos.sans`                    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.commonName=true`      | Same as `traefik.frontend.passTLSClientCert.infos.subject.commonName`      | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.country=true`         | Same as `traefik.frontend.passTLSClientCert.infos.subject.country`         | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.domainComponent=true` | Same as `traefik.frontend.passTLSClientCert.infos.subject.domainComponent` | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.locality=true`        | Same as `traefik.frontend.passTLSClientCert.infos.subject.locality`        | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.organization=true`    | Same as `traefik.frontend.passTLSClientCert.infos.subject.organization`    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.province=true`        | Same as `traefik.frontend.passTLSClientCert.infos.subject.province`        | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.serialNumber=true`    | Same as `traefik.frontend.passTLSClientCert.infos.subject.serialNumber`    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.pem=true`                           | Same as `traefik.frontend.passTLSClientCert.infos.pem`                     | | ||||
| | `traefik.<segment_name>.frontend.passTLSCert=true`                                     | Same as `traefik.frontend.passTLSCert`                                     | | ||||
| | `traefik.<segment_name>.frontend.priority=10`                                          | Same as `traefik.frontend.priority`                                        | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.extractorFunc=EXP`                          | Same as `traefik.frontend.rateLimit.extractorFunc`                         | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.period=6`                    | Same as `traefik.frontend.rateLimit.rateSet.<name>.period`                 | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.average=6`                   | Same as `traefik.frontend.rateLimit.rateSet.<name>.average`                | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.burst=6`                     | Same as `traefik.frontend.rateLimit.rateSet.<name>.burst`                  | | ||||
| | `traefik.<segment_name>.frontend.redirect.entryPoint=https`                            | Same as `traefik.frontend.redirect.entryPoint`                             | | ||||
| | `traefik.<segment_name>.frontend.redirect.regex=^http://localhost/(.*)`                | Same as `traefik.frontend.redirect.regex`                                  | | ||||
| | `traefik.<segment_name>.frontend.redirect.replacement=http://mydomain/$1`              | Same as `traefik.frontend.redirect.replacement`                            | | ||||
| | `traefik.<segment_name>.frontend.redirect.permanent=true`                              | Same as `traefik.frontend.redirect.permanent`                              | | ||||
| | `traefik.<segment_name>.frontend.rule=EXP`                                             | Same as `traefik.frontend.rule`                                            | | ||||
| | `traefik.<segment_name>.frontend.whiteList.sourceRange=RANGE`                          | Same as `traefik.frontend.whiteList.sourceRange`                           | | ||||
| | `traefik.<segment_name>.frontend.whiteList.useXForwardedFor=true`                      | Same as `traefik.frontend.whiteList.useXForwardedFor`                      | | ||||
|  | ||||
| #### Custom Headers | ||||
|  | ||||
|   | ||||
| @@ -64,16 +64,21 @@ Traefik can be configured with a file. | ||||
|       "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", | ||||
|     ] | ||||
|     [frontends.frontend1.passTLSClientCert] | ||||
|         # Pass the escaped pem in a `X-Forwarded-Ssl-Client-Cert` header | ||||
|         pem = true | ||||
|         # Pass the escaped client cert infos selected below in a `X-Forwarded-Ssl-Client-Cert-Infos` header | ||||
|         # The unescaped header is like `Subject="C=%s,ST=%s,L=%s,O=%s,CN=%s",NB=%d,NA=%d,SAN=%s` | ||||
|         # It there is more than one certificates, their are separated by a `;` | ||||
|         [frontends.frontend-server.passTLSClientCert.infos] | ||||
|         [frontends.frontend1.passTLSClientCert.infos] | ||||
|             notBefore = true | ||||
|             notAfter = true | ||||
|             [frontends.frontend-server.passTLSClientCert.infos.subject] | ||||
|             [frontends.frontend1.passTLSClientCert.infos.subject] | ||||
|                 country = true | ||||
|                 domainComponent = true | ||||
|                 province = true | ||||
|                 locality = true | ||||
|                 organization = true | ||||
|                 commonName = true | ||||
|                 serialNumber = true | ||||
|             [frontends.frontend1.passTLSClientCert.infos.issuer] | ||||
|                 country = true | ||||
|                 domainComponent = true | ||||
|                 province = true | ||||
|                 locality = true | ||||
|                 organization = true | ||||
|   | ||||
| @@ -73,6 +73,14 @@ See also [Kubernetes user guide](/user-guide/kubernetes). | ||||
| # | ||||
| # enablePassTLSCert = true | ||||
|  | ||||
| # Throttle how frequently we refresh our configuration from Ingresses when there | ||||
| # are frequent changes. | ||||
| # | ||||
| # Optional | ||||
| # Default: 0 (no throttling) | ||||
| # | ||||
| # throttleDuration = 10s | ||||
|  | ||||
| # Override default configuration template. | ||||
| # | ||||
| # Optional | ||||
| @@ -128,10 +136,11 @@ This will give more flexibility in cloud/dynamic environments. | ||||
| Traefik automatically requests endpoint information based on the service provided in the ingress spec. | ||||
| Although traefik will connect directly to the endpoints (pods), it still checks the service port to see if TLS communication is required. | ||||
|  | ||||
| There are 2 ways to configure Traefik to use https to communicate with backend pods: | ||||
| There are 3 ways to configure Traefik to use https to communicate with backend pods: | ||||
|  | ||||
| 1. If the service port defined in the ingress spec is 443 (note that you can still use `targetPort` to use a different port on your pod). | ||||
| 2. If the service port defined in the ingress spec has a name that starts with `https` (such as `https-api`, `https-web` or just `https`). | ||||
| 3. If the ingress spec includes the annotation `ingress.kubernetes.io/protocol: https`. | ||||
|  | ||||
| If either of those configuration options exist, then the backend communication protocol is assumed to be TLS, and will connect via TLS automatically. | ||||
|  | ||||
| @@ -166,7 +175,7 @@ The following general annotations are applicable on the Ingress object: | ||||
| | `traefik.ingress.kubernetes.io/service-weights: <YML>`                          | Set ingress backend weights specified as percentage or decimal numbers in YAML. (6)                                                                                                        | | ||||
| | `traefik.ingress.kubernetes.io/whitelist-source-range: "1.2.3.0/24, fe80::/16"` | A comma-separated list of IP ranges permitted for access (7).                                                                                                                              | | ||||
| | `ingress.kubernetes.io/whitelist-x-forwarded-for: "true"`                       | Use `X-Forwarded-For` header as valid source of IP for the white list.                                                                                                                     | | ||||
| | `ingress.kubernetes.io/protocol: <NAME>`                                        | Set the protocol Traefik will use to communicate with pods.                                                                                                                                | | ||||
| | `ingress.kubernetes.io/protocol:<NAME>`                                | Set the protocol Traefik will use to communicate with pods. Acceptable protocols: http,https,h2c                                                                                                                        | | ||||
|  | ||||
| <1> `traefik.ingress.kubernetes.io/app-root`: | ||||
| Non-root paths will not be affected by this annotation and handled normally. | ||||
| @@ -209,10 +218,14 @@ infos: | ||||
|     serialnumber: true | ||||
| ``` | ||||
|  | ||||
| If `pem` is set, it will add a `X-Forwarded-Tls-Client-Cert` header that contains the escaped pem as value.   | ||||
| If `pem` is set, it will add a `X-Forwarded-Tls-Client-Cert` header that contains the escaped pem as value. | ||||
| If at least one flag of the `infos` part is set, it will add a `X-Forwarded-Tls-Client-Cert-Infos` header that contains an escaped string composed of the client certificate data selected by the infos flags. | ||||
| This infos part is composed like the following example (not escaped): | ||||
| ```Subject="C=FR,ST=SomeState,L=Lyon,O=Cheese,CN=*.cheese.org",NB=1531900816,NA=1563436816,SAN=*.cheese.org,*.cheese.net,cheese.in,test@cheese.org,test@cheese.net,10.0.1.0,10.0.1.2``` | ||||
| ``` | ||||
| Subject="C=FR,ST=SomeState,L=Lyon,O=Cheese,CN=*.cheese.org",NB=1531900816,NA=1563436816,SAN=*.cheese.org,*.cheese.net,cheese.in,test@cheese.org,test@cheese.net,10.0.1.0,10.0.1.2 | ||||
| ``` | ||||
|  | ||||
| Note these options work only with certificates issued by CAs included in the applicable [EntryPoint ClientCA section](/configuration/entrypoints/#tls-mutual-authentication); certificates from other CAs are not parsed or passed through as-is. | ||||
|  | ||||
| <4> `traefik.ingress.kubernetes.io/rate-limit` example: | ||||
|  | ||||
| @@ -230,7 +243,7 @@ rateset: | ||||
| ``` | ||||
|  | ||||
| <5> `traefik.ingress.kubernetes.io/rule-type` | ||||
| Note: `ReplacePath` is deprecated in this annotation, use the `traefik.ingress.kubernetes.io/request-modifier` annotation instead. Default: `PathPrefix`.  | ||||
| Note: `ReplacePath` is deprecated in this annotation, use the `traefik.ingress.kubernetes.io/request-modifier` annotation instead. Default: `PathPrefix`. | ||||
|  | ||||
| <6> `traefik.ingress.kubernetes.io/service-weights`: | ||||
| Service weights enable to split traffic across multiple backing services in a fine-grained manner. | ||||
| @@ -316,7 +329,7 @@ The following security annotations are applicable on the Ingress object: | ||||
| | `ingress.kubernetes.io/custom-browser-xss-value: VALUE`   | Set custom value for X-XSS-Protection header. This overrides the BrowserXssFilter option.                                                                                                           | | ||||
| | `ingress.kubernetes.io/custom-frame-options-value: VALUE` | Overrides the `X-Frame-Options` header with the custom value.                                                                                                                                       | | ||||
| | `ingress.kubernetes.io/force-hsts: "false"`               | Adds the STS  header to non-SSL requests.                                                                                                                                                           | | ||||
| | `ingress.kubernetes.io/frame-deny: "false"`               | Adds the `X-Frame-Options` header with the value of `DENY`.                                                                                                                                         | | ||||
| | `ingress.kubernetes.io/frame-deny: "true"`                | Adds the `X-Frame-Options` header with the value of `DENY`.                                                                                                                                         | | ||||
| | `ingress.kubernetes.io/hsts-max-age: "315360000"`         | Sets the max-age of the HSTS header.                                                                                                                                                                | | ||||
| | `ingress.kubernetes.io/hsts-include-subdomains: "true"`   | Adds the IncludeSubdomains section of the STS  header.                                                                                                                                              | | ||||
| | `ingress.kubernetes.io/hsts-preload: "true"`              | Adds the preload flag to the HSTS  header.                                                                                                                                                          | | ||||
|   | ||||
| @@ -193,79 +193,87 @@ They may be specified on one of two levels: Application or service. | ||||
|  | ||||
| The following labels can be defined on Marathon applications. They adjust the behavior for the entire application. | ||||
|  | ||||
| | Label                                                               | Description                                                                                                                                                                                                                   | | ||||
| |---------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `traefik.domain`                                                    | Sets the default base domain used for the frontend rules.                                                                                                                                                                          | | ||||
| | `traefik.enable=false`                                              | Disables this container in Traefik.                                                                                                                                                                                            | | ||||
| | `traefik.port=80`                                                   | Registers this port. Useful when the container exposes multiples ports.                                                                                                                                                       | | ||||
| | `traefik.portIndex=1`                                               | Registers port by index in the application's ports array. Useful when the application exposes multiple ports.                                                                                                                 | | ||||
| | `traefik.protocol=https`                                            | Overrides the default `http` protocol.                                                                                                                                                                                        | | ||||
| | `traefik.weight=10`                                                 | Assigns this weight to the container.                                                                                                                                                                                         | | ||||
| | `traefik.backend=foo`                                               | Gives the name `foo` to the generated backend for this container.                                                                                                                                                             | | ||||
| | `traefik.backend.buffering.maxRequestBodyBytes=0`                   | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.maxResponseBodyBytes=0`                  | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memRequestBodyBytes=0`                   | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memResponseBodyBytes=0`                  | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.retryExpression=EXPR`                    | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.circuitbreaker.expression=EXPR`                    | Creates a [circuit breaker](/basics/#backends) to be used against the backend                                                                                                                                                 | | ||||
| | `traefik.backend.responseForwarding.flushInterval=10ms`             | Defines the interval between two flushes when forwarding response from backend to client.                                                                                                                                     | | ||||
| | `traefik.backend.healthcheck.path=/health`                          | Enables health check for the backend, hitting the container at `path`.                                                                                                                                                        | | ||||
| | `traefik.backend.healthcheck.interval=1s`                           | Defines the health check interval. (Default: 30s)                                                                                                                                                                             | | ||||
| | `traefik.backend.healthcheck.port=8080`                             | Sets a different port for the health check.                                                                                                                                                                                   | | ||||
| | `traefik.backend.healthcheck.scheme=http`                           | Overrides the server URL scheme.                                                                                                                                                                                              | | ||||
| | `traefik.backend.healthcheck.hostname=foobar.com`                   | Defines the health check hostname.                                                                                                                                                                                            | | ||||
| | `traefik.backend.healthcheck.headers=EXPR`                          | Defines the health check request headers <br>Format:  <code>HEADER:value||HEADER2:value2</code>                                                                                                                     | | ||||
| | `traefik.backend.loadbalancer.method=drr`                           | Overrides the default `wrr` load balancer algorithm                                                                                                                                                                           | | ||||
| | `traefik.backend.loadbalancer.stickiness=true`                      | Enables backend sticky sessions                                                                                                                                                                                               | | ||||
| | `traefik.backend.loadbalancer.stickiness.cookieName=NAME`           | Sets the cookie name manually for sticky sessions                                                                                                                                                                             | | ||||
| | `traefik.backend.loadbalancer.sticky=true`                          | Enables backend sticky sessions (DEPRECATED)                                                                                                                                                                                  | | ||||
| | `traefik.backend.maxconn.amount=10`                                 | Sets a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect.                                                                                                      | | ||||
| | `traefik.backend.maxconn.extractorfunc=client.ip`                   | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.<br>Must be used in conjunction with the above label to take effect.                                        | | ||||
| | `traefik.frontend.auth.basic=EXPR`                                  | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED).                                                                                                                                 | | ||||
| | `traefik.frontend.auth.basic.removeHeader=true`                     | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.basic.users=EXPR`                            | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash`.                                                                                                                                              | | ||||
| | `traefik.frontend.auth.basic.usersFile=/path/.htpasswd`             | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                         | | ||||
| | `traefik.frontend.auth.digest.removeHeader=true`                    | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.digest.users=EXPR`                           | Sets digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`.                                                                                                                                 | | ||||
| | `traefik.frontend.auth.digest.usersFile=/path/.htdigest`            | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                        | | ||||
| | `traefik.frontend.auth.forward.address=https://example.com`         | Sets the URL of the authentication server.                                                                                                                                                                                    | | ||||
| | `traefik.frontend.auth.forward.authResponseHeaders=EXPR`            | Sets the forward authentication authResponseHeaders in CSV format: `X-Auth-User,X-Auth-Header`                                                                                                                                | | ||||
| | `traefik.frontend.auth.forward.tls.ca=/path/ca.pem`                 | Sets the Certificate Authority (CA) for the TLS connection with the authentication server.                                                                                                                                    | | ||||
| | `traefik.frontend.auth.forward.tls.caOptional=true`                 | Checks the certificates if present but do not force to be signed by a specified Certificate Authority (CA).                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.cert=/path/server.pem`           | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.insecureSkipVerify=true`         | If set to true invalid SSL certificates are accepted.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.forward.tls.key=/path/server.key`            | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.trustForwardHeader=true`             | Trusts X-Forwarded-* headers.                                                                                                                                                                                                 | | ||||
| | `traefik.frontend.auth.headerField=X-WebAuth-User`                  | Sets the header used to pass the authenticated user to the application.                                                                                                                                                       | | ||||
| | `traefik.frontend.auth.removeHeader=true`                           | If set to true, removes the Authorization header.                                                                                                                                                                             | | ||||
| | `traefik.frontend.entryPoints=http,https`                           | Assigns this frontend to entry points `http` and `https`.<br>Overrides `defaultEntryPoints`                                                                                                                                   | | ||||
| | `traefik.frontend.errors.<name>.backend=NAME`                       | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.errors.<name>.query=PATH`                         | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.errors.<name>.status=RANGE`                       | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.passHostHeader=true`                              | Forwards client `Host` header to the backend.                                                                                                                                                                                 | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notAfter=true`            | Add the noAfter field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                            | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notBefore=true`           | Add the noBefore field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                           | | ||||
| | `traefik.frontend.passTLSClientCert.infos.sans=true`                | Add the sans field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.commonName=true`  | Add the subject.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                 | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.country=true`     | Add the subject.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.locality=true`    | Add the subject.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.organization=true`| Add the subject.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.province=true`    | Add the subject.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.serialNumber=true`| Add the subject.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.pem=true`                       | Pass the escaped pem in the `X-Forwarded-Ssl-Client-Cert` header.                                                                                                                                                             | | ||||
| | `traefik.frontend.passTLSCert=true`                                 | Forwards TLS Client certificates to the backend.                                                                                                                                                                              | | ||||
| | `traefik.frontend.priority=10`                                      | Overrides default frontend priority                                                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.extractorFunc=EXP`                      | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.period=6`                | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.average=6`               | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.burst=6`                 | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.redirect.entryPoint=https`                        | Enables Redirect to another entryPoint to this frontend (e.g. HTTPS)                                                                                                                                                          | | ||||
| | `traefik.frontend.redirect.regex=^http://localhost/(.*)`            | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.replacement`.                                                                                                                       | | ||||
| | `traefik.frontend.redirect.replacement=http://mydomain/$1`          | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.regex`.                                                                                                                             | | ||||
| | `traefik.frontend.redirect.permanent=true`                          | Returns 301 instead of 302.                                                                                                                                                                                                   | | ||||
| | `traefik.frontend.rule=EXPR`                                        | Overrides the default frontend rule. Default: `Host:{sub_domain}.{domain}`.                                                                                                                                                   | | ||||
| | `traefik.frontend.whiteList.sourceRange=RANGE`                      | Sets a list of IP-Ranges which are allowed to access.<br>An unset or empty list allows all Source-IPs to access. If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. | | ||||
| | `traefik.frontend.whiteList.useXForwardedFor=true`                  | Uses `X-Forwarded-For` header as valid source of IP for the white list.                                                                                                                                                       | | ||||
| | Label                                                                   | Description                                                                                                                                                                                                                   | | ||||
| |-------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `traefik.domain`                                                        | Sets the default base domain used for the frontend rules.                                                                                                                                                                     | | ||||
| | `traefik.enable=false`                                                  | Disables this container in Traefik.                                                                                                                                                                                           | | ||||
| | `traefik.port=80`                                                       | Registers this port. Useful when the container exposes multiples ports.                                                                                                                                                       | | ||||
| | `traefik.portIndex=1`                                                   | Registers port by index in the application's ports array. Useful when the application exposes multiple ports.                                                                                                                 | | ||||
| | `traefik.protocol=https`                                                | Overrides the default `http` protocol.                                                                                                                                                                                        | | ||||
| | `traefik.weight=10`                                                     | Assigns this weight to the container.                                                                                                                                                                                         | | ||||
| | `traefik.backend=foo`                                                   | Overrides the application name by `foo` in the generated name of the backend.                                                                                                                                                 | | ||||
| | `traefik.backend.buffering.maxRequestBodyBytes=0`                       | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.maxResponseBodyBytes=0`                      | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memRequestBodyBytes=0`                       | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memResponseBodyBytes=0`                      | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.retryExpression=EXPR`                        | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.circuitbreaker.expression=EXPR`                        | Creates a [circuit breaker](/basics/#backends) to be used against the backend                                                                                                                                                 | | ||||
| | `traefik.backend.responseForwarding.flushInterval=10ms`                 | Defines the interval between two flushes when forwarding response from backend to client.                                                                                                                                     | | ||||
| | `traefik.backend.healthcheck.path=/health`                              | Enables health check for the backend, hitting the container at `path`.                                                                                                                                                        | | ||||
| | `traefik.backend.healthcheck.interval=1s`                               | Defines the health check interval. (Default: 30s)                                                                                                                                                                             | | ||||
| | `traefik.backend.healthcheck.port=8080`                                 | Sets a different port for the health check.                                                                                                                                                                                   | | ||||
| | `traefik.backend.healthcheck.scheme=http`                               | Overrides the server URL scheme.                                                                                                                                                                                              | | ||||
| | `traefik.backend.healthcheck.hostname=foobar.com`                       | Defines the health check hostname.                                                                                                                                                                                            | | ||||
| | `traefik.backend.healthcheck.headers=EXPR`                              | Defines the health check request headers <br>Format:  <code>HEADER:value||HEADER2:value2</code>                                                                                                                     | | ||||
| | `traefik.backend.loadbalancer.method=drr`                               | Overrides the default `wrr` load balancer algorithm                                                                                                                                                                           | | ||||
| | `traefik.backend.loadbalancer.stickiness=true`                          | Enables backend sticky sessions                                                                                                                                                                                               | | ||||
| | `traefik.backend.loadbalancer.stickiness.cookieName=NAME`               | Sets the cookie name manually for sticky sessions                                                                                                                                                                             | | ||||
| | `traefik.backend.loadbalancer.sticky=true`                              | Enables backend sticky sessions (DEPRECATED)                                                                                                                                                                                  | | ||||
| | `traefik.backend.maxconn.amount=10`                                     | Sets a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect.                                                                                                      | | ||||
| | `traefik.backend.maxconn.extractorfunc=client.ip`                       | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.<br>Must be used in conjunction with the above label to take effect.                                        | | ||||
| | `traefik.frontend.auth.basic=EXPR`                                      | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED).                                                                                                                                 | | ||||
| | `traefik.frontend.auth.basic.removeHeader=true`                         | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.basic.users=EXPR`                                | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash`.                                                                                                                                              | | ||||
| | `traefik.frontend.auth.basic.usersFile=/path/.htpasswd`                 | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                         | | ||||
| | `traefik.frontend.auth.digest.removeHeader=true`                        | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.digest.users=EXPR`                               | Sets digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`.                                                                                                                                 | | ||||
| | `traefik.frontend.auth.digest.usersFile=/path/.htdigest`                | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                        | | ||||
| | `traefik.frontend.auth.forward.address=https://example.com`             | Sets the URL of the authentication server.                                                                                                                                                                                    | | ||||
| | `traefik.frontend.auth.forward.authResponseHeaders=EXPR`                | Sets the forward authentication authResponseHeaders in CSV format: `X-Auth-User,X-Auth-Header`                                                                                                                                | | ||||
| | `traefik.frontend.auth.forward.tls.ca=/path/ca.pem`                     | Sets the Certificate Authority (CA) for the TLS connection with the authentication server.                                                                                                                                    | | ||||
| | `traefik.frontend.auth.forward.tls.caOptional=true`                     | Checks the certificates if present but do not force to be signed by a specified Certificate Authority (CA).                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.cert=/path/server.pem`               | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.insecureSkipVerify=true`             | If set to true invalid SSL certificates are accepted.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.forward.tls.key=/path/server.key`                | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.trustForwardHeader=true`                 | Trusts X-Forwarded-* headers.                                                                                                                                                                                                 | | ||||
| | `traefik.frontend.auth.headerField=X-WebAuth-User`                      | Sets the header used to pass the authenticated user to the application.                                                                                                                                                       | | ||||
| | `traefik.frontend.auth.removeHeader=true`                               | If set to true, removes the Authorization header.                                                                                                                                                                             | | ||||
| | `traefik.frontend.entryPoints=http,https`                               | Assigns this frontend to entry points `http` and `https`.<br>Overrides `defaultEntryPoints`                                                                                                                                   | | ||||
| | `traefik.frontend.errors.<name>.backend=NAME`                           | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.errors.<name>.query=PATH`                             | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.errors.<name>.status=RANGE`                           | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.passHostHeader=true`                                  | Forwards client `Host` header to the backend.                                                                                                                                                                                 | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.commonName=true`       | Add the issuer.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.country=true`          | Add the issuer.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                     | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.domainComponent=true`  | Add the issuer.domainComponent field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                             | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.locality=true`         | Add the issuer.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.organization=true`     | Add the issuer.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.province=true`         | Add the issuer.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.serialNumber=true`     | Add the issuer.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notAfter=true`                | Add the noAfter field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                            | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notBefore=true`               | Add the noBefore field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                           | | ||||
| | `traefik.frontend.passTLSClientCert.infos.sans=true`                    | Add the sans field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.commonName=true`      | Add the subject.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                 | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.country=true`         | Add the subject.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.domainComponent=true` | Add the subject.domainComponent field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                            | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.locality=true`        | Add the subject.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.organization=true`    | Add the subject.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.province=true`        | Add the subject.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.serialNumber=true`    | Add the subject.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.pem=true`                           | Pass the escaped pem in the `X-Forwarded-Ssl-Client-Cert` header.                                                                                                                                                             | | ||||
| | `traefik.frontend.passTLSCert=true`                                     | Forwards TLS Client certificates to the backend.                                                                                                                                                                              | | ||||
| | `traefik.frontend.priority=10`                                          | Overrides default frontend priority                                                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.extractorFunc=EXP`                          | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.period=6`                    | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.average=6`                   | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.burst=6`                     | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.redirect.entryPoint=https`                            | Enables Redirect to another entryPoint to this frontend (e.g. HTTPS)                                                                                                                                                          | | ||||
| | `traefik.frontend.redirect.regex=^http://localhost/(.*)`                | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.replacement`.                                                                                                                       | | ||||
| | `traefik.frontend.redirect.replacement=http://mydomain/$1`              | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.regex`.                                                                                                                             | | ||||
| | `traefik.frontend.redirect.permanent=true`                              | Returns 301 instead of 302.                                                                                                                                                                                                   | | ||||
| | `traefik.frontend.rule=EXPR`                                            | Overrides the default frontend rule. Default: `Host:{sub_domain}.{domain}`.                                                                                                                                                   | | ||||
| | `traefik.frontend.whiteList.sourceRange=RANGE`                          | Sets a list of IP-Ranges which are allowed to access.<br>An unset or empty list allows all Source-IPs to access. If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. | | ||||
| | `traefik.frontend.whiteList.useXForwardedFor=true`                      | Uses `X-Forwarded-For` header as valid source of IP for the white list.                                                                                                                                                       | | ||||
|  | ||||
| #### Custom Headers | ||||
|  | ||||
| @@ -308,59 +316,67 @@ You can define as many segments as ports exposed in an application. | ||||
|  | ||||
| Segment labels override the default behavior. | ||||
|  | ||||
| | Label                                                                              | Description                                                            | | ||||
| |------------------------------------------------------------------------------------|------------------------------------------------------------------------| | ||||
| | `traefik.<segment_name>.backend=BACKEND`                                           | Same as `traefik.backend`                                              | | ||||
| | `traefik.<segment_name>.domain=DOMAIN`                                             | Same as `traefik.domain`                                               | | ||||
| | `traefik.<segment_name>.portIndex=1`                                               | Same as `traefik.portIndex`                                            | | ||||
| | `traefik.<segment_name>.port=PORT`                                                 | Same as `traefik.port`                                                 | | ||||
| | `traefik.<segment_name>.protocol=http`                                             | Same as `traefik.protocol`                                             | | ||||
| | `traefik.<segment_name>.weight=10`                                                 | Same as `traefik.weight`                                               | | ||||
| | `traefik.<segment_name>.frontend.auth.basic=EXPR`                                  | Same as `traefik.frontend.auth.basic`                                  | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.removeHeader=true`                     | Same as `traefik.frontend.auth.basic.removeHeader`                     | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.users=EXPR`                            | Same as `traefik.frontend.auth.basic.users`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.usersFile=/path/.htpasswd`             | Same as `traefik.frontend.auth.basic.usersFile`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.removeHeader=true`                    | Same as `traefik.frontend.auth.digest.removeHeader`                    | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.users=EXPR`                           | Same as `traefik.frontend.auth.digest.users`                           | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.usersFile=/path/.htdigest`            | Same as `traefik.frontend.auth.digest.usersFile`                       | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.address=https://example.com`         | Same as `traefik.frontend.auth.forward.address`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.authResponseHeaders=EXPR`            | Same as `traefik.frontend.auth.forward.authResponseHeaders`            | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.ca=/path/ca.pem`                 | Same as `traefik.frontend.auth.forward.tls.ca`                         | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.caOptional=true`                 | Same as `traefik.frontend.auth.forward.tls.caOptional`                 | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.cert=/path/server.pem`           | Same as `traefik.frontend.auth.forward.tls.cert`                       | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.insecureSkipVerify=true`         | Same as `traefik.frontend.auth.forward.tls.insecureSkipVerify`         | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.key=/path/server.key`            | Same as `traefik.frontend.auth.forward.tls.key`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.trustForwardHeader=true`             | Same as `traefik.frontend.auth.forward.trustForwardHeader`             | | ||||
| | `traefik.<segment_name>.frontend.auth.headerField=X-WebAuth-User`                  | Same as `traefik.frontend.auth.headerField`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.removeHeader=true`                           | Same as `traefik.frontend.auth.removeHeader`                           | | ||||
| | `traefik.<segment_name>.frontend.entryPoints=https`                                | Same as `traefik.frontend.entryPoints`                                 | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.backend=NAME`                       | Same as `traefik.frontend.errors.<name>.backend`                       | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.query=PATH`                         | Same as `traefik.frontend.errors.<name>.query`                         | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.status=RANGE`                       | Same as `traefik.frontend.errors.<name>.status`                        | | ||||
| | `traefik.<segment_name>.frontend.passHostHeader=true`                              | Same as `traefik.frontend.passHostHeader`                              | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notAfter=true`            | Same as `traefik.frontend.passTLSClientCert.infos.notAfter`            | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notBefore=true`           | Same as `traefik.frontend.passTLSClientCert.infos.notBefore`           | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.sans=true`                | Same as `traefik.frontend.passTLSClientCert.infos.sans`                | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.commonName=true`  | Same as `traefik.frontend.passTLSClientCert.infos.subject.commonName`  | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.country=true`     | Same as `traefik.frontend.passTLSClientCert.infos.subject.country`     | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.locality=true`    | Same as `traefik.frontend.passTLSClientCert.infos.subject.locality`    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.organization=true`| Same as `traefik.frontend.passTLSClientCert.infos.subject.organization`| | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.province=true`    | Same as `traefik.frontend.passTLSClientCert.infos.subject.province`    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.serialNumber=true`| Same as `traefik.frontend.passTLSClientCert.infos.subject.serialNumber`| | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.pem=true`                       | Same as `traefik.frontend.passTLSClientCert.infos.pem`                 | | ||||
| | `traefik.<segment_name>.frontend.passTLSCert=true`                                 | Same as `traefik.frontend.passTLSCert`                                 | | ||||
| | `traefik.<segment_name>.frontend.priority=10`                                      | Same as `traefik.frontend.priority`                                    | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.extractorFunc=EXP`                      | Same as `traefik.frontend.rateLimit.extractorFunc`                     | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.period=6`                | Same as `traefik.frontend.rateLimit.rateSet.<name>.period`             | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.average=6`               | Same as `traefik.frontend.rateLimit.rateSet.<name>.average`            | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.burst=6`                 | Same as `traefik.frontend.rateLimit.rateSet.<name>.burst`              | | ||||
| | `traefik.<segment_name>.frontend.redirect.entryPoint=https`                        | Same as `traefik.frontend.redirect.entryPoint`                         | | ||||
| | `traefik.<segment_name>.frontend.redirect.regex=^http://localhost/(.*)`            | Same as `traefik.frontend.redirect.regex`                              | | ||||
| | `traefik.<segment_name>.frontend.redirect.replacement=http://mydomain/$1`          | Same as `traefik.frontend.redirect.replacement`                        | | ||||
| | `traefik.<segment_name>.frontend.redirect.permanent=true`                          | Same as `traefik.frontend.redirect.permanent`                          | | ||||
| | `traefik.<segment_name>.frontend.rule=EXP`                                         | Same as `traefik.frontend.rule`                                        | | ||||
| | `traefik.<segment_name>.frontend.whiteList.sourceRange=RANGE`                      | Same as `traefik.frontend.whiteList.sourceRange`                       | | ||||
| | `traefik.<segment_name>.frontend.whiteList.useXForwardedFor=true`                  | Same as `traefik.frontend.whiteList.useXForwardedFor`                  | | ||||
| | Label                                                                                  | Description                                                                | | ||||
| |----------------------------------------------------------------------------------------|----------------------------------------------------------------------------| | ||||
| | `traefik.<segment_name>.backend=BACKEND`                                               | Same as `traefik.backend`                                                  | | ||||
| | `traefik.<segment_name>.domain=DOMAIN`                                                 | Same as `traefik.domain`                                                   | | ||||
| | `traefik.<segment_name>.portIndex=1`                                                   | Same as `traefik.portIndex`                                                | | ||||
| | `traefik.<segment_name>.port=PORT`                                                     | Same as `traefik.port`                                                     | | ||||
| | `traefik.<segment_name>.protocol=http`                                                 | Same as `traefik.protocol`                                                 | | ||||
| | `traefik.<segment_name>.weight=10`                                                     | Same as `traefik.weight`                                                   | | ||||
| | `traefik.<segment_name>.frontend.auth.basic=EXPR`                                      | Same as `traefik.frontend.auth.basic`                                      | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.removeHeader=true`                         | Same as `traefik.frontend.auth.basic.removeHeader`                         | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.users=EXPR`                                | Same as `traefik.frontend.auth.basic.users`                                | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.usersFile=/path/.htpasswd`                 | Same as `traefik.frontend.auth.basic.usersFile`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.removeHeader=true`                        | Same as `traefik.frontend.auth.digest.removeHeader`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.users=EXPR`                               | Same as `traefik.frontend.auth.digest.users`                               | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.usersFile=/path/.htdigest`                | Same as `traefik.frontend.auth.digest.usersFile`                           | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.address=https://example.com`             | Same as `traefik.frontend.auth.forward.address`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.authResponseHeaders=EXPR`                | Same as `traefik.frontend.auth.forward.authResponseHeaders`                | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.ca=/path/ca.pem`                     | Same as `traefik.frontend.auth.forward.tls.ca`                             | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.caOptional=true`                     | Same as `traefik.frontend.auth.forward.tls.caOptional`                     | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.cert=/path/server.pem`               | Same as `traefik.frontend.auth.forward.tls.cert`                           | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.insecureSkipVerify=true`             | Same as `traefik.frontend.auth.forward.tls.insecureSkipVerify`             | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.key=/path/server.key`                | Same as `traefik.frontend.auth.forward.tls.key`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.trustForwardHeader=true`                 | Same as `traefik.frontend.auth.forward.trustForwardHeader`                 | | ||||
| | `traefik.<segment_name>.frontend.auth.headerField=X-WebAuth-User`                      | Same as `traefik.frontend.auth.headerField`                                | | ||||
| | `traefik.<segment_name>.frontend.auth.removeHeader=true`                               | Same as `traefik.frontend.auth.removeHeader`                               | | ||||
| | `traefik.<segment_name>.frontend.entryPoints=https`                                    | Same as `traefik.frontend.entryPoints`                                     | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.backend=NAME`                           | Same as `traefik.frontend.errors.<name>.backend`                           | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.query=PATH`                             | Same as `traefik.frontend.errors.<name>.query`                             | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.status=RANGE`                           | Same as `traefik.frontend.errors.<name>.status`                            | | ||||
| | `traefik.<segment_name>.frontend.passHostHeader=true`                                  | Same as `traefik.frontend.passHostHeader`                                  | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.commonName=true`       | Same as `traefik.frontend.passTLSClientCert.infos.issuer.commonName`       | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.domainComponent=true`  | Same as `traefik.frontend.passTLSClientCert.infos.issuer.domainComponent`  | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.country=true`          | Same as `traefik.frontend.passTLSClientCert.infos.issuer.country`          | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.locality=true`         | Same as `traefik.frontend.passTLSClientCert.infos.issuer.locality`         | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.organization=true`     | Same as `traefik.frontend.passTLSClientCert.infos.issuer.organization`     | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.province=true`         | Same as `traefik.frontend.passTLSClientCert.infos.issuer.province`         | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.serialNumber=true`     | Same as `traefik.frontend.passTLSClientCert.infos.issuer.serialNumber`     | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notAfter=true`                | Same as `traefik.frontend.passTLSClientCert.infos.notAfter`                | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notBefore=true`               | Same as `traefik.frontend.passTLSClientCert.infos.notBefore`               | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.sans=true`                    | Same as `traefik.frontend.passTLSClientCert.infos.sans`                    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.commonName=true`      | Same as `traefik.frontend.passTLSClientCert.infos.subject.commonName`      | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.domainComponent=true` | Same as `traefik.frontend.passTLSClientCert.infos.subject.domainComponent` | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.country=true`         | Same as `traefik.frontend.passTLSClientCert.infos.subject.country`         | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.locality=true`        | Same as `traefik.frontend.passTLSClientCert.infos.subject.locality`        | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.organization=true`    | Same as `traefik.frontend.passTLSClientCert.infos.subject.organization`    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.province=true`        | Same as `traefik.frontend.passTLSClientCert.infos.subject.province`        | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.serialNumber=true`    | Same as `traefik.frontend.passTLSClientCert.infos.subject.serialNumber`    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.pem=true`                           | Same as `traefik.frontend.passTLSClientCert.infos.pem`                     | | ||||
| | `traefik.<segment_name>.frontend.passTLSCert=true`                                     | Same as `traefik.frontend.passTLSCert`                                     | | ||||
| | `traefik.<segment_name>.frontend.priority=10`                                          | Same as `traefik.frontend.priority`                                        | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.extractorFunc=EXP`                          | Same as `traefik.frontend.rateLimit.extractorFunc`                         | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.period=6`                    | Same as `traefik.frontend.rateLimit.rateSet.<name>.period`                 | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.average=6`                   | Same as `traefik.frontend.rateLimit.rateSet.<name>.average`                | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.burst=6`                     | Same as `traefik.frontend.rateLimit.rateSet.<name>.burst`                  | | ||||
| | `traefik.<segment_name>.frontend.redirect.entryPoint=https`                            | Same as `traefik.frontend.redirect.entryPoint`                             | | ||||
| | `traefik.<segment_name>.frontend.redirect.regex=^http://localhost/(.*)`                | Same as `traefik.frontend.redirect.regex`                                  | | ||||
| | `traefik.<segment_name>.frontend.redirect.replacement=http://mydomain/$1`              | Same as `traefik.frontend.redirect.replacement`                            | | ||||
| | `traefik.<segment_name>.frontend.redirect.permanent=true`                              | Same as `traefik.frontend.redirect.permanent`                              | | ||||
| | `traefik.<segment_name>.frontend.rule=EXP`                                             | Same as `traefik.frontend.rule`                                            | | ||||
| | `traefik.<segment_name>.frontend.whiteList.sourceRange=RANGE`                          | Same as `traefik.frontend.whiteList.sourceRange`                           | | ||||
| | `traefik.<segment_name>.frontend.whiteList.useXForwardedFor=true`                      | Same as `traefik.frontend.whiteList.useXForwardedFor`                      | | ||||
|  | ||||
| #### Custom Headers | ||||
|  | ||||
|   | ||||
| @@ -106,79 +106,87 @@ domain = "mesos.localhost" | ||||
|  | ||||
| The following labels can be defined on Mesos tasks. They adjust the behavior for the entire application. | ||||
|  | ||||
| | Label                                                               | Description                                                                                                                                                                                                                   | | ||||
| |---------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `traefik.domain`                                                    | Sets the default base domain for the frontend rules.                                                                                                                                                                               | | ||||
| | `traefik.enable=false`                                              | Disables this container in Traefik.                                                                                                                                                                                            | | ||||
| | `traefik.port=80`                                                   | Registers this port. Useful when the application exposes multiple ports.                                                                                                                                                      | | ||||
| | `traefik.portName=web`                                              | Registers port by name in the application's ports array. Useful when the application exposes multiple ports.                                                                                                                  | | ||||
| | `traefik.portIndex=1`                                               | Registers port by index in the application's ports array. Useful when the application exposes multiple ports.                                                                                                                 | | ||||
| | `traefik.protocol=https`                                            | Overrides the default `http` protocol                                                                                                                                                                                         | | ||||
| | `traefik.weight=10`                                                 | Assigns this weight to the container                                                                                                                                                                                          | | ||||
| | `traefik.backend=foo`                                               | Gives the name `foo` to the generated backend for this container.                                                                                                                                                             | | ||||
| | `traefik.backend.buffering.maxRequestBodyBytes=0`                   | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.maxResponseBodyBytes=0`                  | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memRequestBodyBytes=0`                   | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memResponseBodyBytes=0`                  | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.retryExpression=EXPR`                    | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.circuitbreaker.expression=EXPR`                    | Creates a [circuit breaker](/basics/#backends) to be used against the backend                                                                                                                                                 | | ||||
| | `traefik.backend.responseForwarding.flushInterval=10ms`             | Defines the interval between two flushes when forwarding response from backend to client.                                                                                                                                     | | ||||
| | `traefik.backend.healthcheck.path=/health`                          | Enables health check for the backend, hitting the container at `path`.                                                                                                                                                        | | ||||
| | `traefik.backend.healthcheck.interval=1s`                           | Defines the health check interval. (Default: 30s)                                                                                                                                                                             | | ||||
| | `traefik.backend.healthcheck.scheme=http`                           | Overrides the server URL scheme.                                                                                                                                                                                              | | ||||
| | `traefik.backend.healthcheck.port=8080`                             | Sets a different port for the health check.                                                                                                                                                                                   | | ||||
| | `traefik.backend.healthcheck.hostname=foobar.com`                   | Defines the health check hostname.                                                                                                                                                                                            | | ||||
| | `traefik.backend.healthcheck.headers=EXPR`                          | Defines the health check request headers <br>Format:  <code>HEADER:value||HEADER2:value2</code>                                                                                                                     | | ||||
| | `traefik.backend.loadbalancer.method=drr`                           | Overrides the default `wrr` load balancer algorithm                                                                                                                                                                           | | ||||
| | `traefik.backend.loadbalancer.stickiness=true`                      | Enables backend sticky sessions                                                                                                                                                                                               | | ||||
| | `traefik.backend.loadbalancer.stickiness.cookieName=NAME`           | Sets the cookie manually name for sticky sessions                                                                                                                                                                             | | ||||
| | `traefik.backend.maxconn.amount=10`                                 | Sets a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect.                                                                                                      | | ||||
| | `traefik.backend.maxconn.extractorfunc=client.ip`                   | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.<br>Must be used in conjunction with the above label to take effect.                                        | | ||||
| | `traefik.frontend.auth.basic=EXPR`                                  | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED).                                                                                                                                 | | ||||
| | `traefik.frontend.auth.basic.users=EXPR`                            | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash`.                                                                                                                                              | | ||||
| | `traefik.frontend.auth.basic.removeHeader=true`                     | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.basic.usersFile=/path/.htpasswd`             | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                         | | ||||
| | `traefik.frontend.auth.digest.removeHeader=true`                    | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.digest.users=EXPR`                           | Sets digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`.                                                                                                                                 | | ||||
| | `traefik.frontend.auth.digest.usersFile=/path/.htdigest`            | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                        | | ||||
| | `traefik.frontend.auth.forward.address=https://example.com`         | Sets the URL of the authentication server.                                                                                                                                                                                    | | ||||
| | `traefik.frontend.auth.forward.authResponseHeaders=EXPR`            | Sets the forward authentication authResponseHeaders in CSV format: `X-Auth-User,X-Auth-Header`                                                                                                                                | | ||||
| | `traefik.frontend.auth.forward.tls.ca=/path/ca.pem`                 | Sets the Certificate Authority (CA) for the TLS connection with the authentication server.                                                                                                                                    | | ||||
| | `traefik.frontend.auth.forward.tls.caOptional=true`                 | Checks the certificates if present but do not force to be signed by a specified Certificate Authority (CA).                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.cert=/path/server.pem`           | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.insecureSkipVerify=true`         | If set to true invalid SSL certificates are accepted.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.forward.tls.key=/path/server.key`            | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.trustForwardHeader=true`             | Trusts X-Forwarded-* headers.                                                                                                                                                                                                 | | ||||
| | `traefik.frontend.auth.headerField=X-WebAuth-User`                  | Sets the header used to pass the authenticated user to the application.                                                                                                                                                       | | ||||
| | `traefik.frontend.auth.removeHeader=true`                           | If set to true, removes the Authorization header.                                                                                                                                                                             | | ||||
| | `traefik.frontend.entryPoints=http,https`                           | Assigns this frontend to entry points `http` and `https`.<br>Overrides `defaultEntryPoints`                                                                                                                                   | | ||||
| | `traefik.frontend.errors.<name>.backend=NAME`                       | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.errors.<name>.query=PATH`                         | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.errors.<name>.status=RANGE`                       | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.passHostHeader=true`                              | Forwards client `Host` header to the backend.                                                                                                                                                                                 | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notAfter=true`            | Add the noAfter field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                            | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notBefore=true`           | Add the noBefore field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                           | | ||||
| | `traefik.frontend.passTLSClientCert.infos.sans=true`                | Add the sans field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.commonName=true`  | Add the subject.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                 | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.country=true`     | Add the subject.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.locality=true`    | Add the subject.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.organization=true`| Add the subject.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.province=true`    | Add the subject.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.serialNumber=true`| Add the subject.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.pem=true`                       | Pass the escaped pem in the `X-Forwarded-Ssl-Client-Cert` header.                                                                                                                                                             | | ||||
| | `traefik.frontend.passTLSCert=true`                                 | Forwards TLS Client certificates to the backend.                                                                                                                                                                              | | ||||
| | `traefik.frontend.priority=10`                                      | Overrides default frontend priority                                                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.extractorFunc=EXP`                      | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.period=6`                | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.average=6`               | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.burst=6`                 | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.redirect.entryPoint=https`                        | Enables Redirect to another entryPoint to this frontend (e.g. HTTPS)                                                                                                                                                          | | ||||
| | `traefik.frontend.redirect.regex=^http://localhost/(.*)`            | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.replacement`.                                                                                                                       | | ||||
| | `traefik.frontend.redirect.replacement=http://mydomain/$1`          | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.regex`.                                                                                                                             | | ||||
| | `traefik.frontend.redirect.permanent=true`                          | Returns 301 instead of 302.                                                                                                                                                                                                   | | ||||
| | `traefik.frontend.rule=EXPR`                                        | Overrides the default frontend rule. Default: `Host:{discovery_name}.{domain}`.                                                                                                                                               | | ||||
| | `traefik.frontend.whiteList.sourceRange=RANGE`                      | Sets a list of IP-Ranges which are allowed to access.<br>An unset or empty list allows all Source-IPs to access. If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. | | ||||
| | `traefik.frontend.whiteList.useXForwardedFor=true`                  | Uses `X-Forwarded-For` header as valid source of IP for the white list.                                                                                                                                                       | | ||||
| | Label                                                                   | Description                                                                                                                                                                                                                   | | ||||
| |-------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `traefik.domain`                                                        | Sets the default base domain for the frontend rules.                                                                                                                                                                          | | ||||
| | `traefik.enable=false`                                                  | Disables this container in Traefik.                                                                                                                                                                                           | | ||||
| | `traefik.port=80`                                                       | Registers this port. Useful when the application exposes multiple ports.                                                                                                                                                      | | ||||
| | `traefik.portName=web`                                                  | Registers port by name in the application's ports array. Useful when the application exposes multiple ports.                                                                                                                  | | ||||
| | `traefik.portIndex=1`                                                   | Registers port by index in the application's ports array. Useful when the application exposes multiple ports.                                                                                                                 | | ||||
| | `traefik.protocol=https`                                                | Overrides the default `http` protocol                                                                                                                                                                                         | | ||||
| | `traefik.weight=10`                                                     | Assigns this weight to the container                                                                                                                                                                                          | | ||||
| | `traefik.backend=foo`                                                   | Overrides the task name by `foo` in the generated name of the backend.                                                                                                                                                        | | ||||
| | `traefik.backend.buffering.maxRequestBodyBytes=0`                       | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.maxResponseBodyBytes=0`                      | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memRequestBodyBytes=0`                       | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.memResponseBodyBytes=0`                      | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.buffering.retryExpression=EXPR`                        | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                   | | ||||
| | `traefik.backend.circuitbreaker.expression=EXPR`                        | Creates a [circuit breaker](/basics/#backends) to be used against the backend                                                                                                                                                 | | ||||
| | `traefik.backend.responseForwarding.flushInterval=10ms`                 | Defines the interval between two flushes when forwarding response from backend to client.                                                                                                                                     | | ||||
| | `traefik.backend.healthcheck.path=/health`                              | Enables health check for the backend, hitting the container at `path`.                                                                                                                                                        | | ||||
| | `traefik.backend.healthcheck.interval=1s`                               | Defines the health check interval. (Default: 30s)                                                                                                                                                                             | | ||||
| | `traefik.backend.healthcheck.scheme=http`                               | Overrides the server URL scheme.                                                                                                                                                                                              | | ||||
| | `traefik.backend.healthcheck.port=8080`                                 | Sets a different port for the health check.                                                                                                                                                                                   | | ||||
| | `traefik.backend.healthcheck.hostname=foobar.com`                       | Defines the health check hostname.                                                                                                                                                                                            | | ||||
| | `traefik.backend.healthcheck.headers=EXPR`                              | Defines the health check request headers <br>Format:  <code>HEADER:value||HEADER2:value2</code>                                                                                                                     | | ||||
| | `traefik.backend.loadbalancer.method=drr`                               | Overrides the default `wrr` load balancer algorithm                                                                                                                                                                           | | ||||
| | `traefik.backend.loadbalancer.stickiness=true`                          | Enables backend sticky sessions                                                                                                                                                                                               | | ||||
| | `traefik.backend.loadbalancer.stickiness.cookieName=NAME`               | Sets the cookie manually name for sticky sessions                                                                                                                                                                             | | ||||
| | `traefik.backend.maxconn.amount=10`                                     | Sets a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect.                                                                                                      | | ||||
| | `traefik.backend.maxconn.extractorfunc=client.ip`                       | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.<br>Must be used in conjunction with the above label to take effect.                                        | | ||||
| | `traefik.frontend.auth.basic=EXPR`                                      | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED).                                                                                                                                 | | ||||
| | `traefik.frontend.auth.basic.users=EXPR`                                | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash`.                                                                                                                                              | | ||||
| | `traefik.frontend.auth.basic.removeHeader=true`                         | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.basic.usersFile=/path/.htpasswd`                 | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                         | | ||||
| | `traefik.frontend.auth.digest.removeHeader=true`                        | If set to `true`, removes the `Authorization` header.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.digest.users=EXPR`                               | Sets digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`.                                                                                                                                 | | ||||
| | `traefik.frontend.auth.digest.usersFile=/path/.htdigest`                | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                        | | ||||
| | `traefik.frontend.auth.forward.address=https://example.com`             | Sets the URL of the authentication server.                                                                                                                                                                                    | | ||||
| | `traefik.frontend.auth.forward.authResponseHeaders=EXPR`                | Sets the forward authentication authResponseHeaders in CSV format: `X-Auth-User,X-Auth-Header`                                                                                                                                | | ||||
| | `traefik.frontend.auth.forward.tls.ca=/path/ca.pem`                     | Sets the Certificate Authority (CA) for the TLS connection with the authentication server.                                                                                                                                    | | ||||
| | `traefik.frontend.auth.forward.tls.caOptional=true`                     | Checks the certificates if present but do not force to be signed by a specified Certificate Authority (CA).                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.cert=/path/server.pem`               | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.insecureSkipVerify=true`             | If set to true invalid SSL certificates are accepted.                                                                                                                                                                         | | ||||
| | `traefik.frontend.auth.forward.tls.key=/path/server.key`                | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.trustForwardHeader=true`                 | Trusts X-Forwarded-* headers.                                                                                                                                                                                                 | | ||||
| | `traefik.frontend.auth.headerField=X-WebAuth-User`                      | Sets the header used to pass the authenticated user to the application.                                                                                                                                                       | | ||||
| | `traefik.frontend.auth.removeHeader=true`                               | If set to true, removes the Authorization header.                                                                                                                                                                             | | ||||
| | `traefik.frontend.entryPoints=http,https`                               | Assigns this frontend to entry points `http` and `https`.<br>Overrides `defaultEntryPoints`                                                                                                                                   | | ||||
| | `traefik.frontend.errors.<name>.backend=NAME`                           | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.errors.<name>.query=PATH`                             | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.errors.<name>.status=RANGE`                           | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                 | | ||||
| | `traefik.frontend.passHostHeader=true`                                  | Forwards client `Host` header to the backend.                                                                                                                                                                                 | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.commonName=true`       | Add the issuer.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.country=true`          | Add the issuer.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                     | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.domainComponent=true`  | Add the issuer.domainComponent field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                             | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.locality=true`         | Add the issuer.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.organization=true`     | Add the issuer.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.province=true`         | Add the issuer.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.serialNumber=true`     | Add the issuer.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notAfter=true`                | Add the noAfter field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                            | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notBefore=true`               | Add the noBefore field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                           | | ||||
| | `traefik.frontend.passTLSClientCert.infos.sans=true`                    | Add the sans field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.commonName=true`      | Add the subject.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                 | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.country=true`         | Add the subject.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.domainComponent=true` | Add the subject.domainComponent field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                            | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.locality=true`        | Add the subject.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.organization=true`    | Add the subject.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.province=true`        | Add the subject.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.serialNumber=true`    | Add the subject.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.pem=true`                           | Pass the escaped pem in the `X-Forwarded-Ssl-Client-Cert` header.                                                                                                                                                             | | ||||
| | `traefik.frontend.passTLSCert=true`                                     | Forwards TLS Client certificates to the backend.                                                                                                                                                                              | | ||||
| | `traefik.frontend.priority=10`                                          | Overrides default frontend priority                                                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.extractorFunc=EXP`                          | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.period=6`                    | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.average=6`                   | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.burst=6`                     | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                           | | ||||
| | `traefik.frontend.redirect.entryPoint=https`                            | Enables Redirect to another entryPoint to this frontend (e.g. HTTPS)                                                                                                                                                          | | ||||
| | `traefik.frontend.redirect.regex=^http://localhost/(.*)`                | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.replacement`.                                                                                                                       | | ||||
| | `traefik.frontend.redirect.replacement=http://mydomain/$1`              | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.regex`.                                                                                                                             | | ||||
| | `traefik.frontend.redirect.permanent=true`                              | Returns 301 instead of 302.                                                                                                                                                                                                   | | ||||
| | `traefik.frontend.rule=EXPR`                                            | Overrides the default frontend rule. Default: `Host:{discovery_name}.{domain}`.                                                                                                                                               | | ||||
| | `traefik.frontend.whiteList.sourceRange=RANGE`                          | Sets a list of IP-Ranges which are allowed to access.<br>An unset or empty list allows all Source-IPs to access. If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. | | ||||
| | `traefik.frontend.whiteList.useXForwardedFor=true`                      | Uses `X-Forwarded-For` header as valid source of IP for the white list.                                                                                                                                                       | | ||||
|  | ||||
| ### Custom Headers | ||||
|  | ||||
|   | ||||
| @@ -2,6 +2,11 @@ | ||||
|  | ||||
| Traefik can be configured to use Rancher as a provider. | ||||
|  | ||||
| !!! important | ||||
|     This provider is specific to Rancher 1.x. | ||||
|     Rancher 2.x requires Kubernetes and does not have a metadata endpoint of its own for Traefik to query. | ||||
|     As such, Rancher 2.x users should utilize the [Kubernetes provider](./kubernetes.md) directly. | ||||
|  | ||||
| ## Global Configuration | ||||
|  | ||||
| ```toml | ||||
| @@ -138,77 +143,85 @@ secretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | ||||
|  | ||||
| Labels can be used on task containers to override default behavior: | ||||
|  | ||||
| | Label                                                               | Description                                                                                                                                                                                                                      | | ||||
| |---------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `traefik.domain`                                                    | Sets the default base domain for the frontend rules.                                                                                                                                                                             | | ||||
| | `traefik.enable=false`                                              | Disables this container in Traefik.                                                                                                                                                                                              | | ||||
| | `traefik.port=80`                                                   | Registers this port. Useful when the container exposes multiple ports.                                                                                                                                                           | | ||||
| | `traefik.protocol=https`                                            | Overrides the default `http` protocol.                                                                                                                                                                                           | | ||||
| | `traefik.weight=10`                                                 | Assigns this weight to the container.                                                                                                                                                                                            | | ||||
| | `traefik.backend=foo`                                               | Gives the name `foo` to the generated backend for this container.                                                                                                                                                                | | ||||
| | `traefik.backend.buffering.maxRequestBodyBytes=0`                   | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.maxResponseBodyBytes=0`                  | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.memRequestBodyBytes=0`                   | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.memResponseBodyBytes=0`                  | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.retryExpression=EXPR`                    | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.circuitbreaker.expression=EXPR`                    | Creates a [circuit breaker](/basics/#backends) to be used against the backend                                                                                                                                                    | | ||||
| | `traefik.backend.responseForwarding.flushInterval=10ms`             | Defines the interval between two flushes when forwarding response from backend to client.                                                                                                                                        | | ||||
| | `traefik.backend.healthcheck.path=/health`                          | Enables health check for the backend, hitting the container at `path`.                                                                                                                                                           | | ||||
| | `traefik.backend.healthcheck.interval=1s`                           | Defines the health check interval.                                                                                                                                                                                               | | ||||
| | `traefik.backend.healthcheck.port=8080`                             | Sets a different port for the health check.                                                                                                                                                                                      | | ||||
| | `traefik.backend.healthcheck.scheme=http`                           | Overrides the server URL scheme.                                                                                                                                                                                                 | | ||||
| | `traefik.backend.healthcheck.hostname=foobar.com`                   | Defines the health check hostname.                                                                                                                                                                                               | | ||||
| | `traefik.backend.healthcheck.headers=EXPR`                          | Defines the health check request headers <br>Format:  <code>HEADER:value||HEADER2:value2</code>                                                                                                                        | | ||||
| | `traefik.backend.loadbalancer.method=drr`                           | Overrides the default `wrr` load balancer algorithm                                                                                                                                                                              | | ||||
| | `traefik.backend.loadbalancer.stickiness=true`                      | Enables backend sticky sessions                                                                                                                                                                                                  | | ||||
| | `traefik.backend.loadbalancer.stickiness.cookieName=NAME`           | Sets the cookie name manually for sticky sessions                                                                                                                                                                                | | ||||
| | `traefik.backend.loadbalancer.sticky=true`                          | Enables backend sticky sessions (DEPRECATED)                                                                                                                                                                                     | | ||||
| | `traefik.backend.maxconn.amount=10`                                 | Sets a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect.                                                                                                         | | ||||
| | `traefik.backend.maxconn.extractorfunc=client.ip`                   | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.<br>Must be used in conjunction with the above label to take effect.                                           | | ||||
| | `traefik.frontend.auth.basic=EXPR`                                  | Sets the basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED).                                                                                                                                | | ||||
| | `traefik.frontend.auth.basic.removeHeader=true`                     | If set to `true`, removes the `Authorization` header.                                                                                                                                                                            | | ||||
| | `traefik.frontend.auth.basic.users=EXPR`                            | Sets the basic authentication to this frontend in CSV format: `User:Hash,User:Hash` .                                                                                                                                            | | ||||
| | `traefik.frontend.auth.basic.usersFile=/path/.htpasswd`             | Sets the basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                        | | ||||
| | `traefik.frontend.auth.digest.removeHeader=true`                    | If set to `true`, removes the `Authorization` header.                                                                                                                                                                            | | ||||
| | `traefik.frontend.auth.digest.users=EXPR`                           | Sets the digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`.                                                                                                                                | | ||||
| | `traefik.frontend.auth.digest.usersFile=/path/.htdigest`            | Sets the digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                       | | ||||
| | `traefik.frontend.auth.forward.address=https://example.com`         | Sets the URL of the authentication server.                                                                                                                                                                                       | | ||||
| | `traefik.frontend.auth.forward.authResponseHeaders=EXPR`            | Sets the forward authentication authResponseHeaders in CSV format: `X-Auth-User,X-Auth-Header`                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.ca=/path/ca.pem`                 | Sets the Certificate Authority (CA) for the TLS connection with the authentication server.                                                                                                                                       | | ||||
| | `traefik.frontend.auth.forward.tls.caOptional=true`                 | Checks the certificates if present but do not force to be signed by a specified Certificate Authority (CA).                                                                                                                      | | ||||
| | `traefik.frontend.auth.forward.tls.cert=/path/server.pem`           | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                      | | ||||
| | `traefik.frontend.auth.forward.tls.insecureSkipVerify=true`         | If set to true invalid SSL certificates are accepted.                                                                                                                                                                            | | ||||
| | `traefik.frontend.auth.forward.tls.key=/path/server.key`            | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                      | | ||||
| | `traefik.frontend.auth.forward.trustForwardHeader=true`             | Trusts X-Forwarded-* headers.                                                                                                                                                                                                    | | ||||
| | `traefik.frontend.auth.headerField=X-WebAuth-User`                  | Sets the header used to pass the authenticated user to the application.                                                                                                                                                          | | ||||
| | `traefik.frontend.entryPoints=http,https`                           | Assigns this frontend to entry points `http` and `https`.<br>Overrides `defaultEntryPoints`                                                                                                                                      | | ||||
| | `traefik.frontend.errors.<name>.backend=NAME`                       | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                    | | ||||
| | `traefik.frontend.errors.<name>.query=PATH`                         | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                    | | ||||
| | `traefik.frontend.errors.<name>.status=RANGE`                       | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                    | | ||||
| | `traefik.frontend.passHostHeader=true`                              | Forwards client `Host` header to the backend.                                                                                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notAfter=true`            | Add the noAfter field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notBefore=true`           | Add the noBefore field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                              | | ||||
| | `traefik.frontend.passTLSClientCert.infos.sans=true`                | Add the sans field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.commonName=true`  | Add the subject.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.country=true`     | Add the subject.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                       | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.locality=true`    | Add the subject.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                      | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.organization=true`| Add the subject.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.province=true`    | Add the subject.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                      | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.serialNumber=true`| Add the subject.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.pem=true`                       | Pass the escaped pem in the `X-Forwarded-Ssl-Client-Cert` header.                                                                                                                                                                | | ||||
| | `traefik.frontend.passTLSCert=true`                                 | Forwards TLS Client certificates to the backend.                                                                                                                                                                                 | | ||||
| | `traefik.frontend.priority=10`                                      | Overrides default frontend priority                                                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.extractorFunc=EXP`                      | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.period=6`                | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.average=6`               | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.burst=6`                 | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.redirect.entryPoint=https`                        | Enables Redirect to another entryPoint to this frontend (e.g. HTTPS)                                                                                                                                                             | | ||||
| | `traefik.frontend.redirect.regex=^http://localhost/(.*)`            | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.replacement`.                                                                                                                          | | ||||
| | `traefik.frontend.redirect.replacement=http://mydomain/$1`          | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.regex`.                                                                                                                                | | ||||
| | `traefik.frontend.redirect.permanent=true`                          | Returns 301 instead of 302.                                                                                                                                                                                                      | | ||||
| | `traefik.frontend.rule=EXPR`                                        | Overrides the default frontend rule. Default: `Host:{containerName}.{domain}` or `Host:{service}.{project_name}.{domain}` if you are using `docker-compose`.                                                                     | | ||||
| | `traefik.frontend.whiteList.sourceRange=RANGE`                      | Sets a list of IP-Ranges which are allowed to access.<br>An unset or empty list allows all Source-IPs to access.<br>If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. | | ||||
| | `traefik.frontend.whiteList.useXForwardedFor=true`                  | Uses `X-Forwarded-For` header as valid source of IP for the white list.                                                                                                                                                          | | ||||
| | Label                                                                   | Description                                                                                                                                                                                                                      | | ||||
| |-------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `traefik.domain`                                                        | Sets the default base domain for the frontend rules.                                                                                                                                                                             | | ||||
| | `traefik.enable=false`                                                  | Disables this container in Traefik.                                                                                                                                                                                              | | ||||
| | `traefik.port=80`                                                       | Registers this port. Useful when the container exposes multiple ports.                                                                                                                                                           | | ||||
| | `traefik.protocol=https`                                                | Overrides the default `http` protocol.                                                                                                                                                                                           | | ||||
| | `traefik.weight=10`                                                     | Assigns this weight to the container.                                                                                                                                                                                            | | ||||
| | `traefik.backend=foo`                                                   | Overrides the service name by `foo` in the generated name of the backend.                                                                                                                                                        | | ||||
| | `traefik.backend.buffering.maxRequestBodyBytes=0`                       | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.maxResponseBodyBytes=0`                      | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.memRequestBodyBytes=0`                       | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.memResponseBodyBytes=0`                      | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.buffering.retryExpression=EXPR`                        | See [buffering](/configuration/commons/#buffering) section.                                                                                                                                                                      | | ||||
| | `traefik.backend.circuitbreaker.expression=EXPR`                        | Creates a [circuit breaker](/basics/#backends) to be used against the backend                                                                                                                                                    | | ||||
| | `traefik.backend.responseForwarding.flushInterval=10ms`                 | Defines the interval between two flushes when forwarding response from backend to client.                                                                                                                                        | | ||||
| | `traefik.backend.healthcheck.path=/health`                              | Enables health check for the backend, hitting the container at `path`.                                                                                                                                                           | | ||||
| | `traefik.backend.healthcheck.interval=1s`                               | Defines the health check interval.                                                                                                                                                                                               | | ||||
| | `traefik.backend.healthcheck.port=8080`                                 | Sets a different port for the health check.                                                                                                                                                                                      | | ||||
| | `traefik.backend.healthcheck.scheme=http`                               | Overrides the server URL scheme.                                                                                                                                                                                                 | | ||||
| | `traefik.backend.healthcheck.hostname=foobar.com`                       | Defines the health check hostname.                                                                                                                                                                                               | | ||||
| | `traefik.backend.healthcheck.headers=EXPR`                              | Defines the health check request headers <br>Format:  <code>HEADER:value||HEADER2:value2</code>                                                                                                                        | | ||||
| | `traefik.backend.loadbalancer.method=drr`                               | Overrides the default `wrr` load balancer algorithm                                                                                                                                                                              | | ||||
| | `traefik.backend.loadbalancer.stickiness=true`                          | Enables backend sticky sessions                                                                                                                                                                                                  | | ||||
| | `traefik.backend.loadbalancer.stickiness.cookieName=NAME`               | Sets the cookie name manually for sticky sessions                                                                                                                                                                                | | ||||
| | `traefik.backend.loadbalancer.sticky=true`                              | Enables backend sticky sessions (DEPRECATED)                                                                                                                                                                                     | | ||||
| | `traefik.backend.maxconn.amount=10`                                     | Sets a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect.                                                                                                         | | ||||
| | `traefik.backend.maxconn.extractorfunc=client.ip`                       | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.<br>Must be used in conjunction with the above label to take effect.                                           | | ||||
| | `traefik.frontend.auth.basic=EXPR`                                      | Sets the basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED).                                                                                                                                | | ||||
| | `traefik.frontend.auth.basic.removeHeader=true`                         | If set to `true`, removes the `Authorization` header.                                                                                                                                                                            | | ||||
| | `traefik.frontend.auth.basic.users=EXPR`                                | Sets the basic authentication to this frontend in CSV format: `User:Hash,User:Hash` .                                                                                                                                            | | ||||
| | `traefik.frontend.auth.basic.usersFile=/path/.htpasswd`                 | Sets the basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                        | | ||||
| | `traefik.frontend.auth.digest.removeHeader=true`                        | If set to `true`, removes the `Authorization` header.                                                                                                                                                                            | | ||||
| | `traefik.frontend.auth.digest.users=EXPR`                               | Sets the digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`.                                                                                                                                | | ||||
| | `traefik.frontend.auth.digest.usersFile=/path/.htdigest`                | Sets the digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence.                                                                       | | ||||
| | `traefik.frontend.auth.forward.address=https://example.com`             | Sets the URL of the authentication server.                                                                                                                                                                                       | | ||||
| | `traefik.frontend.auth.forward.authResponseHeaders=EXPR`                | Sets the forward authentication authResponseHeaders in CSV format: `X-Auth-User,X-Auth-Header`                                                                                                                                   | | ||||
| | `traefik.frontend.auth.forward.tls.ca=/path/ca.pem`                     | Sets the Certificate Authority (CA) for the TLS connection with the authentication server.                                                                                                                                       | | ||||
| | `traefik.frontend.auth.forward.tls.caOptional=true`                     | Checks the certificates if present but do not force to be signed by a specified Certificate Authority (CA).                                                                                                                      | | ||||
| | `traefik.frontend.auth.forward.tls.cert=/path/server.pem`               | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                      | | ||||
| | `traefik.frontend.auth.forward.tls.insecureSkipVerify=true`             | If set to true invalid SSL certificates are accepted.                                                                                                                                                                            | | ||||
| | `traefik.frontend.auth.forward.tls.key=/path/server.key`                | Sets the Certificate for the TLS connection with the authentication server.                                                                                                                                                      | | ||||
| | `traefik.frontend.auth.forward.trustForwardHeader=true`                 | Trusts X-Forwarded-* headers.                                                                                                                                                                                                    | | ||||
| | `traefik.frontend.auth.headerField=X-WebAuth-User`                      | Sets the header used to pass the authenticated user to the application.                                                                                                                                                          | | ||||
| | `traefik.frontend.entryPoints=http,https`                               | Assigns this frontend to entry points `http` and `https`.<br>Overrides `defaultEntryPoints`                                                                                                                                      | | ||||
| | `traefik.frontend.errors.<name>.backend=NAME`                           | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                    | | ||||
| | `traefik.frontend.errors.<name>.query=PATH`                             | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                    | | ||||
| | `traefik.frontend.errors.<name>.status=RANGE`                           | See [custom error pages](/configuration/commons/#custom-error-pages) section.                                                                                                                                                    | | ||||
| | `traefik.frontend.passHostHeader=true`                                  | Forwards client `Host` header to the backend.                                                                                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.commonName=true`       | Add the issuer.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                     | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.country=true`          | Add the issuer.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                        | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.domainComponent=true`  | Add the issuer.domainComponent field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.locality=true`         | Add the issuer.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                       | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.organization=true`     | Add the issuer.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.province=true`         | Add the issuer.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                       | | ||||
| | `traefik.frontend.passTLSClientCert.infos.issuer.serialNumber=true`     | Add the issuer.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                   | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notAfter=true`                | Add the noAfter field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.notBefore=true`               | Add the noBefore field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                              | | ||||
| | `traefik.frontend.passTLSClientCert.infos.sans=true`                    | Add the sans field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.commonName=true`      | Add the subject.commonName field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                    | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.country=true`         | Add the subject.country field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                       | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.domainComponent=true` | Add the subject.domainComponent field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                               | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.locality=true`        | Add the subject.locality field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                      | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.organization=true`    | Add the subject.organization field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.province=true`        | Add the subject.province field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                      | | ||||
| | `traefik.frontend.passTLSClientCert.infos.subject.serialNumber=true`    | Add the subject.serialNumber field in a escaped client infos in the `X-Forwarded-Ssl-Client-Cert-Infos` header.                                                                                                                  | | ||||
| | `traefik.frontend.passTLSClientCert.pem=true`                           | Pass the escaped pem in the `X-Forwarded-Ssl-Client-Cert` header.                                                                                                                                                                | | ||||
| | `traefik.frontend.passTLSCert=true`                                     | Forwards TLS Client certificates to the backend.                                                                                                                                                                                 | | ||||
| | `traefik.frontend.priority=10`                                          | Overrides default frontend priority                                                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.extractorFunc=EXP`                          | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.period=6`                    | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.average=6`                   | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.rateLimit.rateSet.<name>.burst=6`                     | See [rate limiting](/configuration/commons/#rate-limiting) section.                                                                                                                                                              | | ||||
| | `traefik.frontend.redirect.entryPoint=https`                            | Enables Redirect to another entryPoint to this frontend (e.g. HTTPS)                                                                                                                                                             | | ||||
| | `traefik.frontend.redirect.regex=^http://localhost/(.*)`                | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.replacement`.                                                                                                                          | | ||||
| | `traefik.frontend.redirect.replacement=http://mydomain/$1`              | Redirects to another URL to this frontend.<br>Must be set with `traefik.frontend.redirect.regex`.                                                                                                                                | | ||||
| | `traefik.frontend.redirect.permanent=true`                              | Returns 301 instead of 302.                                                                                                                                                                                                      | | ||||
| | `traefik.frontend.rule=EXPR`                                            | Overrides the default frontend rule. Default: `Host:{containerName}.{domain}` or `Host:{service}.{project_name}.{domain}` if you are using `docker-compose`.                                                                     | | ||||
| | `traefik.frontend.whiteList.sourceRange=RANGE`                          | Sets a list of IP-Ranges which are allowed to access.<br>An unset or empty list allows all Source-IPs to access.<br>If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. | | ||||
| | `traefik.frontend.whiteList.useXForwardedFor=true`                      | Uses `X-Forwarded-For` header as valid source of IP for the white list.                                                                                                                                                          | | ||||
|  | ||||
| #### Custom Headers | ||||
|  | ||||
| @@ -250,57 +263,65 @@ You can define as many segments as ports exposed in a container. | ||||
|  | ||||
| Segment labels override the default behavior. | ||||
|  | ||||
| | Label                                                                              | Description                                                            | | ||||
| |------------------------------------------------------------------------------------|------------------------------------------------------------------------| | ||||
| | `traefik.<segment_name>.backend=BACKEND`                                           | Same as `traefik.backend`                                              | | ||||
| | `traefik.<segment_name>.domain=DOMAIN`                                             | Same as `traefik.domain`                                               | | ||||
| | `traefik.<segment_name>.port=PORT`                                                 | Same as `traefik.port`                                                 | | ||||
| | `traefik.<segment_name>.protocol=http`                                             | Same as `traefik.protocol`                                             | | ||||
| | `traefik.<segment_name>.weight=10`                                                 | Same as `traefik.weight`                                               | | ||||
| | `traefik.<segment_name>.frontend.auth.basic=EXPR`                                  | Same as `traefik.frontend.auth.basic`                                  | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.removeHeader=true`                     | Same as `traefik.frontend.auth.basic.removeHeader`                     | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.users=EXPR`                            | Same as `traefik.frontend.auth.basic.users`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.usersFile=/path/.htpasswd`             | Same as `traefik.frontend.auth.basic.usersFile`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.removeHeader=true`                    | Same as `traefik.frontend.auth.digest.removeHeader`                    | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.users=EXPR`                           | Same as `traefik.frontend.auth.digest.users`                           | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.usersFile=/path/.htdigest`            | Same as `traefik.frontend.auth.digest.usersFile`                       | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.address=https://example.com`         | Same as `traefik.frontend.auth.forward.address`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.authResponseHeaders=EXPR`            | Same as `traefik.frontend.auth.forward.authResponseHeaders`            | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.ca=/path/ca.pem`                 | Same as `traefik.frontend.auth.forward.tls.ca`                         | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.caOptional=true`                 | Same as `traefik.frontend.auth.forward.tls.caOptional`                 | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.cert=/path/server.pem`           | Same as `traefik.frontend.auth.forward.tls.cert`                       | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.insecureSkipVerify=true`         | Same as `traefik.frontend.auth.forward.tls.insecureSkipVerify`         | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.key=/path/server.key`            | Same as `traefik.frontend.auth.forward.tls.key`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.trustForwardHeader=true`             | Same as `traefik.frontend.auth.forward.trustForwardHeader`             | | ||||
| | `traefik.<segment_name>.frontend.auth.headerField=X-WebAuth-User`                  | Same as `traefik.frontend.auth.headerField`                            | | ||||
| | `traefik.<segment_name>.frontend.entryPoints=https`                                | Same as `traefik.frontend.entryPoints`                                 | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.backend=NAME`                       | Same as `traefik.frontend.errors.<name>.backend`                       | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.query=PATH`                         | Same as `traefik.frontend.errors.<name>.query`                         | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.status=RANGE`                       | Same as `traefik.frontend.errors.<name>.status`                        | | ||||
| | `traefik.<segment_name>.frontend.passHostHeader=true`                              | Same as `traefik.frontend.passHostHeader`                              | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notAfter=true`            | Same as `traefik.frontend.passTLSClientCert.infos.notAfter`            | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notBefore=true`           | Same as `traefik.frontend.passTLSClientCert.infos.notBefore`           | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.sans=true`                | Same as `traefik.frontend.passTLSClientCert.infos.sans`                | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.commonName=true`  | Same as `traefik.frontend.passTLSClientCert.infos.subject.commonName`  | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.country=true`     | Same as `traefik.frontend.passTLSClientCert.infos.subject.country`     | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.locality=true`    | Same as `traefik.frontend.passTLSClientCert.infos.subject.locality`    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.organization=true`| Same as `traefik.frontend.passTLSClientCert.infos.subject.organization`| | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.province=true`    | Same as `traefik.frontend.passTLSClientCert.infos.subject.province`    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.serialNumber=true`| Same as `traefik.frontend.passTLSClientCert.infos.subject.serialNumber`| | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.pem=true`                       | Same as `traefik.frontend.passTLSClientCert.infos.pem`                 | | ||||
| | `traefik.<segment_name>.frontend.passTLSCert=true`                                 | Same as `traefik.frontend.passTLSCert`                                 | | ||||
| | `traefik.<segment_name>.frontend.priority=10`                                      | Same as `traefik.frontend.priority`                                    | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.extractorFunc=EXP`                      | Same as `traefik.frontend.rateLimit.extractorFunc`                     | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.period=6`                | Same as `traefik.frontend.rateLimit.rateSet.<name>.period`             | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.average=6`               | Same as `traefik.frontend.rateLimit.rateSet.<name>.average`            | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.burst=6`                 | Same as `traefik.frontend.rateLimit.rateSet.<name>.burst`              | | ||||
| | `traefik.<segment_name>.frontend.redirect.entryPoint=https`                        | Same as `traefik.frontend.redirect.entryPoint`                         | | ||||
| | `traefik.<segment_name>.frontend.redirect.regex=^http://localhost/(.*)`            | Same as `traefik.frontend.redirect.regex`                              | | ||||
| | `traefik.<segment_name>.frontend.redirect.replacement=http://mydomain/$1`          | Same as `traefik.frontend.redirect.replacement`                        | | ||||
| | `traefik.<segment_name>.frontend.redirect.permanent=true`                          | Same as `traefik.frontend.redirect.permanent`                          | | ||||
| | `traefik.<segment_name>.frontend.rule=EXP`                                         | Same as `traefik.frontend.rule`                                        | | ||||
| | `traefik.<segment_name>.frontend.whiteList.sourceRange=RANGE`                      | Same as `traefik.frontend.whiteList.sourceRange`                       | | ||||
| | `traefik.<segment_name>.frontend.whiteList.useXForwardedFor=true`                  | Same as `traefik.frontend.whiteList.useXForwardedFor`                  | | ||||
| | Label                                                                                  | Description                                                                | | ||||
| |----------------------------------------------------------------------------------------|----------------------------------------------------------------------------| | ||||
| | `traefik.<segment_name>.backend=BACKEND`                                               | Same as `traefik.backend`                                                  | | ||||
| | `traefik.<segment_name>.domain=DOMAIN`                                                 | Same as `traefik.domain`                                                   | | ||||
| | `traefik.<segment_name>.port=PORT`                                                     | Same as `traefik.port`                                                     | | ||||
| | `traefik.<segment_name>.protocol=http`                                                 | Same as `traefik.protocol`                                                 | | ||||
| | `traefik.<segment_name>.weight=10`                                                     | Same as `traefik.weight`                                                   | | ||||
| | `traefik.<segment_name>.frontend.auth.basic=EXPR`                                      | Same as `traefik.frontend.auth.basic`                                      | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.removeHeader=true`                         | Same as `traefik.frontend.auth.basic.removeHeader`                         | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.users=EXPR`                                | Same as `traefik.frontend.auth.basic.users`                                | | ||||
| | `traefik.<segment_name>.frontend.auth.basic.usersFile=/path/.htpasswd`                 | Same as `traefik.frontend.auth.basic.usersFile`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.removeHeader=true`                        | Same as `traefik.frontend.auth.digest.removeHeader`                        | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.users=EXPR`                               | Same as `traefik.frontend.auth.digest.users`                               | | ||||
| | `traefik.<segment_name>.frontend.auth.digest.usersFile=/path/.htdigest`                | Same as `traefik.frontend.auth.digest.usersFile`                           | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.address=https://example.com`             | Same as `traefik.frontend.auth.forward.address`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.authResponseHeaders=EXPR`                | Same as `traefik.frontend.auth.forward.authResponseHeaders`                | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.ca=/path/ca.pem`                     | Same as `traefik.frontend.auth.forward.tls.ca`                             | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.caOptional=true`                     | Same as `traefik.frontend.auth.forward.tls.caOptional`                     | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.cert=/path/server.pem`               | Same as `traefik.frontend.auth.forward.tls.cert`                           | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.insecureSkipVerify=true`             | Same as `traefik.frontend.auth.forward.tls.insecureSkipVerify`             | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.tls.key=/path/server.key`                | Same as `traefik.frontend.auth.forward.tls.key`                            | | ||||
| | `traefik.<segment_name>.frontend.auth.forward.trustForwardHeader=true`                 | Same as `traefik.frontend.auth.forward.trustForwardHeader`                 | | ||||
| | `traefik.<segment_name>.frontend.auth.headerField=X-WebAuth-User`                      | Same as `traefik.frontend.auth.headerField`                                | | ||||
| | `traefik.<segment_name>.frontend.entryPoints=https`                                    | Same as `traefik.frontend.entryPoints`                                     | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.backend=NAME`                           | Same as `traefik.frontend.errors.<name>.backend`                           | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.query=PATH`                             | Same as `traefik.frontend.errors.<name>.query`                             | | ||||
| | `traefik.<segment_name>.frontend.errors.<name>.status=RANGE`                           | Same as `traefik.frontend.errors.<name>.status`                            | | ||||
| | `traefik.<segment_name>.frontend.passHostHeader=true`                                  | Same as `traefik.frontend.passHostHeader`                                  | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.commonName=true`       | Same as `traefik.frontend.passTLSClientCert.infos.issuer.commonName`       | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.country=true`          | Same as `traefik.frontend.passTLSClientCert.infos.issuer.country`          | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.domainComponent=true`  | Same as `traefik.frontend.passTLSClientCert.infos.issuer.domainComponent`  | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.locality=true`         | Same as `traefik.frontend.passTLSClientCert.infos.issuer.locality`         | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.organization=true`     | Same as `traefik.frontend.passTLSClientCert.infos.issuer.organization`     | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.province=true`         | Same as `traefik.frontend.passTLSClientCert.infos.issuer.province`         | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.issuer.serialNumber=true`     | Same as `traefik.frontend.passTLSClientCert.infos.issuer.serialNumber`     | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notAfter=true`                | Same as `traefik.frontend.passTLSClientCert.infos.notAfter`                | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.notBefore=true`               | Same as `traefik.frontend.passTLSClientCert.infos.notBefore`               | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.sans=true`                    | Same as `traefik.frontend.passTLSClientCert.infos.sans`                    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.commonName=true`      | Same as `traefik.frontend.passTLSClientCert.infos.subject.commonName`      | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.country=true`         | Same as `traefik.frontend.passTLSClientCert.infos.subject.country`         | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.domainComponent=true` | Same as `traefik.frontend.passTLSClientCert.infos.subject.domainComponent` | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.locality=true`        | Same as `traefik.frontend.passTLSClientCert.infos.subject.locality`        | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.organization=true`    | Same as `traefik.frontend.passTLSClientCert.infos.subject.organization`    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.province=true`        | Same as `traefik.frontend.passTLSClientCert.infos.subject.province`        | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.infos.subject.serialNumber=true`    | Same as `traefik.frontend.passTLSClientCert.infos.subject.serialNumber`    | | ||||
| | `traefik.<segment_name>.frontend.passTLSClientCert.pem=true`                           | Same as `traefik.frontend.passTLSClientCert.infos.pem`                     | | ||||
| | `traefik.<segment_name>.frontend.passTLSCert=true`                                     | Same as `traefik.frontend.passTLSCert`                                     | | ||||
| | `traefik.<segment_name>.frontend.priority=10`                                          | Same as `traefik.frontend.priority`                                        | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.extractorFunc=EXP`                          | Same as `traefik.frontend.rateLimit.extractorFunc`                         | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.period=6`                    | Same as `traefik.frontend.rateLimit.rateSet.<name>.period`                 | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.average=6`                   | Same as `traefik.frontend.rateLimit.rateSet.<name>.average`                | | ||||
| | `traefik.<segment_name>.frontend.rateLimit.rateSet.<name>.burst=6`                     | Same as `traefik.frontend.rateLimit.rateSet.<name>.burst`                  | | ||||
| | `traefik.<segment_name>.frontend.redirect.entryPoint=https`                            | Same as `traefik.frontend.redirect.entryPoint`                             | | ||||
| | `traefik.<segment_name>.frontend.redirect.regex=^http://localhost/(.*)`                | Same as `traefik.frontend.redirect.regex`                                  | | ||||
| | `traefik.<segment_name>.frontend.redirect.replacement=http://mydomain/$1`              | Same as `traefik.frontend.redirect.replacement`                            | | ||||
| | `traefik.<segment_name>.frontend.redirect.permanent=true`                              | Same as `traefik.frontend.redirect.permanent`                              | | ||||
| | `traefik.<segment_name>.frontend.rule=EXP`                                             | Same as `traefik.frontend.rule`                                            | | ||||
| | `traefik.<segment_name>.frontend.whiteList.sourceRange=RANGE`                          | Same as `traefik.frontend.whiteList.sourceRange`                           | | ||||
| | `traefik.<segment_name>.frontend.whiteList.useXForwardedFor=true`                      | Same as `traefik.frontend.whiteList.useXForwardedFor`                      | | ||||
|  | ||||
| #### Custom Headers | ||||
|  | ||||
|   | ||||
| @@ -29,7 +29,7 @@ Traefik can be configured: | ||||
|  | ||||
|  | ||||
| ```shell | ||||
| curl -XPUT @file "http://localhost:8080/api/providers/rest" | ||||
| curl -XPUT -d @file "http://localhost:8080/api/providers/rest" | ||||
| ``` | ||||
|  | ||||
| with `@file`: | ||||
|   | ||||
| @@ -69,6 +69,8 @@ Here is an example of an extension setting Traefik labels: | ||||
| </StatelessServiceType> | ||||
| ``` | ||||
|  | ||||
| > **Note**: The `Label` tag and its `Key` attribute are case sensitive. That is, if you use `label` instead of `Label` or `key` instead of `Key`, they will be silently ignored. | ||||
|  | ||||
| #### Property Manager | ||||
|  | ||||
| Set Labels with the property manager API to overwrite and add labels, while your service is running. | ||||
| @@ -96,11 +98,12 @@ Labels, set through extensions or the property manager, can be used on services | ||||
|  | ||||
| | Label                                                      | Description                                                                                                                                                                                                               | | ||||
| |------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `traefik.enable=false`                                     | Disable this container in Traefik                                                                                                                                                                                          | | ||||
| | `traefik.enable=false`                                     | Disable this container in Traefik                                                                                                                                                                                         | | ||||
| | `traefik.backend.circuitbreaker.expression=EXPR`           | Create a [circuit breaker](/basics/#backends) to be used against the backend                                                                                                                                              | | ||||
| | `traefik.servicefabric.groupname`                               | Group all services with the same name into a single backend in Traefik                                                                                                                                                     | | ||||
| | `traefik.servicefabric.groupweight`                             | Set the weighting of the current services nodes in the backend group                                                                                                                                                      | | ||||
| | `traefik.servicefabric.enablelabeloverrides`                             | Toggle whether labels can be overridden using the Service Fabric Property Manager API                                                                                                                                                      | | ||||
| | `traefik.servicefabric.groupname`                          | Group all services with the same name into a single backend in Traefik                                                                                                                                                    | | ||||
| | `traefik.servicefabric.groupweight`                        | Set the weighting of the current services nodes in the backend group                                                                                                                                                      | | ||||
| | `traefik.servicefabric.enablelabeloverrides`               | Toggle whether labels can be overridden using the Service Fabric Property Manager API                                                                                                                                     | | ||||
| | `traefik.servicefabric.endpointname`                       | Specify the name of the endpoint                                                                                                                                                                                          | | ||||
| | `traefik.backend.healthcheck.path=/health`                 | Enable health check for the backend, hitting the container at `path`.                                                                                                                                                     | | ||||
| | `traefik.backend.healthcheck.port=8080`                    | Allow to use a different port for the health check.                                                                                                                                                                       | | ||||
| | `traefik.backend.healthcheck.interval=1s`                  | Define the health check interval.                                                                                                                                                                                         | | ||||
|   | ||||
| @@ -249,8 +249,13 @@ Multiple sets of rates can be added to each frontend, but the time periods must | ||||
| ``` | ||||
|  | ||||
| In the above example, frontend1 is configured to limit requests by the client's ip address.   | ||||
| An average of 5 requests every 3 seconds is allowed and an average of 100 requests every 10 seconds.   | ||||
| These can "burst" up to 10 and 200 in each period respectively. | ||||
| An average of 100 requests every 10 seconds is allowed and an average of 5 requests every 3 seconds.   | ||||
| These can "burst" up to 200 and 10 in each period respectively.  | ||||
|  | ||||
| Valid values for `extractorfunc` are: | ||||
|   * `client.ip` | ||||
|   * `request.host` | ||||
|   * `request.header.<header name>` | ||||
|  | ||||
| ## Buffering | ||||
|  | ||||
| @@ -528,3 +533,40 @@ Example: | ||||
|   backend = "{{$backend}}" | ||||
| {{end}} | ||||
| ``` | ||||
|  | ||||
| ## Pass TLS Client Cert | ||||
|  | ||||
| ```toml | ||||
| # Pass the escaped client cert infos selected below in a `X-Forwarded-Ssl-Client-Cert-Infos` header. | ||||
| [frontends.frontend1.passTLSClientCert] | ||||
|         pem = true | ||||
|         [frontends.frontend1.passTLSClientCert.infos] | ||||
|             notBefore = true | ||||
|             notAfter = true | ||||
|             [frontends.frontend1.passTLSClientCert.infos.subject] | ||||
|                 country = true | ||||
|                 domainComponent = true | ||||
|                 province = true | ||||
|                 locality = true | ||||
|                 organization = true | ||||
|                 commonName = true | ||||
|                 serialNumber = true | ||||
|             [frontends.frontend1.passTLSClientCert.infos.issuer] | ||||
|                 country = true | ||||
|                 domainComponent = true | ||||
|                 province = true | ||||
|                 locality = true | ||||
|                 organization = true | ||||
|                 commonName = true | ||||
|                 serialNumber = true | ||||
| ``` | ||||
|  | ||||
| Pass TLS Client Cert `pem` defines if the escaped pem is added to a `X-Forwarded-Ssl-Client-Cert` header.   | ||||
| Pass TLS Client Cert `infos` defines how the certificate data are added to a `X-Forwarded-Ssl-Client-Cert-Infos` header.   | ||||
|  | ||||
| The following example shows an unescaped result that uses all the available fields: | ||||
| If there are more than one certificate, they are separated by a `;` | ||||
|  | ||||
| ``` | ||||
| Subject="DC=org,DC=cheese,C=FR,C=US,ST=Cheese org state,ST=Cheese com state,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=*.cheese.com",Issuer="DC=org,DC=cheese,C=FR,C=US,ST=Signing State,ST=Signing State 2,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=Simple Signing CA 2",NB=1544094616,NA=1607166616,SAN=*.cheese.org,*.cheese.net,*.cheese.com,test@cheese.org,test@cheese.net,10.0.1.0,10.0.1.2 | ||||
| ``` | ||||
|   | ||||
| @@ -93,11 +93,11 @@ For more information about the CLI, see the documentation about [Traefik command | ||||
|     Whitespace is used as option separator and `,` is used as value separator for the list.   | ||||
|     The names of the options are case-insensitive. | ||||
|  | ||||
| In compose file the entrypoint syntax is different: | ||||
| In compose file the entrypoint syntax is different. Notice how quotes are used: | ||||
|  | ||||
| ```yaml | ||||
| traefik: | ||||
|     image: traefik | ||||
|     image: traefik:v1.7 | ||||
|     command: | ||||
|         - --defaultentrypoints=powpow | ||||
|         - "--entryPoints=Name:powpow Address::42 Compress:true" | ||||
| @@ -105,7 +105,7 @@ traefik: | ||||
| or | ||||
| ```yaml | ||||
| traefik: | ||||
|     image: traefik | ||||
|     image: traefik:v1.7 | ||||
|     command: --defaultentrypoints=powpow --entryPoints='Name:powpow Address::42 Compress:true' | ||||
| ``` | ||||
|  | ||||
| @@ -235,8 +235,10 @@ If you need to add or remove TLS certificates while Traefik is started, Dynamic | ||||
| ## TLS Mutual Authentication | ||||
|  | ||||
| TLS Mutual Authentication can be `optional` or not. | ||||
| If it's `optional`, Traefik will authorize connection with certificates not signed by a specified Certificate Authority (CA). | ||||
| Otherwise, Traefik will only accept clients that present a certificate signed by a specified Certificate Authority (CA). | ||||
|  | ||||
| * If `optional = true`, if a certificate is provided, verifies if it is signed by a specified Certificate Authority (CA). Otherwise proceeds without any certificate. | ||||
| * If `optional = false`, Traefik will only accept clients that present a certificate signed by a specified Certificate Authority (CA). | ||||
|  | ||||
| `ClientCAFiles` can be configured with multiple `CA:s` in the same file or use multiple files containing one or several `CA:s`. | ||||
| The `CA:s` has to be in PEM format. | ||||
|  | ||||
|   | ||||
| @@ -39,7 +39,7 @@ logLevel = "INFO" | ||||
|  | ||||
| For more information about the CLI, see the documentation about [Traefik command](/basics/#traefik). | ||||
|  | ||||
| ```shell | ||||
| ```bash | ||||
| --logLevel="DEBUG" | ||||
| --traefikLog.filePath="/path/to/traefik.log" | ||||
| --traefikLog.format="json" | ||||
| @@ -54,7 +54,6 @@ For more information about the CLI, see the documentation about [Traefik command | ||||
| --accessLog.fields.headers.names="User-Agent=redact Authorization=drop Content-Type=keep" | ||||
| ``` | ||||
|  | ||||
|  | ||||
| ## Traefik Logs | ||||
|  | ||||
| By default the Traefik log is written to stdout in text format. | ||||
| @@ -66,7 +65,7 @@ To write the logs into a log file specify the `filePath`: | ||||
|   filePath = "/path/to/traefik.log" | ||||
| ``` | ||||
|  | ||||
| To write JSON format logs, specify `json` as the format: | ||||
| To switch to JSON format instead of standard format (`common`), specify `json` as the format: | ||||
|  | ||||
| ```toml | ||||
| [traefikLog] | ||||
| @@ -74,7 +73,6 @@ To write JSON format logs, specify `json` as the format: | ||||
|   format   = "json" | ||||
| ``` | ||||
|  | ||||
|  | ||||
| Deprecated way (before 1.4): | ||||
|  | ||||
| !!! danger "DEPRECATED" | ||||
| @@ -105,13 +103,12 @@ To customize the log level: | ||||
| logLevel = "ERROR" | ||||
| ``` | ||||
|  | ||||
|  | ||||
| ## Access Logs | ||||
|  | ||||
| Access logs are written when `[accessLog]` is defined. | ||||
| By default it will write to stdout and produce logs in the textual Common Log Format (CLF), extended with additional fields. | ||||
| Access logs are written when the entry `[accessLog]` is defined (or the command line flag `--accesslog`). | ||||
| By default it writes to stdout and produces logs in the textual [Common Log Format (CLF)](#clf-common-log-format), extended with additional fields. | ||||
|  | ||||
| To enable access logs using the default settings just add the `[accessLog]` entry: | ||||
| To enable access logs using the default settings, add the `[accessLog]` entry in your `traefik.toml` configuration file: | ||||
|  | ||||
| ```toml | ||||
| [accessLog] | ||||
| @@ -124,12 +121,12 @@ To write the logs into a log file specify the `filePath`: | ||||
| filePath = "/path/to/access.log" | ||||
| ``` | ||||
|  | ||||
| To write JSON format logs, specify `json` as the format: | ||||
| To switch to JSON format instead of [Common Log Format (CLF)](#clf-common-log-format), specify `json` as the format: | ||||
|  | ||||
| ```toml | ||||
| [accessLog] | ||||
| filePath = "/path/to/access.log" | ||||
| format = "json" | ||||
| format = "json"  # Default: "common" | ||||
| ``` | ||||
|  | ||||
| To write the logs in async, specify `bufferingSize` as the format (must be >0): | ||||
| @@ -152,7 +149,7 @@ To filter logs you can specify a set of filters which are logically "OR-connecte | ||||
| ```toml | ||||
| [accessLog] | ||||
| filePath = "/path/to/access.log" | ||||
| format = "json" | ||||
| format = "json"  # Default: "common" | ||||
|  | ||||
|   [accessLog.filters] | ||||
|  | ||||
| @@ -178,22 +175,42 @@ format = "json" | ||||
|   minDuration = "10ms" | ||||
| ``` | ||||
|  | ||||
| To customize logs format: | ||||
| ### CLF - Common Log Format | ||||
|  | ||||
| By default, Traefik use the CLF (`common`) as access log format. | ||||
|  | ||||
| ```html | ||||
| <remote_IP_address> - <client_user_name_if_available> [<timestamp>] "<request_method> <request_path> <request_protocol>" <origin_server_HTTP_status> <origin_server_content_size> "<request_referrer>" "<request_user_agent>" <number_of_requests_received_since_Traefik_started> "<Traefik_frontend_name>" "<Traefik_backend_URL>" <request_duration_in_ms>ms | ||||
| ``` | ||||
|  | ||||
| ### Customize Fields | ||||
|  | ||||
| You can customize the fields written in the access logs. | ||||
| The list of available fields is found below: [List of All Available Fields](#list-of-all-available-fields). | ||||
|  | ||||
| Each field has a "mode" which defines if it is written or not in the access log lines. | ||||
| The possible values for the mode are: | ||||
|  | ||||
| * `keep`: the field and its value are written on the access log line. This is the default behavior. | ||||
| * `drop`: the field is not written at all on the access log. | ||||
|  | ||||
| To customize the fields, you must: | ||||
|  | ||||
| * Switch to the JSON format (mandatory) | ||||
| * Define the "default mode" for all fields (default is `keep`) | ||||
| * OR Define the fields which does not follow the default mode | ||||
|  | ||||
| ```toml | ||||
| [accessLog] | ||||
| filePath = "/path/to/access.log" | ||||
| # Access Log Format | ||||
| # | ||||
| # Optional | ||||
| # Default: "common" | ||||
| # | ||||
| # Accepted values "common", "json" | ||||
| # | ||||
| format = "json" | ||||
|  | ||||
|   [accessLog.filters] | ||||
|  | ||||
|   # statusCodes keep only access logs with status codes in the specified range | ||||
|   # | ||||
|   # Optional | ||||
|   # Default: [] | ||||
|   # | ||||
|   statusCodes = ["200", "300-302"] | ||||
|  | ||||
|   [accessLog.fields] | ||||
|  | ||||
|   # defaultMode | ||||
| @@ -209,6 +226,43 @@ format = "json" | ||||
|   [accessLog.fields.names] | ||||
|     "ClientUsername" = "drop" | ||||
|     # ... | ||||
| ``` | ||||
|  | ||||
| ### Customize Headers | ||||
|  | ||||
| Access logs prints the headers of each request, as fields of the access log line. | ||||
| You can customize which and how the headers are printed, likewise the other fields (see ["Customize Fields" section](#customize-fields)). | ||||
|  | ||||
| Each header has a "mode" which defines how it is written in the access log lines. | ||||
| The possible values for the mode are: | ||||
|  | ||||
| * `keep`: the header and its value are written on the access log line. This is the default behavior. | ||||
| * `drop`: the header is not written at all on the access log. | ||||
| * `redacted`: the header is written, but its value is redacted to avoid leaking sensitive information. | ||||
|  | ||||
| To customize the headers, you must: | ||||
|  | ||||
| * Switch to the JSON format (mandatory) | ||||
| * Define the "default mode" for all headers (default is `keep`) | ||||
| * OR Define the headers which does not follow the default mode | ||||
|  | ||||
| !!! important | ||||
|     The headers are written with the prefix `request_` in the access log. | ||||
|     This prefix must not be included when specifying a header in the TOML configuration. | ||||
|  | ||||
|     * Do: `"User-Agent" = "drop"` | ||||
|     * Don't: `"redacted_User-Agent" = "drop"` | ||||
|  | ||||
| ```toml | ||||
| [accessLog] | ||||
| # Access Log Format | ||||
| # | ||||
| # Optional | ||||
| # Default: "common" | ||||
| # | ||||
| # Accepted values "common", "json" | ||||
| # | ||||
| format = "json" | ||||
|  | ||||
|   [accessLog.fields.headers] | ||||
|     # defaultMode | ||||
| @@ -227,41 +281,42 @@ format = "json" | ||||
|       # ... | ||||
| ``` | ||||
|  | ||||
| ### List of All Available Fields | ||||
|  | ||||
| ### List of all available fields | ||||
| | Field                   | Description                                                                                                                                                         | | ||||
| |-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `StartUTC`              | The time at which request processing started.                                                                                                                       | | ||||
| | `StartLocal`            | The local time at which request processing started.                                                                                                                 | | ||||
| | `Duration`              | The total time taken by processing the response, including the origin server's time but not the log writing time.                                                   | | ||||
| | `FrontendName`          | The name of the Traefik frontend.                                                                                                                                   | | ||||
| | `BackendName`           | The name of the Traefik backend.                                                                                                                                    | | ||||
| | `BackendURL`            | The URL of the Traefik backend.                                                                                                                                     | | ||||
| | `BackendAddr`           | The IP:port of the Traefik backend (extracted from `BackendURL`)                                                                                                    | | ||||
| | `ClientAddr`            | The remote address in its original form (usually IP:port).                                                                                                          | | ||||
| | `ClientHost`            | The remote IP address from which the client request was received.                                                                                                   | | ||||
| | `ClientPort`            | The remote TCP port from which the client request was received.                                                                                                     | | ||||
| | `ClientUsername`        | The username provided in the URL, if present.                                                                                                                       | | ||||
| | `RequestAddr`           | The HTTP Host header (usually IP:port). This is treated as not a header by the Go API.                                                                              | | ||||
| | `RequestHost`           | The HTTP Host server name (not including port).                                                                                                                     | | ||||
| | `RequestPort`           | The TCP port from the HTTP Host.                                                                                                                                    | | ||||
| | `RequestMethod`         | The HTTP method.                                                                                                                                                    | | ||||
| | `RequestPath`           | The HTTP request URI, not including the scheme, host or port.                                                                                                       | | ||||
| | `RequestProtocol`       | The version of HTTP requested.                                                                                                                                      | | ||||
| | `RequestLine`           | `RequestMethod` + `RequestPath` + `RequestProtocol`                                                                                                                 | | ||||
| | `RequestContentSize`    | The number of bytes in the request entity (a.k.a. body) sent by the client.                                                                                         | | ||||
| | `OriginDuration`        | The time taken by the origin server ('upstream') to return its response.                                                                                            | | ||||
| | `OriginContentSize`     | The content length specified by the origin server, or 0 if unspecified.                                                                                             | | ||||
| | `OriginStatus`          | The HTTP status code returned by the origin server. If the request was handled by this Traefik instance (e.g. with a redirect), then this value will be absent.     | | ||||
| | `OriginStatusLine`      | `OriginStatus` + Status code explanation                                                                                                                            | | ||||
| | `DownstreamStatus`      | The HTTP status code returned to the client.                                                                                                                        | | ||||
| | `DownstreamStatusLine`  | `DownstreamStatus` + Status code explanation                                                                                                                        | | ||||
| | `DownstreamContentSize` | The number of bytes in the response entity returned to the client. This is in addition to the "Content-Length" header, which may be present in the origin response. | | ||||
| | `RequestCount`          | The number of requests received since the Traefik instance started.                                                                                                 | | ||||
| | `GzipRatio`             | The response body compression ratio achieved.                                                                                                                       | | ||||
| | `Overhead`              | The processing time overhead caused by Traefik.                                                                                                                     | | ||||
| | `RetryAttempts`         | The amount of attempts the request was retried.                                                                                                                     | | ||||
|  | ||||
| ```ini | ||||
| StartUTC | ||||
| StartLocal | ||||
| Duration | ||||
| FrontendName | ||||
| BackendName | ||||
| BackendURL | ||||
| BackendAddr | ||||
| ClientAddr | ||||
| ClientHost | ||||
| ClientPort | ||||
| ClientUsername | ||||
| RequestAddr | ||||
| RequestHost | ||||
| RequestPort | ||||
| RequestMethod | ||||
| RequestPath | ||||
| RequestProtocol | ||||
| RequestLine | ||||
| RequestContentSize | ||||
| OriginDuration | ||||
| OriginContentSize | ||||
| OriginStatus | ||||
| OriginStatusLine | ||||
| DownstreamStatus | ||||
| DownstreamStatusLine | ||||
| DownstreamContentSize | ||||
| RequestCount | ||||
| GzipRatio | ||||
| Overhead | ||||
| RetryAttempts | ||||
| ``` | ||||
| ### Depreciation Notice | ||||
|  | ||||
| Deprecated way (before 1.4): | ||||
|  | ||||
| @@ -276,15 +331,6 @@ Deprecated way (before 1.4): | ||||
| accessLogsFile = "log/access.log" | ||||
| ``` | ||||
|  | ||||
| ### CLF - Common Log Format | ||||
|  | ||||
| By default, Traefik use the CLF (`common`) as access log format. | ||||
|  | ||||
| ```html | ||||
| <remote_IP_address> - <client_user_name_if_available> [<timestamp>] "<request_method> <request_path> <request_protocol>" <origin_server_HTTP_status> <origin_server_content_size> "<request_referrer>" "<request_user_agent>" <number_of_requests_received_since_Traefik_started> "<Traefik_frontend_name>" "<Traefik_backend_URL>" <request_duration_in_ms>ms  | ||||
| ``` | ||||
|  | ||||
|  | ||||
| ## Log Rotation | ||||
|  | ||||
| Traefik will close and reopen its log files, assuming they're configured, on receipt of a USR1 signal. | ||||
| @@ -292,3 +338,34 @@ This allows the logs to be rotated and processed by an external program, such as | ||||
|  | ||||
| !!! note | ||||
|     This does not work on Windows due to the lack of USR signals. | ||||
|  | ||||
| ## Time Zones | ||||
|  | ||||
| The timestamp of each log line is in UTC time by default. | ||||
|  | ||||
| If you want to use local timezone, you need to ensure the 3 following elements: | ||||
|  | ||||
| 1. Provide the timezone data into /usr/share/zoneinfo | ||||
| 2. Set the environement variable TZ to the timezone to be used | ||||
| 3. Specify the field StartLocal instead of StartUTC (works on default Common Log Format (CLF) as well as JSON) | ||||
|  | ||||
| Example using docker-compose: | ||||
|  | ||||
| ```yml | ||||
| version: '3' | ||||
|  | ||||
| services: | ||||
|   traefik: | ||||
|     image: containous/traefik:[latest stable version] | ||||
|     ports: | ||||
|       - "80:80" | ||||
|     environment: | ||||
|       - "TZ=US/Alaska" | ||||
|     command: | ||||
|       - --docker | ||||
|       - --accesslog | ||||
|       - --accesslog.fields.names="StartUTC=drop" | ||||
|     volumes: | ||||
|       - "/var/run/docker.sock:/var/run/docker.sock" | ||||
|       - "/usr/share/zoneinfo:/usr/share/zoneinfo:ro" | ||||
| ``` | ||||
|   | ||||
| @@ -20,7 +20,7 @@ | ||||
|     # Buckets for latency metrics | ||||
|     # | ||||
|     # Optional | ||||
|     # Default: [0.1, 0.3, 1.2, 5] | ||||
|     # Default: [0.1, 0.3, 1.2, 5.0] | ||||
|     # | ||||
|     buckets = [0.1,0.3,1.2,5.0] | ||||
|  | ||||
|   | ||||
| @@ -30,7 +30,7 @@ Thus, if you have a regular path for `/foo` and an entrypoint on `:80`, you woul | ||||
| * Admin panel: `http://hostname:8080/` | ||||
| * Ping URL: `http://hostname:8080/ping` | ||||
|  | ||||
| However, for security reasons, you may want to be able to expose the `/ping` health-check URL to outside health-checkers, e.g. an Internet service or cloud load-balancer, _without_ exposing your administration panel's port. | ||||
| However, for security reasons, you may want to be able to expose the `/ping` health-check URL to outside health-checkers, e.g. an Internet service or cloud load-balancer, _without_ exposing your dashboard's port. | ||||
| In many environments, the security staff may not _allow_ you to expose it. | ||||
|  | ||||
| You have two options: | ||||
| @@ -40,7 +40,7 @@ You have two options: | ||||
|  | ||||
| ### Ping health check on a regular entry point | ||||
|  | ||||
| To proxy `/ping` from a regular entry point to the administration one without exposing the panel, do the following: | ||||
| To proxy `/ping` from a regular entry point to the administration one without exposing the dashboard, do the following: | ||||
|  | ||||
| ```toml | ||||
| defaultEntryPoints = ["http"] | ||||
|   | ||||
| @@ -58,6 +58,13 @@ Traefik supports three tracing backends: Jaeger, Zipkin and DataDog. | ||||
|     # Default: "127.0.0.1:6831" | ||||
|     # | ||||
|     localAgentHostPort = "127.0.0.1:6831" | ||||
|      | ||||
|     # Trace Context Header Name is the http header name used to propagate tracing context. | ||||
|     # This must be in lower-case to avoid mismatches when decoding incoming headers. | ||||
|     # | ||||
|     # Default: "uber-trace-id" | ||||
|     # | ||||
|     traceContextHeaderName = "uber-trace-id" | ||||
| ``` | ||||
|  | ||||
| !!! warning | ||||
| @@ -156,4 +163,10 @@ Traefik supports three tracing backends: Jaeger, Zipkin and DataDog. | ||||
|     # | ||||
|     globalTag = "" | ||||
|  | ||||
|     # Enable priority sampling. When using distributed tracing, this option must be enabled in order | ||||
|     # to get all the parts of a distributed trace sampled. | ||||
|     # | ||||
|     # Default: false | ||||
|     # | ||||
|     prioritySampling = false | ||||
| ``` | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
| [](/) | ||||
| [](https://goreportcard.com/report/github.com/containous/traefik) | ||||
| [](https://github.com/containous/traefik/blob/master/LICENSE.md) | ||||
| [](https://slack.traefik.io) | ||||
| [](https://community.containo.us/) | ||||
| [](https://twitter.com/intent/follow?screen_name=traefik) | ||||
|  | ||||
|  | ||||
| @@ -66,7 +66,7 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t | ||||
|  | ||||
| In this quickstart, we'll use [Docker compose](https://docs.docker.com/compose) to create our demo infrastructure. | ||||
|  | ||||
| To save some time, you can clone [Traefik's repository](https://github.com/containous/traefik) and use the quickstart files located in the [examples/quickstart](https://github.com/containous/traefik/tree/master/examples/quickstart/) directory. | ||||
| To save some time, you can clone [Traefik's repository](https://github.com/containous/traefik) and use the quickstart files located in the [examples/quickstart](https://github.com/containous/traefik/tree/v1.7/examples/quickstart/) directory. | ||||
|  | ||||
| ### 1 — Launch Traefik — Tell It to Listen to Docker | ||||
|  | ||||
| @@ -77,7 +77,7 @@ version: '3' | ||||
|  | ||||
| services: | ||||
|   reverse-proxy: | ||||
|     image: traefik # The official Traefik docker image | ||||
|     image: traefik:v1.7 # The official Traefik docker image | ||||
|     command: --api --docker # Enables the web UI and tells Traefik to listen to docker | ||||
|     ports: | ||||
|       - "80:80"     # The HTTP port | ||||
| @@ -176,7 +176,7 @@ Our recommendation would be to see for yourself how simple it is to enable HTTPS | ||||
|  | ||||
| ## Resources | ||||
|  | ||||
| Here is a talk given by [Emile Vauge](https://github.com/emilevauge) at [GopherCon 2017](https://gophercon.com). | ||||
| Here is a talk given by [Emile Vauge](https://github.com/emilevauge) at GopherCon 2017. | ||||
| You will learn Traefik basics in less than 10 minutes. | ||||
|  | ||||
| [](https://www.youtube.com/watch?v=RgudiksfL-k) | ||||
| @@ -190,7 +190,7 @@ You will learn fundamental Traefik features and see some demos with Kubernetes. | ||||
|  | ||||
| ### The Official Binary File | ||||
|  | ||||
| You can grab the latest binary from the [releases](https://github.com/containous/traefik/releases) page and just run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/master/traefik.sample.toml): | ||||
| You can grab the latest binary from the [releases](https://github.com/containous/traefik/releases) page and just run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/v1.7/traefik.sample.toml): | ||||
|  | ||||
| ```shell | ||||
| ./traefik -c traefik.toml | ||||
|   | ||||
							
								
								
									
										4
									
								
								docs/theme/partials/footer.html
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								docs/theme/partials/footer.html
									
									
									
									
										vendored
									
									
								
							| @@ -88,9 +88,9 @@ | ||||
|                 </div> | ||||
|                 {% endif %} | ||||
|                 powered by | ||||
|                 <a href="http://www.mkdocs.org" title="MkDocs">MkDocs</a> | ||||
|                 <a href="https://www.mkdocs.org" title="MkDocs">MkDocs</a> | ||||
|                 and | ||||
|                 <a href="http://squidfunk.github.io/mkdocs-material/" | ||||
|                 <a href="https://squidfunk.github.io/mkdocs-material/" | ||||
|                    title="Material for MkDocs"> | ||||
|                     Material for MkDocs</a> | ||||
|             </div> | ||||
|   | ||||
| @@ -91,7 +91,7 @@ To watch docker events, add `--docker.watch`. | ||||
| version: "3" | ||||
| services: | ||||
|   traefik: | ||||
|     image: traefik:1.5 | ||||
|     image: traefik:<stable v1.7 from https://hub.docker.com/_/traefik> | ||||
|     command: | ||||
|       - "--api" | ||||
|       - "--entrypoints=Name:http Address::80 Redirect.EntryPoint:https" | ||||
| @@ -156,7 +156,7 @@ The initializer in a docker-compose file will be: | ||||
|  | ||||
| ```yaml | ||||
|   traefik_init: | ||||
|     image: traefik:1.5 | ||||
|     image: traefik:<stable v1.7 from https://hub.docker.com/_/traefik> | ||||
|     command: | ||||
|       - "storeconfig" | ||||
|       - "--api" | ||||
| @@ -177,7 +177,7 @@ And now, the Traefik part will only have the Consul configuration. | ||||
|  | ||||
| ```yaml | ||||
|   traefik: | ||||
|     image: traefik:1.5 | ||||
|     image: traefik:<stable v1.7 from https://hub.docker.com/_/traefik> | ||||
|     depends_on: | ||||
|       - traefik_init | ||||
|       - consul | ||||
| @@ -200,7 +200,7 @@ The new configuration will be stored in Consul, and you need to restart the Trae | ||||
| version: "3.4" | ||||
| services: | ||||
|   traefik_init: | ||||
|     image: traefik:1.5 | ||||
|     image: traefik:<stable v1.7 from https://hub.docker.com/_/traefik> | ||||
|     command: | ||||
|       - "storeconfig" | ||||
|       - "--api" | ||||
| @@ -229,7 +229,7 @@ services: | ||||
|     depends_on: | ||||
|       - consul | ||||
|   traefik: | ||||
|     image: traefik:1.5 | ||||
|     image: traefik:<stable v1.7 from https://hub.docker.com/_/traefik> | ||||
|     depends_on: | ||||
|       - traefik_init | ||||
|       - consul | ||||
|   | ||||
| @@ -50,7 +50,7 @@ version: '2' | ||||
|  | ||||
| services: | ||||
|   traefik: | ||||
|     image: traefik:1.5.4 | ||||
|     image: traefik:<stable v1.7 from https://hub.docker.com/_/traefik> | ||||
|     restart: always | ||||
|     ports: | ||||
|       - 80:80 | ||||
| @@ -108,6 +108,28 @@ onHostRule = true | ||||
| entryPoint = "http" | ||||
| ``` | ||||
|  | ||||
| Alternatively, the `TOML` file above can also be translated into command line switches.  | ||||
| This is the `command` value of the `traefik` service in the `docker-compose.yml` manifest: | ||||
|  | ||||
| ```yaml | ||||
| command: | ||||
|   - --debug=false | ||||
|   - --logLevel=ERROR | ||||
|   - --defaultentrypoints=https,http | ||||
|   - --entryPoints=Name:http Address::80 Redirect.EntryPoint:https | ||||
|   - --entryPoints=Name:https Address::443 TLS | ||||
|   - --retry | ||||
|   - --docker.endpoint=unix:///var/run/docker.sock | ||||
|   - --docker.domain=my-awesome-app.org | ||||
|   - --docker.watch=true | ||||
|   - --docker.exposedbydefault=false | ||||
|   - --acme.email=your-email-here@my-awesome-app.org | ||||
|   - --acme.storage=acme.json | ||||
|   - --acme.entryPoint=https | ||||
|   - --acme.onHostRule=true | ||||
|   - --acme.httpchallenge.entrypoint=http | ||||
| ``` | ||||
|  | ||||
| This is the minimum configuration required to do the following: | ||||
|  | ||||
| - Log `ERROR`-level messages (or more severe) to the console, but silence `DEBUG`-level messages | ||||
|   | ||||
| @@ -336,37 +336,37 @@ Pay attention to the **labels** section: | ||||
|  | ||||
| ``` | ||||
| home: | ||||
| image: abiosoft/caddy:0.10.14 | ||||
| networks: | ||||
|   - ntw_front | ||||
| volumes: | ||||
|   - ./www/home/srv/:/srv/ | ||||
| deploy: | ||||
|   mode: replicated | ||||
|   replicas: 2 | ||||
|   #placement: | ||||
|   #  constraints: [node.role==manager] | ||||
|   restart_policy: | ||||
|     condition: on-failure | ||||
|     max_attempts: 5 | ||||
|   resources: | ||||
|     limits: | ||||
|       cpus: '0.20' | ||||
|       memory: 9M | ||||
|     reservations: | ||||
|       cpus: '0.05' | ||||
|       memory: 9M | ||||
|   labels: | ||||
|   - "traefik.frontend.rule=PathPrefixStrip:/" | ||||
|   - "traefik.backend=home" | ||||
|   - "traefik.port=2015" | ||||
|   - "traefik.weight=10" | ||||
|   - "traefik.enable=true" | ||||
|   - "traefik.passHostHeader=true" | ||||
|   - "traefik.docker.network=ntw_front" | ||||
|   - "traefik.frontend.entryPoints=http" | ||||
|   - "traefik.backend.loadbalancer.swarm=true" | ||||
|   - "traefik.backend.loadbalancer.method=drr" | ||||
|   image: abiosoft/caddy:0.10.14 | ||||
|   networks: | ||||
|     - ntw_front | ||||
|   volumes: | ||||
|     - ./www/home/srv/:/srv/ | ||||
|   deploy: | ||||
|     mode: replicated | ||||
|     replicas: 2 | ||||
|     #placement: | ||||
|     #  constraints: [node.role==manager] | ||||
|     restart_policy: | ||||
|       condition: on-failure | ||||
|       max_attempts: 5 | ||||
|     resources: | ||||
|       limits: | ||||
|         cpus: '0.20' | ||||
|         memory: 9M | ||||
|       reservations: | ||||
|         cpus: '0.05' | ||||
|         memory: 9M | ||||
|     labels: | ||||
|       - "traefik.frontend.rule=PathPrefixStrip:/" | ||||
|       - "traefik.backend=home" | ||||
|       - "traefik.port=2015" | ||||
|       - "traefik.weight=10" | ||||
|       - "traefik.enable=true" | ||||
|       - "traefik.passHostHeader=true" | ||||
|       - "traefik.docker.network=ntw_front" | ||||
|       - "traefik.frontend.entryPoints=http" | ||||
|       - "traefik.backend.loadbalancer.swarm=true" | ||||
|       - "traefik.backend.loadbalancer.method=drr" | ||||
| ``` | ||||
|  | ||||
| Something more tricky using `regex`. | ||||
| @@ -377,39 +377,39 @@ The double sign `$$` are variables managed by the docker compose file ([document | ||||
|  | ||||
| ``` | ||||
| portainer: | ||||
| image: portainer/portainer:1.16.5 | ||||
| networks: | ||||
|   - ntw_front | ||||
| volumes: | ||||
|   - /var/run/docker.sock:/var/run/docker.sock | ||||
| deploy: | ||||
|   mode: replicated | ||||
|   replicas: 1 | ||||
|   placement: | ||||
|     constraints: [node.role==manager] | ||||
|   restart_policy: | ||||
|     condition: on-failure | ||||
|     max_attempts: 5 | ||||
|   resources: | ||||
|     limits: | ||||
|       cpus: '0.33' | ||||
|       memory: 20M | ||||
|     reservations: | ||||
|       cpus: '0.05' | ||||
|       memory: 10M | ||||
|   labels: | ||||
|     - "traefik.frontend.rule=PathPrefixStrip:/portainer" | ||||
|     - "traefik.backend=portainer" | ||||
|     - "traefik.port=9000" | ||||
|     - "traefik.weight=10" | ||||
|     - "traefik.enable=true" | ||||
|     - "traefik.passHostHeader=true" | ||||
|     - "traefik.docker.network=ntw_front" | ||||
|     - "traefik.frontend.entryPoints=http" | ||||
|     - "traefik.backend.loadbalancer.swarm=true" | ||||
|     - "traefik.backend.loadbalancer.method=drr" | ||||
|     # https://github.com/containous/traefik/issues/563#issuecomment-421360934 | ||||
|     - "traefik.frontend.redirect.regex=^(.*)/portainer$$" | ||||
|     - "traefik.frontend.redirect.replacement=$$1/portainer/" | ||||
|     - "traefik.frontend.rule=PathPrefix:/portainer;ReplacePathRegex: ^/portainer/(.*) /$$1" | ||||
|   image: portainer/portainer:1.16.5 | ||||
|   networks: | ||||
|     - ntw_front | ||||
|   volumes: | ||||
|     - /var/run/docker.sock:/var/run/docker.sock | ||||
|   deploy: | ||||
|     mode: replicated | ||||
|     replicas: 1 | ||||
|     placement: | ||||
|       constraints: [node.role==manager] | ||||
|     restart_policy: | ||||
|       condition: on-failure | ||||
|       max_attempts: 5 | ||||
|     resources: | ||||
|       limits: | ||||
|         cpus: '0.33' | ||||
|         memory: 20M | ||||
|       reservations: | ||||
|         cpus: '0.05' | ||||
|         memory: 10M | ||||
|     labels: | ||||
|       - "traefik.frontend.rule=PathPrefixStrip:/portainer" | ||||
|       - "traefik.backend=portainer" | ||||
|       - "traefik.port=9000" | ||||
|       - "traefik.weight=10" | ||||
|       - "traefik.enable=true" | ||||
|       - "traefik.passHostHeader=true" | ||||
|       - "traefik.docker.network=ntw_front" | ||||
|       - "traefik.frontend.entryPoints=http" | ||||
|       - "traefik.backend.loadbalancer.swarm=true" | ||||
|       - "traefik.backend.loadbalancer.method=drr" | ||||
|       # https://github.com/containous/traefik/issues/563#issuecomment-421360934 | ||||
|       - "traefik.frontend.redirect.regex=^(.*)/portainer$$" | ||||
|       - "traefik.frontend.redirect.replacement=$$1/portainer/" | ||||
|       - "traefik.frontend.rule=PathPrefix:/portainer;ReplacePathRegex: ^/portainer/(.*) /$$1" | ||||
| ``` | ||||
|   | ||||
| @@ -14,7 +14,6 @@ defaultEntryPoints = ["https"] | ||||
| [entryPoints] | ||||
|   [entryPoints.http] | ||||
|   address = ":80" | ||||
|     [entryPoints.http] | ||||
|  | ||||
| [api] | ||||
|  | ||||
|   | ||||
| @@ -4,7 +4,7 @@ This guide explains how to use Traefik as an Ingress controller for a Kubernetes | ||||
|  | ||||
| If you are not familiar with Ingresses in Kubernetes you might want to read the [Kubernetes user guide](https://kubernetes.io/docs/concepts/services-networking/ingress/) | ||||
|  | ||||
| The config files used in this guide can be found in the [examples directory](https://github.com/containous/traefik/tree/master/examples/k8s) | ||||
| The config files used in this guide can be found in the [examples directory](https://github.com/containous/traefik/tree/v1.7/examples/k8s) | ||||
|  | ||||
| ## Prerequisites | ||||
|  | ||||
| @@ -68,10 +68,10 @@ subjects: | ||||
|   namespace: kube-system | ||||
| ``` | ||||
|  | ||||
| [examples/k8s/traefik-rbac.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/traefik-rbac.yaml) | ||||
| [examples/k8s/traefik-rbac.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/traefik-rbac.yaml) | ||||
|  | ||||
| ```shell | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-rbac.yaml | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/traefik-rbac.yaml | ||||
| ``` | ||||
|  | ||||
| For namespaced restrictions, one RoleBinding is required per watched namespace along with a corresponding configuration of Traefik's `kubernetes.namespaces` parameter. | ||||
| @@ -118,7 +118,7 @@ spec: | ||||
|       serviceAccountName: traefik-ingress-controller | ||||
|       terminationGracePeriodSeconds: 60 | ||||
|       containers: | ||||
|       - image: traefik | ||||
|       - image: traefik:v1.7 | ||||
|         name: traefik-ingress-lb | ||||
|         ports: | ||||
|         - name: http | ||||
| @@ -148,7 +148,7 @@ spec: | ||||
|   type: NodePort | ||||
| ``` | ||||
|  | ||||
| [examples/k8s/traefik-deployment.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/traefik-deployment.yaml) | ||||
| [examples/k8s/traefik-deployment.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/traefik-deployment.yaml) | ||||
|  | ||||
| !!! note | ||||
|     The Service will expose two NodePorts which allow access to the ingress and the web interface. | ||||
| @@ -180,7 +180,7 @@ spec: | ||||
|       serviceAccountName: traefik-ingress-controller | ||||
|       terminationGracePeriodSeconds: 60 | ||||
|       containers: | ||||
|       - image: traefik | ||||
|       - image: traefik:v1.7 | ||||
|         name: traefik-ingress-lb | ||||
|         ports: | ||||
|         - name: http | ||||
| @@ -216,7 +216,7 @@ spec: | ||||
|       name: admin | ||||
| ``` | ||||
|  | ||||
| [examples/k8s/traefik-ds.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/traefik-ds.yaml) | ||||
| [examples/k8s/traefik-ds.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/traefik-ds.yaml) | ||||
|  | ||||
| !!! note | ||||
|     This will create a Daemonset that uses privileged ports 80/8080 on the host. This may not work on all providers, but illustrates the static (non-NodePort) hostPort binding. The `traefik-ingress-service` can still be used inside the cluster to access the DaemonSet pods. | ||||
| @@ -224,11 +224,11 @@ spec: | ||||
| To deploy Traefik to your cluster start by submitting one of the YAML files to the cluster with `kubectl`: | ||||
|  | ||||
| ```shell | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-deployment.yaml | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/traefik-deployment.yaml | ||||
| ``` | ||||
|  | ||||
| ```shell | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-ds.yaml | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/traefik-ds.yaml | ||||
| ``` | ||||
|  | ||||
| There are some significant differences between using Deployments and DaemonSets: | ||||
| @@ -352,10 +352,10 @@ spec: | ||||
|           servicePort: web | ||||
| ``` | ||||
|  | ||||
| [examples/k8s/ui.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/ui.yaml) | ||||
| [examples/k8s/ui.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/ui.yaml) | ||||
|  | ||||
| ```shell | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/ui.yaml | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/ui.yaml | ||||
| ``` | ||||
|  | ||||
| Now lets setup an entry in our `/etc/hosts` file to route `traefik-ui.minikube` to our cluster. | ||||
| @@ -375,6 +375,14 @@ We should now be able to visit [traefik-ui.minikube](http://traefik-ui.minikube) | ||||
|     For this example to work you need a TLS entrypoint. You don't have to provide a TLS certificate at this point. | ||||
|     For more details see [here](/configuration/entrypoints/). | ||||
|  | ||||
| You can add a TLS entrypoint by adding the following `args` to the container spec: | ||||
|  | ||||
| ```yaml | ||||
|  --defaultentrypoints=http,https | ||||
|  --entrypoints=Name:https Address::443 TLS | ||||
|  --entrypoints=Name:http Address::80 | ||||
| ``` | ||||
|      | ||||
| To setup an HTTPS-protected ingress, you can leverage the TLS feature of the ingress resource. | ||||
|  | ||||
| ```yaml | ||||
| @@ -573,10 +581,10 @@ spec: | ||||
|         - containerPort: 80 | ||||
| ``` | ||||
|  | ||||
| [examples/k8s/cheese-deployments.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/cheese-deployments.yaml) | ||||
| [examples/k8s/cheese-deployments.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/cheese-deployments.yaml) | ||||
|  | ||||
| ```shell | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-deployments.yaml | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/cheese-deployments.yaml | ||||
| ``` | ||||
|  | ||||
| Next we need to setup a Service for each of the cheese pods. | ||||
| @@ -628,10 +636,10 @@ spec: | ||||
| !!! note | ||||
|     We also set a [circuit breaker expression](/basics/#backends) for one of the backends by setting the `traefik.backend.circuitbreaker` annotation on the service. | ||||
|  | ||||
| [examples/k8s/cheese-services.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/cheese-services.yaml) | ||||
| [examples/k8s/cheese-services.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/cheese-services.yaml) | ||||
|  | ||||
| ```shell | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-services.yaml | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/cheese-services.yaml | ||||
| ``` | ||||
|  | ||||
| Now we can submit an ingress for the cheese websites. | ||||
| @@ -668,13 +676,13 @@ spec: | ||||
|           servicePort: http | ||||
| ``` | ||||
|  | ||||
| [examples/k8s/cheese-ingress.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/cheese-ingress.yaml) | ||||
| [examples/k8s/cheese-ingress.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/cheese-ingress.yaml) | ||||
|  | ||||
| !!! note | ||||
|     we list each hostname, and add a backend service. | ||||
|     We list each hostname, and add a backend service. | ||||
|  | ||||
| ```shell | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-ingress.yaml | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/cheese-ingress.yaml | ||||
| ``` | ||||
|  | ||||
| Now visit the [Traefik dashboard](http://traefik-ui.minikube/) and you should see a frontend for each host. | ||||
| @@ -723,13 +731,13 @@ spec: | ||||
|           servicePort: http | ||||
| ``` | ||||
|  | ||||
| [examples/k8s/cheeses-ingress.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/cheeses-ingress.yaml) | ||||
| [examples/k8s/cheeses-ingress.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/cheeses-ingress.yaml) | ||||
|  | ||||
| !!! note | ||||
|     We are configuring Traefik to strip the prefix from the url path with the `traefik.frontend.rule.type` annotation so that we can use the containers from the previous example without modification. | ||||
|  | ||||
| ```shell | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheeses-ingress.yaml | ||||
| kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/cheeses-ingress.yaml | ||||
| ``` | ||||
|  | ||||
| ```shell | ||||
| @@ -775,11 +783,11 @@ Traefik will now look for cheddar service endpoints (ports on healthy pods) in b | ||||
| Deploying cheddar into the cheese namespace and afterwards shutting down cheddar in the default namespace is enough to migrate the traffic. | ||||
|  | ||||
| !!! note | ||||
|    The kubernetes documentation does not specify this merging behavior. | ||||
|     The kubernetes documentation does not specify this merging behavior. | ||||
|  | ||||
| !!! note | ||||
|    Merging ingress definitions can cause problems if the annotations differ or if the services handle requests differently. | ||||
|    Be careful and extra cautious when running multiple overlapping ingress definitions. | ||||
|     Merging ingress definitions can cause problems if the annotations differ or if the services handle requests differently. | ||||
|     Be careful and extra cautious when running multiple overlapping ingress definitions. | ||||
|  | ||||
| ## Specifying Routing Priorities | ||||
|  | ||||
|   | ||||
| @@ -139,7 +139,7 @@ Here is the [docker-compose file](https://docs.docker.com/compose/compose-file/) | ||||
|  | ||||
| ```yaml | ||||
| traefik: | ||||
|   image: traefik | ||||
|   image: traefik:<stable v1.7 from https://hub.docker.com/_/traefik> | ||||
|   command: --consul --consul.endpoint=127.0.0.1:8500 | ||||
|   ports: | ||||
|     - "80:80" | ||||
|   | ||||
| @@ -7,7 +7,7 @@ The cluster consists of: | ||||
| - 3 servers | ||||
| - 1 manager | ||||
| - 2 workers | ||||
| - 1 [overlay](https://docs.docker.com/engine/userguide/networking/dockernetworks/#an-overlay-network) network (multi-host networking) | ||||
| - 1 [overlay](https://docs.docker.com/network/overlay/) network (multi-host networking) | ||||
|  | ||||
|  | ||||
| ## Prerequisites | ||||
| @@ -76,7 +76,7 @@ docker-machine ssh manager "docker network create --driver=overlay traefik-net" | ||||
| ## Deploy Traefik | ||||
|  | ||||
| Let's deploy Traefik as a docker service in our cluster. | ||||
| The only requirement for Traefik to work with swarm mode is that it needs to run on a manager node - we are going to use a [constraint](https://docs.docker.com/engine/reference/commandline/service_create/#/specify-service-constraints-constraint) for that. | ||||
| The only requirement for Traefik to work with swarm mode is that it needs to run on a manager node - we are going to use a [constraint](https://docs.docker.com/engine/reference/commandline/service_create/#specify-service-constraints---constraint) for that. | ||||
|  | ||||
| ```shell | ||||
| docker-machine ssh manager "docker service create \ | ||||
| @@ -85,7 +85,7 @@ docker-machine ssh manager "docker service create \ | ||||
| 	--publish 80:80 --publish 8080:8080 \ | ||||
| 	--mount	type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \ | ||||
| 	--network traefik-net \ | ||||
| 	traefik \ | ||||
| 	traefik:<stable version from https://hub.docker.com/_/traefik> \ | ||||
| 	--docker \ | ||||
| 	--docker.swarmMode \ | ||||
| 	--docker.domain=traefik \ | ||||
|   | ||||
| @@ -7,7 +7,7 @@ The cluster consists of: | ||||
| - 2 servers | ||||
| - 1 swarm master | ||||
| - 2 swarm nodes | ||||
| - 1 [overlay](https://docs.docker.com/engine/userguide/networking/dockernetworks/#an-overlay-network) network (multi-host networking) | ||||
| - 1 [overlay](https://docs.docker.com/network/overlay/) network (multi-host networking) | ||||
|  | ||||
| ## Prerequisites | ||||
|  | ||||
| @@ -81,7 +81,7 @@ docker $(docker-machine config mhs-demo0) run \ | ||||
|     -p 80:80 -p 8080:8080 \ | ||||
|     --net=my-net \ | ||||
|     -v /var/lib/boot2docker/:/ssl \ | ||||
|     traefik \ | ||||
|     traefik:<stable version from https://hub.docker.com/_/traefik> \ | ||||
|     -l DEBUG \ | ||||
|     -c /dev/null \ | ||||
|     --docker \ | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| traefik: | ||||
|   image: traefik | ||||
|   image: traefik:v1.7 | ||||
|   command: --api --rancher --rancher.domain=rancher.localhost --rancher.endpoint=http://example.com --rancher.accesskey=XXXXXXX --rancher.secretkey=YYYYYY --logLevel=DEBUG | ||||
|   ports: | ||||
|     - "80:80" | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| traefik: | ||||
|   image: traefik | ||||
|   image: traefik:v1.7 | ||||
|   command: -c /dev/null --api --docker --docker.domain=docker.localhost --logLevel=DEBUG | ||||
|   ports: | ||||
|     - "80:80" | ||||
|   | ||||
| @@ -26,7 +26,7 @@ spec: | ||||
|       serviceAccountName: traefik-ingress-controller | ||||
|       terminationGracePeriodSeconds: 60 | ||||
|       containers: | ||||
|       - image: traefik | ||||
|       - image: traefik:v1.7 | ||||
|         name: traefik-ingress-lb | ||||
|         ports: | ||||
|         - name: http | ||||
|   | ||||
| @@ -22,7 +22,7 @@ spec: | ||||
|       serviceAccountName: traefik-ingress-controller | ||||
|       terminationGracePeriodSeconds: 60 | ||||
|       containers: | ||||
|       - image: traefik | ||||
|       - image: traefik:v1.7 | ||||
|         name: traefik-ingress-lb | ||||
|         ports: | ||||
|         - name: http | ||||
|   | ||||
| @@ -22,6 +22,12 @@ rules: | ||||
|       - get | ||||
|       - list | ||||
|       - watch | ||||
|   - apiGroups: | ||||
|     - extensions | ||||
|     resources: | ||||
|     - ingresses/status | ||||
|     verbs: | ||||
|     - update | ||||
| --- | ||||
| kind: ClusterRoleBinding | ||||
| apiVersion: rbac.authorization.k8s.io/v1beta1 | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| In this quickstart, we'll use [Docker compose](https://docs.docker.com/compose) to create our demo infrastructure. | ||||
|  | ||||
| To save some time, you can clone [Traefik's repository](https://github.com/containous/traefik) and use the quickstart files located in the [examples/quickstart](https://github.com/containous/traefik/tree/master/examples/quickstart/) directory. | ||||
| To save some time, you can clone [Traefik's repository](https://github.com/containous/traefik) and use the quickstart files located in the [examples/quickstart](https://github.com/containous/traefik/tree/v1.7/examples/quickstart/) directory. | ||||
|  | ||||
| ### 1 — Launch Traefik — Tell It to Listen to Docker | ||||
|  | ||||
| @@ -13,7 +13,7 @@ version: '3' | ||||
|  | ||||
| services: | ||||
|   reverse-proxy: | ||||
|     image: traefik # The official Traefik docker image | ||||
|     image: traefik:v1.7 # The official Traefik docker image | ||||
|     command: --api --docker # Enables the web UI and tells Traefik to listen to docker | ||||
|     ports: | ||||
|       - "80:80"     # The HTTP port | ||||
| @@ -101,7 +101,7 @@ IP: 172.27.0.4 | ||||
|  | ||||
| ### 4 — Enjoy Traefik's Magic | ||||
|  | ||||
| Now that you have a basic understanding of how Traefik can automatically create the routes to your services and load balance them, it might be time to dive into [the documentation](https://docs.traefik.io/) and let Traefik work for you! | ||||
| Whatever your infrastructure is, there is probably [an available Traefik backend](https://docs.traefik.io/#supported-backends) that will do the job. | ||||
| Now that you have a basic understanding of how Traefik can automatically create the routes to your services and load balance them, it might be time to dive into [the documentation](https://docs.traefik.io/v1.7/) and let Traefik work for you! | ||||
| Whatever your infrastructure is, there is probably [an available Traefik backend](https://docs.traefik.io/v1.7/#supported-backends) that will do the job. | ||||
|  | ||||
| Our recommendation would be to see for yourself how simple it is to enable HTTPS with [Traefik's let's encrypt integration](https://docs.traefik.io/user-guide/examples/#lets-encrypt-support) using the dedicated [user guide](https://docs.traefik.io/user-guide/docker-and-lets-encrypt/). | ||||
| Our recommendation would be to see for yourself how simple it is to enable HTTPS with [Traefik's let's encrypt integration](https://docs.traefik.io/v1.7/user-guide/examples/#lets-encrypt-support) using the dedicated [user guide](https://docs.traefik.io/v1.7/user-guide/docker-and-lets-encrypt/). | ||||
|   | ||||
| @@ -3,7 +3,7 @@ version: '3' | ||||
| services: | ||||
|   # The reverse proxy service (Traefik) | ||||
|   reverse-proxy: | ||||
|     image: traefik  # The official Traefik docker image | ||||
|     image: traefik:v1.7  # The official Traefik docker image | ||||
|     command: --api --docker  # Enables the web UI and tells Traefik to listen to docker | ||||
|     ports: | ||||
|       - "80:80"      # The HTTP port | ||||
| @@ -13,6 +13,6 @@ services: | ||||
|  | ||||
|   # A container that exposes a simple API | ||||
|   whoami: | ||||
|     image: emilevauge/whoami  # A container that exposes an API to show it's IP address | ||||
|     image: emilevauge/whoami  # A container that exposes an API to show its IP address | ||||
|     labels: | ||||
|       - "traefik.frontend.rule=Host:whoami.docker.localhost" | ||||
|   | ||||
							
								
								
									
										44
									
								
								exp.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								exp.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| # WEBUI | ||||
| FROM node:8.15.0 as webui | ||||
|  | ||||
| ENV WEBUI_DIR /src/webui | ||||
| RUN mkdir -p $WEBUI_DIR | ||||
|  | ||||
| COPY ./webui/ $WEBUI_DIR/ | ||||
|  | ||||
| WORKDIR $WEBUI_DIR | ||||
| RUN yarn install | ||||
|  | ||||
| RUN npm run build | ||||
|  | ||||
| # BUILD | ||||
| FROM golang:1.12-alpine as gobuild | ||||
|  | ||||
| RUN apk --update upgrade \ | ||||
|     && apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \ | ||||
|     && update-ca-certificates \ | ||||
|     && rm -rf /var/cache/apk/* | ||||
|  | ||||
| RUN mkdir -p /usr/local/bin \ | ||||
|     && curl -fsSL -o /usr/local/bin/go-bindata https://github.com/containous/go-bindata/releases/download/v1.0.0/go-bindata \ | ||||
|     && chmod +x /usr/local/bin/go-bindata | ||||
|  | ||||
| WORKDIR /go/src/github.com/containous/traefik | ||||
| COPY . /go/src/github.com/containous/traefik | ||||
|  | ||||
| RUN rm -rf /go/src/github.com/containous/traefik/static/ | ||||
| COPY --from=webui /src/static/ /go/src/github.com/containous/traefik/static/ | ||||
|  | ||||
| RUN ./script/make.sh generate binary | ||||
|  | ||||
| ## IMAGE | ||||
| FROM scratch | ||||
|  | ||||
| COPY --from=gobuild /usr/share/zoneinfo /usr/share/zoneinfo | ||||
| COPY --from=gobuild /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ | ||||
| COPY --from=gobuild /go/src/github.com/containous/traefik/dist/traefik / | ||||
|  | ||||
| EXPOSE 80 | ||||
| VOLUME ["/tmp"] | ||||
|  | ||||
| ENTRYPOINT ["/traefik"] | ||||
| @@ -49,17 +49,24 @@ func (opt Options) String() string { | ||||
| 	return fmt.Sprintf("[Hostname: %s Headers: %v Path: %s Port: %d Interval: %s]", opt.Hostname, opt.Headers, opt.Path, opt.Port, opt.Interval) | ||||
| } | ||||
|  | ||||
| type backendURL struct { | ||||
| 	url    *url.URL | ||||
| 	weight int | ||||
| } | ||||
|  | ||||
| // BackendConfig HealthCheck configuration for a backend | ||||
| type BackendConfig struct { | ||||
| 	Options | ||||
| 	name           string | ||||
| 	disabledURLs   []*url.URL | ||||
| 	disabledURLs   []backendURL | ||||
| 	requestTimeout time.Duration | ||||
| } | ||||
|  | ||||
| func (b *BackendConfig) newRequest(serverURL *url.URL) (*http.Request, error) { | ||||
| 	u := &url.URL{} | ||||
| 	*u = *serverURL | ||||
| 	u, err := serverURL.Parse(b.Path) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if len(b.Scheme) > 0 { | ||||
| 		u.Scheme = b.Scheme | ||||
| @@ -69,8 +76,6 @@ func (b *BackendConfig) newRequest(serverURL *url.URL) (*http.Request, error) { | ||||
| 		u.Host = net.JoinHostPort(u.Hostname(), strconv.Itoa(b.Port)) | ||||
| 	} | ||||
|  | ||||
| 	u.Path += b.Path | ||||
|  | ||||
| 	return http.NewRequest(http.MethodGet, u.String(), http.NoBody) | ||||
| } | ||||
|  | ||||
| @@ -129,18 +134,18 @@ func (hc *HealthCheck) execute(ctx context.Context, backend *BackendConfig) { | ||||
|  | ||||
| func (hc *HealthCheck) checkBackend(backend *BackendConfig) { | ||||
| 	enabledURLs := backend.LB.Servers() | ||||
| 	var newDisabledURLs []*url.URL | ||||
| 	for _, url := range backend.disabledURLs { | ||||
| 	var newDisabledURLs []backendURL | ||||
| 	for _, backendurl := range backend.disabledURLs { | ||||
| 		serverUpMetricValue := float64(0) | ||||
| 		if err := checkHealth(url, backend); err == nil { | ||||
| 			log.Warnf("Health check up: Returning to server list. Backend: %q URL: %q", backend.name, url.String()) | ||||
| 			backend.LB.UpsertServer(url, roundrobin.Weight(1)) | ||||
| 		if err := checkHealth(backendurl.url, backend); err == nil { | ||||
| 			log.Warnf("Health check up: Returning to server list. Backend: %q URL: %q Weight: %d", backend.name, backendurl.url.String(), backendurl.weight) | ||||
| 			backend.LB.UpsertServer(backendurl.url, roundrobin.Weight(backendurl.weight)) | ||||
| 			serverUpMetricValue = 1 | ||||
| 		} else { | ||||
| 			log.Warnf("Health check still failing. Backend: %q URL: %q Reason: %s", backend.name, url.String(), err) | ||||
| 			newDisabledURLs = append(newDisabledURLs, url) | ||||
| 			log.Warnf("Health check still failing. Backend: %q URL: %q Reason: %s", backend.name, backendurl.url.String(), err) | ||||
| 			newDisabledURLs = append(newDisabledURLs, backendurl) | ||||
| 		} | ||||
| 		labelValues := []string{"backend", backend.name, "url", url.String()} | ||||
| 		labelValues := []string{"backend", backend.name, "url", backendurl.url.String()} | ||||
| 		hc.metrics.BackendServerUpGauge().With(labelValues...).Set(serverUpMetricValue) | ||||
| 	} | ||||
| 	backend.disabledURLs = newDisabledURLs | ||||
| @@ -148,9 +153,18 @@ func (hc *HealthCheck) checkBackend(backend *BackendConfig) { | ||||
| 	for _, url := range enabledURLs { | ||||
| 		serverUpMetricValue := float64(1) | ||||
| 		if err := checkHealth(url, backend); err != nil { | ||||
| 			log.Warnf("Health check failed: Remove from server list. Backend: %q URL: %q Reason: %s", backend.name, url.String(), err) | ||||
| 			weight := 1 | ||||
| 			rr, ok := backend.LB.(*roundrobin.RoundRobin) | ||||
| 			if ok { | ||||
| 				var gotWeight bool | ||||
| 				weight, gotWeight = rr.ServerWeight(url) | ||||
| 				if !gotWeight { | ||||
| 					weight = 1 | ||||
| 				} | ||||
| 			} | ||||
| 			log.Warnf("Health check failed: Remove from server list. Backend: %q URL: %q Weight: %d Reason: %s", backend.name, url.String(), weight, err) | ||||
| 			backend.LB.RemoveServer(url) | ||||
| 			backend.disabledURLs = append(backend.disabledURLs, url) | ||||
| 			backend.disabledURLs = append(backend.disabledURLs, backendURL{url, weight}) | ||||
| 			serverUpMetricValue = 0 | ||||
| 		} | ||||
| 		labelValues := []string{"backend", backend.name, "url", url.String()} | ||||
|   | ||||
| @@ -112,7 +112,7 @@ func TestSetBackendsConfiguration(t *testing.T) { | ||||
| 			if test.startHealthy { | ||||
| 				lb.servers = append(lb.servers, serverURL) | ||||
| 			} else { | ||||
| 				backend.disabledURLs = append(backend.disabledURLs, serverURL) | ||||
| 				backend.disabledURLs = append(backend.disabledURLs, backendURL{serverURL, 1}) | ||||
| 			} | ||||
|  | ||||
| 			collectingMetrics := testhelpers.NewCollectingHealthCheckMetrics() | ||||
| @@ -150,11 +150,16 @@ func TestSetBackendsConfiguration(t *testing.T) { | ||||
| } | ||||
|  | ||||
| func TestNewRequest(t *testing.T) { | ||||
| 	type expected struct { | ||||
| 		err   bool | ||||
| 		value string | ||||
| 	} | ||||
|  | ||||
| 	testCases := []struct { | ||||
| 		desc      string | ||||
| 		serverURL string | ||||
| 		options   Options | ||||
| 		expected  string | ||||
| 		expected  expected | ||||
| 	}{ | ||||
| 		{ | ||||
| 			desc:      "no port override", | ||||
| @@ -163,7 +168,10 @@ func TestNewRequest(t *testing.T) { | ||||
| 				Path: "/test", | ||||
| 				Port: 0, | ||||
| 			}, | ||||
| 			expected: "http://backend1:80/test", | ||||
| 			expected: expected{ | ||||
| 				err:   false, | ||||
| 				value: "http://backend1:80/test", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc:      "port override", | ||||
| @@ -172,7 +180,10 @@ func TestNewRequest(t *testing.T) { | ||||
| 				Path: "/test", | ||||
| 				Port: 8080, | ||||
| 			}, | ||||
| 			expected: "http://backend2:8080/test", | ||||
| 			expected: expected{ | ||||
| 				err:   false, | ||||
| 				value: "http://backend2:8080/test", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc:      "no port override with no port in server URL", | ||||
| @@ -181,7 +192,10 @@ func TestNewRequest(t *testing.T) { | ||||
| 				Path: "/health", | ||||
| 				Port: 0, | ||||
| 			}, | ||||
| 			expected: "http://backend1/health", | ||||
| 			expected: expected{ | ||||
| 				err:   false, | ||||
| 				value: "http://backend1/health", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc:      "port override with no port in server URL", | ||||
| @@ -190,7 +204,10 @@ func TestNewRequest(t *testing.T) { | ||||
| 				Path: "/health", | ||||
| 				Port: 8080, | ||||
| 			}, | ||||
| 			expected: "http://backend2:8080/health", | ||||
| 			expected: expected{ | ||||
| 				err:   false, | ||||
| 				value: "http://backend2:8080/health", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc:      "scheme override", | ||||
| @@ -200,7 +217,46 @@ func TestNewRequest(t *testing.T) { | ||||
| 				Path:   "/test", | ||||
| 				Port:   0, | ||||
| 			}, | ||||
| 			expected: "http://backend1:80/test", | ||||
| 			expected: expected{ | ||||
| 				err:   false, | ||||
| 				value: "http://backend1:80/test", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc:      "path with param", | ||||
| 			serverURL: "http://backend1:80", | ||||
| 			options: Options{ | ||||
| 				Path: "/health?powpow=do", | ||||
| 				Port: 0, | ||||
| 			}, | ||||
| 			expected: expected{ | ||||
| 				err:   false, | ||||
| 				value: "http://backend1:80/health?powpow=do", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc:      "path with params", | ||||
| 			serverURL: "http://backend1:80", | ||||
| 			options: Options{ | ||||
| 				Path: "/health?powpow=do&do=powpow", | ||||
| 				Port: 0, | ||||
| 			}, | ||||
| 			expected: expected{ | ||||
| 				err:   false, | ||||
| 				value: "http://backend1:80/health?powpow=do&do=powpow", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc:      "path with invalid path", | ||||
| 			serverURL: "http://backend1:80", | ||||
| 			options: Options{ | ||||
| 				Path: ":", | ||||
| 				Port: 0, | ||||
| 			}, | ||||
| 			expected: expected{ | ||||
| 				err:   true, | ||||
| 				value: "", | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| @@ -211,13 +267,18 @@ func TestNewRequest(t *testing.T) { | ||||
|  | ||||
| 			backend := NewBackendConfig(test.options, "backendName") | ||||
|  | ||||
| 			u, err := url.Parse(test.serverURL) | ||||
| 			require.NoError(t, err) | ||||
| 			u := testhelpers.MustParseURL(test.serverURL) | ||||
|  | ||||
| 			req, err := backend.newRequest(u) | ||||
| 			require.NoError(t, err, "failed to create new backend request") | ||||
|  | ||||
| 			assert.Equal(t, test.expected, req.URL.String()) | ||||
| 			if test.expected.err { | ||||
| 				require.Error(t, err) | ||||
| 				assert.Nil(t, nil) | ||||
| 			} else { | ||||
| 				require.NoError(t, err, "failed to create new backend request") | ||||
| 				require.NotNil(t, req) | ||||
| 				assert.Equal(t, test.expected.value, req.URL.String()) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -10,7 +10,7 @@ import ( | ||||
|  | ||||
| 	"github.com/abronan/valkeyrie" | ||||
| 	"github.com/abronan/valkeyrie/store" | ||||
| 	"github.com/abronan/valkeyrie/store/etcd/v3" | ||||
| 	etcdv3 "github.com/abronan/valkeyrie/store/etcd/v3" | ||||
| 	"github.com/containous/traefik/integration/try" | ||||
| 	"github.com/go-check/check" | ||||
|  | ||||
|   | ||||
							
								
								
									
										31
									
								
								integration/fixtures/grpc/config_retry.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								integration/fixtures/grpc/config_retry.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| defaultEntryPoints = ["https"] | ||||
|  | ||||
| rootCAs = [ """{{ .CertContent }}""" ] | ||||
|  | ||||
| [retry] | ||||
|  | ||||
| [entryPoints] | ||||
|   [entryPoints.https] | ||||
|   address = ":4443" | ||||
|     [entryPoints.https.tls] | ||||
|      [[entryPoints.https.tls.certificates]] | ||||
|      certFile = """{{ .CertContent }}""" | ||||
|      keyFile  = """{{ .KeyContent }}""" | ||||
|  | ||||
|  | ||||
| [api] | ||||
|  | ||||
| [file] | ||||
|  | ||||
| [backends] | ||||
|   [backends.backend1] | ||||
|     [backends.backend1.servers.server1] | ||||
|     url = "https://127.0.0.1:{{ .GRPCServerPort }}" | ||||
|     weight = 1 | ||||
|  | ||||
|  | ||||
| [frontends] | ||||
|   [frontends.frontend1] | ||||
|   backend = "backend1" | ||||
|     [frontends.frontend1.routes.test_1] | ||||
|     rule = "Host:127.0.0.1" | ||||
| @@ -0,0 +1,37 @@ | ||||
| logLevel = "DEBUG" | ||||
|  | ||||
| defaultEntryPoints = ["https"] | ||||
|  | ||||
| [entryPoints] | ||||
|   [entryPoints.https] | ||||
|   address = ":4443" | ||||
|     [entryPoints.https.tls] | ||||
|      [entryPoints.https.tls.defaultCertificate] | ||||
|      certFile = "fixtures/https/wildcard.snitest.com.cert" | ||||
|      keyFile = "fixtures/https/wildcard.snitest.com.key" | ||||
|  | ||||
| [api] | ||||
|  | ||||
| [file] | ||||
|  | ||||
| [backends] | ||||
|   [backends.backend1] | ||||
|     [backends.backend1.servers.server1] | ||||
|     url = "http://127.0.0.1:9010" | ||||
|     weight = 1 | ||||
|  | ||||
| [frontends] | ||||
|   [frontends.frontend1] | ||||
|   backend = "backend1" | ||||
|     [frontends.frontend1.routes.test_1] | ||||
|     rule = "HostRegexp: {subdomain:[a-z1-9-]+}.snitest.com" | ||||
|   [frontends.frontend2] | ||||
|   backend = "backend1" | ||||
|     [frontends.frontend2.routes.test_1] | ||||
|     rule = "HostRegexp: {subdomain:[a-z1-9-]+}.www.snitest.com" | ||||
|  | ||||
| [[tls]] | ||||
|   entryPoints = ["https"] | ||||
|   [tls.certificate] | ||||
|     certFile = "fixtures/https/uppercase_wildcard.www.snitest.com.cert" | ||||
|     keyFile = "fixtures/https/uppercase_wildcard.www.snitest.com.key" | ||||
| @@ -0,0 +1,34 @@ | ||||
| logLevel = "DEBUG" | ||||
|  | ||||
| defaultEntryPoints = ["https"] | ||||
|  | ||||
| [entryPoints] | ||||
|   [entryPoints.https] | ||||
|   address = ":4443" | ||||
|     [entryPoints.https.tls] | ||||
|      [[entryPoints.https.tls.certificates]] | ||||
|      certFile = "fixtures/https/uppercase_wildcard.www.snitest.com.cert" | ||||
|      keyFile = "fixtures/https/uppercase_wildcard.www.snitest.com.key" | ||||
|      [entryPoints.https.tls.defaultCertificate] | ||||
|      certFile = "fixtures/https/wildcard.snitest.com.cert" | ||||
|      keyFile = "fixtures/https/wildcard.snitest.com.key" | ||||
|  | ||||
| [api] | ||||
|  | ||||
| [file] | ||||
|  | ||||
| [backends] | ||||
|   [backends.backend1] | ||||
|     [backends.backend1.servers.server1] | ||||
|     url = "http://127.0.0.1:9010" | ||||
|     weight = 1 | ||||
|  | ||||
| [frontends] | ||||
|   [frontends.frontend1] | ||||
|   backend = "backend1" | ||||
|     [frontends.frontend1.routes.test_1] | ||||
|     rule = "HostRegexp: {subdomain:[a-z1-9-]+}.snitest.com" | ||||
|   [frontends.frontend2] | ||||
|   backend = "backend1" | ||||
|     [frontends.frontend2.routes.test_2] | ||||
|     rule = "HostRegexp: {subdomain:[a-z1-9-]+}.www.snitest.com" | ||||
| @@ -0,0 +1,19 @@ | ||||
| -----BEGIN CERTIFICATE----- | ||||
| MIIDDDCCAfSgAwIBAgIJAI1YpPACcsQnMA0GCSqGSIb3DQEBCwUAMB4xHDAaBgNV | ||||
| BAMME0ZPTy5XV1cuU05JVEVTVC5DT00wHhcNMTgxMDI5MTU1NDI4WhcNMjgxMDI2 | ||||
| MTU1NDI4WjAeMRwwGgYDVQQDDBNGT08uV1dXLlNOSVRFU1QuQ09NMIIBIjANBgkq | ||||
| hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxyWr+1O/tf4yjwhfp3/SDGT5fD0chhGs | ||||
| Qc+QM7Ewb5SOmIL5UskxT5pCKc6Kuie5qqEp9xH8Rrfo18iEJQPdhFC1YkaBEI0L | ||||
| l1qvN4jmXzAK/E/u4+X+FFprHyruXCmuXqsWQt/qEOqU1ciN47GE9+ZW4R+q70uB | ||||
| zrEQ+dzN7IBsyf1lzzS3/TwDgj085QmiZYxKxX40d5hZW6AHxPEKJa2p+Gweqg74 | ||||
| SpzBWL1DYQLcqHUuMKlbigHg+gleqcO8NiHT5UdeSPVokD5VJPO1La1PMqkLmJYr | ||||
| 3vVkQ9YzNQ615bX98VMIi17cmE7LE+vz+v287cdFT2f1pNXr3pCGzQIDAQABo00w | ||||
| SzALBgNVHQ8EBAMCBDAwCQYDVR0TBAIwADATBgNVHSUEDDAKBggrBgEFBQcDATAc | ||||
| BgNVHREEFTATghEqLldXVy5TTklURVNULkNPTTANBgkqhkiG9w0BAQsFAAOCAQEA | ||||
| HJyMCj9oHwECmSGWHnYHkO42zeyj24RKlhNG5skUCqZmpmeDc2BRMYH4fjP75MD2 | ||||
| kuasZBMAxyQnur/DEn8TzQ1mlKxYCqoza1ql5PkfcwNUp/tvQ7Jhf45Z5mQVeUM7 | ||||
| RSiBhpeetjHY5/xQb7gXHa97+OjDoRJ6NL/dzGxqypf37kiQPw2jWI5RTFBkP+h/ | ||||
| sPbeAZJjmiEzvw31SAw9IGj3VvIwcuTxbsdJQITU7hCXDSd1EIocmzAoobY7WRcT | ||||
| B1pLmHlP/BaIsM7m0NF/HgUsgo/kgSsxnGA2MHMYQiTImR2DUgrJYzKlJ5acscLK | ||||
| sMq9xUnjr6KF1C15R2FpDw== | ||||
| -----END CERTIFICATE----- | ||||
| @@ -0,0 +1,28 @@ | ||||
| -----BEGIN PRIVATE KEY----- | ||||
| MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDHJav7U7+1/jKP | ||||
| CF+nf9IMZPl8PRyGEaxBz5AzsTBvlI6YgvlSyTFPmkIpzoq6J7mqoSn3EfxGt+jX | ||||
| yIQlA92EULViRoEQjQuXWq83iOZfMAr8T+7j5f4UWmsfKu5cKa5eqxZC3+oQ6pTV | ||||
| yI3jsYT35lbhH6rvS4HOsRD53M3sgGzJ/WXPNLf9PAOCPTzlCaJljErFfjR3mFlb | ||||
| oAfE8Qolran4bB6qDvhKnMFYvUNhAtyodS4wqVuKAeD6CV6pw7w2IdPlR15I9WiQ | ||||
| PlUk87UtrU8yqQuYlive9WRD1jM1DrXltf3xUwiLXtyYTssT6/P6/bztx0VPZ/Wk | ||||
| 1evekIbNAgMBAAECggEAVOFEnTmD47D1oasjAgRj5a5/+6kcaDROJDqwrqeeCmDa | ||||
| KjzgwZ1JLDGGc8U5scBOzWAlv83lpcqrLpWjZRdxqfywYrPEPOaxAxC+z7/E2Ntk | ||||
| Q0hafL5BfjFPqRgmQhft3yGyukwvuogRadEyUNMP5o1BiHBz7cxUBmHH54dqKZuO | ||||
| ueUMgqraJX/GK+Om2rIUst0oOT9yUED+f6ciIjVAmCx1EVxZmX7sxKig10e70eOJ | ||||
| rfHlRguJWtxy0+Wl8R8TVrpI5r7qsE8y2fet9RqFOof/4ds8uA2nlZ3NpGkAq3Oo | ||||
| +65h/2fjD5uQ7jmT+XZcbC7SGhboV42zIrmn0DyNIQKBgQDneeqzMlooNzLD6x+v | ||||
| bXo6BJAHXuml440zS5i5RawKc3+/GxGQjBvnfhFH6AQ7cL4ohYyfuAo4srgifRle | ||||
| x3Gl8yvFf0uLaQHj811HPWV0fU8bwekI77jmH7WZi2ED/qX7X06R2vvUPGshvJi5 | ||||
| yPCmJpDQQA6wmxBG1U4SqNw0xQKBgQDcPu2DMAJpbMWWeb5xWv5/6h6TUF4tV7fV | ||||
| eIBWuVfe9Jry3gAnb6YUOKYmA5xYJJ+fTz4Nhe4+LQbFS1esT/7ZIATvILogZc3S | ||||
| X9+ZCYG/tmDDZvhZqIWWSzzdrjb7dseP1RI4Wp6OnRqHWErrkfzDJKuN15qgW5vR | ||||
| FUR2ykV6aQKBgQCv5ZQ00dly3+ciu+QbAb00o0zzXOt91Lnytcp7V3dRhc0YYrBp | ||||
| QB7gPYtSMfwtUxIdZsaihE64IQ8NnjSOMk6pRW0Iqh+083mtR7ylKwGSkLpxpFu6 | ||||
| H7hInuX3pNN3HqXwq87fxSFCeRsLyu3fl9NO3tWCenrvNxYaTXMDeO/E5QKBgE7D | ||||
| XlMU/zfOg1bN0PJe1TbPdgG+sv9KKF76CgN5otgD58nE5I812VHP9HMRxX6sEj15 | ||||
| rDpP1CR+G7bAu+jObtgdIEaYEJf3cES0rpTfFnyF71LR5yzBHIzj+S9Z1yXUk4d3 | ||||
| bl2i4qMjwdH3HEvkWF09JvDB0vVX7YA3N9W3fmNJAoGBALRi9EbkEBW1vMPwMzps | ||||
| YoJ1lp/YyDGTFcg6KFgTfNaOYccb6EXL2Cd21qvDsJw6wthXS+cSqX3qlTLAVLY8 | ||||
| az/NfyFmW1fUtGjs2s0ZtplStGBhv8VR+2fpt9fgDOOrGYiN2dtmPm7jCAmyQQq7 | ||||
| JCg7Vq6f0q95DUwiUAo24CBn | ||||
| -----END PRIVATE KEY----- | ||||
| @@ -417,3 +417,45 @@ func (s *GRPCSuite) TestGRPCBufferWithFlushInterval(c *check.C) { | ||||
| 	}) | ||||
| 	c.Assert(err, check.IsNil) | ||||
| } | ||||
|  | ||||
| func (s *GRPCSuite) TestGRPCWithRetry(c *check.C) { | ||||
| 	lis, err := net.Listen("tcp", ":0") | ||||
| 	_, port, err := net.SplitHostPort(lis.Addr().String()) | ||||
| 	c.Assert(err, check.IsNil) | ||||
|  | ||||
| 	go func() { | ||||
| 		err := startGRPCServer(lis, &myserver{}) | ||||
| 		c.Log(err) | ||||
| 		c.Assert(err, check.IsNil) | ||||
| 	}() | ||||
|  | ||||
| 	file := s.adaptFile(c, "fixtures/grpc/config_retry.toml", struct { | ||||
| 		CertContent    string | ||||
| 		KeyContent     string | ||||
| 		GRPCServerPort string | ||||
| 	}{ | ||||
| 		CertContent:    string(LocalhostCert), | ||||
| 		KeyContent:     string(LocalhostKey), | ||||
| 		GRPCServerPort: port, | ||||
| 	}) | ||||
|  | ||||
| 	defer os.Remove(file) | ||||
| 	cmd, display := s.traefikCmd(withConfigFile(file)) | ||||
| 	defer display(c) | ||||
|  | ||||
| 	err = cmd.Start() | ||||
| 	c.Assert(err, check.IsNil) | ||||
| 	defer cmd.Process.Kill() | ||||
|  | ||||
| 	// wait for Traefik | ||||
| 	err = try.GetRequest("http://127.0.0.1:8080/api/providers", 1*time.Second, try.BodyContains("Host:127.0.0.1")) | ||||
| 	c.Assert(err, check.IsNil) | ||||
|  | ||||
| 	var response string | ||||
| 	err = try.Do(1*time.Second, func() error { | ||||
| 		response, err = callHelloClientGRPC("World", true) | ||||
| 		return err | ||||
| 	}) | ||||
| 	c.Assert(err, check.IsNil) | ||||
| 	c.Assert(response, check.Equals, "Hello World") | ||||
| } | ||||
|   | ||||
| @@ -830,3 +830,71 @@ func (s *HTTPSSuite) TestEntrypointHttpsRedirectAndPathModification(c *check.C) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // TestWithSNIStaticCaseInsensitive involves a client sending a SNI hostname of | ||||
| // "bar.www.snitest.com", which matches the DNS SAN of '*.WWW.SNITEST.COM'. The test | ||||
| // verifies that traefik presents the correct certificate. | ||||
| func (s *HTTPSSuite) TestWithSNIStaticCaseInsensitive(c *check.C) { | ||||
| 	cmd, display := s.traefikCmd(withConfigFile("fixtures/https/https_sni_case_insensitive_static.toml")) | ||||
| 	defer display(c) | ||||
| 	err := cmd.Start() | ||||
| 	c.Assert(err, checker.IsNil) | ||||
| 	defer cmd.Process.Kill() | ||||
|  | ||||
| 	// wait for Traefik | ||||
| 	err = try.GetRequest("http://127.0.0.1:8080/api/providers", 500*time.Millisecond, try.BodyContains("HostRegexp: {subdomain:[a-z1-9-]+}.www.snitest.com")) | ||||
| 	c.Assert(err, checker.IsNil) | ||||
|  | ||||
| 	tlsConfig := &tls.Config{ | ||||
| 		InsecureSkipVerify: true, | ||||
| 		ServerName:         "bar.www.snitest.com", | ||||
| 		NextProtos:         []string{"h2", "http/1.1"}, | ||||
| 	} | ||||
| 	conn, err := tls.Dial("tcp", "127.0.0.1:4443", tlsConfig) | ||||
| 	c.Assert(err, checker.IsNil, check.Commentf("failed to connect to server")) | ||||
|  | ||||
| 	defer conn.Close() | ||||
| 	err = conn.Handshake() | ||||
| 	c.Assert(err, checker.IsNil, check.Commentf("TLS handshake error")) | ||||
|  | ||||
| 	cs := conn.ConnectionState() | ||||
| 	err = cs.PeerCertificates[0].VerifyHostname("*.WWW.SNITEST.COM") | ||||
| 	c.Assert(err, checker.IsNil, check.Commentf("certificate did not match SNI servername")) | ||||
|  | ||||
| 	proto := conn.ConnectionState().NegotiatedProtocol | ||||
| 	c.Assert(proto, checker.Equals, "h2") | ||||
| } | ||||
|  | ||||
| // TestWithSNIDynamicCaseInsensitive involves a client sending a SNI hostname of | ||||
| // "bar.www.snitest.com", which matches the DNS SAN of '*.WWW.SNITEST.COM'. The test | ||||
| // verifies that traefik presents the correct certificate. | ||||
| func (s *HTTPSSuite) TestWithSNIDynamicCaseInsensitive(c *check.C) { | ||||
| 	cmd, display := s.traefikCmd(withConfigFile("fixtures/https/https_sni_case_insensitive_dynamic.toml")) | ||||
| 	defer display(c) | ||||
| 	err := cmd.Start() | ||||
| 	c.Assert(err, checker.IsNil) | ||||
| 	defer cmd.Process.Kill() | ||||
|  | ||||
| 	// wait for Traefik | ||||
| 	err = try.GetRequest("http://127.0.0.1:8080/api/providers", 500*time.Millisecond, try.BodyContains("HostRegexp: {subdomain:[a-z1-9-]+}.www.snitest.com")) | ||||
| 	c.Assert(err, checker.IsNil) | ||||
|  | ||||
| 	tlsConfig := &tls.Config{ | ||||
| 		InsecureSkipVerify: true, | ||||
| 		ServerName:         "bar.www.snitest.com", | ||||
| 		NextProtos:         []string{"h2", "http/1.1"}, | ||||
| 	} | ||||
| 	conn, err := tls.Dial("tcp", "127.0.0.1:4443", tlsConfig) | ||||
| 	c.Assert(err, checker.IsNil, check.Commentf("failed to connect to server")) | ||||
|  | ||||
| 	defer conn.Close() | ||||
| 	err = conn.Handshake() | ||||
| 	c.Assert(err, checker.IsNil, check.Commentf("TLS handshake error")) | ||||
|  | ||||
| 	cs := conn.ConnectionState() | ||||
| 	err = cs.PeerCertificates[0].VerifyHostname("*.WWW.SNITEST.COM") | ||||
| 	c.Assert(err, checker.IsNil, check.Commentf("certificate did not match SNI servername")) | ||||
|  | ||||
| 	proto := conn.ConnectionState().NegotiatedProtocol | ||||
| 	c.Assert(proto, checker.Equals, "h2") | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,8 @@ | ||||
| consul: | ||||
|   image: consul | ||||
|   # use v1.4.0 because https://github.com/hashicorp/consul/issues/5270 | ||||
|   # v1.4.1 cannot be used. | ||||
|   # waiting for v1.4.2 | ||||
|   image: consul:1.4.0 | ||||
|   command: agent -server -bootstrap-expect 1 -client 0.0.0.0 -log-level debug -ui | ||||
|   ports: | ||||
|     - "8400:8400" | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| pebble: | ||||
|   image: letsencrypt/pebble:2018-07-27 | ||||
|   image: letsencrypt/pebble:v2.0.1 | ||||
|   command: pebble --dnsserver ${DOCKER_HOST_IP}:5053 | ||||
|   ports: | ||||
|     - 14000:14000 | ||||
|   | ||||
| @@ -1,7 +1,5 @@ | ||||
| zipkin: | ||||
|   # Fix zipkin version 2.4.2 | ||||
|   # due to a bug in latest version https://github.com/openzipkin/zipkin/releases/tag/2.4.4 | ||||
|   image: openzipkin/zipkin:2.4.2 | ||||
|   image: openzipkin/zipkin:2.12.6 | ||||
|   environment: | ||||
|     STORAGE_TYPE: mem | ||||
|     JAVA_OPTS: -Dlogging.level.zipkin=DEBUG | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package integration | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"time" | ||||
| @@ -38,6 +39,10 @@ func (s *TimeoutSuite) TestForwardingTimeouts(c *check.C) { | ||||
| 	c.Assert(err, checker.IsNil) | ||||
| 	c.Assert(response.StatusCode, checker.Equals, http.StatusGatewayTimeout) | ||||
|  | ||||
| 	// Check that timeout service is available | ||||
| 	statusURL := fmt.Sprintf("http://%s:9000/statusTest?status=200", httpTimeoutEndpoint) | ||||
| 	c.Assert(try.GetRequest(statusURL, 60*time.Second, try.StatusCodeIs(http.StatusOK)), checker.IsNil) | ||||
|  | ||||
| 	// This simulates a ResponseHeaderTimeout. | ||||
| 	response, err = http.Get("http://127.0.0.1:8000/responseHeaderTimeout?sleep=1000") | ||||
| 	c.Assert(err, checker.IsNil) | ||||
|   | ||||
| @@ -3,6 +3,7 @@ package accesslog | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| @@ -32,6 +33,19 @@ const ( | ||||
| 	JSONFormat = "json" | ||||
| ) | ||||
|  | ||||
| type noopCloser struct { | ||||
| 	*os.File | ||||
| } | ||||
|  | ||||
| func (n noopCloser) Write(p []byte) (int, error) { | ||||
| 	return n.File.Write(p) | ||||
| } | ||||
|  | ||||
| func (n noopCloser) Close() error { | ||||
| 	// noop | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type logHandlerParams struct { | ||||
| 	logDataTable *LogData | ||||
| 	crr          *captureRequestReader | ||||
| @@ -42,7 +56,7 @@ type logHandlerParams struct { | ||||
| type LogHandler struct { | ||||
| 	config         *types.AccessLog | ||||
| 	logger         *logrus.Logger | ||||
| 	file           *os.File | ||||
| 	file           io.WriteCloser | ||||
| 	mu             sync.Mutex | ||||
| 	httpCodeRanges types.HTTPCodeRanges | ||||
| 	logHandlerChan chan logHandlerParams | ||||
| @@ -51,7 +65,7 @@ type LogHandler struct { | ||||
|  | ||||
| // NewLogHandler creates a new LogHandler | ||||
| func NewLogHandler(config *types.AccessLog) (*LogHandler, error) { | ||||
| 	file := os.Stdout | ||||
| 	var file io.WriteCloser = noopCloser{os.Stdout} | ||||
| 	if len(config.FilePath) > 0 { | ||||
| 		f, err := openAccessLogFile(config.FilePath) | ||||
| 		if err != nil { | ||||
| @@ -205,14 +219,15 @@ func (l *LogHandler) Close() error { | ||||
| // Rotate closes and reopens the log file to allow for rotation | ||||
| // by an external source. | ||||
| func (l *LogHandler) Rotate() error { | ||||
| 	var err error | ||||
|  | ||||
| 	if l.file != nil { | ||||
| 		defer func(f *os.File) { | ||||
| 			f.Close() | ||||
| 		}(l.file) | ||||
| 	if l.config.FilePath == "" { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if l.file != nil { | ||||
| 		defer func(f io.Closer) { _ = f.Close() }(l.file) | ||||
| 	} | ||||
|  | ||||
| 	var err error | ||||
| 	l.file, err = os.OpenFile(l.config.FilePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0664) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
|   | ||||
| @@ -24,6 +24,8 @@ func (f *CommonLogFormatter) Format(entry *logrus.Entry) ([]byte, error) { | ||||
| 	var timestamp = defaultValue | ||||
| 	if v, ok := entry.Data[StartUTC]; ok { | ||||
| 		timestamp = v.(time.Time).Format(commonLogTimeFormat) | ||||
| 	} else if v, ok := entry.Data[StartLocal]; ok { | ||||
| 		timestamp = v.(time.Time).Local().Format(commonLogTimeFormat) | ||||
| 	} | ||||
|  | ||||
| 	var elapsedMillis int64 | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package accesslog | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| @@ -57,10 +58,34 @@ func TestCommonLogFormatter_Format(t *testing.T) { | ||||
| 				BackendURL:             "http://10.0.0.2/toto", | ||||
| 			}, | ||||
| 			expectedLog: `10.0.0.1 - Client [10/Nov/2009:23:00:00 +0000] "GET /foo http" 123 132 "referer" "agent" - "foo" "http://10.0.0.2/toto" 123000ms | ||||
| `, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "all data with local time", | ||||
| 			data: map[string]interface{}{ | ||||
| 				StartLocal:             time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), | ||||
| 				Duration:               123 * time.Second, | ||||
| 				ClientHost:             "10.0.0.1", | ||||
| 				ClientUsername:         "Client", | ||||
| 				RequestMethod:          http.MethodGet, | ||||
| 				RequestPath:            "/foo", | ||||
| 				RequestProtocol:        "http", | ||||
| 				OriginStatus:           123, | ||||
| 				OriginContentSize:      132, | ||||
| 				RequestRefererHeader:   "referer", | ||||
| 				RequestUserAgentHeader: "agent", | ||||
| 				RequestCount:           nil, | ||||
| 				FrontendName:           "foo", | ||||
| 				BackendURL:             "http://10.0.0.2/toto", | ||||
| 			}, | ||||
| 			expectedLog: `10.0.0.1 - Client [10/Nov/2009:14:00:00 -0900] "GET /foo http" 123 132 "referer" "agent" - "foo" "http://10.0.0.2/toto" 123000ms | ||||
| `, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	// Set timezone to Alaska to have a constant behavior | ||||
| 	os.Setenv("TZ", "US/Alaska") | ||||
|  | ||||
| 	for _, test := range testCases { | ||||
| 		test := test | ||||
| 		t.Run(test.name, func(t *testing.T) { | ||||
|   | ||||
| @@ -44,8 +44,9 @@ func TestLogRotation(t *testing.T) { | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Error setting up temporary directory: %s", err) | ||||
| 	} | ||||
| 	defer os.RemoveAll(tempDir) | ||||
|  | ||||
| 	fileName := tempDir + "traefik.log" | ||||
| 	fileName := filepath.Join(tempDir, "traefik.log") | ||||
| 	rotatedFileName := fileName + ".rotated" | ||||
|  | ||||
| 	config := &types.AccessLog{FilePath: fileName, Format: CommonFormat} | ||||
| @@ -587,6 +588,7 @@ func captureStdout(t *testing.T) (out *os.File, restoreStdout func()) { | ||||
|  | ||||
| 	restoreStdout = func() { | ||||
| 		os.Stdout = original | ||||
| 		os.RemoveAll(file.Name()) | ||||
| 	} | ||||
|  | ||||
| 	return file, restoreStdout | ||||
|   | ||||
| @@ -134,7 +134,7 @@ func getLinesFromFile(filename string) ([]string, error) { | ||||
| 	var filteredLines []string | ||||
| 	for _, rawLine := range rawLines { | ||||
| 		line := strings.TrimSpace(rawLine) | ||||
| 		if line != "" { | ||||
| 		if line != "" && !strings.HasPrefix(line, "#") { | ||||
| 			filteredLines = append(filteredLines, line) | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -45,6 +45,17 @@ func TestAuthUsersFromFile(t *testing.T) { | ||||
| 				return parserDigestUsers(digest) | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			authType: "basic", | ||||
| 			usersStr: "#Comment\ntest:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/\ntest2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0\n", | ||||
| 			userKeys: []string{"test", "test2"}, | ||||
| 			parserFunc: func(fileName string) (map[string]string, error) { | ||||
| 				basic := &types.Basic{ | ||||
| 					UsersFile: fileName, | ||||
| 				} | ||||
| 				return parserBasicUsers(basic) | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range tests { | ||||
|   | ||||
| @@ -96,7 +96,11 @@ func Forward(config *types.Forward, w http.ResponseWriter, r *http.Request, next | ||||
| 	} | ||||
|  | ||||
| 	for _, headerName := range config.AuthResponseHeaders { | ||||
| 		r.Header.Set(headerName, forwardResponse.Header.Get(headerName)) | ||||
| 		headerKey := http.CanonicalHeaderKey(headerName) | ||||
| 		r.Header.Del(headerKey) | ||||
| 		if len(forwardResponse.Header[headerKey]) > 0 { | ||||
| 			r.Header[headerKey] = append([]string(nil), forwardResponse.Header[headerKey]...) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	r.RequestURI = r.URL.RequestURI() | ||||
|   | ||||
| @@ -50,6 +50,8 @@ func TestForwardAuthFail(t *testing.T) { | ||||
| func TestForwardAuthSuccess(t *testing.T) { | ||||
| 	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| 		w.Header().Set("X-Auth-User", "user@example.com") | ||||
| 		w.Header().Add("X-Auth-Group", "group1") | ||||
| 		w.Header().Add("X-Auth-Group", "group2") | ||||
| 		w.Header().Set("X-Auth-Secret", "secret") | ||||
| 		fmt.Fprintln(w, "Success") | ||||
| 	})) | ||||
| @@ -58,13 +60,14 @@ func TestForwardAuthSuccess(t *testing.T) { | ||||
| 	middleware, err := NewAuthenticator(&types.Auth{ | ||||
| 		Forward: &types.Forward{ | ||||
| 			Address:             server.URL, | ||||
| 			AuthResponseHeaders: []string{"X-Auth-User"}, | ||||
| 			AuthResponseHeaders: []string{"X-Auth-User", "X-Auth-Group"}, | ||||
| 		}, | ||||
| 	}, &tracing.Tracing{}) | ||||
| 	assert.NoError(t, err, "there should be no error") | ||||
|  | ||||
| 	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| 		assert.Equal(t, "user@example.com", r.Header.Get("X-Auth-User")) | ||||
| 		assert.Equal(t, []string{"group1", "group2"}, r.Header["X-Auth-Group"]) | ||||
| 		assert.Empty(t, r.Header.Get("X-Auth-Secret")) | ||||
| 		fmt.Fprintln(w, "traefik") | ||||
| 	}) | ||||
| @@ -74,6 +77,7 @@ func TestForwardAuthSuccess(t *testing.T) { | ||||
| 	defer ts.Close() | ||||
|  | ||||
| 	req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil) | ||||
| 	req.Header.Set("X-Auth-Group", "admin_group") | ||||
| 	res, err := http.DefaultClient.Do(req) | ||||
| 	assert.NoError(t, err, "there should be no error") | ||||
| 	assert.Equal(t, http.StatusOK, res.StatusCode, "they should be equal") | ||||
|   | ||||
| @@ -19,7 +19,10 @@ import ( | ||||
| ) | ||||
|  | ||||
| // Compile time validation that the response recorder implements http interfaces correctly. | ||||
| var _ middlewares.Stateful = &responseRecorderWithCloseNotify{} | ||||
| var ( | ||||
| 	_ middlewares.Stateful = &responseRecorderWithCloseNotify{} | ||||
| 	_ middlewares.Stateful = &codeCatcherWithCloseNotify{} | ||||
| ) | ||||
|  | ||||
| // Handler is a middleware that provides the custom error pages | ||||
| type Handler struct { | ||||
| @@ -74,25 +77,29 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request, next http. | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	recorder := newResponseRecorder(w) | ||||
| 	next.ServeHTTP(recorder, req) | ||||
| 	catcher := newCodeCatcher(w, h.httpCodeRanges) | ||||
| 	next.ServeHTTP(catcher, req) | ||||
| 	if !catcher.isFilteredCode() { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// check the recorder code against the configured http status code ranges | ||||
| 	code := catcher.getCode() | ||||
| 	for _, block := range h.httpCodeRanges { | ||||
| 		if recorder.GetCode() >= block[0] && recorder.GetCode() <= block[1] { | ||||
| 			log.Errorf("Caught HTTP Status Code %d, returning error page", recorder.GetCode()) | ||||
| 		if code >= block[0] && code <= block[1] { | ||||
| 			log.Errorf("Caught HTTP Status Code %d, returning error page", code) | ||||
|  | ||||
| 			var query string | ||||
| 			if len(h.backendQuery) > 0 { | ||||
| 				query = "/" + strings.TrimPrefix(h.backendQuery, "/") | ||||
| 				query = strings.Replace(query, "{status}", strconv.Itoa(recorder.GetCode()), -1) | ||||
| 				query = strings.Replace(query, "{status}", strconv.Itoa(code), -1) | ||||
| 			} | ||||
|  | ||||
| 			pageReq, err := newRequest(h.backendURL + query) | ||||
| 			if err != nil { | ||||
| 				log.Error(err) | ||||
| 				w.WriteHeader(recorder.GetCode()) | ||||
| 				fmt.Fprint(w, http.StatusText(recorder.GetCode())) | ||||
| 				w.WriteHeader(code) | ||||
| 				fmt.Fprint(w, http.StatusText(code)) | ||||
| 				return | ||||
| 			} | ||||
|  | ||||
| @@ -102,16 +109,11 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request, next http. | ||||
| 			h.backendHandler.ServeHTTP(recorderErrorPage, pageReq.WithContext(req.Context())) | ||||
|  | ||||
| 			utils.CopyHeaders(w.Header(), recorderErrorPage.Header()) | ||||
| 			w.WriteHeader(recorder.GetCode()) | ||||
| 			w.WriteHeader(code) | ||||
| 			w.Write(recorderErrorPage.GetBody().Bytes()) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// did not catch a configured status code so proceed with the request | ||||
| 	utils.CopyHeaders(w.Header(), recorder.Header()) | ||||
| 	w.WriteHeader(recorder.GetCode()) | ||||
| 	w.Write(recorder.GetBody().Bytes()) | ||||
| } | ||||
|  | ||||
| func newRequest(baseURL string) (*http.Request, error) { | ||||
| @@ -129,6 +131,133 @@ func newRequest(baseURL string) (*http.Request, error) { | ||||
| 	return req, nil | ||||
| } | ||||
|  | ||||
| type responseInterceptor interface { | ||||
| 	http.ResponseWriter | ||||
| 	http.Flusher | ||||
| 	getCode() int | ||||
| 	isFilteredCode() bool | ||||
| } | ||||
|  | ||||
| // codeCatcher is a response writer that detects as soon as possible whether the | ||||
| // response is a code within the ranges of codes it watches for. If it is, it | ||||
| // simply drops the data from the response. Otherwise, it forwards it directly to | ||||
| // the original client (its responseWriter) without any buffering. | ||||
| type codeCatcher struct { | ||||
| 	headerMap          http.Header | ||||
| 	code               int | ||||
| 	httpCodeRanges     types.HTTPCodeRanges | ||||
| 	firstWrite         bool | ||||
| 	caughtFilteredCode bool | ||||
| 	responseWriter     http.ResponseWriter | ||||
| 	headersSent        bool | ||||
| 	err                error | ||||
| } | ||||
|  | ||||
| type codeCatcherWithCloseNotify struct { | ||||
| 	*codeCatcher | ||||
| } | ||||
|  | ||||
| // CloseNotify returns a channel that receives at most a | ||||
| // single value (true) when the client connection has gone away. | ||||
| func (cc *codeCatcherWithCloseNotify) CloseNotify() <-chan bool { | ||||
| 	return cc.responseWriter.(http.CloseNotifier).CloseNotify() | ||||
| } | ||||
|  | ||||
| func newCodeCatcher(rw http.ResponseWriter, httpCodeRanges types.HTTPCodeRanges) responseInterceptor { | ||||
| 	catcher := &codeCatcher{ | ||||
| 		headerMap:      make(http.Header), | ||||
| 		code:           http.StatusOK, // If backend does not call WriteHeader on us, we consider it's a 200. | ||||
| 		responseWriter: rw, | ||||
| 		httpCodeRanges: httpCodeRanges, | ||||
| 		firstWrite:     true, | ||||
| 	} | ||||
| 	if _, ok := rw.(http.CloseNotifier); ok { | ||||
| 		return &codeCatcherWithCloseNotify{catcher} | ||||
| 	} | ||||
| 	return catcher | ||||
| } | ||||
|  | ||||
| func (cc *codeCatcher) Header() http.Header { | ||||
| 	if cc.headerMap == nil { | ||||
| 		cc.headerMap = make(http.Header) | ||||
| 	} | ||||
|  | ||||
| 	return cc.headerMap | ||||
| } | ||||
|  | ||||
| func (cc *codeCatcher) getCode() int { | ||||
| 	return cc.code | ||||
| } | ||||
|  | ||||
| // isFilteredCode returns whether the codeCatcher received a response code among the ones it is watching, | ||||
| // and for which the response should be deferred to the error handler. | ||||
| func (cc *codeCatcher) isFilteredCode() bool { | ||||
| 	return cc.caughtFilteredCode | ||||
| } | ||||
|  | ||||
| func (cc *codeCatcher) Write(buf []byte) (int, error) { | ||||
| 	if !cc.firstWrite { | ||||
| 		if cc.caughtFilteredCode { | ||||
| 			// We don't care about the contents of the response, | ||||
| 			// since we want to serve the ones from the error page, | ||||
| 			// so we just drop them. | ||||
| 			return len(buf), nil | ||||
| 		} | ||||
| 		return cc.responseWriter.Write(buf) | ||||
| 	} | ||||
| 	cc.firstWrite = false | ||||
|  | ||||
| 	// If WriteHeader was already called from the caller, this is a NOOP. | ||||
| 	// Otherwise, cc.code is actually a 200 here. | ||||
| 	cc.WriteHeader(cc.code) | ||||
|  | ||||
| 	if cc.caughtFilteredCode { | ||||
| 		return len(buf), nil | ||||
| 	} | ||||
| 	return cc.responseWriter.Write(buf) | ||||
| } | ||||
|  | ||||
| func (cc *codeCatcher) WriteHeader(code int) { | ||||
| 	if cc.headersSent || cc.caughtFilteredCode { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	cc.code = code | ||||
| 	for _, block := range cc.httpCodeRanges { | ||||
| 		if cc.code >= block[0] && cc.code <= block[1] { | ||||
| 			cc.caughtFilteredCode = true | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	// it will be up to the other response recorder to send the headers, | ||||
| 	// so it is out of our hands now. | ||||
| 	if cc.caughtFilteredCode { | ||||
| 		return | ||||
| 	} | ||||
| 	utils.CopyHeaders(cc.responseWriter.Header(), cc.Header()) | ||||
| 	cc.responseWriter.WriteHeader(cc.code) | ||||
| 	cc.headersSent = true | ||||
| } | ||||
|  | ||||
| // Hijack hijacks the connection | ||||
| func (cc *codeCatcher) Hijack() (net.Conn, *bufio.ReadWriter, error) { | ||||
| 	if hj, ok := cc.responseWriter.(http.Hijacker); ok { | ||||
| 		return hj.Hijack() | ||||
| 	} | ||||
| 	return nil, nil, fmt.Errorf("%T is not a http.Hijacker", cc.responseWriter) | ||||
| } | ||||
|  | ||||
| // Flush sends any buffered data to the client. | ||||
| func (cc *codeCatcher) Flush() { | ||||
| 	// If WriteHeader was already called from the caller, this is a NOOP. | ||||
| 	// Otherwise, cc.code is actually a 200 here. | ||||
| 	cc.WriteHeader(cc.code) | ||||
|  | ||||
| 	if flusher, ok := cc.responseWriter.(http.Flusher); ok { | ||||
| 		flusher.Flush() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type responseRecorder interface { | ||||
| 	http.ResponseWriter | ||||
| 	http.Flusher | ||||
|   | ||||
| @@ -34,6 +34,30 @@ func TestHandler(t *testing.T) { | ||||
| 				assert.Contains(t, recorder.Body.String(), http.StatusText(http.StatusOK)) | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc:        "no error, but not a 200", | ||||
| 			errorPage:   &types.ErrorPage{Backend: "error", Query: "/test", Status: []string{"500-501", "503-599"}}, | ||||
| 			backendCode: http.StatusPartialContent, | ||||
| 			backendErrorHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| 				fmt.Fprintln(w, "My error page.") | ||||
| 			}), | ||||
| 			validate: func(t *testing.T, recorder *httptest.ResponseRecorder) { | ||||
| 				assert.Equal(t, http.StatusPartialContent, recorder.Code, "HTTP status") | ||||
| 				assert.Contains(t, recorder.Body.String(), http.StatusText(http.StatusPartialContent)) | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc:        "a 304, so no Write called", | ||||
| 			errorPage:   &types.ErrorPage{Backend: "error", Query: "/test", Status: []string{"500-501", "503-599"}}, | ||||
| 			backendCode: http.StatusNotModified, | ||||
| 			backendErrorHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| 				fmt.Fprintln(w, "whatever, should not be called") | ||||
| 			}), | ||||
| 			validate: func(t *testing.T, recorder *httptest.ResponseRecorder) { | ||||
| 				assert.Equal(t, http.StatusNotModified, recorder.Code, "HTTP status") | ||||
| 				assert.Contains(t, recorder.Body.String(), "") | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc:        "in the range", | ||||
| 			errorPage:   &types.ErrorPage{Backend: "error", Query: "/test", Status: []string{"500-501", "503-599"}}, | ||||
| @@ -108,6 +132,9 @@ func TestHandler(t *testing.T) { | ||||
|  | ||||
| 			handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| 				w.WriteHeader(test.backendCode) | ||||
| 				if test.backendCode == http.StatusNotModified { | ||||
| 					return | ||||
| 				} | ||||
| 				fmt.Fprintln(w, http.StatusText(test.backendCode)) | ||||
| 			}) | ||||
|  | ||||
|   | ||||
| @@ -125,8 +125,15 @@ type moveHandler struct { | ||||
| func (m *moveHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { | ||||
| 	rw.Header().Set("Location", m.location.String()) | ||||
| 	status := http.StatusFound | ||||
| 	if req.Method != http.MethodGet { | ||||
| 		status = http.StatusTemporaryRedirect | ||||
| 	} | ||||
|  | ||||
| 	if m.permanent { | ||||
| 		status = http.StatusMovedPermanently | ||||
| 		if req.Method != http.MethodGet { | ||||
| 			status = http.StatusPermanentRedirect | ||||
| 		} | ||||
| 	} | ||||
| 	rw.WriteHeader(status) | ||||
| 	rw.Write([]byte(http.StatusText(status))) | ||||
|   | ||||
| @@ -17,6 +17,7 @@ func TestNewEntryPointHandler(t *testing.T) { | ||||
| 		desc           string | ||||
| 		entryPoint     *configuration.EntryPoint | ||||
| 		permanent      bool | ||||
| 		method         string | ||||
| 		url            string | ||||
| 		expectedURL    string | ||||
| 		expectedStatus int | ||||
| @@ -59,6 +60,24 @@ func TestNewEntryPointHandler(t *testing.T) { | ||||
| 			expectedURL:    "http://foo:80", | ||||
| 			expectedStatus: http.StatusMovedPermanently, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc:           "HTTP to HTTP POST", | ||||
| 			entryPoint:     &configuration.EntryPoint{Address: ":80"}, | ||||
| 			permanent:      false, | ||||
| 			url:            "http://foo:90", | ||||
| 			method:         http.MethodPost, | ||||
| 			expectedURL:    "http://foo:80", | ||||
| 			expectedStatus: http.StatusTemporaryRedirect, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc:           "HTTP to HTTP POST permanent", | ||||
| 			entryPoint:     &configuration.EntryPoint{Address: ":80"}, | ||||
| 			permanent:      true, | ||||
| 			url:            "http://foo:90", | ||||
| 			method:         http.MethodPost, | ||||
| 			expectedURL:    "http://foo:80", | ||||
| 			expectedStatus: http.StatusPermanentRedirect, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc:          "invalid address", | ||||
| 			entryPoint:    &configuration.EntryPoint{Address: ":foo", TLS: &tls.TLS{}}, | ||||
| @@ -80,7 +99,11 @@ func TestNewEntryPointHandler(t *testing.T) { | ||||
| 				require.NoError(t, err) | ||||
|  | ||||
| 				recorder := httptest.NewRecorder() | ||||
| 				r := testhelpers.MustNewRequest(http.MethodGet, test.url, nil) | ||||
| 				method := http.MethodGet | ||||
| 				if test.method != "" { | ||||
| 					method = test.method | ||||
| 				} | ||||
| 				r := testhelpers.MustNewRequest(method, test.url, nil) | ||||
| 				handler.ServeHTTP(recorder, r, nil) | ||||
|  | ||||
| 				location, err := recorder.Result().Location() | ||||
|   | ||||
| @@ -44,9 +44,7 @@ func (retry *Retry) ServeHTTP(rw http.ResponseWriter, r *http.Request) { | ||||
|  | ||||
| 	attempts := 1 | ||||
| 	for { | ||||
| 		attemptsExhausted := attempts >= retry.attempts | ||||
|  | ||||
| 		shouldRetry := !attemptsExhausted | ||||
| 		shouldRetry := attempts < retry.attempts | ||||
| 		retryResponseWriter := newRetryResponseWriter(rw, shouldRetry) | ||||
|  | ||||
| 		// Disable retries when the backend already received request data | ||||
| @@ -99,6 +97,7 @@ type retryResponseWriter interface { | ||||
| func newRetryResponseWriter(rw http.ResponseWriter, shouldRetry bool) retryResponseWriter { | ||||
| 	responseWriter := &retryResponseWriterWithoutCloseNotify{ | ||||
| 		responseWriter: rw, | ||||
| 		headers:        make(http.Header), | ||||
| 		shouldRetry:    shouldRetry, | ||||
| 	} | ||||
| 	if _, ok := rw.(http.CloseNotifier); ok { | ||||
| @@ -109,7 +108,9 @@ func newRetryResponseWriter(rw http.ResponseWriter, shouldRetry bool) retryRespo | ||||
|  | ||||
| type retryResponseWriterWithoutCloseNotify struct { | ||||
| 	responseWriter http.ResponseWriter | ||||
| 	headers        http.Header | ||||
| 	shouldRetry    bool | ||||
| 	written        bool | ||||
| } | ||||
|  | ||||
| func (rr *retryResponseWriterWithoutCloseNotify) ShouldRetry() bool { | ||||
| @@ -121,10 +122,10 @@ func (rr *retryResponseWriterWithoutCloseNotify) DisableRetries() { | ||||
| } | ||||
|  | ||||
| func (rr *retryResponseWriterWithoutCloseNotify) Header() http.Header { | ||||
| 	if rr.ShouldRetry() { | ||||
| 		return make(http.Header) | ||||
| 	if rr.written { | ||||
| 		return rr.responseWriter.Header() | ||||
| 	} | ||||
| 	return rr.responseWriter.Header() | ||||
| 	return rr.headers | ||||
| } | ||||
|  | ||||
| func (rr *retryResponseWriterWithoutCloseNotify) Write(buf []byte) (int, error) { | ||||
| @@ -147,7 +148,18 @@ func (rr *retryResponseWriterWithoutCloseNotify) WriteHeader(code int) { | ||||
| 	if rr.ShouldRetry() { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// In that case retry case is set to false which means we at least managed | ||||
| 	// to write headers to the backend : we are not going to perform any further retry. | ||||
| 	// So it is now safe to alter current response headers with headers collected during | ||||
| 	// the latest try before writing headers to client. | ||||
| 	headers := rr.responseWriter.Header() | ||||
| 	for header, value := range rr.headers { | ||||
| 		headers[header] = value | ||||
| 	} | ||||
|  | ||||
| 	rr.responseWriter.WriteHeader(code) | ||||
| 	rr.written = true | ||||
| } | ||||
|  | ||||
| func (rr *retryResponseWriterWithoutCloseNotify) Hijack() (net.Conn, *bufio.ReadWriter, error) { | ||||
|   | ||||
| @@ -1,8 +1,11 @@ | ||||
| package middlewares | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"net/http/httptest" | ||||
| 	"net/http/httptrace" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
|  | ||||
| @@ -33,7 +36,7 @@ func TestRetry(t *testing.T) { | ||||
| 			desc:                  "no retry when max request attempts is one", | ||||
| 			maxRequestAttempts:    1, | ||||
| 			wantRetryAttempts:     0, | ||||
| 			wantResponseStatus:    http.StatusInternalServerError, | ||||
| 			wantResponseStatus:    http.StatusBadGateway, | ||||
| 			amountFaultyEndpoints: 1, | ||||
| 		}, | ||||
| 		{ | ||||
| @@ -54,7 +57,7 @@ func TestRetry(t *testing.T) { | ||||
| 			desc:                  "max attempts exhausted delivers the 5xx response", | ||||
| 			maxRequestAttempts:    3, | ||||
| 			wantRetryAttempts:     2, | ||||
| 			wantResponseStatus:    http.StatusInternalServerError, | ||||
| 			wantResponseStatus:    http.StatusBadGateway, | ||||
| 			amountFaultyEndpoints: 3, | ||||
| 		}, | ||||
| 	} | ||||
| @@ -80,17 +83,18 @@ func TestRetry(t *testing.T) { | ||||
| 				t.Fatalf("Error creating load balancer: %s", err) | ||||
| 			} | ||||
|  | ||||
| 			basePort := 33444 | ||||
| 			// out of range port | ||||
| 			basePort := 1133444 | ||||
| 			for i := 0; i < test.amountFaultyEndpoints; i++ { | ||||
| 				// 192.0.2.0 is a non-routable IP for testing purposes. | ||||
| 				// See: https://stackoverflow.com/questions/528538/non-routable-ip-address/18436928#18436928 | ||||
| 				// We only use the port specification here because the URL is used as identifier | ||||
| 				// in the load balancer and using the exact same URL would not add a new server. | ||||
| 				loadBalancer.UpsertServer(testhelpers.MustParseURL("http://192.0.2.0:" + string(basePort+i))) | ||||
| 				_ = loadBalancer.UpsertServer(testhelpers.MustParseURL("http://192.0.2.0:" + strconv.Itoa(basePort+i))) | ||||
| 			} | ||||
|  | ||||
| 			// add the functioning server to the end of the load balancer list | ||||
| 			loadBalancer.UpsertServer(testhelpers.MustParseURL(backendServer.URL)) | ||||
| 			_ = loadBalancer.UpsertServer(testhelpers.MustParseURL(backendServer.URL)) | ||||
|  | ||||
| 			retryListener := &countingRetryListener{} | ||||
| 			retry := NewRetry(test.maxRequestAttempts, loadBalancer, retryListener) | ||||
| @@ -152,17 +156,18 @@ func TestRetryWebsocket(t *testing.T) { | ||||
| 				t.Fatalf("Error creating load balancer: %s", err) | ||||
| 			} | ||||
|  | ||||
| 			basePort := 33444 | ||||
| 			// out of range port | ||||
| 			basePort := 1133444 | ||||
| 			for i := 0; i < test.amountFaultyEndpoints; i++ { | ||||
| 				// 192.0.2.0 is a non-routable IP for testing purposes. | ||||
| 				// See: https://stackoverflow.com/questions/528538/non-routable-ip-address/18436928#18436928 | ||||
| 				// We only use the port specification here because the URL is used as identifier | ||||
| 				// in the load balancer and using the exact same URL would not add a new server. | ||||
| 				loadBalancer.UpsertServer(testhelpers.MustParseURL("http://192.0.2.0:" + string(basePort+i))) | ||||
| 				_ = loadBalancer.UpsertServer(testhelpers.MustParseURL("http://192.0.2.0:" + strconv.Itoa(basePort+i))) | ||||
| 			} | ||||
|  | ||||
| 			// add the functioning server to the end of the load balancer list | ||||
| 			loadBalancer.UpsertServer(testhelpers.MustParseURL(backendServer.URL)) | ||||
| 			_ = loadBalancer.UpsertServer(testhelpers.MustParseURL(backendServer.URL)) | ||||
|  | ||||
| 			retryListener := &countingRetryListener{} | ||||
| 			retry := NewRetry(test.maxRequestAttempts, loadBalancer, retryListener) | ||||
| @@ -256,3 +261,45 @@ func TestRetryWithFlush(t *testing.T) { | ||||
| 		t.Errorf("Wrong body %q want %q", responseRecorder.Body.String(), "FULL DATA") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestMultipleRetriesShouldNotLooseHeaders(t *testing.T) { | ||||
| 	attempt := 0 | ||||
| 	expectedHeaderName := "X-Foo-Test-2" | ||||
| 	expectedHeaderValue := "bar" | ||||
|  | ||||
| 	next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { | ||||
| 		headerName := fmt.Sprintf("X-Foo-Test-%d", attempt) | ||||
| 		rw.Header().Add(headerName, expectedHeaderValue) | ||||
| 		if attempt < 2 { | ||||
| 			attempt++ | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		// Request has been successfully written to backend | ||||
| 		trace := httptrace.ContextClientTrace(req.Context()) | ||||
| 		trace.WroteHeaders() | ||||
|  | ||||
| 		// And we decide to answer to client | ||||
| 		rw.WriteHeader(http.StatusNoContent) | ||||
| 	}) | ||||
|  | ||||
| 	retry := NewRetry(3, next, &countingRetryListener{}) | ||||
| 	responseRecorder := httptest.NewRecorder() | ||||
| 	retry.ServeHTTP(responseRecorder, &http.Request{}) | ||||
|  | ||||
| 	headerValue := responseRecorder.Header().Get(expectedHeaderName) | ||||
|  | ||||
| 	// Validate if we have the correct header | ||||
| 	if headerValue != expectedHeaderValue { | ||||
| 		t.Errorf("Expected to have %s for header %s, got %s", expectedHeaderValue, expectedHeaderName, headerValue) | ||||
| 	} | ||||
|  | ||||
| 	// Validate that we don't have headers from previous attempts | ||||
| 	for i := 0; i < attempt; i++ { | ||||
| 		headerName := fmt.Sprintf("X-Foo-Test-%d", i) | ||||
| 		headerValue = responseRecorder.Header().Get("headerName") | ||||
| 		if headerValue != "" { | ||||
| 			t.Errorf("Expected no value for header %s, got %s", headerName, headerValue) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -17,6 +17,7 @@ func NewSecure(headers *types.Headers) *secure.Secure { | ||||
| 		SSLRedirect:             headers.SSLRedirect, | ||||
| 		SSLTemporaryRedirect:    headers.SSLTemporaryRedirect, | ||||
| 		SSLHost:                 headers.SSLHost, | ||||
| 		SSLForceHost:            headers.SSLForceHost, | ||||
| 		SSLProxyHeaders:         headers.SSLProxyHeaders, | ||||
| 		STSSeconds:              headers.STSSeconds, | ||||
| 		STSIncludeSubdomains:    headers.STSIncludeSubdomains, | ||||
|   | ||||
							
								
								
									
										96
									
								
								middlewares/secure_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								middlewares/secure_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| package middlewares | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"net/http/httptest" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/containous/traefik/testhelpers" | ||||
| 	"github.com/containous/traefik/types" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/unrolled/secure" | ||||
| ) | ||||
|  | ||||
| func TestSSLForceHost(t *testing.T) { | ||||
| 	testCases := []struct { | ||||
| 		desc             string | ||||
| 		host             string | ||||
| 		secureMiddleware *secure.Secure | ||||
| 		expected         int | ||||
| 	}{ | ||||
| 		{ | ||||
| 			desc: "http should return a 301", | ||||
| 			host: "http://powpow.example.com", | ||||
| 			secureMiddleware: NewSecure(&types.Headers{ | ||||
| 				SSLRedirect:  true, | ||||
| 				SSLForceHost: true, | ||||
| 				SSLHost:      "powpow.example.com", | ||||
| 			}), | ||||
| 			expected: http.StatusMovedPermanently, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc: "http sub domain should return a 301", | ||||
| 			host: "http://www.powpow.example.com", | ||||
| 			secureMiddleware: NewSecure(&types.Headers{ | ||||
| 				SSLRedirect:  true, | ||||
| 				SSLForceHost: true, | ||||
| 				SSLHost:      "powpow.example.com", | ||||
| 			}), | ||||
| 			expected: http.StatusMovedPermanently, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc: "https should return a 200", | ||||
| 			host: "https://powpow.example.com", | ||||
| 			secureMiddleware: NewSecure(&types.Headers{ | ||||
| 				SSLRedirect:  true, | ||||
| 				SSLForceHost: true, | ||||
| 				SSLHost:      "powpow.example.com", | ||||
| 			}), | ||||
| 			expected: http.StatusOK, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc: "https sub domain should return a 301", | ||||
| 			host: "https://www.powpow.example.com", | ||||
| 			secureMiddleware: NewSecure(&types.Headers{ | ||||
| 				SSLRedirect:  true, | ||||
| 				SSLForceHost: true, | ||||
| 				SSLHost:      "powpow.example.com", | ||||
| 			}), | ||||
| 			expected: http.StatusMovedPermanently, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc: "http without force host and sub domain should return a 301", | ||||
| 			host: "http://www.powpow.example.com", | ||||
| 			secureMiddleware: NewSecure(&types.Headers{ | ||||
| 				SSLRedirect:  true, | ||||
| 				SSLForceHost: false, | ||||
| 				SSLHost:      "powpow.example.com", | ||||
| 			}), | ||||
| 			expected: http.StatusMovedPermanently, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc: "https without force host and sub domain should return a 301", | ||||
| 			host: "https://www.powpow.example.com", | ||||
| 			secureMiddleware: NewSecure(&types.Headers{ | ||||
| 				SSLRedirect:  true, | ||||
| 				SSLForceHost: false, | ||||
| 				SSLHost:      "powpow.example.com", | ||||
| 			}), | ||||
| 			expected: http.StatusOK, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range testCases { | ||||
| 		t.Run(test.desc, func(t *testing.T) { | ||||
| 			req := testhelpers.MustNewRequest(http.MethodGet, test.host, nil) | ||||
| 			next := func(rw http.ResponseWriter, r *http.Request) { | ||||
| 				rw.Write([]byte("OK")) | ||||
| 			} | ||||
|  | ||||
| 			rw := httptest.NewRecorder() | ||||
| 			test.secureMiddleware.HandlerFuncWithNextForRequestOnly(rw, req, next) | ||||
|  | ||||
| 			assert.Equal(t, test.expected, rw.Result().StatusCode) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| @@ -13,45 +13,54 @@ import ( | ||||
| 	"github.com/containous/traefik/types" | ||||
| ) | ||||
|  | ||||
| const xForwardedTLSClientCert = "X-Forwarded-Tls-Client-Cert" | ||||
| const xForwardedTLSClientCertInfos = "X-Forwarded-Tls-Client-Cert-Infos" | ||||
| const ( | ||||
| 	xForwardedTLSClientCert      = "X-Forwarded-Tls-Client-Cert" | ||||
| 	xForwardedTLSClientCertInfos = "X-Forwarded-Tls-Client-Cert-Infos" | ||||
| ) | ||||
|  | ||||
| var attributeTypeNames = map[string]string{ | ||||
| 	"0.9.2342.19200300.100.1.25": "DC", // Domain component OID - RFC 2247 | ||||
| } | ||||
|  | ||||
| // TLSClientCertificateInfos is a struct for specifying the configuration for the tlsClientHeaders middleware. | ||||
| type TLSClientCertificateInfos struct { | ||||
| 	Issuer    *DistinguishedNameOptions | ||||
| 	NotAfter  bool | ||||
| 	NotBefore bool | ||||
| 	Subject   *TLSCLientCertificateSubjectInfos | ||||
| 	Sans      bool | ||||
| 	Subject   *DistinguishedNameOptions | ||||
| } | ||||
|  | ||||
| // TLSCLientCertificateSubjectInfos contains the configuration for the certificate subject infos. | ||||
| type TLSCLientCertificateSubjectInfos struct { | ||||
| 	Country      bool | ||||
| 	Province     bool | ||||
| 	Locality     bool | ||||
| 	Organization bool | ||||
| 	CommonName   bool | ||||
| 	SerialNumber bool | ||||
| // DistinguishedNameOptions is a struct for specifying the configuration for the distinguished name info. | ||||
| type DistinguishedNameOptions struct { | ||||
| 	CommonName          bool | ||||
| 	CountryName         bool | ||||
| 	DomainComponent     bool | ||||
| 	LocalityName        bool | ||||
| 	OrganizationName    bool | ||||
| 	SerialNumber        bool | ||||
| 	StateOrProvinceName bool | ||||
| } | ||||
|  | ||||
| // TLSClientHeaders is a middleware that helps setup a few tls infos features. | ||||
| // TLSClientHeaders is a middleware that helps setup a few tls info features. | ||||
| type TLSClientHeaders struct { | ||||
| 	Infos *TLSClientCertificateInfos // pass selected information from the client certificate | ||||
| 	PEM   bool                       // pass the sanitized pem to the backend in a specific header | ||||
| 	Infos *TLSClientCertificateInfos // pass selected informations from the client certificate | ||||
| } | ||||
|  | ||||
| func newTLSCLientCertificateSubjectInfos(infos *types.TLSCLientCertificateSubjectInfos) *TLSCLientCertificateSubjectInfos { | ||||
| func newDistinguishedNameOptions(infos *types.TLSCLientCertificateDNInfos) *DistinguishedNameOptions { | ||||
| 	if infos == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return &TLSCLientCertificateSubjectInfos{ | ||||
| 		SerialNumber: infos.SerialNumber, | ||||
| 		CommonName:   infos.CommonName, | ||||
| 		Country:      infos.Country, | ||||
| 		Locality:     infos.Locality, | ||||
| 		Organization: infos.Organization, | ||||
| 		Province:     infos.Province, | ||||
| 	return &DistinguishedNameOptions{ | ||||
| 		CommonName:          infos.CommonName, | ||||
| 		CountryName:         infos.Country, | ||||
| 		DomainComponent:     infos.DomainComponent, | ||||
| 		LocalityName:        infos.Locality, | ||||
| 		OrganizationName:    infos.Organization, | ||||
| 		SerialNumber:        infos.SerialNumber, | ||||
| 		StateOrProvinceName: infos.Province, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -61,31 +70,23 @@ func newTLSClientInfos(infos *types.TLSClientCertificateInfos) *TLSClientCertifi | ||||
| 	} | ||||
|  | ||||
| 	return &TLSClientCertificateInfos{ | ||||
| 		NotBefore: infos.NotBefore, | ||||
| 		Issuer:    newDistinguishedNameOptions(infos.Issuer), | ||||
| 		NotAfter:  infos.NotAfter, | ||||
| 		NotBefore: infos.NotBefore, | ||||
| 		Sans:      infos.Sans, | ||||
| 		Subject:   newTLSCLientCertificateSubjectInfos(infos.Subject), | ||||
| 		Subject:   newDistinguishedNameOptions(infos.Subject), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // NewTLSClientHeaders constructs a new TLSClientHeaders instance from supplied frontend header struct. | ||||
| func NewTLSClientHeaders(frontend *types.Frontend) *TLSClientHeaders { | ||||
| 	if frontend == nil { | ||||
| func NewTLSClientHeaders(passTLSClientCert *types.TLSClientHeaders) *TLSClientHeaders { | ||||
| 	if passTLSClientCert == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	var pem bool | ||||
| 	var infos *TLSClientCertificateInfos | ||||
|  | ||||
| 	if frontend.PassTLSClientCert != nil { | ||||
| 		conf := frontend.PassTLSClientCert | ||||
| 		pem = conf.PEM | ||||
| 		infos = newTLSClientInfos(conf.Infos) | ||||
| 	} | ||||
|  | ||||
| 	return &TLSClientHeaders{ | ||||
| 		PEM:   pem, | ||||
| 		Infos: infos, | ||||
| 		Infos: newTLSClientInfos(passTLSClientCert.Infos), | ||||
| 		PEM:   passTLSClientCert.PEM, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -153,46 +154,67 @@ func getSANs(cert *x509.Certificate) []string { | ||||
| 	return append(sans, uris...) | ||||
| } | ||||
|  | ||||
| // getSubjectInfos extract the requested informations from the certificate subject | ||||
| func (s *TLSClientHeaders) getSubjectInfos(cs *pkix.Name) string { | ||||
| 	var subject string | ||||
| func getDNInfos(prefix string, options *DistinguishedNameOptions, cs *pkix.Name) string { | ||||
| 	if options == nil { | ||||
| 		return "" | ||||
| 	} | ||||
|  | ||||
| 	if s.Infos != nil && s.Infos.Subject != nil { | ||||
| 		options := s.Infos.Subject | ||||
| 	content := &strings.Builder{} | ||||
|  | ||||
| 		var content []string | ||||
|  | ||||
| 		if options.Country && len(cs.Country) > 0 { | ||||
| 			content = append(content, fmt.Sprintf("C=%s", cs.Country[0])) | ||||
| 		} | ||||
|  | ||||
| 		if options.Province && len(cs.Province) > 0 { | ||||
| 			content = append(content, fmt.Sprintf("ST=%s", cs.Province[0])) | ||||
| 		} | ||||
|  | ||||
| 		if options.Locality && len(cs.Locality) > 0 { | ||||
| 			content = append(content, fmt.Sprintf("L=%s", cs.Locality[0])) | ||||
| 		} | ||||
|  | ||||
| 		if options.Organization && len(cs.Organization) > 0 { | ||||
| 			content = append(content, fmt.Sprintf("O=%s", cs.Organization[0])) | ||||
| 		} | ||||
|  | ||||
| 		if options.CommonName && len(cs.CommonName) > 0 { | ||||
| 			content = append(content, fmt.Sprintf("CN=%s", cs.CommonName)) | ||||
| 		} | ||||
|  | ||||
| 		if len(content) > 0 { | ||||
| 			subject = `Subject="` + strings.Join(content, ",") + `"` | ||||
| 	// Manage non standard attributes | ||||
| 	for _, name := range cs.Names { | ||||
| 		// Domain Component - RFC 2247 | ||||
| 		if options.DomainComponent && attributeTypeNames[name.Type.String()] == "DC" { | ||||
| 			content.WriteString(fmt.Sprintf("DC=%s,", name.Value)) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return subject | ||||
| 	if options.CountryName { | ||||
| 		writeParts(content, cs.Country, "C") | ||||
| 	} | ||||
|  | ||||
| 	if options.StateOrProvinceName { | ||||
| 		writeParts(content, cs.Province, "ST") | ||||
| 	} | ||||
|  | ||||
| 	if options.LocalityName { | ||||
| 		writeParts(content, cs.Locality, "L") | ||||
| 	} | ||||
|  | ||||
| 	if options.OrganizationName { | ||||
| 		writeParts(content, cs.Organization, "O") | ||||
| 	} | ||||
|  | ||||
| 	if options.SerialNumber { | ||||
| 		writePart(content, cs.SerialNumber, "SN") | ||||
| 	} | ||||
|  | ||||
| 	if options.CommonName { | ||||
| 		writePart(content, cs.CommonName, "CN") | ||||
| 	} | ||||
|  | ||||
| 	if content.Len() > 0 { | ||||
| 		return prefix + `="` + strings.TrimSuffix(content.String(), ",") + `"` | ||||
| 	} | ||||
|  | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| // getXForwardedTLSClientCertInfos Build a string with the wanted client certificates informations | ||||
| // like Subject="C=%s,ST=%s,L=%s,O=%s,CN=%s",NB=%d,NA=%d,SAN=%s; | ||||
| func (s *TLSClientHeaders) getXForwardedTLSClientCertInfos(certs []*x509.Certificate) string { | ||||
| func writeParts(content *strings.Builder, entries []string, prefix string) { | ||||
| 	for _, entry := range entries { | ||||
| 		writePart(content, entry, prefix) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func writePart(content *strings.Builder, entry string, prefix string) { | ||||
| 	if len(entry) > 0 { | ||||
| 		content.WriteString(fmt.Sprintf("%s=%s,", prefix, entry)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // getXForwardedTLSClientCertInfo Build a string with the wanted client certificates information | ||||
| // like Subject="DC=%s,C=%s,ST=%s,L=%s,O=%s,CN=%s",NB=%d,NA=%d,SAN=%s; | ||||
| func (s *TLSClientHeaders) getXForwardedTLSClientCertInfo(certs []*x509.Certificate) string { | ||||
| 	var headerValues []string | ||||
|  | ||||
| 	for _, peerCert := range certs { | ||||
| @@ -201,9 +223,16 @@ func (s *TLSClientHeaders) getXForwardedTLSClientCertInfos(certs []*x509.Certifi | ||||
| 		var nb string | ||||
| 		var na string | ||||
|  | ||||
| 		subject := s.getSubjectInfos(&peerCert.Subject) | ||||
| 		if len(subject) > 0 { | ||||
| 			values = append(values, subject) | ||||
| 		if s.Infos != nil { | ||||
| 			subject := getDNInfos("Subject", s.Infos.Subject, &peerCert.Subject) | ||||
| 			if len(subject) > 0 { | ||||
| 				values = append(values, subject) | ||||
| 			} | ||||
|  | ||||
| 			issuer := getDNInfos("Issuer", s.Infos.Issuer, &peerCert.Issuer) | ||||
| 			if len(issuer) > 0 { | ||||
| 				values = append(values, issuer) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		ci := s.Infos | ||||
| @@ -230,8 +259,9 @@ func (s *TLSClientHeaders) getXForwardedTLSClientCertInfos(certs []*x509.Certifi | ||||
| 	return strings.Join(headerValues, ";") | ||||
| } | ||||
|  | ||||
| // ModifyRequestHeaders set the wanted headers with the certificates informations | ||||
| // ModifyRequestHeaders set the wanted headers with the certificates information | ||||
| func (s *TLSClientHeaders) ModifyRequestHeaders(r *http.Request) { | ||||
| 	r.Header.Del(xForwardedTLSClientCert) | ||||
| 	if s.PEM { | ||||
| 		if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 { | ||||
| 			r.Header.Set(xForwardedTLSClientCert, getXForwardedTLSClientCert(r.TLS.PeerCertificates)) | ||||
| @@ -240,9 +270,10 @@ func (s *TLSClientHeaders) ModifyRequestHeaders(r *http.Request) { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	r.Header.Del(xForwardedTLSClientCertInfos) | ||||
| 	if s.Infos != nil { | ||||
| 		if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 { | ||||
| 			headerContent := s.getXForwardedTLSClientCertInfos(r.TLS.PeerCertificates) | ||||
| 			headerContent := s.getXForwardedTLSClientCertInfo(r.TLS.PeerCertificates) | ||||
| 			r.Header.Set(xForwardedTLSClientCertInfos, url.QueryEscape(headerContent)) | ||||
| 		} else { | ||||
| 			log.Warn("Try to extract certificate on a request without TLS") | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -15,9 +15,14 @@ const Name = "datadog" | ||||
|  | ||||
| // Config provides configuration settings for a datadog tracer | ||||
| type Config struct { | ||||
| 	LocalAgentHostPort string `description:"Set datadog-agent's host:port that the reporter will used. Defaults to localhost:8126" export:"false"` | ||||
| 	GlobalTag          string `description:"Key:Value tag to be set on all the spans." export:"true"` | ||||
| 	Debug              bool   `description:"Enable DataDog debug." export:"true"` | ||||
| 	LocalAgentHostPort         string `description:"Set datadog-agent's host:port that the reporter will used. Defaults to localhost:8126" export:"false"` | ||||
| 	GlobalTag                  string `description:"Key:Value tag to be set on all the spans." export:"true"` | ||||
| 	Debug                      bool   `description:"Enable DataDog debug." export:"true"` | ||||
| 	PrioritySampling           bool   `description:"Enable priority sampling. When using distributed tracing, this option must be enabled in order to get all the parts of a distributed trace sampled."` | ||||
| 	TraceIDHeaderName          string `description:"Specifies the header name that will be used to store the trace ID." export:"true"` | ||||
| 	ParentIDHeaderName         string `description:"Specifies the header name that will be used to store the parent ID." export:"true"` | ||||
| 	SamplingPriorityHeaderName string `description:"Specifies the header name that will be used to store the sampling priority." export:"true"` | ||||
| 	BagagePrefixHeaderName     string `description:"specifies the header name prefix that will be used to store baggage items in a map." export:"true"` | ||||
| } | ||||
|  | ||||
| // Setup sets up the tracer | ||||
| @@ -29,12 +34,22 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error | ||||
| 		value = tag[1] | ||||
| 	} | ||||
|  | ||||
| 	tracer := ddtracer.New( | ||||
| 	opts := []datadog.StartOption{ | ||||
| 		datadog.WithAgentAddr(c.LocalAgentHostPort), | ||||
| 		datadog.WithServiceName(serviceName), | ||||
| 		datadog.WithGlobalTag(tag[0], value), | ||||
| 		datadog.WithDebugMode(c.Debug), | ||||
| 	) | ||||
| 		datadog.WithPropagator(datadog.NewPropagator(&datadog.PropagatorConfig{ | ||||
| 			TraceHeader:    c.TraceIDHeaderName, | ||||
| 			ParentHeader:   c.ParentIDHeaderName, | ||||
| 			PriorityHeader: c.SamplingPriorityHeaderName, | ||||
| 			BaggagePrefix:  c.BagagePrefixHeaderName, | ||||
| 		})), | ||||
| 	} | ||||
| 	if c.PrioritySampling { | ||||
| 		opts = append(opts, datadog.WithPrioritySampling()) | ||||
| 	} | ||||
| 	tracer := ddtracer.New(opts...) | ||||
|  | ||||
| 	// Without this, child spans are getting the NOOP tracer | ||||
| 	opentracing.SetGlobalTracer(tracer) | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/containous/traefik/log" | ||||
| 	"github.com/opentracing/opentracing-go" | ||||
| 	"github.com/uber/jaeger-client-go" | ||||
| 	jaegercfg "github.com/uber/jaeger-client-go/config" | ||||
| 	jaegermet "github.com/uber/jaeger-lib/metrics" | ||||
| ) | ||||
| @@ -14,10 +15,11 @@ const Name = "jaeger" | ||||
|  | ||||
| // Config provides configuration settings for a jaeger tracer | ||||
| type Config struct { | ||||
| 	SamplingServerURL  string  `description:"set the sampling server url." export:"false"` | ||||
| 	SamplingType       string  `description:"set the sampling type." export:"true"` | ||||
| 	SamplingParam      float64 `description:"set the sampling parameter." export:"true"` | ||||
| 	LocalAgentHostPort string  `description:"set jaeger-agent's host:port that the reporter will used." export:"false"` | ||||
| 	SamplingServerURL      string  `description:"set the sampling server url." export:"false"` | ||||
| 	SamplingType           string  `description:"set the sampling type." export:"true"` | ||||
| 	SamplingParam          float64 `description:"set the sampling parameter." export:"true"` | ||||
| 	LocalAgentHostPort     string  `description:"set jaeger-agent's host:port that the reporter will used." export:"false"` | ||||
| 	TraceContextHeaderName string  `description:"set the header to use for the trace-id." export:"true"` | ||||
| } | ||||
|  | ||||
| // Setup sets up the tracer | ||||
| @@ -32,6 +34,9 @@ func (c *Config) Setup(componentName string) (opentracing.Tracer, io.Closer, err | ||||
| 			LogSpans:           true, | ||||
| 			LocalAgentHostPort: c.LocalAgentHostPort, | ||||
| 		}, | ||||
| 		Headers: &jaeger.HeadersConfig{ | ||||
| 			TraceContextHeaderName: c.TraceContextHeaderName, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	jMetricsFactory := jaegermet.NullFactory | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/containous/traefik/log" | ||||
| 	"github.com/opentracing/opentracing-go" | ||||
| 	zipkin "github.com/openzipkin/zipkin-go-opentracing" | ||||
| 	zipkin "github.com/openzipkin-contrib/zipkin-go-opentracing" | ||||
| ) | ||||
|  | ||||
| // Name sets the name of this tracer | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user