mirror of
https://github.com/containous/traefik.git
synced 2025-09-03 21:44:30 +03:00
Compare commits
825 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d42e75bb2e | ||
|
8d016f5e16 | ||
|
927f0bc01a | ||
|
900784a95a | ||
|
98c624bf1a | ||
|
f3479f532b | ||
|
8946dd1898 | ||
|
12fae2ebb8 | ||
|
0a7a6afd59 | ||
|
2090baa938 | ||
|
6f1bd54d86 | ||
|
2798e18e18 | ||
|
ec638a741e | ||
|
097e71ad24 | ||
|
eabcb3e1c0 | ||
|
53a8bd76f2 | ||
|
0e89c48e38 | ||
|
385ff5055c | ||
|
e322184a98 | ||
|
69424a16a5 | ||
|
f9f22b7b70 | ||
|
6706bb1612 | ||
|
8ea339816a | ||
|
00b1d8b0bc | ||
|
21c6edcf58 | ||
|
5c48e3c96c | ||
|
c23c3e0ed3 | ||
|
778dc22e14 | ||
|
cdf0c8b3ec | ||
|
359477c583 | ||
|
b368e71337 | ||
|
dc752c7847 | ||
|
6155c900be | ||
|
6ca4c5da5c | ||
|
e6b1b05fdf | ||
|
8cff718c53 | ||
|
bfda5e607f | ||
|
0f0cc420e1 | ||
|
9250b5937d | ||
|
4406c337d4 | ||
|
ed10bc5833 | ||
|
e33bd6874f | ||
|
05828bab07 | ||
|
736f37cb58 | ||
|
cff71ee496 | ||
|
f02b223639 | ||
|
d4d23dce72 | ||
|
5e4dc783c7 | ||
|
440cb11250 | ||
|
42920595ad | ||
|
e68e647fd9 | ||
|
8b558646fc | ||
|
f8e45a0b29 | ||
|
d65de8fe6c | ||
|
5f2c00b438 | ||
|
c2c1c3e09e | ||
|
d8a778b5cd | ||
|
d8cf90dade | ||
|
a4aad5ce5c | ||
|
15973f5503 | ||
|
a4150409c8 | ||
|
aee515b930 | ||
|
b0d19bd466 | ||
|
d99d2f95e6 | ||
|
8d2a2ff08f | ||
|
73e5dbbfe5 | ||
|
ee3e7cbbec | ||
|
f5d451d816 | ||
|
f84e00e481 | ||
|
fe0af1ec4b | ||
|
95312d5324 | ||
|
e3729ec600 | ||
|
20d6c19c30 | ||
|
7a7b03eb01 | ||
|
ea4f307fcd | ||
|
a6b00608d2 | ||
|
7b649e2f0c | ||
|
52e95deee3 | ||
|
70968bc6a9 | ||
|
da7bb5fc25 | ||
|
34bd611131 | ||
|
b9b7527762 | ||
|
240b83b773 | ||
|
584839e00b | ||
|
099c7e9444 | ||
|
83a5c5cfbd | ||
|
c1d9b9ee1f | ||
|
d53f5f01a0 | ||
|
4e11bf3c38 | ||
|
1a266c661a | ||
|
bda4f50eae | ||
|
19e6170fa5 | ||
|
0017471f0d | ||
|
76723b1288 | ||
|
cef842245c | ||
|
f69fd43122 | ||
|
e5062cef42 | ||
|
998c6174cd | ||
|
ac1753a614 | ||
|
d3516aec31 | ||
|
2c6418e17a | ||
|
fdf27eb644 | ||
|
945ff9b0f9 | ||
|
bbd5846c6a | ||
|
9f145dbc28 | ||
|
c84b510f0d | ||
|
2bc3fa7b4b | ||
|
fc897f6756 | ||
|
c31f5df854 | ||
|
b636b21167 | ||
|
167bdb0d53 | ||
|
7f29595c0a | ||
|
3fcf265d80 | ||
|
618fb5f232 | ||
|
d94e676083 | ||
|
141abce2d5 | ||
|
fc875b38e0 | ||
|
39fe3869b6 | ||
|
d582e01892 | ||
|
75790e0ab8 | ||
|
1391c35978 | ||
|
7bda07a422 | ||
|
9b6af61d1b | ||
|
5edac5eccd | ||
|
83e4abdb30 | ||
|
4e1e2f5ed0 | ||
|
c06629459d | ||
|
05be441027 | ||
|
6c9687f410 | ||
|
5cf1b95c29 | ||
|
74daa4cbb3 | ||
|
709ff6fb09 | ||
|
4fd5fca34f | ||
|
31a93d5045 | ||
|
4cb5825d11 | ||
|
15f50553e9 | ||
|
b4ca02da86 | ||
|
86be0a4e6f | ||
|
0e89a6bec7 | ||
|
c5808af4d9 | ||
|
935d251b21 | ||
|
3b851a5ef2 | ||
|
deab4dae8e | ||
|
f7edb394f2 | ||
|
baf687218c | ||
|
153765f99f | ||
|
5a2e233a15 | ||
|
453e21c7c9 | ||
|
8b759ab797 | ||
|
88a2020817 | ||
|
c3545c620b | ||
|
1034646ae2 | ||
|
538f780a85 | ||
|
b931c8ae9b | ||
|
c5c61dbade | ||
|
1e7dbc70a0 | ||
|
6a2db4e4e9 | ||
|
1ea98d3d31 | ||
|
014fdfc4ec | ||
|
b5ec787fb6 | ||
|
0c8778639a | ||
|
8f29398573 | ||
|
676de5fb68 | ||
|
efa6ca0fa1 | ||
|
bc84fdd006 | ||
|
d5cb9b50f4 | ||
|
e11ff98608 | ||
|
9df04df334 | ||
|
bb6cd581a6 | ||
|
8f9ad16f54 | ||
|
5d8b1949b7 | ||
|
d7ec0cedbf | ||
|
f1104ada65 | ||
|
3ba3ca6eb0 | ||
|
85039e0d54 | ||
|
9be523d772 | ||
|
8b77f0c2dd | ||
|
d02be003ab | ||
|
4d539273ad | ||
|
40de310927 | ||
|
18203f57d2 | ||
|
ef0e9c6f05 | ||
|
d37ea3e882 | ||
|
3174c69c66 | ||
|
f4f3dbe1f5 | ||
|
49f04f2772 | ||
|
03d2e35488 | ||
|
aece9a1051 | ||
|
547cd81599 | ||
|
b5251c6ac4 | ||
|
190b9b1afa | ||
|
9befe0dd51 | ||
|
683e2ee5c6 | ||
|
21da705ec9 | ||
|
a3ac456199 | ||
|
9843757834 | ||
|
f9831f5b1b | ||
|
177c4b0ed1 | ||
|
bab48bed22 | ||
|
6cb2ff2af9 | ||
|
5e0855ecc7 | ||
|
f57cee578f | ||
|
8da38ec0a5 | ||
|
a6d462f6e8 | ||
|
0eeb85d01d | ||
|
64ff214ff8 | ||
|
111f3716fa | ||
|
4e0a05406b | ||
|
39b0aa6650 | ||
|
319517adef | ||
|
7a315bb043 | ||
|
34d2a816c2 | ||
|
81ce45271d | ||
|
3a461d2f23 | ||
|
980dac4572 | ||
|
ff7966f9cd | ||
|
e78374aa29 | ||
|
3bbc560283 | ||
|
ccf3a9995a | ||
|
e522446909 | ||
|
fea94a3393 | ||
|
4ddef9830b | ||
|
45bb00be04 | ||
|
cd8d5b8f10 | ||
|
eff294829f | ||
|
a69c1ba3b7 | ||
|
9adf0fb638 | ||
|
56e2110dc5 | ||
|
5be13802dc | ||
|
7345afd8b6 | ||
|
a84d5c0ef1 | ||
|
2a9471d278 | ||
|
0042562678 | ||
|
74ab88d47e | ||
|
6df9578ace | ||
|
cd7d324295 | ||
|
0e92b02474 | ||
|
9662cdca64 | ||
|
3dfaa3d5fa | ||
|
60123a8f3f | ||
|
2a7b2ef772 | ||
|
d51a2ce487 | ||
|
0a79643001 | ||
|
e77a66c2ac | ||
|
6858dbdd07 | ||
|
b2bb96390a | ||
|
e29a142f6a | ||
|
dae0491b61 | ||
|
f4ddf25e41 | ||
|
35c704ace3 | ||
|
789046f162 | ||
|
186e3e1541 | ||
|
088fe3c270 | ||
|
553ef94047 | ||
|
12e50e20e6 | ||
|
cd326654a7 | ||
|
3de29433f8 | ||
|
84516f962d | ||
|
f92b03a44d | ||
|
085b70c94e | ||
|
0e66ed87f8 | ||
|
d141e4a1ed | ||
|
679975beec | ||
|
8faed97e74 | ||
|
0b4c582088 | ||
|
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 | ||
|
ba822acb23 | ||
|
f5dd233a3b |
@@ -1,5 +1,5 @@
|
||||
dist/
|
||||
!dist/traefik
|
||||
!dist/**/traefik
|
||||
site/
|
||||
vendor/
|
||||
.idea/
|
||||
|
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.6
|
||||
- for Traefik v2: use branch v2.11
|
||||
- for Traefik v3: use branch v3.0
|
||||
|
||||
Bug fixes:
|
||||
- for Traefik v1: use branch v1.7
|
||||
- for Traefik v2: use branch v2.6
|
||||
- for Traefik v2: use branch v2.11
|
||||
- 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/
|
||||
|
||||
|
55
.github/workflows/build.yaml
vendored
55
.github/workflows/build.yaml
vendored
@@ -6,28 +6,39 @@ on:
|
||||
- '*'
|
||||
|
||||
env:
|
||||
GO_VERSION: 1.17
|
||||
GO_VERSION: '1.22'
|
||||
CGO_ENABLED: 0
|
||||
PRE_TARGET: ""
|
||||
|
||||
jobs:
|
||||
|
||||
build-webui:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: webui/.nvmrc
|
||||
cache: yarn
|
||||
cache-dependency-path: webui/yarn.lock
|
||||
|
||||
- name: Build webui
|
||||
working-directory: ./webui
|
||||
run: |
|
||||
yarn install
|
||||
yarn build
|
||||
|
||||
- name: Package webui
|
||||
run: |
|
||||
make generate-webui
|
||||
tar czvf webui.tar.gz ./webui/static/
|
||||
|
||||
- name: Artifact webui
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: webui.tar.gz
|
||||
path: webui.tar.gz
|
||||
@@ -36,41 +47,25 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ ubuntu-20.04, macos-latest, windows-latest ]
|
||||
os: [ ubuntu-latest, macos-latest, windows-latest ]
|
||||
needs:
|
||||
- build-webui
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/go/src/github.com/traefik/traefik
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: go/src/github.com/traefik/traefik
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Go modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
~/.cache/go-build
|
||||
~/Library/Caches/go-build
|
||||
'%LocalAppData%\go-build'
|
||||
key: ${{ runner.os }}-build-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-build-go-
|
||||
|
||||
- name: Artifact webui
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: webui.tar.gz
|
||||
path: ${{ github.workspace }}/go/src/github.com/traefik/traefik
|
||||
|
||||
- name: Untar webui
|
||||
run: tar xvf webui.tar.gz
|
||||
|
8
.github/workflows/check_doc.yml
vendored
8
.github/workflows/check_doc.yml
vendored
@@ -9,13 +9,17 @@ jobs:
|
||||
|
||||
docs:
|
||||
name: Check, verify and build documentation
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- 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 }}
|
||||
|
70
.github/workflows/codeql.yml
vendored
Normal file
70
.github/workflows/codeql.yml
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
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@v4
|
||||
|
||||
- name: setup go
|
||||
uses: actions/setup-go@v5
|
||||
if: ${{ matrix.language == 'go' }}
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
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@v3
|
||||
|
||||
# ℹ️ 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@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
12
.github/workflows/documentation.yml
vendored
12
.github/workflows/documentation.yml
vendored
@@ -7,19 +7,19 @@ on:
|
||||
- v*
|
||||
|
||||
env:
|
||||
STRUCTOR_VERSION: v1.11.2
|
||||
STRUCTOR_VERSION: v1.13.2
|
||||
MIXTUS_VERSION: v0.4.1
|
||||
|
||||
jobs:
|
||||
|
||||
docs:
|
||||
name: Doc Process
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'traefik/traefik'
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -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 }}
|
||||
|
47
.github/workflows/experimental.yaml
vendored
47
.github/workflows/experimental.yaml
vendored
@@ -6,32 +6,63 @@ on:
|
||||
- master
|
||||
- v*
|
||||
|
||||
env:
|
||||
GO_VERSION: '1.22'
|
||||
CGO_ENABLED: 0
|
||||
|
||||
jobs:
|
||||
|
||||
experimental:
|
||||
if: github.repository == 'traefik/traefik'
|
||||
name: Build experimental image on branch
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
# https://github.com/marketplace/actions/checkout
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: webui/.nvmrc
|
||||
cache: yarn
|
||||
cache-dependency-path: webui/yarn.lock
|
||||
|
||||
- name: Build webui
|
||||
working-directory: ./webui
|
||||
run: |
|
||||
yarn install
|
||||
yarn build
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Build
|
||||
run: make generate binary
|
||||
|
||||
- name: Branch name
|
||||
run: echo ${GITHUB_REF##*/}
|
||||
|
||||
- name: Build docker experimental image
|
||||
run: docker build -t traefik/traefik:experimental-${GITHUB_REF##*/} -f exp.Dockerfile .
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Push to Docker Hub
|
||||
run: docker push traefik/traefik:experimental-${GITHUB_REF##*/}
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Build docker experimental image
|
||||
env:
|
||||
DOCKER_BUILDX_ARGS: "--push"
|
||||
run: |
|
||||
make multi-arch-image-experimental-${GITHUB_REF##*/}
|
||||
|
35
.github/workflows/test-conformance.yaml
vendored
Normal file
35
.github/workflows/test-conformance.yaml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
name: Test K8s Gateway API conformance
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
paths:
|
||||
- 'pkg/provider/kubernetes/gateway/**'
|
||||
- 'integration/k8s_conformance_test.go'
|
||||
|
||||
env:
|
||||
GO_VERSION: '1.22'
|
||||
CGO_ENABLED: 0
|
||||
|
||||
jobs:
|
||||
|
||||
test-conformance:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Avoid generating webui
|
||||
run: touch webui/static/index.html
|
||||
|
||||
- name: K8s Gateway API conformance test
|
||||
run: make test-gateway-api-conformance
|
72
.github/workflows/test-integration.yaml
vendored
Normal file
72
.github/workflows/test-integration.yaml
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
name: Test Integration
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
|
||||
env:
|
||||
GO_VERSION: '1.22'
|
||||
CGO_ENABLED: 0
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Avoid generating webui
|
||||
run: touch webui/static/index.html
|
||||
|
||||
- name: Build binary
|
||||
run: make binary
|
||||
|
||||
test-integration:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
parallel: [12]
|
||||
index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Avoid generating webui
|
||||
run: touch webui/static/index.html
|
||||
|
||||
- name: Build binary
|
||||
run: make binary
|
||||
|
||||
- name: Generate go test Slice
|
||||
id: test_split
|
||||
uses: hashicorp-forge/go-test-split-action@v1
|
||||
with:
|
||||
packages: ./integration
|
||||
total: ${{ matrix.parallel }}
|
||||
index: ${{ matrix.index }}
|
||||
|
||||
- name: Run Integration tests
|
||||
run: |
|
||||
TESTS=$(echo "${{ steps.test_split.outputs.run}}" | sed 's/\$/\$\$/g')
|
||||
TESTFLAGS="-run \"${TESTS}\"" make test-integration
|
54
.github/workflows/test-unit.yaml
vendored
54
.github/workflows/test-unit.yaml
vendored
@@ -6,41 +6,47 @@ on:
|
||||
- '*'
|
||||
|
||||
env:
|
||||
GO_VERSION: 1.17
|
||||
PRE_TARGET: ""
|
||||
GO_VERSION: '1.22'
|
||||
|
||||
jobs:
|
||||
|
||||
test-unit:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/go/src/github.com/traefik/traefik
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: go/src/github.com/traefik/traefik
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Go modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
~/.cache/go-build
|
||||
key: ${{ runner.os }}-test-unit-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-test-unit-go-
|
||||
|
||||
- name: Avoid generating webui
|
||||
run: mkdir -p webui/static && touch webui/static/index.html
|
||||
run: touch webui/static/index.html
|
||||
|
||||
- name: Tests
|
||||
run: make test-unit
|
||||
|
||||
test-ui-unit:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Node.js ${{ env.NODE_VERSION }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: webui/.nvmrc
|
||||
cache: 'yarn'
|
||||
cache-dependency-path: webui/yarn.lock
|
||||
|
||||
- name: UI unit tests
|
||||
run: |
|
||||
yarn --cwd webui install
|
||||
yarn --cwd webui test:unit:ci
|
||||
|
65
.github/workflows/validate.yaml
vendored
65
.github/workflows/validate.yaml
vendored
@@ -6,84 +6,55 @@ on:
|
||||
- '*'
|
||||
|
||||
env:
|
||||
GO_VERSION: 1.17
|
||||
GOLANGCI_LINT_VERSION: v1.43.0
|
||||
MISSSPELL_VERSION: v0.3.4
|
||||
PRE_TARGET: ""
|
||||
GO_VERSION: '1.22'
|
||||
GOLANGCI_LINT_VERSION: v1.59.0
|
||||
MISSSPELL_VERSION: v0.6.0
|
||||
|
||||
jobs:
|
||||
|
||||
validate:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/go/src/github.com/traefik/traefik
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: go/src/github.com/traefik/traefik
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Go modules
|
||||
uses: actions/cache@v2
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
~/.cache/go-build
|
||||
key: ${{ runner.os }}-validate-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-validate-go-
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- 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: mkdir -p webui/static && touch webui/static/index.html
|
||||
run: touch webui/static/index.html
|
||||
|
||||
- name: Validate
|
||||
run: make validate
|
||||
|
||||
validate-generate:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/go/src/github.com/traefik/traefik
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: go/src/github.com/traefik/traefik
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Go modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
~/.cache/go-build
|
||||
key: ${{ runner.os }}-validate-generate-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-validate-generate-go-
|
||||
|
||||
- name: go generate
|
||||
run: |
|
||||
go generate
|
||||
make generate
|
||||
git diff --exit-code
|
||||
|
||||
- name: go mod tidy
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -5,7 +5,6 @@
|
||||
.DS_Store
|
||||
/dist
|
||||
/webui/.tmp/
|
||||
/webui/static/
|
||||
/site/
|
||||
/docs/site/
|
||||
/autogen/
|
||||
@@ -19,3 +18,5 @@ vendor/
|
||||
plugins-storage/
|
||||
plugins-local/
|
||||
traefik_changelog.md
|
||||
integration/tailscale.secret
|
||||
integration/conformance-reports/
|
||||
|
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"]
|
281
.golangci.yml
Normal file
281
.golangci.yml
Normal file
@@ -0,0 +1,281 @@
|
||||
run:
|
||||
timeout: 10m
|
||||
|
||||
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: 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/gorilla/mux
|
||||
- github.com/mailgun/minheap
|
||||
- github.com/mailgun/multibuf
|
||||
- github.com/jaguilar/vt100
|
||||
- github.com/cucumber/godog
|
||||
testifylint:
|
||||
disable:
|
||||
- suite-dont-use-pkg
|
||||
- require-error
|
||||
- go-require
|
||||
staticcheck:
|
||||
checks:
|
||||
- all
|
||||
- -SA1019
|
||||
errcheck:
|
||||
exclude-functions:
|
||||
- fmt.Fprintln
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- execinquery # deprecated
|
||||
- gomnd # deprecated
|
||||
- sqlclosecheck # not relevant (SQL)
|
||||
- rowserrcheck # 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
|
||||
- mnd # 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
|
||||
- err113 # 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
|
||||
- exportloopref # Useless with go1.22
|
||||
- musttag
|
||||
|
||||
issues:
|
||||
exclude-use-default: false
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
exclude-dirs:
|
||||
- pkg/provider/kubernetes/crd/generated/
|
||||
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"
|
||||
- 'fmt.Sprintf can be replaced with string'
|
||||
exclude-rules:
|
||||
- path: '(.+)_test.go'
|
||||
linters:
|
||||
- goconst
|
||||
- funlen
|
||||
- godot
|
||||
- canonicalheader
|
||||
- fatcontext
|
||||
- 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/kubernetes.go
|
||||
text: 'SA1019: middleware.Spec.IPWhiteList is deprecated: please use IPAllowList instead.'
|
||||
- path: pkg/server/middleware/tcp/middlewares.go
|
||||
text: 'SA1019: config.IPWhiteList is deprecated: please use IPAllowList instead.'
|
||||
- path: pkg/server/middleware/middlewares.go
|
||||
text: 'SA1019: config.IPWhiteList is deprecated: please use IPAllowList instead.'
|
||||
- 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
|
||||
- path: pkg/cli/deprecation.go
|
||||
linters:
|
||||
- goconst
|
||||
- path: pkg/cli/loader_file.go
|
||||
linters:
|
||||
- goconst
|
@@ -1,8 +1,12 @@
|
||||
project_name: traefik
|
||||
|
||||
dist: "./dist/[[ .GOOS ]]"
|
||||
|
||||
[[ if eq .GOOS "linux" ]]
|
||||
before:
|
||||
hooks:
|
||||
- go generate
|
||||
[[ end ]]
|
||||
|
||||
builds:
|
||||
- binary: traefik
|
||||
@@ -11,36 +15,38 @@ 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
|
||||
disable: true
|
||||
|
||||
archives:
|
||||
- id: traefik
|
@@ -3,7 +3,7 @@ name: Traefik
|
||||
agent:
|
||||
machine:
|
||||
type: e1-standard-4
|
||||
os_image: ubuntu1804
|
||||
os_image: ubuntu2004
|
||||
|
||||
fail_fast:
|
||||
stop:
|
||||
@@ -19,36 +19,18 @@ 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.22
|
||||
- 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.59.0
|
||||
- curl -sSfL https://gist.githubusercontent.com/traefiker/6d7ac019c11d011e4f131bb2cca8900e/raw/goreleaser.sh | bash -s -- -b "${GOPATH}/bin"
|
||||
- checkout
|
||||
- cache restore traefik-$(checksum go.sum)
|
||||
|
||||
blocks:
|
||||
- name: Test Integration
|
||||
dependencies: []
|
||||
run:
|
||||
when: "branch =~ '.*' OR pull_request =~'.*'"
|
||||
task:
|
||||
jobs:
|
||||
- name: Test Integration
|
||||
commands:
|
||||
- make pull-images
|
||||
- mkdir -p webui/static && touch webui/static/index.html # Avoid generating webui
|
||||
- PRE_TARGET="" make binary
|
||||
- make test-integration
|
||||
- df -h
|
||||
epilogue:
|
||||
always:
|
||||
commands:
|
||||
- cache store traefik-$(checksum go.sum) $HOME/go/pkg/mod
|
||||
|
||||
- name: Release
|
||||
dependencies: []
|
||||
run:
|
||||
@@ -57,25 +39,25 @@ 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: "rocamadour"
|
||||
- name: PRE_TARGET
|
||||
value: ""
|
||||
value: "beaufort"
|
||||
prologue:
|
||||
commands:
|
||||
- export VERSION=${SEMAPHORE_GIT_TAG_NAME}
|
||||
- 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
|
||||
|
1478
CHANGELOG.md
1478
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@@ -30,23 +30,35 @@ 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.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
When an inapropriate behavior is reported, maintainers will discuss on the Maintainer's Discord before marking the message as "abuse".
|
||||
This conversation beforehand avoids one-sided decisions.
|
||||
|
||||
The first message will be edited and marked as abuse.
|
||||
The second edited message and marked as abuse results in a 7-day ban.
|
||||
The third edited message and marked as abuse results in a permanent ban.
|
||||
|
||||
The content of edited messages is:
|
||||
`Dear user, we want traefik to provide a welcoming and respectful environment. Your [comment/issue/PR] has been reported and marked as abuse according to our [Code of Conduct](./CODE_OF_CONDUCT.md). Thank you.`
|
||||
|
||||
The [report must be resolved](https://docs.github.com/en/communities/moderating-comments-and-conversations/managing-reported-content-in-your-organizations-repository#resolving-a-report) accordingly.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
@@ -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).
|
||||
|
12
Dockerfile
12
Dockerfile
@@ -1,6 +1,12 @@
|
||||
FROM scratch
|
||||
COPY script/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY dist/traefik /
|
||||
# syntax=docker/dockerfile:1.2
|
||||
FROM alpine:3.20
|
||||
|
||||
RUN apk add --no-cache --no-progress ca-certificates tzdata
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
COPY ./dist/$TARGETPLATFORM/traefik /
|
||||
|
||||
EXPOSE 80
|
||||
VOLUME ["/tmp"]
|
||||
|
||||
ENTRYPOINT ["/traefik"]
|
||||
|
@@ -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-2024 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
|
||||
|
270
Makefile
270
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,163 +5,201 @@ 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)))
|
||||
|
||||
REPONAME := $(shell echo $(REPO) | tr '[:upper:]' '[:lower:]')
|
||||
TRAEFIK_IMAGE := $(if $(REPONAME),$(REPONAME),"traefik/traefik")
|
||||
BIN_NAME := traefik
|
||||
CODENAME ?= cheddar
|
||||
|
||||
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)",)
|
||||
DATE := $(shell date -u '+%Y-%m-%d_%I:%M:%S%p')
|
||||
|
||||
TRAEFIK_ENVS := \
|
||||
-e OS_ARCH_ARG \
|
||||
-e OS_PLATFORM_ARG \
|
||||
-e TESTFLAGS \
|
||||
-e VERBOSE \
|
||||
-e VERSION \
|
||||
-e CODENAME \
|
||||
-e TESTDIRS \
|
||||
-e CI \
|
||||
-e CONTAINER=DOCKER # Indicator for integration tests that we are running inside a container.
|
||||
# Default build target
|
||||
GOOS := $(shell go env GOOS)
|
||||
GOARCH := $(shell go env GOARCH)
|
||||
|
||||
TRAEFIK_MOUNT := -v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/traefik/traefik/$(BIND_DIR)"
|
||||
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)
|
||||
LINT_EXECUTABLES = misspell shellcheck
|
||||
|
||||
PRE_TARGET ?= build-dev-image
|
||||
DOCKER_BUILD_PLATFORMS ?= linux/amd64,linux/arm64
|
||||
|
||||
PLATFORM_URL := $(if $(PLATFORM_URL),$(PLATFORM_URL),"https://pilot.traefik.io")
|
||||
.PHONY: default
|
||||
#? default: Run `make generate` and `make binary`
|
||||
default: generate binary
|
||||
|
||||
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: Create the "dist" directory
|
||||
dist:
|
||||
mkdir dist
|
||||
mkdir -p dist
|
||||
|
||||
## Build WebUI Docker image
|
||||
.PHONY: build-webui-image
|
||||
#? build-webui-image: Build WebUI Docker 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
|
||||
|
||||
## Generate WebUI
|
||||
generate-webui:
|
||||
if [ ! -d "webui/static" ]; then \
|
||||
$(MAKE) build-webui-image; \
|
||||
mkdir -p webui/static; \
|
||||
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; \
|
||||
echo 'For more information show `webui/readme.md`' > $$PWD/webui/static/DONT-EDIT-FILES-IN-THIS-DIRECTORY.md; \
|
||||
fi
|
||||
.PHONY: clean-webui
|
||||
#? clean-webui: Clean WebUI static generated assets
|
||||
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
|
||||
|
||||
## Build the linux binary
|
||||
binary: generate-webui $(PRE_TARGET)
|
||||
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate binary
|
||||
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 binary for the standard platforms (linux, darwin, windows)
|
||||
crossbinary-default: generate-webui build-dev-image
|
||||
$(DOCKER_RUN_TRAEFIK_NOTTY) ./script/make.sh generate crossbinary-default
|
||||
.PHONY: generate-webui
|
||||
#? generate-webui: Generate WebUI
|
||||
generate-webui: webui/static/index.html
|
||||
|
||||
## Build the binary for the standard platforms (linux, darwin, windows) in parallel
|
||||
crossbinary-default-parallel:
|
||||
$(MAKE) generate-webui
|
||||
$(MAKE) build-dev-image crossbinary-default
|
||||
.PHONY: generate
|
||||
#? generate: Generate code (Dynamic and Static configuration documentation reference files)
|
||||
generate:
|
||||
go generate
|
||||
|
||||
## Run the unit and integration tests
|
||||
test: $(PRE_TARGET)
|
||||
-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
|
||||
.PHONY: binary
|
||||
#? binary: Build the binary
|
||||
binary: generate-webui dist
|
||||
@echo SHA: $(VERSION) $(CODENAME) $(DATE)
|
||||
CGO_ENABLED=0 GOGC=off GOOS=${GOOS} GOARCH=${GOARCH} go build ${FLAGS[*]} -ldflags "-s -w \
|
||||
-X github.com/traefik/traefik/v3/pkg/version.Version=$(VERSION) \
|
||||
-X github.com/traefik/traefik/v3/pkg/version.Codename=$(CODENAME) \
|
||||
-X github.com/traefik/traefik/v3/pkg/version.BuildDate=$(DATE)" \
|
||||
-installsuffix nocgo -o "./dist/${GOOS}/${GOARCH}/$(BIN_NAME)" ./cmd/traefik
|
||||
|
||||
## Run the unit tests
|
||||
test-unit: $(PRE_TARGET)
|
||||
-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-linux-arm64: export GOOS := linux
|
||||
binary-linux-arm64: export GOARCH := arm64
|
||||
binary-linux-arm64:
|
||||
@$(MAKE) binary
|
||||
|
||||
## Run the integration tests
|
||||
test-integration: $(PRE_TARGET)
|
||||
-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
|
||||
binary-linux-amd64: export GOOS := linux
|
||||
binary-linux-amd64: export GOARCH := amd64
|
||||
binary-linux-amd64:
|
||||
@$(MAKE) binary
|
||||
|
||||
## Pull all images for integration tests
|
||||
binary-windows-amd64: export GOOS := windows
|
||||
binary-windows-amd64: export GOARCH := amd64
|
||||
binary-windows-amd64: export BIN_NAME := traefik.exe
|
||||
binary-windows-amd64:
|
||||
@$(MAKE) binary
|
||||
|
||||
.PHONY: crossbinary-default
|
||||
#? crossbinary-default: Build the binary for the standard platforms (linux, darwin, windows)
|
||||
crossbinary-default: generate generate-webui
|
||||
$(CURDIR)/script/crossbinary-default.sh
|
||||
|
||||
.PHONY: test
|
||||
#? test: Run the unit and integration tests
|
||||
test: test-ui-unit test-unit test-integration
|
||||
|
||||
.PHONY: test-unit
|
||||
#? test-unit: Run the unit tests
|
||||
test-unit:
|
||||
GOOS=$(GOOS) GOARCH=$(GOARCH) go test -cover "-coverprofile=cover.out" -v $(TESTFLAGS) ./pkg/... ./cmd/...
|
||||
|
||||
.PHONY: test-integration
|
||||
#? test-integration: Run the integration tests
|
||||
test-integration: binary
|
||||
GOOS=$(GOOS) GOARCH=$(GOARCH) go test ./integration -test.timeout=20m -failfast -v $(TESTFLAGS)
|
||||
|
||||
.PHONY: test-gateway-api-conformance
|
||||
#? test-gateway-api-conformance: Run the conformance tests
|
||||
test-gateway-api-conformance: build-image-dirty
|
||||
GOOS=$(GOOS) GOARCH=$(GOARCH) go test ./integration -v -test.run K8sConformanceSuite -k8sConformance $(TESTFLAGS)
|
||||
|
||||
.PHONY: test-ui-unit
|
||||
#? test-ui-unit: Run the unit tests for the webui
|
||||
test-ui-unit:
|
||||
$(MAKE) build-webui-image
|
||||
docker run --rm -v "$(PWD)/webui/static":'/src/webui/static' traefik-webui yarn --cwd webui install
|
||||
docker run --rm -v "$(PWD)/webui/static":'/src/webui/static' traefik-webui yarn --cwd webui test:unit:ci
|
||||
|
||||
.PHONY: pull-images
|
||||
#? pull-images: Pull all Docker images to avoid timeout during integration tests
|
||||
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
|
||||
bash $(CURDIR)/script/validate-shell-script.sh
|
||||
.PHONY: lint
|
||||
#? lint: Run golangci-lint
|
||||
lint:
|
||||
golangci-lint run
|
||||
|
||||
## Validate code, docs, and vendor
|
||||
validate: $(PRE_TARGET)
|
||||
$(if $(PRE_TARGET),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate validate-lint validate-misspell validate-vendor
|
||||
bash $(CURDIR)/script/validate-shell-script.sh
|
||||
.PHONY: validate-files
|
||||
#? validate-files: Validate code and docs
|
||||
validate-files: lint
|
||||
$(foreach exec,$(LINT_EXECUTABLES),\
|
||||
$(if $(shell which $(exec)),,$(error "No $(exec) in PATH")))
|
||||
$(CURDIR)/script/validate-misspell.sh
|
||||
$(CURDIR)/script/validate-shell-script.sh
|
||||
|
||||
## Clean up static directory and build a Docker Traefik image
|
||||
build-image: binary
|
||||
rm -rf webui/static
|
||||
docker build -t $(TRAEFIK_IMAGE) .
|
||||
.PHONY: validate
|
||||
#? validate: Validate code, docs, and vendor
|
||||
validate: lint
|
||||
$(foreach exec,$(EXECUTABLES),\
|
||||
$(if $(shell which $(exec)),,$(error "No $(exec) in PATH")))
|
||||
$(CURDIR)/script/validate-vendor.sh
|
||||
$(CURDIR)/script/validate-misspell.sh
|
||||
$(CURDIR)/script/validate-shell-script.sh
|
||||
|
||||
## Build a Docker Traefik image
|
||||
build-image-dirty: binary
|
||||
docker build -t $(TRAEFIK_IMAGE) .
|
||||
# Target for building images for multiple architectures.
|
||||
.PHONY: multi-arch-image-%
|
||||
multi-arch-image-%: binary-linux-amd64 binary-linux-arm64
|
||||
docker buildx build $(DOCKER_BUILDX_ARGS) -t traefik/traefik:$* --platform=$(DOCKER_BUILD_PLATFORMS) -f Dockerfile .
|
||||
|
||||
## Start a shell inside the build env
|
||||
shell: build-dev-image
|
||||
$(DOCKER_RUN_TRAEFIK) /bin/bash
|
||||
|
||||
## Build documentation site
|
||||
.PHONY: build-image
|
||||
#? build-image: Clean up static directory and build a Docker Traefik image
|
||||
build-image: export DOCKER_BUILDX_ARGS := --load
|
||||
build-image: export DOCKER_BUILD_PLATFORMS := linux/$(GOARCH)
|
||||
build-image: clean-webui
|
||||
@$(MAKE) multi-arch-image-latest
|
||||
|
||||
.PHONY: build-image-dirty
|
||||
#? build-image-dirty: Build a Docker Traefik image without re-building the webui when it's already built
|
||||
build-image-dirty: export DOCKER_BUILDX_ARGS := --load
|
||||
build-image-dirty: export DOCKER_BUILD_PLATFORMS := linux/$(GOARCH)
|
||||
build-image-dirty:
|
||||
@$(MAKE) multi-arch-image-latest
|
||||
|
||||
.PHONY: docs
|
||||
#? docs: Build documentation site
|
||||
docs:
|
||||
make -C ./docs docs
|
||||
|
||||
## Serve the documentation site locally
|
||||
.PHONY: docs-serve
|
||||
#? docs-serve: Serve the documentation site locally
|
||||
docs-serve:
|
||||
make -C ./docs docs-serve
|
||||
|
||||
## Pull image for doc building
|
||||
.PHONY: docs-pull-images
|
||||
#? docs-pull-images: Pull image for doc building
|
||||
docs-pull-images:
|
||||
make -C ./docs docs-pull-images
|
||||
|
||||
## Generate CRD clientset and CRD manifests
|
||||
.PHONY: generate-crd
|
||||
#? generate-crd: Generate CRD clientset and CRD manifests
|
||||
generate-crd:
|
||||
@$(CURDIR)/script/code-gen.sh
|
||||
@$(CURDIR)/script/code-gen-docker.sh
|
||||
|
||||
## Generate code from dynamic configuration https://github.com/traefik/genconf
|
||||
.PHONY: generate-genconf
|
||||
#? generate-genconf: Generate code from dynamic configuration github.com/traefik/genconf
|
||||
generate-genconf:
|
||||
go run ./cmd/internal/gen/
|
||||
|
||||
## Create packages for the release
|
||||
release-packages: generate-webui $(PRE_TARGET)
|
||||
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 \
|
||||
--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/
|
||||
.PHONY: release-packages
|
||||
#? release-packages: Create packages for the release
|
||||
release-packages: generate-webui
|
||||
$(CURDIR)/script/release-packages.sh
|
||||
|
||||
## Format the Code
|
||||
.PHONY: fmt
|
||||
#? fmt: Format the Code
|
||||
fmt:
|
||||
gofmt -s -l -w $(SRCS)
|
||||
|
||||
run-dev:
|
||||
go generate
|
||||
GO111MODULE=on go build ./cmd/traefik
|
||||
./traefik
|
||||
.PHONY: help
|
||||
#? help: Get more info on make commands
|
||||
help: Makefile
|
||||
@echo " Choose a command run in traefik:"
|
||||
@sed -n 's/^#?//p' $< | column -t -s ':' | sort | sed -e 's/^/ /'
|
||||
|
27
README.md
27
README.md
@@ -1,18 +1,21 @@
|
||||
|
||||
<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)
|
||||
[](https://traefik-oss.semaphoreci.com/projects/traefik)
|
||||
[](https://doc.traefik.io/traefik)
|
||||
[](https://goreportcard.com/report/traefik/traefik)
|
||||
[](https://github.com/traefik/traefik/blob/master/LICENSE.md)
|
||||
[](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,18 @@ _(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)
|
||||
- [ECS](https://doc.traefik.io/traefik/providers/ecs/)
|
||||
- [File](https://doc.traefik.io/traefik/providers/file/)
|
||||
|
||||
## Quickstart
|
||||
@@ -88,13 +89,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>.
|
||||
@@ -126,9 +126,8 @@ You can find high level and deep dive videos on [videos.traefik.io](https://vide
|
||||
## Maintainers
|
||||
|
||||
We are strongly promoting a philosophy of openness and sharing, and firmly standing against the elitist closed approach. Being part of the core team should be accessible to anyone who is motivated and want to be part of that journey!
|
||||
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).
|
||||
|
||||
This [document](docs/content/contributing/maintainers-guidelines.md) describes how to be part of the [maintainers' team](docs/content/contributing/maintainers.md) 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](https://github.com/traefik/contributors-guide/blob/master/issue_triage.md).
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@@ -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,32 +0,0 @@
|
||||
FROM golang:1.17-alpine
|
||||
|
||||
RUN apk --update upgrade \
|
||||
&& apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \
|
||||
&& update-ca-certificates \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
# Which docker version to test on
|
||||
ARG DOCKER_VERSION=18.09.7
|
||||
|
||||
# Download docker
|
||||
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 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
|
||||
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
# Download go modules
|
||||
COPY go.mod .
|
||||
COPY go.sum .
|
||||
RUN GO111MODULE=on GOPROXY=https://proxy.golang.org go mod download
|
||||
|
||||
COPY . /go/src/github.com/traefik/traefik
|
@@ -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,14 +153,14 @@ 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 {
|
||||
b := strings.Builder{}
|
||||
b.WriteString(fmt.Sprintf("type %s struct {\n", name))
|
||||
|
||||
for i := 0; i < obj.NumFields(); i++ {
|
||||
for i := range obj.NumFields() {
|
||||
field := obj.Field(i)
|
||||
|
||||
if !field.Exported() {
|
||||
@@ -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/types.FileOrContent" {
|
||||
return "string"
|
||||
}
|
||||
|
||||
if typ.String() == "[]github.com/traefik/traefik/v2/pkg/tls.FileOrContent" {
|
||||
if typ.String() == "[]github.com/traefik/traefik/v3/pkg/types.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.OpenFile(staticConfiguration.Log.FilePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o666)
|
||||
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
|
||||
}
|
||||
|
@@ -5,11 +5,11 @@ import (
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
stdlog "log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"syscall"
|
||||
@@ -18,38 +18,41 @@ import (
|
||||
"github.com/coreos/go-systemd/daemon"
|
||||
"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/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/types"
|
||||
"github.com/traefik/traefik/v3/pkg/version"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// traefik config inits
|
||||
tConfig := cmd.NewTraefikConfiguration()
|
||||
|
||||
loaders := []cli.ResourceLoader{&tcli.FileLoader{}, &tcli.FlagLoader{}, &tcli.EnvLoader{}}
|
||||
loaders := []cli.ResourceLoader{&tcli.DeprecationLoader{}, &tcli.FileLoader{}, &tcli.FlagLoader{}, &tcli.EnvLoader{}}
|
||||
|
||||
cmdTraefik := &cli.Command{
|
||||
Name: "traefik",
|
||||
@@ -76,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)
|
||||
}
|
||||
|
||||
@@ -84,27 +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))
|
||||
log.Debug().RawJSON("staticConfiguration", jsonConf).Msg("Static configuration loaded [json]")
|
||||
}
|
||||
|
||||
if staticConfiguration.Global.CheckNewVersion {
|
||||
@@ -129,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 {
|
||||
@@ -149,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
|
||||
}
|
||||
|
||||
@@ -180,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
|
||||
@@ -189,9 +188,28 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err
|
||||
|
||||
acmeProviders := initACMEProvider(staticConfiguration, &providerAggregator, tlsManager, httpChallengeProvider, tlsChallengeProvider)
|
||||
|
||||
// Tailscale
|
||||
|
||||
tsProviders := initTailscaleProviders(staticConfiguration, &providerAggregator)
|
||||
|
||||
// Observability
|
||||
|
||||
metricRegistries := registerMetricClients(staticConfiguration.Metrics)
|
||||
var semConvMetricRegistry *metrics.SemConvMetricsRegistry
|
||||
if staticConfiguration.Metrics != nil && staticConfiguration.Metrics.OTLP != nil {
|
||||
semConvMetricRegistry, err = metrics.NewSemConvMetricRegistry(ctx, staticConfiguration.Metrics.OTLP)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create SemConv metric registry: %w", err)
|
||||
}
|
||||
}
|
||||
metricsRegistry := metrics.NewMultiRegistry(metricRegistries)
|
||||
accessLog := setupAccessLog(staticConfiguration.AccessLog)
|
||||
tracer, tracerCloser := setupTracing(staticConfiguration.Tracing)
|
||||
observabilityMgr := middleware.NewObservabilityMgr(*staticConfiguration, metricsRegistry, semConvMetricRegistry, accessLog, tracer, tracerCloser)
|
||||
|
||||
// Entrypoints
|
||||
|
||||
serverEntryPointsTCP, err := server.NewTCPEntryPoints(staticConfiguration.EntryPoints)
|
||||
serverEntryPointsTCP, err := server.NewTCPEntryPoints(staticConfiguration.EntryPoints, staticConfiguration.HostResolver, metricsRegistry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -201,34 +219,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)
|
||||
@@ -240,32 +248,41 @@ 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)
|
||||
managerFactory := service.NewManagerFactory(*staticConfiguration, routinesPool, observabilityMgr, roundTripperManager, acmeHTTPHandler)
|
||||
|
||||
// Router factory
|
||||
|
||||
accessLog := setupAccessLog(staticConfiguration.AccessLog)
|
||||
chainBuilder := middleware.NewChainBuilder(*staticConfiguration, metricsRegistry, accessLog)
|
||||
routerFactory := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, chainBuilder, pluginBuilder, metricsRegistry)
|
||||
routerFactory := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, observabilityMgr, pluginBuilder, dialerManager)
|
||||
|
||||
// Watcher
|
||||
|
||||
watcher := server.NewConfigurationWatcher(
|
||||
routinesPool,
|
||||
providerAggregator,
|
||||
time.Duration(staticConfiguration.Providers.ProvidersThrottleDuration),
|
||||
getDefaultsEntrypoints(staticConfiguration),
|
||||
"internal",
|
||||
)
|
||||
@@ -276,7 +293,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)
|
||||
}
|
||||
})
|
||||
@@ -290,13 +307,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)
|
||||
@@ -309,13 +327,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 {
|
||||
@@ -324,12 +351,13 @@ 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")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return server.NewServer(routinesPool, serverEntryPointsTCP, serverEntryPointsUDP, watcher, chainBuilder, accessLog), nil
|
||||
return server.NewServer(routinesPool, serverEntryPointsTCP, serverEntryPointsUDP, watcher, observabilityMgr), nil
|
||||
}
|
||||
|
||||
func getHTTPChallengeHandler(acmeProviders []*acme.Provider, httpChallengeProvider http.Handler) http.Handler {
|
||||
@@ -345,11 +373,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 {
|
||||
@@ -361,22 +405,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{}
|
||||
|
||||
@@ -399,7 +439,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
|
||||
}
|
||||
|
||||
@@ -413,6 +453,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
|
||||
@@ -421,33 +482,60 @@ 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.OTLP != nil {
|
||||
logger := log.With().Str(logs.MetricsProviderName, "openTelemetry").Logger()
|
||||
|
||||
openTelemetryRegistry := metrics.RegisterOpenTelemetry(logger.WithContext(context.Background()), metricsConfig.OTLP)
|
||||
if openTelemetryRegistry != nil {
|
||||
registries = append(registries, openTelemetryRegistry)
|
||||
logger.Debug().
|
||||
Str("pushInterval", metricsConfig.OTLP.PushInterval.String()).
|
||||
Msg("Configured OpenTelemetry metrics")
|
||||
}
|
||||
}
|
||||
|
||||
return registries
|
||||
@@ -474,64 +562,25 @@ 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.Tracer, io.Closer) {
|
||||
if conf == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
level, err := logrus.ParseLevel(levelStr)
|
||||
tracer, closer, err := tracing.NewTracing(conf)
|
||||
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
|
||||
log.Warn().Err(err).Msg("Unable to create tracer")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
return tracer, closer
|
||||
}
|
||||
|
||||
func checkNewVersion() {
|
||||
@@ -544,16 +593,16 @@ func checkNewVersion() {
|
||||
}
|
||||
|
||||
func stats(staticConfiguration *static.Configuration) {
|
||||
logger := log.WithoutContext()
|
||||
logger := log.With().Logger()
|
||||
|
||||
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.Info().Msg(`Stats collection is enabled.`)
|
||||
logger.Info().Msg(`Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.`)
|
||||
logger.Info().Msg(`Help us improve Traefik by leaving this feature on :)`)
|
||||
logger.Info().Msg(`More details on: https://doc.traefik.io/traefik/contributing/data-collection/`)
|
||||
collect(staticConfiguration)
|
||||
} else {
|
||||
logger.Info(`
|
||||
logger.Info().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/
|
||||
@@ -566,7 +615,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.
|
||||
@@ -94,7 +95,6 @@ func TestAppendCertMetric(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -114,3 +114,73 @@ 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",
|
||||
},
|
||||
},
|
||||
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
@@ -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.20
|
||||
|
||||
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
|
||||
|
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. Let us know if you’re talking about Traefik, and we'll promote your enthusiasm!"
|
||||
---
|
||||
|
||||
# Advocating
|
||||
|
||||
Spread the Love & Tell Us about It
|
||||
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 and 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,69 +1,25 @@
|
||||
---
|
||||
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.
|
||||
For changes to its dependencies, the `dep` dependency management tool is required.
|
||||
|
||||
### Method 1: Using `Docker` and `Makefile`
|
||||
|
||||
Run make with the `binary` target.
|
||||
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.
|
||||
|
||||
```bash
|
||||
$ make binary
|
||||
docker build -t traefik-webui -f webui/Dockerfile webui
|
||||
Sending build context to Docker daemon 2.686MB
|
||||
Step 1/11 : FROM node:8.15.0
|
||||
---> 1f6c34f7921c
|
||||
[...]
|
||||
Successfully built ce4ff439c06a
|
||||
Successfully tagged traefik-webui:latest
|
||||
[...]
|
||||
docker build -t "traefik-dev:4475--feature-documentation" -f build.Dockerfile .
|
||||
Sending build context to Docker daemon 279MB
|
||||
Step 1/10 : FROM golang:1.16-alpine
|
||||
---> f4bfb3d22bda
|
||||
[...]
|
||||
Successfully built 5c3c1a911277
|
||||
Successfully tagged traefik-dev:4475--feature-documentation
|
||||
docker run -e "TEST_CONTAINER=1" -v "/var/run/docker.sock:/var/run/docker.sock" -it -e OS_ARCH_ARG -e OS_PLATFORM_ARG -e TESTFLAGS -e VERBOSE -e VERSION -e CODENAME -e TESTDIRS -e CI -e CONTAINER=DOCKER -v "/home/ldez/sources/go/src/github.com/traefik/traefik/"dist":/go/src/github.com/traefik/traefik/"dist"" "traefik-dev:4475--feature-documentation" ./script/make.sh generate binary
|
||||
---> Making bundle: generate (in .)
|
||||
removed 'autogen/genstatic/gen.go'
|
||||
|
||||
---> Making bundle: binary (in .)
|
||||
|
||||
$ 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):
|
||||
|
||||
- `test-unit`
|
||||
- `test-integration`
|
||||
- `validate`
|
||||
- `binary` (the webUI is still generated by using Docker)
|
||||
|
||||
ex:
|
||||
|
||||
```bash
|
||||
PRE_TARGET= make test-unit
|
||||
```
|
||||
|
||||
### Method 2: Using `go`
|
||||
|
||||
Requirements:
|
||||
|
||||
- `go` v1.16+
|
||||
- environment variable `GO111MODULE=on`
|
||||
You need:
|
||||
- [Docker](https://github.com/docker/docker "Link to website of Docker")
|
||||
- `make`
|
||||
- [Go](https://go.dev/ "Link to website of Go")
|
||||
- [misspell](https://github.com/golangci/misspell)
|
||||
- [shellcheck](https://github.com/koalaman/shellcheck)
|
||||
- [Tailscale](https://tailscale.com/) if you are using Docker Desktop
|
||||
|
||||
!!! tip "Source Directory"
|
||||
|
||||
@@ -96,43 +52,34 @@ Requirements:
|
||||
## ... and the list goes on
|
||||
```
|
||||
|
||||
#### Build Traefik
|
||||
### Build Traefik
|
||||
|
||||
Once you've set up your go environment and cloned the source repository, you can build Traefik.
|
||||
|
||||
```bash
|
||||
# Generate UI static files
|
||||
rm -rf ./webui/static/; make generate-webui
|
||||
$ make binary
|
||||
SHA: 8fddfe118288bb5280eb5e77fa952f52def360b4 cheddar 2024-01-11_03:14:57PM
|
||||
CGO_ENABLED=0 GOGC=off GOOS=darwin GOARCH=arm64 go build -ldflags "-s -w \
|
||||
-X github.com/traefik/traefik/v2/pkg/version.Version=8fddfe118288bb5280eb5e77fa952f52def360b4 \
|
||||
-X github.com/traefik/traefik/v2/pkg/version.Codename=cheddar \
|
||||
-X github.com/traefik/traefik/v2/pkg/version.BuildDate=2024-01-11_03:14:57PM" \
|
||||
-installsuffix nocgo -o "./dist/darwin/arm64/traefik" ./cmd/traefik
|
||||
|
||||
# required to merge non-code components into the final binary,
|
||||
# such as the web dashboard/UI
|
||||
go generate
|
||||
$ ls dist/
|
||||
traefik*
|
||||
```
|
||||
|
||||
```bash
|
||||
# Standard go build
|
||||
go build ./cmd/traefik
|
||||
```
|
||||
|
||||
You will find the Traefik executable (`traefik`) in the `~/go/src/github.com/traefik/traefik` directory.
|
||||
You will find the Traefik executable (`traefik`) in the `./dist` directory.
|
||||
|
||||
## Testing
|
||||
|
||||
### Method 1: `Docker` and `make`
|
||||
|
||||
Run unit tests using the `test-unit` target.
|
||||
Run integration tests using the `test-integration` target.
|
||||
Run all tests (unit and integration) using the `test` target.
|
||||
|
||||
```bash
|
||||
$ make test-unit
|
||||
docker build -t "traefik-dev:your-feature-branch" -f build.Dockerfile .
|
||||
# […]
|
||||
docker run --rm -it -e OS_ARCH_ARG -e OS_PLATFORM_ARG -e TESTFLAGS -v "/home/user/go/src/github/traefik/traefik/dist:/go/src/github.com/traefik/traefik/dist" "traefik-dev:your-feature-branch" ./script/make.sh generate test-unit
|
||||
---> Making bundle: generate (in .)
|
||||
removed 'gen.go'
|
||||
|
||||
---> Making bundle: test-unit (in .)
|
||||
GOOS=darwin GOARCH=arm64 go test -cover "-coverprofile=cover.out" -v ./pkg/... ./cmd/...
|
||||
+ go test -cover -coverprofile=cover.out .
|
||||
ok github.com/traefik/traefik 0.005s coverage: 4.1% of statements
|
||||
|
||||
@@ -141,28 +88,30 @@ Test success
|
||||
|
||||
For development purposes, you can specify which tests to run by using (only works the `test-integration` target):
|
||||
|
||||
??? note "Configuring Tailscale for Docker Desktop user"
|
||||
|
||||
Create `tailscale.secret` file in `integration` directory.
|
||||
|
||||
This file need to contains a [Tailscale auth key](https://tailscale.com/kb/1085/auth-keys)
|
||||
(an ephemeral, but reusable, one is recommended).
|
||||
|
||||
Add this section to your tailscale ACLs to auto-approve the routes for the
|
||||
containers in the docker subnet:
|
||||
|
||||
```json
|
||||
"autoApprovers": {
|
||||
// Allow myself to automatically
|
||||
// advertize routes for docker networks
|
||||
"routes": {
|
||||
"172.31.42.0/24": ["your_tailscale_identity"],
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
```bash
|
||||
# Run every tests in the MyTest suite
|
||||
TESTFLAGS="-check.f MyTestSuite" make test-integration
|
||||
TESTFLAGS="-test.run TestAccessLogSuite" make test-integration
|
||||
|
||||
# Run the test "MyTest" in the MyTest suite
|
||||
TESTFLAGS="-check.f MyTestSuite.MyTest" make test-integration
|
||||
|
||||
# Run every tests starting with "My", in the MyTest suite
|
||||
TESTFLAGS="-check.f MyTestSuite.My" make test-integration
|
||||
|
||||
# Run every tests ending with "Test", in the MyTest suite
|
||||
TESTFLAGS="-check.f MyTestSuite.*Test" make test-integration
|
||||
TESTFLAGS="-test.run TestAccessLogSuite -testify.m ^TestAccessLog$" make test-integration
|
||||
```
|
||||
|
||||
More: https://labix.org/gocheck
|
||||
|
||||
### Method 2: `go`
|
||||
|
||||
Unit tests can be run from the cloned directory using `$ go test ./...` which should return `ok`, similar to:
|
||||
|
||||
```test
|
||||
ok _/home/user/go/src/github/traefik/traefik 0.004s
|
||||
```
|
||||
|
||||
Integration tests must be run from the `integration/` directory and require the `-integration` switch: `$ cd integration && go test -integration ./...`.
|
||||
|
@@ -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](../../ "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,90 +1,81 @@
|
||||
---
|
||||
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
|
||||
|
||||

|
||||
|
||||
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
|
||||
and guidelines for Traefik maintainers.
|
||||
|
||||
We are strongly promoting a philosophy of openness and sharing,
|
||||
and firmly standing against the elitist closed approach.
|
||||
Being part of the core team should be accessible to anyone motivated
|
||||
and wants to be part of that journey!
|
||||
|
||||
## Onboarding Process
|
||||
## Becoming a Maintainer
|
||||
|
||||
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.
|
||||
Before a contributor becomes a maintainer, they should meet the following requirements:
|
||||
|
||||
## Maintainer's Requirements
|
||||
- The contributor enabled [2FA](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication) on their GitHub account
|
||||
|
||||
Note: you do not have to meet all the listed requirements,
|
||||
but must have achieved several.
|
||||
- The contributor showed a consistent pattern of helpful, non-threatening, and friendly behavior towards other community members in the past.
|
||||
|
||||
- The contributor has read and accepted the maintainer's guidelines.
|
||||
|
||||
The contributor should also meet one or several of the following requirements:
|
||||
|
||||
- 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
|
||||
- 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.
|
||||
- The contributor showed a consistent pattern of helpful, non-threatening, and friendly behavior towards other community members in the past.
|
||||
|
||||
- The contributor is active on Traefik Community forums
|
||||
or other technical forums/boards such as K8S slack, Reddit, StackOverflow, hacker news.
|
||||
- Have read and accepted the contributor guidelines.
|
||||
|
||||
Any existing active maintainer can create an issue to discuss promoting a contributor to maintainer.
|
||||
Other maintainers can vote on the issue, and if the quorum is reached, the contributor is promoted to maintainer.
|
||||
If the quorum is not reached within one month after the issue is created, it is closed.
|
||||
|
||||
## Maintainer's Responsibilities and Privileges
|
||||
|
||||
There are lots of areas where you can contribute to the project,
|
||||
but we can suggest you start with activities such as:
|
||||
As a maintainer, you are granted a vote for the following:
|
||||
|
||||
- PR reviewing.
|
||||
- According to our guidelines we require you have at least 3 reviewers,
|
||||
thus you can review a PR and leave the relevant comment if it is necessary.
|
||||
- Participating in a daily [issue triage](https://github.com/traefik/contributors-guide/blob/master/issue_triage.md).
|
||||
- The process helps to understand and prioritize the reported issue according to its importance and severity.
|
||||
This is crucial to learn how our users implement Traefik.
|
||||
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.
|
||||
- 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).
|
||||
- We will be promoting you on social channels (mostly on Twitter).
|
||||
- [PR review](https://github.com/traefik/contributors-guide/blob/master/pr_guidelines.md).
|
||||
|
||||
## Governance
|
||||
- [Design review](https://github.com/traefik/contributors-guide/blob/master/proposals.md).
|
||||
|
||||
- Roadmap meetings on a regular basis where all maintainers are welcome.
|
||||
- [Proposals](https://github.com/traefik/contributors-guide/blob/master/proposals.md).
|
||||
|
||||
Maintainers are also added to the maintainer's Discord server where happens the [issue triage](https://github.com/traefik/contributors-guide/blob/master/issue_triage.md)
|
||||
and appear on the [Maintainers](maintainers.md) page.
|
||||
|
||||
As a maintainer, you should:
|
||||
|
||||
- Prioritize PR reviews, design reviews, and issue triage above any other task.
|
||||
|
||||
Making sure contributors and community members are listened to and have an impact on the project is essential to keeping the project active and develop a thriving community.
|
||||
|
||||
- Prioritize helping contributors reaching the expecting quality level over rewriting contributions.
|
||||
|
||||
Any triage activity on issues and PRs (e.g. labels, marking messages as off-topic, refusing, marking duplicates) should result from a collective decision to ensure knowledge is shared among maintainers.
|
||||
|
||||
## 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.
|
||||
You can reach Traefik core developers directly,
|
||||
which offers the possibility to discuss issues, pull requests, enhancements more efficiently
|
||||
- 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.
|
||||
Maintainers can discuss issues, pull requests, enhancements more efficiently
|
||||
and get the feedback almost immediately.
|
||||
Fewer blockers mean more fun and engaging work.
|
||||
|
||||
- On a daily basis, we publish a report that includes all the activities performed during the day.
|
||||
You are updated in regard to the workload that has been processed including:
|
||||
working on the new features and enhancements,
|
||||
activities related to the reported issues and PR’s,
|
||||
other important project-related announcements.
|
||||
- Every decision made on the discord server among maintainers is documented so it's visible to the rest of the community.
|
||||
|
||||
- At 5:00 PM CET every day 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.
|
||||
- Maintainers express their opinions on issues and reviews.
|
||||
It is fine to have different point of views.
|
||||
We encourage active and open conversations which goals are to improve Traefik.
|
||||
|
||||
- When discussing issues and proposals, maintainers should share as much information as possible to help solve the issue.
|
||||
|
||||
## Maintainers Activity
|
||||
|
||||
@@ -92,38 +83,45 @@ In order to keep the core team efficient and dynamic,
|
||||
maintainers' activity and involvement will be reviewed on a regular basis.
|
||||
|
||||
- Has the maintainer engaged with the team and the community by meeting two or more of these benchmarks in the past six months?
|
||||
|
||||
- Has the maintainer participated in at least two or three maintainer meetings?
|
||||
|
||||
- Substantial review of at least one or two PRs from either contributors or maintainers.
|
||||
|
||||
- Opened at least one or two bug fixes or feature request PRs
|
||||
that were eventually merged (or on a trajectory for merge).
|
||||
|
||||
- Substantial participation in the Help Wanted program (answered questions, helped identify issues, applied guidelines from the Help Wanted guide to open issues).
|
||||
|
||||
- Substantial participation with the community in general.
|
||||
|
||||
- Has the maintainer shown a consistent pattern of helpful,
|
||||
non-threatening,
|
||||
and friendly behavior towards other people on the maintainer team and with our community?
|
||||
|
||||
## Additional Comments for (not only) Maintainers
|
||||
## Additional Comments for Maintainers (that should apply to any contributor)
|
||||
|
||||
- Be able to put yourself in users’ shoes.
|
||||
- Be open-minded and respectful with other maintainers and other community members.
|
||||
- Keep the communication public -
|
||||
- Be respectful with other maintainers and other community members.
|
||||
|
||||
- Be open minded when participating in conversations: try to put yourself in others’ shoes.
|
||||
|
||||
- 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.
|
||||
Try to rephrase your sentences, avoiding mental shortcuts;
|
||||
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) -
|
||||
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.
|
||||
none of us is able to predict anyone's thoughts.
|
||||
|
||||
- Be proactive.
|
||||
|
||||
- Emoji are fine,
|
||||
but if you express yourself clearly enough they are not necessary.
|
||||
They will not replace good communication.
|
||||
- Embrace mentorship.
|
||||
- Keep in mind that we all have the same intent to improve the project.
|
||||
|
||||
- Embrace mentorship: help others grow and match the quality level we strive for.
|
||||
|
||||
- Keep in mind that we all have the same goal: improve the project.
|
||||
|
@@ -1,17 +1,16 @@
|
||||
---
|
||||
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
|
||||
## Active Maintainers
|
||||
|
||||
* Emile Vauge [@emilevauge](https://github.com/emilevauge)
|
||||
* Vincent Demeester [@vdemeester](https://github.com/vdemeester)
|
||||
* Ed Robinson [@errm](https://github.com/errm)
|
||||
* Daniel Tomcej [@dtomcej](https://github.com/dtomcej)
|
||||
* Manuel Zapf [@SantoDE](https://github.com/SantoDE)
|
||||
* Timo Reimann [@timoreimann](https://github.com/timoreimann)
|
||||
* Ludovic Fernandez [@ldez](https://github.com/ldez)
|
||||
* Julien Salleyron [@juliens](https://github.com/juliens)
|
||||
* Nicolas Mengin [@nmengin](https://github.com/nmengin)
|
||||
* Marco Jantke [@mjantke](https://github.com/mjeri)
|
||||
* Michaël Matur [@mmatur](https://github.com/mmatur)
|
||||
* Gérald Croës [@geraldcroes](https://github.com/geraldcroes)
|
||||
* Jean-Baptiste Doumenjou [@jbdoumenjou](https://github.com/jbdoumenjou)
|
||||
@@ -20,109 +19,21 @@
|
||||
* Kevin Pollet [@kevinpollet](https://github.com/kevinpollet)
|
||||
* Harold Ozouf [@jspdown](https://github.com/jspdown)
|
||||
* Tom Moulard [@tommoulard](https://github.com/tommoulard)
|
||||
* Landry Benguigui [@lbenguigui](https://github.com/lbenguigui)
|
||||
* Simon Delicata [@sdelicata](https://github.com/sdelicata)
|
||||
* Baptiste Mayelle [@youkoulayley](https://github.com/youkoulayley)
|
||||
|
||||
## Past Maintainers
|
||||
|
||||
People who have had an incredibly positive impact on the project, and are now focusing on other projects.
|
||||
|
||||
* Vincent Demeester [@vdemeester](https://github.com/vdemeester)
|
||||
* Ed Robinson [@errm](https://github.com/errm)
|
||||
* Daniel Tomcej [@dtomcej](https://github.com/dtomcej)
|
||||
* Timo Reimann [@timoreimann](https://github.com/timoreimann)
|
||||
* Marco Jantke [@mjantke](https://github.com/mjeri)
|
||||
* Ludovic Fernandez [@ldez](https://github.com/ldez)
|
||||
|
||||
## Maintainer's Guidelines
|
||||
|
||||
Please read the [maintainer's guidelines](maintainers-guidelines.md)
|
||||
|
||||
## Issue Triage
|
||||
|
||||
Issues and PRs are triaged daily and the process for triaging may be found under [triaging issues](https://github.com/traefik/contributors-guide/blob/master/issue_triage.md) in our [contributors guide repository](https://github.com/traefik/contributors-guide).
|
||||
|
||||
## PR Review Process
|
||||
|
||||
The process for reviewing PRs may be found under [review guidelines](https://github.com/traefik/contributors-guide/blob/master/review_guidelines.md) in our contributors guide repository.
|
||||
|
||||
## Labels
|
||||
|
||||
A maintainer that looks at an issue/PR must define its `kind/*`, `area/*`, and `status/*`.
|
||||
|
||||
### Status - Workflow
|
||||
|
||||
The `status/*` labels represent the desired state in the workflow.
|
||||
|
||||
* `status/0-needs-triage`: all the new issues and PRs have this status. _[bot only]_
|
||||
* `status/1-needs-design-review`: needs a design review. **(only for PR)**
|
||||
* `status/2-needs-review`: needs a code/documentation review. **(only for PR)**
|
||||
* `status/3-needs-merge`: ready to merge. **(only for PR)**
|
||||
* `status/4-merge-in-progress`: merge is in progress. _[bot only]_
|
||||
|
||||
### Contributor
|
||||
|
||||
* `contributor/need-more-information`: we need more information from the contributor in order to analyze a problem.
|
||||
* `contributor/waiting-for-feedback`: we need the contributor to give us feedback.
|
||||
* `contributor/waiting-for-corrections`: we need the contributor to take actions in order to move forward with a PR. **(only for PR)** _[bot, humans]_
|
||||
* `contributor/needs-resolve-conflicts`: use it only when there is some conflicts (and an automatic rebase is not possible). **(only for PR)** _[bot, humans]_
|
||||
|
||||
### Kind
|
||||
|
||||
* `kind/enhancement`: a new or improved feature.
|
||||
* `kind/question`: a question. **(only for issue)**
|
||||
* `kind/proposal`: a proposal that needs to be discussed.
|
||||
* _Proposal issues_ are design proposals
|
||||
* _Proposal PRs_ are technical prototypes that need to be refined with multiple contributors.
|
||||
|
||||
* `kind/bug/possible`: a possible bug that needs analysis before it is confirmed or fixed. **(only for issues)**
|
||||
* `kind/bug/confirmed`: a confirmed bug (reproducible). **(only for issues)**
|
||||
* `kind/bug/fix`: a bug fix. **(only for PR)**
|
||||
|
||||
### Resolution
|
||||
|
||||
* `resolution/duplicate`: a duplicate issue/PR.
|
||||
* `resolution/declined`: declined (Rule #1 of open-source: no is temporary, yes is forever).
|
||||
* `WIP`: Work In Progress. **(only for PR)**
|
||||
|
||||
### Platform
|
||||
|
||||
* `platform/windows`: Windows related.
|
||||
|
||||
### Area
|
||||
|
||||
* `area/acme`: ACME related.
|
||||
* `area/api`: Traefik API related.
|
||||
* `area/authentication`: Authentication related.
|
||||
* `area/cluster`: Traefik clustering related.
|
||||
* `area/documentation`: Documentation related.
|
||||
* `area/infrastructure`: CI or Traefik building scripts related.
|
||||
* `area/healthcheck`: Health-check related.
|
||||
* `area/logs`: Logs related.
|
||||
* `area/middleware`: Middleware related.
|
||||
* `area/middleware/metrics`: Metrics related. (Prometheus, StatsD, ...)
|
||||
* `area/middleware/tracing`: Tracing related. (Jaeger, Zipkin, ...)
|
||||
* `area/oxy`: Oxy related.
|
||||
* `area/provider`: related to all providers.
|
||||
* `area/provider/boltdb`: Boltd DB related.
|
||||
* `area/provider/consul`: Consul related.
|
||||
* `area/provider/docker`: Docker and Swarm related.
|
||||
* `area/provider/ecs`: ECS related.
|
||||
* `area/provider/etcd`: Etcd related.
|
||||
* `area/provider/eureka`: Eureka related.
|
||||
* `area/provider/file`: file provider related.
|
||||
* `area/provider/k8s`: Kubernetes related.
|
||||
* `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.
|
||||
* `area/server`: Server related.
|
||||
* `area/sticky-session`: Sticky session related.
|
||||
* `area/tls`: TLS related.
|
||||
* `area/websocket`: WebSocket related.
|
||||
* `area/webui`: Web UI related.
|
||||
|
||||
### Issues Priority
|
||||
|
||||
* `priority/P0`: needs hot fix.
|
||||
* `priority/P1`: need to be fixed in next release.
|
||||
* `priority/P2`: need to be fixed in the future.
|
||||
* `priority/P3`: maybe.
|
||||
|
||||
### PR Size
|
||||
|
||||
Automatically set by a bot.
|
||||
|
||||
* `size/S`: small PR.
|
||||
* `size/M`: medium PR.
|
||||
* `size/L`: Large PR.
|
||||
Please read the [maintainer's guidelines](maintainers-guidelines.md).
|
||||
|
@@ -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.
|
||||
The process of sorting and checking the issues is a daunting task, and requires a lot of work.
|
||||
To help maintainers (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,228 @@
|
||||
# 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, but because it's a time consuming operation, it's not always possible.
|
||||
|
||||
The PRs we are able to handle the 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 from 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.
|
||||
* Kindly comment on the pull request. Doing so will automatically give your PR visibility during the triage process.
|
||||
|
||||
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,27 +1,32 @@
|
||||
---
|
||||
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/),
|
||||
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.
|
||||
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),
|
||||
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:
|
||||
|
||||
- Propose and idea, request a feature a report a bug,
|
||||
read the page [Submitting Issues](./submitting-issues.md).
|
||||
- Propose an idea, request a feature, or report a bug,
|
||||
then read [Submitting Issues](./submitting-issues.md).
|
||||
- Discover how to make an efficient contribution,
|
||||
read the page [Submitting Pull Requests](./submitting-pull-requests.md).
|
||||
then read [Submitting Pull Requests](./submitting-pull-requests.md).
|
||||
- Learn how to build and test Traefik,
|
||||
the page [Building and Testing](./building-testing.md) is for you.
|
||||
then the page [Building and Testing](./building-testing.md) is for you.
|
||||
- Contribute to the documentation,
|
||||
read the related page [Documentation](./documentation.md).
|
||||
then read the page about [Documentation](./documentation.md).
|
||||
- Understand how do we learn about Traefik usage,
|
||||
read the [Data Collection](./data-collection.md) page.
|
||||
- Spread the love about Traefik, please check the [Advocating](./advocating.md) page.
|
||||
- Learn about who are the maintainers and how they work on the project,
|
||||
read the [Maintainers](./maintainers.md) page.
|
||||
read the [Maintainers](./maintainers.md) and [Maintainer Guidelines](./maintainers-guidelines.md) pages.
|
||||
|
26
docs/content/deprecation/features.md
Normal file
26
docs/content/deprecation/features.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# 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 CRD Provider API Version `traefik.io/v1alpha1`](#kubernetes-crd-provider-api-version-traefikiov1alpha1) | 3.0 | N/A | 4.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 CRD Provider API Version `traefik.io/v1alpha1`
|
||||
|
||||
The Kubernetes CRD provider API Version `traefik.io/v1alpha1` is deprecated in Traefik v3.
|
||||
Please use the API Group `traefik.io/v1` instead.
|
||||
|
||||
### Kubernetes Ingress API Version `networking.k8s.io/v1beta1`
|
||||
|
||||
The Kubernetes Ingress API Version `networking.k8s.io/v1beta1` support is removed in v3.
|
||||
Please use the API Group `networking.k8s.io/v1` instead.
|
||||
|
||||
### Traefik CRD Definitions API Version `apiextensions.k8s.io/v1beta1`
|
||||
|
||||
The Traefik CRD definitions API Version `apiextensions.k8s.io/v1beta1` support is removed in v3.
|
||||
Please use the API Group `apiextensions.k8s.io/v1` instead.
|
38
docs/content/deprecation/releases.md
Normal file
38
docs/content/deprecation/releases.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Releases
|
||||
|
||||
## Versions
|
||||
|
||||
Below is a non-exhaustive list of versions and their maintenance status:
|
||||
|
||||
| Version | Release Date | Community Support |
|
||||
|---------|--------------|--------------------|
|
||||
| 3.0 | Apr 29, 2024 | Yes |
|
||||
| 2.11 | Feb 12, 2024 | Ends Apr 29, 2025 |
|
||||
| 2.10 | Apr 24, 2023 | Ended Feb 12, 2024 |
|
||||
| 2.9 | Oct 03, 2022 | Ended Apr 24, 2023 |
|
||||
| 2.8 | Jun 29, 2022 | Ended Oct 03, 2022 |
|
||||
| 2.7 | May 24, 2022 | Ended Jun 29, 2022 |
|
||||
| 2.6 | Jan 24, 2022 | Ended May 24, 2022 |
|
||||
| 2.5 | Aug 17, 2021 | Ended Jan 24, 2022 |
|
||||
| 2.4 | Jan 19, 2021 | Ended Aug 17, 2021 |
|
||||
| 2.3 | Sep 23, 2020 | Ended Jan 19, 2021 |
|
||||
| 2.2 | Mar 25, 2020 | Ended Sep 23, 2020 |
|
||||
| 2.1 | Dec 11, 2019 | Ended Mar 25, 2020 |
|
||||
| 2.0 | Sep 16, 2019 | Ended Dec 11, 2019 |
|
||||
| 1.7 | Sep 24, 2018 | Ended Dec 31, 2021 |
|
||||
|
||||
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 [v2 to v3 migration guide](../migration/v2-to-v3.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*; this 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.
|
||||
This means that when a service is deployed, Traefik detects it immediately and updates the routing rules in real time.
|
||||
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,17 +79,19 @@ traefik --help
|
||||
# or
|
||||
|
||||
docker run traefik[:version] --help
|
||||
# ex: docker run traefik:v2.6 --help
|
||||
# ex: docker run traefik:v3.0 --help
|
||||
```
|
||||
|
||||
All available arguments can also be found [here](../reference/static-configuration/cli.md).
|
||||
Check the [CLI reference](../reference/static-configuration/cli.md "Link to CLI reference overview") for an overview about all available arguments.
|
||||
|
||||
### Environment Variables
|
||||
|
||||
All available environment variables can be found [here](../reference/static-configuration/env.md)
|
||||
All available environment variables can be found in the [static configuration environment overview](../reference/static-configuration/env.md).
|
||||
|
||||
## Available Configuration Options
|
||||
|
||||
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?
|
||||
@@ -24,7 +29,7 @@ Not to mention that dynamic configuration changes potentially make that kind of
|
||||
Therefore, in this dynamic context,
|
||||
the static configuration of an `entryPoint` does not give any hint whatsoever about how the traffic going through that `entryPoint` is going to be routed.
|
||||
Or whether it's even going to be routed at all,
|
||||
i.e. whether there is a Router matching the kind of traffic going through it.
|
||||
that is whether there is a Router matching the kind of traffic going through it.
|
||||
|
||||
### `404 Not found`
|
||||
|
||||
@@ -66,7 +71,7 @@ Traefik returns a `502` response code when an error happens while contacting the
|
||||
|
||||
### `503 Service Unavailable`
|
||||
|
||||
Traefik returns a `503` response code when a Router has been matched
|
||||
Traefik returns a `503` response code when a Router has been matched,
|
||||
but there are no servers ready to handle the request.
|
||||
|
||||
This situation is encountered when a service has been explicitly configured without servers,
|
||||
@@ -79,7 +84,7 @@ Sometimes, the `404` response code doesn't play well with other parties or servi
|
||||
In these situations, you may want Traefik to always reply with a `503` response code,
|
||||
instead of a `404` response code.
|
||||
|
||||
To achieve this behavior, a simple catchall router,
|
||||
To achieve this behavior, a catchall router,
|
||||
with the lowest possible priority and routing to a service without servers,
|
||||
can handle all the requests when no other router has been matched.
|
||||
|
||||
@@ -88,7 +93,7 @@ The example below is a file provider only version (`yaml`) of what this configur
|
||||
```yaml tab="Static configuration"
|
||||
# traefik.yml
|
||||
|
||||
entrypoints:
|
||||
entryPoints:
|
||||
web:
|
||||
address: :80
|
||||
|
||||
@@ -125,7 +130,7 @@ http:
|
||||
the principle of the above example above (a catchall router) still stands,
|
||||
but the `unavailable` service should be adapted to fit such a need.
|
||||
|
||||
## Why Is My TLS Certificate Not Reloaded When Its Contents Change?
|
||||
## Why Is My TLS Certificate Not Reloaded When Its Contents Change?
|
||||
|
||||
With the file provider,
|
||||
a configuration update is only triggered when one of the [watched](../providers/file.md#provider-configuration) configuration files is modified.
|
||||
@@ -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 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 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 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:
|
||||
|
||||
```shell
|
||||
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.6/traefik.sample.yml)
|
||||
* [TOML](https://raw.githubusercontent.com/traefik/traefik/v2.6/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
|
||||
```shell
|
||||
docker run -d -p 8080:8080 -p 80:80 \
|
||||
-v $PWD/traefik.yml:/etc/traefik/traefik.yml traefik:v2.6
|
||||
-v $PWD/traefik.yml:/etc/traefik/traefik.yml traefik:v3.0
|
||||
```
|
||||
|
||||
For more details, go to the [Docker provider documentation](../providers/docker.md)
|
||||
@@ -24,28 +29,23 @@ 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.6`
|
||||
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.
|
||||
|
||||
## Use the Helm Chart
|
||||
|
||||
!!! warning
|
||||
|
||||
The Traefik Chart from
|
||||
[Helm's default charts repository](https://github.com/helm/charts/tree/master/stable/traefik) is still using [Traefik v1.7](https://doc.traefik.io/traefik/v1.7).
|
||||
|
||||
Traefik can be installed in Kubernetes using the Helm chart from <https://github.com/traefik/traefik-helm-chart>.
|
||||
|
||||
Ensure that the following requirements are met:
|
||||
|
||||
* Kubernetes 1.14+
|
||||
* Helm version 3.x is [installed](https://helm.sh/docs/intro/install/)
|
||||
* Kubernetes 1.22+
|
||||
* 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:
|
||||
@@ -54,7 +54,7 @@ You can update the chart repository by running:
|
||||
helm repo update
|
||||
```
|
||||
|
||||
And install it with the `helm` command line:
|
||||
And install it with the Helm command line:
|
||||
|
||||
```bash
|
||||
helm install traefik traefik/traefik
|
||||
@@ -63,6 +63,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 +81,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`:
|
||||
@@ -99,7 +101,7 @@ helm install traefik traefik/traefik
|
||||
|
||||
### Exposing the Traefik dashboard
|
||||
|
||||
This HelmChart does not expose the Traefik dashboard by default, for security concerns.
|
||||
This Helm chart does not expose the Traefik dashboard by default, for security concerns.
|
||||
Thus, there are multiple ways to expose the dashboard.
|
||||
For instance, the dashboard access could be achieved through a port-forward:
|
||||
|
||||
@@ -114,7 +116,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 +175,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: "Get started with Traefik Proxy and Kubernetes."
|
||||
---
|
||||
|
||||
# Quick Start
|
||||
|
||||
A 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.
|
||||
|
||||
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 # This tutorial uses the "default" K8s namespace.
|
||||
```
|
||||
|
||||
!!! 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 an 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: "Get started with Traefik Proxy and Docker."
|
||||
---
|
||||
|
||||
# Quick Start
|
||||
|
||||
A Simple Use Case Using Docker
|
||||
A Use Case Using Docker
|
||||
{: .subtitle }
|
||||
|
||||

|
||||
@@ -14,8 +19,8 @@ version: '3'
|
||||
|
||||
services:
|
||||
reverse-proxy:
|
||||
# The official v2 Traefik docker image
|
||||
image: traefik:v2.6
|
||||
# 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:
|
||||
@@ -36,16 +41,21 @@ Start your `reverse-proxy` with the following command:
|
||||
docker-compose up -d reverse-proxy
|
||||
```
|
||||
|
||||
You can open a browser and go to `http://localhost:8080/api/rawdata` to see Traefik's API rawdata (we'll go back there once we have launched a service in step 2).
|
||||
You can open a browser and go to `http://localhost:8080/api/rawdata` to see Traefik's API rawdata (you'll go back there once you have launched a service in step 2).
|
||||
|
||||
## Traefik Detects New Services and Creates the Route for You
|
||||
|
||||
Now that we have a Traefik instance up and running, we will deploy new services.
|
||||
Now that you have a Traefik instance up and running, you 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`: a web service that outputs information about the machine it is deployed on (its IP address, host, and others).
|
||||
|
||||
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, you'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:
|
||||
|
||||
@@ -93,7 +103,7 @@ Finally, see that Traefik load-balances between the two instances of your servic
|
||||
curl -H Host:whoami.docker.localhost http://127.0.0.1
|
||||
```
|
||||
|
||||
The output will show alternatively one of the followings:
|
||||
The output will show alternatively one of the following:
|
||||
|
||||
```yaml
|
||||
Hostname: a656c8ddca6c
|
||||
@@ -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 user guides](../../user-guides/docker-compose/basic-example/ "Link to the user guides") and [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"
|
||||
|
||||
@@ -105,8 +116,8 @@ Please check the [configuration examples below](#configuration-examples) for mor
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--entrypoints.web.address=:80
|
||||
--entrypoints.websecure.address=:443
|
||||
--entryPoints.web.address=:80
|
||||
--entryPoints.websecure.address=:443
|
||||
# ...
|
||||
--certificatesresolvers.myresolver.acme.email=your-email@example.com
|
||||
--certificatesresolvers.myresolver.acme.storage=acme.json
|
||||
@@ -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"
|
||||
|
||||
@@ -143,7 +154,7 @@ Traefik automatically tracks the expiry date of ACME certificates it generates.
|
||||
By default, Traefik manages 90 days certificates,
|
||||
and starts to renew certificates 30 days before their expiry.
|
||||
|
||||
When using a certificates resolver that issues certificates with custom durations,
|
||||
When using a certificate resolver that issues certificates with custom durations,
|
||||
one can configure the certificates' duration with the [`certificatesDuration`](#certificatesduration) option.
|
||||
|
||||
!!! info ""
|
||||
@@ -158,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`
|
||||
|
||||
@@ -228,8 +241,8 @@ when using the `HTTP-01` challenge, `certificatesresolvers.myresolver.acme.httpc
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--entrypoints.web.address=:80
|
||||
--entrypoints.websecure.address=:443
|
||||
--entryPoints.web.address=:80
|
||||
--entryPoints.websecure.address=:443
|
||||
# ...
|
||||
--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web
|
||||
```
|
||||
@@ -270,8 +283,25 @@ 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
|
||||
```
|
||||
|
||||
!!! warning "Multiple DNS Challenge provider"
|
||||
|
||||
Multiple DNS challenge provider are not supported with Traefik, but you can use `CNAME` to handle that.
|
||||
For example, if you have `example.org` (account foo) and `example.com` (account bar) you can create a CNAME on `example.org` called `_acme-challenge.example.org` pointing to `challenge.example.com`.
|
||||
This way, you can obtain certificates for `example.com` with the `foo` account.
|
||||
|
||||
!!! important
|
||||
A `provider` is mandatory.
|
||||
|
||||
#### `providers`
|
||||
|
||||
@@ -284,114 +314,147 @@ 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) |
|
||||
| [CPanel and WHM](https://cpanel.net/) | `cpanel` | `CPANEL_MODE`, `CPANEL_USERNAME`, `CPANEL_TOKEN`, `CPANEL_BASE_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/cpanel) |
|
||||
| [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_PERSONAL_ACCESS_TOKEN` | [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) |
|
||||
| [http.net](https://www.http.net/) | `httpnet` | `HTTPNET_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/httpnet) |
|
||||
| [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) |
|
||||
| [Mail-in-a-Box](https://mailinabox.email) | `mailinabox` | `MAILINABOX_EMAIL`, `MAILINABOX_PASSWORD`, `MAILINABOX_BASE_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/mailinabox) |
|
||||
| [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`, `OVH_CLIENT_ID`, `OVH_CLIENT_SECRET` | [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` | `SCW_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/scaleway) |
|
||||
| [Selectel](https://selectel.ru/en/) | `selectel` | `SELECTEL_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/selectel) |
|
||||
| [Selectel v2](https://selectel.ru/en/) | `selectelv2` | `SELECTELV2_ACCOUNT_ID`, `SELECTELV2_PASSWORD`, `SELECTELV2_PROJECT_ID`, `SELECTELV2_USERNAME` | [Additional configuration](https://go-acme.github.io/lego/dns/selectelv2) |
|
||||
| [Servercow](https://servercow.de) | `servercow` | `SERVERCOW_USERNAME`, `SERVERCOW_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/servercow) |
|
||||
| [Shellrent](https://www.shellrent.com) | `shellrent` | `SHELLRENT_USERNAME`, `SHELLRENT_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/shellrent) |
|
||||
| [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) |
|
||||
| [Webnames](https://www.webnames.ru/) | `webnames` | `WEBNAMES_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/webnames) |
|
||||
| [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.
|
||||
@@ -647,8 +710,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,28 +1,16 @@
|
||||
|
||||
```yaml tab="Docker"
|
||||
```yaml tab="Docker & Swarm"
|
||||
## 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].main=example.com
|
||||
- traefik.http.routers.blog.tls.domains[0].sans=*.example.org
|
||||
```
|
||||
|
||||
```yaml tab="Docker (Swarm)"
|
||||
## Dynamic configuration
|
||||
deploy:
|
||||
labels:
|
||||
- traefik.http.routers.blog.rule=Host(`example.com`) && Path(`/blog`)
|
||||
- traefik.http.services.blog-svc.loadbalancer.server.port=8080"
|
||||
- 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="Kubernetes"
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: blogtls
|
||||
@@ -38,32 +26,11 @@ spec:
|
||||
tls:
|
||||
certResolver: myresolver
|
||||
domains:
|
||||
- main: example.org
|
||||
- main: example.com
|
||||
sans:
|
||||
- '*.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:
|
||||
@@ -73,7 +40,7 @@ http:
|
||||
tls:
|
||||
certResolver: myresolver
|
||||
domains:
|
||||
- main: "example.org"
|
||||
- main: "example.com"
|
||||
sans:
|
||||
- "*.example.org"
|
||||
```
|
||||
@@ -86,6 +53,6 @@ http:
|
||||
[http.routers.blog.tls]
|
||||
certResolver = "myresolver" # From static configuration
|
||||
[[http.routers.blog.tls.domains]]
|
||||
main = "example.org"
|
||||
main = "example.com"
|
||||
sans = ["*.example.org"]
|
||||
```
|
||||
|
@@ -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!}
|
||||
|
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.
|
10
docs/content/includes/traefik-for-business-applications.md
Normal file
10
docs/content/includes/traefik-for-business-applications.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
|
||||
!!! question "Using Traefik OSS in Production? Consider Adding Advanced Capabilities."
|
||||
|
||||
Add API Gateway or API Management capabilities seamlessly to your existing Traefik deployments.
|
||||
No rip and replace. No learning curve.
|
||||
|
||||
- [Explore our API Gateway](https://traefik.io/traefik-hub-api-gateway/)
|
||||
- [Explore our API Management](https://traefik.io/traefik-hub/)
|
||||
- [Get 24/7/365 Commercial Support for Traefik OSS](https://info.traefik.io/request-commercial-support)
|
@@ -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,20 +13,17 @@ 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.
|
||||
|
||||
Developing Traefik, our main goal is to make it simple to use, and we're sure you'll enjoy it.
|
||||
Developing Traefik, our main goal is to make it effortless to use, and we're sure you'll enjoy it.
|
||||
|
||||
-- The Traefik Maintainer Team
|
||||
|
||||
!!! 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 OSS in Production? Add enterprise-grade API Gateway and API Management capabilities to your existing deployments seamlessly. No rip and replace. No learning curve. Learn more from [this short video](https://info.traefik.io/traefik-upgrade-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
|
||||
@@ -5,11 +10,11 @@ Adding Basic Authentication
|
||||
|
||||

|
||||
|
||||
The BasicAuth middleware restricts access to your services to known users.
|
||||
The BasicAuth middleware grants access to services to authorized users only.
|
||||
|
||||
## 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:
|
||||
@@ -95,7 +88,7 @@ The `users` option is an array of authorized users. Each user must be declared u
|
||||
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"
|
||||
```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.
|
||||
@@ -109,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
|
||||
@@ -152,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:
|
||||
@@ -196,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
|
||||
@@ -227,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:
|
||||
@@ -263,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
|
||||
@@ -282,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:
|
||||
@@ -311,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
|
||||
@@ -331,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:
|
||||
@@ -356,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
|
||||
@@ -375,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:
|
||||
@@ -92,6 +85,7 @@ At specified intervals (`checkPeriod`), the circuit breaker evaluates `expressio
|
||||
### Open
|
||||
|
||||
While open, the fallback mechanism takes over the normal service calls for a duration of `FallbackDuration`.
|
||||
The fallback mechanism returns a `HTTP 503` (or `ResponseCode`) to the client.
|
||||
After this duration, it enters the recovering state.
|
||||
|
||||
### Recovering
|
||||
@@ -171,15 +165,24 @@ 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).
|
||||
|
||||
### `ResponseCode`
|
||||
|
||||
_Optional, Default="503"_
|
||||
|
||||
The status code that the circuit breaker will return while it is in the open 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,45 @@ http:
|
||||
|
||||
Responses are compressed when the following criteria are all met:
|
||||
|
||||
* The response body is larger than the configured minimum amount of bytes (default is `1024`).
|
||||
* 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, the response won't be encoded.
|
||||
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), or is one among the [includedContentTypes options](#includedcontenttypes).
|
||||
* 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
|
||||
|
||||
The `excludedContentTypes` and `includedContentTypes` options are mutually exclusive.
|
||||
|
||||
!!! 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 +106,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:
|
||||
@@ -123,21 +121,74 @@ http:
|
||||
excludedContentTypes = ["text/event-stream"]
|
||||
```
|
||||
|
||||
### `includedContentTypes`
|
||||
|
||||
_Optional, Default=""_
|
||||
|
||||
`includedContentTypes` specifies a list of content types to compare the `Content-Type` header of the responses before compressing.
|
||||
|
||||
The responses with content types defined in `includedContentTypes` are compressed.
|
||||
|
||||
Content types are compared in a case-insensitive, whitespace-ignored manner.
|
||||
|
||||
!!! info
|
||||
|
||||
The `excludedContentTypes` and `includedContentTypes` options are mutually exclusive.
|
||||
|
||||
```yaml tab="Docker & Swarm"
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-compress.compress.includedcontenttypes=application/json,text/html,text/plain"
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: test-compress
|
||||
spec:
|
||||
compress:
|
||||
includedContentTypes:
|
||||
- application/json
|
||||
- text/html
|
||||
- text/plain
|
||||
```
|
||||
|
||||
```yaml tab="Consul Catalog"
|
||||
- "traefik.http.middlewares.test-compress.compress.includedcontenttypes=application/json,text/html,text/plain"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
http:
|
||||
middlewares:
|
||||
test-compress:
|
||||
compress:
|
||||
includedContentTypes:
|
||||
- application/json
|
||||
- text/html
|
||||
- text/plain
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[http.middlewares]
|
||||
[http.middlewares.test-compress.compress]
|
||||
includedContentTypes = ["application/json","text/html","text/plain"]
|
||||
```
|
||||
|
||||
### `minResponseBodyBytes`
|
||||
|
||||
_Optional, Default=1024_
|
||||
|
||||
`minResponseBodyBytes` specifies the minimum amount of bytes a response body must have to be compressed.
|
||||
|
||||
The default value is `1024`, which should be a reasonable value for most cases.
|
||||
|
||||
Responses smaller than the specified values will not be compressed.
|
||||
|
||||
```yaml tab="Docker"
|
||||
```yaml tab="Docker & Swarm"
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-compress.compress.minresponsebodybytes=1200"
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: test-compress
|
||||
@@ -150,17 +201,6 @@ spec:
|
||||
- "traefik.http.middlewares.test-compress.compress.minresponsebodybytes=1200"
|
||||
```
|
||||
|
||||
```json tab="Marathon"
|
||||
"labels": {
|
||||
"traefik.http.middlewares.test-compress.compress.minresponsebodybytes": 1200
|
||||
}
|
||||
```
|
||||
|
||||
```yaml tab="Rancher"
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-compress.compress.minresponsebodybytes=1200"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
http:
|
||||
middlewares:
|
||||
@@ -173,4 +213,45 @@ http:
|
||||
[http.middlewares]
|
||||
[http.middlewares.test-compress.compress]
|
||||
minResponseBodyBytes = 1200
|
||||
```
|
||||
```
|
||||
|
||||
### `defaultEncoding`
|
||||
|
||||
_Optional, Default=""_
|
||||
|
||||
`defaultEncoding` specifies the default encoding if the `Accept-Encoding` header is not in the request or contains a wildcard (`*`).
|
||||
|
||||
There is no fallback on the `defaultEncoding` when the header value is empty or unsupported.
|
||||
|
||||
```yaml tab="Docker & Swarm"
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-compress.compress.defaultEncoding=gzip"
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: test-compress
|
||||
spec:
|
||||
compress:
|
||||
defaultEncoding: gzip
|
||||
```
|
||||
|
||||
```yaml tab="Consul Catalog"
|
||||
- "traefik.http.middlewares.test-compress.compress.defaultEncoding=gzip"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
http:
|
||||
middlewares:
|
||||
test-compress:
|
||||
compress:
|
||||
defaultEncoding: gzip
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[http.middlewares]
|
||||
[http.middlewares.test-compress.compress]
|
||||
defaultEncoding = "gzip"
|
||||
```
|
||||
|
@@ -1,86 +1,67 @@
|
||||
---
|
||||
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`
|
||||
|
||||
!!! warning
|
||||
|
||||
`autoDetect` option is deprecated and should not be used.
|
||||
Moreover, it is redundant with an empty ContentType middleware declaration.
|
||||
|
||||
`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
|
||||
@@ -5,11 +10,11 @@ Adding Digest Authentication
|
||||
|
||||

|
||||
|
||||
The DigestAuth middleware restricts access to your services to known users.
|
||||
The DigestAuth middleware grants access to services to authorized users only.
|
||||
|
||||
## 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,23 +18,26 @@ 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,501,503,505-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:
|
||||
- "500-599"
|
||||
- "500"
|
||||
- "501"
|
||||
- "503"
|
||||
- "505-599"
|
||||
query: /{status}.html
|
||||
service:
|
||||
name: whoami
|
||||
@@ -37,36 +45,23 @@ 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"
|
||||
# Dynamic Custom Error Page for 5XX Status Code excluding 502 and 504
|
||||
- "traefik.http.middlewares.test-errors.errors.status=500,501,503,505-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
|
||||
# Dynamic Custom Error Page for 5XX Status Code excluding 502 and 504
|
||||
http:
|
||||
middlewares:
|
||||
test-errorpage:
|
||||
test-errors:
|
||||
errors:
|
||||
status:
|
||||
- "500-599"
|
||||
- "500"
|
||||
- "501"
|
||||
- "503"
|
||||
- "505-599"
|
||||
service: serviceError
|
||||
query: "/{status}.html"
|
||||
|
||||
@@ -75,10 +70,10 @@ http:
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
# Custom Error Page for 5XX
|
||||
# Dynamic Custom Error Page for 5XX Status Code excluding 502 and 504
|
||||
[http.middlewares]
|
||||
[http.middlewares.test-errorpage.errors]
|
||||
status = ["500-599"]
|
||||
[http.middlewares.test-errors.errors]
|
||||
status = ["500","501","503","505-599"]
|
||||
service = "serviceError"
|
||||
query = "/{status}.html"
|
||||
|
||||
@@ -96,14 +91,16 @@ http:
|
||||
|
||||
The `status` option defines which status or range of statuses should result in an error page.
|
||||
|
||||
The status code ranges are inclusive (`500-599` will trigger with every code between `500` and `599`, `500` and `599` included).
|
||||
The status code ranges are inclusive (`505-599` will trigger with every code between `505` and `599`, `505` and `599` included).
|
||||
|
||||
!!! note ""
|
||||
|
||||
You can define either a status code as a number (`500`),
|
||||
as multiple comma-separated numbers (`500,502`),
|
||||
as ranges by separating two codes with a dash (`500-599`),
|
||||
or a combination of the two (`404,418,500-599`).
|
||||
as ranges by separating two codes with a dash (`505-599`),
|
||||
or a combination of the two (`404,418,505-599`).
|
||||
The comma-separated syntax is only available for label-based providers.
|
||||
The examples above demonstrate which syntax is appropriate for each provider.
|
||||
|
||||
### `service`
|
||||
|
||||
@@ -116,8 +113,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:
|
||||
@@ -347,6 +285,55 @@ http:
|
||||
authRequestHeaders = "Accept,X-CustomHeader"
|
||||
```
|
||||
|
||||
### `addAuthCookiesToResponse`
|
||||
|
||||
The `addAuthCookiesToResponse` option is the list of cookies to copy from the authentication server to the response,
|
||||
replacing any existing conflicting cookie from the forwarded response.
|
||||
|
||||
!!! info
|
||||
|
||||
Please note that all backend cookies matching the configured list will not be added to the response.
|
||||
|
||||
```yaml tab="Docker"
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-auth.forwardauth.addAuthCookiesToResponse=Session-Cookie,State-Cookie"
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: test-auth
|
||||
spec:
|
||||
forwardAuth:
|
||||
address: https://example.com/auth
|
||||
addAuthCookiesToResponse:
|
||||
- Session-Cookie
|
||||
- State-Cookie
|
||||
```
|
||||
|
||||
```yaml tab="Consul Catalog"
|
||||
- "traefik.http.middlewares.test-auth.forwardauth.addAuthCookiesToResponse=Session-Cookie,State-Cookie"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
http:
|
||||
middlewares:
|
||||
test-auth:
|
||||
forwardAuth:
|
||||
address: "https://example.com/auth"
|
||||
addAuthCookiesToResponse:
|
||||
- "Session-Cookie"
|
||||
- "State-Cookie"
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[http.middlewares]
|
||||
[http.middlewares.test-auth.forwardAuth]
|
||||
address = "https://example.com/auth"
|
||||
addAuthCookiesToResponse = ["Session-Cookie", "State-Cookie"]
|
||||
```
|
||||
|
||||
### `tls`
|
||||
|
||||
_Optional_
|
||||
@@ -360,13 +347,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 +379,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 +397,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 +404,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 +438,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 +469,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 +503,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 +533,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 +554,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
|
||||
@@ -449,7 +406,7 @@ The `referrerPolicy` allows sites to control whether browsers forward the `Refer
|
||||
|
||||
!!! warning
|
||||
|
||||
Deprecated in favor of `permissionsPolicy`
|
||||
Deprecated in favor of [`permissionsPolicy`](#permissionsPolicy)
|
||||
|
||||
The `featurePolicy` allows sites to control browser features.
|
||||
|
||||
@@ -462,3 +419,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:
|
||||
|
206
docs/content/middlewares/http/ipallowlist.md
Normal file
206
docs/content/middlewares/http/ipallowlist.md
Normal file
@@ -0,0 +1,206 @@
|
||||
---
|
||||
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 }
|
||||
|
||||
IPAllowList limits allowed requests based on the client IP.
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
```yaml tab="Docker"
|
||||
# Accepts request from defined IP
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7"
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: test-ipallowlist
|
||||
spec:
|
||||
ipAllowList:
|
||||
sourceRange:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.7
|
||||
```
|
||||
|
||||
```yaml tab="Consul Catalog"
|
||||
# Accepts request from defined IP
|
||||
- "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-ipallowlist:
|
||||
ipAllowList:
|
||||
sourceRange:
|
||||
- "127.0.0.1/32"
|
||||
- "192.168.1.7"
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
# Accepts request from defined IP
|
||||
[http.middlewares]
|
||||
[http.middlewares.test-ipallowlist.ipAllowList]
|
||||
sourceRange = ["127.0.0.1/32", "192.168.1.7"]
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### `sourceRange`
|
||||
|
||||
_Required_
|
||||
|
||||
The `sourceRange` option sets the allowed IPs (or ranges of allowed IPs by using CIDR notation).
|
||||
|
||||
### `ipStrategy`
|
||||
|
||||
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`
|
||||
|
||||
The `depth` option tells Traefik to use the `X-Forwarded-For` header and take the IP located at the `depth` position (starting from the right).
|
||||
|
||||
- If `depth` is greater than the total number of IPs in `X-Forwarded-For`, then the client IP will be empty.
|
||||
- `depth` is ignored if its value is less than or equal to 0.
|
||||
|
||||
!!! 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 is `"12.0.0.1"` (`depth=2`).
|
||||
|
||||
| `X-Forwarded-For` | `depth` | clientIP |
|
||||
|-----------------------------------------|---------|--------------|
|
||||
| `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `1` | `"13.0.0.1"` |
|
||||
| `"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"
|
||||
# Allowlisting Based on `X-Forwarded-For` with `depth=2`
|
||||
labels:
|
||||
- "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"
|
||||
# Allowlisting Based on `X-Forwarded-For` with `depth=2`
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: test-ipallowlist
|
||||
spec:
|
||||
ipAllowList:
|
||||
sourceRange:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.7
|
||||
ipStrategy:
|
||||
depth: 2
|
||||
```
|
||||
|
||||
```yaml tab="Consul Catalog"
|
||||
# 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)"
|
||||
# Allowlisting Based on `X-Forwarded-For` with `depth=2`
|
||||
http:
|
||||
middlewares:
|
||||
test-ipallowlist:
|
||||
ipAllowList:
|
||||
sourceRange:
|
||||
- "127.0.0.1/32"
|
||||
- "192.168.1.7"
|
||||
ipStrategy:
|
||||
depth: 2
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
# Allowlisting Based on `X-Forwarded-For` with `depth=2`
|
||||
[http.middlewares]
|
||||
[http.middlewares.test-ipallowlist.ipAllowList]
|
||||
sourceRange = ["127.0.0.1/32", "192.168.1.7"]
|
||||
[http.middlewares.test-ipallowlist.ipAllowList.ipStrategy]
|
||||
depth = 2
|
||||
```
|
||||
|
||||
#### `ipStrategy.excludedIPs`
|
||||
|
||||
`excludedIPs` configures Traefik to scan the `X-Forwarded-For` header and select the first IP not in the list.
|
||||
|
||||
!!! important "If `depth` is specified, `excludedIPs` is ignored."
|
||||
|
||||
!!! example "Example of ExcludedIPs & X-Forwarded-For"
|
||||
|
||||
| `X-Forwarded-For` | `excludedIPs` | clientIP |
|
||||
|-----------------------------------------|-----------------------|--------------|
|
||||
| `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"12.0.0.1,13.0.0.1"` | `"11.0.0.1"` |
|
||||
| `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"15.0.0.1,13.0.0.1"` | `"12.0.0.1"` |
|
||||
| `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"10.0.0.1,13.0.0.1"` | `"12.0.0.1"` |
|
||||
| `"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"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourceRange=127.0.0.1/32, 192.168.1.0/24"
|
||||
- "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.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: test-ipallowlist
|
||||
spec:
|
||||
ipAllowList:
|
||||
sourceRange:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.0/24
|
||||
ipStrategy:
|
||||
excludedIPs:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.7
|
||||
```
|
||||
|
||||
```yaml tab="Consul Catalog"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourceRange=127.0.0.1/32, 192.168.1.0/24"
|
||||
- "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-ipallowlist:
|
||||
ipAllowList:
|
||||
sourceRange:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.0/24
|
||||
ipStrategy:
|
||||
excludedIPs:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.7
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
[http.middlewares]
|
||||
[http.middlewares.test-ipallowlist.ipAllowList]
|
||||
sourceRange = ["127.0.0.1/32", "192.168.1.0/24"]
|
||||
[http.middlewares.test-ipallowlist.ipAllowList.ipStrategy]
|
||||
excludedIPs = ["127.0.0.1/32", "192.168.1.7"]
|
||||
```
|
@@ -1,11 +1,20 @@
|
||||
---
|
||||
title: "Traefik HTTP Middlewares IPWhiteList"
|
||||
description: "Learn how to use IPWhiteList in HTTP middleware for limiting clients to specific IPs in Traefik Proxy. Read the technical documentation."
|
||||
---
|
||||
|
||||
# IPWhiteList
|
||||
|
||||
Limiting Clients to Specific IPs
|
||||
{: .subtitle }
|
||||
|
||||

|
||||

|
||||
|
||||
IPWhitelist accepts / refuses requests based on the client IP.
|
||||
IPWhiteList limits allowed requests based on the client IP.
|
||||
|
||||
!!! warning
|
||||
|
||||
This middleware is deprecated, please use the [IPAllowList](./ipallowlist.md) middleware instead.
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
@@ -16,7 +25,7 @@ labels:
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: test-ipwhitelist
|
||||
@@ -32,18 +41,6 @@ spec:
|
||||
- "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"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
# Accepts request from defined IP
|
||||
http:
|
||||
@@ -66,11 +63,16 @@ http:
|
||||
|
||||
### `sourceRange`
|
||||
|
||||
_Required_
|
||||
|
||||
The `sourceRange` option sets the allowed IPs (or ranges of allowed IPs by using CIDR notation).
|
||||
|
||||
### `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`
|
||||
|
||||
@@ -98,7 +100,7 @@ labels:
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
# Whitelisting Based on `X-Forwarded-For` with `depth=2`
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: test-ipwhitelist
|
||||
@@ -117,20 +119,6 @@ spec:
|
||||
- "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"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
# Whitelisting Based on `X-Forwarded-For` with `depth=2`
|
||||
http:
|
||||
@@ -172,18 +160,22 @@ http:
|
||||
```yaml tab="Docker"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourceRange=127.0.0.1/32, 192.168.1.0/24"
|
||||
- "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.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
|
||||
spec:
|
||||
ipWhiteList:
|
||||
ipStrategy:
|
||||
sourceRange:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.0/24
|
||||
excludedIPs:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.7
|
||||
@@ -191,37 +183,30 @@ spec:
|
||||
|
||||
```yaml tab="Consul Catalog"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
- "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourceRange=127.0.0.1/32, 192.168.1.0/24"
|
||||
- "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"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
http:
|
||||
middlewares:
|
||||
test-ipwhitelist:
|
||||
ipWhiteList:
|
||||
sourceRange:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.0/24
|
||||
ipStrategy:
|
||||
excludedIPs:
|
||||
- "127.0.0.1/32"
|
||||
- "192.168.1.7"
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.7
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
[http.middlewares]
|
||||
[http.middlewares.test-ipwhitelist.ipWhiteList]
|
||||
sourceRange = ["127.0.0.1/32", "192.168.1.0/24"]
|
||||
[http.middlewares.test-ipwhitelist.ipWhiteList.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"
|
||||
@@ -90,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
|
||||
@@ -141,52 +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.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",
|
||||
"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.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"
|
||||
- "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:
|
||||
@@ -249,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
|
||||
|
||||
* Each header value is a string that has been escaped in order to be a valid 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.
|
||||
|
||||
@@ -366,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:
|
||||
|
||||
@@ -440,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.
|
||||
@@ -447,8 +411,8 @@ 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
|
||||
```
|
||||
|
||||
And it is formatted as follows in the header:
|
||||
@@ -481,8 +445,8 @@ 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
|
||||
```
|
||||
|
||||
And it is formatted as follows in the header:
|
||||
|
@@ -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,69 +10,56 @@ 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.
|
||||
# In addition, a burst of 200 requests is allowed.
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-ratelimit.ratelimit.average=100"
|
||||
- "traefik.http.middlewares.test-ratelimit.ratelimit.burst=50"
|
||||
- "traefik.http.middlewares.test-ratelimit.ratelimit.burst=200"
|
||||
```
|
||||
|
||||
```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
|
||||
# In addition, a burst of 200 requests is allowed.
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: test-ratelimit
|
||||
spec:
|
||||
rateLimit:
|
||||
average: 100
|
||||
burst: 50
|
||||
burst: 200
|
||||
```
|
||||
|
||||
```yaml tab="Consul Catalog"
|
||||
# Here, an average of 100 requests per second is allowed.
|
||||
# In addition, a burst of 50 requests is allowed.
|
||||
# In addition, a burst of 200 requests is allowed.
|
||||
- "traefik.http.middlewares.test-ratelimit.ratelimit.average=100"
|
||||
- "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.
|
||||
# In addition, a burst of 200 requests is allowed.
|
||||
http:
|
||||
middlewares:
|
||||
test-ratelimit:
|
||||
rateLimit:
|
||||
average: 100
|
||||
burst: 50
|
||||
burst: 200
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
# Here, an average of 100 requests per second is allowed.
|
||||
# In addition, a burst of 50 requests is allowed.
|
||||
# In addition, a burst of 200 requests is allowed.
|
||||
[http.middlewares]
|
||||
[http.middlewares.test-ratelimit.rateLimit]
|
||||
average = 100
|
||||
burst = 50
|
||||
burst = 200
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
@@ -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,15 @@ http:
|
||||
|
||||
Name of the header used to group incoming requests.
|
||||
|
||||
```yaml tab="Docker"
|
||||
!!! important "If the header is not present, rate limiting will still be applied, but all requests without the specified header will be grouped together."
|
||||
|
||||
```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 +381,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 +401,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 +421,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,18 +75,18 @@ 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).
|
||||
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).
|
||||
|
||||
### `forceSlash`
|
||||
|
||||
_Optional, Default=true_
|
||||
|
||||
!!! warning
|
||||
|
||||
`forceSlash` option is deprecated and should not be used.
|
||||
|
||||
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`
|
||||
@@ -125,7 +118,7 @@ labels:
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: example
|
||||
@@ -136,19 +129,6 @@ spec:
|
||||
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:
|
||||
|
@@ -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!}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user