mirror of
				https://github.com/containous/traefik.git
				synced 2025-10-30 20:24:28 +03:00 
			
		
		
		
	Compare commits
	
		
			609 Commits
		
	
	
		
			v2.5.7
			...
			v3.0.0-bet
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | c7cd0df3b3 | ||
|  | 286181aa61 | ||
|  | 6a34f238ce | ||
|  | 4b2c763cf3 | ||
|  | d03d8d53fd | ||
|  | 8d0979bfd0 | ||
|  | e95fde5652 | ||
|  | ab7993428d | ||
|  | b966215e6c | ||
|  | b786f58f80 | ||
|  | 173154cf59 | ||
|  | 4acec60e72 | ||
|  | c3880a69ca | ||
|  | 4d63eb30f9 | ||
|  | dbc679dc30 | ||
|  | fc7f732029 | ||
|  | ba912e1a93 | ||
|  | 3216c8ab10 | ||
|  | 561c580701 | ||
|  | 3fd5c747a2 | ||
|  | b6b6cef3da | ||
|  | d651d1e7cf | ||
|  | 6f22b9e0a7 | ||
|  | f29325c679 | ||
|  | 57780d8004 | ||
|  | 46f4a8541e | ||
|  | 1d85515aac | ||
|  | 55e00be36e | ||
|  | d6457e6cbb | ||
|  | ca2b9e8e77 | ||
|  | d948784d38 | ||
|  | 1ddb0afb24 | ||
|  | f518676238 | ||
|  | db3e8a7f5a | ||
|  | 0bd367ebbd | ||
|  | f4dc298406 | ||
|  | 3f93e9ea71 | ||
|  | eb585740a1 | ||
|  | 1709f3854c | ||
|  | ebde81e91c | ||
|  | 47faae25d7 | ||
|  | 7792d197e6 | ||
|  | deb4235028 | ||
|  | 124ee3c48c | ||
|  | bed6069e82 | ||
|  | e29da5ad65 | ||
|  | 48de3b0230 | ||
|  | 00048a8351 | ||
|  | 2df5defd36 | ||
|  | aaa763b7af | ||
|  | 8a68ece2cc | ||
|  | 08b80c20f0 | ||
|  | d4daafa468 | ||
|  | 52d2d959af | ||
|  | 0a35fa096a | ||
|  | a7ef965412 | ||
|  | 0a861716d4 | ||
|  | 4fbe9b81ec | ||
|  | 5fd6913ee5 | ||
|  | 7741c68eaa | ||
|  | 18077ff69a | ||
|  | fa555d0d29 | ||
|  | 0e5898b2f8 | ||
|  | aae76408e2 | ||
|  | 9cc9ed6a0c | ||
|  | fecaec7a4a | ||
|  | e62fe64ec9 | ||
|  | 6885e410f0 | ||
|  | 68ed875966 | ||
|  | d1bdeb3a92 | ||
|  | 878e7de56a | ||
|  | 27353d0740 | ||
|  | 606281a4a5 | ||
|  | c5f23493ab | ||
|  | db515195f0 | ||
|  | 9aa57f362b | ||
|  | 6977b68b72 | ||
|  | 8d8717d421 | ||
|  | 981ad74870 | ||
|  | 021f37ff71 | ||
|  | 511762cbf3 | ||
|  | 466d7461b7 | ||
|  | 1522afe2ec | ||
|  | 9c73c4c584 | ||
|  | 8f206ce319 | ||
|  | 65c59c9a09 | ||
|  | e044e2b765 | ||
|  | 7805c683e3 | ||
|  | e38c0c3969 | ||
|  | 2cebd0a083 | ||
|  | c0e03ae17d | ||
|  | 9060522414 | ||
|  | bb4eb32b1c | ||
|  | 30f991effa | ||
|  | fc071a5ebe | ||
|  | 6082b22922 | ||
|  | 5635687a3e | ||
|  | a3f1009170 | ||
|  | 79c5f34156 | ||
|  | 928db9bc42 | ||
|  | c4bea197ab | ||
|  | e8878fe6ac | ||
|  | f344239bef | ||
|  | 4ed3964b35 | ||
|  | 11966c2098 | ||
|  | 0d1bb72306 | ||
|  | 4c9765b52d | ||
|  | 5f514b0d16 | ||
|  | 01f346f239 | ||
|  | be1b1a6489 | ||
|  | ae65d5ff78 | ||
|  | 7fc07c31a0 | ||
|  | f2eda3aa6d | ||
|  | ac9d88e5a2 | ||
|  | 598caf6f78 | ||
|  | 77509b0913 | ||
|  | 8b47c5adf7 | ||
|  | a3bcf0f39e | ||
|  | be702c2b61 | ||
|  | 54f6144ef2 | ||
|  | a020ab640d | ||
|  | 7875826bd9 | ||
|  | f7be1e97df | ||
|  | 48a2c8e41c | ||
|  | 358f47443e | ||
|  | 3b9e155807 | ||
|  | 2083e4bc16 | ||
|  | c823879097 | ||
|  | 4bc2305ed3 | ||
|  | 99d779a546 | ||
|  | 6e460cd652 | ||
|  | 7c2af10bbd | ||
|  | 7af9d16208 | ||
|  | 598a257ae1 | ||
|  | b3f162a8a6 | ||
|  | 4aa3496092 | ||
|  | bbe6a5c07b | ||
|  | 20e47d9102 | ||
|  | 21c455cf20 | ||
|  | 667b2a4078 | ||
|  | 4ae07d91a4 | ||
|  | 7bdf13ebdc | ||
|  | 807feef176 | ||
|  | 7202038649 | ||
|  | dd710dbeb7 | ||
|  | f26e250648 | ||
|  | 80790cba17 | ||
|  | 2e6e5cbd03 | ||
|  | 241fb5093a | ||
|  | ab36ea7844 | ||
|  | cfef9d9df2 | ||
|  | 9ce69fbdef | ||
|  | 1a6dfe1f6b | ||
|  | e053eb6f17 | ||
|  | 780936eff9 | ||
|  | 0503253cfe | ||
|  | 39331e41a8 | ||
|  | 044dc6a221 | ||
|  | 38f5024ed0 | ||
|  | 479878503d | ||
|  | 6f6c1f7fec | ||
|  | e50bf21a84 | ||
|  | d66875f903 | ||
|  | 707f84e2e4 | ||
|  | f94298e867 | ||
|  | b995a11d63 | ||
|  | e1abf103c0 | ||
|  | f01a668d53 | ||
|  | 8cd4923e72 | ||
|  | cd90b9761a | ||
|  | e82976e001 | ||
|  | f0f5f41fb9 | ||
|  | c9e9e8dee2 | ||
|  | 0861c47e54 | ||
|  | 8bf68b7efd | ||
|  | e1e86763e3 | ||
|  | b22aef7fff | ||
|  | b9a175f5c2 | ||
|  | a2016a2953 | ||
|  | c38d405cfd | ||
|  | 8c98234c07 | ||
|  | d046af2e91 | ||
|  | 943238faba | ||
|  | 2b67f1f66f | ||
|  | 943811fad6 | ||
|  | 2ad1fd725a | ||
|  | 7129f03dc9 | ||
|  | 29b8b6911e | ||
|  | e7baf44a2e | ||
|  | 74ef79ea23 | ||
|  | 748254b6c5 | ||
|  | a08a428787 | ||
|  | 3eeea2bb2b | ||
|  | da93dab828 | ||
|  | c2dac39da1 | ||
|  | e54ee89330 | ||
|  | fdd3f2abef | ||
|  | 517917cd7c | ||
|  | d97d3a6726 | ||
|  | 6c75052a13 | ||
|  | a8df674dcf | ||
|  | abd569701f | ||
|  | 7e3fe48b80 | ||
|  | 8cf9385938 | ||
|  | 519ed8bde5 | ||
|  | 46a61ce9c8 | ||
|  | 778188ed34 | ||
|  | 88603810a8 | ||
|  | c7647b4938 | ||
|  | af71443b61 | ||
|  | c57876c116 | ||
|  | 0d81fac3fc | ||
|  | db287c4d31 | ||
|  | 4d86668af3 | ||
|  | b93141992e | ||
|  | 18d66d7432 | ||
|  | a3e4c85ec0 | ||
|  | bee86b5ac7 | ||
|  | 0ba51d62fa | ||
|  | 268d1edc8f | ||
|  | 580e7fa774 | ||
|  | 7c72780820 | ||
|  | 46c266661c | ||
|  | 61325d7b91 | ||
|  | 68e8eb2435 | ||
|  | 3f8aa13e68 | ||
|  | 08279047ae | ||
|  | 3dd4968c41 | ||
|  | ba1ca68977 | ||
|  | 81a5b1b4c8 | ||
|  | 52e6ce95cf | ||
|  | d547718fdd | ||
|  | 56f7515ecd | ||
|  | af4e74c39d | ||
|  | 27c02b5a56 | ||
|  | f6b7940b76 | ||
|  | f1b91a119d | ||
|  | 630de7481e | ||
|  | fadee5e87b | ||
|  | 35d8281f4d | ||
|  | 67d9c8da0b | ||
|  | 00de5c711a | ||
|  | b935c80dbd | ||
|  | 22c6630412 | ||
|  | 1a1cfd1adc | ||
|  | 240fb871b6 | ||
|  | b2c4221429 | ||
|  | d131ef57da | ||
|  | 97de552e06 | ||
|  | 281fa25844 | ||
|  | 454f552691 | ||
|  | 7258048403 | ||
|  | bd3eaf4f5e | ||
|  | 15f7472091 | ||
|  | a041a6b198 | ||
|  | 7582da9650 | ||
|  | 7a6bfd3336 | ||
|  | 1b9873cae9 | ||
|  | e86f21ae7b | ||
|  | ccbbd0d766 | ||
|  | 93212125e3 | ||
|  | be3b798dd6 | ||
|  | 8128d6ca26 | ||
|  | 194247caae | ||
|  | cd0654026a | ||
|  | 14ab1514dc | ||
|  | 40242294d8 | ||
|  | 996eccf5b7 | ||
|  | b39ce8cc58 | ||
|  | e9de061b84 | ||
|  | 33f0aed5ea | ||
|  | 0ca1c8aac3 | ||
|  | 2c550c284d | ||
|  | 87815586be | ||
|  | 09d6383621 | ||
|  | 188ef84c4f | ||
|  | a5c520664a | ||
|  | 39b0077725 | ||
|  | e2a9caf760 | ||
|  | bc79796c38 | ||
|  | b1db81d8ac | ||
|  | 38d7011487 | ||
|  | ae7db879d9 | ||
|  | dd34905ea9 | ||
|  | 3812e6f3cb | ||
|  | 627175694d | ||
|  | 82cf6c9577 | ||
|  | 63a1186d3e | ||
|  | f75f636e27 | ||
|  | 615dc7fd35 | ||
|  | 52b6b057f0 | ||
|  | 7b3faef4b3 | ||
|  | 7758880f3f | ||
|  | d04903edb2 | ||
|  | a63d5c95a8 | ||
|  | bb66950197 | ||
|  | c4cc30ccc6 | ||
|  | 9cd54baca4 | ||
|  | 7ac687a0a9 | ||
|  | 83ae1021f6 | ||
|  | 033fccccc7 | ||
|  | df99a9fb57 | ||
|  | 67e3bc6380 | ||
|  | d6b69e1347 | ||
|  | 4bd055cf97 | ||
|  | 4b291b2cf8 | ||
|  | 89870ad539 | ||
|  | 5bc03af75f | ||
|  | 30ec5c58fe | ||
|  | a4b447256b | ||
|  | 1c9a7b8c61 | ||
|  | d06573de6c | ||
|  | 6c2c561d8f | ||
|  | e5309a4601 | ||
|  | e9f98fb6eb | ||
|  | b351266b2d | ||
|  | fd95560c66 | ||
|  | 788f8fa951 | ||
|  | 89dc466b23 | ||
|  | ab8d7d2e78 | ||
|  | a002ccfce3 | ||
|  | 693d5da1b9 | ||
|  | 8ddc37d528 | ||
|  | 0cb2652f51 | ||
|  | fe8e7ab5b8 | ||
|  | d531963f95 | ||
|  | d578ed7327 | ||
|  | 10528c973a | ||
|  | 56a1ed4220 | ||
|  | 37b6edb28c | ||
|  | 44a2b85dba | ||
|  | 77c8d60092 | ||
|  | b33c8cec0b | ||
|  | 52df1d63fe | ||
|  | c84378d649 | ||
|  | 12dccc4fdd | ||
|  | 32e44816c9 | ||
|  | 23c74c9f2e | ||
|  | 9a82d96e68 | ||
|  | d9589878fb | ||
|  | 703de5331b | ||
|  | d3e4d56a0d | ||
|  | adf82d72ae | ||
|  | 25027d6df8 | ||
|  | e56dfeb7d5 | ||
|  | 5ca7fff7f6 | ||
|  | dfa1f3fc00 | ||
|  | b26c45af2b | ||
|  | 626da4c0ae | ||
|  | 9c02612f65 | ||
|  | b3f4f6bb21 | ||
|  | 2cac58d9c0 | ||
|  | a553085689 | ||
|  | 6dd63e1702 | ||
|  | 868ab7a5c8 | ||
|  | 23c26d64ee | ||
|  | 63f9ec9c38 | ||
|  | 40db06204b | ||
|  | 4755bb2f33 | ||
|  | 45453b20fa | ||
|  | 40d2421db9 | ||
|  | af749f1864 | ||
|  | 1576ad85b8 | ||
|  | 2a2ea759d1 | ||
|  | b4ee7bdcbe | ||
|  | 146991efda | ||
|  | ab94bbaece | ||
|  | 5a706296f2 | ||
|  | 5b3354b8ce | ||
|  | 7751fb24eb | ||
|  | f85f3b68aa | ||
|  | b361608693 | ||
|  | cdda9a18ab | ||
|  | 3686f95832 | ||
|  | 2cb011f595 | ||
|  | b7199a7a9b | ||
|  | 14eb56cf30 | ||
|  | ff2911d070 | ||
|  | f07fcd3d54 | ||
|  | 0e4b4c1a31 | ||
|  | 154d8470ab | ||
|  | c9520480c2 | ||
|  | 05c3486347 | ||
|  | 0231db05b4 | ||
|  | 4dc379c601 | ||
|  | 8f6463ba7a | ||
|  | aff334ffb4 | ||
|  | 28da781194 | ||
|  | 51a02caea3 | ||
|  | 839bc7b3a8 | ||
|  | 9c79fafeeb | ||
|  | c51e590591 | ||
|  | 9c4b336f3b | ||
|  | aa8fda5eae | ||
|  | 8b22101236 | ||
|  | 3c1d5e0393 | ||
|  | 03598d395b | ||
|  | 9d61cb64a2 | ||
|  | ba3f5b318c | ||
|  | 62e17c659e | ||
|  | 41748c3ae4 | ||
|  | 65a317010b | ||
|  | a887794313 | ||
|  | 77e1ce2877 | ||
|  | 470a4f6e5f | ||
|  | 94141233f0 | ||
|  | 467c8b31c3 | ||
|  | ff17ac53df | ||
|  | 55ba4356f2 | ||
|  | 804b0ff2f2 | ||
|  | 818541d4d7 | ||
|  | 1b199730d2 | ||
|  | f8f685193d | ||
|  | 6e535f8cef | ||
|  | 23340c46e6 | ||
|  | 5c15f5fe04 | ||
|  | ba7e9ed788 | ||
|  | 9ccc8cfb25 | ||
|  | 9810bde68b | ||
|  | 251798a778 | ||
|  | 91f4ccf087 | ||
|  | 73306a1533 | ||
|  | b3eb629785 | ||
|  | aa0b5466a9 | ||
|  | becee5e393 | ||
|  | 59e66dfce5 | ||
|  | 9c59df5e9c | ||
|  | 2a88b25712 | ||
|  | b952f814c1 | ||
|  | f90e3817e8 | ||
|  | 6d6f8b28d7 | ||
|  | 118d56fc40 | ||
|  | f352c34136 | ||
|  | fbf90e6981 | ||
|  | 607faace07 | ||
|  | 521109d3f2 | ||
|  | ec25bdb9f9 | ||
|  | 685962545a | ||
|  | 34d29e7a10 | ||
|  | 05f3e60366 | ||
|  | 5aa1220e5a | ||
|  | c1919c6b24 | ||
|  | 6349e2e28c | ||
|  | e642365613 | ||
|  | ac4086d0ac | ||
|  | d5ff301d90 | ||
|  | 575d4ab431 | ||
|  | ede2be1f66 | ||
|  | d134a993d0 | ||
|  | 86cc6df374 | ||
|  | 32920ca65c | ||
|  | 3ac708ddcb | ||
|  | 0dac0c3a5b | ||
|  | 9810120aff | ||
|  | ae6e844143 | ||
|  | a34e1c0747 | ||
|  | c29ed24a06 | ||
|  | 619621f239 | ||
|  | ff5cd9b592 | ||
|  | af855ef7b4 | ||
|  | 6559d63d3c | ||
|  | 4758cc0c8e | ||
|  | e4ed829661 | ||
|  | 2968e5b61b | ||
|  | 7d274e8088 | ||
|  | 6c2eb6eef3 | ||
|  | 95257d2ee1 | ||
|  | 707d355d4a | ||
|  | 73ba7ed2d2 | ||
|  | 55addfefc8 | ||
|  | 0ecd85cc66 | ||
|  | a9fe3f98c5 | ||
|  | 77b2a88819 | ||
|  | 44621ad28c | ||
|  | 232e2c1e7d | ||
|  | ad3625bef3 | ||
|  | 7c4bf602f0 | ||
|  | ffdd693ff6 | ||
|  | 85b0a47fe8 | ||
|  | 78822a8015 | ||
|  | 55cef21fbe | ||
|  | 2691ac1307 | ||
|  | a51851247e | ||
|  | 0e532a3634 | ||
|  | 883422dc21 | ||
|  | c9daf16388 | ||
|  | b22945e185 | ||
|  | 71150bcaaf | ||
|  | 8c56d1a338 | ||
|  | a49b537d9c | ||
|  | 45328ab719 | ||
|  | 4b755dc58d | ||
|  | 0f29e893f4 | ||
|  | e3adf93a74 | ||
|  | 0d7d5a0318 | ||
|  | 81f88dd998 | ||
|  | b6bfa905db | ||
|  | c0b0f3f0f7 | ||
|  | 16d7b89cb1 | ||
|  | a4560fa20d | ||
|  | fbdb6e6e78 | ||
|  | 8d58f33a28 | ||
|  | 9398222db7 | ||
|  | d2a2362be5 | ||
|  | 4c0a3721d0 | ||
|  | ba2d09f6fb | ||
|  | 7243e65b51 | ||
|  | 3bf4a8fbe2 | ||
|  | 23a6602cbf | ||
|  | 822b94c45d | ||
|  | 0a776c3fd5 | ||
|  | d7378a96ad | ||
|  | db4c6111fd | ||
|  | 2da7fa0397 | ||
|  | 0d58e8d1ad | ||
|  | dad76e0478 | ||
|  | 79aab5aab8 | ||
|  | b02c651961 | ||
|  | 0617a1b0e0 | ||
|  | 06749e71f2 | ||
|  | 6622027c7c | ||
|  | 401c171bbd | ||
|  | a1e766e180 | ||
|  | 63bb770b9c | ||
|  | b3de9a040b | ||
|  | a59dbc4c79 | ||
|  | 40deefa868 | ||
|  | 491de0cf64 | ||
|  | c7b24f4e9c | ||
|  | 27a7563e33 | ||
|  | 25725e9b2f | ||
|  | 819de02101 | ||
|  | ce851a5929 | ||
|  | 7e390ef516 | ||
|  | fb23bd5d26 | ||
|  | 6974f54bfd | ||
|  | aaf5aa4506 | ||
|  | 371b6e3c86 | ||
|  | 9297055ad8 | ||
|  | 9e96089da6 | ||
|  | a79868fadc | ||
|  | 84a0810546 | ||
|  | d9fbb5e25c | ||
|  | e97aa6515b | ||
|  | 6bcfba43c8 | ||
|  | 0c83ee736c | ||
|  | ca55dfe1c6 | ||
|  | 4da33c2bc2 | ||
|  | 2d56be0ebb | ||
|  | 5780dc2b15 | ||
|  | 764bf59d4d | ||
|  | 6742dd8454 | ||
|  | 3ac755bd2f | ||
|  | 7543709ecf | ||
|  | 3ed72c4e46 | ||
|  | 477fa15859 | ||
|  | 1048348ae6 | ||
|  | 390eb9cb61 | ||
|  | 5a1c936ede | ||
|  | 47ad6538f1 | ||
|  | 9be44d8330 | ||
|  | a4b354b33f | ||
|  | a70b864c55 | ||
|  | 3bd5fc0f90 | ||
|  | aabfb792af | ||
|  | 64af364b02 | ||
|  | f29e311b73 | ||
|  | a914ce2bd2 | ||
|  | b42a7c89e7 | ||
|  | cf14504fd5 | ||
|  | b84829336d | ||
|  | ba822acb23 | ||
|  | d969e59911 | ||
|  | 936b6148ff | ||
|  | f5dd233a3b | ||
|  | 48ce6c32c1 | ||
|  | 4990239855 | ||
|  | fc7f109cb2 | ||
|  | da092e653d | ||
|  | bf29417136 | ||
|  | 89cd9e8ddd | ||
|  | d970813c20 | ||
|  | 93de7cf0c0 | ||
|  | 95fabeae73 | ||
|  | 83a7f10c75 | ||
|  | 0a5c9095ac | ||
|  | 1f17731369 | ||
|  | 8e32d1913b | ||
|  | e10a82a501 | ||
|  | ce47f200d5 | ||
|  | 85dd45cb81 | ||
|  | 32340252b2 | ||
|  | 969dd088a2 | ||
|  | 9ef3fc84f9 | ||
|  | 380514941c | ||
|  | 07a3c37a23 | ||
|  | 8f0832d340 | ||
|  | 2084201c8f | ||
|  | 70359e5d27 | ||
|  | 7ff13c3e3e | ||
|  | 60ff50a675 | ||
|  | ba3967aa16 | ||
|  | 4235cef1b2 | ||
|  | f81ceaef8a | ||
|  | 817ac8f256 | ||
|  | c76d58d532 | ||
|  | f25139424a | ||
|  | 36ffdf548d | ||
|  | ca2ff214c4 | 
							
								
								
									
										2
									
								
								.github/ISSUE_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/ISSUE_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							| @@ -8,7 +8,7 @@ DO NOT FILE ISSUES FOR GENERAL SUPPORT QUESTIONS. | ||||
| The issue tracker is for reporting bugs and feature requests only. | ||||
| For end-user related support questions, please refer to one of the following: | ||||
|  | ||||
| - the Traefik community forum: https://community.containo.us/ | ||||
| - the Traefik community forum: https://community.traefik.io/ | ||||
|  | ||||
| --> | ||||
|  | ||||
|   | ||||
							
								
								
									
										10
									
								
								.github/ISSUE_TEMPLATE/bug_report.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.github/ISSUE_TEMPLATE/bug_report.yml
									
									
									
									
										vendored
									
									
								
							| @@ -6,16 +6,18 @@ body: | ||||
|     attributes: | ||||
|       label: Welcome! | ||||
|       description: | | ||||
|         The issue tracker is for reporting bugs and feature requests only. For end-user related support questions, please refer to one of the following: | ||||
|         - the Traefik community forum: https://community.containo.us/ | ||||
|         The issue tracker is for reporting bugs and feature requests only. | ||||
|         For end-user related support questions, please use the [Traefik community forum](https://community.traefik.io/). | ||||
|  | ||||
|         The configurations between 1.X and 2.X are NOT compatible. Please have a look [here](https://doc.traefik.io/traefik/getting-started/configuration-overview/). | ||||
|         All new/updated issues are triaged regularly by the maintainers. | ||||
|         All issues closed by a bot are subsequently double-checked by the maintainers. | ||||
|  | ||||
|         DO NOT FILE ISSUES FOR GENERAL SUPPORT QUESTIONS. | ||||
|  | ||||
|       options: | ||||
|         - label: Yes, I've searched similar issues on [GitHub](https://github.com/traefik/traefik/issues) and didn't find any. | ||||
|           required: true | ||||
|         - label: Yes, I've searched similar issues on the [Traefik community forum](https://community.containo.us) and didn't find any. | ||||
|         - label: Yes, I've searched similar issues on the [Traefik community forum](https://community.traefik.io) and didn't find any. | ||||
|           required: true | ||||
|  | ||||
|   - type: textarea | ||||
|   | ||||
							
								
								
									
										4
									
								
								.github/ISSUE_TEMPLATE/feature-request.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/ISSUE_TEMPLATE/feature-request.yml
									
									
									
									
										vendored
									
									
								
							| @@ -7,13 +7,13 @@ body: | ||||
|       label: Welcome! | ||||
|       description: | | ||||
|         The issue tracker is for reporting bugs and feature requests only. For end-user related support questions, please refer to one of the following: | ||||
|         - the Traefik community forum: https://community.containo.us/ | ||||
|         - the Traefik community forum: https://community.traefik.io/ | ||||
|  | ||||
|         DO NOT FILE ISSUES FOR GENERAL SUPPORT QUESTIONS. | ||||
|       options: | ||||
|         - label: Yes, I've searched similar issues on [GitHub](https://github.com/traefik/traefik/issues) and didn't find any. | ||||
|           required: true | ||||
|         - label: Yes, I've searched similar issues on the [Traefik community forum](https://community.containo.us) and didn't find any. | ||||
|         - label: Yes, I've searched similar issues on the [Traefik community forum](https://community.traefik.io) and didn't find any. | ||||
|           required: true | ||||
|  | ||||
|   - type: textarea | ||||
|   | ||||
							
								
								
									
										12
									
								
								.github/PULL_REQUEST_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/PULL_REQUEST_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							| @@ -2,16 +2,16 @@ | ||||
| PLEASE READ THIS MESSAGE. | ||||
|  | ||||
| Documentation fixes or enhancements: | ||||
| - for Traefik v1: use branch v1.7 | ||||
| - for Traefik v2: use branch v2.5 | ||||
| - for Traefik v2: use branch v2.10 | ||||
| - for Traefik v3: use branch v3.0 | ||||
|  | ||||
| Bug fixes: | ||||
| - for Traefik v1: use branch v1.7 | ||||
| - for Traefik v2: use branch v2.5 | ||||
| - for Traefik v2: use branch v2.10 | ||||
| - for Traefik v3: use branch v3.0 | ||||
|  | ||||
| Enhancements: | ||||
| - for Traefik v1: we only accept bug fixes | ||||
| - for Traefik v2: use branch master | ||||
| - for Traefik v2: we only accept bug fixes | ||||
| - for Traefik v3: use branch master | ||||
|  | ||||
| HOW TO WRITE A GOOD PULL REQUEST? https://doc.traefik.io/traefik/contributing/submitting-pull-requests/ | ||||
|  | ||||
|   | ||||
							
								
								
									
										13
									
								
								.github/workflows/build.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								.github/workflows/build.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -6,9 +6,9 @@ on: | ||||
|       - '*' | ||||
|  | ||||
| env: | ||||
|   GO_VERSION: 1.17 | ||||
|   GO_VERSION: '1.21' | ||||
|   CGO_ENABLED: 0 | ||||
|   PRE_TARGET: "" | ||||
|   IN_DOCKER: "" | ||||
|  | ||||
| jobs: | ||||
|  | ||||
| @@ -23,8 +23,8 @@ jobs: | ||||
|  | ||||
|       - name: Build webui | ||||
|         run: | | ||||
|           make generate-webui | ||||
|           tar czvf webui.tar.gz ./static/ | ||||
|           make clean-webui generate-webui | ||||
|           tar czvf webui.tar.gz ./webui/static/ | ||||
|  | ||||
|       - name: Artifact webui | ||||
|         uses: actions/upload-artifact@v2 | ||||
| @@ -56,7 +56,7 @@ jobs: | ||||
|           fetch-depth: 0 | ||||
|  | ||||
|       - name: Cache Go modules | ||||
|         uses: actions/cache@v2 | ||||
|         uses: actions/cache@v3 | ||||
|         with: | ||||
|           path: | | ||||
|             ~/go/pkg/mod | ||||
| @@ -66,9 +66,6 @@ jobs: | ||||
|           key: ${{ runner.os }}-build-go-${{ hashFiles('**/go.sum') }} | ||||
|           restore-keys: ${{ runner.os }}-build-go- | ||||
|  | ||||
|       - name: Installing dependencies | ||||
|         run: go install github.com/containous/go-bindata/go-bindata@v1.0.0 | ||||
|  | ||||
|       - name: Artifact webui | ||||
|         uses: actions/download-artifact@v2 | ||||
|         with: | ||||
|   | ||||
							
								
								
									
										4
									
								
								.github/workflows/check_doc.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/check_doc.yml
									
									
									
									
										vendored
									
									
								
							| @@ -19,3 +19,7 @@ jobs: | ||||
|  | ||||
|       - name: Check documentation | ||||
|         run: make docs-pull-images docs | ||||
|         env: | ||||
|           # These variables are not passed to workflows that are triggered by a pull request from a fork. | ||||
|           DOCS_VERIFY_SKIP: ${{ vars.DOCS_VERIFY_SKIP }} | ||||
|           DOCS_LINT_SKIP: ${{ vars.DOCS_LINT_SKIP }} | ||||
|   | ||||
							
								
								
									
										64
									
								
								.github/workflows/codeql.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								.github/workflows/codeql.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| name: "CodeQL" | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - master | ||||
|       - v* | ||||
|   schedule: | ||||
|     - cron: '11 22 * * 1' | ||||
|  | ||||
| jobs: | ||||
|   analyze: | ||||
|     name: Analyze | ||||
|     runs-on: ubuntu-latest | ||||
|     permissions: | ||||
|       actions: read | ||||
|       contents: read | ||||
|       security-events: write | ||||
|  | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         language: [ 'javascript', 'go' ] | ||||
|         # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] | ||||
|         # Use only 'java' to analyze code written in Java, Kotlin or both | ||||
|         # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both | ||||
|         # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support | ||||
|  | ||||
|     steps: | ||||
|     - name: Checkout repository | ||||
|       uses: actions/checkout@v3 | ||||
|  | ||||
|     # Initializes the CodeQL tools for scanning. | ||||
|     - name: Initialize CodeQL | ||||
|       uses: github/codeql-action/init@v2 | ||||
|       with: | ||||
|         languages: ${{ matrix.language }} | ||||
|         # If you wish to specify custom queries, you can do so here or in a config file. | ||||
|         # By default, queries listed here will override any specified in a config file. | ||||
|         # Prefix the list here with "+" to use these queries and those in the config file. | ||||
|  | ||||
|         # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs | ||||
|         # queries: security-extended,security-and-quality | ||||
|  | ||||
|  | ||||
|     # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). | ||||
|     # If this step fails, then you should remove it and run the build manually (see below) | ||||
|     - name: Autobuild | ||||
|       uses: github/codeql-action/autobuild@v2 | ||||
|  | ||||
|     # ℹ️ Command-line programs to run using the OS shell. | ||||
|     # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun | ||||
|  | ||||
|     #   If the Autobuild fails above, remove it and uncomment the following three lines. | ||||
|     #   modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. | ||||
|  | ||||
|     # - run: | | ||||
|     #     echo "Run, Build Application using script" | ||||
|     #     ./location_of_script_within_repo/buildscript.sh | ||||
|  | ||||
|     - name: Perform CodeQL Analysis | ||||
|       uses: github/codeql-action/analyze@v2 | ||||
|       with: | ||||
|         category: "/language:${{matrix.language}}" | ||||
							
								
								
									
										8
									
								
								.github/workflows/documentation.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/documentation.yml
									
									
									
									
										vendored
									
									
								
							| @@ -7,7 +7,7 @@ on: | ||||
|       - v* | ||||
|  | ||||
| env: | ||||
|   STRUCTOR_VERSION: v1.11.2 | ||||
|   STRUCTOR_VERSION: v1.13.2 | ||||
|   MIXTUS_VERSION: v0.4.1 | ||||
|  | ||||
| jobs: | ||||
| @@ -41,12 +41,12 @@ jobs: | ||||
|       - name: Build documentation | ||||
|         run: $HOME/bin/structor -o traefik -r traefik --dockerfile-url="https://raw.githubusercontent.com/traefik/traefik/v1.7/docs.Dockerfile" --menu.js-url="https://raw.githubusercontent.com/traefik/structor/master/traefik-menu.js.gotmpl" --rqts-url="https://raw.githubusercontent.com/traefik/structor/master/requirements-override.txt" --force-edit-url --exp-branch=master --debug | ||||
|         env: | ||||
|           STRUCTOR_LATEST_TAG: ${{ secrets.STRUCTOR_LATEST_TAG }} | ||||
|           STRUCTOR_LATEST_TAG: ${{ vars.STRUCTOR_LATEST_TAG }} | ||||
|  | ||||
|       - name: Apply seo | ||||
|         run: $HOME/bin/seo -path=./site | ||||
|         run: $HOME/bin/seo -path=./site -product=traefik | ||||
|  | ||||
|       - name: Publish documentation | ||||
|         run: $HOME/bin/mixtus --dst-doc-path="./traefik" --dst-owner=traefik --dst-repo-name=doc --git-user-email="30906710+traefiker@users.noreply.github.com" --git-user-name=traefiker --src-doc-path="./site" --src-owner=containous --src-repo-name=traefik | ||||
|         run: $HOME/bin/mixtus --dst-doc-path="./traefik" --dst-owner=traefik --dst-repo-name=doc --git-user-email="30906710+traefiker@users.noreply.github.com" --git-user-name=traefiker --src-doc-path="./site" --src-owner=traefik --src-repo-name=traefik | ||||
|         env: | ||||
|           GITHUB_TOKEN: ${{ secrets.GH_TOKEN_REPO }} | ||||
|   | ||||
							
								
								
									
										10
									
								
								.github/workflows/test-unit.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.github/workflows/test-unit.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -6,8 +6,8 @@ on: | ||||
|       - '*' | ||||
|  | ||||
| env: | ||||
|   GO_VERSION: 1.17 | ||||
|   PRE_TARGET: "" | ||||
|   GO_VERSION: '1.21' | ||||
|   IN_DOCKER: "" | ||||
|  | ||||
| jobs: | ||||
|  | ||||
| @@ -31,7 +31,7 @@ jobs: | ||||
|           fetch-depth: 0 | ||||
|  | ||||
|       - name: Cache Go modules | ||||
|         uses: actions/cache@v2 | ||||
|         uses: actions/cache@v3 | ||||
|         with: | ||||
|           path: | | ||||
|             ~/go/pkg/mod | ||||
| @@ -39,8 +39,8 @@ jobs: | ||||
|           key: ${{ runner.os }}-test-unit-go-${{ hashFiles('**/go.sum') }} | ||||
|           restore-keys: ${{ runner.os }}-test-unit-go- | ||||
|  | ||||
|       - name: Installing dependencies | ||||
|         run: go install github.com/containous/go-bindata/go-bindata@v1.0.0 | ||||
|       - name: Avoid generating webui | ||||
|         run: touch webui/static/index.html | ||||
|  | ||||
|       - name: Tests | ||||
|         run: make test-unit | ||||
|   | ||||
							
								
								
									
										23
									
								
								.github/workflows/validate.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								.github/workflows/validate.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -6,10 +6,10 @@ on: | ||||
|       - '*' | ||||
|  | ||||
| env: | ||||
|   GO_VERSION: 1.17 | ||||
|   GOLANGCI_LINT_VERSION: v1.43.0 | ||||
|   MISSSPELL_VERSION: v0.3.4 | ||||
|   PRE_TARGET: "" | ||||
|   GO_VERSION: '1.21' | ||||
|   GOLANGCI_LINT_VERSION: v1.54.1 | ||||
|   MISSSPELL_VERSION: v0.4.0 | ||||
|   IN_DOCKER: "" | ||||
|  | ||||
| jobs: | ||||
|  | ||||
| @@ -33,7 +33,7 @@ jobs: | ||||
|           fetch-depth: 0 | ||||
|  | ||||
|       - name: Cache Go modules | ||||
|         uses: actions/cache@v2 | ||||
|         uses: actions/cache@v3 | ||||
|         with: | ||||
|           path: | | ||||
|             ~/go/pkg/mod | ||||
| @@ -41,14 +41,14 @@ jobs: | ||||
|           key: ${{ runner.os }}-validate-go-${{ hashFiles('**/go.sum') }} | ||||
|           restore-keys: ${{ runner.os }}-validate-go- | ||||
|  | ||||
|       - name: Installing dependencies | ||||
|         run: go install github.com/containous/go-bindata/go-bindata@v1.0.0 | ||||
|  | ||||
|       - name: Install golangci-lint ${{ env.GOLANGCI_LINT_VERSION }} | ||||
|         run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin ${GOLANGCI_LINT_VERSION} | ||||
|  | ||||
|       - name: Install missspell ${{ env.MISSSPELL_VERSION }} | ||||
|         run: curl -sfL https://raw.githubusercontent.com/client9/misspell/master/install-misspell.sh | sh -s -- -b $(go env GOPATH)/bin ${MISSSPELL_VERSION} | ||||
|         run: curl -sfL https://raw.githubusercontent.com/golangci/misspell/master/install-misspell.sh | sh -s -- -b $(go env GOPATH)/bin ${MISSSPELL_VERSION} | ||||
|  | ||||
|       - name: Avoid generating webui | ||||
|         run: touch webui/static/index.html | ||||
|  | ||||
|       - name: Validate | ||||
|         run: make validate | ||||
| @@ -73,7 +73,7 @@ jobs: | ||||
|           fetch-depth: 0 | ||||
|  | ||||
|       - name: Cache Go modules | ||||
|         uses: actions/cache@v2 | ||||
|         uses: actions/cache@v3 | ||||
|         with: | ||||
|           path: | | ||||
|             ~/go/pkg/mod | ||||
| @@ -81,9 +81,6 @@ jobs: | ||||
|           key: ${{ runner.os }}-validate-generate-go-${{ hashFiles('**/go.sum') }} | ||||
|           restore-keys: ${{ runner.os }}-validate-generate-go- | ||||
|  | ||||
|       - name: Installing dependencies | ||||
|         run: go install github.com/containous/go-bindata/go-bindata@v1.0.0 | ||||
|  | ||||
|       - name: go generate | ||||
|         run: | | ||||
|           go generate | ||||
|   | ||||
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -5,10 +5,8 @@ | ||||
| .DS_Store | ||||
| /dist | ||||
| /webui/.tmp/ | ||||
| /webui/static/ | ||||
| /site/ | ||||
| /docs/site/ | ||||
| /static/ | ||||
| /autogen/ | ||||
| /traefik | ||||
| /traefik.toml | ||||
| @@ -20,3 +18,4 @@ vendor/ | ||||
| plugins-storage/ | ||||
| plugins-local/ | ||||
| traefik_changelog.md | ||||
| integration/tailscale.secret | ||||
|   | ||||
							
								
								
									
										159
									
								
								.golangci.toml
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								.golangci.toml
									
									
									
									
									
								
							| @@ -1,159 +0,0 @@ | ||||
| [run] | ||||
|   timeout = "10m" | ||||
|   skip-files = [] | ||||
|   skip-dirs = [ | ||||
|     "pkg/provider/kubernetes/crd/generated/", | ||||
|   ] | ||||
|  | ||||
| [linters-settings] | ||||
|  | ||||
|   [linters-settings.govet] | ||||
|     check-shadowing = false | ||||
|  | ||||
|   [linters-settings.golint] | ||||
|     min-confidence = 0.0 | ||||
|  | ||||
|   [linters-settings.gocyclo] | ||||
|     min-complexity = 14.0 | ||||
|  | ||||
|   [linters-settings.goconst] | ||||
|     min-len = 3.0 | ||||
|     min-occurrences = 4.0 | ||||
|  | ||||
|   [linters-settings.misspell] | ||||
|     locale = "US" | ||||
|  | ||||
|   [linters-settings.funlen] | ||||
|     lines = 230 # default 60 | ||||
|     statements = 120 # default 40 | ||||
|  | ||||
|   [linters-settings.forbidigo] | ||||
|     forbid = [ | ||||
|       '^print(ln)?$', | ||||
|       '^spew\.Print(f|ln)?$', | ||||
|       '^spew\.Dump$', | ||||
|     ] | ||||
|  | ||||
|   [linters-settings.depguard] | ||||
|     list-type = "blacklist" | ||||
|     include-go-root = false | ||||
|     packages = ["github.com/pkg/errors"] | ||||
|  | ||||
|   [linters-settings.godox] | ||||
|     keywords = ["FIXME"] | ||||
|  | ||||
|   [linters-settings.importas] | ||||
|     corev1 = "k8s.io/api/core/v1" | ||||
|     networkingv1beta1 = "k8s.io/api/networking/v1beta1" | ||||
|     extensionsv1beta1 = "k8s.io/api/extensions/v1beta1" | ||||
|     metav1 = "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
|     kubeerror = "k8s.io/apimachinery/pkg/api/errors" | ||||
|     composeapi = "github.com/docker/compose/v2/pkg/api" | ||||
|  | ||||
|   [linters-settings.gomoddirectives] | ||||
|     replace-allow-list = [ | ||||
|       "github.com/abbot/go-http-auth", | ||||
|       "github.com/go-check/check", | ||||
|       "github.com/gorilla/mux", | ||||
|       "github.com/mailgun/minheap", | ||||
|       "github.com/mailgun/multibuf", | ||||
|       "github.com/jaguilar/vt100", | ||||
|     ] | ||||
|  | ||||
| [linters] | ||||
|   enable-all = true | ||||
|   disable = [ | ||||
|     "scopelint", # Deprecated | ||||
|     "interfacer", # Deprecated | ||||
|     "maligned", # Deprecated | ||||
|     "golint", # Deprecated | ||||
|     "sqlclosecheck", # Not relevant (SQL) | ||||
|     "rowserrcheck", # Not relevant (SQL) | ||||
|     "lll", # Not relevant | ||||
|     "gocyclo", # FIXME must be fixed | ||||
|     "cyclop", # Duplicate of gocyclo | ||||
|     "gocognit", # Too strict | ||||
|     "nestif", # Too many false-positive. | ||||
|     "prealloc", # Too many false-positive. | ||||
|     "makezero", # Not relevant | ||||
|     "ifshort", # Not relevant | ||||
|     "dupl", # Too strict | ||||
|     "gosec", # Too strict | ||||
|     "gochecknoinits", | ||||
|     "gochecknoglobals", | ||||
|     "wsl", # Too strict | ||||
|     "nlreturn", # Not relevant | ||||
|     "gomnd", # Too strict | ||||
|     "stylecheck", # skip because report issues related to some generated files. | ||||
|     "testpackage", # Too strict | ||||
|     "tparallel", # Not relevant | ||||
|     "paralleltest", # Not relevant | ||||
|     "exhaustive", # Not relevant | ||||
|     "exhaustivestruct", # Not relevant | ||||
|     "goerr113", # Too strict | ||||
|     "wrapcheck", # Too strict | ||||
|     "noctx", # Too strict | ||||
|     "bodyclose", # Too many false-positive and panics. | ||||
|     "unparam", # Too strict | ||||
|     "godox", # Too strict | ||||
|     "forcetypeassert", # Too strict | ||||
|     "tagliatelle", # Not compatible with current tags. | ||||
|     "varnamelen", # not relevant | ||||
|     "nilnil", # not relevant | ||||
|     "ireturn", # not relevant | ||||
|     "contextcheck", # too many false-positive | ||||
|   ] | ||||
|  | ||||
| [issues] | ||||
|   exclude-use-default = false | ||||
|   max-per-linter = 0 | ||||
|   max-same-issues = 0 | ||||
|   exclude = [ | ||||
|     "Error return value of .((os\\.)?std(out|err)\\..*|.*Close|.*Flush|os\\.Remove(All)?|.*printf?|os\\.(Un)?Setenv). is not checked", | ||||
|     "should have a package comment, unless it's in another file for this package", | ||||
|     "SA1019: http.CloseNotifier has been deprecated",  # FIXME must be fixed | ||||
|     "SA1019: cfg.SSLRedirect is deprecated", | ||||
|     "SA1019: cfg.SSLTemporaryRedirect is deprecated", | ||||
|     "SA1019: cfg.SSLHost is deprecated", | ||||
|     "SA1019: cfg.SSLForceHost is deprecated", | ||||
|     "SA1019: cfg.FeaturePolicy is deprecated", | ||||
|   ] | ||||
|  [[issues.exclude-rules]] | ||||
|     path = "(.+)_test.go" | ||||
|     linters = ["goconst", "funlen", "godot"] | ||||
|  [[issues.exclude-rules]] | ||||
|     path = "integration/.+_test.go" | ||||
|     text = "Error return value of `cmd\\.Process\\.Kill` is not checked" | ||||
|  [[issues.exclude-rules]] | ||||
|     path = "integration/(consul_catalog_test|constraint_test).go" | ||||
|     text = "Error return value of `(s.deregisterService|s.deregisterAgentService)` is not checked" | ||||
|  [[issues.exclude-rules]] | ||||
|     path = "integration/grpc_test.go" | ||||
|     text = "Error return value of `closer` is not checked" | ||||
|  [[issues.exclude-rules]] | ||||
|     path = "pkg/h2c/h2c.go" | ||||
|     text = "Error return value of `rw.Write` is not checked" | ||||
|  [[issues.exclude-rules]] | ||||
|     path = "pkg/provider/docker/builder_test.go" | ||||
|     text = "(U1000: func )?`(.+)` is unused" | ||||
|  [[issues.exclude-rules]] | ||||
|     path = "pkg/provider/kubernetes/builder_(endpoint|service)_test.go" | ||||
|     text = "(U1000: func )?`(.+)` is unused" | ||||
|  [[issues.exclude-rules]] | ||||
|     path = "pkg/server/service/bufferpool.go" | ||||
|     text = "SA6002: argument should be pointer-like to avoid allocations" | ||||
|  [[issues.exclude-rules]] | ||||
|     path = "cmd/configuration.go" | ||||
|     text = "string `traefik` has (\\d) occurrences, make it a constant" | ||||
|  [[issues.exclude-rules]] | ||||
|     path = "pkg/server/middleware/middlewares.go" | ||||
|     text = "Function 'buildConstructor' has too many statements" | ||||
|  [[issues.exclude-rules]] | ||||
|     path = "pkg/tracing/haystack/logger.go" | ||||
|     linters = ["goprintffuncname"] | ||||
|  [[issues.exclude-rules]] | ||||
|     path = "pkg/tracing/tracing.go" | ||||
|     text = "printf-like formatting function 'SetErrorWithEvent' should be named 'SetErrorWithEventf'" | ||||
|  [[issues.exclude-rules]] | ||||
|     path = "pkg/log/deprecated.go" | ||||
|     linters = ["godot"] | ||||
							
								
								
									
										266
									
								
								.golangci.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										266
									
								
								.golangci.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,266 @@ | ||||
| run: | ||||
|   timeout: 10m | ||||
|   skip-files: [] | ||||
|   skip-dirs: | ||||
|     - pkg/provider/kubernetes/crd/generated/ | ||||
|  | ||||
| linters-settings: | ||||
|   govet: | ||||
|     enable-all: true | ||||
|     disable: | ||||
|       - shadow | ||||
|       - fieldalignment | ||||
|   gocyclo: | ||||
|     min-complexity: 14 | ||||
|   goconst: | ||||
|     min-len: 3 | ||||
|     min-occurrences: 4 | ||||
|   misspell: | ||||
|     locale: US | ||||
|   funlen: | ||||
|     lines: -1 | ||||
|     statements: 120 | ||||
|   forbidigo: | ||||
|     forbid: | ||||
|       - ^print(ln)?$ | ||||
|       - ^spew\.Print(f|ln)?$ | ||||
|       - ^spew\.Dump$ | ||||
|   depguard: | ||||
|     rules: | ||||
|       main: | ||||
|         deny: | ||||
|           - pkg: "github.com/instana/testify" | ||||
|             desc: not allowed | ||||
|           - pkg: "github.com/pkg/errors" | ||||
|             desc: Should be replaced by standard lib errors package | ||||
|           - pkg: "k8s.io/api/networking/v1beta1" | ||||
|             desc: This API is deprecated | ||||
|           - pkg: "k8s.io/api/extensions/v1beta1" | ||||
|             desc: This API is deprecated | ||||
|   godox: | ||||
|     keywords: | ||||
|       - FIXME | ||||
|   importas: | ||||
|     no-unaliased: true | ||||
|     alias: | ||||
|       - alias: composeapi | ||||
|         pkg: github.com/docker/compose/v2/pkg/api | ||||
|  | ||||
|       # Standard Kubernetes rewrites: | ||||
|       - alias: corev1 | ||||
|         pkg: "k8s.io/api/core/v1" | ||||
|       - alias: netv1 | ||||
|         pkg: "k8s.io/api/networking/v1" | ||||
|       - alias: admv1 | ||||
|         pkg: "k8s.io/api/admission/v1" | ||||
|       - alias: admv1beta1 | ||||
|         pkg: "k8s.io/api/admission/v1beta1" | ||||
|       - alias: metav1 | ||||
|         pkg: "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
|       - alias: ktypes | ||||
|         pkg: "k8s.io/apimachinery/pkg/types" | ||||
|       - alias: kerror | ||||
|         pkg: "k8s.io/apimachinery/pkg/api/errors" | ||||
|       - alias: kclientset | ||||
|         pkg: "k8s.io/client-go/kubernetes" | ||||
|       - alias: kinformers | ||||
|         pkg: "k8s.io/client-go/informers" | ||||
|       - alias: ktesting | ||||
|         pkg: "k8s.io/client-go/testing" | ||||
|       - alias: kschema | ||||
|         pkg: "k8s.io/apimachinery/pkg/runtime/schema" | ||||
|       - alias: kscheme | ||||
|         pkg: "k8s.io/client-go/kubernetes/scheme" | ||||
|       - alias: kversion | ||||
|         pkg: "k8s.io/apimachinery/pkg/version" | ||||
|       - alias: kubefake | ||||
|         pkg: "k8s.io/client-go/kubernetes/fake" | ||||
|       - alias: discoveryfake | ||||
|         pkg: "k8s.io/client-go/discovery/fake" | ||||
|  | ||||
|       # Kubernetes Gateway rewrites: | ||||
|       - alias: gateclientset | ||||
|         pkg: "sigs.k8s.io/gateway-api/pkg/client/clientset/gateway/versioned" | ||||
|       - alias: gateinformers | ||||
|         pkg: "sigs.k8s.io/gateway-api/pkg/client/informers/gateway/externalversions" | ||||
|       - alias: gatev1alpha2 | ||||
|         pkg: "sigs.k8s.io/gateway-api/apis/v1alpha2" | ||||
|  | ||||
|       # Traefik Kubernetes rewrites: | ||||
|       - alias: containousv1alpha1 | ||||
|         pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1" | ||||
|       - alias: traefikv1alpha1 | ||||
|         pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" | ||||
|       - alias: traefikclientset | ||||
|         pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned" | ||||
|       - alias: traefikinformers | ||||
|         pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions" | ||||
|       - alias: traefikscheme | ||||
|         pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" | ||||
|       - alias: traefikcrdfake | ||||
|         pkg: "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake" | ||||
|   tagalign: | ||||
|     align: false | ||||
|     sort: true | ||||
|     order: | ||||
|       - description | ||||
|       - json | ||||
|       - toml | ||||
|       - yaml | ||||
|       - yml | ||||
|       - label | ||||
|       - label-slice-as-struct | ||||
|       - file | ||||
|       - kv | ||||
|       - export | ||||
|   revive: | ||||
|     rules: | ||||
|       - name: struct-tag | ||||
|       - name: blank-imports | ||||
|       - name: context-as-argument | ||||
|       - name: context-keys-type | ||||
|       - name: dot-imports | ||||
|       - name: error-return | ||||
|       - name: error-strings | ||||
|       - name: error-naming | ||||
|       - name: exported | ||||
|         disabled: true | ||||
|       - name: if-return | ||||
|       - name: increment-decrement | ||||
|       - name: var-naming | ||||
|       - name: var-declaration | ||||
|       - name: package-comments | ||||
|         disabled: true | ||||
|       - name: range | ||||
|       - name: receiver-naming | ||||
|       - name: time-naming | ||||
|       - name: unexported-return | ||||
|       - name: indent-error-flow | ||||
|       - name: errorf | ||||
|       - name: empty-block | ||||
|       - name: superfluous-else | ||||
|       - name: unused-parameter | ||||
|         disabled: true | ||||
|       - name: unreachable-code | ||||
|       - name: redefines-builtin-id | ||||
|   gomoddirectives: | ||||
|     replace-allow-list: | ||||
|       - github.com/abbot/go-http-auth | ||||
|       - github.com/go-check/check | ||||
|       - github.com/gorilla/mux | ||||
|       - github.com/mailgun/minheap | ||||
|       - github.com/mailgun/multibuf | ||||
|       - github.com/jaguilar/vt100 | ||||
|  | ||||
| linters: | ||||
|   enable-all: true | ||||
|   disable: | ||||
|     - deadcode # deprecated | ||||
|     - exhaustivestruct # deprecated | ||||
|     - golint # deprecated | ||||
|     - ifshort # deprecated | ||||
|     - interfacer # deprecated | ||||
|     - maligned # deprecated | ||||
|     - nosnakecase # deprecated | ||||
|     - scopelint # deprecated | ||||
|     - scopelint # deprecated | ||||
|     - structcheck # deprecated | ||||
|     - varcheck # deprecated | ||||
|     - sqlclosecheck # not relevant (SQL) | ||||
|     - rowserrcheck # not relevant (SQL) | ||||
|     - execinquery # not relevant (SQL) | ||||
|     - cyclop # duplicate of gocyclo | ||||
|     - lll # Not relevant | ||||
|     - gocyclo # FIXME must be fixed | ||||
|     - gocognit # Too strict | ||||
|     - nestif # Too many false-positive. | ||||
|     - prealloc # Too many false-positive. | ||||
|     - makezero # Not relevant | ||||
|     - dupl # Too strict | ||||
|     - gosec # Too strict | ||||
|     - gochecknoinits | ||||
|     - gochecknoglobals | ||||
|     - wsl # Too strict | ||||
|     - nlreturn # Not relevant | ||||
|     - gomnd # Too strict | ||||
|     - stylecheck # skip because report issues related to some generated files. | ||||
|     - testpackage # Too strict | ||||
|     - tparallel # Not relevant | ||||
|     - paralleltest # Not relevant | ||||
|     - exhaustive # Not relevant | ||||
|     - exhaustruct # Not relevant | ||||
|     - goerr113 # Too strict | ||||
|     - wrapcheck # Too strict | ||||
|     - noctx # Too strict | ||||
|     - bodyclose # too many false-positive | ||||
|     - forcetypeassert # Too strict | ||||
|     - tagliatelle # Too strict | ||||
|     - varnamelen # Not relevant | ||||
|     - nilnil # Not relevant | ||||
|     - ireturn # Not relevant | ||||
|     - contextcheck # too many false-positive | ||||
|     - containedctx # too many false-positive | ||||
|     - maintidx # kind of duplicate of gocyclo | ||||
|     - nonamedreturns # Too strict | ||||
|     - gosmopolitan  # not relevant | ||||
|  | ||||
| issues: | ||||
|   exclude-use-default: false | ||||
|   max-per-linter: 0 | ||||
|   max-same-issues: 0 | ||||
|   exclude: | ||||
|     - 'Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked' | ||||
|     - "should have a package comment, unless it's in another file for this package" | ||||
|   exclude-rules: | ||||
|     - path: '(.+)_test.go' | ||||
|       linters: | ||||
|         - goconst | ||||
|         - funlen | ||||
|         - godot | ||||
|     - path: '(.+)_test.go' | ||||
|       text: ' always receives ' | ||||
|       linters: | ||||
|         - unparam | ||||
|     - path: '(.+)\.go' | ||||
|       text: 'struct-tag: unknown option ''inline'' in JSON tag' | ||||
|       linters: | ||||
|         - revive | ||||
|     - path: pkg/server/service/bufferpool.go | ||||
|       text: 'SA6002: argument should be pointer-like to avoid allocations' | ||||
|     - path: pkg/server/middleware/middlewares.go | ||||
|       text: "Function 'buildConstructor' has too many statements" | ||||
|       linters: | ||||
|         - funlen | ||||
|     - path: pkg/logs/haystack.go | ||||
|       linters: | ||||
|         - goprintffuncname | ||||
|     - path: pkg/tracing/tracing.go | ||||
|       text: "printf-like formatting function 'SetErrorWithEvent' should be named 'SetErrorWithEventf'" | ||||
|       linters: | ||||
|         - goprintffuncname | ||||
|     - path: pkg/tls/tlsmanager_test.go | ||||
|       text: 'SA1019: config.ClientCAs.Subjects has been deprecated since Go 1.18' | ||||
|     - path: pkg/types/tls_test.go | ||||
|       text: 'SA1019: tlsConfig.RootCAs.Subjects has been deprecated since Go 1.18' | ||||
|     - path: pkg/provider/kubernetes/(crd|gateway)/client.go | ||||
|       linters: | ||||
|         - interfacebloat | ||||
|     - path: pkg/metrics/metrics.go | ||||
|       linters: | ||||
|         - interfacebloat | ||||
|     - path: integration/healthcheck_test.go | ||||
|       text: 'Duplicate words \(wsp2,\) found' | ||||
|       linters: | ||||
|         - dupword | ||||
|     - path: pkg/types/domain_test.go | ||||
|       text: 'Duplicate words \(sub\) found' | ||||
|       linters: | ||||
|         - dupword | ||||
|     - path: pkg/provider/kubernetes/crd/kubernetes.go | ||||
|       text: "Function 'loadConfigurationFromCRD' has too many statements" | ||||
|       linters: | ||||
|         - funlen | ||||
|     - path: pkg/provider/kubernetes/gateway/client_mock_test.go | ||||
|       text: 'unusedwrite: unused write to field' | ||||
|       linters: | ||||
|         - govet | ||||
| @@ -1,8 +1,12 @@ | ||||
| project_name: traefik | ||||
| 
 | ||||
| dist: "./dist/[[ .GOOS ]]" | ||||
| 
 | ||||
| [[ if eq .GOOS "linux" ]] | ||||
| before: | ||||
|   hooks: | ||||
|     - go generate | ||||
| [[ end ]] | ||||
| 
 | ||||
| builds: | ||||
|   - binary: traefik | ||||
| @@ -11,33 +15,35 @@ builds: | ||||
|     env: | ||||
|       - CGO_ENABLED=0 | ||||
|     ldflags: | ||||
|       - -s -w -X github.com/traefik/traefik/v2/pkg/version.Version={{.Version}} -X github.com/traefik/traefik/v2/pkg/version.Codename={{.Env.CODENAME}} -X github.com/traefik/traefik/v2/pkg/version.BuildDate={{.Date}} | ||||
| 
 | ||||
|       - -s -w -X github.com/traefik/traefik/v3/pkg/version.Version={{.Version}} -X github.com/traefik/traefik/v3/pkg/version.Codename={{.Env.CODENAME}} -X github.com/traefik/traefik/v3/pkg/version.BuildDate={{.Date}} | ||||
|     flags: | ||||
|       - -trimpath | ||||
|     goos: | ||||
|       - linux | ||||
|       - darwin | ||||
|       - windows | ||||
|       - freebsd | ||||
|       - openbsd | ||||
|       - "[[ .GOOS ]]" | ||||
|     goarch: | ||||
|       - amd64 | ||||
|       - 386 | ||||
|       - '386' | ||||
|       - arm | ||||
|       - arm64 | ||||
|       - ppc64le | ||||
|       - s390x | ||||
|       - riscv64 | ||||
|     goarm: | ||||
|       - 7 | ||||
|       - 6 | ||||
|       - 5 | ||||
|       - '7' | ||||
|       - '6' | ||||
|     ignore: | ||||
|       - goos: darwin | ||||
|         goarch: 386 | ||||
|         goarch: '386' | ||||
|       - goos: openbsd | ||||
|         goarch: arm | ||||
|       - goos: openbsd | ||||
|         goarch: arm64 | ||||
|       - goos: freebsd | ||||
|         goarch: arm | ||||
|       - goos: freebsd | ||||
|         goarch: arm64 | ||||
|       - goos: windows | ||||
|         goarch: arm | ||||
| 
 | ||||
| changelog: | ||||
|   skip: true | ||||
| @@ -3,7 +3,7 @@ name: Traefik | ||||
| agent: | ||||
|   machine: | ||||
|     type: e1-standard-4 | ||||
|     os_image: ubuntu1804 | ||||
|     os_image: ubuntu2004 | ||||
|  | ||||
| fail_fast: | ||||
|   stop: | ||||
| @@ -19,15 +19,14 @@ global_job_config: | ||||
|   prologue: | ||||
|     commands: | ||||
|       - curl -sSfL https://raw.githubusercontent.com/ldez/semgo/master/godownloader.sh | sudo sh -s -- -b "/usr/local/bin" | ||||
|       - sudo semgo go1.17 | ||||
|       - sudo semgo go1.21 | ||||
|       - export "GOPATH=$(go env GOPATH)" | ||||
|       - export "SEMAPHORE_GIT_DIR=${GOPATH}/src/github.com/traefik/${SEMAPHORE_PROJECT_NAME}" | ||||
|       - export "PATH=${GOPATH}/bin:${PATH}" | ||||
|       - mkdir -vp "${SEMAPHORE_GIT_DIR}" "${GOPATH}/bin" | ||||
|       - export GOPROXY=https://proxy.golang.org,direct | ||||
|       - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${GOPATH}/bin" v1.43.0 | ||||
|       - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${GOPATH}/bin" v1.54.1 | ||||
|       - curl -sSfL https://gist.githubusercontent.com/traefiker/6d7ac019c11d011e4f131bb2cca8900e/raw/goreleaser.sh | bash -s -- -b "${GOPATH}/bin" | ||||
|       - go install github.com/containous/go-bindata/go-bindata@v1.0.0 | ||||
|       - checkout | ||||
|       - cache restore traefik-$(checksum go.sum) | ||||
|  | ||||
| @@ -41,8 +40,8 @@ blocks: | ||||
|         - name: Test Integration | ||||
|           commands: | ||||
|             - make pull-images | ||||
|             - mkdir -p static # Avoid to generate webui | ||||
|             - PRE_TARGET="" make binary | ||||
|             - touch webui/static/index.html # Avoid generating webui | ||||
|             - IN_DOCKER="" make binary | ||||
|             - make test-integration | ||||
|             - df -h | ||||
|       epilogue: | ||||
| @@ -58,15 +57,15 @@ blocks: | ||||
|       agent: | ||||
|         machine: | ||||
|           type: e1-standard-8 | ||||
|           os_image: ubuntu1804 | ||||
|           os_image: ubuntu2004 | ||||
|       secrets: | ||||
|         - name: traefik | ||||
|       env_vars: | ||||
|         - name: GH_VERSION | ||||
|           value: 1.12.1 | ||||
|           value: 2.32.1 | ||||
|         - name: CODENAME | ||||
|           value: "brie" | ||||
|         - name: PRE_TARGET | ||||
|           value: "beaufort" | ||||
|         - name: IN_DOCKER | ||||
|           value: "" | ||||
|       prologue: | ||||
|         commands: | ||||
| @@ -74,9 +73,11 @@ blocks: | ||||
|           - curl -sSL -o /tmp/gh_${GH_VERSION}_linux_amd64.tar.gz https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_amd64.tar.gz | ||||
|           - tar -zxvf /tmp/gh_${GH_VERSION}_linux_amd64.tar.gz -C /tmp | ||||
|           - sudo mv /tmp/gh_${GH_VERSION}_linux_amd64/bin/gh /usr/local/bin/gh | ||||
|           - sudo rm -rf ~/.phpbrew ~/.kerl ~/.sbt ~/.nvm ~/.npm ~/.kiex /usr/lib/jvm /opt/az /opt/firefox /usr/lib/google-cloud-sdk ~/.rbenv ~/.pip_download_cache # Remove unnecessary data. | ||||
|           - sudo service docker stop && sudo umount /var/lib/docker && sudo service docker start # Unmounts the docker disk and the whole system disk is usable. | ||||
|       jobs: | ||||
|         - name: Release | ||||
|           commands: | ||||
|             - make release-packages | ||||
|             - gh release create ${SEMAPHORE_GIT_TAG_NAME} ./dist/traefik*.* --repo traefik/traefik --title ${SEMAPHORE_GIT_TAG_NAME} --notes ${SEMAPHORE_GIT_TAG_NAME} | ||||
|             - gh release create ${SEMAPHORE_GIT_TAG_NAME} ./dist/**/traefik*.{zip,tar.gz} ./dist/traefik*.{tar.gz,txt} --repo traefik/traefik --title ${SEMAPHORE_GIT_TAG_NAME} --notes ${SEMAPHORE_GIT_TAG_NAME} | ||||
|             - ./script/deploy.sh | ||||
|   | ||||
							
								
								
									
										1040
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										1040
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -30,18 +30,18 @@ Project maintainers have the right and responsibility to remove, edit, or reject | ||||
|  | ||||
| ## Scope | ||||
|  | ||||
| This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or our community.  | ||||
| This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or our community. | ||||
|  | ||||
| Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.  | ||||
| Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. | ||||
| Representation of a project may be further defined and clarified by project maintainers. | ||||
|  | ||||
| ## Enforcement | ||||
|  | ||||
| Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@traefik.io | ||||
|  | ||||
| All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.  | ||||
| All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. | ||||
|  | ||||
| The project team is obligated to maintain confidentiality with regard to the reporter of an incident.  | ||||
| The project team is obligated to maintain confidentiality with regard to the reporter of an incident. | ||||
|  | ||||
| Further details of specific enforcement policies may be posted separately. | ||||
|  | ||||
|   | ||||
| @@ -2,8 +2,10 @@ | ||||
|  | ||||
| Here are some guidelines that should help to start contributing to the project. | ||||
|  | ||||
| - [Submitting pull Requests](https://github.com/traefik/contributors-guide/blob/master/pr_guidelines.md) | ||||
| - [Submitting pull Requests](https://doc.traefik.io/traefik/contributing/submitting-pull-requests/) | ||||
| - [Submitting issues](https://doc.traefik.io/traefik/contributing/submitting-issues/) | ||||
| - [Submitting security issues](docs/content/contributing/submitting-security-issues.md) | ||||
| - [Submitting security issues](https://doc.traefik.io/traefik/contributing/submitting-security-issues/) | ||||
| - [Advocating for Traefik](https://doc.traefik.io/traefik/contributing/advocating/) | ||||
| - [Triage Process](https://github.com/traefik/contributors-guide/blob/master/issue_triage.md) | ||||
|  | ||||
| If you are willing to become a maintainer of the project, please take a look at the [maintainers guidelines](docs/content/contributing/maintainers-guidelines.md). | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| The MIT License (MIT) | ||||
|  | ||||
| Copyright (c) 2016-2020 Containous SAS; 2020-2022 Traefik Labs | ||||
| Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
|   | ||||
							
								
								
									
										144
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										144
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,5 +1,3 @@ | ||||
| .PHONY: all docs docs-serve | ||||
|  | ||||
| SRCS = $(shell git ls-files '*.go' | grep -v '^vendor/') | ||||
|  | ||||
| TAG_NAME := $(shell git tag -l --contains HEAD) | ||||
| @@ -7,8 +5,6 @@ SHA := $(shell git rev-parse HEAD) | ||||
| VERSION_GIT := $(if $(TAG_NAME),$(TAG_NAME),$(SHA)) | ||||
| VERSION := $(if $(VERSION),$(VERSION),$(VERSION_GIT)) | ||||
|  | ||||
| BIND_DIR := dist | ||||
|  | ||||
| GIT_BRANCH := $(subst heads/,,$(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)) | ||||
| TRAEFIK_DEV_IMAGE := traefik-dev$(if $(GIT_BRANCH),:$(subst /,-,$(GIT_BRANCH))) | ||||
|  | ||||
| @@ -18,6 +14,7 @@ TRAEFIK_IMAGE := $(if $(REPONAME),$(REPONAME),"traefik/traefik") | ||||
| INTEGRATION_OPTS := $(if $(MAKE_DOCKER_HOST),-e "DOCKER_HOST=$(MAKE_DOCKER_HOST)",-v "/var/run/docker.sock:/var/run/docker.sock") | ||||
| DOCKER_BUILD_ARGS := $(if $(DOCKER_VERSION), "--build-arg=DOCKER_VERSION=$(DOCKER_VERSION)",) | ||||
|  | ||||
| # only used when running in docker | ||||
| TRAEFIK_ENVS := \ | ||||
| 	-e OS_ARCH_ARG \ | ||||
| 	-e OS_PLATFORM_ARG \ | ||||
| @@ -27,142 +24,193 @@ TRAEFIK_ENVS := \ | ||||
| 	-e CODENAME \ | ||||
| 	-e TESTDIRS \ | ||||
| 	-e CI \ | ||||
| 	-e CONTAINER=DOCKER		# Indicator for integration tests that we are running inside a container. | ||||
| 	-e IN_DOCKER=true		# Indicator for integration tests that we are running inside a container. | ||||
|  | ||||
| TRAEFIK_MOUNT := -v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/traefik/traefik/$(BIND_DIR)" | ||||
| TRAEFIK_MOUNT := -v "$(CURDIR)/dist:/go/src/github.com/traefik/traefik/dist" | ||||
| DOCKER_RUN_OPTS := $(TRAEFIK_ENVS) $(TRAEFIK_MOUNT) "$(TRAEFIK_DEV_IMAGE)" | ||||
| DOCKER_NON_INTERACTIVE ?= false | ||||
| DOCKER_RUN_TRAEFIK := docker run $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -it) $(DOCKER_RUN_OPTS) | ||||
| DOCKER_RUN_TRAEFIK_TEST := docker run --add-host=host.docker.internal:127.0.0.1 --rm --name=traefik --network traefik-test-network -v $(PWD):$(PWD) -w $(PWD) $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -it) $(DOCKER_RUN_OPTS) | ||||
| DOCKER_RUN_TRAEFIK_NOTTY := docker run $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -i) $(DOCKER_RUN_OPTS) | ||||
|  | ||||
| PRE_TARGET ?= build-dev-image | ||||
|  | ||||
| PLATFORM_URL := $(if $(PLATFORM_URL),$(PLATFORM_URL),"https://pilot.traefik.io") | ||||
| IN_DOCKER ?= true | ||||
|  | ||||
| .PHONY: default | ||||
| default: binary | ||||
|  | ||||
| ## Build Dev Docker image | ||||
| build-dev-image: dist | ||||
| 	docker build $(DOCKER_BUILD_ARGS) -t "$(TRAEFIK_DEV_IMAGE)" -f build.Dockerfile . | ||||
|  | ||||
| ## Build Dev Docker image without cache | ||||
| build-dev-image-no-cache: dist | ||||
| 	docker build --no-cache -t "$(TRAEFIK_DEV_IMAGE)" -f build.Dockerfile . | ||||
|  | ||||
| ## Create the "dist" directory | ||||
| dist: | ||||
| 	mkdir dist | ||||
| 	mkdir -p dist | ||||
|  | ||||
| ## Build Dev Docker image | ||||
| .PHONY: build-dev-image | ||||
| build-dev-image: dist | ||||
| ifneq ("$(IN_DOCKER)", "") | ||||
| 	docker build $(DOCKER_BUILD_ARGS) -t "$(TRAEFIK_DEV_IMAGE)" --build-arg HOST_PWD="$(PWD)" -f build.Dockerfile . | ||||
| endif | ||||
|  | ||||
| ## Build Dev Docker image without cache | ||||
| .PHONY: build-dev-image-no-cache | ||||
| build-dev-image-no-cache: dist | ||||
| ifneq ("$(IN_DOCKER)", "") | ||||
| 	docker build $(DOCKER_BUILD_ARGS) --no-cache -t "$(TRAEFIK_DEV_IMAGE)" --build-arg HOST_PWD="$(PWD)" -f build.Dockerfile . | ||||
| endif | ||||
|  | ||||
| ## Build WebUI Docker image | ||||
| .PHONY: build-webui-image | ||||
| build-webui-image: | ||||
| 	docker build -t traefik-webui --build-arg ARG_PLATFORM_URL=$(PLATFORM_URL) -f webui/Dockerfile webui | ||||
| 	docker build -t traefik-webui -f webui/Dockerfile webui | ||||
|  | ||||
| ## Clean WebUI static generated assets | ||||
| .PHONY: clean-webui | ||||
| clean-webui: | ||||
| 	rm -r webui/static | ||||
| 	mkdir -p webui/static | ||||
| 	printf 'For more information see `webui/readme.md`' > webui/static/DONT-EDIT-FILES-IN-THIS-DIRECTORY.md | ||||
|  | ||||
| ## Generate WebUI | ||||
| generate-webui: | ||||
| 	if [ ! -d "static" ]; then \ | ||||
| 		$(MAKE) build-webui-image; \ | ||||
| 		mkdir -p static; \ | ||||
| 		docker run --rm -v "$$PWD/static":'/src/static' traefik-webui npm run build:nc; \ | ||||
| 		docker run --rm -v "$$PWD/static":'/src/static' traefik-webui chown -R $(shell id -u):$(shell id -g) ../static; \ | ||||
| 		echo 'For more information show `webui/readme.md`' > $$PWD/static/DONT-EDIT-FILES-IN-THIS-DIRECTORY.md; \ | ||||
| 	fi | ||||
| webui/static/index.html: | ||||
| 	$(MAKE) build-webui-image | ||||
| 	docker run --rm -v "$(PWD)/webui/static":'/src/webui/static' traefik-webui npm run build:nc | ||||
| 	docker run --rm -v "$(PWD)/webui/static":'/src/webui/static' traefik-webui chown -R $(shell id -u):$(shell id -g) ./static | ||||
|  | ||||
| ## Build the linux binary | ||||
| binary: generate-webui $(PRE_TARGET) | ||||
| 	$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate binary | ||||
| .PHONY: generate-webui | ||||
| generate-webui: webui/static/index.html | ||||
|  | ||||
| ## Build the binary | ||||
| .PHONY: binary | ||||
| binary: generate-webui build-dev-image | ||||
| 	$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate binary | ||||
|  | ||||
| ## Build the linux binary locally | ||||
| .PHONY: binary-debug | ||||
| binary-debug: generate-webui | ||||
| 	GOOS=linux ./script/make.sh binary | ||||
|  | ||||
| ## Build the binary for the standard platforms (linux, darwin, windows) | ||||
| .PHONY: crossbinary-default | ||||
| crossbinary-default: generate-webui build-dev-image | ||||
| 	$(DOCKER_RUN_TRAEFIK_NOTTY) ./script/make.sh generate crossbinary-default | ||||
|  | ||||
| ## Build the binary for the standard platforms (linux, darwin, windows) in parallel | ||||
| .PHONY: crossbinary-default-parallel | ||||
| crossbinary-default-parallel: | ||||
| 	$(MAKE) generate-webui | ||||
| 	$(MAKE) build-dev-image crossbinary-default | ||||
|  | ||||
| ## Run the unit and integration tests | ||||
| test: $(PRE_TARGET) | ||||
| .PHONY: test | ||||
| test: build-dev-image | ||||
| 	-docker network create traefik-test-network --driver bridge --subnet 172.31.42.0/24 | ||||
| 	trap 'docker network rm traefik-test-network' EXIT; \ | ||||
| 	$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK_TEST),) ./script/make.sh generate test-unit binary test-integration | ||||
| 	$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_TEST)) ./script/make.sh generate test-unit binary test-integration | ||||
|  | ||||
| ## Run the unit tests | ||||
| test-unit: $(PRE_TARGET) | ||||
| .PHONY: test-unit | ||||
| test-unit: build-dev-image | ||||
| 	-docker network create traefik-test-network --driver bridge --subnet 172.31.42.0/24 | ||||
| 	trap 'docker network rm traefik-test-network' EXIT; \ | ||||
| 	$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK_TEST)) ./script/make.sh generate test-unit | ||||
| 	$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_TEST)) ./script/make.sh generate test-unit | ||||
|  | ||||
| ## Run the integration tests | ||||
| test-integration: $(PRE_TARGET) | ||||
| .PHONY: test-integration | ||||
| test-integration: build-dev-image | ||||
| 	-docker network create traefik-test-network --driver bridge --subnet 172.31.42.0/24 | ||||
| 	trap 'docker network rm traefik-test-network' EXIT; \ | ||||
| 	$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK_TEST),) ./script/make.sh generate binary test-integration | ||||
| 	$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_TEST)) ./script/make.sh generate binary test-integration | ||||
|  | ||||
| ## Pull all images for integration tests | ||||
| .PHONY: pull-images | ||||
| pull-images: | ||||
| 	grep --no-filename -E '^\s+image:' ./integration/resources/compose/*.yml | awk '{print $$2}' | sort | uniq | xargs -P 6 -n 1 docker pull | ||||
| 	grep --no-filename -E '^\s+image:' ./integration/resources/compose/*.yml \ | ||||
| 		| awk '{print $$2}' \ | ||||
| 		| sort \ | ||||
| 		| uniq \ | ||||
| 		| xargs -P 6 -n 1 docker pull | ||||
|  | ||||
| ## Validate code and docs | ||||
| validate-files: $(PRE_TARGET) | ||||
| 	$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate validate-lint validate-misspell | ||||
| .PHONY: validate-files | ||||
| validate-files: build-dev-image | ||||
| 	$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate validate-lint validate-misspell | ||||
| 	bash $(CURDIR)/script/validate-shell-script.sh | ||||
|  | ||||
| ## Validate code, docs, and vendor | ||||
| validate: $(PRE_TARGET) | ||||
| 	$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate validate-lint validate-misspell validate-vendor | ||||
| .PHONY: validate | ||||
| validate: build-dev-image | ||||
| 	$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate validate-lint validate-misspell validate-vendor | ||||
| 	bash $(CURDIR)/script/validate-shell-script.sh | ||||
|  | ||||
| ## Clean up static directory and build a Docker Traefik image | ||||
| build-image: binary | ||||
| 	rm -rf static | ||||
| .PHONY: build-image | ||||
| build-image: clean-webui binary | ||||
| 	docker build -t $(TRAEFIK_IMAGE) . | ||||
|  | ||||
| ## Build a Docker Traefik image | ||||
| ## Build a Docker Traefik image without re-building the webui | ||||
| .PHONY: build-image-dirty | ||||
| build-image-dirty: binary | ||||
| 	docker build -t $(TRAEFIK_IMAGE) . | ||||
|  | ||||
| ## Locally build traefik for linux, then shove it an alpine image, with basic tools. | ||||
| .PHONY: build-image-debug | ||||
| build-image-debug: binary-debug | ||||
| 	docker build -t $(TRAEFIK_IMAGE) -f debug.Dockerfile . | ||||
|  | ||||
| ## Start a shell inside the build env | ||||
| .PHONY: shell | ||||
| shell: build-dev-image | ||||
| 	$(DOCKER_RUN_TRAEFIK) /bin/bash | ||||
|  | ||||
| ## Build documentation site | ||||
| .PHONY: docs | ||||
| docs: | ||||
| 	make -C ./docs docs | ||||
|  | ||||
| ## Serve the documentation site locally | ||||
| .PHONY: docs-serve | ||||
| docs-serve: | ||||
| 	make -C ./docs docs-serve | ||||
|  | ||||
| ## Pull image for doc building | ||||
| .PHONY: docs-pull-images | ||||
| docs-pull-images: | ||||
| 	make -C ./docs docs-pull-images | ||||
|  | ||||
| ## Generate CRD clientset and CRD manifests | ||||
| .PHONY: generate-crd | ||||
| generate-crd: | ||||
| 	@$(CURDIR)/script/code-gen.sh | ||||
|  | ||||
| ## Generate code from dynamic configuration https://github.com/traefik/genconf | ||||
| .PHONY: generate-genconf | ||||
| generate-genconf: | ||||
| 	go run ./cmd/internal/gen/ | ||||
|  | ||||
| ## Create packages for the release | ||||
| release-packages: generate-webui $(PRE_TARGET) | ||||
| .PHONY: release-packages | ||||
| release-packages: generate-webui build-dev-image | ||||
| 	rm -rf dist | ||||
| 	$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK_NOTTY)) goreleaser release --skip-publish --timeout="90m" | ||||
| 	$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK_NOTTY)) tar cfz dist/traefik-${VERSION}.src.tar.gz \ | ||||
| 	@- $(foreach os, linux darwin windows freebsd openbsd, \ | ||||
|         $(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) goreleaser release --skip-publish -p 2 --timeout="90m" --config $(shell go run ./internal/release $(os)); \ | ||||
|         $(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) go clean -cache; \ | ||||
|     ) | ||||
|  | ||||
| 	$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) cat dist/**/*_checksums.txt >> dist/traefik_${VERSION}_checksums.txt | ||||
| 	$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) rm dist/**/*_checksums.txt | ||||
| 	$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) tar cfz dist/traefik-${VERSION}.src.tar.gz \ | ||||
| 		--exclude-vcs \ | ||||
| 		--exclude .idea \ | ||||
| 		--exclude .travis \ | ||||
| 		--exclude .semaphoreci \ | ||||
| 		--exclude .github \ | ||||
| 		--exclude dist . | ||||
| 	$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK_NOTTY)) chown -R $(shell id -u):$(shell id -g) dist/ | ||||
| 	$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) chown -R $(shell id -u):$(shell id -g) dist/ | ||||
|  | ||||
| ## Format the Code | ||||
| .PHONY: fmt | ||||
| fmt: | ||||
| 	gofmt -s -l -w $(SRCS) | ||||
|  | ||||
| .PHONY: run-dev | ||||
| run-dev: | ||||
| 	go generate | ||||
| 	GO111MODULE=on go build ./cmd/traefik | ||||
|   | ||||
							
								
								
									
										20
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,6 +1,10 @@ | ||||
|  | ||||
| <p align="center"> | ||||
| <img src="docs/content/assets/img/traefik.logo.png" alt="Traefik" title="Traefik" /> | ||||
|     <picture> | ||||
|       <source media="(prefers-color-scheme: dark)" srcset="docs/content/assets/img/traefik.logo-dark.png"> | ||||
|       <source media="(prefers-color-scheme: light)" srcset="docs/content/assets/img/traefik.logo.png"> | ||||
|       <img alt="Traefik" title="Traefik" src="docs/content/assets/img/traefik.logo.png"> | ||||
|     </picture> | ||||
| </p> | ||||
|  | ||||
| [](https://semaphoreci.com/containous/traefik) | ||||
| @@ -10,9 +14,8 @@ | ||||
| [](https://community.traefik.io/) | ||||
| [](https://twitter.com/intent/follow?screen_name=traefik) | ||||
|  | ||||
|  | ||||
| Traefik (pronounced _traffic_) is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. | ||||
| Traefik integrates with your existing infrastructure components ([Docker](https://www.docker.com/), [Swarm mode](https://docs.docker.com/engine/swarm/), [Kubernetes](https://kubernetes.io), [Marathon](https://mesosphere.github.io/marathon/), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Rancher](https://rancher.com), [Amazon ECS](https://aws.amazon.com/ecs), ...) and configures itself automatically and dynamically. | ||||
| Traefik integrates with your existing infrastructure components ([Docker](https://www.docker.com/), [Swarm mode](https://docs.docker.com/engine/swarm/), [Kubernetes](https://kubernetes.io), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Rancher v2](https://rancher.com), [Amazon ECS](https://aws.amazon.com/ecs), ...) and configures itself automatically and dynamically. | ||||
| Pointing Traefik at your orchestrator should be the _only_ configuration step you need. | ||||
|  | ||||
| --- | ||||
| @@ -58,20 +61,17 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t | ||||
| - Provides HTTPS to your microservices by leveraging [Let's Encrypt](https://letsencrypt.org)  (wildcard certificates support) | ||||
| - Circuit breakers, retry | ||||
| - See the magic through its clean web UI | ||||
| - Websocket, HTTP/2, GRPC ready | ||||
| - Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB) | ||||
| - Websocket, HTTP/2, gRPC ready | ||||
| - Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB 2.X) | ||||
| - Keeps access logs (JSON, CLF) | ||||
| - Fast | ||||
| - Exposes a Rest API | ||||
| - Packaged as a single binary file (made with :heart: with go) and available as an [official](https://hub.docker.com/r/_/traefik/) docker image | ||||
|  | ||||
|  | ||||
| ## Supported Backends | ||||
|  | ||||
| - [Docker](https://doc.traefik.io/traefik/providers/docker/) / [Swarm mode](https://doc.traefik.io/traefik/providers/docker/) | ||||
| - [Kubernetes](https://doc.traefik.io/traefik/providers/kubernetes-crd/) | ||||
| - [Marathon](https://doc.traefik.io/traefik/providers/marathon/) | ||||
| - [Rancher](https://doc.traefik.io/traefik/providers/rancher/) (Metadata) | ||||
| - [File](https://doc.traefik.io/traefik/providers/file/) | ||||
|  | ||||
| ## Quickstart | ||||
| @@ -88,13 +88,12 @@ You can access the simple HTML frontend of Traefik. | ||||
|  | ||||
| You can find the complete documentation of Traefik v2 at [https://doc.traefik.io/traefik/](https://doc.traefik.io/traefik/). | ||||
|  | ||||
| If you are using Traefik v1, you can find the complete documentation at [https://doc.traefik.io/traefik/v1.7/](https://doc.traefik.io/traefik/v1.7/). | ||||
|  | ||||
| A collection of contributions around Traefik can be found at [https://awesome.traefik.io](https://awesome.traefik.io). | ||||
|  | ||||
| ## Support | ||||
|  | ||||
| To get community support, you can: | ||||
|  | ||||
| - join the Traefik community forum: [](https://community.traefik.io/) | ||||
|  | ||||
| If you need commercial support, please contact [Traefik.io](https://traefik.io) by mail: <mailto:support@traefik.io>. | ||||
| @@ -129,7 +128,6 @@ We are strongly promoting a philosophy of openness and sharing, and firmly stand | ||||
| This [document](docs/content/contributing/maintainers-guidelines.md) describes how to be part of the core team as well as various responsibilities and guidelines for Traefik maintainers. | ||||
| You can also find more information on our process to review pull requests and manage issues [in this document](docs/content/contributing/maintainers.md). | ||||
|  | ||||
|  | ||||
| ## Contributing | ||||
|  | ||||
| If you'd like to contribute to the project, refer to the [contributing documentation](CONTRIBUTING.md). | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| # Security Policy | ||||
|  | ||||
| We strongly advise you to register your Traefik instances to [Pilot](https://pilot.traefik.io) to be notified of security advisories that apply to your Traefik version. | ||||
| You can also join our security mailing list to be aware of the latest announcements from our security team. | ||||
| You can join our security mailing list to be aware of the latest announcements from our security team. | ||||
| You can subscribe sending a mail to security+subscribe@traefik.io or on [the online viewer](https://groups.google.com/a/traefik.io/forum/#!forum/security). | ||||
|  | ||||
| Reported vulnerabilities can be found on [cve.mitre.org](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=traefik). | ||||
| @@ -17,7 +16,7 @@ Each version is supported until the next one is released (e.g. 1.1.x will be sup | ||||
| We use [Semantic Versioning](https://semver.org/). | ||||
|  | ||||
| | Version   | Supported          | | ||||
| | --------- | ------------------ | | ||||
| |-----------|--------------------| | ||||
| | `2.2.x`   | :white_check_mark: | | ||||
| | `< 2.2.x` | :x:                | | ||||
| | `1.7.x`   | :white_check_mark: | | ||||
| @@ -26,4 +25,6 @@ We use [Semantic Versioning](https://semver.org/). | ||||
| ## Reporting a Vulnerability | ||||
|  | ||||
| We want to keep Traefik safe for everyone. | ||||
| If you've discovered a security vulnerability in Traefik, we appreciate your help in disclosing it to us in a responsible manner, using [this form](https://security.traefik.io). | ||||
| If you've discovered a security vulnerability in Traefik, | ||||
| we appreciate your help in disclosing it to us in a responsible manner, | ||||
| by creating a [security advisory](https://github.com/traefik/traefik/security/advisories). | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| FROM golang:1.17-alpine | ||||
| FROM golang:1.21-alpine | ||||
|  | ||||
| RUN apk --update upgrade \ | ||||
|     && apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \ | ||||
| RUN 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/* | ||||
|  | ||||
| @@ -13,22 +12,23 @@ RUN mkdir -p /usr/local/bin \ | ||||
|     && curl -fL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz \ | ||||
|     | tar -xzC /usr/local/bin --transform 's#^.+/##x' | ||||
|  | ||||
| # 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 golangci-lint binary to bin folder in $GOPATH | ||||
| RUN curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- -b $GOPATH/bin v1.43.0 | ||||
| RUN curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- -b $GOPATH/bin v1.54.1 | ||||
|  | ||||
| # Download misspell binary to bin folder in $GOPATH | ||||
| RUN  curl -sfL https://raw.githubusercontent.com/client9/misspell/master/install-misspell.sh | bash -s -- -b $GOPATH/bin v0.3.4 | ||||
| RUN curl -sfL https://raw.githubusercontent.com/golangci/misspell/master/install-misspell.sh | bash -s -- -b $GOPATH/bin v0.4.0 | ||||
|  | ||||
| # Download goreleaser binary to bin folder in $GOPATH | ||||
| RUN curl -sfL https://gist.githubusercontent.com/traefiker/6d7ac019c11d011e4f131bb2cca8900e/raw/goreleaser.sh | sh | ||||
|  | ||||
| WORKDIR /go/src/github.com/traefik/traefik | ||||
|  | ||||
| # Because of CVE-2022-24765 (https://github.blog/2022-04-12-git-security-vulnerability-announced/), | ||||
| # we configure git to allow the Traefik codebase path on the Host for docker in docker usages. | ||||
| ARG HOST_PWD="" | ||||
|  | ||||
| RUN git config --global --add safe.directory "${HOST_PWD}" | ||||
|  | ||||
| # Download go modules | ||||
| COPY go.mod . | ||||
| COPY go.sum . | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	ptypes "github.com/traefik/paerser/types" | ||||
| 	"github.com/traefik/traefik/v2/pkg/config/static" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/static" | ||||
| ) | ||||
|  | ||||
| // TraefikCmdConfiguration wraps the static configuration and extra parameters. | ||||
| @@ -28,6 +28,10 @@ func NewTraefikConfiguration() *TraefikCmdConfiguration { | ||||
| 			ServersTransport: &static.ServersTransport{ | ||||
| 				MaxIdleConnsPerHost: 200, | ||||
| 			}, | ||||
| 			TCPServersTransport: &static.TCPServersTransport{ | ||||
| 				DialTimeout:   ptypes.Duration(30 * time.Second), | ||||
| 				DialKeepAlive: ptypes.Duration(15 * time.Second), | ||||
| 			}, | ||||
| 		}, | ||||
| 		ConfigFile: "", | ||||
| 	} | ||||
|   | ||||
| @@ -8,7 +8,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/traefik/paerser/cli" | ||||
| 	"github.com/traefik/traefik/v2/pkg/config/static" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/static" | ||||
| ) | ||||
|  | ||||
| // NewCmd builds a new HealthCheck command. | ||||
| @@ -64,7 +64,7 @@ func Do(staticConfiguration static.Configuration) (*http.Response, error) { | ||||
| 	client := &http.Client{Timeout: 5 * time.Second} | ||||
| 	protocol := "http" | ||||
|  | ||||
| 	// FIXME Handle TLS on ping etc... | ||||
| 	// TODO Handle TLS on ping etc... | ||||
| 	// if pingEntryPoint.TLS != nil { | ||||
| 	// 	protocol = "https" | ||||
| 	// 	tr := &http.Transport{ | ||||
|   | ||||
| @@ -13,6 +13,7 @@ import ( | ||||
| 	"path" | ||||
| 	"path/filepath" | ||||
| 	"reflect" | ||||
| 	"slices" | ||||
| 	"sort" | ||||
| 	"strings" | ||||
|  | ||||
| @@ -72,22 +73,16 @@ func NewCentrifuge(rootPkg string) (*Centrifuge, error) { | ||||
|  | ||||
| // Run runs the code extraction and the code generation. | ||||
| func (c Centrifuge) Run(dest string, pkgName string) error { | ||||
| 	files, err := c.run(c.pkg.Scope(), c.rootPkg, pkgName) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	files := c.run(c.pkg.Scope(), c.rootPkg, pkgName) | ||||
|  | ||||
| 	err = fileWriter{baseDir: dest}.Write(files) | ||||
| 	err := fileWriter{baseDir: dest}.Write(files) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for _, p := range c.pkg.Imports() { | ||||
| 		if contains(c.IncludedImports, p.Path()) { | ||||
| 			fls, err := c.run(p.Scope(), p.Path(), p.Name()) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		if slices.Contains(c.IncludedImports, p.Path()) { | ||||
| 			fls := c.run(p.Scope(), p.Path(), p.Name()) | ||||
|  | ||||
| 			err = fileWriter{baseDir: filepath.Join(dest, p.Name())}.Write(fls) | ||||
| 			if err != nil { | ||||
| @@ -99,11 +94,11 @@ func (c Centrifuge) Run(dest string, pkgName string) error { | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (c Centrifuge) run(sc *types.Scope, rootPkg string, pkgName string) (map[string]*File, error) { | ||||
| func (c Centrifuge) run(sc *types.Scope, rootPkg string, pkgName string) map[string]*File { | ||||
| 	files := map[string]*File{} | ||||
|  | ||||
| 	for _, name := range sc.Names() { | ||||
| 		if contains(c.ExcludedTypes, name) { | ||||
| 		if slices.Contains(c.ExcludedTypes, name) { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| @@ -113,7 +108,7 @@ func (c Centrifuge) run(sc *types.Scope, rootPkg string, pkgName string) (map[st | ||||
| 		} | ||||
|  | ||||
| 		filename := filepath.Base(c.fileSet.File(o.Pos()).Name()) | ||||
| 		if contains(c.ExcludedFiles, path.Join(rootPkg, filename)) { | ||||
| 		if slices.Contains(c.ExcludedFiles, path.Join(rootPkg, filename)) { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| @@ -158,7 +153,7 @@ func (c Centrifuge) run(sc *types.Scope, rootPkg string, pkgName string) (map[st | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return files, nil | ||||
| 	return files | ||||
| } | ||||
|  | ||||
| func (c Centrifuge) writeStruct(name string, obj *types.Struct, rootPkg string, elt *File) string { | ||||
| @@ -243,16 +238,6 @@ func extractPackage(t types.Type) string { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func contains(values []string, value string) bool { | ||||
| 	for _, val := range values { | ||||
| 		if val == value { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| type fileWriter struct { | ||||
| 	baseDir string | ||||
| } | ||||
|   | ||||
| @@ -11,7 +11,7 @@ import ( | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| const rootPkg = "github.com/traefik/traefik/v2/pkg/config/dynamic" | ||||
| const rootPkg = "github.com/traefik/traefik/v3/pkg/config/dynamic" | ||||
|  | ||||
| const ( | ||||
| 	destModuleName = "github.com/traefik/genconf" | ||||
| @@ -57,8 +57,8 @@ func run(dest string) error { | ||||
| 	} | ||||
|  | ||||
| 	centrifuge.IncludedImports = []string{ | ||||
| 		"github.com/traefik/traefik/v2/pkg/tls", | ||||
| 		"github.com/traefik/traefik/v2/pkg/types", | ||||
| 		"github.com/traefik/traefik/v3/pkg/tls", | ||||
| 		"github.com/traefik/traefik/v3/pkg/types", | ||||
| 	} | ||||
|  | ||||
| 	centrifuge.ExcludedTypes = []string{ | ||||
| @@ -71,8 +71,8 @@ func run(dest string) error { | ||||
| 	} | ||||
|  | ||||
| 	centrifuge.ExcludedFiles = []string{ | ||||
| 		"github.com/traefik/traefik/v2/pkg/types/logs.go", | ||||
| 		"github.com/traefik/traefik/v2/pkg/types/metrics.go", | ||||
| 		"github.com/traefik/traefik/v3/pkg/types/logs.go", | ||||
| 		"github.com/traefik/traefik/v3/pkg/types/metrics.go", | ||||
| 	} | ||||
|  | ||||
| 	centrifuge.TypeCleaner = cleanType | ||||
| @@ -87,11 +87,11 @@ func run(dest string) error { | ||||
| } | ||||
|  | ||||
| func cleanType(typ types.Type, base string) string { | ||||
| 	if typ.String() == "github.com/traefik/traefik/v2/pkg/tls.FileOrContent" { | ||||
| 	if typ.String() == "github.com/traefik/traefik/v3/pkg/tls.FileOrContent" { | ||||
| 		return "string" | ||||
| 	} | ||||
|  | ||||
| 	if typ.String() == "[]github.com/traefik/traefik/v2/pkg/tls.FileOrContent" { | ||||
| 	if typ.String() == "[]github.com/traefik/traefik/v3/pkg/tls.FileOrContent" { | ||||
| 		return "[]string" | ||||
| 	} | ||||
|  | ||||
| @@ -103,8 +103,8 @@ func cleanType(typ types.Type, base string) string { | ||||
| 		return strings.ReplaceAll(typ.String(), base+".", "") | ||||
| 	} | ||||
|  | ||||
| 	if strings.Contains(typ.String(), "github.com/traefik/traefik/v2/pkg/") { | ||||
| 		return strings.ReplaceAll(typ.String(), "github.com/traefik/traefik/v2/pkg/", "") | ||||
| 	if strings.Contains(typ.String(), "github.com/traefik/traefik/v3/pkg/") { | ||||
| 		return strings.ReplaceAll(typ.String(), "github.com/traefik/traefik/v3/pkg/", "") | ||||
| 	} | ||||
|  | ||||
| 	return typ.String() | ||||
| @@ -114,9 +114,9 @@ func cleanPackage(src string) string { | ||||
| 	switch src { | ||||
| 	case "github.com/traefik/paerser/types": | ||||
| 		return "" | ||||
| 	case "github.com/traefik/traefik/v2/pkg/tls": | ||||
| 	case "github.com/traefik/traefik/v3/pkg/tls": | ||||
| 		return path.Join(destModuleName, destPkg, "tls") | ||||
| 	case "github.com/traefik/traefik/v2/pkg/types": | ||||
| 	case "github.com/traefik/traefik/v3/pkg/types": | ||||
| 		return path.Join(destModuleName, destPkg, "types") | ||||
| 	default: | ||||
| 		return src | ||||
|   | ||||
							
								
								
									
										89
									
								
								cmd/traefik/logger.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								cmd/traefik/logger.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"io" | ||||
| 	stdlog "log" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/natefinch/lumberjack" | ||||
| 	"github.com/rs/zerolog" | ||||
| 	"github.com/rs/zerolog/log" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/static" | ||||
| 	"github.com/traefik/traefik/v3/pkg/logs" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	// hide the first logs before the setup of the logger. | ||||
| 	zerolog.SetGlobalLevel(zerolog.ErrorLevel) | ||||
| } | ||||
|  | ||||
| func setupLogger(staticConfiguration *static.Configuration) { | ||||
| 	// configure log format | ||||
| 	w := getLogWriter(staticConfiguration) | ||||
|  | ||||
| 	// configure log level | ||||
| 	logLevel := getLogLevel(staticConfiguration) | ||||
|  | ||||
| 	// create logger | ||||
| 	logCtx := zerolog.New(w).With().Timestamp() | ||||
| 	if logLevel <= zerolog.DebugLevel { | ||||
| 		logCtx = logCtx.Caller() | ||||
| 	} | ||||
|  | ||||
| 	log.Logger = logCtx.Logger().Level(logLevel) | ||||
| 	zerolog.DefaultContextLogger = &log.Logger | ||||
| 	zerolog.SetGlobalLevel(logLevel) | ||||
|  | ||||
| 	// Global logrus replacement (related to lib like go-rancher-metadata, docker, etc.) | ||||
| 	logrus.StandardLogger().Out = logs.NoLevel(log.Logger, zerolog.DebugLevel) | ||||
|  | ||||
| 	// configure default standard log. | ||||
| 	stdlog.SetFlags(stdlog.Lshortfile | stdlog.LstdFlags) | ||||
| 	stdlog.SetOutput(logs.NoLevel(log.Logger, zerolog.DebugLevel)) | ||||
| } | ||||
|  | ||||
| func getLogWriter(staticConfiguration *static.Configuration) io.Writer { | ||||
| 	var w io.Writer = os.Stderr | ||||
|  | ||||
| 	if staticConfiguration.Log != nil && len(staticConfiguration.Log.FilePath) > 0 { | ||||
| 		_, _ = os.Create(staticConfiguration.Log.FilePath) | ||||
| 		w = &lumberjack.Logger{ | ||||
| 			Filename:   staticConfiguration.Log.FilePath, | ||||
| 			MaxSize:    staticConfiguration.Log.MaxSize, | ||||
| 			MaxBackups: staticConfiguration.Log.MaxBackups, | ||||
| 			MaxAge:     staticConfiguration.Log.MaxAge, | ||||
| 			Compress:   true, | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if staticConfiguration.Log == nil || staticConfiguration.Log.Format != "json" { | ||||
| 		w = zerolog.ConsoleWriter{ | ||||
| 			Out:        w, | ||||
| 			TimeFormat: time.RFC3339, | ||||
| 			NoColor:    staticConfiguration.Log != nil && (staticConfiguration.Log.NoColor || len(staticConfiguration.Log.FilePath) > 0), | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return w | ||||
| } | ||||
|  | ||||
| func getLogLevel(staticConfiguration *static.Configuration) zerolog.Level { | ||||
| 	levelStr := "error" | ||||
| 	if staticConfiguration.Log != nil && staticConfiguration.Log.Level != "" { | ||||
| 		levelStr = strings.ToLower(staticConfiguration.Log.Level) | ||||
| 	} | ||||
|  | ||||
| 	logLevel, err := zerolog.ParseLevel(strings.ToLower(levelStr)) | ||||
| 	if err != nil { | ||||
| 		log.Error().Err(err). | ||||
| 			Str("logLevel", levelStr). | ||||
| 			Msg("Unspecified or invalid log level, setting the level to default (ERROR)...") | ||||
|  | ||||
| 		logLevel = zerolog.ErrorLevel | ||||
| 	} | ||||
|  | ||||
| 	return logLevel | ||||
| } | ||||
| @@ -3,8 +3,8 @@ package main | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/traefik/traefik/v2/pkg/config/static" | ||||
| 	"github.com/traefik/traefik/v2/pkg/plugins" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/static" | ||||
| 	"github.com/traefik/traefik/v3/pkg/plugins" | ||||
| ) | ||||
|  | ||||
| const outputDir = "./plugins-storage/" | ||||
| @@ -27,21 +27,20 @@ func initPlugins(staticCfg *static.Configuration) (*plugins.Client, map[string]p | ||||
| 	var client *plugins.Client | ||||
| 	plgs := map[string]plugins.Descriptor{} | ||||
|  | ||||
| 	if isPilotEnabled(staticCfg) && hasPlugins(staticCfg) { | ||||
| 	if hasPlugins(staticCfg) { | ||||
| 		opts := plugins.ClientOptions{ | ||||
| 			Output: outputDir, | ||||
| 			Token:  staticCfg.Pilot.Token, | ||||
| 		} | ||||
|  | ||||
| 		var err error | ||||
| 		client, err = plugins.NewClient(opts) | ||||
| 		if err != nil { | ||||
| 			return nil, nil, nil, err | ||||
| 			return nil, nil, nil, fmt.Errorf("unable to create plugins client: %w", err) | ||||
| 		} | ||||
|  | ||||
| 		err = plugins.SetupRemotePlugins(client, staticCfg.Experimental.Plugins) | ||||
| 		if err != nil { | ||||
| 			return nil, nil, nil, err | ||||
| 			return nil, nil, nil, fmt.Errorf("unable to set up plugins environment: %w", err) | ||||
| 		} | ||||
|  | ||||
| 		plgs = staticCfg.Experimental.Plugins | ||||
| @@ -75,10 +74,6 @@ func checkUniquePluginNames(e *static.Experimental) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func isPilotEnabled(staticCfg *static.Configuration) bool { | ||||
| 	return staticCfg.Pilot != nil && staticCfg.Pilot.Token != "" | ||||
| } | ||||
|  | ||||
| func hasPlugins(staticCfg *static.Configuration) bool { | ||||
| 	return staticCfg.Experimental != nil && len(staticCfg.Experimental.Plugins) > 0 | ||||
| } | ||||
|   | ||||
| @@ -9,42 +9,43 @@ import ( | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"os/signal" | ||||
| 	"path/filepath" | ||||
| 	"sort" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/coreos/go-systemd/daemon" | ||||
| 	assetfs "github.com/elazarl/go-bindata-assetfs" | ||||
| 	"github.com/go-acme/lego/v4/challenge" | ||||
| 	gokitmetrics "github.com/go-kit/kit/metrics" | ||||
| 	"github.com/rs/zerolog/log" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/spiffe/go-spiffe/v2/workloadapi" | ||||
| 	"github.com/traefik/paerser/cli" | ||||
| 	"github.com/traefik/traefik/v2/autogen/genstatic" | ||||
| 	"github.com/traefik/traefik/v2/cmd" | ||||
| 	"github.com/traefik/traefik/v2/cmd/healthcheck" | ||||
| 	cmdVersion "github.com/traefik/traefik/v2/cmd/version" | ||||
| 	tcli "github.com/traefik/traefik/v2/pkg/cli" | ||||
| 	"github.com/traefik/traefik/v2/pkg/collector" | ||||
| 	"github.com/traefik/traefik/v2/pkg/config/dynamic" | ||||
| 	"github.com/traefik/traefik/v2/pkg/config/runtime" | ||||
| 	"github.com/traefik/traefik/v2/pkg/config/static" | ||||
| 	"github.com/traefik/traefik/v2/pkg/log" | ||||
| 	"github.com/traefik/traefik/v2/pkg/metrics" | ||||
| 	"github.com/traefik/traefik/v2/pkg/middlewares/accesslog" | ||||
| 	"github.com/traefik/traefik/v2/pkg/pilot" | ||||
| 	"github.com/traefik/traefik/v2/pkg/provider/acme" | ||||
| 	"github.com/traefik/traefik/v2/pkg/provider/aggregator" | ||||
| 	"github.com/traefik/traefik/v2/pkg/provider/traefik" | ||||
| 	"github.com/traefik/traefik/v2/pkg/safe" | ||||
| 	"github.com/traefik/traefik/v2/pkg/server" | ||||
| 	"github.com/traefik/traefik/v2/pkg/server/middleware" | ||||
| 	"github.com/traefik/traefik/v2/pkg/server/service" | ||||
| 	traefiktls "github.com/traefik/traefik/v2/pkg/tls" | ||||
| 	"github.com/traefik/traefik/v2/pkg/types" | ||||
| 	"github.com/traefik/traefik/v2/pkg/version" | ||||
| 	"github.com/vulcand/oxy/roundrobin" | ||||
| 	"github.com/traefik/traefik/v3/cmd" | ||||
| 	"github.com/traefik/traefik/v3/cmd/healthcheck" | ||||
| 	cmdVersion "github.com/traefik/traefik/v3/cmd/version" | ||||
| 	tcli "github.com/traefik/traefik/v3/pkg/cli" | ||||
| 	"github.com/traefik/traefik/v3/pkg/collector" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/dynamic" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/runtime" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/static" | ||||
| 	"github.com/traefik/traefik/v3/pkg/logs" | ||||
| 	"github.com/traefik/traefik/v3/pkg/metrics" | ||||
| 	"github.com/traefik/traefik/v3/pkg/middlewares/accesslog" | ||||
| 	"github.com/traefik/traefik/v3/pkg/provider/acme" | ||||
| 	"github.com/traefik/traefik/v3/pkg/provider/aggregator" | ||||
| 	"github.com/traefik/traefik/v3/pkg/provider/tailscale" | ||||
| 	"github.com/traefik/traefik/v3/pkg/provider/traefik" | ||||
| 	"github.com/traefik/traefik/v3/pkg/safe" | ||||
| 	"github.com/traefik/traefik/v3/pkg/server" | ||||
| 	"github.com/traefik/traefik/v3/pkg/server/middleware" | ||||
| 	"github.com/traefik/traefik/v3/pkg/server/service" | ||||
| 	"github.com/traefik/traefik/v3/pkg/tcp" | ||||
| 	traefiktls "github.com/traefik/traefik/v3/pkg/tls" | ||||
| 	"github.com/traefik/traefik/v3/pkg/tracing" | ||||
| 	"github.com/traefik/traefik/v3/pkg/tracing/jaeger" | ||||
| 	"github.com/traefik/traefik/v3/pkg/types" | ||||
| 	"github.com/traefik/traefik/v3/pkg/version" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| @@ -78,7 +79,7 @@ Complete documentation is available at https://traefik.io`, | ||||
|  | ||||
| 	err = cli.Execute(cmdTraefik) | ||||
| 	if err != nil { | ||||
| 		stdlog.Println(err) | ||||
| 		log.Error().Err(err).Msg("Command error") | ||||
| 		logrus.Exit(1) | ||||
| 	} | ||||
|  | ||||
| @@ -86,31 +87,24 @@ Complete documentation is available at https://traefik.io`, | ||||
| } | ||||
|  | ||||
| func runCmd(staticConfiguration *static.Configuration) error { | ||||
| 	configureLogging(staticConfiguration) | ||||
| 	setupLogger(staticConfiguration) | ||||
|  | ||||
| 	http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment | ||||
|  | ||||
| 	if err := roundrobin.SetDefaultWeight(0); err != nil { | ||||
| 		log.WithoutContext().Errorf("Could not set round robin default weight: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	staticConfiguration.SetEffectiveConfiguration() | ||||
| 	if err := staticConfiguration.ValidateConfiguration(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	log.WithoutContext().Infof("Traefik version %s built on %s", version.Version, version.BuildDate) | ||||
| 	log.Info().Str("version", version.Version). | ||||
| 		Msgf("Traefik version %s built on %s", version.Version, version.BuildDate) | ||||
|  | ||||
| 	jsonConf, err := json.Marshal(staticConfiguration) | ||||
| 	if err != nil { | ||||
| 		log.WithoutContext().Errorf("Could not marshal static configuration: %v", err) | ||||
| 		log.WithoutContext().Debugf("Static configuration loaded [struct] %#v", staticConfiguration) | ||||
| 		log.Error().Err(err).Msg("Could not marshal static configuration") | ||||
| 		log.Debug().Interface("staticConfiguration", staticConfiguration).Msg("Static configuration loaded [struct]") | ||||
| 	} else { | ||||
| 		log.WithoutContext().Debugf("Static configuration loaded %s", string(jsonConf)) | ||||
| 	} | ||||
|  | ||||
| 	if staticConfiguration.API != nil && staticConfiguration.API.Dashboard { | ||||
| 		staticConfiguration.API.DashboardAssets = &assetfs.AssetFS{Asset: genstatic.Asset, AssetInfo: genstatic.AssetInfo, AssetDir: genstatic.AssetDir, Prefix: "static"} | ||||
| 		log.Debug().RawJSON("staticConfiguration", jsonConf).Msg("Static configuration loaded [json]") | ||||
| 	} | ||||
|  | ||||
| 	if staticConfiguration.Global.CheckNewVersion { | ||||
| @@ -135,16 +129,16 @@ func runCmd(staticConfiguration *static.Configuration) error { | ||||
|  | ||||
| 	sent, err := daemon.SdNotify(false, "READY=1") | ||||
| 	if !sent && err != nil { | ||||
| 		log.WithoutContext().Errorf("Failed to notify: %v", err) | ||||
| 		log.Error().Err(err).Msg("Failed to notify") | ||||
| 	} | ||||
|  | ||||
| 	t, err := daemon.SdWatchdogEnabled(false) | ||||
| 	if err != nil { | ||||
| 		log.WithoutContext().Errorf("Could not enable Watchdog: %v", err) | ||||
| 		log.Error().Err(err).Msg("Could not enable Watchdog") | ||||
| 	} else if t != 0 { | ||||
| 		// Send a ping each half time given | ||||
| 		t /= 2 | ||||
| 		log.WithoutContext().Infof("Watchdog activated with timer duration %s", t) | ||||
| 		log.Info().Msgf("Watchdog activated with timer duration %s", t) | ||||
| 		safe.Go(func() { | ||||
| 			tick := time.Tick(t) | ||||
| 			for range tick { | ||||
| @@ -155,17 +149,17 @@ func runCmd(staticConfiguration *static.Configuration) error { | ||||
|  | ||||
| 				if staticConfiguration.Ping == nil || errHealthCheck == nil { | ||||
| 					if ok, _ := daemon.SdNotify(false, "WATCHDOG=1"); !ok { | ||||
| 						log.WithoutContext().Error("Fail to tick watchdog") | ||||
| 						log.Error().Msg("Fail to tick watchdog") | ||||
| 					} | ||||
| 				} else { | ||||
| 					log.WithoutContext().Error(errHealthCheck) | ||||
| 					log.Error().Err(errHealthCheck).Send() | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	svr.Wait() | ||||
| 	log.WithoutContext().Info("Shutting down") | ||||
| 	log.Info().Msg("Shutting down") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @@ -186,8 +180,7 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
| 	tlsManager := traefiktls.NewManager() | ||||
| 	httpChallengeProvider := acme.NewChallengeHTTP() | ||||
|  | ||||
| 	// we need to wait at least 2 times the ProvidersThrottleDuration to be sure to handle the challenge. | ||||
| 	tlsChallengeProvider := acme.NewChallengeTLSALPN(time.Duration(staticConfiguration.Providers.ProvidersThrottleDuration) * 2) | ||||
| 	tlsChallengeProvider := acme.NewChallengeTLSALPN() | ||||
| 	err = providerAggregator.AddProvider(tlsChallengeProvider) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -195,9 +188,18 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
|  | ||||
| 	acmeProviders := initACMEProvider(staticConfiguration, &providerAggregator, tlsManager, httpChallengeProvider, tlsChallengeProvider) | ||||
|  | ||||
| 	// Tailscale | ||||
|  | ||||
| 	tsProviders := initTailscaleProviders(staticConfiguration, &providerAggregator) | ||||
|  | ||||
| 	// Metrics | ||||
|  | ||||
| 	metricRegistries := registerMetricClients(staticConfiguration.Metrics) | ||||
| 	metricsRegistry := metrics.NewMultiRegistry(metricRegistries) | ||||
|  | ||||
| 	// Entrypoints | ||||
|  | ||||
| 	serverEntryPointsTCP, err := server.NewTCPEntryPoints(staticConfiguration.EntryPoints) | ||||
| 	serverEntryPointsTCP, err := server.NewTCPEntryPoints(staticConfiguration.EntryPoints, staticConfiguration.HostResolver, metricsRegistry) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -207,34 +209,24 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// Pilot | ||||
|  | ||||
| 	var aviator *pilot.Pilot | ||||
| 	var pilotRegistry *metrics.PilotRegistry | ||||
| 	if isPilotEnabled(staticConfiguration) { | ||||
| 		pilotRegistry = metrics.RegisterPilot() | ||||
|  | ||||
| 		aviator = pilot.New(staticConfiguration.Pilot.Token, pilotRegistry, routinesPool) | ||||
|  | ||||
| 		routinesPool.GoCtx(func(ctx context.Context) { | ||||
| 			aviator.Tick(ctx) | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	if staticConfiguration.Pilot != nil { | ||||
| 		version.PilotEnabled = staticConfiguration.Pilot.Dashboard | ||||
| 	if staticConfiguration.API != nil { | ||||
| 		version.DisableDashboardAd = staticConfiguration.API.DisableDashboardAd | ||||
| 	} | ||||
|  | ||||
| 	// Plugins | ||||
|  | ||||
| 	pluginBuilder, err := createPluginBuilder(staticConfiguration) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 		log.Error().Err(err).Msg("Plugins are disabled because an error has occurred.") | ||||
| 	} | ||||
|  | ||||
| 	// Providers plugins | ||||
|  | ||||
| 	for name, conf := range staticConfiguration.Providers.Plugin { | ||||
| 		if pluginBuilder == nil { | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		p, err := pluginBuilder.BuildProvider(name, conf) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("plugin: failed to build provider: %w", err) | ||||
| @@ -246,32 +238,45 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Metrics | ||||
|  | ||||
| 	metricRegistries := registerMetricClients(staticConfiguration.Metrics) | ||||
| 	if pilotRegistry != nil { | ||||
| 		metricRegistries = append(metricRegistries, pilotRegistry) | ||||
| 	} | ||||
| 	metricsRegistry := metrics.NewMultiRegistry(metricRegistries) | ||||
|  | ||||
| 	// Service manager factory | ||||
|  | ||||
| 	roundTripperManager := service.NewRoundTripperManager() | ||||
| 	var spiffeX509Source *workloadapi.X509Source | ||||
| 	if staticConfiguration.Spiffe != nil && staticConfiguration.Spiffe.WorkloadAPIAddr != "" { | ||||
| 		log.Info().Str("workloadAPIAddr", staticConfiguration.Spiffe.WorkloadAPIAddr). | ||||
| 			Msg("Waiting on SPIFFE SVID delivery") | ||||
|  | ||||
| 		spiffeX509Source, err = workloadapi.NewX509Source( | ||||
| 			ctx, | ||||
| 			workloadapi.WithClientOptions( | ||||
| 				workloadapi.WithAddr( | ||||
| 					staticConfiguration.Spiffe.WorkloadAPIAddr, | ||||
| 				), | ||||
| 			), | ||||
| 		) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("unable to create SPIFFE x509 source: %w", err) | ||||
| 		} | ||||
| 		log.Info().Msg("Successfully obtained SPIFFE SVID.") | ||||
| 	} | ||||
|  | ||||
| 	roundTripperManager := service.NewRoundTripperManager(spiffeX509Source) | ||||
| 	dialerManager := tcp.NewDialerManager(spiffeX509Source) | ||||
| 	acmeHTTPHandler := getHTTPChallengeHandler(acmeProviders, httpChallengeProvider) | ||||
| 	managerFactory := service.NewManagerFactory(*staticConfiguration, routinesPool, metricsRegistry, roundTripperManager, acmeHTTPHandler) | ||||
|  | ||||
| 	// Router factory | ||||
|  | ||||
| 	accessLog := setupAccessLog(staticConfiguration.AccessLog) | ||||
| 	chainBuilder := middleware.NewChainBuilder(*staticConfiguration, metricsRegistry, accessLog) | ||||
| 	routerFactory := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, chainBuilder, pluginBuilder, metricsRegistry) | ||||
| 	tracer := setupTracing(staticConfiguration.Tracing) | ||||
|  | ||||
| 	chainBuilder := middleware.NewChainBuilder(metricsRegistry, accessLog, tracer) | ||||
| 	routerFactory := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, chainBuilder, pluginBuilder, metricsRegistry, dialerManager) | ||||
|  | ||||
| 	// Watcher | ||||
|  | ||||
| 	watcher := server.NewConfigurationWatcher( | ||||
| 		routinesPool, | ||||
| 		providerAggregator, | ||||
| 		time.Duration(staticConfiguration.Providers.ProvidersThrottleDuration), | ||||
| 		getDefaultsEntrypoints(staticConfiguration), | ||||
| 		"internal", | ||||
| 	) | ||||
| @@ -282,7 +287,7 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
| 		tlsManager.UpdateConfigs(ctx, conf.TLS.Stores, conf.TLS.Options, conf.TLS.Certificates) | ||||
|  | ||||
| 		gauge := metricsRegistry.TLSCertsNotAfterTimestampGauge() | ||||
| 		for _, certificate := range tlsManager.GetCertificates() { | ||||
| 		for _, certificate := range tlsManager.GetServerCertificates() { | ||||
| 			appendCertMetric(gauge, certificate) | ||||
| 		} | ||||
| 	}) | ||||
| @@ -296,13 +301,14 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
| 	// Server Transports | ||||
| 	watcher.AddListener(func(conf dynamic.Configuration) { | ||||
| 		roundTripperManager.Update(conf.HTTP.ServersTransports) | ||||
| 		dialerManager.Update(conf.TCP.ServersTransports) | ||||
| 	}) | ||||
|  | ||||
| 	// Switch router | ||||
| 	watcher.AddListener(switchRouter(routerFactory, serverEntryPointsTCP, serverEntryPointsUDP, aviator)) | ||||
| 	watcher.AddListener(switchRouter(routerFactory, serverEntryPointsTCP, serverEntryPointsUDP)) | ||||
|  | ||||
| 	// Metrics | ||||
| 	if metricsRegistry.IsEpEnabled() || metricsRegistry.IsSvcEnabled() { | ||||
| 	if metricsRegistry.IsEpEnabled() || metricsRegistry.IsRouterEnabled() || metricsRegistry.IsSvcEnabled() { | ||||
| 		var eps []string | ||||
| 		for key := range serverEntryPointsTCP { | ||||
| 			eps = append(eps, key) | ||||
| @@ -315,13 +321,22 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
| 	// TLS challenge | ||||
| 	watcher.AddListener(tlsChallengeProvider.ListenConfiguration) | ||||
|  | ||||
| 	// ACME | ||||
| 	// Certificate Resolvers | ||||
|  | ||||
| 	resolverNames := map[string]struct{}{} | ||||
|  | ||||
| 	// ACME | ||||
| 	for _, p := range acmeProviders { | ||||
| 		resolverNames[p.ResolverName] = struct{}{} | ||||
| 		watcher.AddListener(p.ListenConfiguration) | ||||
| 	} | ||||
|  | ||||
| 	// Tailscale | ||||
| 	for _, p := range tsProviders { | ||||
| 		resolverNames[p.ResolverName] = struct{}{} | ||||
| 		watcher.AddListener(p.HandleConfigUpdate) | ||||
| 	} | ||||
|  | ||||
| 	// Certificate resolver logs | ||||
| 	watcher.AddListener(func(config dynamic.Configuration) { | ||||
| 		for rtName, rt := range config.HTTP.Routers { | ||||
| @@ -330,7 +345,8 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err | ||||
| 			} | ||||
|  | ||||
| 			if _, ok := resolverNames[rt.TLS.CertResolver]; !ok { | ||||
| 				log.WithoutContext().Errorf("the router %s uses a non-existent resolver: %s", rtName, rt.TLS.CertResolver) | ||||
| 				log.Error().Err(err).Str(logs.RouterName, rtName).Str("certificateResolver", rt.TLS.CertResolver). | ||||
| 					Msg("Router uses a non-existent certificate resolver") | ||||
| 			} | ||||
| 		} | ||||
| 	}) | ||||
| @@ -351,11 +367,27 @@ func getHTTPChallengeHandler(acmeProviders []*acme.Provider, httpChallengeProvid | ||||
|  | ||||
| func getDefaultsEntrypoints(staticConfiguration *static.Configuration) []string { | ||||
| 	var defaultEntryPoints []string | ||||
|  | ||||
| 	// Determines if at least one EntryPoint is configured to be used by default. | ||||
| 	var hasDefinedDefaults bool | ||||
| 	for _, ep := range staticConfiguration.EntryPoints { | ||||
| 		if ep.AsDefault { | ||||
| 			hasDefinedDefaults = true | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for name, cfg := range staticConfiguration.EntryPoints { | ||||
| 		// By default all entrypoints are considered. | ||||
| 		// If at least one is flagged, then only flagged entrypoints are included. | ||||
| 		if hasDefinedDefaults && !cfg.AsDefault { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		protocol, err := cfg.GetProtocol() | ||||
| 		if err != nil { | ||||
| 			// Should never happen because Traefik should not start if protocol is invalid. | ||||
| 			log.WithoutContext().Errorf("Invalid protocol: %v", err) | ||||
| 			log.Error().Err(err).Msg("Invalid protocol") | ||||
| 		} | ||||
|  | ||||
| 		if protocol != "udp" && name != static.DefaultInternalEntryPointName { | ||||
| @@ -367,22 +399,18 @@ func getDefaultsEntrypoints(staticConfiguration *static.Configuration) []string | ||||
| 	return defaultEntryPoints | ||||
| } | ||||
|  | ||||
| func switchRouter(routerFactory *server.RouterFactory, serverEntryPointsTCP server.TCPEntryPoints, serverEntryPointsUDP server.UDPEntryPoints, aviator *pilot.Pilot) func(conf dynamic.Configuration) { | ||||
| func switchRouter(routerFactory *server.RouterFactory, serverEntryPointsTCP server.TCPEntryPoints, serverEntryPointsUDP server.UDPEntryPoints) func(conf dynamic.Configuration) { | ||||
| 	return func(conf dynamic.Configuration) { | ||||
| 		rtConf := runtime.NewConfig(conf) | ||||
|  | ||||
| 		routers, udpRouters := routerFactory.CreateRouters(rtConf) | ||||
|  | ||||
| 		if aviator != nil { | ||||
| 			aviator.SetDynamicConfiguration(conf) | ||||
| 		} | ||||
|  | ||||
| 		serverEntryPointsTCP.Switch(routers) | ||||
| 		serverEntryPointsUDP.Switch(udpRouters) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // initACMEProvider creates an acme provider from the ACME part of globalConfiguration. | ||||
| // initACMEProvider creates and registers acme.Provider instances corresponding to the configured ACME certificate resolvers. | ||||
| func initACMEProvider(c *static.Configuration, providerAggregator *aggregator.ProviderAggregator, tlsManager *traefiktls.Manager, httpChallengeProvider, tlsChallengeProvider challenge.Provider) []*acme.Provider { | ||||
| 	localStores := map[string]*acme.LocalStore{} | ||||
|  | ||||
| @@ -405,7 +433,7 @@ func initACMEProvider(c *static.Configuration, providerAggregator *aggregator.Pr | ||||
| 		} | ||||
|  | ||||
| 		if err := providerAggregator.AddProvider(p); err != nil { | ||||
| 			log.WithoutContext().Errorf("The ACME resolver %q is skipped from the resolvers list because: %v", name, err) | ||||
| 			log.Error().Err(err).Str("resolver", name).Msg("The ACME resolve is skipped from the resolvers list") | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| @@ -419,6 +447,27 @@ func initACMEProvider(c *static.Configuration, providerAggregator *aggregator.Pr | ||||
| 	return resolvers | ||||
| } | ||||
|  | ||||
| // initTailscaleProviders creates and registers tailscale.Provider instances corresponding to the configured Tailscale certificate resolvers. | ||||
| func initTailscaleProviders(cfg *static.Configuration, providerAggregator *aggregator.ProviderAggregator) []*tailscale.Provider { | ||||
| 	var providers []*tailscale.Provider | ||||
| 	for name, resolver := range cfg.CertificatesResolvers { | ||||
| 		if resolver.Tailscale == nil { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		tsProvider := &tailscale.Provider{ResolverName: name} | ||||
|  | ||||
| 		if err := providerAggregator.AddProvider(tsProvider); err != nil { | ||||
| 			log.Error().Err(err).Str(logs.ProviderName, name).Msg("Unable to create Tailscale provider") | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		providers = append(providers, tsProvider) | ||||
| 	} | ||||
|  | ||||
| 	return providers | ||||
| } | ||||
|  | ||||
| func registerMetricClients(metricsConfig *types.Metrics) []metrics.Registry { | ||||
| 	if metricsConfig == nil { | ||||
| 		return nil | ||||
| @@ -427,33 +476,61 @@ func registerMetricClients(metricsConfig *types.Metrics) []metrics.Registry { | ||||
| 	var registries []metrics.Registry | ||||
|  | ||||
| 	if metricsConfig.Prometheus != nil { | ||||
| 		ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "prometheus")) | ||||
| 		prometheusRegister := metrics.RegisterPrometheus(ctx, metricsConfig.Prometheus) | ||||
| 		logger := log.With().Str(logs.MetricsProviderName, "prometheus").Logger() | ||||
|  | ||||
| 		prometheusRegister := metrics.RegisterPrometheus(logger.WithContext(context.Background()), metricsConfig.Prometheus) | ||||
| 		if prometheusRegister != nil { | ||||
| 			registries = append(registries, prometheusRegister) | ||||
| 			log.FromContext(ctx).Debug("Configured Prometheus metrics") | ||||
| 			logger.Debug().Msg("Configured Prometheus metrics") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if metricsConfig.Datadog != nil { | ||||
| 		ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "datadog")) | ||||
| 		registries = append(registries, metrics.RegisterDatadog(ctx, metricsConfig.Datadog)) | ||||
| 		log.FromContext(ctx).Debugf("Configured Datadog metrics: pushing to %s once every %s", | ||||
| 			metricsConfig.Datadog.Address, metricsConfig.Datadog.PushInterval) | ||||
| 		logger := log.With().Str(logs.MetricsProviderName, "datadog").Logger() | ||||
|  | ||||
| 		registries = append(registries, metrics.RegisterDatadog(logger.WithContext(context.Background()), metricsConfig.Datadog)) | ||||
| 		logger.Debug(). | ||||
| 			Str("address", metricsConfig.Datadog.Address). | ||||
| 			Str("pushInterval", metricsConfig.Datadog.PushInterval.String()). | ||||
| 			Msgf("Configured Datadog metrics") | ||||
| 	} | ||||
|  | ||||
| 	if metricsConfig.StatsD != nil { | ||||
| 		ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "statsd")) | ||||
| 		registries = append(registries, metrics.RegisterStatsd(ctx, metricsConfig.StatsD)) | ||||
| 		log.FromContext(ctx).Debugf("Configured StatsD metrics: pushing to %s once every %s", | ||||
| 			metricsConfig.StatsD.Address, metricsConfig.StatsD.PushInterval) | ||||
| 		logger := log.With().Str(logs.MetricsProviderName, "statsd").Logger() | ||||
|  | ||||
| 		registries = append(registries, metrics.RegisterStatsd(logger.WithContext(context.Background()), metricsConfig.StatsD)) | ||||
| 		logger.Debug(). | ||||
| 			Str("address", metricsConfig.StatsD.Address). | ||||
| 			Str("pushInterval", metricsConfig.StatsD.PushInterval.String()). | ||||
| 			Msg("Configured StatsD metrics") | ||||
| 	} | ||||
|  | ||||
| 	if metricsConfig.InfluxDB != nil { | ||||
| 		ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "influxdb")) | ||||
| 		registries = append(registries, metrics.RegisterInfluxDB(ctx, metricsConfig.InfluxDB)) | ||||
| 		log.FromContext(ctx).Debugf("Configured InfluxDB metrics: pushing to %s once every %s", | ||||
| 			metricsConfig.InfluxDB.Address, metricsConfig.InfluxDB.PushInterval) | ||||
| 	if metricsConfig.InfluxDB2 != nil { | ||||
| 		logger := log.With().Str(logs.MetricsProviderName, "influxdb2").Logger() | ||||
|  | ||||
| 		influxDB2Register := metrics.RegisterInfluxDB2(logger.WithContext(context.Background()), metricsConfig.InfluxDB2) | ||||
| 		if influxDB2Register != nil { | ||||
| 			registries = append(registries, influxDB2Register) | ||||
| 			logger.Debug(). | ||||
| 				Str("address", metricsConfig.InfluxDB2.Address). | ||||
| 				Str("bucket", metricsConfig.InfluxDB2.Bucket). | ||||
| 				Str("organization", metricsConfig.InfluxDB2.Org). | ||||
| 				Str("pushInterval", metricsConfig.InfluxDB2.PushInterval.String()). | ||||
| 				Msg("Configured InfluxDB v2 metrics") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if metricsConfig.OpenTelemetry != nil { | ||||
| 		logger := log.With().Str(logs.MetricsProviderName, "openTelemetry").Logger() | ||||
|  | ||||
| 		openTelemetryRegistry := metrics.RegisterOpenTelemetry(logger.WithContext(context.Background()), metricsConfig.OpenTelemetry) | ||||
| 		if openTelemetryRegistry != nil { | ||||
| 			registries = append(registries, openTelemetryRegistry) | ||||
| 			logger.Debug(). | ||||
| 				Str("address", metricsConfig.OpenTelemetry.Address). | ||||
| 				Str("pushInterval", metricsConfig.OpenTelemetry.PushInterval.String()). | ||||
| 				Msg("Configured OpenTelemetry metrics") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return registries | ||||
| @@ -480,64 +557,85 @@ func setupAccessLog(conf *types.AccessLog) *accesslog.Handler { | ||||
|  | ||||
| 	accessLoggerMiddleware, err := accesslog.NewHandler(conf) | ||||
| 	if err != nil { | ||||
| 		log.WithoutContext().Warnf("Unable to create access logger : %v", err) | ||||
| 		log.Warn().Err(err).Msg("Unable to create access logger") | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return accessLoggerMiddleware | ||||
| } | ||||
|  | ||||
| func configureLogging(staticConfiguration *static.Configuration) { | ||||
| 	// configure default log flags | ||||
| 	stdlog.SetFlags(stdlog.Lshortfile | stdlog.LstdFlags) | ||||
|  | ||||
| 	// configure log level | ||||
| 	// an explicitly defined log level always has precedence. if none is | ||||
| 	// given and debug mode is disabled, the default is ERROR, and DEBUG | ||||
| 	// otherwise. | ||||
| 	levelStr := "error" | ||||
| 	if staticConfiguration.Log != nil && staticConfiguration.Log.Level != "" { | ||||
| 		levelStr = strings.ToLower(staticConfiguration.Log.Level) | ||||
| func setupTracing(conf *static.Tracing) *tracing.Tracing { | ||||
| 	if conf == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	level, err := logrus.ParseLevel(levelStr) | ||||
| 	var backend tracing.Backend | ||||
|  | ||||
| 	if conf.Jaeger != nil { | ||||
| 		backend = conf.Jaeger | ||||
| 	} | ||||
|  | ||||
| 	if conf.Zipkin != nil { | ||||
| 		if backend != nil { | ||||
| 			log.Error().Msg("Multiple tracing backend are not supported: cannot create Zipkin backend.") | ||||
| 		} else { | ||||
| 			backend = conf.Zipkin | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if conf.Datadog != nil { | ||||
| 		if backend != nil { | ||||
| 			log.Error().Msg("Multiple tracing backend are not supported: cannot create Datadog backend.") | ||||
| 		} else { | ||||
| 			backend = conf.Datadog | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if conf.Instana != nil { | ||||
| 		if backend != nil { | ||||
| 			log.Error().Msg("Multiple tracing backend are not supported: cannot create Instana backend.") | ||||
| 		} else { | ||||
| 			backend = conf.Instana | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if conf.Haystack != nil { | ||||
| 		if backend != nil { | ||||
| 			log.Error().Msg("Multiple tracing backend are not supported: cannot create Haystack backend.") | ||||
| 		} else { | ||||
| 			backend = conf.Haystack | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if conf.Elastic != nil { | ||||
| 		if backend != nil { | ||||
| 			log.Error().Msg("Multiple tracing backend are not supported: cannot create Elastic backend.") | ||||
| 		} else { | ||||
| 			backend = conf.Elastic | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if conf.OpenTelemetry != nil { | ||||
| 		if backend != nil { | ||||
| 			log.Error().Msg("Tracing backends are all mutually exclusive: cannot create OpenTelemetry backend.") | ||||
| 		} else { | ||||
| 			backend = conf.OpenTelemetry | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if backend == nil { | ||||
| 		log.Debug().Msg("Could not initialize tracing, using Jaeger by default") | ||||
| 		defaultBackend := &jaeger.Config{} | ||||
| 		defaultBackend.SetDefaults() | ||||
| 		backend = defaultBackend | ||||
| 	} | ||||
|  | ||||
| 	tracer, err := tracing.NewTracing(conf.ServiceName, conf.SpanNameLimit, backend) | ||||
| 	if err != nil { | ||||
| 		log.WithoutContext().Errorf("Error getting level: %v", err) | ||||
| 	} | ||||
| 	log.SetLevel(level) | ||||
|  | ||||
| 	var logFile string | ||||
| 	if staticConfiguration.Log != nil && len(staticConfiguration.Log.FilePath) > 0 { | ||||
| 		logFile = staticConfiguration.Log.FilePath | ||||
| 	} | ||||
|  | ||||
| 	// configure log format | ||||
| 	var formatter logrus.Formatter | ||||
| 	if staticConfiguration.Log != nil && staticConfiguration.Log.Format == "json" { | ||||
| 		formatter = &logrus.JSONFormatter{} | ||||
| 	} else { | ||||
| 		disableColors := len(logFile) > 0 | ||||
| 		formatter = &logrus.TextFormatter{DisableColors: disableColors, FullTimestamp: true, DisableSorting: true} | ||||
| 	} | ||||
| 	log.SetFormatter(formatter) | ||||
|  | ||||
| 	if len(logFile) > 0 { | ||||
| 		dir := filepath.Dir(logFile) | ||||
|  | ||||
| 		if err := os.MkdirAll(dir, 0o755); err != nil { | ||||
| 			log.WithoutContext().Errorf("Failed to create log path %s: %s", dir, err) | ||||
| 		} | ||||
|  | ||||
| 		err = log.OpenFile(logFile) | ||||
| 		logrus.RegisterExitHandler(func() { | ||||
| 			if err := log.CloseFile(); err != nil { | ||||
| 				log.WithoutContext().Errorf("Error while closing log: %v", err) | ||||
| 			} | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			log.WithoutContext().Errorf("Error while opening log file %s: %v", logFile, err) | ||||
| 		} | ||||
| 		log.Warn().Err(err).Msg("Unable to create tracer") | ||||
| 		return nil | ||||
| 	} | ||||
| 	return tracer | ||||
| } | ||||
|  | ||||
| func checkNewVersion() { | ||||
| @@ -550,16 +648,16 @@ func checkNewVersion() { | ||||
| } | ||||
|  | ||||
| func stats(staticConfiguration *static.Configuration) { | ||||
| 	logger := log.WithoutContext() | ||||
| 	logger := log.Info() | ||||
|  | ||||
| 	if staticConfiguration.Global.SendAnonymousUsage { | ||||
| 		logger.Info(`Stats collection is enabled.`) | ||||
| 		logger.Info(`Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.`) | ||||
| 		logger.Info(`Help us improve Traefik by leaving this feature on :)`) | ||||
| 		logger.Info(`More details on: https://doc.traefik.io/traefik/contributing/data-collection/`) | ||||
| 		logger.Msg(`Stats collection is enabled.`) | ||||
| 		logger.Msg(`Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.`) | ||||
| 		logger.Msg(`Help us improve Traefik by leaving this feature on :)`) | ||||
| 		logger.Msg(`More details on: https://doc.traefik.io/traefik/contributing/data-collection/`) | ||||
| 		collect(staticConfiguration) | ||||
| 	} else { | ||||
| 		logger.Info(` | ||||
| 		logger.Msg(` | ||||
| Stats collection is disabled. | ||||
| Help us improve Traefik by turning this feature on :) | ||||
| More details on: https://doc.traefik.io/traefik/contributing/data-collection/ | ||||
| @@ -572,7 +670,7 @@ func collect(staticConfiguration *static.Configuration) { | ||||
| 	safe.Go(func() { | ||||
| 		for time.Sleep(10 * time.Minute); ; <-ticker { | ||||
| 			if err := collector.Collect(staticConfiguration); err != nil { | ||||
| 				log.WithoutContext().Debug(err) | ||||
| 				log.Debug().Err(err).Send() | ||||
| 			} | ||||
| 		} | ||||
| 	}) | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import ( | ||||
| 	"github.com/go-kit/kit/metrics" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 	"github.com/traefik/traefik/v3/pkg/config/static" | ||||
| ) | ||||
|  | ||||
| // FooCert is a PEM-encoded TLS cert. | ||||
| @@ -114,3 +115,79 @@ func TestAppendCertMetric(t *testing.T) { | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestGetDefaultsEntrypoints(t *testing.T) { | ||||
| 	testCases := []struct { | ||||
| 		desc        string | ||||
| 		entrypoints static.EntryPoints | ||||
| 		expected    []string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			desc: "Skips special names", | ||||
| 			entrypoints: map[string]*static.EntryPoint{ | ||||
| 				"web": { | ||||
| 					Address: ":80", | ||||
| 				}, | ||||
| 				"traefik": { | ||||
| 					Address: ":8080", | ||||
| 				}, | ||||
| 				"traefikhub-api": { | ||||
| 					Address: ":9900", | ||||
| 				}, | ||||
| 				"traefikhub-tunl": { | ||||
| 					Address: ":9901", | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: []string{"web"}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc: "Two EntryPoints not attachable", | ||||
| 			entrypoints: map[string]*static.EntryPoint{ | ||||
| 				"web": { | ||||
| 					Address: ":80", | ||||
| 				}, | ||||
| 				"websecure": { | ||||
| 					Address: ":443", | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: []string{"web", "websecure"}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc: "Two EntryPoints only one attachable", | ||||
| 			entrypoints: map[string]*static.EntryPoint{ | ||||
| 				"web": { | ||||
| 					Address: ":80", | ||||
| 				}, | ||||
| 				"websecure": { | ||||
| 					Address:   ":443", | ||||
| 					AsDefault: true, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: []string{"websecure"}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			desc: "Two attachable EntryPoints", | ||||
| 			entrypoints: map[string]*static.EntryPoint{ | ||||
| 				"web": { | ||||
| 					Address:   ":80", | ||||
| 					AsDefault: true, | ||||
| 				}, | ||||
| 				"websecure": { | ||||
| 					Address:   ":443", | ||||
| 					AsDefault: true, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: []string{"web", "websecure"}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range testCases { | ||||
| 		t.Run(test.desc, func(t *testing.T) { | ||||
| 			actual := getDefaultsEntrypoints(&static.Configuration{ | ||||
| 				EntryPoints: test.entrypoints, | ||||
| 			}) | ||||
|  | ||||
| 			assert.ElementsMatch(t, test.expected, actual) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -8,7 +8,7 @@ import ( | ||||
| 	"text/template" | ||||
|  | ||||
| 	"github.com/traefik/paerser/cli" | ||||
| 	"github.com/traefik/traefik/v2/pkg/version" | ||||
| 	"github.com/traefik/traefik/v3/pkg/version" | ||||
| ) | ||||
|  | ||||
| var versionTemplate = `Version:      {{.Version}} | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										10
									
								
								debug.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								debug.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| FROM alpine:3.14 | ||||
| # Feel free to add below any helpful dependency for debugging. | ||||
| # iproute2 is for ss. | ||||
| RUN apk --no-cache --no-progress add bash curl ca-certificates tzdata lsof iproute2 \ | ||||
|     && update-ca-certificates \ | ||||
|     && rm -rf /var/cache/apk/* | ||||
| COPY dist/traefik / | ||||
| EXPOSE 80 | ||||
| VOLUME ["/tmp"] | ||||
| ENTRYPOINT ["/traefik"] | ||||
| @@ -4,6 +4,7 @@ | ||||
|     "MD009": false, | ||||
|     "MD013": false, | ||||
|     "MD024": false, | ||||
|     "MD025": false, | ||||
|     "MD026": false, | ||||
|     "MD033": false, | ||||
|     "MD034": false, | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
|  | ||||
| ####### | ||||
| # This Makefile contains all targets related to the documentation | ||||
| ####### | ||||
| @@ -16,41 +15,51 @@ DOCKER_RUN_DOC_MOUNTS := -v $(CURDIR):/mkdocs | ||||
| DOCKER_RUN_DOC_OPTS := --rm $(DOCKER_RUN_DOC_MOUNTS) -p $(DOCKER_RUN_DOC_PORT):8000 | ||||
|  | ||||
| # Default: generates the documentation into $(SITE_DIR) | ||||
| .PHONY: docs | ||||
| docs: docs-clean docs-image docs-lint docs-build docs-verify | ||||
|  | ||||
| # Writer Mode: build and serve docs on http://localhost:8000 with livereload | ||||
| .PHONY: docs-serve | ||||
| docs-serve: docs-image | ||||
| 	docker run  $(DOCKER_RUN_DOC_OPTS) $(TRAEFIK_DOCS_BUILD_IMAGE) mkdocs serve | ||||
|  | ||||
| ## Pull image for doc building | ||||
| .PHONY: docs-pull-images | ||||
| docs-pull-images: | ||||
| 	grep --no-filename -E '^FROM' ./*.Dockerfile | awk '{print $$2}' | sort | uniq | xargs -P 6 -n 1 docker pull | ||||
| 	grep --no-filename -E '^FROM' ./*.Dockerfile \ | ||||
| 		| awk '{print $$2}' \ | ||||
| 		| sort \ | ||||
| 		| uniq \ | ||||
| 		| xargs -P 6 -n 1 docker pull | ||||
|  | ||||
| # Utilities Targets for each step | ||||
| .PHONY: docs-image | ||||
| docs-image: | ||||
| 	docker build -t $(TRAEFIK_DOCS_BUILD_IMAGE) -f docs.Dockerfile ./ | ||||
|  | ||||
| .PHONY: docs-build | ||||
| docs-build: docs-image | ||||
| 	docker run $(DOCKER_RUN_DOC_OPTS) $(TRAEFIK_DOCS_BUILD_IMAGE) sh -c "mkdocs build \ | ||||
| 		&& chown -R $(shell id -u):$(shell id -g) ./site" | ||||
|  | ||||
| .PHONY: docs-verify | ||||
| docs-verify: docs-build | ||||
| 	@if [ "$(DOCS_VERIFY_SKIP)" != "true" ]; then \ | ||||
| 		docker build -t $(TRAEFIK_DOCS_CHECK_IMAGE) -f check.Dockerfile ./; \ | ||||
| 		docker run --rm -v $(CURDIR):/app $(TRAEFIK_DOCS_CHECK_IMAGE) /verify.sh; \ | ||||
| 	else \ | ||||
| 		echo "DOCS_VERIFY_SKIP is true: no verification done."; \ | ||||
| 	fi | ||||
| ifneq ("$(DOCS_VERIFY_SKIP)", "true") | ||||
| 	docker build -t $(TRAEFIK_DOCS_CHECK_IMAGE) -f check.Dockerfile ./ | ||||
| 	docker run --rm -v $(CURDIR):/app $(TRAEFIK_DOCS_CHECK_IMAGE) /verify.sh | ||||
| else | ||||
| 	echo "DOCS_VERIFY_SKIP is true: no verification done." | ||||
| endif | ||||
|  | ||||
| .PHONY: docs-lint | ||||
| docs-lint: | ||||
| 	@if [ "$(DOCS_LINT_SKIP)" != "true" ]; then \ | ||||
| 		docker build -t $(TRAEFIK_DOCS_CHECK_IMAGE) -f check.Dockerfile ./ && \ | ||||
| 		docker run --rm -v $(CURDIR):/app $(TRAEFIK_DOCS_CHECK_IMAGE) /lint.sh; \ | ||||
| 	else \ | ||||
| 		echo "DOCS_LINT_SKIP is true: no linting done."; \ | ||||
| 	fi | ||||
| ifneq ("$(DOCS_LINT_SKIP)", "true") | ||||
| 	docker build -t $(TRAEFIK_DOCS_CHECK_IMAGE) -f check.Dockerfile ./ | ||||
| 	docker run --rm -v $(CURDIR):/app $(TRAEFIK_DOCS_CHECK_IMAGE) /lint.sh | ||||
| else | ||||
| 	echo "DOCS_LINT_SKIP is true: no linting done." | ||||
| endif | ||||
|  | ||||
| .PHONY: docs-clean | ||||
| docs-clean: | ||||
| 	rm -rf $(SITE_DIR) | ||||
|  | ||||
| .PHONY: all docs-verify docs docs-clean docs-build docs-lint | ||||
|   | ||||
| @@ -1,18 +1,21 @@ | ||||
|  | ||||
| FROM alpine:3.14 as alpine | ||||
| FROM alpine:3.18 as alpine | ||||
|  | ||||
| RUN apk --no-cache --no-progress add \ | ||||
|     build-base \ | ||||
|     gcompat \ | ||||
|     libcurl \ | ||||
|     libxml2-dev \ | ||||
|     libxslt-dev \ | ||||
|     ruby \ | ||||
|     ruby-bigdecimal \ | ||||
|     ruby-dev \ | ||||
|     ruby-etc \ | ||||
|     ruby-ffi \ | ||||
|     ruby-json \ | ||||
|     ruby-nokogiri \ | ||||
|     ruby-dev \ | ||||
|     build-base | ||||
|     zlib-dev | ||||
|  | ||||
| RUN gem install html-proofer --version 3.19.0 --no-document -- --use-system-libraries | ||||
| RUN gem install nokogiri --version 1.15.3 --no-document -- --use-system-libraries | ||||
| RUN gem install html-proofer --version 5.0.7 --no-document -- --use-system-libraries | ||||
|  | ||||
| # After Ruby, some NodeJS YAY! | ||||
| RUN apk --no-cache --no-progress add \ | ||||
| @@ -20,12 +23,9 @@ RUN apk --no-cache --no-progress add \ | ||||
|     nodejs \ | ||||
|     npm | ||||
|  | ||||
| # To handle 'not get uid/gid' | ||||
| RUN npm config set unsafe-perm true | ||||
|  | ||||
| RUN npm install --global \ | ||||
|     markdownlint@0.22.0 \ | ||||
|     markdownlint-cli@0.26.0 | ||||
|     markdownlint@0.29.0 \ | ||||
|     markdownlint-cli@0.35.0 | ||||
|  | ||||
| # Finally the shell tools we need for later | ||||
| # tini helps to terminate properly all the parallelized tasks when sending CTRL-C | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 58 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/content/assets/img/providers/nomad.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/content/assets/img/providers/nomad.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 13 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/content/assets/img/traefik.logo-dark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/content/assets/img/traefik.logo-dark.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 38 KiB | 
| @@ -1,10 +1,31 @@ | ||||
| --- | ||||
| title: "Traefik Advocation Documentation" | ||||
| description: "There are many ways to contribute to Traefik Proxy. If you're talking about Traefik, let us know and we'll promote your enthusiasm!" | ||||
| --- | ||||
|  | ||||
| # Advocating | ||||
|  | ||||
| Spread the Love & Tell Us about It | ||||
| {: .subtitle } | ||||
|  | ||||
| There are many ways to contribute to the project, and there is one that always spark joy: when we see/read about users talking about how Traefik helps them solve their problems. | ||||
| Traefik Proxy was started by the community for the community. | ||||
| You can contribute to the Traefik community in three main ways: | ||||
|  | ||||
| If you're talking about Traefik, [let us know](https://blog.traefik.io/spread-the-love-ba5a40aa72e7) and we'll promote your enthusiasm! | ||||
| **Spread the word!** Guides, videos, blog posts, how-to articles, and showing off your network design all help spread the word about Traefik Proxy | ||||
| and teach others in the community how to best implement it. | ||||
| It always sparks joy when users share how Traefik Proxy helps them solve their problems. | ||||
| If you are talking about Traefik Proxy, [let us know](https://traefik.io/submit-my-contribution/) and we will promote your work and reward your enthusiasm! | ||||
| If you are giving a talk that includes or is about Traefik Proxy, [let us know](https://traefik.io/submit-my-contribution/) and we will send you swag and stickers for your time at the conference. | ||||
| If you have written about Traefik or shared useful information you would like to promote, feel free to add links to the [dedicated wiki page on GitHub](https://github.com/traefik/traefik/wiki/Awesome-Traefik). | ||||
|  | ||||
| Also, if you've written about Traefik or shared useful information you'd like to promote, feel free to add links in the [dedicated wiki page on Github](https://github.com/traefik/traefik/wiki/Awesome-Traefik). | ||||
| **Help community members!** Everyone needs a place to share their cool innovations or get help with that pesky bug that only a different pair of eyes seems to be able to see. | ||||
| Join our [Community Forum](https://community.traefik.io/) where you can ask questions, help out other users, and share your neat configuration examples or snippets. | ||||
| Top contributors will be asked to join the Ambassador program and get unique swag to celebrate! | ||||
|  | ||||
| **Build cool solutions!** Traefik Proxy would be so much better if only it had… | ||||
| We love all the wonderful ideas that our users come up with, but we can only build so much. | ||||
| Luckily, as an open source community, our users can help by [building awesome features](https://github.com/orgs/traefik/projects/9/views/7), enhancements, or bug fixes. | ||||
| We are a big community, so we do need to prioritize a bit. | ||||
| That is why we use the tag `contributor/wanted` to let you know which pull requests will make it to the front of the queue for design support and review. | ||||
| Feel free to grab one of these and run with it. | ||||
| Top contributors get unique swag to celebrate. | ||||
|   | ||||
| @@ -1,19 +1,29 @@ | ||||
| --- | ||||
| title: "Traefik Building & Testing Documentation" | ||||
| description: "Compile and test your own Traefik Proxy! Learn how to build your own Traefik binary from the sources, and read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Building and Testing | ||||
|  | ||||
| Compile and Test Your Own Traefik! | ||||
| {: .subtitle } | ||||
|  | ||||
| So you want to build your own Traefik binary from the sources? | ||||
| You want to build your own Traefik binary from the sources? | ||||
| Let's see how. | ||||
|  | ||||
| ## Building | ||||
|  | ||||
| You need either [Docker](https://github.com/docker/docker) and `make` (Method 1), or `go` (Method 2) in order to build Traefik. | ||||
| You need either [Docker](https://github.com/docker/docker "Link to website of Docker") and `make` (Method 1), or [Go](https://go.dev/ "Link to website of Go") (Method 2) in order to build Traefik. | ||||
| For changes to its dependencies, the `dep` dependency management tool is required. | ||||
|  | ||||
| ### Method 1: Using `Docker` and `Makefile` | ||||
|  | ||||
| Run make with the `binary` target. | ||||
|  | ||||
| ```bash | ||||
| make binary | ||||
| ``` | ||||
|  | ||||
| This will create binaries for the Linux platform in the `dist` folder. | ||||
|  | ||||
| In case when you run build on CI, you may probably want to run docker in non-interactive mode. To achieve that define `DOCKER_NON_INTERACTIVE=true` environment variable. | ||||
| @@ -45,7 +55,7 @@ $ ls dist/ | ||||
| traefik* | ||||
| ``` | ||||
|  | ||||
| The following targets can be executed outside Docker by setting the variable `PRE_TARGET` to an empty string (we don't recommend that): | ||||
| The following targets can be executed outside Docker by setting the variable `IN_DOCKER` to an empty string (although be aware that some of the tests might fail in that context): | ||||
|  | ||||
| - `test-unit` | ||||
| - `test-integration` | ||||
| @@ -55,7 +65,7 @@ The following targets can be executed outside Docker by setting the variable `PR | ||||
| ex: | ||||
|  | ||||
| ```bash | ||||
| PRE_TARGET= make test-unit | ||||
| IN_DOCKER= make test-unit | ||||
| ``` | ||||
|  | ||||
| ### Method 2: Using `go` | ||||
| @@ -64,7 +74,6 @@ Requirements: | ||||
|  | ||||
| - `go` v1.16+ | ||||
| - environment variable `GO111MODULE=on` | ||||
| - [go-bindata](https://github.com/containous/go-bindata) `GO111MODULE=off go get -u github.com/containous/go-bindata/...` | ||||
|  | ||||
| !!! tip "Source Directory" | ||||
|  | ||||
| @@ -101,18 +110,9 @@ Requirements: | ||||
|  | ||||
| Once you've set up your go environment and cloned the source repository, you can build Traefik. | ||||
|  | ||||
| Beforehand, you need to get [go-bindata](https://github.com/containous/go-bindata) (the first time) in order to be able to use the `go generate` command (which is part of the build process). | ||||
|  | ||||
| ```bash | ||||
| cd ~/go/src/github.com/traefik/traefik | ||||
|  | ||||
| # Get go-bindata. (Important: the ellipses are required.) | ||||
| GO111MODULE=off go get github.com/containous/go-bindata/... | ||||
| ``` | ||||
|  | ||||
| ```bash | ||||
| # Generate UI static files | ||||
| rm -rf static/ autogen/; make generate-webui | ||||
| make clean-webui generate-webui | ||||
|  | ||||
| # required to merge non-code components into the final binary, | ||||
| # such as the web dashboard/UI | ||||
| @@ -165,7 +165,7 @@ TESTFLAGS="-check.f MyTestSuite.My" make test-integration | ||||
| TESTFLAGS="-check.f MyTestSuite.*Test" make test-integration | ||||
| ``` | ||||
|  | ||||
| More: https://labix.org/gocheck | ||||
| Check [gocheck](https://labix.org/gocheck "Link to website of gocheck") for more information. | ||||
|  | ||||
| ### Method 2: `go` | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Data Collection Documentation" | ||||
| description: "To learn more about how Traefik is being used and improve it, we collect anonymous usage statistics from running instances. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Data Collection | ||||
|  | ||||
| Understanding How Traefik is Being Used | ||||
| @@ -5,8 +10,8 @@ Understanding How Traefik is Being Used | ||||
|  | ||||
| ## Configuration Example | ||||
|  | ||||
| Understanding how you use Traefik is very important to us: it helps us improve the solution in many different ways.   | ||||
| For this very reason, the sendAnonymousUsage option is mandatory: we want you to take time to consider whether or not you wish to share anonymous data with us so we can benefit from your experience and use cases. | ||||
| Understanding how you use Traefik is very important to us: it helps us improve the solution in many different ways. | ||||
| For this very reason, the sendAnonymousUsage option is mandatory: we want you to take time to consider whether or not you wish to share anonymous data with us, so we can benefit from your experience and use cases. | ||||
|  | ||||
| !!! example "Enabling Data Collection" | ||||
|  | ||||
| @@ -29,9 +34,7 @@ For this very reason, the sendAnonymousUsage option is mandatory: we want you to | ||||
|  | ||||
| ## Collected Data | ||||
|  | ||||
| This feature comes from the public proposal [here](https://github.com/traefik/traefik/issues/2369). | ||||
|  | ||||
| This feature is activated when using Traefik Pilot to better understand the community's need, and also to get information about plug-ins popularity. | ||||
| This feature comes from this [public proposal](https://github.com/traefik/traefik/issues/2369). | ||||
|  | ||||
| In order to help us learn more about how Traefik is being used and improve it, we collect anonymous usage statistics from running instances. | ||||
| Those data help us prioritize our developments and focus on what's important for our users (for example, which provider is popular, and which is not). | ||||
| @@ -42,7 +45,7 @@ Once a day (the first call begins 10 minutes after the start of Traefik), we col | ||||
|  | ||||
| - the Traefik version number | ||||
| - a hash of the configuration | ||||
| - an **anonymized version** of the static configuration (token, user name, password, URL, IP, domain, email, etc, are removed). | ||||
| - an **anonymized version** of the static configuration (token, username, password, URL, IP, domain, email, etc., are removed). | ||||
|  | ||||
| !!! info | ||||
|  | ||||
| @@ -63,7 +66,6 @@ providers: | ||||
|   docker: | ||||
|     endpoint: "tcp://10.10.10.10:2375" | ||||
|     exposedByDefault: true | ||||
|     swarmMode: true | ||||
|  | ||||
|     tls: | ||||
|       ca: dockerCA | ||||
| @@ -83,7 +85,6 @@ providers: | ||||
|   docker: | ||||
|     endpoint: "xxxx" | ||||
|     exposedByDefault: true | ||||
|     swarmMode: true | ||||
|  | ||||
|     tls: | ||||
|       ca: xxxx | ||||
| @@ -96,4 +97,4 @@ providers: | ||||
|  | ||||
| If you want to dig into more details, here is the source code of the collecting system: [collector.go](https://github.com/traefik/traefik/blob/master/pkg/collector/collector.go) | ||||
|  | ||||
| By default we anonymize all configuration fields, except fields tagged with `export=true`. | ||||
| By default, we anonymize all configuration fields, except fields tagged with `export=true`. | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Contribution Documentation" | ||||
| description: "Found something unclear in the Traefik Proxy documentation and want to give a try at explaining it better? Read the guide to building documentation." | ||||
| --- | ||||
|  | ||||
| # Documentation | ||||
|  | ||||
| Features Are Better When You Know How to Use Them | ||||
| @@ -10,10 +15,14 @@ Let's see how. | ||||
|  | ||||
| ### General | ||||
|  | ||||
| This [documentation](https://doc.traefik.io/traefik/) is built with [mkdocs](https://mkdocs.org/). | ||||
| This [documentation](https://doc.traefik.io/traefik/ "Link to the official Traefik documentation") is built with [MkDocs](https://mkdocs.org/ "Link to website of MkDocs"). | ||||
|  | ||||
| ### Method 1: `Docker` and `make` | ||||
|  | ||||
| Please make sure you have the following requirements installed: | ||||
|  | ||||
| - [Docker](https://www.docker.com/ "Link to website of Docker") | ||||
|  | ||||
| You can build the documentation and test it locally (with live reloading), using the `docs-serve` target: | ||||
|  | ||||
| ```bash | ||||
| @@ -38,9 +47,12 @@ $ make docs-build | ||||
| ... | ||||
| ``` | ||||
|  | ||||
| ### Method 2: `mkdocs` | ||||
| ### Method 2: `MkDocs` | ||||
|  | ||||
| First, make sure you have `python` and `pip` installed. | ||||
| Please make sure you have the following requirements installed: | ||||
|  | ||||
| - [Python](https://www.python.org/ "Link to website of Python") | ||||
| - [pip](https://pypi.org/project/pip/ "Link to the website of pip on PyPI") | ||||
|  | ||||
| ```bash | ||||
| $ python --version | ||||
| @@ -49,7 +61,7 @@ $ pip --version | ||||
| pip 1.5.2 | ||||
| ``` | ||||
|  | ||||
| Then, install mkdocs with `pip`. | ||||
| Then, install MkDocs with `pip`. | ||||
|  | ||||
| ```bash | ||||
| pip install --user -r requirements.txt | ||||
| @@ -82,7 +94,7 @@ Running ["HtmlCheck", "ImageCheck", "ScriptCheck", "LinkCheck"] on /app/site/bas | ||||
|  | ||||
| !!! note "Clean & Verify" | ||||
|  | ||||
|     If you've made changes to the documentation, it's safter to clean it before verifying it. | ||||
|     If you've made changes to the documentation, it's safer to clean it before verifying it. | ||||
|  | ||||
|     ```bash | ||||
|     $ make docs | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Maintainer's Guidelines Documentation" | ||||
| description: "Interested in contributing more to the community and becoming a Traefik Proxy maintainer? Read the guide to becoming a part of the core team." | ||||
| --- | ||||
|  | ||||
| # Maintainer's Guidelines | ||||
|  | ||||
|  | ||||
| @@ -6,7 +11,7 @@ Note: the document is a work in progress. | ||||
|  | ||||
| Welcome to the Traefik Community. | ||||
| This document describes how to be part of the core team | ||||
| as well as various responsibilities | ||||
| together with various responsibilities | ||||
| and guidelines for Traefik maintainers. | ||||
| We are strongly promoting a philosophy of openness and sharing, | ||||
| and firmly standing against the elitist closed approach. | ||||
| @@ -15,7 +20,7 @@ and wants to be part of that journey! | ||||
|  | ||||
| ## Onboarding Process | ||||
|  | ||||
| If you consider joining our community please drop us a line using Twitter or leave a note in the issue. | ||||
| If you consider joining our community, please drop us a line using Twitter or leave a note in the issue. | ||||
| We will schedule a quick call to meet you and learn more about your motivation. | ||||
| During the call, the team will discuss the process of becoming a maintainer. | ||||
| We will be happy to answer any questions and explain all your doubts. | ||||
| @@ -25,7 +30,7 @@ We will be happy to answer any questions and explain all your doubts. | ||||
| Note: you do not have to meet all the listed requirements, | ||||
| but must have achieved several. | ||||
|  | ||||
| - Enabled [2FA](https://docs.github.com/en/github/authenticating-to-github/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication) on your Github account | ||||
| - Enabled [2FA](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication) on your GitHub account | ||||
| - The contributor has opened and successfully run medium to large PR’s in the past 6 months. | ||||
| - The contributor has participated in multiple code reviews of other PR’s, | ||||
|   including those of other maintainers and contributors. | ||||
| @@ -48,15 +53,15 @@ but we can suggest you start with activities such as: | ||||
|       Each of the issues that are labeled as bug/possible bug/confirmed requires a reproducible use case.  | ||||
|       You can help in creating a reproducible use case if it has not been added to the issue | ||||
|       or use the sample code provided by the reporter. | ||||
|       Typically, a simple docker compose should be enough to reproduce the issue. | ||||
|       Typically, a simple Docker Compose should be enough to reproduce the issue. | ||||
| - Code contribution. | ||||
| - Documentation contribution. | ||||
|     - Technical documentation is one of the most important components of the product. | ||||
|       The ability to set up a testing environment in a few minutes, | ||||
|       using the official documentation, | ||||
|       is a game changer. | ||||
| - You will be listed on our Maintainers Github page | ||||
|   as well as on our website in the section [maintainers](maintainers.md). | ||||
| - You will be listed on our Maintainers GitHub page | ||||
|   and on our website in the section [maintainers](maintainers.md). | ||||
| - We will be promoting you on social channels (mostly on Twitter). | ||||
|  | ||||
| ## Governance | ||||
| @@ -65,8 +70,8 @@ but we can suggest you start with activities such as: | ||||
|  | ||||
| ## Communicating | ||||
|  | ||||
| - All of our maintainers are added to Slack #traefik-maintainers channel that belongs to Traefik labs workspace. | ||||
|   Having the team in one place helps us to communicate effectively.  | ||||
| - All of our maintainers are added to the Traefik Maintainers Discord server that belongs to Traefik labs. | ||||
|   Having the team in one place helps us to communicate effectively. | ||||
|   You can reach Traefik core developers directly, | ||||
|   which offers the possibility to discuss issues, pull requests, enhancements more efficiently | ||||
|   and get the feedback almost immediately. | ||||
| @@ -78,13 +83,13 @@ but we can suggest you start with activities such as: | ||||
|   activities related to the reported issues and PR’s, | ||||
|   other important project-related announcements. | ||||
|  | ||||
| - At 5:00 PM CET every day we review all the created issues that have been reported, | ||||
| - At 2:15pm CET every Monday and Thursday we review all the created issues that have been reported, | ||||
|   assign them the appropriate *[labels](maintainers.md#labels)* | ||||
|   and prioritize them based on the severity of the problem. | ||||
|   The process is called *[issue triaging](https://github.com/traefik/contributors-guide/blob/master/issue_triage.md)*. | ||||
|   Each of the maintainers is welcome to join the meeting. | ||||
|   For that purpose, we use a dedicated Discord server | ||||
|   where you are invited once you have become the official maintainer. | ||||
|   For that purpose, we use the Traefik Maintainers Discord server | ||||
|   where you are invited once you have become an official maintainer. | ||||
|  | ||||
| ## Maintainers Activity | ||||
|  | ||||
| @@ -107,9 +112,9 @@ maintainers' activity and involvement will be reviewed on a regular basis. | ||||
|  | ||||
| - Be able to put yourself in users’ shoes. | ||||
| - Be open-minded and respectful with other maintainers and other community members. | ||||
| - Keep the communication public -  | ||||
| - Keep the communication public - | ||||
|   if anyone tries to communicate with you directly, | ||||
|   ask him politely to move the conversation to a public communication channel. | ||||
|   ask politely to move the conversation to a public communication channel. | ||||
| - Stay away from defensive comments. | ||||
| - Please try to express your thoughts clearly enough | ||||
|   and note that some of us are not native English speakers. | ||||
| @@ -117,7 +122,7 @@ maintainers' activity and involvement will be reviewed on a regular basis. | ||||
|   none of us is able to predict your thoughts. | ||||
| - There are a lot of use cases of using Traefik | ||||
|   and even more issues that are difficult to reproduce. | ||||
|   If the issue can’t be replicated due to a lack of reproducible case (a simple docker compose should be enough) -  | ||||
|   If the issue can’t be replicated due to a lack of reproducible case (a simple Docker Compose should be enough) - | ||||
|   set your time limits while working on the issue | ||||
|   and express clearly that you were not able to replicate it. | ||||
|   You can come back later to that case. | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Maintainers Documentation" | ||||
| description: "Traefik Proxy is an open source software with a thriving community of contributors and maintainers. Read the list of maintainers on this page." | ||||
| --- | ||||
|  | ||||
| # Maintainers | ||||
|  | ||||
| ## The Team | ||||
| @@ -102,7 +107,6 @@ The `status/*` labels represent the desired state in the workflow. | ||||
| * `area/provider/kv`: KV related. | ||||
| * `area/provider/marathon`: Marathon related. | ||||
| * `area/provider/mesos`: Mesos related. | ||||
| * `area/provider/rancher`: Rancher related. | ||||
| * `area/provider/servicefabric`: Azure service fabric related. | ||||
| * `area/provider/zk`: Zoo Keeper related. | ||||
| * `area/rules`: Rules related. | ||||
|   | ||||
| @@ -1,44 +1,63 @@ | ||||
| --- | ||||
| title: "Traefik Submitting Issues Documentation" | ||||
| description: "Help us help you! Learn how to submit an issue, following the guidelines, so the Traefik Proxy team can help. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Submitting Issues | ||||
|  | ||||
| Help Us Help You! | ||||
| {: .subtitle } | ||||
|  | ||||
| We use the [GitHub issue tracker](https://github.com/traefik/traefik/issues) to keep track of issues in Traefik.  | ||||
| Issues are perfect for requesting a feature/enhancement or reporting a suspected bug. | ||||
| We use the [GitHub issue tracker](https://github.com/traefik/traefik/issues) to keep track of issues in Traefik. | ||||
|  | ||||
| The process of sorting and checking the issues is a daunting task, and requires a lot of work (more than an hour a day ... just for sorting). | ||||
| To save us some time and get quicker feedback, be sure to follow the guide lines below. | ||||
| To help us (and other community members) quickly and effortlessly understand what you need, | ||||
| be sure to follow the guidelines below. | ||||
|  | ||||
| !!! important "Getting Help Vs Reporting an Issue" | ||||
|  | ||||
|     The issue tracker is not a general support forum, but a place to report bugs and asks for new features. | ||||
|  | ||||
|     For end-user related support questions, try using first: | ||||
|  | ||||
|     - the Traefik community forum: [](https://community.traefik.io/) | ||||
|     For end-user related support questions, try using the [Traefik Community Forum](https://community.traefik.io/) | ||||
|    [](https://community.traefik.io/) | ||||
|  | ||||
| ## Issue Title | ||||
|  | ||||
| The title must be short and descriptive. (~60 characters) | ||||
|  | ||||
| ## Description | ||||
| Examples: | ||||
|  | ||||
| Follow the [issue template](https://github.com/traefik/traefik/blob/master/.github/ISSUE_TEMPLATE.md) as much as possible. | ||||
|  | ||||
| Explain us in which conditions you encountered the issue, what is your context. | ||||
|  | ||||
| Remain as clear and concise as possible | ||||
|  | ||||
| Take time to polish the format of your message so we'll enjoy reading it and working on it.  | ||||
| Help the readers focus on what matters, and help them understand the structure of your message (see the [Github Markdown Syntax](https://help.github.com/articles/github-flavored-markdown)). | ||||
| * Bug: Duplicate requests in access logs | ||||
| * Feature: Support TCP | ||||
|  | ||||
| ## Feature Request | ||||
|  | ||||
| Traefik is an open-source project and aims to be the best edge router possible. | ||||
| Traefik is an open source project and aims to be the best edge router possible. | ||||
|  | ||||
| Remember when asking for new features that these must be useful to the majority (and not only useful in edge case scenarios, or hack-like setups). | ||||
| Follow the [issue template](https://github.com/traefik/traefik/blob/master/.github/ISSUE_TEMPLATE/feature-request.yml) as much as possible. | ||||
|  | ||||
| Do you best to explain what you're looking for, and why it would improve Traefik for everyone.  | ||||
| Do your best to explain what you're looking for, and why it would improve Traefik for everyone. | ||||
| Be detailed and share the use-case(s) to allow us to see the value of your feature request as quickly as possible. | ||||
|  | ||||
| Features with a lot of positive interaction (claps, +1s, conversation about how this would impact them) indicate higher community interest and help us to prioritize. | ||||
|  | ||||
| If you are interested in creating a PR for your feature request, let us know in the issue, so we can work with you. | ||||
| It can take a lot of work to make sure a PR can integrate with our existing code and planning with the team ahead of time can make sure that your PR can be accepted and merged quickly. | ||||
|  | ||||
| ## Issues or Possible Bug Reports | ||||
|  | ||||
| Follow the [issue template](https://github.com/traefik/traefik/blob/master/.github/ISSUE_TEMPLATE/bug_report.yml) as much as possible. | ||||
|  | ||||
| Explain the conditions in which you encountered the issue; what is your context? | ||||
| Share any logs you may have, and make sure to share the steps it takes to reproduce your issue or bug. | ||||
|  | ||||
| Remain as clear and concise as possible. | ||||
|  | ||||
| Take time to polish the format of your message, so we'll enjoy reading it and working on it. | ||||
| Help your readers focus on what matters and help them understand the structure of your message (see the [GitHub Markdown Syntax](https://docs.github.com/en/get-started/writing-on-github)). | ||||
|  | ||||
| ## International English | ||||
|  | ||||
| Every maintainer / Traefik user is not a native English speaker, so if you feel sometimes that some messages sound rude, remember that it probably is a language barrier problem from someone willing to help you. | ||||
| Every maintainer / Traefik user is not a native English speaker, so if you sometimes feel that some messages sound rude, remember that it probably is a language barrier problem from someone willing to help you. | ||||
|   | ||||
| @@ -1,9 +1,231 @@ | ||||
| # Submitting Pull Requests | ||||
| --- | ||||
| title: "Traefik Pull Requests Documentation" | ||||
| description: "Looking to contribute to Traefik Proxy? This guide will show you the guidelines for submitting a PR in our contributors guide repository." | ||||
| --- | ||||
|  | ||||
| A Quick Guide for Efficient Contributions | ||||
| {: .subtitle } | ||||
| # Before You Submit a Pull Request | ||||
|  | ||||
| So you've decided to improve Traefik?  | ||||
| Thank You!  | ||||
| This guide is for contributors who already have a pull request to submit. | ||||
| If you are looking for information on setting up your developer environment | ||||
| and creating code to contribute to Traefik Proxy or related projects, | ||||
| see the [development guide](https://docs.traefik.io/contributing/building-testing/). | ||||
|  | ||||
| Please review the [guidelines on creating PRs](https://github.com/traefik/contributors-guide/blob/master/pr_guidelines.md) for Traefik in our [contributors guide repository](https://github.com/traefik/contributors-guide). | ||||
| Looking for a way to contribute to Traefik Proxy? | ||||
| Check out this list of [Priority Issues](https://github.com/traefik/traefik/labels/contributor%2Fwanted), | ||||
| the [Good First Issue](https://github.com/traefik/traefik/labels/contributor%2Fgood-first-issue) list, | ||||
| or the list of [confirmed bugs](https://github.com/traefik/traefik/labels/kind%2Fbug%2Fconfirmed) waiting to be remedied. | ||||
|  | ||||
| ## How We Prioritize | ||||
|  | ||||
| We wish we could review every pull request right away. | ||||
| Unfortunately, our team has to prioritize pull requests (PRs) for review | ||||
| (but we are welcoming new [maintainers](https://github.com/traefik/traefik/blob/master/docs/content/contributing/maintainers-guidelines.md) to speed this up, | ||||
| if you are interested, check it out and apply). | ||||
|  | ||||
| The PRs we are able to handle fastest are: | ||||
|  | ||||
| * Documentation updates. | ||||
| * Bug fixes. | ||||
| * Enhancements and Features with a `contributor/wanted` tag. | ||||
|  | ||||
| PRs that take more time to address include: | ||||
|  | ||||
| * Enhancements or Features without the `contributor/wanted` tag. | ||||
|  | ||||
| If you have an idea for an enhancement or feature that you would like to build, | ||||
| [create an issue](https://github.com/traefik/traefik/issues/new/choose) for it first | ||||
| and tell us you are interested in writing the PR. | ||||
| If an issue already exists, definitely comment on it to tell us you are interested in creating a PR. | ||||
|  | ||||
| This will allow us to communicate directly and let you know if it is something we would accept. | ||||
|  | ||||
| It also allows us to make sure you have all the information you need during the design phase | ||||
| so that it can be reviewed and merged quickly. | ||||
|  | ||||
| Read more about the [Triage process](https://github.com/traefik/contributors-guide/blob/master/issue_triage.md) in the docs. | ||||
|  | ||||
| ## The Pull Request Submit Process | ||||
|  | ||||
| Merging a PR requires the following steps to be completed before it is merged automatically. | ||||
|  | ||||
| * Make sure your pull request adheres to our best practices. These include: | ||||
|     * [Following project conventions](https://github.com/traefik/traefik/blob/master/docs/content/contributing/maintainers-guidelines.md); including using the PR Template. | ||||
|     * Make small pull requests. | ||||
|     * Solve only one problem at a time. | ||||
|     * Comment thoroughly. | ||||
|     * Do not open the PR from an organization repository. | ||||
|     * Keep "allows edit from maintainer" checked. | ||||
|     * Use semantic line breaks for documentation. | ||||
|     * Ensure your PR is not a draft. We do not review drafts, but do answer questions and confer with developers on them as needed. | ||||
| * Pass the validation check. | ||||
| * Pass all tests. | ||||
| * Receive 3 approving reviews maintainers. | ||||
|  | ||||
| ## Pull Request Review Cycle | ||||
|  | ||||
| Learn about our [Triage Process](https://github.com/traefik/contributors-guide/blob/master/issue_triage.md), | ||||
| in short, it looks like this: | ||||
|  | ||||
| * We triage every new PR or comment before entering it into the review process. | ||||
|     * We ensure that all prerequisites for review have been met. | ||||
|     * We check to make sure the use case meets our needs. | ||||
|     * We assign reviewers. | ||||
| * Design Review. | ||||
|     * This takes longer than other parts of the process. | ||||
|     * We review that there are no obvious conflicts with our codebase. | ||||
| * Code Review. | ||||
|     * We review the code in-depth and run tests. | ||||
|     * We may ask for changes here. | ||||
|     * During code review, we ask that you be reasonably responsive, | ||||
|       if a PR languishes in code review it is at risk of rejection, | ||||
|       or we may take ownership of the PR and the contributor will become a co-author. | ||||
| * Merge. | ||||
|     * Success! | ||||
|  | ||||
| !!! note | ||||
|  | ||||
|     Occasionally, we may freeze our codebase when working towards a specific feature or goal that could impact other development. | ||||
|     During this time, your pull request could remain unmerged while the release work is completed. | ||||
|  | ||||
| ## Run Local Verifications | ||||
|  | ||||
| You must run these local verifications before you submit your pull request to predict the pass or failure of continuous integration. | ||||
| Your PR will not be reviewed until these are green on the CI. | ||||
|  | ||||
| * `make validate` | ||||
| * `make pull-images` | ||||
| * `make test` | ||||
|  | ||||
| ## The Testing and Merge Workflow | ||||
|  | ||||
| Pull Requests are managed by the bot [Myrmica Lobicornis](https://github.com/traefik/lobicornis). | ||||
| This bot is responsible for verifying GitHub Checks (CI, Tests, etc), mergability, and minimum reviews. | ||||
| In addition, it rebases or merges with the base PR branch if needed. | ||||
| It performs several other housekeeping items | ||||
| and you can read more about those on the [README](https://github.com/traefik/lobicornis) for Lobicornis. | ||||
|  | ||||
| The maintainer giving the final LGTM must add the `status/3-needs-merge` label to trigger the merge bot. | ||||
|  | ||||
| By default, a squash-rebase merge will be carried out. | ||||
|  | ||||
| The status `status/4-merge-in-progress` is only used by the bot. | ||||
|  | ||||
| If the bot is not able to perform the merge, the label `bot/need-human-merge` is added. | ||||
| In such a situation, solve the conflicts/CI/... and then remove the label `bot/need-human-merge`. | ||||
|  | ||||
| To prevent the bot from automatically merging a PR, add the label `bot/no-merge`. | ||||
|  | ||||
| The label `bot/light-review` decreases the number of required LGTM from 3 to 1. | ||||
|  | ||||
| This label can be used when: | ||||
|  | ||||
| * Updating a dependency. | ||||
| * Merging branches back into the next version branch. | ||||
| * Submitting minor documentation changes. | ||||
| * Submitting changelog PRs. | ||||
|  | ||||
| ## Why Was My Pull Request Closed? | ||||
|  | ||||
| Traefik Proxy is made by the community for the community, | ||||
| as such the goal is to engage the community to make Traefik the best reverse proxy available. | ||||
| Part of this goal is maintaining a lean codebase and ensuring code velocity. | ||||
| unfortunately, this means that sometimes we will not be able to merge a pull request. | ||||
|  | ||||
| Because we respect the work you did, you will always be told why we are closing your pull request. | ||||
| If you do not agree with our decision, do not worry; closed pull requests are effortless to recreate, | ||||
| and little work is lost by closing a pull request that subsequently needs to be reopened. | ||||
|  | ||||
| Your pull request might be closed if: | ||||
|  | ||||
| * Your PR's design conflicts with our existing codebase in such a way that merging is not an option | ||||
|   and the work needed to make your pull request usable is too high. | ||||
|     * To prevent this, make sure you created an issue first | ||||
|       and think about including Traefik Proxy maintainers in your design phase to minimize conflicts. | ||||
| * Your PR is for an enhancement or feature that we will not use. | ||||
|     * Please remember to create an issue for any pull request **before** you create a PR | ||||
|       to ensure that your goal is something we can merge and that you have any design insight you might need from the team. | ||||
| * Your PR has been waiting for feedback from the contributor for over 90 days. | ||||
|  | ||||
| ## Why is My Pull Request Not Getting Reviewed | ||||
|  | ||||
| A few factors affect how long your pull request might wait for review. | ||||
|  | ||||
| We must prioritize which PRs we focus on. | ||||
| Our first priority is PRs we have identified as having high community engagement and broad applicability. | ||||
| We put our top priorities on our roadmap, and you can identify them by the `contributor/wanted` tag. | ||||
| These PRs will enter our review process the fastest. | ||||
|  | ||||
| Our second priority is bug fixes. | ||||
| Especially for bugs that have already been tagged with `bug/confirmed`. | ||||
| These reviews enter the process quickly. | ||||
|  | ||||
| If your PR does not meet the criteria above, | ||||
| it will take longer for us to review, as any PRs that do meet the criteria above will be prioritized. | ||||
|  | ||||
| Additionally, during the last few weeks of a milestone, we stop reviewing PRs to reduce churn and stabilize. | ||||
| We will resume after the release. | ||||
|  | ||||
| The second major reason that we deprioritize your PR is that you are not following best practices. | ||||
|  | ||||
| The most common failures to follow best practices are: | ||||
|  | ||||
| * You did not create an issue for the PR you wish to make. | ||||
|   If you do not create an issue before submitting your PR, | ||||
|   we will not be able to answer any design questions and let you know how likely your PR is to be merged. | ||||
| * You created pull requests that are too large to review. | ||||
|     * Break your pull requests up. | ||||
|       If you can extract whole ideas from your pull request and send those as pull requests of their own, | ||||
|       you should do that instead. | ||||
|       It is better to have many pull requests addressing one thing than one pull request addressing many things. | ||||
|     * Traefik Proxy is a fast-moving codebase — lock in your changes ASAP with your small pull request, | ||||
|       and make merges be someone else's problem. | ||||
|       We want every pull request to be useful on its own, | ||||
|       so use your best judgment on what should be a pull request vs. a commit. | ||||
| * You did not comment well. | ||||
|     * Comment everything. | ||||
|  | ||||
| Please remember that we are working internationally, cross-culturally, and with different use-cases. | ||||
| Your reviewer will not intuitively understand the problem the same way you do or solve it the same way you would. | ||||
| This is why every change you make must be explained, and your strategy for coding must also be explained. | ||||
|  | ||||
| * Your tests were inadequate or absent. | ||||
|     * If you do not know how to test your PR, please ask! | ||||
|       We will be happy to help you or suggest appropriate test cases. | ||||
|  | ||||
| If you have already followed the best practices and your PR still has not received a response, | ||||
| here are some things you can do to move the process along: | ||||
|  | ||||
| * If you have fixed all the issues from a review, | ||||
|   remember to re-request a review (using the designated button) to let your reviewer know that you are ready. | ||||
|   You can choose to comment with the changes you made. | ||||
| * Ping `@tfny` if you have not been assigned to a reviewer. | ||||
|  | ||||
| For more information on best practices, try these links: | ||||
|  | ||||
| * [How to Write a Git Commit Message - Chris Beams](https://chris.beams.io/posts/git-commit/) | ||||
| * [Distributed Git - Contributing to a Project (Commit Guidelines)](https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project) | ||||
| * [What’s with the 50/72 rule? - Preslav Rachev](https://preslav.me/2015/02/21/what-s-with-the-50-72-rule/) | ||||
| * [A Note About Git Commit Messages - Tim Pope](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) | ||||
|  | ||||
| ## It's OK to Push Back | ||||
|  | ||||
| Sometimes reviewers make mistakes. | ||||
| It is OK to push back on changes your reviewer requested. | ||||
| If you have a good reason for doing something a certain way, you are absolutely allowed to debate the merits of a requested change. | ||||
| Both the reviewer and reviewee should strive to discuss these issues in a polite and respectful manner. | ||||
|  | ||||
| You might be overruled, but you might also prevail. | ||||
| We are pretty reasonable people. | ||||
|  | ||||
| Another phenomenon of open-source projects (where anyone can comment on any issue) is the dog-pile - | ||||
| your pull request gets so many comments from so many people it becomes hard to follow. | ||||
| In this situation, you can ask the primary reviewer (assignee) whether they want you to fork a new pull request | ||||
| to clear out all the comments. | ||||
| You do not have to fix every issue raised by every person who feels like commenting, | ||||
| but you should answer reasonable comments with an explanation. | ||||
|  | ||||
| ## Common Sense and Courtesy | ||||
|  | ||||
| No document can take the place of common sense and good taste. | ||||
| Use your best judgment, while you put a bit of thought into how your work can be made easier to review. | ||||
| If you do these things, your pull requests will get merged with less friction. | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Security Documentation" | ||||
| description: "Security is a key part of Traefik Proxy. Read the technical documentation to learn about security advisories, CVE, and how to report a vulnerability." | ||||
| --- | ||||
|  | ||||
| # Security | ||||
|  | ||||
| ## Security Advisories | ||||
| @@ -7,10 +12,12 @@ You can subscribe sending a mail to security+subscribe@traefik.io or on [the onl | ||||
|  | ||||
| ## CVE | ||||
|  | ||||
| Reported vulnerabilities can be found on  | ||||
| Reported vulnerabilities can be found on | ||||
| [cve.mitre.org](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=traefik). | ||||
|  | ||||
| ## Report a Vulnerability | ||||
|  | ||||
| We want to keep Traefik safe for everyone. | ||||
| If you've discovered a security vulnerability in Traefik, we appreciate your help in disclosing it to us in a responsible manner, using [this form](https://security.traefik.io). | ||||
| If you've discovered a security vulnerability in Traefik, | ||||
| we appreciate your help in disclosing it to us in a responsible manner, | ||||
| by creating a [security advisory](https://github.com/traefik/traefik/security/advisories). | ||||
|   | ||||
| @@ -1,13 +1,18 @@ | ||||
| --- | ||||
| title: "Traefik Contribution Documentation" | ||||
| description: "Thank you to all those who have contributed! Traefik Proxy is an open-source project that thrives with the support of our passionate community." | ||||
| --- | ||||
|  | ||||
| # Thank You! | ||||
|  | ||||
| _You_ Made It | ||||
| {: .subtitle} | ||||
|  | ||||
| Traefik truly is an [open-source project](https://github.com/traefik/traefik/), | ||||
| Traefik Proxy truly is an [open-source project](https://github.com/traefik/traefik/), | ||||
| and wouldn't have become what it is today without the help of our [many contributors](https://github.com/traefik/traefik/graphs/contributors) (at the time of writing this), | ||||
| not accounting for people having helped with issues, tests, comments, articles, ... or just enjoying it and letting others know. | ||||
| not accounting for people having helped with issues, tests, comments, articles, ... or just enjoy using Traefik Proxy and share with others. | ||||
|  | ||||
| So once again, thank you for your invaluable help on making Traefik such a good product. | ||||
| So once again, thank you for your invaluable help in making Traefik such a good product! | ||||
|  | ||||
| !!! question "Where to Go Next?" | ||||
|     If you want to: | ||||
|   | ||||
							
								
								
									
										23
									
								
								docs/content/deprecation/features.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								docs/content/deprecation/features.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| # Feature Deprecation Notices | ||||
|  | ||||
| This page is maintained and updated periodically to reflect our roadmap and any decisions around feature deprecation. | ||||
|  | ||||
| | Feature                                                                                                              | Deprecated | End of Support | Removal | | ||||
| |----------------------------------------------------------------------------------------------------------------------|------------|----------------|---------| | ||||
| | [Kubernetes CRDs API Version `traefik.io/v1alpha1`](#kubernetes-crds-api-version-traefikiov1alpha1)                  | N/A        | N/A            | 3.0     | | ||||
| | [Kubernetes Ingress API Version `networking.k8s.io/v1beta1`](#kubernetes-ingress-api-version-networkingk8siov1beta1) | N/A        | N/A            | 3.0     | | ||||
| | [CRD API Version `apiextensions.k8s.io/v1beta1`](#kubernetes-ingress-api-version-networkingk8siov1beta1)             | N/A        | N/A            | 3.0     | | ||||
|  | ||||
| ## Impact | ||||
|  | ||||
| ### Kubernetes CRDs API Version `traefik.io/v1alpha1` | ||||
|  | ||||
| The newly introduced Kubernetes CRD API Version `traefik.io/v1alpha1` will subsequently be removed in Traefik v3. The following version will be `traefik.io/v1`. | ||||
|  | ||||
| ### Kubernetes Ingress API Version `networking.k8s.io/v1beta1` | ||||
|  | ||||
| The Kubernetes Ingress API Version `networking.k8s.io/v1beta1` is removed in v3. Please use the API Group `networking.k8s.io/v1` instead. | ||||
|  | ||||
| ### Traefik CRD API Version `apiextensions.k8s.io/v1beta1` | ||||
|  | ||||
| The Traefik CRD API Version `apiextensions.k8s.io/v1beta1` is removed in v3. Please use the API Group `apiextensions.k8s.io/v1` instead. | ||||
							
								
								
									
										41
									
								
								docs/content/deprecation/releases.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								docs/content/deprecation/releases.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| # Releases | ||||
|  | ||||
| ## Versions | ||||
|  | ||||
| Below is a non-exhaustive list of versions and their maintenance status: | ||||
|  | ||||
| | Version | Release Date | Active Support     | Security Support |  | ||||
| |---------|--------------|--------------------|------------------| | ||||
| | 2.10    | Apr 24, 2023 | Yes                | Yes              | | ||||
| | 2.9     | Oct 03, 2022 | Ended Apr 24, 2023 | No               | | ||||
| | 2.8     | Jun 29, 2022 | Ended Oct 03, 2022 | No               | | ||||
| | 2.7     | May 24, 2022 | Ended Jun 29, 2022 | No               | | ||||
| | 2.6     | Jan 24, 2022 | Ended May 24, 2022 | No               | | ||||
| | 2.5     | Aug 17, 2021 | Ended Jan 24, 2022 | No               | | ||||
| | 2.4     | Jan 19, 2021 | Ended Aug 17, 2021 | No               | | ||||
| | 2.3     | Sep 23, 2020 | Ended Jan 19, 2021 | No               | | ||||
| | 2.2     | Mar 25, 2020 | Ended Sep 23, 2020 | No               | | ||||
| | 2.1     | Dec 11, 2019 | Ended Mar 25, 2020 | No               | | ||||
| | 2.0     | Sep 16, 2019 | Ended Dec 11, 2019 | No               | | ||||
| | 1.7     | Sep 24, 2018 | Ended Dec 31, 2021 | Contact Support  | | ||||
|  | ||||
| ??? example "Active Support / Security Support" | ||||
|  | ||||
|     **Active support**: receives any bug fixes. | ||||
|     **Security support**: receives only critical bug and security fixes. | ||||
|  | ||||
| This page is maintained and updated periodically to reflect our roadmap and any decisions affecting the end of support for Traefik Proxy. | ||||
|  | ||||
| Please refer to our migration guides for specific instructions on upgrading between versions, an example is the [v1 to v2 migration guide](../migration/v1-to-v2.md). | ||||
|  | ||||
| !!! important "All target dates for end of support or feature removal announcements may be subject to change." | ||||
|  | ||||
| ## Versioning Scheme | ||||
|  | ||||
| The Traefik Proxy project follows the [semantic versioning](https://semver.org/) scheme and maintains a separate branch for each minor version. The main branch always represents the next upcoming minor or major version. | ||||
|  | ||||
| And these are our guiding rules for version support: | ||||
|  | ||||
| - **Only the latest `minor`** will be on active support at any given time | ||||
| - **The last `minor` after releasing a new `major`** will be supported for 1 year following the `major` release | ||||
| - **Previous rules are subject to change** and in such cases an announcement will be made publicly, [here](https://traefik.io/blog/traefik-2-1-in-the-wild/) is an example extending v1.x branch support. | ||||
| @@ -1,14 +1,34 @@ | ||||
| --- | ||||
| title: Concepts | ||||
| description: Traefik - base concepts and main features | ||||
| --- | ||||
|  | ||||
| # Concepts | ||||
|  | ||||
| Everything You Need to Know | ||||
| {: .subtitle } | ||||
| This page explains the base concepts of Traefik. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Introduction | ||||
|  | ||||
| Traefik is based on the concept of EntryPoints, Routers, Middlewares and Services. | ||||
|  | ||||
| The main features include dynamic configuration, automatic service discovery, and support for multiple backends and protocols. | ||||
|  | ||||
| 1. [EntryPoints](../routing/entrypoints.md "Link to docs about EntryPoints"): EntryPoints are the network entry points into Traefik. They define the port which will receive the packets, and whether to listen for TCP or UDP. | ||||
|  | ||||
| 2. [Routers](../routing/routers/index.md "Link to docs about routers"): A router is in charge of connecting incoming requests to the services that can handle them. | ||||
|  | ||||
| 3. [Middlewares](../middlewares/overview.md "Link to docs about middlewares"): Attached to the routers, middlewares can modify the requests or responses before they are sent to your service | ||||
|  | ||||
| 4. [Services](../routing/services/index.md "Link to docs about services"): Services are responsible for configuring how to reach the actual services that will eventually handle the incoming requests. | ||||
|  | ||||
| ## Edge Router | ||||
|  | ||||
| Traefik is an _Edge Router_, it means that it's the door to your platform, and that it intercepts and routes every incoming request: | ||||
| it knows all the logic and every rule that determine which services handle which requests (based on the [path](../routing/routers/index.md#rule), the [host](../routing/routers/index.md#rule), [headers](../routing/routers/index.md#rule), [and so on](../routing/routers/index.md#rule) ...). | ||||
| Traefik is an *Edge Router*, it means that it's the door to your platform, and that it intercepts and routes every incoming request: | ||||
| it knows all the logic and every [rule](../routing/routers/index.md#rule "Link to docs about routing rules") that determine which services handle which requests (based on the *path*, the *host*, *headers*, etc.). | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Auto Service Discovery | ||||
|  | ||||
| @@ -16,21 +36,25 @@ Where traditionally edge routers (or reverse proxies) need a configuration file | ||||
|  | ||||
| Deploying your services, you attach information that tells Traefik the characteristics of the requests the services can handle. | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| It means that when a service is deployed, Traefik detects it immediately and updates the routing rules in real time. | ||||
| The opposite is true: when you remove a service from your infrastructure, the route will disappear accordingly. | ||||
| Similarly, when a service is removed from the infrastructure, the corresponding route is deleted accordingly. | ||||
|  | ||||
| You no longer need to create and synchronize configuration files cluttered with IP addresses or other rules. | ||||
|  | ||||
| !!! info "Many different rules" | ||||
|  | ||||
|     In the example above, we used the request [path](../routing/routers/index.md#rule) to determine which service was in charge, but of course you can use many other different [rules](../routing/routers/index.md#rule). | ||||
|     In the example above, we used the request [path rule](../routing/routers/index.md#rule "Link to docs about routing rules") to determine which service was in charge. | ||||
|     Certainly, you can use many other different [rules](../routing/routers/index.md#rule "Link to docs about routing rules"). | ||||
|  | ||||
| !!! info "Updating the requests" | ||||
|  | ||||
|     In the [middleware](../middlewares/overview.md) section, you can learn about how to update the requests before forwarding them to the services. | ||||
|     In the [middleware](../middlewares/overview.md "Link to middleware documentation") section, you can learn about how to update the requests before forwarding them to the services. | ||||
|  | ||||
| !!! question "How does Traefik discover the services?" | ||||
|  | ||||
|     Traefik is able to use your cluster API to discover the services and read the attached information. In Traefik, these connectors are called [providers](../providers/overview.md) because they _provide_ the configuration to Traefik. To learn more about them, read the [provider overview](../providers/overview.md) section. | ||||
|     Traefik is able to use your cluster API to discover the services and read the attached information. | ||||
|     In Traefik, these connectors are called [providers](../providers/overview.md "Link to overview about Traefik providers") because they *provide* the configuration to Traefik. | ||||
|  | ||||
| {!traefik-for-business-applications.md!} | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Configuration Documentation" | ||||
| description: "Get started with Traefik Proxy. This page will introduce you to the dynamic routing and startup configurations. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Configuration Introduction | ||||
|  | ||||
| How the Magic Happens | ||||
| @@ -51,7 +56,7 @@ Once positioned, this option sets (and resets) all the default values of the sub | ||||
|  | ||||
| ### Configuration File | ||||
|  | ||||
| At startup, Traefik searches for a file named `traefik.yml` (or `traefik.yaml` or `traefik.toml`) in: | ||||
| At startup, Traefik searches for static configuration in a file named `traefik.yml` (or `traefik.yaml` or `traefik.toml`) in: | ||||
|  | ||||
| - `/etc/traefik/` | ||||
| - `$XDG_CONFIG_HOME/` | ||||
| @@ -74,7 +79,7 @@ traefik --help | ||||
| # or | ||||
|  | ||||
| docker run traefik[:version] --help | ||||
| # ex: docker run traefik:2.1 --help | ||||
| # ex: docker run traefik:v3.0 --help | ||||
| ``` | ||||
|  | ||||
| All available arguments can also be found [here](../reference/static-configuration/cli.md). | ||||
| @@ -88,3 +93,5 @@ All available environment variables can be found [here](../reference/static-conf | ||||
| All the configuration options are documented in their related section. | ||||
|  | ||||
| You can browse the available features in the menu, the [providers](../providers/overview.md), or the [routing section](../routing/overview.md) to see them in action. | ||||
|  | ||||
| {!traefik-for-business-applications.md!} | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Getting Started FAQ" | ||||
| description: "Check out our FAQ page for answers to commonly asked questions on getting started with Traefik Proxy. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # FAQ | ||||
|  | ||||
| ## Why is Traefik Answering `XXX` HTTP Response Status Code? | ||||
| @@ -152,3 +157,97 @@ By default, the following headers are automatically added when proxying requests | ||||
|  | ||||
| For more details, | ||||
| please check out the [forwarded header](../routing/entrypoints.md#forwarded-headers) documentation. | ||||
|  | ||||
| ## How Traefik is Storing and Serving TLS Certificates? | ||||
|  | ||||
| ### Storing TLS Certificates | ||||
|  | ||||
| [TLS](../https/tls.md "Link to Traefik TLS docs") certificates are either provided directly by the [dynamic configuration](./configuration-overview.md#the-dynamic-configuration "Link to dynamic configuration overview") from [providers](../https/tls.md#user-defined "Link to the TLS configuration"), | ||||
| or by [ACME resolvers](../https/acme.md#providers "Link to ACME resolvers"), which act themselves as providers internally. | ||||
|  | ||||
| For each TLS certificate, Traefik produces an identifier used as a key to store it. | ||||
| This identifier is constructed as the alphabetically ordered concatenation of the SANs `DNSNames` and `IPAddresses` of the TLScertificate. | ||||
|  | ||||
| #### Examples: | ||||
|  | ||||
| | X509v3 Subject Alternative Name         | TLS Certificate Identifier  | | ||||
| |-----------------------------------------|-----------------------------| | ||||
| | `DNS:example.com, IP Address:127.0.0.1` | `127.0.0.1,example.com`     | | ||||
| | `DNS:example.com, DNS:*.example.com`    | `*.example.com,example.com` | | ||||
|  | ||||
| The identifier is used to store TLS certificates in order to be later used to handle TLS connections. | ||||
| This operation happens each time there are configuration changes. | ||||
|  | ||||
| If multiple TLS certificates are provided with the same SANs definition (same identifier), only the one processed first is kept. | ||||
| Because the dynamic configuration is aggregated from all providers, | ||||
| when processing it to gather TLS certificates, | ||||
| there is no guarantee of the order in which they would be processed. | ||||
| This means that along with configurations applied, it is possible that the TLS certificate retained for a given identifier differs. | ||||
|  | ||||
| ### Serving TLS Certificates | ||||
|  | ||||
| For each incoming connection, Traefik is serving the "best" matching TLS certificate for the provided server name. | ||||
|  | ||||
| The TLS certificate selection process narrows down the list of TLS certificates matching the server name, | ||||
| and then selects the last TLS certificate in this list after having ordered it by the identifier alphabetically. | ||||
|  | ||||
| #### Examples: | ||||
|  | ||||
| | Selected TLS Certificates Identifiers               | Sorted TLS Certificates Identifiers                 | Served Certificate Identifier | | ||||
| |-----------------------------------------------------|-----------------------------------------------------|-------------------------------| | ||||
| | `127.0.0.1,example.com`,`*.example.com,example.com` | `*.example.com,example.com`,`127.0.0.1,example.com` | `127.0.0.1,example.com`       | | ||||
| | `*.example.com,example.com`,`example.com`           | `*.example.com,example.com`,`example.com`           | `example.com`                 | | ||||
|  | ||||
| ### Caching TLS Certificates | ||||
|  | ||||
| While Traefik is serving the best matching TLS certificate for each incoming connection, | ||||
| the selection process cost for each incoming connection is avoided thanks to a cache mechanism. | ||||
|  | ||||
| Once a TLS certificate has been selected as the "best" TLS certificate for a server name, | ||||
| it is cached for an hour, avoiding the selection process for further connections. | ||||
|  | ||||
| Nonetheless, when a new configuration is applied, the cache is reset. | ||||
|  | ||||
| ## What does the "field not found" error mean? | ||||
|  | ||||
| ```shell | ||||
| error: field not found, node: -badField- | ||||
| ``` | ||||
|  | ||||
| The "field not found" error occurs, when an unknown property is encountered in the dynamic or static configuration. | ||||
|  | ||||
| One easy way to check whether a configuration file is well-formed, is to validate it with: | ||||
|  | ||||
| - [JSON Schema of the static configuration](https://json.schemastore.org/traefik-v2.json) | ||||
| - [JSON Schema of the dynamic configuration](https://json.schemastore.org/traefik-v2-file-provider.json) | ||||
|  | ||||
| ## Why are some resources (routers, middlewares, services...) not created/applied? | ||||
|  | ||||
| As a common tip, if a resource is dropped/not created by Traefik after the dynamic configuration was evaluated, | ||||
| one should look for an error in the logs. | ||||
|  | ||||
| If found, the error obviously confirms that something went wrong while creating the resource, | ||||
| and the message should help in figuring out the mistake(s) in the configuration, and how to fix it. | ||||
|  | ||||
| When using the file provider, | ||||
| one easy way to check if the dynamic configuration is well-formed is to validate it with the [JSON Schema of the dynamic configuration](https://json.schemastore.org/traefik-v2-file-provider.json). | ||||
|  | ||||
| ## Why does Let's Encrypt wildcard certificate renewal/generation with DNS challenge fail? | ||||
|  | ||||
| If you're trying to renew wildcard certificates, with DNS challenge, | ||||
| and you're getting errors such as: | ||||
|  | ||||
| ```txt | ||||
| msg="Error renewing certificate from LE: {example.com [*.example.com]}" | ||||
| providerName=letsencrypt.acme error="error: one or more domains had a problem: | ||||
| [example.com] acme: error presenting token: gandiv5: unexpected authZone example.com. for fqdn example.com." | ||||
| ``` | ||||
|  | ||||
| then it could be due to `CNAME` support. | ||||
|  | ||||
| In which case, you should make sure your infrastructure is properly set up for a | ||||
| `DNS` challenge that does not rely on `CNAME`, and you should try disabling `CNAME` support with: | ||||
|  | ||||
| ```bash | ||||
| LEGO_DISABLE_CNAME_SUPPORT=true | ||||
| ``` | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Installation Documentation" | ||||
| description: "There are several flavors to choose from when installing Traefik Proxy. Get started with Traefik Proxy, and read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Install Traefik | ||||
|  | ||||
| You can install Traefik with the following flavors: | ||||
| @@ -11,12 +16,12 @@ You can install Traefik with the following flavors: | ||||
|  | ||||
| Choose one of the [official Docker images](https://hub.docker.com/_/traefik) and run it with one sample configuration file: | ||||
|  | ||||
| * [YAML](https://raw.githubusercontent.com/traefik/traefik/v2.5/traefik.sample.yml) | ||||
| * [TOML](https://raw.githubusercontent.com/traefik/traefik/v2.5/traefik.sample.toml) | ||||
| * [YAML](https://raw.githubusercontent.com/traefik/traefik/v3.0/traefik.sample.yml) | ||||
| * [TOML](https://raw.githubusercontent.com/traefik/traefik/v3.0/traefik.sample.toml) | ||||
|  | ||||
| ```bash | ||||
| docker run -d -p 8080:8080 -p 80:80 \ | ||||
|     -v $PWD/traefik.yml:/etc/traefik/traefik.yml traefik:v2.5 | ||||
|     -v $PWD/traefik.yml:/etc/traefik/traefik.yml traefik:v3.0 | ||||
| ``` | ||||
|  | ||||
| For more details, go to the [Docker provider documentation](../providers/docker.md) | ||||
| @@ -24,7 +29,7 @@ For more details, go to the [Docker provider documentation](../providers/docker. | ||||
| !!! tip | ||||
|  | ||||
|     * Prefer a fixed version than the latest that could be an unexpected version. | ||||
|     ex: `traefik:v2.5` | ||||
|     ex: `traefik:v3.0` | ||||
|     * Docker images are based from the [Alpine Linux Official image](https://hub.docker.com/_/alpine). | ||||
|     * Any orchestrator using docker images can fetch the official Traefik docker image. | ||||
|  | ||||
| @@ -39,13 +44,13 @@ Traefik can be installed in Kubernetes using the Helm chart from <https://github | ||||
|  | ||||
| Ensure that the following requirements are met: | ||||
|  | ||||
| * Kubernetes 1.14+ | ||||
| * Helm version 3.x is [installed](https://helm.sh/docs/intro/install/) | ||||
| * Kubernetes 1.16+ | ||||
| * Helm version 3.9+ is [installed](https://helm.sh/docs/intro/install/) | ||||
|  | ||||
| Add Traefik's chart repository to Helm: | ||||
| Add Traefik Labs chart repository to Helm: | ||||
|  | ||||
| ```bash | ||||
| helm repo add traefik https://helm.traefik.io/traefik | ||||
| helm repo add traefik https://traefik.github.io/charts | ||||
| ``` | ||||
|  | ||||
| You can update the chart repository by running: | ||||
| @@ -63,6 +68,9 @@ helm install traefik traefik/traefik | ||||
| !!! tip "Helm Features" | ||||
|  | ||||
|     All [Helm features](https://helm.sh/docs/intro/using_helm/) are supported. | ||||
|  | ||||
|     Examples are provided [here](https://github.com/traefik/traefik-helm-chart/blob/master/EXAMPLES.md).  | ||||
|  | ||||
|     For instance, installing the chart in a dedicated namespace: | ||||
|  | ||||
|     ```bash tab="Install in a Dedicated Namespace" | ||||
| @@ -78,8 +86,7 @@ helm install traefik traefik/traefik | ||||
|     as with [any helm chart](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). | ||||
|     {: #helm-custom-values } | ||||
|  | ||||
|     The values are not (yet) documented, but are self-explanatory: | ||||
|     you can look at the [default `values.yaml`](https://github.com/traefik/traefik-helm-chart/blob/master/traefik/values.yaml) file to explore possibilities. | ||||
|     All parameters are documented in the default [`values.yaml`](https://github.com/traefik/traefik-helm-chart/blob/master/traefik/values.yaml). | ||||
|  | ||||
|     You can also set Traefik command line flags using `additionalArguments`. | ||||
|     Example of installation with logging set to `DEBUG`: | ||||
| @@ -114,7 +121,7 @@ by defining and applying an IngressRoute CRD (`kubectl apply -f dashboard.yaml`) | ||||
|  | ||||
| ```yaml | ||||
| # dashboard.yaml | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: IngressRoute | ||||
| metadata: | ||||
|   name: dashboard | ||||
| @@ -173,3 +180,5 @@ And run it: | ||||
| ## Compile your Binary from the Sources | ||||
|  | ||||
| All the details are available in the [Contributing Guide](../contributing/building-testing.md) | ||||
|  | ||||
| {!traefik-for-business-applications.md!} | ||||
|   | ||||
							
								
								
									
										320
									
								
								docs/content/getting-started/quick-start-with-kubernetes.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										320
									
								
								docs/content/getting-started/quick-start-with-kubernetes.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,320 @@ | ||||
| --- | ||||
| title: "Traefik Getting Started With Kubernetes" | ||||
| description: "Looking to get started with Traefik Proxy? Read the technical documentation to learn a simple use case that leverages Kubernetes." | ||||
| --- | ||||
|  | ||||
| # Quick Start | ||||
|  | ||||
| A Simple Use Case of Traefik Proxy and Kubernetes | ||||
| {: .subtitle } | ||||
|  | ||||
| This guide is an introduction to using Traefik Proxy in a Kubernetes environment. | ||||
| The objective is to learn how to run an application behind a Traefik reverse proxy in Kubernetes. | ||||
| It presents and explains the basic blocks required to start with Traefik such as Ingress Controller, Ingresses, Deployments, static, and dynamic configuration. | ||||
|  | ||||
| ## Permissions and Accesses | ||||
|  | ||||
| Traefik uses the Kubernetes API to discover running services. | ||||
|  | ||||
| In order to use the Kubernetes API, Traefik needs some permissions. | ||||
| This [permission mechanism](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) is based on roles defined by the cluster administrator. | ||||
| The role is then bound to an account used by an application, in this case, Traefik Proxy. | ||||
|  | ||||
| The first step is to create the role. | ||||
| The [`ClusterRole`](https://kubernetes.io/docs/reference/kubernetes-api/authorization-resources/cluster-role-v1/#ClusterRole) resource enumerates the resources and actions available for the role. | ||||
| In a file called `00-role.yml`, put the following `ClusterRole`: | ||||
|  | ||||
| ```yaml tab="00-role.yml" | ||||
| kind: ClusterRole | ||||
| apiVersion: rbac.authorization.k8s.io/v1 | ||||
| metadata: | ||||
|   name: traefik-role | ||||
|  | ||||
| rules: | ||||
|   - apiGroups: | ||||
|       - "" | ||||
|     resources: | ||||
|       - services | ||||
|       - endpoints | ||||
|       - secrets | ||||
|     verbs: | ||||
|       - get | ||||
|       - list | ||||
|       - watch | ||||
|   - apiGroups: | ||||
|       - extensions | ||||
|       - networking.k8s.io | ||||
|     resources: | ||||
|       - ingresses | ||||
|       - ingressclasses | ||||
|     verbs: | ||||
|       - get | ||||
|       - list | ||||
|       - watch | ||||
|   - apiGroups: | ||||
|       - extensions | ||||
|       - networking.k8s.io | ||||
|     resources: | ||||
|       - ingresses/status | ||||
|     verbs: | ||||
|       - update | ||||
| ``` | ||||
|  | ||||
| !!! info "You can find the reference for this file [there](../../reference/dynamic-configuration/kubernetes-crd/#rbac)." | ||||
|  | ||||
| The next step is to create a dedicated service account for Traefik. | ||||
| In a file called `00-account.yml`, put the following [`ServiceAccount`](https://kubernetes.io/docs/reference/kubernetes-api/authentication-resources/service-account-v1/#ServiceAccount) resource: | ||||
|  | ||||
| ```yaml tab="00-account.yml" | ||||
| apiVersion: v1 | ||||
| kind: ServiceAccount | ||||
| metadata: | ||||
|   name: traefik-account | ||||
| ``` | ||||
|  | ||||
| And then, bind the role on the account to apply the permissions and rules on the latter. In a file called `01-role-binding.yml`, put the | ||||
| following [`ClusterRoleBinding`](https://kubernetes.io/docs/reference/kubernetes-api/authorization-resources/cluster-role-binding-v1/#ClusterRoleBinding) resource: | ||||
|  | ||||
| ```yaml tab="01-role-binding.yml" | ||||
| kind: ClusterRoleBinding | ||||
| apiVersion: rbac.authorization.k8s.io/v1 | ||||
| metadata: | ||||
|   name: traefik-role-binding | ||||
|  | ||||
| roleRef: | ||||
|   apiGroup: rbac.authorization.k8s.io | ||||
|   kind: ClusterRole | ||||
|   name: traefik-role | ||||
| subjects: | ||||
|   - kind: ServiceAccount | ||||
|     name: traefik-account | ||||
|     namespace: default # Using "default" because we did not specify a namespace when creating the ClusterAccount. | ||||
| ``` | ||||
|  | ||||
| !!! info "`roleRef` is the Kubernetes reference to the role created in `00-role.yml`." | ||||
|  | ||||
| !!! info "`subjects` is the list of accounts reference." | ||||
|  | ||||
|     In this guide, it only contains the account created in `00-account.yml` | ||||
|  | ||||
| ## Deployment and Exposition | ||||
|  | ||||
| !!! info "This section can be managed with the help of the [Traefik Helm chart](../install-traefik/#use-the-helm-chart)." | ||||
|  | ||||
| The [ingress controller](https://traefik.io/glossary/kubernetes-ingress-and-ingress-controller-101/#what-is-a-kubernetes-ingress-controller) | ||||
| is a software that runs in the same way as any other application on a cluster. | ||||
| To start Traefik on the Kubernetes cluster, | ||||
| a [`Deployment`](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/deployment-v1/) resource must exist to describe how to configure | ||||
| and scale containers horizontally to support larger workloads. | ||||
|  | ||||
| Start by creating a file called `02-traefik.yml` and paste the following `Deployment` resource: | ||||
|  | ||||
| ```yaml tab="02-traefik.yml" | ||||
| kind: Deployment | ||||
| apiVersion: apps/v1 | ||||
| metadata: | ||||
|   name: traefik-deployment | ||||
|   labels: | ||||
|     app: traefik | ||||
|  | ||||
| spec: | ||||
|   replicas: 1 | ||||
|   selector: | ||||
|     matchLabels: | ||||
|       app: traefik | ||||
|   template: | ||||
|     metadata: | ||||
|       labels: | ||||
|         app: traefik | ||||
|     spec: | ||||
|       serviceAccountName: traefik-account | ||||
|       containers: | ||||
|         - name: traefik | ||||
|           image: traefik:v3.0 | ||||
|           args: | ||||
|             - --api.insecure | ||||
|             - --providers.kubernetesingress | ||||
|           ports: | ||||
|             - name: web | ||||
|               containerPort: 80 | ||||
|             - name: dashboard | ||||
|               containerPort: 8080 | ||||
| ``` | ||||
|  | ||||
| The deployment contains an important attribute for customizing Traefik: `args`. | ||||
| These arguments are the static configuration for Traefik. | ||||
| From here, it is possible to enable the dashboard, | ||||
| configure entry points, | ||||
| select dynamic configuration providers, | ||||
| and [more](../reference/static-configuration/cli.md)... | ||||
|  | ||||
| In this deployment, | ||||
| the static configuration enables the Traefik dashboard, | ||||
| and uses Kubernetes native Ingress resources as router definitions to route incoming requests. | ||||
|  | ||||
| !!! info "When there is no entry point in the static configuration" | ||||
|  | ||||
|     Traefik creates a default one called `web` using the port `80` routing HTTP requests. | ||||
|  | ||||
| !!! info "When enabling the [`api.insecure`](../../operations/api/#insecure) mode, Traefik exposes the dashboard on the port `8080`." | ||||
|  | ||||
| A deployment manages scaling and then can create lots of containers, called [Pods](https://kubernetes.io/docs/concepts/workloads/pods/). | ||||
| Each Pod is configured following the `spec` field in the deployment. | ||||
| Given that, a Deployment can run multiple Traefik Proxy Pods, | ||||
| a piece is required to forward the traffic to any of the instance: | ||||
| namely a [`Service`](https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#Service). | ||||
| Create a file called `02-traefik-services.yml` and insert the two `Service` resources: | ||||
|  | ||||
| ```yaml tab="02-traefik-services.yml" | ||||
| apiVersion: v1 | ||||
| kind: Service | ||||
| metadata: | ||||
|   name: traefik-dashboard-service | ||||
|  | ||||
| spec: | ||||
|   type: LoadBalancer | ||||
|   ports: | ||||
|     - port: 8080 | ||||
|       targetPort: dashboard | ||||
|   selector: | ||||
|     app: traefik | ||||
| --- | ||||
| apiVersion: v1 | ||||
| kind: Service | ||||
| metadata: | ||||
|   name: traefik-web-service | ||||
|  | ||||
| spec: | ||||
|   type: LoadBalancer | ||||
|   ports: | ||||
|     - targetPort: web | ||||
|       port: 80 | ||||
|   selector: | ||||
|     app: traefik | ||||
| ``` | ||||
|  | ||||
| !!! warning "It is possible to expose a service in different ways." | ||||
|  | ||||
|     Depending on your working environment and use case, the `spec.type` might change. | ||||
|     It is strongly recommended to understand the available [service types](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) before proceeding to the next step. | ||||
|  | ||||
| It is now time to apply those files on your cluster to start Traefik. | ||||
|  | ||||
| ```shell | ||||
| kubectl apply -f 00-role.yml \ | ||||
|               -f 00-account.yml \ | ||||
|               -f 01-role-binding.yml \ | ||||
|               -f 02-traefik.yml \ | ||||
|               -f 02-traefik-services.yml | ||||
| ``` | ||||
|  | ||||
| ## Proxying applications | ||||
|  | ||||
| The only part still missing is the business application behind the reverse proxy. | ||||
| For this guide, we use the example application [traefik/whoami](https://github.com/traefik/whoami), | ||||
| but the principles are applicable to any other application. | ||||
|  | ||||
| The `whoami` application is a simple HTTP server running on port 80 which answers host-related information to the incoming requests. | ||||
| As usual, start by creating a file called `03-whoami.yml` and paste the following `Deployment` resource: | ||||
|  | ||||
| ```yaml tab="03-whoami.yml" | ||||
| kind: Deployment | ||||
| apiVersion: apps/v1 | ||||
| metadata: | ||||
|   name: whoami | ||||
|   labels: | ||||
|     app: whoami | ||||
|  | ||||
| spec: | ||||
|   replicas: 1 | ||||
|   selector: | ||||
|     matchLabels: | ||||
|       app: whoami | ||||
|   template: | ||||
|     metadata: | ||||
|       labels: | ||||
|         app: whoami | ||||
|     spec: | ||||
|       containers: | ||||
|         - name: whoami | ||||
|           image: traefik/whoami | ||||
|           ports: | ||||
|             - name: web | ||||
|               containerPort: 80 | ||||
| ``` | ||||
|  | ||||
| And continue by creating the following `Service` resource in a file called `03-whoami-services.yml`: | ||||
|  | ||||
| ```yaml tab="03-whoami-services.yml" | ||||
| apiVersion: v1 | ||||
| kind: Service | ||||
| metadata: | ||||
|   name: whoami | ||||
|  | ||||
| spec: | ||||
|   ports: | ||||
|     - name: web | ||||
|       port: 80 | ||||
|       targetPort: web | ||||
|        | ||||
|   selector: | ||||
|     app: whoami | ||||
| ``` | ||||
|  | ||||
| Thanks to the Kubernetes API, | ||||
| Traefik is notified when an Ingress resource is created, updated, or deleted. | ||||
| This makes the process dynamic. | ||||
| The ingresses are, in a way, the [dynamic configuration](../../providers/kubernetes-ingress/) for Traefik. | ||||
|  | ||||
| !!! tip | ||||
|  | ||||
|     Find more information on [ingress controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/), | ||||
|     and [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) in the official Kubernetes documentation. | ||||
|  | ||||
| Create a file called `04-whoami-ingress.yml` and insert the `Ingress` resource: | ||||
|  | ||||
| ```yaml tab="04-whoami-ingress.yml" | ||||
| apiVersion: networking.k8s.io/v1 | ||||
| kind: Ingress | ||||
| metadata: | ||||
|   name: whoami-ingress | ||||
| spec: | ||||
|   rules: | ||||
|   - http: | ||||
|       paths: | ||||
|       - path: / | ||||
|         pathType: Prefix | ||||
|         backend: | ||||
|           service: | ||||
|             name: whoami | ||||
|             port: | ||||
|               name: web | ||||
| ``` | ||||
|  | ||||
| This `Ingress` configures Traefik to redirect any incoming requests starting with `/` to the `whoami:80` service. | ||||
|  | ||||
| At this point, all the configurations are ready. | ||||
| It is time to apply those new files: | ||||
|  | ||||
| ```shell | ||||
| kubectl apply -f 03-whoami.yml \ | ||||
|               -f 03-whoami-services.yml \ | ||||
|               -f 04-whoami-ingress.yml | ||||
| ``` | ||||
|  | ||||
| Now you should be able to access the `whoami` application and the Traefik dashboard. | ||||
| Load the dashboard on a web browser: [`http://localhost:8080`](http://localhost:8080). | ||||
|  | ||||
| And now access the `whoami` application: | ||||
|  | ||||
| ```shell | ||||
| curl -v http://localhost/ | ||||
| ``` | ||||
|  | ||||
| !!! question "Going further" | ||||
|  | ||||
|     - [Filter the ingresses](../providers/kubernetes-ingress.md#ingressclass) to use with [IngressClass](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) | ||||
|     - Use [IngressRoute CRD](../providers/kubernetes-crd.md) | ||||
|     - Protect [ingresses with TLS](../routing/providers/kubernetes-ingress.md#enabling-tls-via-annotations) | ||||
|      | ||||
| {!traefik-for-business-applications.md!} | ||||
| @@ -1,6 +1,11 @@ | ||||
| --- | ||||
| title: "Traefik Getting Started Quickly" | ||||
| description: "Looking to get started with Traefik Proxy quickly? Read the technical documentation to see a basic use case that leverages Docker." | ||||
| --- | ||||
|  | ||||
| # Quick Start | ||||
|  | ||||
| A Simple Use Case Using Docker | ||||
| A Basic Use Case Using Docker | ||||
| {: .subtitle } | ||||
|  | ||||
|  | ||||
| @@ -14,9 +19,9 @@ version: '3' | ||||
|  | ||||
| services: | ||||
|   reverse-proxy: | ||||
|     # The official v2 Traefik docker image | ||||
|     image: traefik:v2.5 | ||||
|     # Enables the web UI and tells Traefik to listen to docker | ||||
|     # The official v3 Traefik Docker image | ||||
|     image: traefik:v3.0 | ||||
|     # Enables the web UI and tells Traefik to listen to Docker | ||||
|     command: --api.insecure=true --providers.docker | ||||
|     ports: | ||||
|       # The HTTP port | ||||
| @@ -45,7 +50,12 @@ Now that we have a Traefik instance up and running, we will deploy new services. | ||||
| Edit your `docker-compose.yml` file and add the following at the end of your file. | ||||
|  | ||||
| ```yaml | ||||
| # ... | ||||
| version: '3' | ||||
|  | ||||
| services: | ||||
|  | ||||
|   ... | ||||
|  | ||||
|   whoami: | ||||
|     # A container that exposes an API to show its IP address | ||||
|     image: traefik/whoami | ||||
| @@ -53,7 +63,7 @@ Edit your `docker-compose.yml` file and add the following at the end of your fil | ||||
|       - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)" | ||||
| ``` | ||||
|  | ||||
| The above defines `whoami`: a simple web service that outputs information about the machine it is deployed on (its IP address, host, and so on). | ||||
| The above defines [`whoami`](https://github.com/traefik/whoami "Link to whoami app on GitHub"), a web service that outputs information about the machine it is deployed on (its IP address, host, etc.). | ||||
|  | ||||
| Start the `whoami` service with the following command: | ||||
|  | ||||
| @@ -61,9 +71,9 @@ Start the `whoami` service with the following command: | ||||
| docker-compose up -d whoami | ||||
| ``` | ||||
|  | ||||
| Go back to your browser (`http://localhost:8080/api/rawdata`) and see that Traefik has automatically detected the new container and updated its own configuration. | ||||
| Browse `http://localhost:8080/api/rawdata` and see that Traefik has automatically detected the new container and updated its own configuration. | ||||
|  | ||||
| When Traefik detects new services, it creates the corresponding routes so you can call them ... _let's see!_  (Here, we're using curl) | ||||
| When Traefik detects new services, it creates the corresponding routes, so you can call them ... _let's see!_  (Here, we're using curl) | ||||
|  | ||||
| ```shell | ||||
| curl -H Host:whoami.docker.localhost http://127.0.0.1 | ||||
| @@ -85,7 +95,7 @@ Run more instances of your `whoami` service with the following command: | ||||
| docker-compose up -d --scale whoami=2 | ||||
| ``` | ||||
|  | ||||
| Go back to your browser (`http://localhost:8080/api/rawdata`) and see that Traefik has automatically detected the new instance of the container. | ||||
| Browse to `http://localhost:8080/api/rawdata` and see that Traefik has automatically detected the new instance of the container. | ||||
|  | ||||
| Finally, see that Traefik load-balances between the two instances of your service by running the following command twice: | ||||
|  | ||||
| @@ -108,4 +118,7 @@ IP: 172.27.0.4 | ||||
| ``` | ||||
|  | ||||
| !!! question "Where to Go Next?" | ||||
|     Now that you have a basic understanding of how Traefik can automatically create the routes to your services and load balance them, it is time to dive into [the documentation](/) and let Traefik work for you! | ||||
|  | ||||
|     Now that you have a basic understanding of how Traefik can automatically create the routes to your services and load balance them, it is time to dive into [the documentation](/ "Link to the docs landing page") and let Traefik work for you! | ||||
|  | ||||
| {!traefik-for-business-applications.md!} | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Let's Encrypt Documentation" | ||||
| description: "Learn how to configure Traefik Proxy to use an ACME provider like Let's Encrypt for automatic certificate generation. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Let's Encrypt | ||||
|  | ||||
| Automatic HTTPS | ||||
| @@ -6,7 +11,11 @@ Automatic HTTPS | ||||
| You can configure Traefik to use an ACME provider (like Let's Encrypt) for automatic certificate generation. | ||||
|  | ||||
| !!! warning "Let's Encrypt and Rate Limiting" | ||||
|     Note that Let's Encrypt API has [rate limiting](https://letsencrypt.org/docs/rate-limits). | ||||
|     Note that Let's Encrypt API has [rate limiting](https://letsencrypt.org/docs/rate-limits). These last up to **one week**, and can not be overridden. | ||||
|      | ||||
|     When running Traefik in a container this file should be persisted across restarts.  | ||||
|     If Traefik requests new certificates each time it starts up, a crash-looping container can quickly reach Let's Encrypt's ratelimits. | ||||
|     To configure where certificates are stored, please take a look at the [storage](#storage) configuration. | ||||
|  | ||||
|     Use Let's Encrypt staging server with the [`caServer`](#caserver) configuration option | ||||
|     when experimenting to avoid hitting this limit too fast. | ||||
| @@ -23,7 +32,9 @@ Certificates are requested for domain names retrieved from the router's [dynamic | ||||
|  | ||||
| You can read more about this retrieval mechanism in the following section: [ACME Domain Definition](#domain-definition). | ||||
|  | ||||
| !!! important "Defining a certificates resolver does not result in all routers automatically using it. Each router that is supposed to use the resolver must [reference](../routing/routers/index.md#certresolver) it." | ||||
| !!! warning "Defining an [ACME challenge type](#the-different-acme-challenges) is a requirement for a certificate resolver to be functional." | ||||
|  | ||||
| !!! important "Defining a certificate resolver does not result in all routers automatically using it. Each router that is supposed to use the resolver must [reference](../routing/routers/index.md#certresolver) it." | ||||
|  | ||||
| ??? note "Configuration Reference" | ||||
|  | ||||
| @@ -114,7 +125,7 @@ Please check the [configuration examples below](#configuration-examples) for mor | ||||
|     --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web | ||||
|     ``` | ||||
|  | ||||
| !!! important "Defining a certificates resolver does not result in all routers automatically using it. Each router that is supposed to use the resolver must [reference](../routing/routers/index.md#certresolver) it." | ||||
| !!! important "Defining a certificate resolver does not result in all routers automatically using it. Each router that is supposed to use the resolver must [reference](../routing/routers/index.md#certresolver) it." | ||||
|  | ||||
| ??? example "Single Domain from Router's Rule Example" | ||||
|  | ||||
| @@ -140,7 +151,11 @@ Please check the [configuration examples below](#configuration-examples) for mor | ||||
|  | ||||
| Traefik automatically tracks the expiry date of ACME certificates it generates. | ||||
|  | ||||
| If there are less than 30 days remaining before the certificate expires, Traefik will attempt to renew it automatically. | ||||
| By default, Traefik manages 90 days certificates, | ||||
| and starts to renew certificates 30 days before their expiry. | ||||
|  | ||||
| When using a certificate resolver that issues certificates with custom durations, | ||||
| one can configure the certificates' duration with the [`certificatesDuration`](#certificatesduration) option. | ||||
|  | ||||
| !!! info "" | ||||
|     Certificates that are no longer used may still be renewed, as Traefik does not currently check if the certificate is being used before renewing. | ||||
| @@ -154,7 +169,9 @@ When using LetsEncrypt with kubernetes, there are some known caveats with both t | ||||
|  | ||||
| ## The Different ACME Challenges | ||||
|  | ||||
| !!! important "Defining a certificates resolver does not result in all routers automatically using it. Each router that is supposed to use the resolver must [reference](../routing/routers/index.md#certresolver) it." | ||||
| !!! warning "Defining one ACME challenge is a requirement for a certificate resolver to be functional." | ||||
|  | ||||
| !!! important "Defining a certificate resolver does not result in all routers automatically using it. Each router that is supposed to use the resolver must [reference](../routing/routers/index.md#certresolver) it." | ||||
|  | ||||
| ### `tlsChallenge` | ||||
|  | ||||
| @@ -266,8 +283,19 @@ Use the `DNS-01` challenge to generate and renew ACME certificates by provisioni | ||||
|     # ... | ||||
|     ``` | ||||
|  | ||||
|     !!! important | ||||
|         A `provider` is mandatory. | ||||
| !!! warning "`CNAME` support" | ||||
|  | ||||
|     `CNAME` are supported (and sometimes even [encouraged](https://letsencrypt.org/2019/10/09/onboarding-your-customers-with-lets-encrypt-and-acme.html#the-advantages-of-a-cname)), | ||||
|     but there are a few cases where they can be [problematic](../../getting-started/faq/#why-does-lets-encrypt-wildcard-certificate-renewalgeneration-with-dns-challenge-fail). | ||||
|  | ||||
|     If needed, `CNAME` support can be disabled with the following environment variable: | ||||
|  | ||||
|     ```bash | ||||
|     LEGO_DISABLE_CNAME_SUPPORT=true | ||||
|     ``` | ||||
|  | ||||
| !!! important | ||||
|     A `provider` is mandatory. | ||||
|  | ||||
| #### `providers` | ||||
|  | ||||
| @@ -280,114 +308,141 @@ For example, `CF_API_EMAIL_FILE=/run/secrets/traefik_cf-api-email` could be used | ||||
|  | ||||
| For complete details, refer to your provider's _Additional configuration_ link. | ||||
|  | ||||
| | Provider Name                                               | Provider Code  | Environment Variables                                                                                                                       |                                                                             | | ||||
| |-------------------------------------------------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------| | ||||
| | [ACME DNS](https://github.com/joohoi/acme-dns)              | `acme-dns`     | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH`                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/acme-dns)     | | ||||
| | [Alibaba Cloud](https://www.alibabacloud.com)               | `alidns`       | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID`                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/alidns)       | | ||||
| | [all-inkl](https://all-inkl.com)                            | `allinkl`      | `ALL_INKL_LOGIN`, `ALL_INKL_PASSWORD`                                                                                                       | [Additional configuration](https://go-acme.github.io/lego/dns/allinkl)      | | ||||
| | [ArvanCloud](https://www.arvancloud.com/en)                 | `arvancloud`   | `ARVANCLOUD_API_KEY`                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/arvancloud)   | | ||||
| | [Auroradns](https://www.pcextreme.com/dns-health-checks)    | `auroradns`    | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT`                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/auroradns)    | | ||||
| | [Autodns](https://www.internetx.com/domains/autodns/)       | `autodns`      | `AUTODNS_API_USER`, `AUTODNS_API_PASSWORD`                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/autodns)      | | ||||
| | [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]`   | [Additional configuration](https://go-acme.github.io/lego/dns/azure)        | | ||||
| | [Bindman](https://github.com/labbsr0x/bindman-dns-webhook)  | `bindman`      | `BINDMAN_MANAGER_ADDRESS`                                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/bindman)      | | ||||
| | [Blue Cat](https://www.bluecatnetworks.com/)                | `bluecat`      | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW`                                    | [Additional configuration](https://go-acme.github.io/lego/dns/bluecat)      | | ||||
| | [Checkdomain](https://www.checkdomain.de/)                  | `checkdomain`  | `CHECKDOMAIN_TOKEN`,                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/checkdomain/) | | ||||
| | [CloudDNS](https://vshosting.eu/)                           | `clouddns`     | `CLOUDDNS_CLIENT_ID`, `CLOUDDNS_EMAIL`, `CLOUDDNS_PASSWORD`                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/clouddns)     | | ||||
| | [Cloudflare](https://www.cloudflare.com)                    | `cloudflare`   | `CF_API_EMAIL`, `CF_API_KEY` [^5] or `CF_DNS_API_TOKEN`, `[CF_ZONE_API_TOKEN]`                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/cloudflare)   | | ||||
| | [ClouDNS](https://www.cloudns.net/)                         | `cloudns`      | `CLOUDNS_AUTH_ID`, `CLOUDNS_AUTH_PASSWORD`                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/cloudns)      | | ||||
| | [CloudXNS](https://www.cloudxns.net)                        | `cloudxns`     | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/cloudxns)     | | ||||
| | [ConoHa](https://www.conoha.jp)                             | `conoha`       | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD`                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/conoha)       | | ||||
| | [Constellix](https://constellix.com)                        | `constellix`   | `CONSTELLIX_API_KEY`, `CONSTELLIX_SECRET_KEY`                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/constellix)   | | ||||
| | [deSEC](https://desec.io)                                   | `desec`        | `DESEC_TOKEN`                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/desec)        | | ||||
| | [DigitalOcean](https://www.digitalocean.com)                | `digitalocean` | `DO_AUTH_TOKEN`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/digitalocean) | | ||||
| | [DNS Made Easy](https://dnsmadeeasy.com)                    | `dnsmadeeasy`  | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX`                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/dnsmadeeasy)  | | ||||
| | [DNSimple](https://dnsimple.com)                            | `dnsimple`     | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL`                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/dnsimple)     | | ||||
| | [DNSPod](https://www.dnspod.com/)                           | `dnspod`       | `DNSPOD_API_KEY`                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/dnspod)       | | ||||
| | [Domain Offensive (do.de)](https://www.do.de/)              | `dode`         | `DODE_TOKEN`                                                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/dode)         | | ||||
| | [Domeneshop](https://domene.shop)                           | `domeneshop`   | `DOMENESHOP_API_TOKEN`, `DOMENESHOP_API_SECRET`                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/domeneshop)   | | ||||
| | [DreamHost](https://www.dreamhost.com/)                     | `dreamhost`    | `DREAMHOST_API_KEY`                                                                                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/dreamhost)    | | ||||
| | [Duck DNS](https://www.duckdns.org/)                        | `duckdns`      | `DUCKDNS_TOKEN`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/duckdns)      | | ||||
| | [Dyn](https://dyn.com)                                      | `dyn`          | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD`                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/dyn)          | | ||||
| | [Dynu](https://www.dynu.com)                                | `dynu`         | `DYNU_API_KEY`                                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/dynu)         | | ||||
| | [EasyDNS](https://easydns.com/)                             | `easydns`      | `EASYDNS_TOKEN`, `EASYDNS_KEY`                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/easydns)      | | ||||
| | [EdgeDNS](https://www.akamai.com/)                          | `edgedns`      | `AKAMAI_CLIENT_TOKEN`,  `AKAMAI_CLIENT_SECRET`,  `AKAMAI_ACCESS_TOKEN`                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns)      | | ||||
| | [Epik](https://www.epik.com)                                | `epik`         | `EPIK_SIGNATURE`                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/epik)         | | ||||
| | [Exoscale](https://www.exoscale.com)                        | `exoscale`     | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT`                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/exoscale)     | | ||||
| | [Fast DNS](https://www.akamai.com/)                         | `fastdns`      | `AKAMAI_CLIENT_TOKEN`,  `AKAMAI_CLIENT_SECRET`,  `AKAMAI_ACCESS_TOKEN`                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns)      | | ||||
| | [Freemyip.com](https://freemyip.com)                        | `freemyip`     | `FREEMYIP_TOKEN`                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/freemyip)     | | ||||
| | [G-Core Lab](https://gcorelabs.com/dns/)                    | `gcore`        | `GCORE_PERMANENT_API_TOKEN`                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/gcore)        | | ||||
| | [Gandi v5](https://doc.livedns.gandi.net)                   | `gandiv5`      | `GANDIV5_API_KEY`                                                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/gandiv5)      | | ||||
| | [Gandi](https://www.gandi.net)                              | `gandi`        | `GANDI_API_KEY`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/gandi)        | | ||||
| | [Glesys](https://glesys.com/)                               | `glesys`       | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN`                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/glesys)       | | ||||
| | [GoDaddy](https://godaddy.com/)                             | `godaddy`      | `GODADDY_API_KEY`, `GODADDY_API_SECRET`                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/godaddy)      | | ||||
| | [Google Cloud DNS](https://cloud.google.com/dns/docs/)      | `gcloud`       | `GCE_PROJECT`, Application Default Credentials [^2] [^3], [`GCE_SERVICE_ACCOUNT_FILE`]                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/gcloud)       | | ||||
| | [Hetzner](https://hetzner.com)                              | `hetzner`      | `HETZNER_API_KEY`                                                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/hetzner)      | | ||||
| | [hosting.de](https://www.hosting.de)                        | `hostingde`    | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME`                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/hostingde)    | | ||||
| | [Hosttech](https://www.hosttech.eu)                         | `hosttech`     | `HOSTTECH_API_KEY`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/hosttech)     | | ||||
| | [HyperOne](https://www.hyperone.com)                        | `hyperone`     | `HYPERONE_PASSPORT_LOCATION`, `HYPERONE_LOCATION_ID`                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/hyperone)     | | ||||
| | [IBM Cloud (SoftLayer)](https://www.ibm.com/cloud/)         | `ibmcloud`     | `SOFTLAYER_USERNAME`, `SOFTLAYER_API_KEY`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/ibmcloud)     | | ||||
| | [IIJ](https://www.iij.ad.jp/)                               | `iij`          | `IIJ_API_ACCESS_KEY`, `IIJ_API_SECRET_KEY`, `IIJ_DO_SERVICE_CODE`                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/iij)          | | ||||
| | [Infoblox](https://www.infoblox.com/)                       | `infoblox`     | `INFOBLOX_USER`, `INFOBLOX_PASSWORD`, `INFOBLOX_HOST`                                                                                       | [Additional configuration](https://go-acme.github.io/lego/dns/infoblox)     | | ||||
| | [Infomaniak](https://www.infomaniak.com)                    | `infomaniak`   | `INFOMANIAK_ACCESS_TOKEN`                                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/infomaniak)   | | ||||
| | [Internet.bs](https://internetbs.net)                       | `internetbs`   | `INTERNET_BS_API_KEY`, `INTERNET_BS_PASSWORD`                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/internetbs)   | | ||||
| | [INWX](https://www.inwx.de/en)                              | `inwx`         | `INWX_USERNAME`, `INWX_PASSWORD`                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/inwx)         | | ||||
| | [ionos](https://ionos.com/)                                 | `ionos`        | `IONOS_API_KEY`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/ionos)        | | ||||
| | [Joker.com](https://joker.com)                              | `joker`        | `JOKER_API_MODE` with `JOKER_API_KEY` or `JOKER_USERNAME`, `JOKER_PASSWORD`                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/joker)        | | ||||
| | [Lightsail](https://aws.amazon.com/lightsail/)              | `lightsail`    | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `DNS_ZONE`                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/lightsail)    | | ||||
| | [Linode v4](https://www.linode.com)                         | `linode`       | `LINODE_TOKEN`                                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/linode)       | | ||||
| | [Liquid Web](https://www.liquidweb.com/)                    | `liquidweb`    | `LIQUID_WEB_PASSWORD`, `LIQUID_WEB_USERNAME`, `LIQUID_WEB_ZONE`                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/liquidweb)    | | ||||
| | [Loopia](https://loopia.com/)                               | `loopia`       | `LOOPIA_API_PASSWORD`, `LOOPIA_API_USER`                                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/loopia)       | | ||||
| | [LuaDNS](https://luadns.com)                                | `luadns`       | `LUADNS_API_USERNAME`, `LUADNS_API_TOKEN`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/luadns)       | | ||||
| | [MyDNS.jp](https://www.mydns.jp/)                           | `mydnsjp`      | `MYDNSJP_MASTER_ID`, `MYDNSJP_PASSWORD`                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/mydnsjp)      | | ||||
| | [Mythic Beasts](https://www.mythic-beasts.com)              | `mythicbeasts` | `MYTHICBEASTS_USER_NAME`, `MYTHICBEASTS_PASSWORD`                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/mythicbeasts) | | ||||
| | [name.com](https://www.name.com/)                           | `namedotcom`   | `NAMECOM_USERNAME`, `NAMECOM_API_TOKEN`, `NAMECOM_SERVER`                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/namedotcom)   | | ||||
| | [Namecheap](https://www.namecheap.com)                      | `namecheap`    | `NAMECHEAP_API_USER`, `NAMECHEAP_API_KEY`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/namecheap)    | | ||||
| | [Namesilo](https://www.namesilo.com/)                       | `namesilo`     | `NAMESILO_API_KEY`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/namesilo)     | | ||||
| | [Netcup](https://www.netcup.eu/)                            | `netcup`       | `NETCUP_CUSTOMER_NUMBER`, `NETCUP_API_KEY`, `NETCUP_API_PASSWORD`                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/netcup)       | | ||||
| | [Netlify](https://www.netlify.com)                          | `netlify`      | `NETLIFY_TOKEN`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/netlify)      | | ||||
| | [Nicmanager](https://www.nicmanager.com)                    | `nicmanager`   | `NICMANAGER_API_EMAIL`, `NICMANAGER_API_PASSWORD`                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/nicmanager)   | | ||||
| | [NIFCloud](https://cloud.nifty.com/service/dns.htm)         | `nifcloud`     | `NIFCLOUD_ACCESS_KEY_ID`, `NIFCLOUD_SECRET_ACCESS_KEY`                                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/nifcloud)     | | ||||
| | [Njalla](https://njal.la)                                   | `njalla`       | `NJALLA_TOKEN`                                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/njalla)       | | ||||
| | [NS1](https://ns1.com/)                                     | `ns1`          | `NS1_API_KEY`                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/ns1)          | | ||||
| | [Open Telekom Cloud](https://cloud.telekom.de)              | `otc`          | `OTC_DOMAIN_NAME`, `OTC_USER_NAME`, `OTC_PASSWORD`, `OTC_PROJECT_NAME`, `OTC_IDENTITY_ENDPOINT`                                             | [Additional configuration](https://go-acme.github.io/lego/dns/otc)          | | ||||
| | [Openstack Designate](https://docs.openstack.org/designate) | `designate`    | `OS_AUTH_URL`, `OS_USERNAME`, `OS_PASSWORD`, `OS_TENANT_NAME`, `OS_REGION_NAME`                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/designate)    | | ||||
| | [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` | [Additional configuration](https://go-acme.github.io/lego/dns/oraclecloud)  | | ||||
| | [OVH](https://www.ovh.com)                                  | `ovh`          | `OVH_ENDPOINT`, `OVH_APPLICATION_KEY`, `OVH_APPLICATION_SECRET`, `OVH_CONSUMER_KEY`                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/ovh)          | | ||||
| | [Porkbun](https://porkbun.com/)                             | `porkbun`      | `PORKBUN_SECRET_API_KEY`, `PORKBUN_API_KEY`                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/porkbun)      | | ||||
| | [PowerDNS](https://www.powerdns.com)                        | `pdns`         | `PDNS_API_KEY`, `PDNS_API_URL`                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/pdns)         | | ||||
| | [Rackspace](https://www.rackspace.com/cloud/dns)            | `rackspace`    | `RACKSPACE_USER`, `RACKSPACE_API_KEY`                                                                                                       | [Additional configuration](https://go-acme.github.io/lego/dns/rackspace)    | | ||||
| | [reg.ru](https://www.reg.ru)                                | `regru`        | `REGRU_USERNAME`, `REGRU_PASSWORD`                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/regru)        | | ||||
| | [RFC2136](https://tools.ietf.org/html/rfc2136)              | `rfc2136`      | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER`                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/rfc2136)      | | ||||
| | [RimuHosting](https://rimuhosting.com)                      | `rimuhosting`  | `RIMUHOSTING_API_KEY`                                                                                                                       | [Additional configuration](https://go-acme.github.io/lego/dns/rimuhosting)  | | ||||
| | [Route 53](https://aws.amazon.com/route53/)                 | `route53`      | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile.             | [Additional configuration](https://go-acme.github.io/lego/dns/route53)      | | ||||
| | [Sakura Cloud](https://cloud.sakura.ad.jp/)                 | `sakuracloud`  | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET`                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/sakuracloud)  | | ||||
| | [Scaleway](https://www.scaleway.com)                        | `scaleway`     | `SCALEWAY_API_TOKEN`                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/scaleway)     | | ||||
| | [Selectel](https://selectel.ru/en/)                         | `selectel`     | `SELECTEL_API_TOKEN`                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/selectel)     | | ||||
| | [Servercow](https://servercow.de)                           | `servercow`    | `SERVERCOW_USERNAME`, `SERVERCOW_PASSWORD`                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/servercow)    | | ||||
| | [Simply.com](https://www.simply.com/en/domains/)            | `simply`       | `SIMPLY_ACCOUNT_NAME`, `SIMPLY_API_KEY`                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/simply)       | | ||||
| | [Sonic](https://www.sonic.com/)                             | `sonic`        | `SONIC_USER_ID`, `SONIC_API_KEY`                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/sonic)        | | ||||
| | [Stackpath](https://www.stackpath.com/)                     | `stackpath`    | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID`                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath)    | | ||||
| | [Tencent Cloud DNS](https://cloud.tencent.com/product/cns)  | `tencentcloud` | `TENCENTCLOUD_SECRET_ID`, `TENCENTCLOUD_SECRET_KEY`                                                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/tencentcloud) | | ||||
| | [TransIP](https://www.transip.nl/)                          | `transip`      | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH`                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/transip)      | | ||||
| | [UKFast SafeDNS](https://www.ukfast.co.uk/dns-hosting.html) | `safedns`      | `SAFEDNS_AUTH_TOKEN`                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/safedns)      | | ||||
| | [VegaDNS](https://github.com/shupp/VegaDNS-API)             | `vegadns`      | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL`                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/vegadns)      | | ||||
| | [Versio](https://www.versio.nl/domeinnamen)                 | `versio`       | `VERSIO_USERNAME`, `VERSIO_PASSWORD`                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/versio)       | | ||||
| | [VinylDNS](https://www.vinyldns.io)                         | `vinyldns`     | `VINYLDNS_ACCESS_KEY`, `VINYLDNS_SECRET_KEY`, `VINYLDNS_HOST`                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/vinyldns)     | | ||||
| | [Vscale](https://vscale.io/)                                | `vscale`       | `VSCALE_API_TOKEN`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/vscale)       | | ||||
| | [VULTR](https://www.vultr.com)                              | `vultr`        | `VULTR_API_KEY`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/vultr)        | | ||||
| | [WEDOS](https://www.wedos.com)                              | `wedos`        | `WEDOS_USERNAME`, `WEDOS_WAPI_PASSWORD`                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/wedos)        | | ||||
| | [Yandex](https://yandex.com)                                | `yandex`       | `YANDEX_PDD_TOKEN`                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/yandex)       | | ||||
| | [Zone.ee](https://www.zone.ee)                              | `zoneee`       | `ZONEEE_API_USER`, `ZONEEE_API_KEY`                                                                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/zoneee)       | | ||||
| | [Zonomi](https://zonomi.com)                                | `zonomi`       | `ZONOMI_API_KEY`                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/zonomi)       | | ||||
| | External Program                                            | `exec`         | `EXEC_PATH`                                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/exec)         | | ||||
| | HTTP request                                                | `httpreq`      | `HTTPREQ_ENDPOINT`, `HTTPREQ_MODE`, `HTTPREQ_USERNAME`, `HTTPREQ_PASSWORD` [^1]                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/httpreq)      | | ||||
| | manual                                                      | `manual`       | none, but you need to run Traefik interactively [^4], turn on debug log to see instructions and press <kbd>Enter</kbd>.                     |                                                                             | | ||||
| | Provider Name                                                          | Provider Code      | Environment Variables                                                                                                                                                            |                                                                                 | | ||||
| |------------------------------------------------------------------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------| | ||||
| | [ACME DNS](https://github.com/joohoi/acme-dns)                         | `acme-dns`         | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH`                                                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/acme-dns)         | | ||||
| | [Alibaba Cloud](https://www.alibabacloud.com)                          | `alidns`           | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID`                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/alidns)           | | ||||
| | [all-inkl](https://all-inkl.com)                                       | `allinkl`          | `ALL_INKL_LOGIN`, `ALL_INKL_PASSWORD`                                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/allinkl)          | | ||||
| | [ArvanCloud](https://www.arvancloud.ir/en)                            | `arvancloud`       | `ARVANCLOUD_API_KEY`                                                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/arvancloud)       | | ||||
| | [Auroradns](https://www.pcextreme.com/dns-health-checks)               | `auroradns`        | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT`                                                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/auroradns)        | | ||||
| | [Autodns](https://www.internetx.com/domains/autodns/)                  | `autodns`          | `AUTODNS_API_USER`, `AUTODNS_API_PASSWORD`                                                                                                                                       | [Additional configuration](https://go-acme.github.io/lego/dns/autodns)          | | ||||
| | [Azure](https://azure.microsoft.com/services/dns/)  (DEPRECATED)       | `azure`            | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_METADATA_ENDPOINT]`                                        | [Additional configuration](https://go-acme.github.io/lego/dns/azure)            | | ||||
| | [AzureDNS](https://azure.microsoft.com/services/dns/)                  | `azuredns`         | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_TENANT_ID`, `AZURE_SUBSCRIPTION_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_ENVIRONMENT]`, `[AZURE_PRIVATE_ZONE]`, `[AZURE_ZONE_NAME]` | [Additional configuration](https://go-acme.github.io/lego/dns/azuredns)         | | ||||
| | [Bindman](https://github.com/labbsr0x/bindman-dns-webhook)             | `bindman`          | `BINDMAN_MANAGER_ADDRESS`                                                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/bindman)          | | ||||
| | [Blue Cat](https://www.bluecatnetworks.com/)                           | `bluecat`          | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW`                                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/bluecat)          | | ||||
| | [Brandit](https://www.brandit.com)                                     | `brandit`          | `BRANDIT_API_USERNAME`, `BRANDIT_API_KEY`                                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/brandit)          | | ||||
| | [Bunny](https://bunny.net)                                             | `bunny`            | `BUNNY_API_KEY`                                                                                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/bunny)            | | ||||
| | [Checkdomain](https://www.checkdomain.de/)                             | `checkdomain`      | `CHECKDOMAIN_TOKEN`,                                                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/checkdomain/)     | | ||||
| | [Civo](https://www.civo.com/)                                          | `civo`             | `CIVO_TOKEN`                                                                                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/civo)             | | ||||
| | [Cloud.ru](https://cloud.ru)                                           | `cloudru`          | `CLOUDRU_SERVICE_INSTANCE_ID`, `CLOUDRU_KEY_ID`, `CLOUDRU_SECRET`                                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/cloudru)          | | ||||
| | [CloudDNS](https://vshosting.eu/)                                      | `clouddns`         | `CLOUDDNS_CLIENT_ID`, `CLOUDDNS_EMAIL`, `CLOUDDNS_PASSWORD`                                                                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/clouddns)         | | ||||
| | [Cloudflare](https://www.cloudflare.com)                               | `cloudflare`       | `CF_API_EMAIL`, `CF_API_KEY` [^5] or `CF_DNS_API_TOKEN`, `[CF_ZONE_API_TOKEN]`                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/cloudflare)       | | ||||
| | [ClouDNS](https://www.cloudns.net/)                                    | `cloudns`          | `CLOUDNS_AUTH_ID`, `CLOUDNS_AUTH_PASSWORD`                                                                                                                                       | [Additional configuration](https://go-acme.github.io/lego/dns/cloudns)          | | ||||
| | [CloudXNS](https://www.cloudxns.net)                                   | `cloudxns`         | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY`                                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/cloudxns)         | | ||||
| | [ConoHa](https://www.conoha.jp)                                        | `conoha`           | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD`                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/conoha)           | | ||||
| | [Constellix](https://constellix.com)                                   | `constellix`       | `CONSTELLIX_API_KEY`, `CONSTELLIX_SECRET_KEY`                                                                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/constellix)       | | ||||
| | [Derak Cloud](https://derak.cloud/)                                    | `derak`            | `DERAK_API_KEY`                                                                                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/derak)            | | ||||
| | [deSEC](https://desec.io)                                              | `desec`            | `DESEC_TOKEN`                                                                                                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/desec)            | | ||||
| | [DigitalOcean](https://www.digitalocean.com)                           | `digitalocean`     | `DO_AUTH_TOKEN`                                                                                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/digitalocean)     | | ||||
| | [DNS Made Easy](https://dnsmadeeasy.com)                               | `dnsmadeeasy`      | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX`                                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/dnsmadeeasy)      | | ||||
| | [dnsHome.de](https://www.dnshome.de)                                   | `dnsHomede`        | `DNSHOMEDE_CREDENTIALS`                                                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/dnshomede)        | | ||||
| | [DNSimple](https://dnsimple.com)                                       | `dnsimple`         | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL`                                                                                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/dnsimple)         | | ||||
| | [DNSPod](https://www.dnspod.com/)                                      | `dnspod`           | `DNSPOD_API_KEY`                                                                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/dnspod)           | | ||||
| | [Domain Offensive (do.de)](https://www.do.de/)                         | `dode`             | `DODE_TOKEN`                                                                                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/dode)             | | ||||
| | [Domeneshop](https://domene.shop)                                      | `domeneshop`       | `DOMENESHOP_API_TOKEN`, `DOMENESHOP_API_SECRET`                                                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/domeneshop)       | | ||||
| | [DreamHost](https://www.dreamhost.com/)                                | `dreamhost`        | `DREAMHOST_API_KEY`                                                                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/dreamhost)        | | ||||
| | [Duck DNS](https://www.duckdns.org/)                                   | `duckdns`          | `DUCKDNS_TOKEN`                                                                                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/duckdns)          | | ||||
| | [Dyn](https://dyn.com)                                                 | `dyn`              | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/dyn)              | | ||||
| | [Dynu](https://www.dynu.com)                                           | `dynu`             | `DYNU_API_KEY`                                                                                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/dynu)             | | ||||
| | [EasyDNS](https://easydns.com/)                                        | `easydns`          | `EASYDNS_TOKEN`, `EASYDNS_KEY`                                                                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/easydns)          | | ||||
| | [EdgeDNS](https://www.akamai.com/)                                     | `edgedns`          | `AKAMAI_CLIENT_TOKEN`,  `AKAMAI_CLIENT_SECRET`,  `AKAMAI_ACCESS_TOKEN`                                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns)          | | ||||
| | [Efficient IP](https://efficientip.com)                                | `efficientip`      | `EFFICIENTIP_USERNAME`, `EFFICIENTIP_PASSWORD`, `EFFICIENTIP_HOSTNAME`, `EFFICIENTIP_DNS_NAME`                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/efficientip)      | | ||||
| | [Epik](https://www.epik.com)                                           | `epik`             | `EPIK_SIGNATURE`                                                                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/epik)             | | ||||
| | [Exoscale](https://www.exoscale.com)                                   | `exoscale`         | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT`                                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/exoscale)         | | ||||
| | [Fast DNS](https://www.akamai.com/)                                    | `fastdns`          | `AKAMAI_CLIENT_TOKEN`,  `AKAMAI_CLIENT_SECRET`,  `AKAMAI_ACCESS_TOKEN`                                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns)          | | ||||
| | [Freemyip.com](https://freemyip.com)                                   | `freemyip`         | `FREEMYIP_TOKEN`                                                                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/freemyip)         | | ||||
| | [G-Core](https://gcore.com/dns/)                                       | `gcore`            | `GCORE_PERMANENT_API_TOKEN`                                                                                                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/gcore)            | | ||||
| | [Gandi v5](https://doc.livedns.gandi.net)                              | `gandiv5`          | `GANDIV5_API_KEY`                                                                                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/gandiv5)          | | ||||
| | [Gandi](https://www.gandi.net)                                         | `gandi`            | `GANDI_API_KEY`                                                                                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/gandi)            | | ||||
| | [Glesys](https://glesys.com/)                                          | `glesys`           | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/glesys)           | | ||||
| | [GoDaddy](https://www.godaddy.com)                                     | `godaddy`          | `GODADDY_API_KEY`, `GODADDY_API_SECRET`                                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/godaddy)          | | ||||
| | [Google Cloud DNS](https://cloud.google.com/dns/docs/)                 | `gcloud`           | `GCE_PROJECT`, Application Default Credentials [^2] [^3], [`GCE_SERVICE_ACCOUNT_FILE`]                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/gcloud)           | | ||||
| | [Google Domains](https://domains.google)                               | `googledomains`    | `GOOGLE_DOMAINS_ACCESS_TOKEN`                                                                                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/googledomains)    | | ||||
| | [Hetzner](https://hetzner.com)                                         | `hetzner`          | `HETZNER_API_KEY`                                                                                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/hetzner)          | | ||||
| | [hosting.de](https://www.hosting.de)                                   | `hostingde`        | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME`                                                                                                                                       | [Additional configuration](https://go-acme.github.io/lego/dns/hostingde)        | | ||||
| | [Hosttech](https://www.hosttech.eu)                                    | `hosttech`         | `HOSTTECH_API_KEY`                                                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/hosttech)         | | ||||
| | [Hurricane Electric](https://dns.he.net)                               | `hurricane`        | `HURRICANE_TOKENS` [^6]                                                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/hurricane)        | | ||||
| | [HyperOne](https://www.hyperone.com)                                   | `hyperone`         | `HYPERONE_PASSPORT_LOCATION`, `HYPERONE_LOCATION_ID`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/hyperone)         | | ||||
| | [IBM Cloud (SoftLayer)](https://www.ibm.com/cloud/)                    | `ibmcloud`         | `SOFTLAYER_USERNAME`, `SOFTLAYER_API_KEY`                                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/ibmcloud)         | | ||||
| | [IIJ DNS Platform Service](https://www.iij.ad.jp)                      | `iijdpf`           | `IIJ_DPF_API_TOKEN` , `IIJ_DPF_DPM_SERVICE_CODE`                                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/iijdpf)           | | ||||
| | [IIJ](https://www.iij.ad.jp/)                                          | `iij`              | `IIJ_API_ACCESS_KEY`, `IIJ_API_SECRET_KEY`, `IIJ_DO_SERVICE_CODE`                                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/iij)              | | ||||
| | [Infoblox](https://www.infoblox.com/)                                  | `infoblox`         | `INFOBLOX_USERNAME`, `INFOBLOX_PASSWORD`, `INFOBLOX_HOST`                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/infoblox)         | | ||||
| | [Infomaniak](https://www.infomaniak.com)                               | `infomaniak`       | `INFOMANIAK_ACCESS_TOKEN`                                                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/infomaniak)       | | ||||
| | [Internet.bs](https://internetbs.net)                                  | `internetbs`       | `INTERNET_BS_API_KEY`, `INTERNET_BS_PASSWORD`                                                                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/internetbs)       | | ||||
| | [INWX](https://www.inwx.de/en)                                         | `inwx`             | `INWX_USERNAME`, `INWX_PASSWORD`                                                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/inwx)             | | ||||
| | [ionos](https://ionos.com/)                                            | `ionos`            | `IONOS_API_KEY`                                                                                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/ionos)            | | ||||
| | [IPv64](https://ipv64.net)                                             | `ipv64`            | `IPV64_API_KEY`                                                                                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/ipv64)            | | ||||
| | [iwantmyname](https://iwantmyname.com)                                 | `iwantmyname`      | `IWANTMYNAME_USERNAME` , `IWANTMYNAME_PASSWORD`                                                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/iwantmyname)      | | ||||
| | [Joker.com](https://joker.com)                                         | `joker`            | `JOKER_API_MODE` with `JOKER_API_KEY` or `JOKER_USERNAME`, `JOKER_PASSWORD`                                                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/joker)            | | ||||
| | [Liara](https://liara.ir)                                              | `liara`            | `LIARA_API_KEY`                                                                                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/liara)            | | ||||
| | [Lightsail](https://aws.amazon.com/lightsail/)                         | `lightsail`        | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `DNS_ZONE`                                                                                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/lightsail)        | | ||||
| | [Linode v4](https://www.linode.com)                                    | `linode`           | `LINODE_TOKEN`                                                                                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/linode)           | | ||||
| | [Liquid Web](https://www.liquidweb.com/)                               | `liquidweb`        | `LIQUID_WEB_PASSWORD`, `LIQUID_WEB_USERNAME`, `LIQUID_WEB_ZONE`                                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/liquidweb)        | | ||||
| | [Loopia](https://loopia.com/)                                          | `loopia`           | `LOOPIA_API_PASSWORD`, `LOOPIA_API_USER`                                                                                                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/loopia)           | | ||||
| | [LuaDNS](https://luadns.com)                                           | `luadns`           | `LUADNS_API_USERNAME`, `LUADNS_API_TOKEN`                                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/luadns)           | | ||||
| | [Metaname](https://metaname.net)                                       | `metaname`         | `METANAME_ACCOUNT_REFERENCE`, `METANAME_API_KEY`                                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/metaname)         | | ||||
| | [MyDNS.jp](https://www.mydns.jp/)                                      | `mydnsjp`          | `MYDNSJP_MASTER_ID`, `MYDNSJP_PASSWORD`                                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/mydnsjp)          | | ||||
| | [Mythic Beasts](https://www.mythic-beasts.com)                         | `mythicbeasts`     | `MYTHICBEASTS_USER_NAME`, `MYTHICBEASTS_PASSWORD`                                                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/mythicbeasts)     | | ||||
| | [name.com](https://www.name.com/)                                      | `namedotcom`       | `NAMECOM_USERNAME`, `NAMECOM_API_TOKEN`, `NAMECOM_SERVER`                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/namedotcom)       | | ||||
| | [Namecheap](https://www.namecheap.com)                                 | `namecheap`        | `NAMECHEAP_API_USER`, `NAMECHEAP_API_KEY`                                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/namecheap)        | | ||||
| | [Namesilo](https://www.namesilo.com/)                                  | `namesilo`         | `NAMESILO_API_KEY`                                                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/namesilo)         | | ||||
| | [NearlyFreeSpeech.NET](https://www.nearlyfreespeech.net/)              | `nearlyfreespeech` | `NEARLYFREESPEECH_API_KEY`, `NEARLYFREESPEECH_LOGIN`                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/nearlyfreespeech) | | ||||
| | [Netcup](https://www.netcup.eu/)                                       | `netcup`           | `NETCUP_CUSTOMER_NUMBER`, `NETCUP_API_KEY`, `NETCUP_API_PASSWORD`                                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/netcup)           | | ||||
| | [Netlify](https://www.netlify.com)                                     | `netlify`          | `NETLIFY_TOKEN`                                                                                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/netlify)          | | ||||
| | [Nicmanager](https://www.nicmanager.com)                               | `nicmanager`       | `NICMANAGER_API_EMAIL`, `NICMANAGER_API_PASSWORD`                                                                                                                                | [Additional configuration](https://go-acme.github.io/lego/dns/nicmanager)       | | ||||
| | [NIFCloud](https://cloud.nifty.com/service/dns.htm)                    | `nifcloud`         | `NIFCLOUD_ACCESS_KEY_ID`, `NIFCLOUD_SECRET_ACCESS_KEY`                                                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/nifcloud)         | | ||||
| | [Njalla](https://njal.la)                                              | `njalla`           | `NJALLA_TOKEN`                                                                                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/njalla)           | | ||||
| | [Nodion](https://www.nodion.com)                                       | `nodion`           | `NODION_API_TOKEN`                                                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/nodion)           | | ||||
| | [NS1](https://ns1.com/)                                                | `ns1`              | `NS1_API_KEY`                                                                                                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/ns1)              | | ||||
| | [Open Telekom Cloud](https://cloud.telekom.de)                         | `otc`              | `OTC_DOMAIN_NAME`, `OTC_USER_NAME`, `OTC_PASSWORD`, `OTC_PROJECT_NAME`, `OTC_IDENTITY_ENDPOINT`                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/otc)              | | ||||
| | [Openstack Designate](https://docs.openstack.org/designate)            | `designate`        | `OS_AUTH_URL`, `OS_USERNAME`, `OS_PASSWORD`, `OS_TENANT_NAME`, `OS_REGION_NAME`                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/designate)        | | ||||
| | [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`                                      | [Additional configuration](https://go-acme.github.io/lego/dns/oraclecloud)      | | ||||
| | [OVH](https://www.ovh.com)                                             | `ovh`              | `OVH_ENDPOINT`, `OVH_APPLICATION_KEY`, `OVH_APPLICATION_SECRET`, `OVH_CONSUMER_KEY`                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/ovh)              | | ||||
| | [Plesk](https://www.plesk.com)                                         | `plesk`            | `PLESK_SERVER_BASE_URL`, `PLESK_USERNAME`, `PLESK_PASSWORD`                                                                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/plesk)            | | ||||
| | [Porkbun](https://porkbun.com/)                                        | `porkbun`          | `PORKBUN_SECRET_API_KEY`, `PORKBUN_API_KEY`                                                                                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/porkbun)          | | ||||
| | [PowerDNS](https://www.powerdns.com)                                   | `pdns`             | `PDNS_API_KEY`, `PDNS_API_URL`                                                                                                                                                   | [Additional configuration](https://go-acme.github.io/lego/dns/pdns)             | | ||||
| | [Rackspace](https://www.rackspace.com/cloud/dns)                       | `rackspace`        | `RACKSPACE_USER`, `RACKSPACE_API_KEY`                                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/rackspace)        | | ||||
| | [RcodeZero](https://www.rcodezero.at)                                  | `rcodezero`        | `RCODEZERO_API_TOKEN`                                                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/rcodezero)        | | ||||
| | [reg.ru](https://www.reg.ru)                                           | `regru`            | `REGRU_USERNAME`, `REGRU_PASSWORD`                                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/regru)            | | ||||
| | [RFC2136](https://tools.ietf.org/html/rfc2136)                         | `rfc2136`          | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER`                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/rfc2136)          | | ||||
| | [RimuHosting](https://rimuhosting.com)                                 | `rimuhosting`      | `RIMUHOSTING_API_KEY`                                                                                                                                                            | [Additional configuration](https://go-acme.github.io/lego/dns/rimuhosting)      | | ||||
| | [Route 53](https://aws.amazon.com/route53/)                            | `route53`          | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile.                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/route53)          | | ||||
| | [Sakura Cloud](https://cloud.sakura.ad.jp/)                            | `sakuracloud`      | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET`                                                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/sakuracloud)      | | ||||
| | [Scaleway](https://www.scaleway.com)                                   | `scaleway`         | `SCALEWAY_API_TOKEN`                                                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/scaleway)         | | ||||
| | [Selectel](https://selectel.ru/en/)                                    | `selectel`         | `SELECTEL_API_TOKEN`                                                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/selectel)         | | ||||
| | [Servercow](https://servercow.de)                                      | `servercow`        | `SERVERCOW_USERNAME`, `SERVERCOW_PASSWORD`                                                                                                                                       | [Additional configuration](https://go-acme.github.io/lego/dns/servercow)        | | ||||
| | [Simply.com](https://www.simply.com/en/domains/)                       | `simply`           | `SIMPLY_ACCOUNT_NAME`, `SIMPLY_API_KEY`                                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/simply)           | | ||||
| | [Sonic](https://www.sonic.com/)                                        | `sonic`            | `SONIC_USER_ID`, `SONIC_API_KEY`                                                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/sonic)            | | ||||
| | [Stackpath](https://www.stackpath.com/)                                | `stackpath`        | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID`                                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath)        | | ||||
| | [Tencent Cloud DNS](https://cloud.tencent.com/product/cns)             | `tencentcloud`     | `TENCENTCLOUD_SECRET_ID`, `TENCENTCLOUD_SECRET_KEY`                                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/tencentcloud)     | | ||||
| | [TransIP](https://www.transip.nl/)                                     | `transip`          | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH`                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/transip)          | | ||||
| | [UKFast SafeDNS](https://docs.ukfast.co.uk/domains/safedns/index.html) | `safedns`          | `SAFEDNS_AUTH_TOKEN`                                                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/safedns)          | | ||||
| | [Ultradns](https://neustarsecurityservices.com/dns-services)           | `ultradns`         | `ULTRADNS_USERNAME`, `ULTRADNS_PASSWORD`                                                                                                                                         | [Additional configuration](https://go-acme.github.io/lego/dns/ultradns)         | | ||||
| | [Variomedia](https://www.variomedia.de/)                               | `variomedia`       | `VARIOMEDIA_API_TOKEN`                                                                                                                                                           | [Additional configuration](https://go-acme.github.io/lego/dns/variomedia)       | | ||||
| | [VegaDNS](https://github.com/shupp/VegaDNS-API)                        | `vegadns`          | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL`                                                                                                                     | [Additional configuration](https://go-acme.github.io/lego/dns/vegadns)          | | ||||
| | [Vercel](https://vercel.com)                                           | `vercel`           | `VERCEL_API_TOKEN`                                                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/vercel)           | | ||||
| | [Versio](https://www.versio.nl/domeinnamen)                            | `versio`           | `VERSIO_USERNAME`, `VERSIO_PASSWORD`                                                                                                                                             | [Additional configuration](https://go-acme.github.io/lego/dns/versio)           | | ||||
| | [VinylDNS](https://www.vinyldns.io)                                    | `vinyldns`         | `VINYLDNS_ACCESS_KEY`, `VINYLDNS_SECRET_KEY`, `VINYLDNS_HOST`                                                                                                                    | [Additional configuration](https://go-acme.github.io/lego/dns/vinyldns)         | | ||||
| | [VK Cloud](https://mcs.mail.ru/)                                       | `vkcloud`          | `VK_CLOUD_PASSWORD`, `VK_CLOUD_PROJECT_ID`, `VK_CLOUD_USERNAME`                                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/vkcloud)          | | ||||
| | [Vscale](https://vscale.io/)                                           | `vscale`           | `VSCALE_API_TOKEN`                                                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/vscale)           | | ||||
| | [VULTR](https://www.vultr.com)                                         | `vultr`            | `VULTR_API_KEY`                                                                                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/vultr)            | | ||||
| | [Websupport](https://websupport.sk)                                    | `websupport`       | `WEBSUPPORT_API_KEY`, `WEBSUPPORT_SECRET`                                                                                                                                        | [Additional configuration](https://go-acme.github.io/lego/dns/websupport)       | | ||||
| | [WEDOS](https://www.wedos.com)                                         | `wedos`            | `WEDOS_USERNAME`, `WEDOS_WAPI_PASSWORD`                                                                                                                                          | [Additional configuration](https://go-acme.github.io/lego/dns/wedos)            | | ||||
| | [Yandex 360](https://360.yandex.ru)                                    | `yandex360`        | `YANDEX360_OAUTH_TOKEN`, `YANDEX360_ORG_ID`                                                                                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/yandex360)        | | ||||
| | [Yandex Cloud](https://cloud.yandex.com/en/)                           | `yandexcloud`      | `YANDEX_CLOUD_FOLDER_ID`, `YANDEX_CLOUD_IAM_TOKEN`                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/yandexcloud)      | | ||||
| | [Yandex](https://yandex.com)                                           | `yandex`           | `YANDEX_PDD_TOKEN`                                                                                                                                                               | [Additional configuration](https://go-acme.github.io/lego/dns/yandex)           | | ||||
| | [Zone.ee](https://www.zone.ee)                                         | `zoneee`           | `ZONEEE_API_USER`, `ZONEEE_API_KEY`                                                                                                                                              | [Additional configuration](https://go-acme.github.io/lego/dns/zoneee)           | | ||||
| | [Zonomi](https://zonomi.com)                                           | `zonomi`           | `ZONOMI_API_KEY`                                                                                                                                                                 | [Additional configuration](https://go-acme.github.io/lego/dns/zonomi)           | | ||||
| | External Program                                                       | `exec`             | `EXEC_PATH`                                                                                                                                                                      | [Additional configuration](https://go-acme.github.io/lego/dns/exec)             | | ||||
| | HTTP request                                                           | `httpreq`          | `HTTPREQ_ENDPOINT`, `HTTPREQ_MODE`, `HTTPREQ_USERNAME`, `HTTPREQ_PASSWORD` [^1]                                                                                                  | [Additional configuration](https://go-acme.github.io/lego/dns/httpreq)          | | ||||
| | manual                                                                 | `manual`           | none, but you need to run Traefik interactively [^4], turn on debug log to see instructions and press <kbd>Enter</kbd>.                                                          |                                                                                 | | ||||
|  | ||||
| [^1]: more information about the HTTP message format can be found [here](https://go-acme.github.io/lego/dns/httpreq/) | ||||
| [^2]: [providing_credentials_to_your_application](https://cloud.google.com/docs/authentication/production) | ||||
| [^1]: More information about the HTTP message format can be found [here](https://go-acme.github.io/lego/dns/httpreq/). | ||||
| [^2]: [Providing credentials to your application](https://cloud.google.com/docs/authentication/production). | ||||
| [^3]: [google/default.go](https://github.com/golang/oauth2/blob/36a7019397c4c86cf59eeab3bc0d188bac444277/google/default.go#L61-L76) | ||||
| [^4]: `docker stack` remark: there is no way to support terminal attached to container when deploying with `docker stack`, so you might need to run container with `docker run -it` to generate certificates using `manual` provider. | ||||
| [^5]: The `Global API Key` needs to be used, not the `Origin CA Key`. | ||||
| [^6]: As explained in the [LEGO hurricane configuration](https://go-acme.github.io/lego/dns/hurricane/#credentials), each domain or wildcard (record name) needs a token. So each update of record name must be followed by an update of the `HURRICANE_TOKENS` variable, and a restart of Traefik. | ||||
|  | ||||
| !!! info "`delayBeforeCheck`" | ||||
|     By default, the `provider` verifies the TXT record _before_ letting ACME verify. | ||||
| @@ -535,6 +590,50 @@ docker run -v "/my/host/acme:/etc/traefik/acme" traefik | ||||
| !!! warning | ||||
|     For concurrency reasons, this file cannot be shared across multiple instances of Traefik. | ||||
|  | ||||
| ### `certificatesDuration` | ||||
|  | ||||
| _Optional, Default=2160_ | ||||
|  | ||||
| The `certificatesDuration` option defines the certificates' duration in hours. | ||||
| It defaults to `2160` (90 days) to follow Let's Encrypt certificates' duration. | ||||
|  | ||||
| !!! warning "Traefik cannot manage certificates with a duration lower than 1 hour." | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| certificatesResolvers: | ||||
|   myresolver: | ||||
|     acme: | ||||
|       # ... | ||||
|       certificatesDuration: 72 | ||||
|       # ... | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [certificatesResolvers.myresolver.acme] | ||||
|   # ... | ||||
|   certificatesDuration=72 | ||||
|   # ... | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| # ... | ||||
| --certificatesresolvers.myresolver.acme.certificatesduration=72 | ||||
| # ... | ||||
| ``` | ||||
|  | ||||
| `certificatesDuration` is used to calculate two durations: | ||||
|  | ||||
| - `Renew Period`: the period before the end of the certificate duration, during which the certificate should be renewed. | ||||
| - `Renew Interval`: the interval between renew attempts. | ||||
|  | ||||
| | Certificate Duration | Renew Period      | Renew Interval          | | ||||
| |----------------------|-------------------|-------------------------| | ||||
| | >= 1 year            | 4 months          | 1 week                  | | ||||
| | >= 90 days           | 30 days           | 1 day                   | | ||||
| | >= 7 days            | 1 day             | 1 hour                  | | ||||
| | >= 24 hours          | 6 hours           | 10 min                  | | ||||
| | < 24 hours           | 20 min            | 1 min                   | | ||||
|  | ||||
| ### `preferredChain` | ||||
|  | ||||
| _Optional, Default=""_ | ||||
| @@ -599,8 +698,10 @@ certificatesResolvers: | ||||
| If Let's Encrypt is not reachable, the following certificates will apply: | ||||
|  | ||||
|   1. Previously generated ACME certificates (before downtime) | ||||
|   1. Expired ACME certificates | ||||
|   1. Provided certificates | ||||
|   2. Expired ACME certificates | ||||
|   3. Provided certificates | ||||
|  | ||||
| !!! important | ||||
|     For new (sub)domains which need Let's Encrypt authentication, the default Traefik certificate will be used until Traefik is restarted. | ||||
|  | ||||
| {!traefik-for-business-applications.md!} | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| ## Dynamic configuration | ||||
| labels: | ||||
|   - traefik.http.routers.blog.rule=Host(`example.com`) && Path(`/blog`) | ||||
| @@ -22,7 +22,7 @@ deploy: | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: IngressRoute | ||||
| metadata: | ||||
|   name: blogtls | ||||
| @@ -43,27 +43,6 @@ spec: | ||||
|       - '*.example.org' | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| labels: { | ||||
|   "traefik.http.routers.blog.rule": "Host(`example.com`) && Path(`/blog`)", | ||||
|   "traefik.http.routers.blog.tls": "true", | ||||
|   "traefik.http.routers.blog.tls.certresolver": "myresolver", | ||||
|   "traefik.http.routers.blog.tls.domains[0].main": "example.com", | ||||
|   "traefik.http.routers.blog.tls.domains[0].sans": "*.example.com", | ||||
|   "traefik.http.services.blog-svc.loadbalancer.server.port": "8080" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| ## Dynamic configuration | ||||
| labels: | ||||
|   - traefik.http.routers.blog.rule=Host(`example.com`) && Path(`/blog`) | ||||
|   - traefik.http.routers.blog.tls=true | ||||
|   - traefik.http.routers.blog.tls.certresolver=myresolver | ||||
|   - traefik.http.routers.blog.tls.domains[0].main=example.org | ||||
|   - traefik.http.routers.blog.tls.domains[0].sans=*.example.org | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| ## Dynamic configuration | ||||
| http: | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| ## Dynamic configuration | ||||
| labels: | ||||
|   - traefik.http.routers.blog.rule=(Host(`example.com`) && Path(`/blog`)) || Host(`blog.example.org`) | ||||
| @@ -18,7 +18,7 @@ deploy: | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: IngressRoute | ||||
| metadata: | ||||
|   name: blogtls | ||||
| @@ -35,23 +35,6 @@ spec: | ||||
|     certResolver: myresolver | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| labels: { | ||||
|   "traefik.http.routers.blog.rule": "(Host(`example.com`) && Path(`/blog`)) || Host(`blog.example.org`)", | ||||
|   "traefik.http.routers.blog.tls": "true", | ||||
|   "traefik.http.routers.blog.tls.certresolver": "myresolver", | ||||
|   "traefik.http.services.blog-svc.loadbalancer.server.port": "8080" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| ## Dynamic configuration | ||||
| labels: | ||||
|   - traefik.http.routers.blog.rule=(Host(`example.com`) && Path(`/blog`)) || Host(`blog.example.org`) | ||||
|   - traefik.http.routers.blog.tls=true | ||||
|   - traefik.http.routers.blog.tls.certresolver=myresolver | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| ## Dynamic configuration | ||||
| http: | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| ## Dynamic configuration | ||||
| labels: | ||||
|   - traefik.http.routers.blog.rule=Host(`example.com`) && Path(`/blog`) | ||||
| @@ -18,7 +18,7 @@ deploy: | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: IngressRoute | ||||
| metadata: | ||||
|   name: blogtls | ||||
| @@ -35,23 +35,6 @@ spec: | ||||
|     certResolver: myresolver | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| labels: { | ||||
|   "traefik.http.routers.blog.rule": "Host(`example.com`) && Path(`/blog`)", | ||||
|   "traefik.http.routers.blog.tls": "true", | ||||
|   "traefik.http.routers.blog.tls.certresolver": "myresolver", | ||||
|   "traefik.http.services.blog-svc.loadbalancer.server.port": "8080" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| ## Dynamic configuration | ||||
| labels: | ||||
|   - traefik.http.routers.blog.rule=Host(`example.com`) && Path(`/blog`) | ||||
|   - traefik.http.routers.blog.tls=true | ||||
|   - traefik.http.routers.blog.tls.certresolver=myresolver | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| ## Dynamic configuration | ||||
| http: | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Proxy  HTTPS & TLS Overview |Traefik Docs" | ||||
| description: "Traefik supports HTTPS & TLS, which concerns roughly two parts of the configuration: routers, and the TLS connection. Read the documentation to learn more." | ||||
| --- | ||||
|  | ||||
| # HTTPS & TLS | ||||
|  | ||||
| Overview | ||||
| @@ -14,3 +19,5 @@ The next sections of this documentation explain how to configure the TLS connect | ||||
| That is to say, how to obtain [TLS certificates](./tls.md#certificates-definition): | ||||
| either through a definition in the dynamic configuration, or through [Let's Encrypt](./acme.md) (ACME). | ||||
| And how to configure [TLS options](./tls.md#tls-options), and [certificates stores](./tls.md#certificates-stores). | ||||
|  | ||||
| {!traefik-for-business-applications.md!} | ||||
|   | ||||
| @@ -22,6 +22,14 @@ | ||||
|   # | ||||
|   # caServer = "https://acme-staging-v02.api.letsencrypt.org/directory" | ||||
|  | ||||
|   # The certificates' duration in hours. | ||||
|   # It defaults to 2160 (90 days) to follow Let's Encrypt certificates' duration. | ||||
|   # | ||||
|   # Optional | ||||
|   # Default: 2160 | ||||
|   # | ||||
|   # certificatesDuration=2160 | ||||
|  | ||||
|   # Preferred chain to use. | ||||
|   # | ||||
|   # If the CA offers multiple certificate chains, prefer the chain with an issuer matching this Subject Common Name. | ||||
|   | ||||
| @@ -21,6 +21,14 @@ | ||||
| # | ||||
| --certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory | ||||
|  | ||||
| # The certificates' duration in hours. | ||||
| # It defaults to 2160 (90 days) to follow Let's Encrypt certificates' duration. | ||||
| # | ||||
| # Optional | ||||
| # Default: 2160 | ||||
| # | ||||
| --certificatesresolvers.myresolver.acme.certificatesDuration=2160 | ||||
|  | ||||
| # Preferred chain to use. | ||||
| # | ||||
| # If the CA offers multiple certificate chains, prefer the chain with an issuer matching this Subject Common Name. | ||||
|   | ||||
| @@ -24,6 +24,14 @@ certificatesResolvers: | ||||
|       # | ||||
|       # caServer: "https://acme-staging-v02.api.letsencrypt.org/directory" | ||||
|  | ||||
|       # The certificates' duration in hours. | ||||
|       # It defaults to 2160 (90 days) to follow Let's Encrypt certificates' duration. | ||||
|       # | ||||
|       # Optional | ||||
|       # Default: 2160 | ||||
|       # | ||||
|       # certificatesDuration: 2160 | ||||
|  | ||||
|       # Preferred chain to use. | ||||
|       # | ||||
|       # If the CA offers multiple certificate chains, prefer the chain with an issuer matching this Subject Common Name. | ||||
|   | ||||
							
								
								
									
										56
									
								
								docs/content/https/spiffe.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								docs/content/https/spiffe.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| --- | ||||
| title: "Traefik SPIFFE Documentation" | ||||
| description: "Learn how to configure Traefik to use SPIFFE. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # SPIFFE | ||||
|  | ||||
| Secure the backend connection with SPIFFE. | ||||
| {: .subtitle } | ||||
|  | ||||
| [SPIFFE](https://spiffe.io/docs/latest/spiffe-about/overview/) (Secure Production Identity Framework For Everyone),  | ||||
| provides a secure identity in the form of a specially crafted X.509 certificate,  | ||||
| to every workload in an environment. | ||||
|  | ||||
| Traefik is able to connect to the Workload API to obtain an x509-SVID used to secure the connection with SPIFFE enabled backends. | ||||
|  | ||||
| ## Configuration | ||||
|  | ||||
| ### General | ||||
|  | ||||
| Enabling SPIFFE is part of the [static configuration](../getting-started/configuration-overview.md#the-static-configuration). | ||||
| It can be defined by using a file (YAML or TOML) or CLI arguments. | ||||
|  | ||||
| ### Workload API | ||||
|  | ||||
| The `workloadAPIAddr` configuration defines the address of the SPIFFE [Workload API](https://spiffe.io/docs/latest/spiffe-about/spiffe-concepts/#spiffe-workload-api). | ||||
|  | ||||
| !!! info "Enabling SPIFFE in ServersTransports" | ||||
|  | ||||
|     Enabling SPIFFE does not imply that backend connections are going to use it automatically. | ||||
|     Each [ServersTransport](../routing/services/index.md#serverstransport_1) or [TCPServersTransport](../routing/services/index.md#serverstransport_2), | ||||
| 	that is meant to be secured with SPIFFE, | ||||
| 	must explicitly enable it (see [SPIFFE with ServersTransport](../routing/services/index.md#spiffe) or [SPIFFE with TCPServersTransport](../routing/services/index.md#spiffe_1)). | ||||
|  | ||||
| !!! warning "SPIFFE can cause Traefik to stall" | ||||
| 	When using SPIFFE, | ||||
| 	Traefik will wait for the first SVID to be delivered before starting. | ||||
| 	If Traefik is hanging when waiting on SPIFFE SVID delivery, | ||||
| 	please double check that it is correctly registered as workload in your SPIFFE infrastructure. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| ## Static configuration | ||||
| spiffe: | ||||
|     workloadAPIAddr: localhost | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| ## Static configuration | ||||
| [spiffe] | ||||
|     workloadAPIAddr: localhost | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| ## Static configuration | ||||
| --spiffe.workloadAPIAddr=localhost | ||||
| ``` | ||||
							
								
								
									
										207
									
								
								docs/content/https/tailscale.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								docs/content/https/tailscale.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,207 @@ | ||||
| --- | ||||
| title: "Traefik Tailscale Documentation" | ||||
| description: "Learn how to configure Traefik Proxy to resolve TLS certificates for your Tailscale services. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Tailscale | ||||
|  | ||||
| Provision TLS certificates for your internal Tailscale services. | ||||
| {: .subtitle } | ||||
|  | ||||
| To protect a service with TLS, a certificate from a public Certificate Authority is needed. | ||||
| In addition to its vpn role, Tailscale can also [provide certificates](https://tailscale.com/kb/1153/enabling-https/) for the machines in your Tailscale network. | ||||
|  | ||||
| ## Certificate resolvers | ||||
|  | ||||
| To obtain a TLS certificate from the Tailscale daemon, | ||||
| a Tailscale certificate resolver needs to be configured as below. | ||||
|  | ||||
| !!! info "Referencing a certificate resolver" | ||||
|  | ||||
|     Defining a certificate resolver does not imply that routers are going to use it automatically. | ||||
|     Each router or entrypoint that is meant to use the resolver must explicitly [reference](../routing/routers/index.md#certresolver) it. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| certificatesResolvers: | ||||
|     myresolver: | ||||
|         tailscale: {} | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [certificatesResolvers.myresolver.tailscale] | ||||
| ``` | ||||
|  | ||||
| ```bash tab="CLI" | ||||
| --certificatesresolvers.myresolver.tailscale=true | ||||
| ``` | ||||
|  | ||||
| ## Domain Definition | ||||
|  | ||||
| A certificate resolver requests certificates for a set of domain names inferred from routers, according to the following: | ||||
|  | ||||
| - If the router has a [`tls.domains`](../routing/routers/index.md#domains) option set, | ||||
|   then the certificate resolver derives this router domain name from the `main` option of `tls.domains`. | ||||
|  | ||||
| - Otherwise, the certificate resolver derives the domain name from any `Host()` or `HostSNI()` matchers | ||||
|   in the [router's rule](../routing/routers/index.md#rule). | ||||
|  | ||||
| !!! info "Tailscale Domain Format" | ||||
|  | ||||
|     The domain is only taken into account if it is a Tailscale-specific one, | ||||
|     i.e. of the form `machine-name.domains-alias.ts.net`. | ||||
|  | ||||
| ## Configuration Example | ||||
|  | ||||
| !!! example "Enabling Tailscale certificate resolution" | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     entryPoints: | ||||
|       web: | ||||
|         address: ":80" | ||||
|  | ||||
|       websecure: | ||||
|         address: ":443" | ||||
|  | ||||
|     certificatesResolvers: | ||||
|       myresolver: | ||||
|         tailscale: {} | ||||
|     ``` | ||||
|  | ||||
|     ```toml tab="File (TOML)" | ||||
|     [entryPoints] | ||||
|       [entryPoints.web] | ||||
|         address = ":80" | ||||
|  | ||||
|       [entryPoints.websecure] | ||||
|         address = ":443" | ||||
|  | ||||
|     [certificatesResolvers.myresolver.tailscale] | ||||
|     ``` | ||||
|  | ||||
|     ```bash tab="CLI" | ||||
|     --entrypoints.web.address=:80 | ||||
|     --entrypoints.websecure.address=:443 | ||||
|     # ... | ||||
|     --certificatesresolvers.myresolver.tailscale=true | ||||
|     ``` | ||||
|  | ||||
| !!! example "Domain from Router's Rule Example" | ||||
|  | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     ## Dynamic configuration | ||||
|     labels: | ||||
|       - traefik.http.routers.blog.rule=Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`) | ||||
|       - traefik.http.routers.blog.tls.certresolver=myresolver | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Docker (Swarm)" | ||||
|     ## Dynamic configuration | ||||
|     deploy: | ||||
|       labels: | ||||
|         - traefik.http.routers.blog.rule=Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`) | ||||
|         - traefik.http.routers.blog.tls.certresolver=myresolver | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Kubernetes" | ||||
|     apiVersion: traefik.io/v1alpha1 | ||||
|     kind: IngressRoute | ||||
|     metadata: | ||||
|       name: blogtls | ||||
|     spec: | ||||
|       entryPoints: | ||||
|         - websecure | ||||
|       routes: | ||||
|         - match: Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`) | ||||
|           kind: Rule | ||||
|           services: | ||||
|             - name: blog | ||||
|               port: 8080 | ||||
|       tls: | ||||
|         certResolver: myresolver | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     ## Dynamic configuration | ||||
|     http: | ||||
|       routers: | ||||
|         blog: | ||||
|           rule: "Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)" | ||||
|           tls: | ||||
|             certResolver: myresolver | ||||
|     ``` | ||||
|  | ||||
|     ```toml tab="File (TOML)" | ||||
|     ## Dynamic configuration | ||||
|     [http.routers] | ||||
|       [http.routers.blog] | ||||
|       rule = "Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)" | ||||
|       [http.routers.blog.tls] | ||||
|         certResolver = "myresolver" | ||||
|     ``` | ||||
|  | ||||
| !!! example "Domain from Router's tls.domain Example" | ||||
|  | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     ## Dynamic configuration | ||||
|     labels: | ||||
|       - traefik.http.routers.blog.rule=Path(`/metrics`) | ||||
|       - traefik.http.routers.blog.tls.certresolver=myresolver | ||||
|       - traefik.http.routers.blog.tls.domains[0].main=monitoring.yak-bebop.ts.net | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Docker (Swarm)" | ||||
|     ## Dynamic configuration | ||||
|     deploy: | ||||
|       labels: | ||||
|         - traefik.http.routers.blog.rule=Path(`/metrics`) | ||||
|         - traefik.http.routers.blog.tls.certresolver=myresolver | ||||
|         - traefik.http.routers.blog.tls.domains[0].main=monitoring.yak-bebop.ts.net | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Kubernetes" | ||||
|     apiVersion: traefik.io/v1alpha1 | ||||
|     kind: IngressRoute | ||||
|     metadata: | ||||
|       name: blogtls | ||||
|     spec: | ||||
|       entryPoints: | ||||
|         - websecure | ||||
|       routes: | ||||
|         - match: Path(`/metrics`) | ||||
|           kind: Rule | ||||
|           services: | ||||
|             - name: blog | ||||
|               port: 8080 | ||||
|       tls: | ||||
|         certResolver: myresolver | ||||
|         domains: | ||||
|           - main: monitoring.yak-bebop.ts.net | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     ## Dynamic configuration | ||||
|     http: | ||||
|       routers: | ||||
|         blog: | ||||
|           rule: "Path(`/metrics`)" | ||||
|           tls: | ||||
|             certResolver: myresolver | ||||
|             domains: | ||||
|               - main: "monitoring.yak-bebop.ts.net" | ||||
|     ``` | ||||
|  | ||||
|     ```toml tab="File (TOML)" | ||||
|     ## Dynamic configuration | ||||
|     [http.routers] | ||||
|       [http.routers.blog] | ||||
|         rule = "Path(`/metrics`)" | ||||
|         [http.routers.blog.tls] | ||||
|           certResolver = "myresolver" | ||||
|           [[http.routers.blog.tls.domains]] | ||||
|             main = "monitoring.yak-bebop.ts.net" | ||||
|     ``` | ||||
|  | ||||
| ## Automatic Renewals | ||||
|  | ||||
| Traefik automatically tracks the expiry date of each Tailscale certificate it fetches, | ||||
| and starts to renew a certificate 14 days before its expiry to match Tailscale daemon renew policy. | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik TLS Documentation" | ||||
| description: "Learn how to configure the transport layer security (TLS) connection in Traefik Proxy. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # TLS | ||||
|  | ||||
| Transport Layer Security | ||||
| @@ -128,7 +133,91 @@ tls: | ||||
|       keyFile  = "path/to/cert.key" | ||||
| ``` | ||||
|  | ||||
| If no default certificate is provided, Traefik generates and uses a self-signed certificate. | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: TLSStore | ||||
| metadata: | ||||
|   name: default | ||||
|   namespace: default | ||||
|  | ||||
| spec: | ||||
|   defaultCertificate: | ||||
|     secretName: default-certificate | ||||
|      | ||||
| --- | ||||
| apiVersion: v1 | ||||
| kind: Secret | ||||
| metadata: | ||||
|   name: default-certificate | ||||
|   namespace: default | ||||
|    | ||||
| type: Opaque | ||||
| data: | ||||
|   tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= | ||||
|   tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0= | ||||
| ``` | ||||
|  | ||||
| If no `defaultCertificate` is provided, Traefik will use the generated one. | ||||
|  | ||||
| ### ACME Default Certificate | ||||
|  | ||||
| You can configure Traefik to use an ACME provider (like Let's Encrypt) to generate the default certificate. | ||||
| The configuration to resolve the default certificate should be defined in a TLS store: | ||||
|  | ||||
| !!! important "Precedence with the `defaultGeneratedCert` option" | ||||
|  | ||||
|     The `defaultGeneratedCert` definition takes precedence over the ACME default certificate configuration. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Dynamic configuration | ||||
|  | ||||
| tls: | ||||
|   stores: | ||||
|     default: | ||||
|       defaultGeneratedCert: | ||||
|         resolver: myresolver | ||||
|         domain: | ||||
|           main: example.org | ||||
|           sans: | ||||
|             - foo.example.org | ||||
|             - bar.example.org | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| # Dynamic configuration | ||||
|  | ||||
| [tls.stores] | ||||
|   [tls.stores.default.defaultGeneratedCert] | ||||
|     resolver = "myresolver" | ||||
|     [tls.stores.default.defaultGeneratedCert.domain] | ||||
|       main = "example.org" | ||||
|       sans = ["foo.example.org", "bar.example.org"] | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: TLSStore | ||||
| metadata: | ||||
|   name: default | ||||
|   namespace: default | ||||
|  | ||||
| spec: | ||||
|   defaultGeneratedCert: | ||||
|     resolver: myresolver | ||||
|     domain: | ||||
|       main: example.org | ||||
|       sans: | ||||
|         - foo.example.org | ||||
|         - bar.example.org | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Docker & Swarm" | ||||
| ## Dynamic configuration | ||||
| labels: | ||||
|   - "traefik.tls.stores.default.defaultgeneratedcert.resolver=myresolver" | ||||
|   - "traefik.tls.stores.default.defaultgeneratedcert.domain.main=example.org" | ||||
|   - "traefik.tls.stores.default.defaultgeneratedcert.domain.sans=foo.example.org, bar.example.org" | ||||
| ``` | ||||
|  | ||||
| ## TLS Options | ||||
|  | ||||
| @@ -143,11 +232,11 @@ The TLS options allow one to configure some parameters of the TLS connection. | ||||
|     you must specify the provider namespace, for example:   | ||||
|     `traefik.http.routers.myrouter.tls.options=myoptions@file` | ||||
|  | ||||
| !!! important "TLSOptions in Kubernetes" | ||||
| !!! important "TLSOption in Kubernetes" | ||||
|  | ||||
|     When using the TLSOptions-CRD in Kubernetes, one might setup a default set of options that, | ||||
|     When using the [TLSOption resource](../../routing/providers/kubernetes-crd#kind-tlsoption) in Kubernetes, one might setup a default set of options that, | ||||
|     if not explicitly overwritten, should apply to all ingresses.   | ||||
|     To achieve that, you'll have to create a TLSOptions CR with the name `default`. | ||||
|     To achieve that, you'll have to create a TLSOption resource with the name `default`. | ||||
|     There may exist only one TLSOption with the name `default` (across all namespaces) - otherwise they will be dropped.   | ||||
|     To explicitly use a different TLSOption (and using the Kubernetes Ingress resources) | ||||
|     you'll have to add an annotation to the Ingress in the following form: | ||||
| @@ -180,7 +269,7 @@ tls: | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: TLSOption | ||||
| metadata: | ||||
|   name: default | ||||
| @@ -190,7 +279,7 @@ spec: | ||||
|   minVersion: VersionTLS12 | ||||
|  | ||||
| --- | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: TLSOption | ||||
| metadata: | ||||
|   name: mintls13 | ||||
| @@ -231,7 +320,7 @@ tls: | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: TLSOption | ||||
| metadata: | ||||
|   name: default | ||||
| @@ -241,7 +330,7 @@ spec: | ||||
|   maxVersion: VersionTLS13 | ||||
|  | ||||
| --- | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: TLSOption | ||||
| metadata: | ||||
|   name: maxtls12 | ||||
| @@ -276,7 +365,7 @@ tls: | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: TLSOption | ||||
| metadata: | ||||
|   name: default | ||||
| @@ -321,7 +410,7 @@ tls: | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: TLSOption | ||||
| metadata: | ||||
|   name: default | ||||
| @@ -335,8 +424,9 @@ spec: | ||||
|  | ||||
| ### Strict SNI Checking | ||||
|  | ||||
| With strict SNI checking enabled, Traefik won't allow connections from clients | ||||
| that do not specify a server_name extension or don't match any certificate configured on the tlsOption. | ||||
| With strict SNI checking enabled, Traefik won't allow connections from clients that do not specify a server_name extension | ||||
| or don't match any of the configured certificates. | ||||
| The default certificate is irrelevant on that matter. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Dynamic configuration | ||||
| @@ -356,7 +446,7 @@ tls: | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: TLSOption | ||||
| metadata: | ||||
|   name: default | ||||
| @@ -366,39 +456,6 @@ spec: | ||||
|   sniStrict: true | ||||
| ``` | ||||
|  | ||||
| ### Prefer Server Cipher Suites | ||||
|  | ||||
| This option allows the server to choose its most preferred cipher suite instead of the client's. | ||||
| Please note that this is enabled automatically when `minVersion` or `maxVersion` are set. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Dynamic configuration | ||||
|  | ||||
| tls: | ||||
|   options: | ||||
|     default: | ||||
|       preferServerCipherSuites: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| # Dynamic configuration | ||||
|  | ||||
| [tls.options] | ||||
|   [tls.options.default] | ||||
|     preferServerCipherSuites = true | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| kind: TLSOption | ||||
| metadata: | ||||
|   name: default | ||||
|   namespace: default | ||||
|  | ||||
| spec: | ||||
|   preferServerCipherSuites: true | ||||
| ``` | ||||
|  | ||||
| ### ALPN Protocols | ||||
|  | ||||
| _Optional, Default="h2, http/1.1, acme-tls/1"_ | ||||
| @@ -428,7 +485,7 @@ tls: | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: TLSOption | ||||
| metadata: | ||||
|   name: default | ||||
| @@ -444,15 +501,17 @@ spec: | ||||
|  | ||||
| Traefik supports mutual authentication, through the `clientAuth` section. | ||||
|  | ||||
| For authentication policies that require verification of the client certificate, the certificate authority for the certificate should be set in `clientAuth.caFiles`. | ||||
| For authentication policies that require verification of the client certificate, the certificate authority for the certificates should be set in `clientAuth.caFiles`. | ||||
|  | ||||
| In Kubernetes environment, CA certificate can be set in `clientAuth.secretNames`. See [TLSOption resource](../../routing/providers/kubernetes-crd#kind-tlsoption) for more details. | ||||
|  | ||||
| The `clientAuth.clientAuthType` option governs the behaviour as follows: | ||||
|  | ||||
| - `NoClientCert`: disregards any client certificate. | ||||
| - `RequestClientCert`: asks for a certificate but proceeds anyway if none is provided. | ||||
| - `RequireAnyClientCert`: requires a certificate but does not verify if it is signed by a CA listed in `clientAuth.caFiles`. | ||||
| - `VerifyClientCertIfGiven`: if a certificate is provided, verifies if it is signed by a CA listed in `clientAuth.caFiles`. Otherwise proceeds without any certificate. | ||||
| - `RequireAndVerifyClientCert`: requires a certificate, which must be signed by a CA listed in `clientAuth.caFiles`. | ||||
| - `RequireAnyClientCert`: requires a certificate but does not verify if it is signed by a CA listed in `clientAuth.caFiles` or in `clientAuth.secretNames`. | ||||
| - `VerifyClientCertIfGiven`: if a certificate is provided, verifies if it is signed by a CA listed in `clientAuth.caFiles` or in `clientAuth.secretNames`. Otherwise proceeds without any certificate. | ||||
| - `RequireAndVerifyClientCert`: requires a certificate, which must be signed by a CA listed in `clientAuth.caFiles` or in `clientAuth.secretNames`. | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Dynamic configuration | ||||
| @@ -480,7 +539,7 @@ tls: | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: TLSOption | ||||
| metadata: | ||||
|   name: default | ||||
| @@ -493,3 +552,5 @@ spec: | ||||
|       - secretCA | ||||
|     clientAuthType: RequireAndVerifyClientCert | ||||
| ``` | ||||
|  | ||||
| {!traefik-for-business-applications.md!} | ||||
|   | ||||
							
								
								
									
										4
									
								
								docs/content/includes/.markdownlint.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								docs/content/includes/.markdownlint.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| { | ||||
|   "extends": "../../.markdownlint.json", | ||||
|   "MD041": false | ||||
| } | ||||
							
								
								
									
										3
									
								
								docs/content/includes/kubernetes-requirements.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								docs/content/includes/kubernetes-requirements.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| Traefik follows the [Kubernetes support policy](https://kubernetes.io/releases/version-skew-policy/#supported-versions), | ||||
| and supports at least the latest three minor versions of Kubernetes. | ||||
| General functionality cannot be guaranteed for versions older than that. | ||||
							
								
								
									
										14
									
								
								docs/content/includes/traefik-for-business-applications.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								docs/content/includes/traefik-for-business-applications.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| --- | ||||
|  | ||||
| !!! question "Using Traefik for Business Applications?" | ||||
|  | ||||
|     If you are using Traefik in your organization, consider our enterprise-grade solutions: | ||||
|  | ||||
|     - API Management   | ||||
|       [Explore](https://traefik.io/solutions/api-management/) // [Watch Demo Video](https://info.traefik.io/watch-traefik-hub-demo) | ||||
|     - API Gateway   | ||||
|       [Explore](https://traefik.io/solutions/api-gateway/) // [Watch Demo Video](https://info.traefik.io/watch-traefikee-demo) | ||||
|     - Ingress Controller   | ||||
|       [Kubernetes](https://traefik.io/solutions/kubernetes-ingress/) // [Docker Swarm](https://traefik.io/solutions/docker-swarm-ingress/) | ||||
|  | ||||
|     These tools help businesses discover, deploy, secure, and manage microservices and APIs easily, at scale, across any environment. | ||||
| @@ -1,3 +1,7 @@ | ||||
| --- | ||||
| title: "Traefik Proxy Documentation" | ||||
| description: "Traefik Proxy, an open source Edge Router, auto-discovers configurations and supports major orchestrators, like Kubernetes. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Welcome | ||||
|  | ||||
| @@ -9,7 +13,7 @@ It receives requests on behalf of your system and finds out which components are | ||||
| What sets Traefik apart, besides its many features, is that it automatically discovers the right configuration for your services.  | ||||
| The magic happens when Traefik inspects your infrastructure, where it finds relevant information and discovers which service serves which request.  | ||||
|  | ||||
| Traefik is natively compliant with every major cluster technology, such as Kubernetes, Docker, Docker Swarm, AWS, Mesos, Marathon, and [the list goes on](providers/overview.md); and can handle many at the same time. (It even works for legacy software running on bare metal.) | ||||
| Traefik is natively compliant with every major cluster technology, such as Kubernetes, Docker, Docker Swarm, AWS, and [the list goes on](providers/overview.md); and can handle many at the same time. (It even works for legacy software running on bare metal.) | ||||
|   | ||||
| With Traefik, there is no need to maintain and synchronize a separate configuration file: everything happens automatically, in real time (no restarts, no connection interruptions). | ||||
| With Traefik, you spend time developing and deploying new features to your system, not on configuring and maintaining its working state.    | ||||
| @@ -20,9 +24,8 @@ Developing Traefik, our main goal is to make it simple to use, and we're sure yo | ||||
|  | ||||
| !!! info | ||||
|  | ||||
|     Join our user friendly and active [Community Forum](https://community.traefik.io) to discuss, learn, and connect with the traefik community. | ||||
|      | ||||
|     If you're a business running critical services behind Traefik, | ||||
|     know that [Traefik Labs](https://traefik.io), the company that sponsors Traefik's development, | ||||
|     can provide [commercial support](https://info.traefik.io/commercial-services) | ||||
|     and develops an [Enterprise Edition](https://traefik.io/traefik-enterprise/) of Traefik. | ||||
|     Join our user friendly and active [Community Forum](https://community.traefik.io "Link to Traefik Community Forum") to discuss, learn, and connect with the traefik community. | ||||
|  | ||||
|     Using Traefik in your organization? Consider [Traefik Enterprise](https://traefik.io/traefik-enterprise/ "Lino to Traefik Enterprise"), our unified API Gateway and Ingress that simplifies the discovery, security, and deployment of APIs and microservices across any environment. | ||||
|  | ||||
|     See it in action in [this short video walkthrough](https://info.traefik.io/watch-traefikee-demo "Link to video walkthrough"). | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik AddPrefix Documentation" | ||||
| description: "Learn how to implement the HTTP AddPrefix middleware in Traefik Proxy to updates request paths before being forwarded. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Add Prefix | ||||
|  | ||||
| Prefixing the Path | ||||
| @@ -9,7 +14,7 @@ The AddPrefix middleware updates the path of a request before forwarding it. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Prefixing with /foo | ||||
| labels: | ||||
|   - "traefik.http.middlewares.add-foo.addprefix.prefix=/foo" | ||||
| @@ -17,7 +22,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Prefixing with /foo | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: add-foo | ||||
| @@ -31,18 +36,6 @@ spec: | ||||
| - "traefik.http.middlewares.add-foo.addprefix.prefix=/foo" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.add-foo.addprefix.prefix": "/foo" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Prefixing with /foo | ||||
| labels: | ||||
|   - "traefik.http.middlewares.add-foo.addprefix.prefix=/foo" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Prefixing with /foo | ||||
| http: | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik BasicAuth Documentation" | ||||
| description: "The HTTP basic authentication (BasicAuth) middleware in Traefik Proxy restricts access to your Services to known users. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # BasicAuth | ||||
|  | ||||
| Adding Basic Authentication | ||||
| @@ -9,7 +14,7 @@ The BasicAuth middleware restricts access to your services to known users. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Declaring the user list | ||||
| # | ||||
| # Note: when used in docker-compose.yml all dollar signs in the hash need to be doubled for escaping. | ||||
| @@ -23,7 +28,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Declaring the user list | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -36,18 +41,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Declaring the user list | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Declaring the user list | ||||
| http: | ||||
| @@ -88,7 +81,14 @@ The `users` option is an array of authorized users. Each user must be declared u | ||||
|     - If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`. | ||||
|     - For security reasons, the field `users` doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| !!! note "Kubernetes kubernetes.io/basic-auth secret type" | ||||
|      | ||||
|     Kubernetes supports a special `kubernetes.io/basic-auth` secret type. | ||||
|     This secret must contain two keys: `username` and `password`. | ||||
|     Please note that these keys are not hashed or encrypted in any way, and therefore is less secure than other methods. | ||||
|     You can find more information on the [Kubernetes Basic Authentication Secret Documentation](https://kubernetes.io/docs/concepts/configuration/secret/#basic-authentication-secret) | ||||
|  | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Declaring the user list | ||||
| # | ||||
| # Note: when used in docker-compose.yml all dollar signs in the hash need to be doubled for escaping. | ||||
| @@ -102,7 +102,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Declaring the user list | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -120,11 +120,24 @@ kind: Secret | ||||
| metadata: | ||||
|   name: authsecret | ||||
|   namespace: default | ||||
|  | ||||
| data: | ||||
|   users: |2 | ||||
|     dGVzdDokYXByMSRINnVza2trVyRJZ1hMUDZld1RyU3VCa1RycUU4d2ovCnRlc3QyOiRhcHIxJGQ5 | ||||
|     aHI5SEJCJDRIeHdnVWlyM0hQNEVzZ2dQL1FObzAK | ||||
|  | ||||
| --- | ||||
| # This is an alternate auth secret that demonstrates the basic-auth secret type. | ||||
| # Note: the password is not hashed, and is merely base64 encoded. | ||||
|  | ||||
| apiVersion: v1 | ||||
| kind: Secret | ||||
| metadata: | ||||
|   name: authsecret2 | ||||
|   namespace: default | ||||
| type: kubernetes.io/basic-auth | ||||
| data: | ||||
|   username: dXNlcg== # username: user | ||||
|   password: cGFzc3dvcmQ= # password: password | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| @@ -132,18 +145,6 @@ data: | ||||
| - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Declaring the user list | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Declaring the user list | ||||
| http: | ||||
| @@ -176,13 +177,13 @@ The file content is a list of `name:hashed-password`. | ||||
|     - If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`. | ||||
|     - Because it does not make much sense to refer to a file path on Kubernetes, the `usersFile` field doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -207,17 +208,6 @@ data: | ||||
| - "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.basicauth.usersfile": "/path/to/my/usersfile" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -243,13 +233,13 @@ http: | ||||
|  | ||||
| You can customize the realm for the authentication with the `realm` option. The default value is `traefik`. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -262,17 +252,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.basicauth.realm": "MyRealm" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -291,13 +270,13 @@ http: | ||||
|  | ||||
| You can define a header field to store the authenticated user using the `headerField`option. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.my-auth.basicauth.headerField=X-WebAuth-User" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: my-auth | ||||
| @@ -311,12 +290,6 @@ spec: | ||||
| - "traefik.http.middlewares.my-auth.basicauth.headerField=X-WebAuth-User" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.my-auth.basicauth.headerField": "X-WebAuth-User" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -336,13 +309,13 @@ http: | ||||
|  | ||||
| Set the `removeHeader` option to `true` to remove the authorization header before forwarding the request to your service. (Default value is `false`.) | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.removeheader=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -355,17 +328,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.basicauth.removeheader=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.basicauth.removeheader": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.basicauth.removeheader=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Buffering Documentation" | ||||
| description: "The HTTP buffering middleware in Traefik Proxy limits the size of requests that can be forwarded to Services. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Buffering | ||||
|  | ||||
| How to Read the Request before Forwarding It | ||||
| @@ -13,7 +18,7 @@ This can help services avoid large amounts of data (`multipart/form-data` for ex | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Sets the maximum request body to 2MB | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" | ||||
| @@ -21,7 +26,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Sets the maximum request body to 2MB | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: limit | ||||
| @@ -35,18 +40,6 @@ spec: | ||||
| - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes": "2000000" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Sets the maximum request body to 2MB | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Sets the maximum request body to 2MB | ||||
| http: | ||||
| @@ -67,17 +60,19 @@ http: | ||||
|  | ||||
| ### `maxRequestBodyBytes` | ||||
|  | ||||
| _Optional, Default=0_ | ||||
|  | ||||
| The `maxRequestBodyBytes` option configures the maximum allowed body size for the request (in bytes). | ||||
|  | ||||
| If the request exceeds the allowed size, it is not forwarded to the service, and the client gets a `413 (Request Entity Too Large)` response. | ||||
| If the request exceeds the allowed size, it is not forwarded to the service, and the client gets a `413` (Request Entity Too Large) response. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: limit | ||||
| @@ -90,17 +85,6 @@ spec: | ||||
| - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes": "2000000" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -117,15 +101,17 @@ http: | ||||
|  | ||||
| ### `memRequestBodyBytes` | ||||
|  | ||||
| _Optional, Default=1048576_ | ||||
|  | ||||
| You can configure a threshold (in bytes) from which the request will be buffered on disk instead of in memory with the `memRequestBodyBytes` option. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: limit | ||||
| @@ -138,17 +124,6 @@ spec: | ||||
| - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.limit.buffering.memRequestBodyBytes": "2000000" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -165,17 +140,19 @@ http: | ||||
|  | ||||
| ### `maxResponseBodyBytes` | ||||
|  | ||||
| _Optional, Default=0_ | ||||
|  | ||||
| The `maxResponseBodyBytes` option configures the maximum allowed response size from the service (in bytes). | ||||
|  | ||||
| If the response exceeds the allowed size, it is not forwarded to the client. The client gets a `413 (Request Entity Too Large) response` instead. | ||||
| If the response exceeds the allowed size, it is not forwarded to the client. The client gets a `500` (Internal Server Error) response instead. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: limit | ||||
| @@ -188,17 +165,6 @@ spec: | ||||
| - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes": "2000000" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -215,15 +181,17 @@ http: | ||||
|  | ||||
| ### `memResponseBodyBytes` | ||||
|  | ||||
| _Optional, Default=1048576_ | ||||
|  | ||||
| You can configure a threshold (in bytes) from which the response will be buffered on disk instead of in memory with the `memResponseBodyBytes` option. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: limit | ||||
| @@ -236,17 +204,6 @@ spec: | ||||
| - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.limit.buffering.memResponseBodyBytes": "2000000" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes=2000000" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -263,17 +220,19 @@ http: | ||||
|  | ||||
| ### `retryExpression` | ||||
|  | ||||
| _Optional, Default=""_ | ||||
|  | ||||
| You can have the Buffering middleware replay the request using `retryExpression`. | ||||
|  | ||||
| ??? example "Retries once in the case of a network error" | ||||
|  | ||||
|     ```yaml tab="Docker" | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     labels: | ||||
|       - "traefik.http.middlewares.limit.buffering.retryExpression=IsNetworkError() && Attempts() < 2" | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Kubernetes" | ||||
|     apiVersion: traefik.containo.us/v1alpha1 | ||||
|     apiVersion: traefik.io/v1alpha1 | ||||
|     kind: Middleware | ||||
|     metadata: | ||||
|       name: limit | ||||
| @@ -286,17 +245,6 @@ You can have the Buffering middleware replay the request using `retryExpression` | ||||
|     - "traefik.http.middlewares.limit.buffering.retryExpression=IsNetworkError() && Attempts() < 2" | ||||
|     ``` | ||||
|  | ||||
|     ```json tab="Marathon" | ||||
|     "labels": { | ||||
|       "traefik.http.middlewares.limit.buffering.retryExpression": "IsNetworkError() && Attempts() < 2" | ||||
|     } | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Rancher" | ||||
|     labels: | ||||
|       - "traefik.http.middlewares.limit.buffering.retryExpression=IsNetworkError() && Attempts() < 2" | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     http: | ||||
|       middlewares: | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Command Line Documentation" | ||||
| description: "The HTTP chain middleware lets you define reusable combinations of other middleware, to reuse the same groups. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Chain | ||||
|  | ||||
| When One Isn't Enough | ||||
| @@ -10,9 +15,9 @@ It makes reusing the same groups easier. | ||||
|  | ||||
| ## Configuration Example | ||||
|  | ||||
| Below is an example of a Chain containing `WhiteList`, `BasicAuth`, and `RedirectScheme`. | ||||
| Below is an example of a Chain containing `AllowList`, `BasicAuth`, and `RedirectScheme`. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.routers.router1.service=service1" | ||||
|   - "traefik.http.routers.router1.middlewares=secured" | ||||
| @@ -20,12 +25,12 @@ labels: | ||||
|   - "traefik.http.middlewares.secured.chain.middlewares=https-only,known-ips,auth-users" | ||||
|   - "traefik.http.middlewares.auth-users.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" | ||||
|   - "traefik.http.middlewares.https-only.redirectscheme.scheme=https" | ||||
|   - "traefik.http.middlewares.known-ips.ipwhitelist.sourceRange=192.168.1.7,127.0.0.1/32" | ||||
|   - "traefik.http.middlewares.known-ips.ipallowlist.sourceRange=192.168.1.7,127.0.0.1/32" | ||||
|   - "traefik.http.services.service1.loadbalancer.server.port=80" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: IngressRoute | ||||
| metadata: | ||||
|   name: test | ||||
| @@ -42,7 +47,7 @@ spec: | ||||
|       middlewares: | ||||
|         - name: secured | ||||
| --- | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: secured | ||||
| @@ -53,7 +58,7 @@ spec: | ||||
|     - name: known-ips | ||||
|     - name: auth-users | ||||
| --- | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: auth-users | ||||
| @@ -62,7 +67,7 @@ spec: | ||||
|     users: | ||||
|     - test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/ | ||||
| --- | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: https-only | ||||
| @@ -70,12 +75,12 @@ spec: | ||||
|   redirectScheme: | ||||
|     scheme: https | ||||
| --- | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: known-ips | ||||
| spec: | ||||
|   ipWhiteList: | ||||
|   ipAllowList: | ||||
|     sourceRange: | ||||
|     - 192.168.1.7 | ||||
|     - 127.0.0.1/32 | ||||
| @@ -88,35 +93,10 @@ spec: | ||||
| - "traefik.http.middlewares.secured.chain.middlewares=https-only,known-ips,auth-users" | ||||
| - "traefik.http.middlewares.auth-users.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" | ||||
| - "traefik.http.middlewares.https-only.redirectscheme.scheme=https" | ||||
| - "traefik.http.middlewares.known-ips.ipwhitelist.sourceRange=192.168.1.7,127.0.0.1/32" | ||||
| - "traefik.http.middlewares.known-ips.ipallowlist.sourceRange=192.168.1.7,127.0.0.1/32" | ||||
| - "traefik.http.services.service1.loadbalancer.server.port=80" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.routers.router1.service": "service1", | ||||
|   "traefik.http.routers.router1.middlewares": "secured", | ||||
|   "traefik.http.routers.router1.rule": "Host(`mydomain`)", | ||||
|   "traefik.http.middlewares.secured.chain.middlewares": "https-only,known-ips,auth-users", | ||||
|   "traefik.http.middlewares.auth-users.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", | ||||
|   "traefik.http.middlewares.https-only.redirectscheme.scheme": "https", | ||||
|   "traefik.http.middlewares.known-ips.ipwhitelist.sourceRange": "192.168.1.7,127.0.0.1/32", | ||||
|   "traefik.http.services.service1.loadbalancer.server.port": "80" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.routers.router1.service=service1" | ||||
|   - "traefik.http.routers.router1.middlewares=secured" | ||||
|   - "traefik.http.routers.router1.rule=Host(`mydomain`)" | ||||
|   - "traefik.http.middlewares.secured.chain.middlewares=https-only,known-ips,auth-users" | ||||
|   - "traefik.http.middlewares.auth-users.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/" | ||||
|   - "traefik.http.middlewares.https-only.redirectscheme.scheme=https" | ||||
|   - "traefik.http.middlewares.known-ips.ipwhitelist.sourceRange=192.168.1.7,127.0.0.1/32" | ||||
|   - "traefik.http.services.service1.loadbalancer.server.port=80" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # ... | ||||
| http: | ||||
| @@ -145,7 +125,7 @@ http: | ||||
|         scheme: https | ||||
|  | ||||
|     known-ips: | ||||
|       ipWhiteList: | ||||
|       ipAllowList: | ||||
|         sourceRange: | ||||
|           - "192.168.1.7" | ||||
|           - "127.0.0.1/32" | ||||
| @@ -175,7 +155,7 @@ http: | ||||
|   [http.middlewares.https-only.redirectScheme] | ||||
|     scheme = "https" | ||||
|  | ||||
|   [http.middlewares.known-ips.ipWhiteList] | ||||
|   [http.middlewares.known-ips.ipAllowList] | ||||
|     sourceRange = ["192.168.1.7", "127.0.0.1/32"] | ||||
|  | ||||
| [http.services] | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik CircuitBreaker Documentation" | ||||
| description: "The HTTP circuit breaker in Traefik Proxy prevents stacking requests to unhealthy Services, resulting in cascading failures. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # CircuitBreaker | ||||
|  | ||||
| Don't Waste Time Calling Unhealthy Services | ||||
| @@ -25,7 +30,7 @@ To assess if your system is healthy, the circuit breaker constantly monitors the | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Latency Check | ||||
| labels: | ||||
|   - "traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100" | ||||
| @@ -33,7 +38,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Latency Check | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: latency-check | ||||
| @@ -47,18 +52,6 @@ spec: | ||||
| - "traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.latency-check.circuitbreaker.expression": "LatencyAtQuantileMS(50.0) > 100" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Latency Check | ||||
| labels: | ||||
|   - "traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Latency Check | ||||
| http: | ||||
| @@ -171,15 +164,18 @@ This behavior cannot be configured. | ||||
|  | ||||
| ### `CheckPeriod` | ||||
|  | ||||
| The interval used to evaluate `expression` and decide if the state of the circuit breaker must change. | ||||
| By default, `CheckPeriod` is 100ms. This value cannot be configured. | ||||
| _Optional, Default="100ms"_ | ||||
|  | ||||
| The interval between successive checks of the circuit breaker condition (when in standby state). | ||||
|  | ||||
| ### `FallbackDuration` | ||||
|  | ||||
| By default, `FallbackDuration` is 10 seconds. This value cannot be configured. | ||||
| _Optional, Default="10s"_ | ||||
|  | ||||
| ### `RecoveringDuration` | ||||
| The duration for which the circuit breaker will wait before trying to recover (from a tripped state). | ||||
|  | ||||
| The duration of the recovering mode (recovering state). | ||||
| ### `RecoveryDuration` | ||||
|  | ||||
| By default, `RecoveringDuration` is 10 seconds. This value cannot be configured. | ||||
| _Optional, Default="10s"_ | ||||
|  | ||||
| The duration for which the circuit breaker will try to recover (as soon as it is in recovering state). | ||||
|   | ||||
| @@ -1,23 +1,29 @@ | ||||
| --- | ||||
| title: "Traefik Compress Documentation" | ||||
| description: "Traefik Proxy's HTTP middleware lets you compress responses before sending them to the client. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Compress | ||||
|  | ||||
| Compress Responses before Sending them to the Client | ||||
| Compress Allows Compressing Responses before Sending them to the Client | ||||
| {: .subtitle } | ||||
|  | ||||
|  | ||||
|  | ||||
| The Compress middleware uses gzip compression. | ||||
| The Compress middleware supports gzip and Brotli compression. | ||||
| The activation of compression, and the compression method choice rely (among other things) on the request's `Accept-Encoding` header. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| # Enable gzip compression | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Enable compression | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-compress.compress=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Enable gzip compression | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| # Enable compression | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-compress | ||||
| @@ -26,24 +32,12 @@ spec: | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Enable gzip compression | ||||
| # Enable compression | ||||
| - "traefik.http.middlewares.test-compress.compress=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-compress.compress": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Enable gzip compression | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-compress.compress=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Enable gzip compression | ||||
| # Enable compression | ||||
| http: | ||||
|   middlewares: | ||||
|     test-compress: | ||||
| @@ -51,7 +45,7 @@ http: | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| # Enable gzip compression | ||||
| # Enable compression | ||||
| [http.middlewares] | ||||
|   [http.middlewares.test-compress.compress] | ||||
| ``` | ||||
| @@ -60,30 +54,41 @@ http: | ||||
|  | ||||
|     Responses are compressed when the following criteria are all met: | ||||
|  | ||||
|     * The response body is larger than `1400` bytes. | ||||
|     * The `Accept-Encoding` request header contains `gzip`. | ||||
|     * The `Accept-Encoding` request header contains `gzip`, `*`, and/or `br` with or without [quality values](https://developer.mozilla.org/en-US/docs/Glossary/Quality_values). | ||||
|     If the `Accept-Encoding` request header is absent, it is meant as br compression is requested. | ||||
|     If it is present, but its value is the empty string, then compression is disabled. | ||||
|     * The response is not already compressed, i.e. the `Content-Encoding` response header is not already set. | ||||
|  | ||||
|     If the `Content-Type` header is not defined, or empty, the compress middleware will automatically [detect](https://mimesniff.spec.whatwg.org/) a content type. | ||||
|     It will also set the `Content-Type` header according to the detected MIME type. | ||||
|     * The response`Content-Type` header is not one among the [excludedContentTypes options](#excludedcontenttypes). | ||||
|     * The response body is larger than the [configured minimum amount of bytes](#minresponsebodybytes) (default is `1024`). | ||||
|  | ||||
| ## Configuration Options | ||||
|  | ||||
| ### `excludedContentTypes` | ||||
|  | ||||
| _Optional, Default=""_  | ||||
|  | ||||
| `excludedContentTypes` specifies a list of content types to compare the `Content-Type` header of the incoming requests and responses before compressing. | ||||
|  | ||||
| The responses with content types defined in `excludedContentTypes` are not compressed. | ||||
|  | ||||
| Content types are compared in a case-insensitive, whitespace-ignored manner. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| !!! info "In the case of gzip" | ||||
|  | ||||
|     If the `Content-Type` header is not defined, or empty, the compress middleware will automatically [detect](https://mimesniff.spec.whatwg.org/) a content type. | ||||
|     It will also set the `Content-Type` header according to the detected MIME type. | ||||
|  | ||||
| !!! info "gRPC" | ||||
|  | ||||
|     Note that `application/grpc` is never compressed. | ||||
|  | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-compress.compress.excludedcontenttypes=text/event-stream" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-compress | ||||
| @@ -97,17 +102,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-compress.compress.excludedcontenttypes=text/event-stream" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-compress.compress.excludedcontenttypes": "text/event-stream" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-compress.compress.excludedcontenttypes=text/event-stream" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -122,3 +116,44 @@ http: | ||||
|   [http.middlewares.test-compress.compress] | ||||
|     excludedContentTypes = ["text/event-stream"] | ||||
| ``` | ||||
|  | ||||
| ### `minResponseBodyBytes` | ||||
|  | ||||
| _Optional, Default=1024_ | ||||
|  | ||||
| `minResponseBodyBytes` specifies the minimum amount of bytes a response body must have to be compressed. | ||||
|  | ||||
| Responses smaller than the specified values will not be compressed. | ||||
|  | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-compress.compress.minresponsebodybytes=1200" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-compress | ||||
| spec: | ||||
|   compress: | ||||
|     minResponseBodyBytes: 1200 | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| - "traefik.http.middlewares.test-compress.compress.minresponsebodybytes=1200" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|     test-compress: | ||||
|       compress: | ||||
|         minResponseBodyBytes: 1200 | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [http.middlewares] | ||||
|   [http.middlewares.test-compress.compress] | ||||
|     minResponseBodyBytes = 1200 | ||||
| ``` | ||||
|   | ||||
| @@ -1,86 +1,54 @@ | ||||
| --- | ||||
| title: "Traefik ContentType Documentation" | ||||
| description: "Traefik Proxy's HTTP middleware automatically sets the `Content-Type` header value when it is not set by the backend. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # ContentType | ||||
|  | ||||
| Handling Content-Type auto-detection | ||||
| {: .subtitle } | ||||
|  | ||||
| The Content-Type middleware - or rather its `autoDetect` option - | ||||
| specifies whether to let the `Content-Type` header, | ||||
| if it has not been defined by the backend, | ||||
| be automatically set to a value derived from the contents of the response. | ||||
|  | ||||
| As a proxy, the default behavior should be to leave the header alone, | ||||
| regardless of what the backend did with it. | ||||
| However, the historic default was to always auto-detect and set the header if it was not already defined, | ||||
| and altering this behavior would be a breaking change which would impact many users. | ||||
|  | ||||
| This middleware exists to enable the correct behavior until at least the default one can be changed in a future version. | ||||
| The Content-Type middleware sets the `Content-Type` header value to the media type detected from the response content, | ||||
| when it is not set by the backend. | ||||
|  | ||||
| !!! info | ||||
|  | ||||
|     As explained above, for compatibility reasons the default behavior on a router (without this middleware), | ||||
|     is still to automatically set the `Content-Type` header. | ||||
|     Therefore, given the default value of the `autoDetect` option (false), | ||||
|     simply enabling this middleware for a router switches the router's behavior. | ||||
|  | ||||
|     The scope of the Content-Type middleware is the MIME type detection done by the core of Traefik (the server part). | ||||
|     Therefore, it has no effect against any other `Content-Type` header modifications (e.g.: in another middleware such as compress). | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| # Disable auto-detection | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Enable auto-detection | ||||
| labels: | ||||
|   - "traefik.http.middlewares.autodetect.contenttype.autodetect=false" | ||||
|   - "traefik.http.middlewares.autodetect.contenttype=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Disable auto-detection | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| # Enable auto-detection | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: autodetect | ||||
| spec: | ||||
|   contentType: | ||||
|     autoDetect: false | ||||
|   contentType: {} | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Disable auto-detection | ||||
| - "traefik.http.middlewares.autodetect.contenttype.autodetect=false" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.autodetect.contenttype.autodetect": "false" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Disable auto-detection | ||||
| labels: | ||||
|   - "traefik.http.middlewares.autodetect.contenttype.autodetect=false" | ||||
| # Enable auto-detection | ||||
| - "traefik.http.middlewares.autodetect.contenttype=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Disable auto-detection | ||||
| # Enable auto-detection | ||||
| http: | ||||
|   middlewares: | ||||
|     autodetect: | ||||
|       contentType: | ||||
|         autoDetect: false | ||||
|       contentType: {} | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| # Disable auto-detection | ||||
| # Enable auto-detection | ||||
| [http.middlewares] | ||||
|   [http.middlewares.autodetect.contentType] | ||||
|      autoDetect=false | ||||
| ``` | ||||
|  | ||||
| ## Configuration Options | ||||
|  | ||||
| ### `autoDetect` | ||||
|  | ||||
| `autoDetect` specifies whether to let the `Content-Type` header, | ||||
| if it has not been set by the backend, | ||||
| be automatically set to a value derived from the contents of the response. | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik DigestAuth Documentation" | ||||
| description: "Traefik Proxy's HTTP DigestAuth middleware restricts access to your services to known users. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # DigestAuth | ||||
|  | ||||
| Adding Digest Authentication | ||||
| @@ -9,7 +14,7 @@ The DigestAuth middleware restricts access to your services to known users. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Declaring the user list | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| @@ -17,7 +22,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Declaring the user list | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -31,18 +36,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.digestauth.users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Declaring the user list | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Declaring the user list | ||||
| http: | ||||
| @@ -79,13 +72,13 @@ The `users` option is an array of authorized users. Each user will be declared u | ||||
|     - If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`. | ||||
|     - For security reasons, the field `users` doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -109,17 +102,6 @@ data: | ||||
| - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.digestauth.users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -150,13 +132,13 @@ The file content is a list of `name:realm:encoded-password`. | ||||
|     - If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`. | ||||
|     - Because it does not make much sense to refer to a file path on Kubernetes, the `usersFile` field doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -181,17 +163,6 @@ data: | ||||
| - "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.digestauth.usersfile": "/path/to/my/usersfile" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -217,13 +188,13 @@ http: | ||||
|  | ||||
| You can customize the realm for the authentication with the `realm` option. The default value is `traefik`. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -236,17 +207,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.digestauth.realm": "MyRealm" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -265,13 +225,13 @@ http: | ||||
|  | ||||
| You can customize the header field for the authenticated user using the `headerField`option. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: my-auth | ||||
| @@ -285,17 +245,6 @@ spec: | ||||
| - "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.my-auth.digestauth.headerField": "X-WebAuth-User" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -315,13 +264,13 @@ http: | ||||
|  | ||||
| Set the `removeHeader` option to `true` to remove the authorization header before forwarding the request to your service. (Default value is `false`.) | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.removeheader=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -334,17 +283,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.digestauth.removeheader=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.digestauth.removeheader": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.digestauth.removeheader=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|   | ||||
| @@ -1,11 +1,16 @@ | ||||
| # ErrorPage | ||||
| --- | ||||
| title: "Traefik Errors Documentation" | ||||
| description: "In Traefik Proxy, the Errors middleware returns custom pages according to configured ranges of HTTP Status codes. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Errors | ||||
|  | ||||
| It Has Never Been Easier to Say That Something Went Wrong | ||||
| {: .subtitle } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| The ErrorPage middleware returns a custom page in lieu of the default, according to configured ranges of HTTP Status codes. | ||||
| The Errors middleware returns a custom page in lieu of the default, according to configured ranges of HTTP Status codes. | ||||
|  | ||||
| !!! important | ||||
|  | ||||
| @@ -13,19 +18,19 @@ The ErrorPage middleware returns a custom page in lieu of the default, according | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Dynamic Custom Error Page for 5XX Status Code | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-errorpage.errors.status=500-599" | ||||
|   - "traefik.http.middlewares.test-errorpage.errors.service=serviceError" | ||||
|   - "traefik.http.middlewares.test-errorpage.errors.query=/{status}.html" | ||||
|   - "traefik.http.middlewares.test-errors.errors.status=500-599" | ||||
|   - "traefik.http.middlewares.test-errors.errors.service=serviceError" | ||||
|   - "traefik.http.middlewares.test-errors.errors.query=/{status}.html" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-errorpage | ||||
|   name: test-errors | ||||
| spec: | ||||
|   errors: | ||||
|     status: | ||||
| @@ -38,32 +43,16 @@ spec: | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Dynamic Custom Error Page for 5XX Status Code | ||||
| - "traefik.http.middlewares.test-errorpage.errors.status=500-599" | ||||
| - "traefik.http.middlewares.test-errorpage.errors.service=serviceError" | ||||
| - "traefik.http.middlewares.test-errorpage.errors.query=/{status}.html" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-errorpage.errors.status": "500-599", | ||||
|   "traefik.http.middlewares.test-errorpage.errors.service": "serviceError", | ||||
|   "traefik.http.middlewares.test-errorpage.errors.query": "/{status}.html" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Dynamic Custom Error Page for 5XX Status Code | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-errorpage.errors.status=500-599" | ||||
|   - "traefik.http.middlewares.test-errorpage.errors.service=serviceError" | ||||
|   - "traefik.http.middlewares.test-errorpage.errors.query=/{status}.html" | ||||
| - "traefik.http.middlewares.test-errors.errors.status=500-599" | ||||
| - "traefik.http.middlewares.test-errors.errors.service=serviceError" | ||||
| - "traefik.http.middlewares.test-errors.errors.query=/{status}.html" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Custom Error Page for 5XX | ||||
| http: | ||||
|   middlewares: | ||||
|     test-errorpage: | ||||
|     test-errors: | ||||
|       errors: | ||||
|         status: | ||||
|           - "500-599" | ||||
| @@ -77,7 +66,7 @@ http: | ||||
| ```toml tab="File (TOML)" | ||||
| # Custom Error Page for 5XX | ||||
| [http.middlewares] | ||||
|   [http.middlewares.test-errorpage.errors] | ||||
|   [http.middlewares.test-errors.errors] | ||||
|     status = ["500-599"] | ||||
|     service = "serviceError" | ||||
|     query = "/{status}.html" | ||||
| @@ -116,8 +105,17 @@ The service that will serve the new requested error page. | ||||
| !!! info "Host Header" | ||||
|  | ||||
|     By default, the client `Host` header value is forwarded to the configured error [service](#service). | ||||
|     To forward the `Host` value corresponding to the configured error service URL, the [passHostHeader](../../../routing/services/#pass-host-header) option must be set to `false`.      | ||||
|     To forward the `Host` value corresponding to the configured error service URL, the [passHostHeader](../../../routing/services/#pass-host-header) option must be set to `false`. | ||||
|  | ||||
| ### `query` | ||||
|  | ||||
| The URL for the error page (hosted by `service`). You can use the `{status}` variable in the `query` option in order to insert the status code in the URL. | ||||
| The URL for the error page (hosted by [`service`](#service))). | ||||
|  | ||||
| There are multiple variables that can be placed in the `query` option to insert values in the URL. | ||||
|  | ||||
| The table below lists all the available variables and their associated values. | ||||
|  | ||||
| | Variable   | Value                                                              | | ||||
| |------------|--------------------------------------------------------------------| | ||||
| | `{status}` | The response status code.                                          | | ||||
| | `{url}`    | The [escaped](https://pkg.go.dev/net/url#QueryEscape) request URL. | | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik ForwardAuth Documentation" | ||||
| description: "In Traefik Proxy, the HTTP ForwardAuth middleware delegates authentication to an external Service. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # ForwardAuth | ||||
|  | ||||
| Using an External Service to Forward Authentication | ||||
| @@ -11,7 +16,7 @@ Otherwise, the response from the authentication server is returned. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Forward authentication to example.com | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" | ||||
| @@ -19,7 +24,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Forward authentication to example.com | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -33,18 +38,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.address": "https://example.com/auth" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Forward authentication to example.com | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Forward authentication to example.com | ||||
| http: | ||||
| @@ -79,13 +72,13 @@ The following request properties are provided to the forward-auth target endpoin | ||||
|  | ||||
| The `address` option defines the authentication server address. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -98,17 +91,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.address": "https://example.com/auth" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -127,13 +109,13 @@ http: | ||||
|  | ||||
| Set the `trustForwardHeader` option to `true` to trust all `X-Forwarded-*` headers. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -147,17 +129,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -179,13 +150,13 @@ http: | ||||
| The `authResponseHeaders` option is the list of headers to copy from the authentication server response and set on | ||||
| forwarded request, replacing any existing conflicting headers. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -201,17 +172,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders": "X-Auth-User,X-Secret" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -237,13 +197,13 @@ set on forwarded request, after stripping all headers that match the regex. | ||||
| It allows partial matching of the regular expression against the header key. | ||||
| The start of string (`^`) and end of string (`$`) anchors should be used to ensure a full match against the header key. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex=^X-" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -257,17 +217,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex=^X-" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex": "^X-" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex=^X-" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -296,13 +245,13 @@ The `authRequestHeaders` option is the list of the headers to copy from the requ | ||||
| It allows filtering headers that should not be passed to the authentication server. | ||||
| If not set or empty then all request headers are passed. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders=Accept,X-CustomHeader" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -318,17 +267,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders=Accept,X-CustomHeader" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders": "Accept,X-CustomHeader" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders=Accept,X-CustomHeader" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -360,13 +298,13 @@ _Optional_ | ||||
| `ca` is the path to the certificate authority used for the secured connection to the authentication server, | ||||
| it defaults to the system bundle. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -392,17 +330,6 @@ data: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.tls.ca": "path/to/local.crt" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -421,70 +348,6 @@ http: | ||||
|       ca = "path/to/local.crt" | ||||
| ``` | ||||
|  | ||||
| #### `caOptional` | ||||
|  | ||||
| _Optional_ | ||||
|  | ||||
| The value of `caOptional` defines which policy should be used for the secure connection with TLS Client Authentication to the authentication server. | ||||
|  | ||||
| !!! warning "" | ||||
|  | ||||
|     If `ca` is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified. | ||||
|  | ||||
| When this option is set to `true`, a client certificate is requested during the handshake but is not required. If a certificate is sent, it is required to be valid. | ||||
|  | ||||
| When this option is set to `false`, a client certificate is requested during the handshake, and at least one valid certificate should be sent by the client. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.caOptional=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| spec: | ||||
|   forwardAuth: | ||||
|     address: https://example.com/auth | ||||
|     tls: | ||||
|       caOptional: true | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.tls.caOptional=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.tls.caOptional": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.caOptional=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|     test-auth: | ||||
|       forwardAuth: | ||||
|         address: "https://example.com/auth" | ||||
|         tls: | ||||
|           caOptional: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [http.middlewares] | ||||
|   [http.middlewares.test-auth.forwardAuth] | ||||
|     address = "https://example.com/auth" | ||||
|     [http.middlewares.test-auth.forwardAuth.tls] | ||||
|       caOptional = true | ||||
| ``` | ||||
|  | ||||
| #### `cert` | ||||
|  | ||||
| _Optional_ | ||||
| @@ -492,14 +355,14 @@ _Optional_ | ||||
| `cert` is the path to the public certificate used for the secure connection to the authentication server. | ||||
| When using this option, setting the `key` option is required. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert" | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -526,19 +389,6 @@ data: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.tls.cert": "path/to/foo.cert", | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.tls.key": "path/to/foo.key" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert" | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -570,14 +420,14 @@ _Optional_ | ||||
| `key` is the path to the private key used for the secure connection to the authentication server. | ||||
| When using this option, setting the `cert` option is required. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert" | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -604,19 +454,6 @@ data: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.tls.cert": "path/to/foo.cert", | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.tls.key": "path/to/foo.key" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert" | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -647,13 +484,13 @@ _Optional, Default=false_ | ||||
|  | ||||
| If `insecureSkipVerify` is `true`, the TLS connection to the authentication server accepts any certificate presented by the server regardless of the hostnames it covers. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.insecureSkipVerify=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-auth | ||||
| @@ -668,17 +505,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-auth.forwardauth.tls.InsecureSkipVerify=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-auth.forwardauth.tls.insecureSkipVerify": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-auth.forwardauth.tls.InsecureSkipVerify=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|   | ||||
							
								
								
									
										66
									
								
								docs/content/middlewares/http/grpcweb.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								docs/content/middlewares/http/grpcweb.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| --- | ||||
| title: "Traefik GrpcWeb Documentation" | ||||
| description: "In Traefik Proxy's HTTP middleware, GrpcWeb converts a gRPC Web requests to HTTP/2 gRPC requests. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # GrpcWeb | ||||
|  | ||||
| Converting gRPC Web requests to HTTP/2 gRPC requests. | ||||
| {: .subtitle } | ||||
|  | ||||
| The GrpcWeb middleware converts gRPC Web requests to HTTP/2 gRPC requests before forwarding them to the backends. | ||||
|  | ||||
| !!! tip | ||||
|  | ||||
|     Please note, that Traefik needs to communicate using gRPC with the backends (h2c or HTTP/2 over TLS). | ||||
|     Check out the [gRPC](../../user-guides/grpc.md) user guide for more details. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-grpcweb.grpcweb.allowOrigins=*" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-grpcweb | ||||
| spec: | ||||
|   grpcWeb: | ||||
|     allowOrigins: | ||||
|       - "*" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| - "traefik.http.middlewares.test-grpcweb.grpcWeb.allowOrigins=*" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|     test-grpcweb: | ||||
|       grpcWeb: | ||||
|         allowOrigins: | ||||
|           - "*" | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [http.middlewares] | ||||
|   [http.middlewares.test-grpcweb.grpcWeb] | ||||
|     allowOrigins = ["*"] | ||||
| ``` | ||||
|  | ||||
| ## Configuration Options | ||||
|  | ||||
| ### `allowOrigins` | ||||
|  | ||||
| The `allowOrigins` contains the list of allowed origins. | ||||
| A wildcard origin `*` can also be configured to match all requests. | ||||
|  | ||||
| More information including how to use the settings can be found at: | ||||
|  | ||||
| - [Mozilla.org](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin) | ||||
| - [w3](https://fetch.spec.whatwg.org/#http-access-control-allow-origin) | ||||
| - [IETF](https://tools.ietf.org/html/rfc6454#section-7.1) | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Headers Documentation" | ||||
| description: "In Traefik Proxy, the HTTP headers middleware manages the headers of requests and responses. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Headers | ||||
|  | ||||
| Managing Request/Response headers | ||||
| @@ -15,14 +20,14 @@ A set of forwarded headers are automatically added by default. See the [FAQ](../ | ||||
|  | ||||
| The following example adds the `X-Script-Name` header to the proxied request and the `X-Custom-Response-Header` header to the response | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testHeader.headers.customrequestheaders.X-Script-Name=test" | ||||
|   - "traefik.http.middlewares.testHeader.headers.customresponseheaders.X-Custom-Response-Header=value" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-header | ||||
| @@ -39,19 +44,6 @@ spec: | ||||
| - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=value" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name": "test", | ||||
|   "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header": "value" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test" | ||||
|   - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=value" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -77,7 +69,7 @@ http: | ||||
| In the following example, requests are proxied with an extra `X-Script-Name` header while their `X-Custom-Request-Header` header gets stripped, | ||||
| and responses are stripped of their `X-Custom-Response-Header` header. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test" | ||||
|   - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Custom-Request-Header=" | ||||
| @@ -85,7 +77,7 @@ labels: | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-header | ||||
| @@ -104,21 +96,6 @@ spec: | ||||
| - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name": "test", | ||||
|   "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Custom-Request-Header": "", | ||||
|   "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header": "", | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test" | ||||
|   - "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Custom-Request-Header=" | ||||
|   - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -146,21 +123,21 @@ http: | ||||
| Security-related headers (HSTS headers, Browser XSS filter, etc) can be managed similarly to custom headers as shown above. | ||||
| This functionality makes it possible to easily use security features by adding headers. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testHeader.headers.framedeny=true" | ||||
|   - "traefik.http.middlewares.testHeader.headers.browserxssfilter=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-header | ||||
| spec: | ||||
|   headers: | ||||
|     frameDeny: true | ||||
|     browserxssfilter: true | ||||
|     browserXssFilter: true | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| @@ -168,50 +145,42 @@ spec: | ||||
| - "traefik.http.middlewares.testheader.headers.browserxssfilter=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.testheader.headers.framedeny": "true", | ||||
|   "traefik.http.middlewares.testheader.headers.browserxssfilter": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testheader.headers.framedeny=true" | ||||
|   - "traefik.http.middlewares.testheader.headers.browserxssfilter=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|     testHeader: | ||||
|       headers: | ||||
|         frameDeny: true | ||||
|         browserxssfilter: true | ||||
|         browserXssFilter: true | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [http.middlewares] | ||||
|   [http.middlewares.testHeader.headers] | ||||
|     frameDeny = true | ||||
|     browserxssfilter = true | ||||
|     browserXssFilter = true | ||||
| ``` | ||||
|  | ||||
| ### CORS Headers | ||||
|  | ||||
| CORS (Cross-Origin Resource Sharing) headers can be added and configured in a manner similar to the custom headers above. | ||||
| This functionality allows for more advanced security features to quickly be set. | ||||
| If CORS headers are set, then the middleware does not pass preflight requests to any service, | ||||
| instead the response will be generated and sent back to the client directly.   | ||||
| Please note that the example below is by no means authoritative or exhaustive, | ||||
| and should not be used as is for production. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT" | ||||
|   - "traefik.http.middlewares.testheader.headers.accesscontrolallowheaders=*" | ||||
|   - "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=https://foo.bar.org,https://example.org" | ||||
|   - "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100" | ||||
|   - "traefik.http.middlewares.testheader.headers.addvaryheader=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-header | ||||
| @@ -221,6 +190,8 @@ spec: | ||||
|       - "GET" | ||||
|       - "OPTIONS" | ||||
|       - "PUT" | ||||
|     accessControlAllowHeaders: | ||||
|       - "*" | ||||
|     accessControlAllowOriginList: | ||||
|       - "https://foo.bar.org" | ||||
|       - "https://example.org" | ||||
| @@ -230,28 +201,12 @@ spec: | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| - "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT" | ||||
| - "traefik.http.middlewares.testheader.headers.accesscontrolallowheaders=*" | ||||
| - "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=https://foo.bar.org,https://example.org" | ||||
| - "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100" | ||||
| - "traefik.http.middlewares.testheader.headers.addvaryheader=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods": "GET,OPTIONS,PUT", | ||||
|   "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist": "https://foo.bar.org,https://example.org", | ||||
|   "traefik.http.middlewares.testheader.headers.accesscontrolmaxage": "100", | ||||
|   "traefik.http.middlewares.testheader.headers.addvaryheader": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT" | ||||
|   - "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=https://foo.bar.org,https://example.org" | ||||
|   - "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100" | ||||
|   - "traefik.http.middlewares.testheader.headers.addvaryheader=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -261,6 +216,7 @@ http: | ||||
|           - GET | ||||
|           - OPTIONS | ||||
|           - PUT | ||||
|         accessControlAllowHeaders: "*" | ||||
|         accessControlAllowOriginList: | ||||
|           - https://foo.bar.org | ||||
|           - https://example.org | ||||
| @@ -271,7 +227,8 @@ http: | ||||
| ```toml tab="File (TOML)" | ||||
| [http.middlewares] | ||||
|   [http.middlewares.testHeader.headers] | ||||
|     accessControlAllowMethods= ["GET", "OPTIONS", "PUT"] | ||||
|     accessControlAllowMethods = ["GET", "OPTIONS", "PUT"] | ||||
|     accessControlAllowHeaders = [ "*" ] | ||||
|     accessControlAllowOriginList = ["https://foo.bar.org","https://example.org"] | ||||
|     accessControlMaxAge = 100 | ||||
|     addVaryHeader = true | ||||
| @@ -357,43 +314,11 @@ The `allowedHosts` option lists fully qualified domain names that are allowed. | ||||
|  | ||||
| The `hostsProxyHeaders` option is a set of header keys that may hold a proxied hostname value for the request. | ||||
|  | ||||
| ### `sslRedirect` | ||||
|  | ||||
| !!! warning | ||||
|  | ||||
|     Deprecated in favor of [EntryPoint redirection](../../routing/entrypoints.md#redirection) or the [RedirectScheme middleware](./redirectscheme.md). | ||||
|  | ||||
| The `sslRedirect` only allow HTTPS requests when set to `true`. | ||||
|  | ||||
| ### `sslTemporaryRedirect` | ||||
|  | ||||
| !!! warning | ||||
|  | ||||
|     Deprecated in favor of [EntryPoint redirection](../../routing/entrypoints.md#redirection) or the [RedirectScheme middleware](./redirectscheme.md). | ||||
|  | ||||
| Set `sslTemporaryRedirect` to `true` to force an SSL redirection using a 302 (instead of a 301). | ||||
|  | ||||
| ### `sslHost` | ||||
|  | ||||
| !!! warning | ||||
|  | ||||
|     Deprecated in favor of the [RedirectRegex middleware](./redirectregex.md). | ||||
|  | ||||
| The `sslHost` option is the host name that is used to redirect HTTP requests to HTTPS. | ||||
|  | ||||
| ### `sslProxyHeaders` | ||||
|  | ||||
| The `sslProxyHeaders` option is set of header keys with associated values that would indicate a valid HTTPS request. | ||||
| It can be useful when using other proxies (example: `"X-Forwarded-Proto": "https"`). | ||||
|  | ||||
| ### `sslForceHost` | ||||
|  | ||||
| !!! warning | ||||
|  | ||||
|     Deprecated in favor of the [RedirectRegex middleware](./redirectregex.md). | ||||
|  | ||||
| Set `sslForceHost` to `true` and set `sslHost` to force requests to use `SSLHost` regardless of whether they already use SSL. | ||||
|  | ||||
| ### `stsSeconds` | ||||
|  | ||||
| The `stsSeconds` is the max-age of the `Strict-Transport-Security` header. | ||||
| @@ -445,14 +370,6 @@ The `publicKey` implements HPKP to prevent MITM attacks with forged certificates | ||||
|  | ||||
| The `referrerPolicy` allows sites to control whether browsers forward the `Referer` header to other sites. | ||||
|  | ||||
| ### `featurePolicy` | ||||
|  | ||||
| !!! warning | ||||
|  | ||||
|     Deprecated in favor of `permissionsPolicy` | ||||
|  | ||||
| The `featurePolicy` allows sites to control browser features. | ||||
|  | ||||
| ### `permissionsPolicy` | ||||
|  | ||||
| The `permissionsPolicy` allows sites to control browser features. | ||||
| @@ -462,3 +379,5 @@ The `permissionsPolicy` allows sites to control browser features. | ||||
| Set `isDevelopment` to `true` when developing to mitigate the unwanted effects of the `AllowedHosts`, SSL, and STS options. | ||||
| Usually testing takes place using HTTP, not HTTPS, and on `localhost`, not your production domain. | ||||
| If you would like your development environment to mimic production with complete Host blocking, SSL redirects, and STS headers, leave this as `false`. | ||||
|  | ||||
| {!traefik-for-business-applications.md!} | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik InFlightReq Documentation" | ||||
| description: "Traefik Proxy's HTTP middleware lets you limit the number of simultaneous in-flight requests. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # InFlightReq | ||||
|  | ||||
| Limiting the Number of Simultaneous In-Flight Requests | ||||
| @@ -9,13 +14,13 @@ To proactively prevent services from being overwhelmed with high load, the numbe | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-inflightreq | ||||
| @@ -29,18 +34,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-inflightreq.inflightreq.amount": "10" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Limiting to 10 simultaneous connections | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Limiting to 10 simultaneous connections | ||||
| http: | ||||
| @@ -64,13 +57,13 @@ http: | ||||
| The `amount` option defines the maximum amount of allowed simultaneous in-flight request. | ||||
| The middleware responds with `HTTP 429 Too Many Requests` if there are already `amount` requests in progress (based on the same `sourceCriterion` strategy). | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-inflightreq | ||||
| @@ -84,18 +77,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-inflightreq.inflightreq.amount": "10" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Limiting to 10 simultaneous connections | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Limiting to 10 simultaneous connections | ||||
| http: | ||||
| @@ -122,6 +103,8 @@ If none are set, the default is to use the `requestHost`. | ||||
|  | ||||
| The `ipStrategy` option defines two parameters that configures how Traefik determines the client IP: `depth`, and `excludedIPs`. | ||||
|  | ||||
| !!! important "As a middleware, InFlightReq happens before the actual proxying to the backend takes place. In addition, the previous network hop only gets appended to `X-Forwarded-For` during the last stages of proxying, i.e. after it has already passed through the middleware. Therefore, during InFlightReq, as the previous network hop is not yet present in `X-Forwarded-For`, it cannot be used and/or relied upon." | ||||
|  | ||||
| ##### `ipStrategy.depth` | ||||
|  | ||||
| The `depth` option tells Traefik to use the `X-Forwarded-For` header and select the IP located at the `depth` position (starting from the right). | ||||
| @@ -139,13 +122,13 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and select | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `3`     | `"11.0.0.1"` | | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `5`     | `""`         | | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth=2" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-inflightreq | ||||
| @@ -160,17 +143,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth=2" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth": "2" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth=2" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -204,13 +176,13 @@ http: | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"15.0.0.1,16.0.0.1"` | `"13.0.0.1"` | | ||||
|     | `"10.0.0.1,11.0.0.1"`                   | `"10.0.0.1,11.0.0.1"` | `""`         | | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-inflightreq | ||||
| @@ -227,17 +199,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -261,13 +222,13 @@ http: | ||||
|  | ||||
| Name of the header used to group incoming requests. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername=username" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-inflightreq | ||||
| @@ -281,17 +242,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername=username" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername": "username" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername=username" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -312,13 +262,13 @@ http: | ||||
|  | ||||
| Whether to consider the request host as the source. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-inflightreq | ||||
| @@ -332,17 +282,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|   | ||||
| @@ -1,27 +1,30 @@ | ||||
| # IPWhiteList | ||||
| --- | ||||
| title: "Traefik HTTP Middlewares IPAllowList" | ||||
| description: "Learn how to use IPAllowList in HTTP middleware for limiting clients to specific IPs in Traefik Proxy. Read the technical documentation." | ||||
| --- | ||||
| 
 | ||||
| # IPAllowList | ||||
| 
 | ||||
| Limiting Clients to Specific IPs | ||||
| {: .subtitle } | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| IPWhitelist accepts / refuses requests based on the client IP. | ||||
| IPAllowList accepts / refuses requests based on the client IP. | ||||
| 
 | ||||
| ## Configuration Examples | ||||
| 
 | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Accepts request from defined IP | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
|   - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-ipwhitelist | ||||
|   name: test-ipallowlist | ||||
| spec: | ||||
|   ipWhiteList: | ||||
|   ipAllowList: | ||||
|     sourceRange: | ||||
|       - 127.0.0.1/32 | ||||
|       - 192.168.1.7 | ||||
| @@ -29,27 +32,15 @@ spec: | ||||
| 
 | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Accepts request from defined IP | ||||
| - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange": "127.0.0.1/32,192.168.1.7" | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Rancher" | ||||
| # Accepts request from defined IP | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="File (YAML)" | ||||
| # Accepts request from defined IP | ||||
| http: | ||||
|   middlewares: | ||||
|     test-ipwhitelist: | ||||
|       ipWhiteList: | ||||
|     test-ipallowlist: | ||||
|       ipAllowList: | ||||
|         sourceRange: | ||||
|           - "127.0.0.1/32" | ||||
|           - "192.168.1.7" | ||||
| @@ -58,7 +49,7 @@ http: | ||||
| ```toml tab="File (TOML)" | ||||
| # Accepts request from defined IP | ||||
| [http.middlewares] | ||||
|   [http.middlewares.test-ipwhitelist.ipWhiteList] | ||||
|   [http.middlewares.test-ipallowlist.ipAllowList] | ||||
|     sourceRange = ["127.0.0.1/32", "192.168.1.7"] | ||||
| ``` | ||||
| 
 | ||||
| @@ -70,7 +61,10 @@ The `sourceRange` option sets the allowed IPs (or ranges of allowed IPs by using | ||||
| 
 | ||||
| ### `ipStrategy` | ||||
| 
 | ||||
| The `ipStrategy` option defines two parameters that set how Traefik determines the client IP: `depth`, and `excludedIPs`. | ||||
| The `ipStrategy` option defines two parameters that set how Traefik determines the client IP: `depth`, and `excludedIPs`.   | ||||
| If no strategy is set, the default behavior is to match `sourceRange` against the Remote address found in the request. | ||||
| 
 | ||||
| !!! important "As a middleware, whitelisting happens before the actual proxying to the backend takes place. In addition, the previous network hop only gets appended to `X-Forwarded-For` during the last stages of proxying, i.e. after it has already passed through whitelisting. Therefore, during whitelisting, as the previous network hop is not yet present in `X-Forwarded-For`, it cannot be matched against `sourceRange`." | ||||
| 
 | ||||
| #### `ipStrategy.depth` | ||||
| 
 | ||||
| @@ -81,7 +75,7 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take th | ||||
| 
 | ||||
| !!! example "Examples of Depth & X-Forwarded-For" | ||||
| 
 | ||||
|     If `depth` is set to 2, and the request `X-Forwarded-For` header is `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` then the "real" client IP is `"10.0.0.1"` (at depth 4) but the IP used for the whitelisting is `"12.0.0.1"` (`depth=2`). | ||||
|     If `depth` is set to 2, and the request `X-Forwarded-For` header is `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` then the "real" client IP is `"10.0.0.1"` (at depth 4) but the IP used is `"12.0.0.1"` (`depth=2`). | ||||
| 
 | ||||
|     | `X-Forwarded-For`                       | `depth` | clientIP     | | ||||
|     |-----------------------------------------|---------|--------------| | ||||
| @@ -89,21 +83,21 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take th | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `3`     | `"11.0.0.1"` | | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `5`     | `""`         | | ||||
| 
 | ||||
| ```yaml tab="Docker" | ||||
| # Whitelisting Based on `X-Forwarded-For` with `depth=2` | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Allowlisting Based on `X-Forwarded-For` with `depth=2` | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
|   - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.depth=2" | ||||
|   - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
|   - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2" | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Kubernetes" | ||||
| # Whitelisting Based on `X-Forwarded-For` with `depth=2` | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| # Allowlisting Based on `X-Forwarded-For` with `depth=2` | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-ipwhitelist | ||||
|   name: test-ipallowlist | ||||
| spec: | ||||
|   ipWhiteList: | ||||
|   ipAllowList: | ||||
|     sourceRange: | ||||
|       - 127.0.0.1/32 | ||||
|       - 192.168.1.7 | ||||
| @@ -112,31 +106,17 @@ spec: | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Whitelisting Based on `X-Forwarded-For` with `depth=2` | ||||
| - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.depth=2" | ||||
| ``` | ||||
| 
 | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange": "127.0.0.1/32, 192.168.1.7", | ||||
|   "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.depth": "2" | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Rancher" | ||||
| # Whitelisting Based on `X-Forwarded-For` with `depth=2` | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
|   - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.depth=2" | ||||
| # Allowlisting Based on `X-Forwarded-For` with `depth=2` | ||||
| - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" | ||||
| - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2" | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="File (YAML)" | ||||
| # Whitelisting Based on `X-Forwarded-For` with `depth=2` | ||||
| # Allowlisting Based on `X-Forwarded-For` with `depth=2` | ||||
| http: | ||||
|   middlewares: | ||||
|     test-ipwhitelist: | ||||
|       ipWhiteList: | ||||
|     test-ipallowlist: | ||||
|       ipAllowList: | ||||
|         sourceRange: | ||||
|           - "127.0.0.1/32" | ||||
|           - "192.168.1.7" | ||||
| @@ -145,11 +125,11 @@ http: | ||||
| ``` | ||||
| 
 | ||||
| ```toml tab="File (TOML)" | ||||
| # Whitelisting Based on `X-Forwarded-For` with `depth=2` | ||||
| # Allowlisting Based on `X-Forwarded-For` with `depth=2` | ||||
| [http.middlewares] | ||||
|   [http.middlewares.test-ipwhitelist.ipWhiteList] | ||||
|   [http.middlewares.test-ipallowlist.ipAllowList] | ||||
|     sourceRange = ["127.0.0.1/32", "192.168.1.7"] | ||||
|     [http.middlewares.test-ipwhitelist.ipWhiteList.ipStrategy] | ||||
|     [http.middlewares.test-ipallowlist.ipAllowList.ipStrategy] | ||||
|       depth = 2 | ||||
| ``` | ||||
| 
 | ||||
| @@ -169,20 +149,20 @@ http: | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"15.0.0.1,16.0.0.1"` | `"13.0.0.1"` | | ||||
|     | `"10.0.0.1,11.0.0.1"`                   | `"10.0.0.1,11.0.0.1"` | `""`         | | ||||
| 
 | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Exclude from `X-Forwarded-For` | ||||
| labels: | ||||
|     - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
|     - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Kubernetes" | ||||
| # Exclude from `X-Forwarded-For` | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-ipwhitelist | ||||
|   name: test-ipallowlist | ||||
| spec: | ||||
|   ipWhiteList: | ||||
|   ipAllowList: | ||||
|     ipStrategy: | ||||
|       excludedIPs: | ||||
|         - 127.0.0.1/32 | ||||
| @@ -191,27 +171,15 @@ spec: | ||||
| 
 | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Exclude from `X-Forwarded-For` | ||||
| - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7" | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="Rancher" | ||||
| # Exclude from `X-Forwarded-For` | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
| 
 | ||||
| ```yaml tab="File (YAML)" | ||||
| # Exclude from `X-Forwarded-For` | ||||
| http: | ||||
|   middlewares: | ||||
|     test-ipwhitelist: | ||||
|       ipWhiteList: | ||||
|     test-ipallowlist: | ||||
|       ipAllowList: | ||||
|         ipStrategy: | ||||
|           excludedIPs: | ||||
|             - "127.0.0.1/32" | ||||
| @@ -221,7 +189,7 @@ http: | ||||
| ```toml tab="File (TOML)" | ||||
| # Exclude from `X-Forwarded-For` | ||||
| [http.middlewares] | ||||
|   [http.middlewares.test-ipwhitelist.ipWhiteList] | ||||
|     [http.middlewares.test-ipwhitelist.ipWhiteList.ipStrategy] | ||||
|   [http.middlewares.test-ipallowlist.ipAllowList] | ||||
|     [http.middlewares.test-ipallowlist.ipAllowList.ipStrategy] | ||||
|       excludedIPs = ["127.0.0.1/32", "192.168.1.7"] | ||||
| ``` | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Proxy HTTP Middleware Overview" | ||||
| description: "Read the official Traefik Proxy documentation for an overview of the available HTTP middleware." | ||||
| --- | ||||
|  | ||||
| # HTTP Middlewares | ||||
|  | ||||
| Controlling connections | ||||
| @@ -7,7 +12,7 @@ Controlling connections | ||||
|  | ||||
| ## Configuration Example | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # As a Docker Label | ||||
| whoami: | ||||
|   #  A container that exposes an API to show its IP address | ||||
| @@ -21,21 +26,8 @@ whoami: | ||||
|  | ||||
| ```yaml tab="Kubernetes IngressRoute" | ||||
| # As a Kubernetes Traefik IngressRoute | ||||
| apiVersion: apiextensions.k8s.io/v1beta1 | ||||
| kind: CustomResourceDefinition | ||||
| metadata: | ||||
|   name: middlewares.traefik.containo.us | ||||
| spec: | ||||
|   group: traefik.containo.us | ||||
|   version: v1alpha1 | ||||
|   names: | ||||
|     kind: Middleware | ||||
|     plural: middlewares | ||||
|     singular: middleware | ||||
|   scope: Namespaced | ||||
|  | ||||
| --- | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: stripprefix | ||||
| @@ -45,7 +37,7 @@ spec: | ||||
|       - /stripit | ||||
|  | ||||
| --- | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: IngressRoute | ||||
| metadata: | ||||
|   name: ingressroute | ||||
| @@ -64,22 +56,6 @@ spec: | ||||
| - "traefik.http.routers.router1.middlewares=foo-add-prefix@consulcatalog" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.foo-add-prefix.addprefix.prefix": "/foo", | ||||
|   "traefik.http.routers.router1.middlewares": "foo-add-prefix@marathon" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # As a Rancher Label | ||||
| labels: | ||||
|   # Create a middleware named `foo-add-prefix` | ||||
|   - "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo" | ||||
|   # Apply the middleware named `foo-add-prefix` to the router named `router1` | ||||
|   - "traefik.http.routers.router1.middlewares=foo-add-prefix@rancher" | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| # As TOML Configuration File | ||||
| [http.routers] | ||||
| @@ -137,7 +113,7 @@ http: | ||||
| | [Errors](errorpages.md)                   | Defines custom error pages                        | Request Lifecycle           | | ||||
| | [ForwardAuth](forwardauth.md)             | Delegates Authentication                          | Security, Authentication    | | ||||
| | [Headers](headers.md)                     | Adds / Updates headers                            | Security                    | | ||||
| | [IPWhiteList](ipwhitelist.md)             | Limits the allowed client IPs                     | Security, Request lifecycle | | ||||
| | [IPAllowList](ipallowlist.md)             | Limits the allowed client IPs                     | Security, Request lifecycle | | ||||
| | [InFlightReq](inflightreq.md)             | Limits the number of simultaneous connections     | Security, Request lifecycle | | ||||
| | [PassTLSClientCert](passtlsclientcert.md) | Adds Client Certificates in a Header              | Security                    | | ||||
| | [RateLimit](ratelimit.md)                 | Limits the call frequency                         | Security, Request lifecycle | | ||||
| @@ -148,3 +124,9 @@ http: | ||||
| | [Retry](retry.md)                         | Automatically retries in case of error            | Request lifecycle           | | ||||
| | [StripPrefix](stripprefix.md)             | Changes the path of the request                   | Path Modifier               | | ||||
| | [StripPrefixRegex](stripprefixregex.md)   | Changes the path of the request                   | Path Modifier               | | ||||
|  | ||||
| ## Community Middlewares | ||||
|  | ||||
| Please take a look at the community-contributed plugins in the [plugin catalog](https://plugins.traefik.io/plugins). | ||||
|  | ||||
| {!traefik-for-business-applications.md!} | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik PassTLSClientCert Documentation" | ||||
| description: "In Traefik Proxy's HTTP middleware, the PassTLSClientCert adds selected data from passed client TLS certificates to headers. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # PassTLSClientCert | ||||
|  | ||||
| Adding Client Certificates in a Header | ||||
| @@ -11,16 +16,16 @@ PassTLSClientCert adds the selected data from the passed client TLS certificate | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header. | ||||
| Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| # Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header. | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-passtlsclientcert | ||||
| @@ -30,24 +35,12 @@ spec: | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header | ||||
| # Pass the pem in the `X-Forwarded-Tls-Client-Cert` header | ||||
| - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header. | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header. | ||||
| # Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. | ||||
| http: | ||||
|   middlewares: | ||||
|     test-passtlsclientcert: | ||||
| @@ -56,15 +49,15 @@ http: | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| # Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header. | ||||
| # Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. | ||||
| [http.middlewares] | ||||
|   [http.middlewares.test-passtlsclientcert.passTLSClientCert] | ||||
|     pem = true | ||||
| ``` | ||||
|  | ||||
| ??? example "Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header" | ||||
| ??? example "Pass the pem in the `X-Forwarded-Tls-Client-Cert` header" | ||||
|  | ||||
|     ```yaml tab="Docker" | ||||
|     ```yaml tab="Docker & Swarm" | ||||
|     # Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header | ||||
|     labels: | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter=true" | ||||
| @@ -76,6 +69,7 @@ http: | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organizationalunit=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname=true" | ||||
| @@ -89,7 +83,7 @@ http: | ||||
|  | ||||
|     ```yaml tab="Kubernetes" | ||||
|     # Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header | ||||
|     apiVersion: traefik.containo.us/v1alpha1 | ||||
|     apiVersion: traefik.io/v1alpha1 | ||||
|     kind: Middleware | ||||
|     metadata: | ||||
|       name: test-passtlsclientcert | ||||
| @@ -104,6 +98,7 @@ http: | ||||
|             province: true | ||||
|             locality: true | ||||
|             organization: true | ||||
|             organizationalUnit: true | ||||
|             commonName: true | ||||
|             serialNumber: true | ||||
|             domainComponent: true | ||||
| @@ -127,6 +122,7 @@ http: | ||||
|     - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true" | ||||
|     - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality=true" | ||||
|     - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization=true" | ||||
|     - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organizationalunit=true" | ||||
|     - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province=true" | ||||
|     - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber=true" | ||||
|     - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname=true" | ||||
| @@ -138,50 +134,6 @@ http: | ||||
|     - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber=true" | ||||
|     ``` | ||||
|  | ||||
|     ```json tab="Marathon" | ||||
|     "labels": { | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.country": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.domaincomponent": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.locality": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.organization": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.province": "true", | ||||
|       "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber": "true" | ||||
|     } | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="Rancher" | ||||
|     # Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header | ||||
|     labels: | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.country=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.domaincomponent=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.locality=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.organization=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.province=true" | ||||
|       - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber=true" | ||||
|     ``` | ||||
|  | ||||
|     ```yaml tab="File (YAML)" | ||||
|     # Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header | ||||
|     http: | ||||
| @@ -197,6 +149,7 @@ http: | ||||
|                 province: true | ||||
|                 locality: true | ||||
|                 organization: true | ||||
|                 organizationalUnit: true | ||||
|                 commonName: true | ||||
|                 serialNumber: true | ||||
|                 domainComponent: true | ||||
| @@ -223,6 +176,7 @@ http: | ||||
|             province = true | ||||
|             locality = true | ||||
|             organization = true | ||||
|             organizationalUnit = true | ||||
|             commonName = true | ||||
|             serialNumber = true | ||||
|             domainComponent = true | ||||
| @@ -242,12 +196,12 @@ http: | ||||
|  | ||||
| PassTLSClientCert can add two headers to the request: | ||||
|  | ||||
| - `X-Forwarded-Tls-Client-Cert` that contains the escaped pem. | ||||
| - `X-Forwarded-Tls-Client-Cert` that contains the pem. | ||||
| - `X-Forwarded-Tls-Client-Cert-Info` that contains all the selected certificate information in an escaped string. | ||||
|  | ||||
| !!! info | ||||
|  | ||||
|     * The headers are filled with escaped string so it can be safely placed inside a URL query. | ||||
|     * `X-Forwarded-Tls-Client-Cert-Info` header value is a string that has been escaped in order to be a valid URL query. | ||||
|     * These options only work accordingly to the [MutualTLS configuration](../../https/tls.md#client-authentication-mtls). | ||||
|     That is to say, only the certificates that match the `clientAuth.clientAuthType` policy are passed. | ||||
|  | ||||
| @@ -359,7 +313,7 @@ The following example shows a complete certificate and explains each of the midd | ||||
|  | ||||
| ### `pem` | ||||
|  | ||||
| The `pem` option sets the `X-Forwarded-Tls-Client-Cert` header with the escaped certificate. | ||||
| The `pem` option sets the `X-Forwarded-Tls-Client-Cert` header with the certificate. | ||||
|  | ||||
| In the example, it is the part between `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----` delimiters: | ||||
|  | ||||
| @@ -412,15 +366,18 @@ In the example, it is the part between `-----BEGIN CERTIFICATE-----` and `-----E | ||||
| !!! warning "`X-Forwarded-Tls-Client-Cert` value could exceed the web server header size limit" | ||||
|  | ||||
|     The header size limit of web servers is commonly between 4kb and 8kb. | ||||
|     You could change the server configuration to allow bigger header or use the `info` option with the needed field(s). | ||||
|     If that turns out to be a problem, and if reconfiguring the server to allow larger headers is not an option, | ||||
|     one can alleviate the problem by selecting only the interesting parts of the cert, | ||||
|     through the use of the `info` options described below. (And by setting `pem` to false). | ||||
|  | ||||
| ### `info` | ||||
|  | ||||
| The `info` option selects the specific client certificate details you want to add to the `X-Forwarded-Tls-Client-Cert-Info` header. | ||||
|  | ||||
| The value of the header is an escaped concatenation of all the selected certificate details. | ||||
| But in the following, unless specified otherwise, all the header values examples are shown unescaped, for readability. | ||||
|  | ||||
| The following example shows an unescaped result that uses all the available fields: | ||||
| The following example shows such a concatenation, when all the available fields are selected: | ||||
|  | ||||
| ```text | ||||
| 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=*.example.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="*.example.org,*.example.net,*.example.com,test@example.org,test@example.net,10.0.1.0,10.0.1.2" | ||||
| @@ -430,6 +387,23 @@ Subject="DC=org,DC=cheese,C=FR,C=US,ST=Cheese org state,ST=Cheese com state,L=TO | ||||
|  | ||||
|     If there are more than one certificate, they are separated by a `,`. | ||||
|  | ||||
| #### `info.serialNumber` | ||||
|  | ||||
| Set the `info.serialNumber` option to `true` to add the `Serial Number` of the certificate. | ||||
|  | ||||
| The data is taken from the following certificate part: | ||||
|  | ||||
| ```text | ||||
| Serial Number: | ||||
|    6a:2f:20:f8:ce:8d:48:52:ba:d9:bb:be:60:ec:bf:79 | ||||
| ``` | ||||
|  | ||||
| And it is formatted as follows in the header (decimal representation): | ||||
|  | ||||
| ```text | ||||
| SerialNumber="141142874255168551917600297745052909433" | ||||
| ``` | ||||
|  | ||||
| #### `info.notAfter` | ||||
|  | ||||
| Set the `info.notAfter` option to `true` to add the `Not After` information from the `Validity` part. | ||||
| @@ -437,11 +411,11 @@ Set the `info.notAfter` option to `true` to add the `Not After` information from | ||||
| The data is taken from the following certificate part: | ||||
|  | ||||
| ```text | ||||
|     Validity | ||||
|         Not After : Dec  5 11:10:16 2020 GMT | ||||
| Validity | ||||
|     Not After : Dec  5 11:10:16 2020 GMT | ||||
| ``` | ||||
|  | ||||
| The escaped `notAfter` info part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| NA="1607166616" | ||||
| @@ -458,7 +432,7 @@ Validity | ||||
|     Not Before: Dec  6 11:10:16 2018 GMT | ||||
| ``` | ||||
|  | ||||
| The escaped `notBefore` info part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| NB="1544094616" | ||||
| @@ -471,11 +445,11 @@ Set the `info.sans` option to `true` to add the `Subject Alternative Name` infor | ||||
| The data is taken from the following certificate part: | ||||
|  | ||||
| ```text | ||||
|  X509v3 Subject Alternative Name: | ||||
|     DNS:*.example.org, DNS:*.example.net, DNS:*.example.com, IP Address:10.0.1.0, IP Address:10.0.1.2, email:test@example.org, email:test@example.net | ||||
| X509v3 Subject Alternative Name: | ||||
|    DNS:*.example.org, DNS:*.example.net, DNS:*.example.com, IP Address:10.0.1.0, IP Address:10.0.1.2, email:test@example.org, email:test@example.net | ||||
| ``` | ||||
|  | ||||
| The escape SANs info part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| SAN="*.example.org,*.example.net,*.example.com,test@example.org,test@example.net,10.0.1.0,10.0.1.2" | ||||
| @@ -501,7 +475,7 @@ Set the `info.subject.country` option to `true` to add the `country` information | ||||
|  | ||||
| The data is taken from the subject part with the `C` key. | ||||
|  | ||||
| The escape country info in the subject part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| C=FR,C=US | ||||
| @@ -513,7 +487,7 @@ Set the `info.subject.province` option to `true` to add the `province` informati | ||||
|  | ||||
| The data is taken from the subject part with the `ST` key. | ||||
|  | ||||
| The escape province info in the subject part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| ST=Cheese org state,ST=Cheese com state | ||||
| @@ -525,7 +499,7 @@ Set the `info.subject.locality` option to `true` to add the `locality` informati | ||||
|  | ||||
| The data is taken from the subject part with the `L` key. | ||||
|  | ||||
| The escape locality info in the subject part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| L=TOULOUSE,L=LYON | ||||
| @@ -537,19 +511,31 @@ Set the `info.subject.organization` option to `true` to add the `organization` i | ||||
|  | ||||
| The data is taken from the subject part with the `O` key. | ||||
|  | ||||
| The escape organization info in the subject part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| O=Cheese,O=Cheese 2 | ||||
| ``` | ||||
|  | ||||
| ##### `info.subject.organizationalUnit` | ||||
|  | ||||
| Set the `info.subject.organizationalUnit` option to `true` to add the `organizationalUnit` information into the subject. | ||||
|  | ||||
| The data is taken from the subject part with the `OU` key. | ||||
|  | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| OU=Cheese Section,OU=Cheese Section 2 | ||||
| ``` | ||||
|  | ||||
| ##### `info.subject.commonName` | ||||
|  | ||||
| Set the `info.subject.commonName` option to `true` to add the `commonName` information into the subject. | ||||
|  | ||||
| The data is taken from the subject part with the `CN` key. | ||||
|  | ||||
| The escape common name info in the subject part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| CN=*.example.com | ||||
| @@ -561,7 +547,7 @@ Set the `info.subject.serialNumber` option to `true` to add the `serialNumber` i | ||||
|  | ||||
| The data is taken from the subject part with the `SN` key. | ||||
|  | ||||
| The escape serial number info in the subject part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| SN=1234567890 | ||||
| @@ -573,7 +559,7 @@ Set the `info.subject.domainComponent` option to `true` to add the `domainCompon | ||||
|  | ||||
| The data is taken from the subject part with the `DC` key. | ||||
|  | ||||
| The escape domain component info in the subject part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| DC=org,DC=cheese | ||||
| @@ -595,7 +581,7 @@ Set the `info.issuer.country` option to `true` to add the `country` information | ||||
|  | ||||
| The data is taken from the issuer part with the `C` key. | ||||
|  | ||||
| The escape country info in the issuer part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| C=FR,C=US | ||||
| @@ -607,7 +593,7 @@ Set the `info.issuer.province` option to `true` to add the `province` informatio | ||||
|  | ||||
| The data is taken from the issuer part with the `ST` key. | ||||
|  | ||||
| The escape province info in the issuer part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| ST=Signing State,ST=Signing State 2 | ||||
| @@ -619,7 +605,7 @@ Set the `info.issuer.locality` option to `true` to add the `locality` informatio | ||||
|  | ||||
| The data is taken from the issuer part with the `L` key. | ||||
|  | ||||
| The escape locality info in the issuer part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| L=TOULOUSE,L=LYON | ||||
| @@ -631,7 +617,7 @@ Set the `info.issuer.organization` option to `true` to add the `organization` in | ||||
|  | ||||
| The data is taken from the issuer part with the `O` key. | ||||
|  | ||||
| The escape organization info in the issuer part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| O=Cheese,O=Cheese 2 | ||||
| @@ -643,7 +629,7 @@ Set the `info.issuer.commonName` option to `true` to add the `commonName` inform | ||||
|  | ||||
| The data is taken from the issuer part with the `CN` key. | ||||
|  | ||||
| The escape common name info in the issuer part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| CN=Simple Signing CA 2 | ||||
| @@ -655,7 +641,7 @@ Set the `info.issuer.serialNumber` option to `true` to add the `serialNumber` in | ||||
|  | ||||
| The data is taken from the issuer part with the `SN` key. | ||||
|  | ||||
| The escape serial number info in the issuer part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| SN=1234567890 | ||||
| @@ -667,7 +653,7 @@ Set the `info.issuer.domainComponent` option to `true` to add the `domainCompone | ||||
|  | ||||
| The data is taken from the issuer part with the `DC` key. | ||||
|  | ||||
| The escape domain component info in the issuer part is formatted as below: | ||||
| And it is formatted as follows in the header: | ||||
|  | ||||
| ```text | ||||
| DC=org,DC=cheese | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik RateLimit Documentation" | ||||
| description: "Traefik Proxy's HTTP RateLimit middleware ensures Services receive fair amounts of requests. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # RateLimit | ||||
|  | ||||
| To Control the Number of Requests Going to a Service | ||||
| @@ -5,9 +10,11 @@ To Control the Number of Requests Going to a Service | ||||
|  | ||||
| The RateLimit middleware ensures that services will receive a _fair_ amount of requests, and allows one to define what fair is. | ||||
|  | ||||
| It is based on a [token bucket](https://en.wikipedia.org/wiki/Token_bucket) implementation. In this analogy, the [average](#average) parameter (defined below) is the rate at which the bucket refills, and the [burst](#burst) is the size (volume) of the bucket. | ||||
|  | ||||
| ## Configuration Example | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Here, an average of 100 requests per second is allowed. | ||||
| # In addition, a burst of 50 requests is allowed. | ||||
| labels: | ||||
| @@ -18,7 +25,7 @@ labels: | ||||
| ```yaml tab="Kubernetes" | ||||
| # Here, an average of 100 requests per second is allowed. | ||||
| # In addition, a burst of 50 requests is allowed. | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-ratelimit | ||||
| @@ -35,21 +42,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=50" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.average": "100", | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.burst": "50" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Here, an average of 100 requests per second is allowed. | ||||
| # In addition, a burst of 50 requests is allowed. | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=50" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Here, an average of 100 requests per second is allowed. | ||||
| # In addition, a burst of 50 requests is allowed. | ||||
| @@ -81,7 +73,7 @@ It defaults to `0`, which means no rate limiting. | ||||
| The rate is actually defined by dividing `average` by `period`. | ||||
| So for a rate below 1 req/s, one needs to define a `period` larger than a second. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # 100 reqs/s | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" | ||||
| @@ -89,7 +81,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # 100 reqs/s | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-ratelimit | ||||
| @@ -103,17 +95,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.average": "100", | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # 100 reqs/s | ||||
| http: | ||||
| @@ -140,7 +121,7 @@ r = average / period | ||||
|  | ||||
| It defaults to `1` second. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # 6 reqs/minute | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.average=6" | ||||
| @@ -149,7 +130,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # 6 reqs/minute | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-ratelimit | ||||
| @@ -165,20 +146,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.period=1m" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.average": "6", | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.period": "1m", | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # 6 reqs/minute | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.average=6" | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.period=1m" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # 6 reqs/minute | ||||
| http: | ||||
| @@ -203,13 +170,13 @@ http: | ||||
|  | ||||
| It defaults to `1`. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=100" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-ratelimit | ||||
| @@ -222,17 +189,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=100" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.burst": "100", | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=100" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -257,6 +213,8 @@ If none are set, the default is to use the request's remote address field (as an | ||||
|  | ||||
| The `ipStrategy` option defines two parameters that configures how Traefik determines the client IP: `depth`, and `excludedIPs`. | ||||
|  | ||||
| !!! important "As a middleware, rate-limiting happens before the actual proxying to the backend takes place. In addition, the previous network hop only gets appended to `X-Forwarded-For` during the last stages of proxying, i.e. after it has already passed through rate-limiting. Therefore, during rate-limiting, as the previous network hop is not yet present in `X-Forwarded-For`, it cannot be found and/or relied upon." | ||||
|  | ||||
| ##### `ipStrategy.depth` | ||||
|  | ||||
| The `depth` option tells Traefik to use the `X-Forwarded-For` header and select the IP located at the `depth` position (starting from the right). | ||||
| @@ -274,13 +232,13 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and select | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `3`     | `"11.0.0.1"` | | ||||
|     | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `5`     | `""`         | | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth=2" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-ratelimit | ||||
| @@ -295,17 +253,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth=2" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth": "2" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth=2" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -366,13 +313,13 @@ and the first IP that is _not_ in the pool (if any) is returned. | ||||
|     | `"10.0.0.1,11.0.0.1,13.0.0.1"` | `"15.0.0.1,16.0.0.1"` | `"13.0.0.1"` | | ||||
|     | `"10.0.0.1,11.0.0.1"`          | `"10.0.0.1,11.0.0.1"` | `""`         | | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-ratelimit | ||||
| @@ -389,17 +336,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -423,13 +359,13 @@ http: | ||||
|  | ||||
| Name of the header used to group incoming requests. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername=username" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-ratelimit | ||||
| @@ -443,17 +379,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername=username" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername": "username" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername=username" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
| @@ -474,13 +399,13 @@ http: | ||||
|  | ||||
| Whether to consider the request host as the source. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-ratelimit | ||||
| @@ -494,17 +419,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik RedirectRegex Documentation" | ||||
| description: "In Traefik Proxy's HTTP middleware, RedirectRegex redirecting clients to different locations. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # RedirectRegex | ||||
|  | ||||
| Redirecting the Client to a Different Location | ||||
| @@ -11,7 +16,7 @@ The RedirectRegex redirects a request using regex matching and replacement. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Redirect with domain replacement | ||||
| # Note: all dollar signs need to be doubled for escaping. | ||||
| labels: | ||||
| @@ -21,7 +26,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Redirect with domain replacement | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-redirectregex | ||||
| @@ -38,21 +43,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$${1}" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-redirectregex.redirectregex.regex": "^http://localhost/(.*)", | ||||
|   "traefik.http.middlewares.test-redirectregex.redirectregex.replacement": "http://mydomain/${1}" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Redirect with domain replacement | ||||
| # Note: all dollar signs need to be doubled for escaping. | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-redirectregex.redirectregex.regex=^http://localhost/(.*)" | ||||
|   - "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$${1}" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Redirect with domain replacement | ||||
| http: | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik RedirectScheme Documentation" | ||||
| description: "In Traefik Proxy's HTTP middleware, RedirectScheme redirects clients to different schemes/ports. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # RedirectScheme | ||||
|  | ||||
| Redirecting the Client to a Different Scheme/Port | ||||
| @@ -7,11 +12,20 @@ Redirecting the Client to a Different Scheme/Port | ||||
| TODO: add schema | ||||
| --> | ||||
|  | ||||
| RedirectScheme redirects requests from a scheme/port to another. | ||||
| The RedirectScheme middleware redirects the request if the request scheme is different from the configured scheme. | ||||
|  | ||||
| !!! warning "When behind another reverse-proxy" | ||||
|  | ||||
|     When there is at least one other reverse-proxy between the client and Traefik,  | ||||
|     the other reverse-proxy (i.e. the last hop) needs to be a [trusted](../../routing/entrypoints.md#forwarded-headers) one.  | ||||
|      | ||||
|     Otherwise, Traefik would clean up the X-Forwarded headers coming from this last hop,  | ||||
|     and as the RedirectScheme middleware relies on them to determine the scheme used, | ||||
|     it would not function as intended. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" | ||||
| @@ -20,7 +34,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Redirect to https | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-redirectscheme | ||||
| @@ -37,20 +51,6 @@ labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme": "https" | ||||
|   "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Redirect to https | ||||
| http: | ||||
| @@ -75,7 +75,7 @@ http: | ||||
|  | ||||
| Set the `permanent` option to `true` to apply a permanent redirection. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   # ... | ||||
| @@ -84,7 +84,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Redirect to https | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-redirectscheme | ||||
| @@ -101,20 +101,6 @@ labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|  | ||||
|   "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent": "true" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   # ... | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Redirect to https | ||||
| http: | ||||
| @@ -137,7 +123,7 @@ http: | ||||
|  | ||||
| The `scheme` option defines the scheme of the new URL. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" | ||||
| @@ -145,7 +131,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Redirect to https | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-redirectscheme | ||||
| @@ -160,18 +146,6 @@ labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme": "https" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Redirect to https | ||||
| http: | ||||
| @@ -192,7 +166,7 @@ http: | ||||
|  | ||||
| The `port` option defines the port of the new URL. | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   # ... | ||||
| @@ -201,7 +175,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Redirect to https | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-redirectscheme | ||||
| @@ -218,20 +192,6 @@ labels: | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|  | ||||
|   "traefik.http.middlewares.test-redirectscheme.redirectscheme.port": "443" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Redirect to https | ||||
| labels: | ||||
|   # ... | ||||
|   - "traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Redirect to https | ||||
| http: | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik ReplacePath Documentation" | ||||
| description: "In Traefik Proxy's HTTP middleware, ReplacePath updates paths before forwarding requests. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # ReplacePath | ||||
|  | ||||
| Updating the Path Before Forwarding the Request | ||||
| @@ -11,7 +16,7 @@ Replace the path of the request URL. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Replace the path with /foo | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-replacepath.replacepath.path=/foo" | ||||
| @@ -19,7 +24,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Replace the path with /foo | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-replacepath | ||||
| @@ -33,18 +38,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-replacepath.replacepath.path=/foo" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-replacepath.replacepath.path": "/foo" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Replace the path with /foo | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-replacepath.replacepath.path=/foo" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Replace the path with /foo | ||||
| http: | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik ReplacePathRegex Documentation" | ||||
| description: "In Traefik Proxy's HTTP middleware, ReplacePathRegex updates paths before forwarding requests, using a regex. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # ReplacePathRegex | ||||
|  | ||||
| Updating the Path Before Forwarding the Request (Using a Regex) | ||||
| @@ -11,7 +16,7 @@ The ReplaceRegex replaces the path of a URL using regex matching and replacement | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Replace path with regex | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-replacepathregex.replacepathregex.regex=^/foo/(.*)" | ||||
| @@ -20,7 +25,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Replace path with regex | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-replacepathregex | ||||
| @@ -36,20 +41,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement=/bar/$1" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-replacepathregex.replacepathregex.regex": "^/foo/(.*)", | ||||
|   "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement": "/bar/$1" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Replace path with regex | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-replacepathregex.replacepathregex.regex=^/foo/(.*)" | ||||
|   - "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement=/bar/$1" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Replace path with regex | ||||
| http: | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik HTTP Retry Documentation" | ||||
| description: "Configure Traefik Proxy's HTTP Retry middleware, so you can retry requests to a backend server until it succeeds. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # Retry | ||||
|  | ||||
| Retrying until it Succeeds | ||||
| @@ -13,7 +18,7 @@ The Retry middleware has an optional configuration to enable an exponential back | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Retry 4 times with exponential backoff | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-retry.retry.attempts=4" | ||||
| @@ -22,7 +27,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Retry 4 times with exponential backoff | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-retry | ||||
| @@ -38,20 +43,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-retry.retry.initialinterval=100ms" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-retry.retry.attempts": "4", | ||||
|   "traefik.http.middlewares.test-retry.retry.initialinterval": "100ms", | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Retry 4 times with exponential backoff | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-retry.retry.attempts=4" | ||||
|   - "traefik.http.middlewares.test-retry.retry.initialinterval=100ms" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Retry 4 times with exponential backoff | ||||
| http: | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik StripPrefix Documentation" | ||||
| description: "In Traefik Proxy's HTTP middleware, StripPrefix removes prefixes from paths before forwarding requests. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # StripPrefix | ||||
|  | ||||
| Removing Prefixes From the Path Before Forwarding the Request | ||||
| @@ -11,7 +16,7 @@ Remove the specified prefixes from the URL path. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # Strip prefix /foobar and /fiibar | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar" | ||||
| @@ -19,7 +24,7 @@ labels: | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| # Strip prefix /foobar and /fiibar | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-stripprefix | ||||
| @@ -35,18 +40,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes": "/foobar,/fiibar" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # Strip prefix /foobar and /fiibar | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Strip prefix /foobar and /fiibar | ||||
| http: | ||||
| @@ -82,86 +75,4 @@ The `prefixes` option defines the prefixes to strip from the request URL. | ||||
| For instance, `/products` also matches `/products/shoes` and `/products/shirts`. | ||||
|  | ||||
| If your backend is serving assets (e.g., images or JavaScript files), it can use the `X-Forwarded-Prefix` header to properly construct relative URLs. | ||||
| Using the previous example, the backend should return `/products/shoes/image.png` (and not `/images.png`, which Traefik would likely not be able to associate with the same backend). | ||||
|  | ||||
| ### `forceSlash` | ||||
|  | ||||
| _Optional, Default=true_ | ||||
|  | ||||
| The `forceSlash` option ensures the resulting stripped path is not the empty string, by replacing it with `/` when necessary. | ||||
|  | ||||
| This option was added to keep the initial (non-intuitive) behavior of this middleware, in order to avoid introducing a breaking change. | ||||
|  | ||||
| It is recommended to explicitly set `forceSlash` to `false`. | ||||
|  | ||||
| ??? info "Behavior examples" | ||||
|  | ||||
|     - `forceSlash=true` | ||||
|  | ||||
|     | Path       | Prefix to strip | Result | | ||||
|     |------------|-----------------|--------| | ||||
|     | `/`        | `/`             | `/`    | | ||||
|     | `/foo`     | `/foo`          | `/`    | | ||||
|     | `/foo/`    | `/foo`          | `/`    | | ||||
|     | `/foo/`    | `/foo/`         | `/`    | | ||||
|     | `/bar`     | `/foo`          | `/bar` | | ||||
|     | `/foo/bar` | `/foo`          | `/bar` | | ||||
|  | ||||
|     - `forceSlash=false` | ||||
|  | ||||
|     | Path       | Prefix to strip | Result | | ||||
|     |------------|-----------------|--------| | ||||
|     | `/`        | `/`             | empty  | | ||||
|     | `/foo`     | `/foo`          | empty  | | ||||
|     | `/foo/`    | `/foo`          | `/`    | | ||||
|     | `/foo/`    | `/foo/`         | empty  | | ||||
|     | `/bar`     | `/foo`          | `/bar` | | ||||
|     | `/foo/bar` | `/foo`          | `/bar` | | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.example.stripprefix.prefixes=/foobar" | ||||
|   - "traefik.http.middlewares.example.stripprefix.forceSlash=false" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: example | ||||
| spec: | ||||
|   stripPrefix: | ||||
|     prefixes: | ||||
|       - "/foobar" | ||||
|     forceSlash: false | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.example.stripprefix.prefixes": "/foobar", | ||||
|   "traefik.http.middlewares.example.stripprefix.forceSlash": "false" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.example.stripprefix.prefixes=/foobar" | ||||
|   - "traefik.http.middlewares.example.stripprefix.forceSlash=false" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|     example: | ||||
|       stripPrefix: | ||||
|         prefixes: | ||||
|           - "/foobar" | ||||
|         forceSlash: false | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| [http.middlewares] | ||||
|   [http.middlewares.example.stripPrefix] | ||||
|     prefixes = ["/foobar"] | ||||
|     forceSlash = false | ||||
| ``` | ||||
| Using the previous example, the backend should return `/products/shoes/image.png` (and not `/image.png`, which Traefik would likely not be able to associate with the same backend). | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik StripPrefixRegex Documentation" | ||||
| description: "In Traefik Proxy's HTTP middleware, StripPrefixRegex removes prefixes from paths before forwarding requests, using regex. Read the technical documentation." | ||||
| --- | ||||
|  | ||||
| # StripPrefixRegex | ||||
|  | ||||
| Removing Prefixes From the Path Before Forwarding the Request (Using a Regex) | ||||
| @@ -7,13 +12,13 @@ Remove the matching prefixes from the URL path. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: test-stripprefixregex | ||||
| @@ -27,17 +32,6 @@ spec: | ||||
| - "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex": "/foo/[a-z0-9]+/[0-9]+/" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| labels: | ||||
|   - "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| http: | ||||
|   middlewares: | ||||
|   | ||||
| @@ -1,3 +1,8 @@ | ||||
| --- | ||||
| title: "Traefik Proxy Middleware Overview" | ||||
| description: "There are several available middleware in Traefik Proxy used to modify requests or headers, take charge of redirections, add authentication, and so on." | ||||
| --- | ||||
|  | ||||
| # Middlewares | ||||
|  | ||||
| Tweaking the Request | ||||
| @@ -18,7 +23,7 @@ Middlewares that use the same protocol can be combined into chains to fit every | ||||
|  | ||||
| ## Configuration Example | ||||
|  | ||||
| ```yaml tab="Docker" | ||||
| ```yaml tab="Docker & Swarm" | ||||
| # As a Docker Label | ||||
| whoami: | ||||
|   #  A container that exposes an API to show its IP address | ||||
| @@ -32,7 +37,7 @@ whoami: | ||||
|  | ||||
| ```yaml tab="Kubernetes IngressRoute" | ||||
| --- | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: Middleware | ||||
| metadata: | ||||
|   name: stripprefix | ||||
| @@ -42,7 +47,7 @@ spec: | ||||
|       - /stripit | ||||
|  | ||||
| --- | ||||
| apiVersion: traefik.containo.us/v1alpha1 | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: IngressRoute | ||||
| metadata: | ||||
|   name: ingressroute | ||||
| @@ -61,22 +66,6 @@ spec: | ||||
| - "traefik.http.routers.router1.middlewares=foo-add-prefix@consulcatalog" | ||||
| ``` | ||||
|  | ||||
| ```json tab="Marathon" | ||||
| "labels": { | ||||
|   "traefik.http.middlewares.foo-add-prefix.addprefix.prefix": "/foo", | ||||
|   "traefik.http.routers.router1.middlewares": "foo-add-prefix@marathon" | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Rancher" | ||||
| # As a Rancher Label | ||||
| labels: | ||||
|   # Create a middleware named `foo-add-prefix` | ||||
|   - "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo" | ||||
|   # Apply the middleware named `foo-add-prefix` to the router named `router1` | ||||
|   - "traefik.http.routers.router1.middlewares=foo-add-prefix@rancher" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # As YAML Configuration File | ||||
| http: | ||||
| @@ -124,3 +113,5 @@ http: | ||||
| A list of HTTP middlewares can be found [here](http/overview.md). | ||||
|  | ||||
| A list of TCP middlewares can be found [here](tcp/overview.md). | ||||
|  | ||||
| {!traefik-for-business-applications.md!} | ||||
|   | ||||
							
								
								
									
										51
									
								
								docs/content/middlewares/tcp/inflightconn.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								docs/content/middlewares/tcp/inflightconn.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| # InFlightConn | ||||
|  | ||||
| Limiting the Number of Simultaneous connections. | ||||
| {: .subtitle } | ||||
|  | ||||
| To proactively prevent services from being overwhelmed with high load, the number of allowed simultaneous connections by IP can be limited. | ||||
|  | ||||
| ## Configuration Examples | ||||
|  | ||||
| ```yaml tab="Docker & Swarm" | ||||
| labels: | ||||
|   - "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Kubernetes" | ||||
| apiVersion: traefik.io/v1alpha1 | ||||
| kind: MiddlewareTCP | ||||
| metadata: | ||||
|   name: test-inflightconn | ||||
| spec: | ||||
|   inFlightConn: | ||||
|     amount: 10 | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="Consul Catalog" | ||||
| # Limiting to 10 simultaneous connections | ||||
| - "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10" | ||||
| ``` | ||||
|  | ||||
| ```yaml tab="File (YAML)" | ||||
| # Limiting to 10 simultaneous connections. | ||||
| tcp: | ||||
|   middlewares: | ||||
|     test-inflightconn: | ||||
|       inFlightConn: | ||||
|         amount: 10 | ||||
| ``` | ||||
|  | ||||
| ```toml tab="File (TOML)" | ||||
| # Limiting to 10 simultaneous connections | ||||
| [tcp.middlewares] | ||||
|   [tcp.middlewares.test-inflightconn.inFlightConn] | ||||
|     amount = 10 | ||||
| ``` | ||||
|  | ||||
| ## Configuration Options | ||||
|  | ||||
| ### `amount` | ||||
|  | ||||
| The `amount` option defines the maximum amount of allowed simultaneous connections. | ||||
| The middleware closes the connection if there are already `amount` connections opened. | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user