1
0
mirror of https://github.com/containous/traefik.git synced 2025-08-24 09:49:31 +03:00

Compare commits

...

2921 Commits

Author SHA1 Message Date
fc0fac8543 Add passive health checks 2025-08-21 11:40:06 +02:00
c20802b07e Merge branch v3.5 into master 2025-08-05 15:17:05 +02:00
16c536e83a Restore missing migration section 2025-08-04 16:52:04 +02:00
1827652258 Merge branch v2.11 into v3.5 2025-08-01 16:42:28 +02:00
19a2e2efc5 Allow maintainers to run deploy documentation 2025-08-01 12:10:05 +02:00
b350ad7f7c Update Traefik Proxy dashboard UI development deps 2025-08-01 11:42:05 +02:00
bcdb70b689 Fix invalid links in documentation 2025-08-01 11:34:05 +02:00
860159315d Fix mispelling in docs 2025-07-31 15:48:05 +02:00
a274f52924 Merge branch v3.4 into v3.5 2025-07-29 17:10:28 +02:00
cf1e582af5 Add Traefik Hub Middlewares To Reference Section 2025-07-29 16:02:52 +02:00
9896192efb Update releases docs for v3.5 2025-07-29 16:00:06 +02:00
ba0f7364f1 Update Migration Docs 2025-07-24 18:06:04 +02:00
40bdea4db8 chore: add extend documentation 2025-07-24 17:58:04 +02:00
31db97cbe4 Add back the link to Peka's page 2025-07-24 16:06:04 +02:00
5d85e6d088 Provide Log Body in OTEL access Log 2025-07-24 11:52:04 +02:00
c0edcc09bb Bump github.com/go-acme/lego/v4 to v4.25.1 2025-07-24 09:54:05 +02:00
24cede62ee Merge branch v3.5 into master 2025-07-24 09:03:26 +02:00
2cbd96e64c Prepare release v3.5.0 2025-07-23 15:46:04 +02:00
4576155005 Remove dead link to Peka blog 2025-07-23 15:04:08 +02:00
2dcc1c16b7 Merge branch v3.4 into v3.5 2025-07-23 14:38:33 +02:00
43162507e3 Add a note for the removal of default MPTCP enablement in the migration guide 2025-07-23 12:04:04 +02:00
2ed2123fc0 Add constraints key limitations for label providers 2025-07-23 11:40:04 +02:00
9bf14b6764 Prepare release v3.4.5 2025-07-23 11:16:04 +02:00
16d43aefd7 Merge branch v2.11 into v3.4 2025-07-23 10:41:06 +02:00
c6daab54e3 Prepare release v2.11.28 2025-07-23 10:34:04 +02:00
a59bcb29b5 Improve integration tests 2025-07-23 09:56:04 +02:00
117e0b4471 Add extended NGinX annotation support documentation 2025-07-23 09:30:05 +02:00
028e8ca0b0 Revert 11711 adding url param to healthcheck command 2025-07-22 17:10:05 +02:00
6486cf95d8 Merge branch v2.11 into v3.4 2025-07-22 16:11:58 +02:00
50931813f2 Remove all mentions of ordering for TLSOption CurvePreferences field 2025-07-22 15:44:05 +02:00
96386b1d78 Bump github.com/quic-go/quic-go to v0.54.0 2025-07-22 14:54:04 +02:00
5ef853a0c5 Fix client arbitrary file access during archive extraction zipslip 2025-07-22 14:24:05 +02:00
b2b4b66b08 Disable MPTCP by default
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-07-22 11:10:05 +02:00
78cc85283c Add k8s resource attributes automatically
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-07-21 12:06:04 +02:00
27326e6569 Redact logged install configuration 2025-07-18 17:16:04 +02:00
7b78128d4e Add resourceAttributes option to OTel metrics
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-07-18 17:08:04 +02:00
8c23eb6833 Introduce trace verbosity config and produce less spans by default 2025-07-18 15:32:05 +02:00
f2b7d7f6e1 Fix typo 2025-07-17 15:28:05 +02:00
5c94bbf122 Merge branch v3.5 into master 2025-07-11 16:17:14 +02:00
77ef7fe490 Prepare release v3.5.0-rc2 2025-07-11 11:24:04 +02:00
ff992fb7f9 Merge branch v3.4 into v3.5 2025-07-11 10:29:18 +02:00
95434e870b Prepare release v3.4.4 2025-07-11 10:26:04 +02:00
aa1c0d8686 Merge branch v2.11 into v3.4 2025-07-11 09:35:25 +02:00
7ca90a4b18 Prepare release v2.11.27 2025-07-11 09:30:05 +02:00
a3685ee9fa Bump github.com/go-viper/mapstructure/v2 to v2.3.0 2025-07-10 16:10:05 +02:00
ba595bfa98 Fix concurrent access to balancer status map in WRR and P2C strategies 2025-07-10 16:08:04 +02:00
9a46d35169 Update index.md to include full Traefik Platform context 2025-07-09 11:54:04 +02:00
955f484d33 Fix label for overriding swarm network on container 2025-07-08 17:46:05 +02:00
cdacf0bca8 Respect service.nativelb=false annotation when nativeLBByDefault is enabled 2025-07-08 11:58:04 +02:00
91331415ce Add missing resource attributes detectors 2025-07-07 15:36:04 +02:00
d674b393a8 Add New Expose Guides to the Documentation 2025-07-04 10:14:04 +02:00
137efedba7 Update Logs and Accesslogs Reference Documentation with OTLP Options 2025-07-01 08:54:04 +02:00
c69a8b5cdb Add New Setup Guides to the Documentation 2025-06-30 09:28:04 +02:00
9862cd6780 Prepare release v3.5.0-rc1 2025-06-26 16:44:04 +02:00
4af188242c Merge branch v3.4 into master 2025-06-26 15:39:55 +02:00
b0e246cea9 Prepare release v3.4.3 2025-06-26 15:18:04 +02:00
c9c8cd6b50 Bump quic-go to v.0.49.0 2025-06-26 14:46:04 +02:00
c02ec6857f Merge branch v3.4 into master 2025-06-26 14:12:07 +02:00
a519180665 Prepare release v3.4.2 2025-06-26 12:30:04 +02:00
e223116225 Merge branch v2.11 into v3.4 2025-06-26 12:05:16 +02:00
8ae0379171 Prepare release v2.11.26 2025-06-26 11:50:04 +02:00
2d98795cc5 Merge current branch v3.4 into master 2025-06-25 14:31:25 +02:00
4daf13b866 Update the EntryPoints Documentation 2025-06-25 14:30:04 +02:00
cbfecc5d49 Merge branch v3.4 into master 2025-06-25 11:14:51 +02:00
c2c488ffc5 Remove conflicting information from the CircuitBreaker documentation. 2025-06-25 11:12:04 +02:00
56a95d6c16 Add url option to healthcheck command 2025-06-24 10:56:09 +02:00
9bd5c61782 NGINX Ingress Provider
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-06-23 18:06:04 +02:00
107efb8a5a Add New Observe Guides to the Documentation 2025-06-23 17:06:04 +02:00
0f862f4792 Update Getting started Section with New Docker and Kubernetes Tutorial 2025-06-20 17:36:04 +02:00
74eafcd044 Merge branch v2.11 into v3.4 2025-06-11 10:03:28 +02:00
b0d8e08e2b Fix typo in redirect middleware documentation 2025-06-11 09:46:05 +02:00
b39ee8ede5 OCSP stapling 2025-06-06 17:44:04 +02:00
917771739e Add a note about Ingress Backend Resource support 2025-06-04 16:22:04 +02:00
Ben
2949995abc Handle context canceled in ForwardAuth middleware 2025-06-04 15:38:04 +02:00
ae79d4e5f0 Do not log redis sentinel username and password 2025-06-04 12:08:04 +02:00
aac8bc69ad Clarify mirroring service default percent value 2025-06-04 11:18:04 +02:00
bfcef58a4f Fix KV reference rendering 2025-06-03 16:56:04 +02:00
bf72b9768c Introduce X25519MLKEM768 for Post-Quantum-Secure TLS 2025-06-03 11:44:05 +02:00
f7a6f32784 Update Dockerfiles to Alpine 3.22 2025-06-03 11:24:05 +02:00
fd5796ac39 Improve visualization for StatusRewrites option of errors middleware 2025-06-03 10:02:04 +02:00
ce1b13f228 Bump sigs.k8s.io/gateway-api to v1.3.0 2025-06-03 09:20:04 +02:00
289d6e5dca Merge branch v3.4 into master 2025-06-02 17:01:46 +02:00
fe5c7fdc65 Add a note to certificatesDuration 2025-06-02 16:22:04 +02:00
92f798dfcd Update supported versions 2025-06-02 16:08:04 +02:00
bd4bfd8919 Merge branch v2.11 into v3.4 2025-06-02 15:50:06 +02:00
f174014d96 feat: parallelise unit tests 2025-06-02 11:00:05 +02:00
2fdee25bb3 Attempt to fix TestProxyFromEnvironment test
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-06-02 10:46:04 +02:00
cd16321dd9 Bump to go1.24
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-06-02 10:36:05 +02:00
0b4058dde0 Remove obsolete version field in compose files 2025-05-28 17:16:08 +02:00
6a54f1f66c Add WebSocket guide 2025-05-28 11:46:04 +02:00
f16fff577a Migrate Traefik Proxy dashboard UI to React 2025-05-28 11:26:04 +02:00
8b495b45a5 Prepare release v3.4.1 2025-05-27 14:32:04 +02:00
4b68e674eb Merge branch v2.11 into v3.4 2025-05-27 14:00:30 +02:00
5f35c88805 Prepare release v2.11.25 2025-05-27 12:10:05 +02:00
859f4e8868 Use routing path in v3 matchers
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-05-27 11:06:05 +02:00
de1802d849 Merge branch v2.11 into v3.4 2025-05-27 09:51:59 +02:00
a3745d1eb2 Match encoded certificate to example data for tlspassthrough 2025-05-27 09:46:04 +02:00
23c7c78a1a Add HTTP/2 maxConcurrentStream parameter test 2025-05-27 09:34:04 +02:00
fa18c35a9a Refactor new muxer to have only one parser instance 2025-05-26 17:12:08 +02:00
55e6d327bc acme.md: specify which file should be specified between restarts 2025-05-26 15:50:04 +02:00
be0b54bade Merge branch v2.11 into v3.4 2025-05-23 16:16:18 +02:00
ab3234e458 Scope the rate limit counter key by source AND by middleware 2025-05-23 15:38:04 +02:00
08d5dfee01 Normalize request path
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-05-23 15:10:05 +02:00
b669981018 Fix panic for ingress with backend resource
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-05-23 14:56:05 +02:00
76153acac6 Fix CEL validation for RootCA in ServersTransport
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-05-23 11:34:05 +02:00
06b02bcd95 Do not display RemoveHeader option when not defined
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-05-23 10:44:40 +02:00
4790e4910f Make the behavior of prefix matching in Ingress consistent with Kubernetes doc 2025-05-20 14:40:05 +02:00
3deea566ac Make P2C strategy thread-safe 2025-05-19 09:52:05 +02:00
79fde2b6dd Do not warn network missing if connected to a container network 2025-05-19 09:26:09 +02:00
aa5f2b92d4 Fix broken link in documentation 2025-05-16 12:02:04 +02:00
8c6ed23c5f Merge branch v3.4 into master 2025-05-14 09:55:58 +02:00
9ee0e43eac Merge current v2.11 into v3.4 2025-05-14 09:34:13 +02:00
6b9738e675 GOGC empty default value for build 2025-05-14 09:32:04 +02:00
b82290ac5b Adding garbage collector as variable in compilation 2025-05-13 16:02:04 +02:00
3ee316c5bb Fix incorrect case and missing rbac in documentation 2025-05-13 11:04:05 +02:00
c5f7381c80 Merge current v3.4 into master 2025-05-13 09:33:27 +02:00
0dc5b7d013 Merge current v2.11 into v3.4 2025-05-12 15:06:32 +02:00
49b598d087 tests: create redis sentinel config with permissive perms 2025-05-12 14:30:04 +02:00
448785d830 Add multi-tenant TLS guidance to the docs 2025-05-07 09:16:04 +02:00
ce42e8501e Prepare release v3.4.0 2025-05-05 15:34:04 +02:00
bf399f3075 Merge branch v3.3 into v3.4 2025-05-05 11:08:36 +02:00
74bc93308b Prepare release v3.3.7 2025-05-05 10:38:04 +02:00
dddb68cd5f Allow configuration of ACME provider http timeout 2025-04-28 14:30:06 +02:00
87b57406ff Add SpanID and TraceID accessLogs fields only when tracing is enabled 2025-04-28 14:26:05 +02:00
9bc71b0010 Add a note about how to disable connection reuse with backends 2025-04-28 09:10:04 +02:00
8f37c8f0c5 Ability to enable unsafe in yaegi through plugin manifest 2025-04-25 11:26:04 +02:00
a092c4f535 Merge branch v3.4 into master 2025-04-18 16:42:34 +02:00
9d0e76baa8 Prepare release v3.4.0 rc2 2025-04-18 14:24:04 +02:00
9c1902c62e Merge branch v3.3 into v3.4 2025-04-18 11:49:36 +02:00
b05ec75f98 Prepare release v3.3.6 2025-04-18 11:10:04 +02:00
2d617b3a65 Remove default load-balancing strategy from CRD 2025-04-18 10:58:04 +02:00
ec6deb40ab Merge branch v2.11 into v3.3 2025-04-18 10:45:03 +02:00
160edff257 Change version for path sanitization migration guide 2025-04-18 10:42:04 +02:00
8816cb86a4 Prepare release v2.11.24 2025-04-18 09:34:04 +02:00
316be0782c Add content-length best practice documentation 2025-04-18 08:12:04 +02:00
30d836f963 Merge branch v2.11 into v3.3 2025-04-17 17:02:40 +02:00
14da838a21 Bump github.com/redis/go-redis/v9 to v9.7.3 2025-04-17 16:56:05 +02:00
f6fb240eb6 Merge branch v2.11 into v3.3 2025-04-17 16:18:33 +02:00
a75b2384ea Prepare release v2.11.23 2025-04-17 11:56:03 +02:00
8bdca45861 Bump gopkg.in/DataDog/dd-trace-go.v1 to v1.72.2 2025-04-17 11:48:04 +02:00
7442162e3f Bump golang.org/x/net to v0.38.0 2025-04-17 10:16:04 +02:00
dd5cb68cb1 Sanitize request path 2025-04-17 10:02:04 +02:00
299a16f0a4 Bump github.com/go-acme/lego/v4 to v4.23.1 2025-04-17 09:20:04 +02:00
545f2feacc Add Content-Length header to preflight response 2025-04-16 15:00:05 +02:00
e3caaf0791 Bump golang.org/x/oauth2 to v0.28.0 2025-04-16 11:58:04 +02:00
746cc80d0f Bump github.com/redis/go-redis/v9 to v9.7.3 2025-04-15 11:40:04 +02:00
fd0fd39642 Typos on what is Traefik docs page 2025-04-15 09:22:04 +02:00
f794f8a294 chore: update linter 2025-04-11 10:56:05 +02:00
8cf22207b5 Typo fix on the Explanation Section for User Guide HTTP Challenge. 2025-04-11 10:18:04 +02:00
5e44a138a8 Update Welcome Page 2025-04-10 14:56:04 +02:00
0664367c53 Document how to pass multiple Headers on tracing with CLI 2025-04-09 10:20:05 +02:00
d7d0017545 Add unhealthy Interval to the health check configuration 2025-04-09 10:10:05 +02:00
bb8dfa568a Restrict regex validation of HTTP status codes for Ingress CRD resources 2025-04-08 09:38:04 +02:00
88c5e6a3fd Remove empty (v2) CRD definition file 2025-04-08 09:36:04 +02:00
2965aa42cc Fix Kubernetes Gateway statusAddress documentation 2025-04-03 10:02:04 +02:00
6c3b099c25 Add acme.httpChallenge.delay option 2025-04-01 17:08:05 +02:00
405be420c9 Prepare release v3.4.0-rc1 2025-03-31 15:42:05 +02:00
ec38a0675f Merge branch v3.3 into master 2025-03-31 10:43:49 +02:00
bd4ff81818 Prepare release v3.3.5 2025-03-31 10:38:04 +02:00
e817d822d7 Merge branch v2.11 into v3.3 2025-03-31 10:04:06 +02:00
b7be71c02a Prepare release v2.11.22 2025-03-31 09:48:04 +02:00
6e9d713668 Bump github.com/vulcand/oxy/v2 to v2.0.3 2025-03-31 09:24:06 +02:00
ddb32ef86f Allow underscore character in hostSNI matcher 2025-03-28 11:36:04 +01:00
496f00c7c2 Revert compress middleware algorithms priority to v2 behavior
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-03-28 11:30:05 +01:00
f0cd6f210b Add support to disable session ticket 2025-03-28 10:58:04 +01:00
c910ceeb00 Merge branch v2.11 into v3.3 2025-03-27 09:38:43 +01:00
2087e11f55 Bump nokogiri to 1.18.6 and html-proofer to 5.0.10 2025-03-26 17:52:05 +01:00
42778d2ba6 Do not abort request when response content-type is malformed 2025-03-26 11:30:05 +01:00
a5d46fc6ef Change boolean module properties default value to undefined 2025-03-26 10:22:05 +01:00
84742275a4 Bump golang.org/x/net to v0.37.0 2025-03-26 10:06:05 +01:00
54a2d657f3 Bump github.com/redis/go-redis/v9 to v9.6.3 2025-03-26 09:48:05 +01:00
08b90ade94 Bump github.com/golang-jwt/jwt to v4.5.2 and v5.2.2 2025-03-26 09:30:05 +01:00
bb7ef7b48a Deprecate defaultRuleSyntax and ruleSyntax options
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-03-21 11:02:04 +01:00
8ba99adc50 Error level log for configuration-related TLS errors with backends
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-03-21 11:00:06 +01:00
50b0d772e5 Add acme.profile and acme.emailAddresses options 2025-03-17 10:00:07 +01:00
b02946147d Bump golang.org/x/net to v0.36.0 2025-03-14 09:24:05 +01:00
137c632793 Add Security Support 2025-03-14 09:10:04 +01:00
e76b65f44d Add Security Support column in deprecation section 2025-03-13 17:08:15 +01:00
55ebaee4a7 Clarifies that retry middleware uses TCP, not HTTP status codes 2025-03-13 09:44:04 +01:00
5953331c73 Add back forwarded headers section in FAQ 2025-03-13 09:42:04 +01:00
ae4a00b4bc Allow root CA to be added through config maps 2025-03-11 15:38:05 +01:00
4ff76e13c4 Remove documentation for OriginStatusLine and DownstreamStatusLine accessLogs fields 2025-03-11 15:32:04 +01:00
30fe11eccf Merge branch v3.3 into master 2025-03-10 16:48:27 +01:00
05eb438ae1 Merge branch v2.11 into v3.3 2025-03-10 16:07:04 +01:00
b7170df2c3 New Routing Reference Documentation 2025-03-10 15:28:06 +01:00
9e029a84c4 Add p2c load-balancing strategy for servers load-balancer
Co-authored-by: Ian Ross <ifross@gmail.com>
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-03-10 12:12:04 +01:00
14e400bcd0 Bump AWS SDK to v2 2025-03-10 11:50:04 +01:00
550d96ea67 Add Redis rate limiter 2025-03-10 11:02:05 +01:00
3c99135bf9 Set scheme to https with BackendTLSPolicy
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-03-07 16:56:04 +01:00
474ab23fe9 Compress data on flush when compression is not started
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-03-07 16:16:04 +01:00
c166a41c99 Improve CEL validation on Ingress CRD resources 2025-03-06 15:48:04 +01:00
740b4cfd25 Support domain configuration for sticky cookies 2025-03-06 09:38:04 +01:00
7cfd10db62 Update codegen to v0.30.10 2025-03-05 10:20:05 +01:00
fa76ed57d3 Support rewriting status codes in error page middleware 2025-03-03 11:54:04 +01:00
9d8a42111f Add tip for dynamic configuration updates of Redis 2025-02-28 14:18:05 +01:00
0dfd12ee61 Bump github.com/go-jose/go-jose/v4 to v4.0.5 2025-02-25 14:06:04 +01:00
07e6491ace Prepare release v3.3.4 2025-02-25 11:04:04 +01:00
32ea014d07 Merge branch v2.11 into v3.3 2025-02-25 10:06:03 +01:00
a3fd484728 Prepare release v2.11.21 2025-02-24 15:32:06 +01:00
9b0348577a Update ACME provider configuration options 2025-02-24 15:26:06 +01:00
efe03bc9da Fix incorrect grammar in ACME documentation 2025-02-24 10:42:06 +01:00
cce935493a Fix panic when calling Tracer 2025-02-24 10:26:39 +01:00
f196de90e1 Enable the retry middleware in the proxy
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-02-21 11:36:05 +01:00
c2a294c872 Retry should send headers on Write
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-02-21 10:52:04 +01:00
8e5d4c6ae9 Bum github.com/go-acme/lego/v4 to v4.22.2 2025-02-21 09:36:04 +01:00
f0849e8ee6 Merge branch v3.3 into master 2025-02-19 10:48:30 +01:00
1ccbf743cb Add WebSocket headers if they are present in the request
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-02-17 20:20:05 +01:00
1cfcf0d318 Chunked responses does not have a Content-Length header
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-02-14 17:44:04 +01:00
eb07a5ca1a Bump github.com/traefik/paerser to v0.2.2
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-02-14 11:24:04 +01:00
56ea028e81 Change request duration metric unit from millisecond to second
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-02-14 11:22:04 +01:00
05c547f211 Fix double hash in sticky cookie 2025-02-13 16:42:08 +01:00
dcd9f2ea96 Replace globalAttributes with resourceAttributes in tracing reference 2025-02-13 14:58:05 +01:00
84e20aa9c3 chore: update linter 2025-02-12 10:02:04 +01:00
b5a5e259ed Bump github.com/valyala/fasthttp to v1.58.0 2025-02-11 14:26:04 +01:00
8488214e93 Add missing options in entrypoints page 2025-02-10 15:20:04 +01:00
b74767bfa4 Use ResourceAttributes instead of GlobalAttributes 2025-02-06 11:24:04 +01:00
786d9f3272 Merge branch v3.3 into master 2025-01-31 16:23:49 +01:00
da2278b29a Prepare release v3.3.3 2025-01-31 15:46:04 +01:00
cfebed7328 Merge branch v2.11 into v3.3 2025-01-31 15:20:12 +01:00
4e441d09ed Prepare release v2.11.20 2025-01-31 15:16:04 +01:00
8f5dd7bd9d Change docker-compose to docker compose 2025-01-31 14:30:05 +01:00
d04e2d717c Add missing headerField in Middleware CRD 2025-01-31 14:28:06 +01:00
cdd24e91b4 Fix content-length header assertion
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-01-31 12:00:05 +01:00
4fd6b10b7d Merge branch v2.11 into v3.3 2025-01-31 11:14:59 +01:00
86315e0f18 Fix ACME write when traefik is shutting down 2025-01-31 11:06:04 +01:00
c20af070e3 Set check-latest to true in Go setup 2025-01-30 14:06:04 +01:00
8593581cbf Fix integration tests for HTTPS 2025-01-29 17:04:05 +01:00
857fbb933e Do not create observability model by default
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-01-29 13:56:04 +01:00
8103992977 Prepare release v2.11.19 2025-01-29 11:36:08 +01:00
c5b92b5260 Do not create a logger instance for each proxy 2025-01-27 11:24:04 +01:00
2afa03b55c Add option to preserve request method in forwardAuth 2025-01-23 14:28:04 +01:00
2b6a04bc1d Set rule priority in Gateway API TLSRoute 2025-01-23 11:46:04 +01:00
fb527dac1c Handle responses without content length header
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-01-23 10:00:05 +01:00
ef887332c2 Add auto webui theme option and default to it 2025-01-23 09:36:04 +01:00
c19cf125e8 Fix auto refresh not clearing on component unmount 2025-01-21 14:58:04 +01:00
261e4395f3 Add support for UDP routing in systemd socket activation 2025-01-21 09:38:09 +01:00
435d28c790 changing log message when client cert is not available to debug 2025-01-17 09:42:04 +01:00
4ce4bd7121 Bring back TraceID and SpanID fields in access logs
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2025-01-15 16:26:08 +01:00
020ab5f347 Prepare release v3.3.2 2025-01-14 16:46:04 +01:00
ad7fb8e82b Fix observability configuration on EntryPoints 2025-01-14 16:28:05 +01:00
0528c054a6 Do not read response body for HEAD requests
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2025-01-14 15:16:05 +01:00
ad99c5bbea Update Gateway API CRDs for integration tests 2025-01-14 10:36:04 +01:00
8272be0eda Remove awesome.traefik.io reference in documentation section 2025-01-13 10:28:04 +01:00
0a6ff446c7 Fix deprecated dnsChallenge propagation logging and documentation 2025-01-13 10:06:04 +01:00
9a9644bafe Set content-type when serving webui index 2025-01-13 09:18:04 +01:00
95dd17e020 Allow configuring server URLs with label providers 2025-01-09 17:20:06 +01:00
b0a72960bc Merge branch v3.3 into master 2025-01-08 11:29:59 +01:00
a57e118a1a Merge branch v2.11 into v3.3 2025-01-08 11:10:59 +01:00
d2414feaff Add test to check that SettingEnableConnectProtocol frame is not sent 2025-01-08 11:02:37 +01:00
6aa56788ea Add missing trailing s to propagation.delayBeforeCheck option 2025-01-08 09:36:04 +01:00
1aa450c028 Prepare release v2.11.18 2025-01-07 16:24:04 +01:00
f9ff6049d3 Disable http2 connect setting for websocket by default
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
Co-authored-by: Michael <michael.matur@gmail.com>
2025-01-07 16:12:04 +01:00
d4d61151e1 Prepare release v3.3.1 2025-01-07 15:46:04 +01:00
456188fa0d Merge current branch v3.2 into v3.3 2025-01-07 15:14:43 +01:00
03c170f264 Prepare release v3.2.5 2025-01-07 15:10:04 +01:00
7cb46626a1 Disable http2 connect setting for websocket by default
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
Co-authored-by: Michael <michael.matur@gmail.com>
2025-01-07 14:58:04 +01:00
5b53bae42d Prepare release v3.3.0 2025-01-06 12:04:04 +01:00
caf56e6aed Merge branch v3.2 into v3.3 2025-01-06 11:13:12 +01:00
69c8ecfa99 Prepare release v3.2.4 2025-01-06 11:04:04 +01:00
7db2bbb4a3 Merge branch v2.11 into v3.2 2025-01-06 10:29:57 +01:00
ee8305549a Allow release only on traefik/traefik repo 2025-01-06 10:28:04 +01:00
a31b026364 Prepare release v2.11.17 2025-01-06 10:00:07 +01:00
20d496268c Fix typo in basicauth note 2025-01-06 09:36:08 +01:00
6d3a685d5a Add ingress status for ClusterIP and NodePort Service Type 2025-01-03 16:10:04 +01:00
845d0b5ac7 Merge current v3.3 into master 2025-01-03 15:36:10 +01:00
34aa3b75b8 Merge current v3.2 into v3.3 2025-01-03 15:07:43 +01:00
f62fc67418 Merge current v2.11 into v3.2 2025-01-03 14:50:43 +01:00
5f3c30e37b chore: update linter 2025-01-03 09:58:04 +01:00
139f929ec8 Support empty value for core Kubernetes API group 2025-01-03 09:56:04 +01:00
e20409676a Upgrade github.com/spiffe/go-spiffe/v2 to v2.4.0 2025-01-03 09:38:04 +01:00
d152f7fafc Merge current v3.2 into v3.3 2025-01-02 19:32:34 +01:00
ee449db656 Merge current v2.11 into v3.2 2025-01-02 17:15:11 +01:00
38ac1e75a2 Update go-acme/lego to v4.21.0 2025-01-02 12:46:04 +01:00
109a8712cc Update copyright for 2025 2025-01-02 12:08:04 +01:00
278e739242 Fix allowACMEByPass TOML example 2024-12-30 16:08:03 +01:00
db31a4c961 Add webui static files in release tarball 2024-12-20 16:46:04 +01:00
a1099bf8d0 Merge branch v3.2 into v3.3 2024-12-20 15:55:24 +01:00
596aadfe68 Merge branch v2.11 into v3.2 2024-12-20 15:19:30 +01:00
35ce6baaae Bump golang.org/x/net to v0.33.0 2024-12-20 14:36:06 +01:00
95f20fc753 Configure ErrorLog in httputil.ReverseProxy 2024-12-20 14:18:04 +01:00
d9f58f94a2 Prepare release v3.3.0-rc2 2024-12-20 11:52:04 +01:00
a29628fa2e Fix fenced server status computation
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-12-20 11:26:04 +01:00
e280716645 Update Gateway API version support to v1.2.1 2024-12-19 11:12:04 +01:00
f1c4ba2f26 Remove duplicate github.com/coreos/go-systemd dependency 2024-12-19 09:20:04 +01:00
a870c2af9b Add @jnoordsij to maintainers 2024-12-17 15:34:04 +01:00
aa8eb1af6e Replace experimental maps and slices with stdlib 2024-12-17 11:24:04 +01:00
189db8d990 Pass TLS bool from IngressRouteTCP to TCPService 2024-12-17 10:12:04 +01:00
68a8650297 Prepare Release v3.3.0-rc1 2024-12-16 15:30:05 +01:00
1a5ea1c597 Merge branch v3.2 into master 2024-12-16 11:30:15 +01:00
8983e45fcf Prepare release v3.2.3 2024-12-16 11:20:04 +01:00
ec214fa825 Merge branch v2.11 into v3.2 2024-12-16 10:51:44 +01:00
1c0094048b Prepare release v2.11.16 2024-12-16 10:48:04 +01:00
3a3ffab689 Update reference install documentation with current chart default 2024-12-13 11:14:06 +01:00
2302debac2 Add an option to preserve the ForwardAuth Server Location header 2024-12-13 10:38:37 +01:00
4974d9e4d7 Merge branch v3.2 into master 2024-12-12 15:47:51 +01:00
33cf06b36a Merge branch v2.11 into v3.2 2024-12-12 15:20:22 +01:00
590ddfc990 Update nokogiri gem to v1.16.8 2024-12-12 15:12:04 +01:00
39d7b77609 Bump Dockerfile to Alpine v3.21 2024-12-12 14:44:05 +01:00
e85d02c530 Add support dump API endpoint 2024-12-12 14:12:04 +01:00
74e0abf8bf Update golang.org/x dependencies 2024-12-12 13:02:04 +01:00
d953ee69b4 Add exprimental flag for OTLP logs integration 2024-12-12 12:22:05 +01:00
26738cbf93 Send request body to authorization server for forward auth 2024-12-12 10:18:05 +01:00
b1934231ca Manage observability at entrypoint and router level
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-12-12 09:52:07 +01:00
9588e51146 Implementation of serving not ready endpoints 2024-12-11 13:54:05 +01:00
e87da0f390 Prepare release v3.2.2 2024-12-10 15:48:04 +01:00
8eb12795d7 Merge current branch v2.11 into v3.2 2024-12-10 15:04:04 +01:00
cc14c165c0 Prepare release v2.11.15 2024-12-10 14:18:04 +01:00
f2ba4353b2 Fix experimental build ci 2024-12-10 12:12:05 +01:00
514914639a Rename traefik.docker.* labels for Docker Swarm to traefik.swarm.* 2024-12-10 09:48:05 +01:00
a4c0b1649d Create FUNDING.yml 2024-12-09 14:46:05 +01:00
f547f1b22b Update sigs.k8s.io/gateway-api to v1.2.1 2024-12-09 09:44:05 +01:00
42df9afeaf Fix release by using github action 2024-12-06 16:56:06 +01:00
c8b0285c91 Fix WASM settings 2024-12-06 16:38:05 +01:00
2df655cefe Update github.com/quic-go/quic-go to v0.48.2 2024-12-06 16:36:05 +01:00
826a2b74aa OpenTelemetry Logs and Access Logs
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-12-06 14:50:04 +01:00
47b4df71bf New Install Reference Documentation 2024-12-06 10:14:07 +01:00
2b35c7e205 Fix models mechanism for default rule syntax
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-11-29 10:52:05 +01:00
33c1d700c0 Add options to control ACME propagation checks 2024-11-26 09:08:04 +01:00
536e11d949 Move callout to the entrypoint page footer 2024-11-25 17:22:04 +01:00
0ec12c7aa7 Configurable API & Dashboard base path
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-11-25 11:52:04 +01:00
c120b70483 Update go-acme/lego to v4.20.4 2024-11-22 09:54:04 +01:00
ab0713d587 Fix incorrect links in v3 migration sections 2024-11-22 09:44:04 +01:00
090db6d4b0 Merge branch v3.2 into master 2024-11-21 14:53:27 +01:00
5cfc11fe68 Prepare release v3.2.1 2024-11-20 17:28:04 +01:00
8a0c1e614f Fix HostRegexp config for rule syntax v2
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-11-20 17:04:04 +01:00
394f97bc48 Merge branch v2.11 into v3.2 2024-11-20 15:37:27 +01:00
8eadfbb990 Prepare release v2.11.14 2024-11-20 15:26:04 +01:00
ca5b70e196 Merge branch v2.11 into v3.2 2024-11-20 14:21:43 +01:00
cc80568d9e Fix internal handlers ServiceBuilder composition 2024-11-19 14:52:04 +01:00
8ffd1854db Fix the defaultRule CLI examples 2024-11-18 14:40:05 +01:00
6baa110adb Update access-logs.md, add examples for accesslog.format 2024-11-18 11:58:04 +01:00
5658c8ac06 Fix spelling, grammar, and rephrase sections for clarity in some documentation pages 2024-11-18 11:42:04 +01:00
1c80f12bc2 Apply keepalive config to h2c entrypoints 2024-11-18 09:56:04 +01:00
ef5f1b1508 Improve documentation on dashboard 2024-11-14 11:14:04 +01:00
fdce8c604a Change level of peeking first byte error log to DEBUG for Postgres 2024-11-12 17:34:04 +01:00
8c19652361 Fix absolute link in the migration guide 2024-11-12 17:06:03 +01:00
b7b4dd9554 Merge branch v2.11 into v3.2 2024-11-12 16:24:22 +01:00
e5c80637fc Add X-Forwarded-Prefix to the migration guide
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-11-12 15:04:04 +01:00
f437fb4230 chore: update linter 2024-11-12 10:56:06 +01:00
9c50129520 Update go-acme/lego to v4.20.2 2024-11-12 10:32:09 +01:00
00a5f4c401 Fix a small typo in entrypoints documentation 2024-11-12 10:14:04 +01:00
a79cdd1dfa Change level of peeking first byte error log to DEBUG
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-11-08 14:28:08 +01:00
2096fd7081 Drop untrusted X-Forwarded-Prefix header
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-11-08 12:12:35 +01:00
ec00c4aa42 Configurable path for sticky cookies 2024-11-06 16:04:04 +01:00
552bd8f180 Add AbortOnPluginFailure option to abort startup on plugin load failure 2024-11-06 11:58:04 +01:00
f70949e3fa Fix case problem for websocket upgrade 2024-11-06 09:56:04 +01:00
97caf758ef Make the IngressRoute kind optional 2024-11-04 16:26:04 +01:00
7f4ff359a2 Add tips about the use of docker in dynamic configuration for swarm provider 2024-11-04 16:00:05 +01:00
47466a456e Document how to use Certificates of cert-manager 2024-10-30 15:54:04 +01:00
6f18344c56 Add a warning about environment variables casing for static configuration 2024-10-30 10:54:04 +01:00
e8ff825ed2 Set Host header in HTTP provider request 2024-10-29 15:30:38 +01:00
8527369797 Add Compress middleware to migration guide 2024-10-29 12:12:04 +01:00
7004f0e750 Merge branch v3.2 into master 2024-10-29 09:29:27 +01:00
25caa72c09 Prepare release v3.2.0 2024-10-28 15:46:04 +01:00
8beba9f278 Merge branch v3.1 into v3.2 2024-10-28 11:38:08 +01:00
e90f4a7cb4 Prepare release v3.1.7 2024-10-28 11:34:03 +01:00
20cdbdbf31 Merge branch v2.11 into v3.1 2024-10-28 10:32:18 +01:00
08fe27ce5f Prepare release v2.11.13 2024-10-28 10:22:04 +01:00
0dc36379cf Ensuring Gateway API reflected Traefik resource name unicity
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-10-28 10:08:05 +01:00
27948493aa Panic on aborted requests to properly close the connection 2024-10-25 15:44:04 +02:00
e3ed52ba7c Detect and drop broken conns in the fastproxy pool
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-10-25 14:26:04 +02:00
b22e081c7c Merge branch v3.1 into v3.2 2024-10-24 11:47:38 +02:00
62fa5f1a8e Merge branch v2.11 into v3.1 2024-10-24 10:55:59 +02:00
edc0a52b5a Updates to Business Callouts in Docs 2024-10-24 09:52:04 +02:00
3d2336bc83 Use golangci-lint action 2024-10-23 17:06:04 +02:00
0605f8bf09 Document nativeLBByDefault annotation on Kubernetes Gateway provider 2024-10-23 11:10:04 +02:00
f18fcf3688 Preserve GRPCRoute filters order 2024-10-21 10:10:04 +02:00
eeb99c3536 Preserve HTTPRoute filters order 2024-10-21 09:54:04 +02:00
83871f27dd Add an option to preserve server path 2024-10-17 09:12:04 +02:00
6e1f5dc071 Fix instructions for downloading CRDs of Gateway API v1.2 2024-10-11 15:24:03 +02:00
ef5aa129c7 Fix broken links in Kubernetes Gateway provider page 2024-10-11 12:12:05 +02:00
f54f28921b Add missing RBAC in the migration guide 2024-10-11 12:10:04 +02:00
ef168b801c Refactor compress handler to make it generic
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-10-10 16:04:04 +02:00
06e64af9e9 Merge branch v3.2 into master 2024-10-10 11:32:18 +02:00
be156f6071 Ignore garbage collector flaky test 2024-10-10 10:48:04 +02:00
6f469ee1ec Only calculate basic auth hashes once for concurrent requests 2024-10-10 10:36:04 +02:00
b46665c620 Prepare release v3.2.0-rc2 2024-10-09 17:16:04 +02:00
be13b5b55d Merge branch v3.1 into v3.2 2024-10-09 16:47:13 +02:00
e9d677f8cb Support http and https appProtocol for Kubernetes Service 2024-10-09 16:26:04 +02:00
7edb9a2101 Bump github.com/go-acme/lego to v4.19.2 2024-10-09 16:04:04 +02:00
4613ddd757 Prepare release v3.1.6 2024-10-09 15:54:05 +02:00
c441d04788 Avoid updating Accepted status for routes matching no Gateways
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-10-09 15:50:04 +02:00
5d5dd9dd30 Merge branch v2.11 into v3.1 2024-10-09 15:19:14 +02:00
1508a2c221 Do not update gateway status when not selected by a gateway class
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-10-09 15:14:05 +02:00
934ca5fd22 Prepare release v2.11.12 2024-10-09 14:32:04 +02:00
f16d14cfa6 Reuse compression writers 2024-10-09 14:14:03 +02:00
4625bdf5cb Merge current v2.11 into v3.1 2024-10-08 17:54:23 +02:00
7b477f762a Upgrade to node 22.9 and yarn lock to fix vulnerabilities
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-10-08 17:52:04 +02:00
157cf75e38 Update business callout in docs 2024-10-08 12:06:04 +02:00
ab35b3266a Ensure shellcheck failure exit code is reflected in GH job result 2024-10-08 11:58:05 +02:00
d339bfc8d2 Use correct default weight in Accept-Encoding 2024-10-08 11:48:04 +02:00
7b08ecfa5e Bump sigs.k8s.io/gateway-api to v1.2.0
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-10-08 10:46:04 +02:00
0a6b8780f0 Adopt a layout for the large amount of entrypoint port numbers 2024-10-08 10:44:04 +02:00
45292148e7 Detail CRD update with v3.2 in the migration guide 2024-10-07 09:54:04 +02:00
fc563d3f6e Fix the resolved TAG_NAME for commit in multiple tags 2024-10-07 09:32:05 +02:00
a762cce430 Close wasm middleware to prevent memory leak 2024-10-04 16:36:04 +02:00
306d3f277d Bump github.com/klauspost/compress to dbd6c381492a 2024-10-04 10:48:04 +02:00
6f7649fccc Bump golangci-lint to 1.61.0 2024-10-04 09:38:04 +02:00
e8ab3af74d Clarify only header fields may be redacted in access-logs 2024-10-03 16:28:04 +02:00
a7502c8700 Prepare Release v3.2.0-rc1 2024-10-02 16:24:04 +02:00
54c3afd760 Merge branch v3.1 into master 2024-10-02 15:32:09 +02:00
a2ab3e534d Prepare release v3.1.5 2024-10-02 14:42:05 +02:00
8cfa68a8e1 Merge branch v2.11 into v3.1 2024-10-02 11:25:30 +02:00
518caa79f9 Prepare release v2.11.11 2024-10-02 11:10:04 +02:00
373095f1a8 Support NativeLB option in GatewayAPI provider
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-10-02 10:34:04 +02:00
b641d5cf2a Merge current v2.11 into v3.1 2024-09-30 14:59:38 +02:00
4d6cb6af03 Ensure defaultGeneratedCert.main as Subject's CN 2024-09-30 12:10:05 +02:00
9eb804a689 Bump github.com/klauspost/compress to 8e14b1b5a913 2024-09-30 11:56:04 +02:00
c02b72ca51 Disable IngressClass lookup when disableClusterScopeResources is enabled 2024-09-27 16:24:04 +02:00
2bb712135d Specify default format value for access log 2024-09-27 15:34:04 +02:00
14e5d4b4b3 Remove unused boot files from webui 2024-09-27 15:22:04 +02:00
e485edbe9f Update API documentation to mention pagination 2024-09-27 15:00:06 +02:00
d317cd90fc Support HTTPRoute destination port matching 2024-09-27 12:12:05 +02:00
eccfcc0924 feat: allow setting service.name for OTLP metrics 2024-09-27 11:58:05 +02:00
61bb3ab991 Rework condition to not log on timeout 2024-09-27 11:34:05 +02:00
e62f8af23b Rework condition to not log on timeout 2024-09-27 11:20:04 +02:00
a42d396ed2 Clean connection headers for forward auth request only
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-09-27 11:18:05 +02:00
7bb181dfa0 Bump sigs.k8s.io/gateway-api to v1.2.0-rc2 2024-09-27 11:02:04 +02:00
fbf6757ce9 Support for watching instead of polling Nomad 2024-09-26 15:56:04 +02:00
f8a78b3b25 Introduce a fast proxy mode to improve HTTP/1.1 performances with backends
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2024-09-26 11:00:05 +02:00
a6db1cac37 Update sigs.k8s.io/gateway-api to v1.2.0-rc1
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-09-26 09:12:04 +02:00
312ebb17ab Add support for ipv6 subnet in ipStrategy 2024-09-24 18:04:05 +02:00
a398536688 Merge branch v3.1 into master 2024-09-20 09:51:54 +02:00
0be01cc067 Prepare release v3.1.4 2024-09-19 15:44:04 +02:00
f3eba8d3a2 Guess Datadog socket type when prefix is unix 2024-09-19 15:30:05 +02:00
7e75dc0819 Merge current v2.11 into v3.1 2024-09-19 14:16:19 +02:00
b00f640d72 Prepare release v2.11.10 2024-09-19 12:08:04 +02:00
ac42dd8f83 Check if ACME certificate resolver is not nil 2024-09-19 11:50:04 +02:00
4b5968e0cc Bump github.com/quic-go/quic-go to v0.47.0 2024-09-19 11:36:04 +02:00
42e1f2c9b1 Add supported features to the Gateway API GatewayClass status 2024-09-17 16:40:04 +02:00
bbeceba580 Mention v3 in readme 2024-09-17 15:20:04 +02:00
1ebd12ff82 Add support for Gateway API BackendTLSPolicies 2024-09-17 10:50:04 +02:00
89f3b272c3 Prepare release v3.1.3 2024-09-16 17:06:03 +02:00
093989fc14 Merge branch v2.11 into v3.1 2024-09-16 16:41:57 +02:00
06d7fab820 Prepare release v2.11.9 2024-09-16 15:26:12 +02:00
f90f9df1db Ensure proper logs for aborted streaming responses 2024-09-16 12:06:03 +02:00
9750bbc353 Configurable max request header size 2024-09-16 11:30:04 +02:00
8c977b8f8c Removes goexport dependency and adds _initialize 2024-09-16 11:12:04 +02:00
5841441005 Cleanup Connection headers before passing the middleware chain
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-09-16 11:10:04 +02:00
0cf2032c15 Allow handling ACME challenges with custom routers 2024-09-13 15:54:04 +02:00
d547b943df Spelling 2024-09-13 11:40:04 +02:00
71d4b3b13c Make the keys of the accessLog.fields.names map case-insensitive 2024-09-13 10:04:07 +02:00
ac1dad3d14 Add support for custom CA certificates by certificate resolver 2024-09-09 17:24:04 +02:00
be5c429825 Unify tab titles 2024-09-09 10:10:06 +02:00
e222d5cb2f Add support for backend protocol selection in HTTP and GRPC routes 2024-09-09 10:08:08 +02:00
9dc2155e63 Fix sync docker images latest tag 2024-09-06 09:56:03 +02:00
c2cb4fac10 Sync docker images from docker hub to ghcr 2024-09-05 10:02:04 +02:00
e8335a94a4 Record trace id and EntryPoint span id into access log 2024-09-03 16:40:04 +02:00
3d92f1645f Fix Go version to 1.23 when running Gateway API conformance tests 2024-09-03 15:12:04 +02:00
3f74993f4a Fix typo in multiple DNS challenge provider warning 2024-09-03 14:40:04 +02:00
533c102d4f Fix tracing documentation 2024-09-03 14:02:03 +02:00
3eb7ecce19 Improve Kubernetes GatewayAPI TCPRoute and TLSRoute support 2024-09-03 12:10:04 +02:00
0b34e0cdcb Merge current v3.1 into master 2024-09-03 10:31:10 +02:00
cf2869407d Wrap capture for services used by pieces of middleware 2024-09-03 10:30:08 +02:00
8ca27b4a1d Merge current v2.11 into v3.1 2024-09-03 10:00:38 +02:00
6009aaed87 Improve CI speed 2024-09-03 09:44:04 +02:00
eb99c8c785 Add mirrorBody option to HTTP mirroring 2024-09-02 16:36:06 +02:00
bf71560515 Update go-acme/lego to v4.18.0 2024-09-02 15:42:05 +02:00
51f7f610c9 Add versioning for Gateway API Conformance Test Report 2024-08-30 17:14:03 +02:00
5ed972ccd8 Support GRPC routes
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-08-30 10:36:06 +02:00
2714831a4e fix: otlp doc + potential panic 2024-08-29 14:30:05 +02:00
6b3167d03e Remove same email requirement for certresolvers 2024-08-29 11:36:05 +02:00
1417da4a21 Update k8s quickstart permissions 2024-08-29 11:08:09 +02:00
3040f2659a Upgrade paerser to v0.2.1 2024-08-29 10:54:05 +02:00
6b1a584c2b Update quick-start-with-kubernetes.md to include required permissions 2024-08-29 10:50:06 +02:00
3a80aa172c Give valid examples for exposing dashboard with default Helm values 2024-08-29 10:40:05 +02:00
8dc9607db7 Merge current v3.1 into master 2024-08-29 10:09:18 +02:00
85f4fd0979 Merge current v2.11 into v3.1 2024-08-28 16:35:55 +02:00
e56ae1a766 Update to go1.23 2024-08-28 15:00:06 +02:00
d2030a5835 Upgrade webui dependencies 2024-08-27 18:08:03 +02:00
58bbc0cf0f Remove mentions about APIVersion traefik.io/v1 2024-08-26 09:44:04 +02:00
7056eeff6a Re-allow empty configuration for Kubernetes Ingress provider 2024-08-19 14:38:33 +02:00
ad613e58cd Allow configuring rule syntax with Kubernetes Ingress annotation 2024-08-12 14:28:04 +02:00
e7dc097901 Prevent error logging when TCP WRR pool is empty 2024-08-12 14:08:05 +02:00
12a37346a4 Support ResponseHeaderModifier filter 2024-08-12 11:34:04 +02:00
78079377e8 Add 30 day certificatesDuration step 2024-08-08 10:22:05 +02:00
75881359ab Add encodings option to the compression middleware 2024-08-07 16:20:04 +02:00
0eb0a15aa1 Remove documention for unimplemented service retries metric 2024-08-07 09:52:08 +02:00
8d9ff0c441 Mention missing metrics removal in the migration guide 2024-08-07 09:44:03 +02:00
b611f967b7 Merge branch v3.1 into master 2024-08-06 16:38:39 +02:00
4c4780f886 Prepare release v3.1.2 2024-08-06 15:34:03 +02:00
926a8e88e9 Merge current v2.11 into v3.1 2024-08-06 14:54:50 +02:00
6b1adabeb5 Prepare release v2.11.8 2024-08-06 14:50:04 +02:00
4eedcabbb3 Use Standard channel by default with Gateway API 2024-08-06 11:36:04 +02:00
5bf4b536e2 Change logs output from stderr to stdout 2024-08-05 16:56:34 +02:00
5380e48747 Include status addresses when comparing Gateway statuses 2024-08-05 12:22:04 +02:00
ccc11a69f1 Fix yaml config example for HTTP provider headers 2024-08-05 11:26:04 +02:00
0f57f108ae Fix missing codeblock ending in HTTP discover documentation 2024-08-05 11:14:03 +02:00
c0b704e1b0 Fix grafana dashboard to work with scrape interval greater than 15s 2024-08-02 10:18:04 +02:00
a50345bf8d Allow to disable Kubernetes cluster scope resources discovery
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-08-01 15:50:04 +02:00
bd93e224de Support HTTP BasicAuth for docker and swarm endpoint 2024-08-01 14:26:04 +02:00
ea019be133 Upgrade webui dependencies 2024-08-01 11:00:06 +02:00
02de683b94 Fix embedded youtube video 2024-08-01 09:30:04 +02:00
930f84850b Merge current v2.11 intov3.1 2024-07-31 17:14:45 +02:00
8970ae9199 Update to github.com/docker/docker v27.1.1 2024-07-31 16:20:04 +02:00
de732ba53c Add Access logs section to the migration guide
Co-authored-by: Simon Delicata <simon.delicata@free.fr>
2024-07-31 10:20:04 +02:00
0f7af2b4e7 Updated index.md to include video 2024-07-31 10:00:05 +02:00
e8324132f9 Merge current v3.1 into master 2024-07-30 15:54:24 +02:00
f52a36ba12 Prepare release v3.1.1 2024-07-30 15:52:03 +02:00
2ffa6c6feb Merge current v2.11 into v3.1 2024-07-30 15:14:29 +02:00
210400905f Prepare release v2.11.7 2024-07-30 14:14:03 +02:00
ba6b4cbcc3 chore(ci): fix deprecation and optimization 2024-07-29 15:58:04 +02:00
7dbd3f88f6 Do not update route status when nothing changed 2024-07-29 15:48:05 +02:00
898eab20ac Improve error and documentation on the needed link between router and service 2024-07-29 15:39:06 +02:00
957a5f5e73 feat: forwardAuth support LogUserHeader 2024-07-29 14:30:05 +02:00
5a70910dce Improve explanation on API exposition 2024-07-29 12:12:04 +02:00
386c2ffb20 Use ServiceName in traefik_service_server_up metric 2024-07-29 11:52:05 +02:00
266a2d8b91 Fix grafana dashboard to work with scrape interval greater than 15s 2024-07-29 11:32:04 +02:00
3ba53df005 Document Docker port selection on multiple exposed ports 2024-07-29 10:22:04 +02:00
5142733858 Bump google.golang.org/grpc to v1.64.1 2024-07-26 09:30:04 +02:00
ecdfb10653 Remove duplicated kubectl apply from kubernetes-gateway.md 2024-07-25 15:24:04 +02:00
0f4e72d522 Update the supported versions table for v3.1 release 2024-07-25 15:14:04 +02:00
70dd7cdc71 Enforce default cipher suites list
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-07-23 16:30:05 +02:00
c3e943658a Modify certificatesDuration documentation 2024-07-23 14:34:04 +02:00
4720caed04 Update open connections gauge with connections count 2024-07-23 11:52:04 +02:00
c5a6b49330 Merge current v2.11 into v3.1 2024-07-22 10:01:16 +02:00
a5df24a21d Upgrade dependencies 2024-07-19 14:52:04 +02:00
f5a811d8fa Make the log about new version more accurate 2024-07-17 09:28:03 +02:00
87db3300d3 Merge current v3.1 into master 2024-07-16 09:38:17 +02:00
4b4eaa49b5 Prepare release v3.1.0 2024-07-15 16:38:04 +02:00
fc174062b6 Merge current v3.0 into v3.1 2024-07-15 15:22:14 +02:00
d700e95c21 Merge branch v2.11 into v3.0 2024-07-15 14:13:45 +02:00
aa760b5a71 Rework Kubernetes Gateway API documentation 2024-07-15 10:42:03 +02:00
a52c81fd91 Incorrect value in default priority computation example 2024-07-11 15:46:03 +02:00
127c0a7542 Improve doc on sensitive data stored into labels/tags 2024-07-11 14:40:07 +02:00
58dcbb43f9 Retry on Gateway API resource status update
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-07-11 11:26:03 +02:00
f32884d9b8 Update PR approval process 2024-07-10 11:46:03 +02:00
173a18fdc1 Bump opentelemetry-go to v1.28 2024-07-04 16:28:05 +02:00
876899be4b Prepare release v3.1.0 rc3 2024-07-02 17:18:03 +02:00
89108972b6 Merge branch v3.0 into v3.1 2024-07-02 16:33:29 +02:00
d42e75bb2e Prepare release v3.0.4 2024-07-02 15:42:03 +02:00
8d016f5e16 Merge branch v2.11 into v3.0 2024-07-02 14:43:56 +02:00
927f0bc01a Prepare release v2.11.6 2024-07-02 14:22:03 +02:00
900784a95a Disable QUIC 0-RTT
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2024-07-02 10:48:04 +02:00
98c624bf1a Fix a typo in the ACME docker-compose docs 2024-07-01 17:12:04 +02:00
f3479f532b Fix ECS config for OIDC + IRSA 2024-07-01 16:50:04 +02:00
8946dd1898 Remove interface names from IPv6 2024-07-01 16:26:04 +02:00
2a0cfda90b Do not disable Gateway API provider if not enabled in experimental 2024-07-01 14:10:03 +02:00
12fae2ebb8 Fix typo in keepAliveMaxTime docs 2024-07-01 14:08:04 +02:00
9758b1ce36 Prepare release v3.1.0-rc2 2024-06-28 10:42:03 +02:00
fe4cca6e9c Fix build only linux and darwin support wazergo 2024-06-28 10:16:03 +02:00
b1b4e6b918 Prepare release v3.1.0-rc1 2024-06-27 16:28:03 +02:00
8cb1829698 Upgrade to OpenTelemetry Semantic Conventions v1.26.0 2024-06-27 14:14:03 +02:00
2f9905061e Merge current v3.0 into master 2024-06-27 10:17:11 +02:00
0a7a6afd59 Merge current v2.11 into v3.0 2024-06-26 17:44:51 +02:00
b577b3a6ba Fix conformance tests report format 2024-06-26 16:30:05 +02:00
230019eccf feat: add logs for plugins load
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2024-06-26 16:08:04 +02:00
2090baa938 Update Advanced Capabilities Callout 2024-06-26 09:30:04 +02:00
b7de043991 Support systemd socket-activation
Co-authored-by: Michael <michael.matur@gmail.com>
2024-06-25 16:30:04 +02:00
9e0800f938 Fix the Kubernetes GatewayAPI documentation 2024-06-25 14:20:04 +02:00
e7d1a98c5e Enhance wasm plugins
Co-authored-by: Michael <[michael.matur@gmail.com](mailto:michael.matur@gmail.com)>
2024-06-25 09:58:04 +02:00
6f1bd54d86 Fix some documentation links
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-06-24 11:22:03 +02:00
983940ae60 KubernetesGateway provider out of experimental
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-06-24 10:36:03 +02:00
6d8407893d Bump Gateway API to v1.1.0
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-06-22 05:46:03 +02:00
a8a92eb2a5 Migrate to EndpointSlices API 2024-06-21 14:56:03 +02:00
2798e18e18 Update maintainers 2024-06-21 11:10:04 +02:00
61defcdd66 Merge current v3.0 into master 2024-06-21 09:15:28 +02:00
ec638a741e Merge current v2.11 into v3.0 2024-06-21 08:55:31 +02:00
097e71ad24 fix: readme badge 2024-06-21 08:54:03 +02:00
eabcb3e1c0 Update maintainers 2024-06-19 17:18:03 +02:00
53a8bd76f2 Prepare release v3.0.3 2024-06-18 16:10:06 +02:00
0e89c48e38 Merge branch v2.11 into v3.0 2024-06-18 14:05:42 +02:00
385ff5055c Prepare release v2.11.5 2024-06-18 12:00:04 +02:00
b4f99ae3ac Support HTTPRoute method and query param matching 2024-06-18 09:48:04 +02:00
a696f7c654 Add HTTPUrlRewrite Filter in Gateway API 2024-06-13 17:06:04 +02:00
3ca667a3d4 Support HTTPRoute redirect port and scheme
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-06-13 11:16:04 +02:00
27af1fb478 Merge current v3.0 into master 2024-06-13 10:40:32 +02:00
e322184a98 Merge current v2.11 into v3.0 2024-06-13 10:22:18 +02:00
69424a16a5 fix: etcd image no more compatible 2024-06-13 10:20:04 +02:00
f9f22b7b70 Update the supported versions table 2024-06-12 12:06:04 +02:00
b795f128d7 Add support for Zstandard to the Compression middleware 2024-06-12 11:38:04 +02:00
6706bb1612 Update go-acme/lego to v4.17.4 2024-06-12 09:08:03 +02:00
3f48e6f8ef Merge current 'v3.0' into master 2024-06-11 09:50:40 +02:00
8ea339816a Prepare release v3.0.2 2024-06-10 16:34:04 +02:00
00b1d8b0bc Merge branch v2.11 into v3.0 2024-06-10 15:35:51 +02:00
21c6edcf58 Prepare release v2.11.4 2024-06-10 15:16:04 +02:00
5c48e3c96c chore(ci): improve webui build and lint 2024-06-07 16:56:04 +02:00
c23c3e0ed3 Run UI tests on the CI 2024-06-07 11:06:05 +02:00
b37aaea36d Headers middleware: support Content-Security-Policy-Report-Only 2024-06-07 09:24:04 +02:00
67f0700377 Merge branch v3.0 into master 2024-06-06 17:38:32 +02:00
778dc22e14 Support Accept-Encoding header weights with Compress middleware 2024-06-06 16:42:04 +02:00
cdf0c8b3ec Add user guides link to getting started 2024-06-06 15:46:03 +02:00
359477c583 Update v2 > v3 migration guide 2024-06-06 15:22:04 +02:00
28d40e7f3c Fix HTTPRoute Redirect Filter with port and scheme
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-06-06 10:56:03 +02:00
b368e71337 Bump Docker images use for documentation to Alpine 3.20 2024-06-05 16:58:05 +02:00
dc752c7847 grafana: traefik-kubernetes: fix service name label_replace 2024-06-05 16:38:05 +02:00
6155c900be Passing the correct status code when compression is disabled within the Brotli handler
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-06-05 15:04:04 +02:00
6ca4c5da5c Merge branch v2.11 into v3.0 2024-06-05 00:05:37 +02:00
7eac92f49c Support Gateway API reference grant for HTTPRoute backends
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-06-04 14:16:04 +02:00
e6b1b05fdf bump otel dependencies 2024-06-04 10:04:04 +02:00
b452f37e08 Fix default value of Healthcheck for ExternalName services 2024-06-04 09:32:04 +02:00
8cff718c53 Update metrics in traefik-kubernetes.json grafana dashboard 2024-06-03 14:32:04 +02:00
bfda5e607f Remove helm default repo warning as repo has been long deprecated 2024-05-30 17:46:04 +02:00
7fc56454ea Add HealthCheck for KubernetesCRD ExternalName services 2024-05-30 17:18:05 +02:00
c0a2e6b4b6 Compute HTTPRoute priorities
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-05-30 09:14:04 +02:00
0f0cc420e1 docs(ratelimit requestheader): add note concerning behavior if header is missing
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-05-29 10:40:05 +02:00
9250b5937d Update go-acme/lego to v4.17.3 2024-05-29 09:16:07 +02:00
e9bd2b45ac Fix route attachments to gateways
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-05-28 14:30:04 +02:00
4406c337d4 fix .com and .org domain in documentation 2024-05-27 15:12:03 +02:00
ed10bc5833 chore: update linter 2024-05-27 09:46:08 +02:00
e33bd6874f Append to log file if it exists 2024-05-24 14:24:03 +02:00
6e61fe0de1 Support RegularExpression for path matching 2024-05-23 20:08:03 +02:00
05828bab07 Bump Dockerfile Alpine to v3.20 2024-05-23 16:24:04 +02:00
0e215f9b61 Support invalid HTTPRoute status
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-05-22 17:20:04 +02:00
7fdb1ff8af Merge branch v3.0 into master 2024-05-22 16:01:03 +02:00
736f37cb58 Prepare release v3.0.1 2024-05-22 15:08:04 +02:00
cff71ee496 Merge branch v2.11 into v3.0 2024-05-21 16:24:57 +02:00
f02b223639 Prepare release v2.11.3 2024-05-21 16:16:05 +02:00
d4d23dce72 Fix UI unit tests 2024-05-21 15:26:04 +02:00
5e4dc783c7 Allow empty configuration for OpenTelemetry metrics and tracing 2024-05-21 10:42:04 +02:00
440cb11250 Add support for IP White list 2024-05-21 09:24:08 +02:00
42920595ad Display of Content Security Policy values getting out of screen 2024-05-17 16:18:04 +02:00
e68e647fd9 Fix OTel documentation 2024-05-16 09:52:06 +02:00
8b558646fc fix: remove providers not more support in documentation 2024-05-15 16:26:04 +02:00
f8e45a0b29 fix: doc consistency forwardauth 2024-05-15 15:52:04 +02:00
d65de8fe6c Fix rule syntax version for all internal routers 2024-05-15 10:46:04 +02:00
5f2c00b438 Fixed typo in PathRegexp explanation 2024-05-15 10:20:04 +02:00
c2c1c3e09e Fix the rule syntax mechanism for TCP 2024-05-14 09:42:04 +02:00
d8a778b5cd Fix log.compress value 2024-05-13 15:44:03 +02:00
d8cf90dade Improve mirroring example on Kubernetes 2024-05-13 15:42:04 +02:00
6a06560318 Change log level from Warning to Info when ExternalName services is enabled 2024-05-13 09:06:03 +02:00
a4aad5ce5c fix: router documentation example 2024-05-13 08:54:03 +02:00
15973f5503 Remove deadlines when handling PostgreSQL connections 2024-05-06 15:46:04 +02:00
a4150409c8 Add link to the new http3 config in migration 2024-05-06 14:50:04 +02:00
aee515b930 Regenerate v3.0.0 changelog 2024-05-02 18:42:03 +02:00
05d2c86074 Set Gateway HTTPRoute status
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-05-01 06:38:03 +02:00
b0d19bd466 Bump tscert dependency to 28a91b69a046
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-04-30 02:20:04 +02:00
d99d2f95e6 Prepare release v3.0.0 2024-04-29 16:06:04 +02:00
8d2a2ff08f Native Kubernetes service load-balancing at the provider level 2024-04-29 12:20:04 +02:00
73e5dbbfe5 Update Kubernetes version for v3 Helm chart 2024-04-29 10:44:03 +02:00
ee3e7cbbec chore: patch migration/v2.md 2024-04-25 14:54:04 +02:00
9d8fd24730 Merge branch v3.0 into master 2024-04-23 13:25:25 +02:00
f5d451d816 Merge branch v2.11 into v3.0 2024-04-22 17:30:39 +02:00
f84e00e481 Consistent entryPoints capitalization in CLI flag usage 2024-04-22 17:24:04 +02:00
fe0af1ec4b Use latest Ubuntu (LTS) image consistenly across GitHub workflow 2024-04-22 17:04:05 +02:00
95312d5324 Adds the missing circuit-breaker response code for CRD 2024-04-19 11:26:05 +02:00
e3729ec600 Fix HTTPRoute path type 2024-04-19 11:06:04 +02:00
20d6c19c30 Fix HTTPRoute use of backendRefs 2024-04-19 10:44:04 +02:00
7a7b03eb01 Fix unfinished migration sentence for v2.11.2 2024-04-18 16:24:04 +02:00
ea4f307fcd Fix provider icon size 2024-04-18 16:04:04 +02:00
a6b00608d2 Merge branch v2.11 into v3.0 2024-04-18 15:34:01 +02:00
7b649e2f0c Fix some typos in comments 2024-04-18 15:14:04 +02:00
52e95deee3 In cluster Gateway API Conformance Tests
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-04-17 15:22:04 +02:00
70968bc6a9 Remove deadlines for non-TLS connections
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-04-15 17:02:06 +02:00
da7bb5fc25 Prepare release v3.0.0-rc5 2024-04-11 18:24:03 +02:00
34bd611131 Merge branch v2.11 into v3.0 2024-04-11 17:52:42 +02:00
b9b7527762 Prepare release v2.11.2 2024-04-11 17:36:03 +02:00
240b83b773 Set default ReadTimeout value to 60s
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-04-11 17:18:03 +02:00
584839e00b Prepare release v2.11.2 2024-04-11 16:08:04 +02:00
099c7e9444 Revert LingeringTimeout and change default value for ReadTimeout
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-04-11 15:48:04 +02:00
83a5c5cfbd Prepare release v3.0.0-rc4 2024-04-10 16:34:03 +02:00
c1d9b9ee1f Merge branch v2.11 into v3.0 2024-04-10 15:48:10 +02:00
d53f5f01a0 Prepare release v2.11.1 2024-04-10 11:52:03 +02:00
4e11bf3c38 Adjust ECS network interface detection logic 2024-04-10 10:42:04 +02:00
1a266c661a Add a horizontal scroll for the mobile view 2024-04-10 10:22:11 +02:00
bda4f50eae Avoid cumulative send anonymous usage log 2024-04-10 10:08:04 +02:00
19e6170fa5 Modify the Hub Button 2024-04-10 09:50:04 +02:00
0017471f0d Add option to set Gateway status address
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-04-10 09:34:07 +02:00
76723b1288 Close created file in ACME local store CheckFile func 2024-04-09 13:12:04 +02:00
cef842245c Introduce Lingering Timeout
Co-authored-by: Baptiste Mayelle <baptiste.mayelle@traefik.io>
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-04-08 17:16:04 +02:00
f69fd43122 Add support for Kubernetes Gateway API RequestHeaderModifier filter
Co-authored-by: Baptiste Mayelle <baptiste.mayelle@traefik.io>
2024-04-05 17:18:03 +02:00
e5062cef42 chore: update dependencies 2024-04-05 15:14:04 +02:00
998c6174cd Improved documentation about Nomad ACL minimum rights 2024-04-05 10:14:03 +02:00
ac1753a614 Nomad provider to allow empty services 2024-04-04 11:54:04 +02:00
d3516aec31 docs: excludedIPs with IPWhiteList and IPAllowList middleware 2024-04-04 11:32:05 +02:00
2c6418e17a docs: fix typo and improve explanation on internal resources 2024-04-04 10:14:06 +02:00
1ffbffb26a Merge branch v3.0 into master 2024-04-03 20:32:20 +02:00
fdf27eb644 Merge current v2.11 into v3.0 2024-04-03 19:09:39 +02:00
945ff9b0f9 chore(ci): fix and update codeql 2024-04-03 19:08:03 +02:00
bbd5846c6a Update Yaegi to v0.16.1 2024-04-03 18:46:03 +02:00
9f145dbc28 Merge branch v2.11 into v3.0 2024-04-03 17:54:11 +02:00
c84b510f0d Toggle support for Gateway API experimental channel 2024-04-02 17:32:04 +02:00
2bc3fa7b4b Reserve priority range for internal routers
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-04-02 17:04:05 +02:00
fc897f6756 fix: support regexp in path/pathprefix in matcher v2 2024-04-02 14:46:04 +02:00
c31f5df854 Enforce handling of ACME-TLS/1 challenges
Co-authored-by: Baptiste Mayelle <baptiste.mayelle@traefik.io>
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-03-29 11:36:05 +01:00
b636b21167 fix: typo in dialer_test.go 2024-03-29 09:20:03 +01:00
167bdb0d53 docs: improve middleware example 2024-03-28 14:36:04 +01:00
7f29595c0a Allow empty replacement with ReplacePathRegex middleware 2024-03-26 13:28:04 +01:00
3fcf265d80 Move from http.FileServer to http.FileServerFS 2024-03-25 20:22:05 +01:00
618fb5f232 Handle middlewares in filters extension ref in gateway api provider
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-03-25 14:38:04 +01:00
d94e676083 Enforce failure for TCP HostSNI with hostname
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-03-25 11:08:04 +01:00
141abce2d5 chore: update linter 2024-03-20 10:26:03 +01:00
fc875b38e0 Added specification for TCP TLS routers in documentation 2024-03-19 16:00:05 +01:00
39fe3869b6 Add missing Docker Swarm logo 2024-03-18 15:08:04 +01:00
d582e01892 runtime.Object in routerTransform
Co-authored-by: lbenguigui <lbenguigui@gmail.com>
2024-03-15 09:24:03 +01:00
75790e0ab8 Add sdelicata to maintainers 2024-03-14 16:54:04 +01:00
1391c35978 Add youkoulayley to maintainers 2024-03-14 16:18:04 +01:00
7bda07a422 Fix struct names in comment 2024-03-14 14:52:04 +01:00
9b6af61d1b Prepare release v3.0.0 rc3 2024-03-13 16:46:04 +01:00
5edac5eccd Merge v2.11 into v3.0 2024-03-13 16:04:25 +01:00
83e4abdb30 Fix dashboard exposition through a router 2024-03-13 15:56:04 +01:00
4e1e2f5ed0 Bump Elastic APM to v2.4.8 2024-03-12 18:26:05 +01:00
c06629459d Prepare release v3.0.0-rc2 2024-03-12 15:18:04 +01:00
05be441027 Merge current v2.11 into v3.0 2024-03-12 12:08:03 +01:00
6c9687f410 Semconv OTLP stable HTTP metrics 2024-03-12 09:48:04 +01:00
5cf1b95c29 Fix host header mention in prometheus metrics doc 2024-03-11 14:52:04 +01:00
74daa4cbb3 Update gandiv5 env variable in providers table 2024-03-11 12:06:04 +01:00
709ff6fb09 Add captured headers options for tracing
Co-authored-by: Baptiste Mayelle <baptiste.mayelle@traefik.io>
2024-03-11 11:50:04 +01:00
4fd5fca34f Update go-acme/lego to v4.16.1 2024-03-11 09:18:03 +01:00
31a93d5045 Fix log when default TLSStore and TLSOptions are defined multiple times 2024-03-06 14:32:04 +01:00
4cb5825d11 Fix paragraph in entrypoints and Docker docs 2024-03-06 14:12:04 +01:00
15f50553e9 Make text more readable in dark mode 2024-03-05 15:10:05 +01:00
b4ca02da86 Fix multiple dns provider documentation 2024-03-05 14:54:04 +01:00
86be0a4e6f fix: invalid version in docs about Gateway API on Traefik v3 2024-02-29 15:18:05 +01:00
0e89a6bec7 ConsulCatalog StrictChecks 2024-02-27 21:30:04 +01:00
c5808af4d9 chore: upgrades http-wasm host to v0.6.0 to support clients using v0.4.0 2024-02-27 14:22:04 +01:00
c1ef742977 Allow to use internal node IPs for NodePort services 2024-02-27 10:54:04 +01:00
935d251b21 Fix typo in migration docs 2024-02-27 10:20:03 +01:00
73769af0fe Merge branch v3.0 into master 2024-02-27 09:30:21 +01:00
3b851a5ef2 Upgrade opentelemetry dependencies 2024-02-26 15:22:04 +01:00
deab4dae8e Fix default value for peerCertURI option 2024-02-26 15:20:05 +01:00
f7edb394f2 chore(webui): Migrate to Quasar 2.x and Vue.js 3.x 2024-02-26 15:02:04 +01:00
baf687218c Support OTEL_PROPAGATORS to configure tracing propagation
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-02-26 11:50:04 +01:00
153765f99f Allow to configure TLSStore default generated certificate with labels 2024-02-26 10:02:06 +01:00
5a2e233a15 Add ReferenceGrants to Gateway API Traefik controller RBAC 2024-02-26 08:50:04 +01:00
453e21c7c9 fix: add ipallowlist in dashboard 2024-02-19 16:50:05 +01:00
8b759ab797 fix: int overflow during doc generation on 32 bit arch 2024-02-19 16:02:04 +01:00
88a2020817 chore: update linter 2024-02-19 15:44:03 +01:00
c3545c620b Improve ruleSyntax option documentation 2024-02-19 15:02:04 +01:00
1034646ae2 Update releases page 2024-02-19 14:46:03 +01:00
538f780a85 Update goreleaser configuration 2024-02-16 10:08:04 +01:00
b931c8ae9b Update releases page 2024-02-16 09:54:04 +01:00
c5c61dbade Fix a regression on flags using spaces between key and value 2024-02-16 09:44:06 +01:00
1e7dbc70a0 fix: don't allow routers higher than internal ones 2024-02-15 16:40:05 +01:00
6a2db4e4e9 Fix typo in statsd metrics docs 2024-02-15 15:20:04 +01:00
1ea98d3d31 Fix codename 2024-02-14 10:26:07 +01:00
014fdfc4ec Prepare release v3.0.0-rc1 2024-02-13 14:38:03 +01:00
b5ec787fb6 Merge current v2.11 into v3.0 2024-02-13 09:46:53 +01:00
0c8778639a Prepare release v2.11.0 2024-02-12 16:14:04 +01:00
8f29398573 Update the documentation for RateLimit to provide a better example 2024-02-12 09:44:11 +01:00
676de5fb68 Fix file watcher 2024-02-09 11:08:05 +01:00
063f8fae79 Merge current v3.0 into master 2024-02-08 17:03:01 +01:00
efa6ca0fa1 fix: go version for conformance tests gateway api 2024-02-08 16:46:06 +01:00
4e831b920e Merge v3.0' into master 2024-02-08 16:14:39 +01:00
bc84fdd006 Merge current v2.11 into v3.0 2024-02-08 14:35:35 +01:00
d5cb9b50f4 Update to go1.22
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2024-02-07 17:14:07 +01:00
e11ff98608 Fix NTLM and Kerberos 2024-02-06 17:34:07 +01:00
9df04df334 Delete warning in Kubernetes CRD provider about the supported version 2024-02-06 11:20:06 +01:00
bb6cd581a6 Align OpenTelemetry tracing and metrics configurations
Co-authored-by: Michael <michael.matur@gmail.com>
2024-02-06 10:04:05 +01:00
8f9ad16f54 chore: Upgrade Node.js version 2024-02-06 09:00:07 +01:00
5d8b1949b7 fix: upgrade actions/upload-artifact to v4 2024-02-01 14:08:06 +01:00
d7ec0cedbf Reload provider file configuration on SIGHUP 2024-02-01 14:06:05 +01:00
f1104ada65 Fixes the Header Button 2024-02-01 10:52:07 +01:00
3ba3ca6eb0 Fix the keepAlive options for the CLI examples 2024-01-31 17:00:06 +01:00
85039e0d54 Fix brotli response status code when compression is disabled 2024-01-30 17:32:05 +01:00
9be523d772 Support for cross-namespace references / GatewayAPI ReferenceGrants 2024-01-30 16:44:05 +01:00
8b77f0c2dd Remove observability for internal resources 2024-01-30 16:28:05 +01:00
d02be003ab Add SO_REUSEPORT support for EntryPoints 2024-01-30 14:56:05 +01:00
4d539273ad docs: include ECS as supported backend 2024-01-29 18:50:05 +01:00
40de310927 Reintroduce dropped v2 dynamic config
Co-authored-by: Baptiste Mayelle <baptiste.mayelle@traefik.io>
2024-01-29 17:32:05 +01:00
18203f57d2 Add support for sending DogStatsD metrics over Unix Socket 2024-01-29 17:08:05 +01:00
ef0e9c6f05 Update go-acme/lego to v4.15.0 2024-01-29 15:10:05 +01:00
d37ea3e882 Add ResponseCode to CircuitBreaker 2024-01-29 10:58:05 +01:00
3174c69c66 Adds weight on ServersLoadBalancer 2024-01-26 01:44:05 +01:00
f4f3dbe1f5 Update version comment in quick-start.md 2024-01-25 15:12:05 +01:00
49f04f2772 fix: URL encode resource's id before calling API endpoints 2024-01-25 09:56:05 +01:00
03d2e35488 fix: remove snapshot from release target 2024-01-24 18:54:05 +01:00
aece9a1051 fix: opentelemetry unit tests 2024-01-24 16:58:05 +01:00
547cd81599 Prepare release v2.11.0-rc2 2024-01-24 15:20:09 +01:00
b5251c6ac4 misc(Makefile): add help target to display the help msg 2024-01-24 11:58:05 +01:00
190b9b1afa Merge current v2.11 into v3.0 2024-01-24 11:19:52 +01:00
9befe0dd51 Fix flaky test 2024-01-23 16:46:05 +01:00
683e2ee5c6 Bring back v2 rule matchers 2024-01-23 11:34:05 +01:00
21da705ec9 fix: gateway api conformance tests 2024-01-23 11:04:05 +01:00
a3ac456199 fix: OpenTelemetry unit tests 2024-01-23 10:13:20 +01:00
9843757834 Merge current v2.11 into v3.0 2024-01-23 09:32:28 +01:00
f9831f5b1b Introduce static config hints
Co-authored-by: Baptiste Mayelle <baptiste.mayelle@traefik.io>
2024-01-23 09:22:05 +01:00
177c4b0ed1 fix: flakiness test on configuration watcher 2024-01-22 16:52:05 +01:00
bab48bed22 fix: OpenTelemetry metrics flaky test 2024-01-22 16:38:06 +01:00
6cb2ff2af9 fix: gateway api conformance tests 2024-01-22 16:04:05 +01:00
5e0855ecc7 feat: adds conformance test gateway api 2024-01-22 15:30:05 +01:00
f57cee578f Merge back v2.11 into v3.0 2024-01-19 16:03:50 +01:00
8da38ec0a5 fix: tailscale is required for Docker Desktop users 2024-01-19 15:44:05 +01:00
a6d462f6e8 feat: upgrade gh-action os 2024-01-19 15:12:05 +01:00
6c19a9cb8f Merge current v3.0 into master 2024-01-19 14:34:31 +01:00
0eeb85d01d Support setting sticky cookie max age 2024-01-18 09:30:06 +01:00
64ff214ff8 remove marathon labels from gendoc 2024-01-17 14:54:05 +01:00
111f3716fa Merge current v2.11 into v3.0 2024-01-17 11:37:50 +01:00
4e0a05406b Implements the includedContentTypes option for the compress middleware 2024-01-17 11:32:06 +01:00
39b0aa6650 Improve makefile 2024-01-17 11:12:05 +01:00
319517adef Merge branch v2.11 into v3.0 2024-01-16 15:42:38 +01:00
7a315bb043 Disable br compression when no Accept-Encoding header is present 2024-01-16 15:30:06 +01:00
34d2a816c2 Enhance gendoc for Generating Static and Dynamic Reference Configuration Files 2024-01-16 10:32:05 +01:00
81ce45271d Add forwardAuth.addAuthCookiesToResponse 2024-01-15 16:14:05 +01:00
3a461d2f23 deps: update the Nomad API dependency to v1.7.2 2024-01-12 14:22:05 +01:00
980dac4572 Support file path as input param for Kubernetes token value 2024-01-11 17:06:06 +01:00
ff7966f9cd feat: re introduce IpWhitelist middleware as deprecated 2024-01-11 10:40:06 +01:00
e78374aa29 docs: slightly rewords the documentation 2024-01-10 15:12:07 +01:00
3bbc560283 Merge v2.11 into v3.0 2024-01-10 14:08:30 +01:00
ccf3a9995a Add rejectStatusCode option to IPAllowList middleware 2024-01-09 20:26:05 +01:00
e522446909 Improve integration tests
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2024-01-09 17:00:07 +01:00
fea94a3393 feat: upgrade gateway api to v1.0.0 2024-01-09 10:28:05 +01:00
4ddef9830b Migrate to opentelemetry 2024-01-08 09:10:06 +01:00
45bb00be04 Improve migration guide
Co-authored-by: Baptiste Mayelle <baptiste.mayelle@traefik.io>
2024-01-05 16:04:05 +01:00
cd8d5b8f10 chore: update github.com/docker/docker to v24.0.7 2024-01-05 15:10:05 +01:00
eff294829f Add missing TCP IPAllowList middleware constructor
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-01-04 14:58:05 +01:00
a69c1ba3b7 Merge branch v2.11 into v3.0 2024-01-03 17:28:22 +01:00
9adf0fb638 Prepare release v2.11.0-rc1 2024-01-03 11:12:05 +01:00
56e2110dc5 Fix readHeaderTimeout in proxyproto 2024-01-02 22:02:05 +01:00
5be13802dc chore: update github.com/fsnotify/fsnotify to v1.7.0 2024-01-02 20:58:06 +01:00
7345afd8b6 Update quic-go to v0.40.1 2024-01-02 20:36:06 +01:00
a84d5c0ef1 Adjust deprecation notice for Kubernetes CRD provider
Co-authored-by: Baptiste Mayelle <baptiste.mayelle@traefik.io>
2024-01-02 20:04:06 +01:00
2a9471d278 docs: fix typo 2024-01-02 19:12:06 +01:00
0042562678 docs: fix the explanation of the TLS challenge 2024-01-02 18:46:05 +01:00
74ab88d47e docs: fix description for anonymous usage statistics references 2024-01-02 18:20:06 +01:00
6df9578ace Update wording of compose example 2024-01-02 17:56:06 +01:00
cd7d324295 Documentation enhancements 2024-01-02 17:30:06 +01:00
0e92b02474 Deprecate IPWhiteList middleware in favor of IPAllowList
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2024-01-02 17:04:06 +01:00
9662cdca64 Add KeepAliveMaxTime and KeepAliveMaxRequests features to entrypoints 2024-01-02 16:40:06 +01:00
3dfaa3d5fa Add Redis Sentinel support
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-01-02 16:16:05 +01:00
60123a8f3f Hash WRR sticky cookies
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2024-01-02 15:52:05 +01:00
2a7b2ef772 chore: happy new year 2024 2024-01-02 15:28:09 +01:00
d51a2ce487 Compute priority for https forwarder TLS routes 2023-12-08 16:42:05 +01:00
0a79643001 Prepare release v2.10.7 2023-12-06 16:42:09 +01:00
e77a66c2ac Fixed datadog logs json format issue 2023-12-06 14:36:05 +01:00
6858dbdd07 Add http-wasm plugin support to Traefik 2023-11-30 21:42:06 +01:00
b2bb96390a Prepare release v3.0.0 beta5 2023-11-29 16:08:05 +01:00
e29a142f6a Merge v2.10 into v3.0 2023-11-29 14:39:01 +01:00
dae0491b61 Prepare release v2.10.6 2023-11-28 15:46:10 +01:00
f4ddf25e41 Fixed stripPrefix middleware is not applied to retried attempts 2023-11-24 09:30:06 +01:00
35c704ace3 fix: unit tests were never run on cmd package 2023-11-22 19:18:05 +01:00
789046f162 feat: upgrade codegen for kubernetes to v0.28.3 2023-11-22 11:28:06 +01:00
186e3e1541 Refuse recursive requests
Co-authored-by: Michael <michael.matur@gmail.com>
2023-11-21 15:08:06 +01:00
088fe3c270 docs: improve errorpages examples to avoid confusion 2023-11-17 16:30:06 +01:00
553ef94047 chore: update linter 2023-11-17 01:50:06 +01:00
12e50e20e6 Deny request with fragment in URL path
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2023-11-16 16:54:07 +01:00
cd326654a7 Guidelines Update 2023-11-15 11:24:05 +01:00
3de29433f8 docs: better visibility of the review process + maintainers team 2023-11-14 08:44:06 +01:00
84516f962d Remove backoff for http challenge
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2023-11-13 15:58:09 +01:00
f92b03a44d Rephrase BasicAuth and DigestAuth docs 2023-11-10 09:32:05 +01:00
085b70c94e chore: update github.com/hashicorp/consul/api
Co-authored-by: lbenguigui <lbenguigui@gmail.com>
2023-11-09 16:58:06 +01:00
0e66ed87f8 Add @lbenguigui to maintainers 2023-11-09 15:28:05 +01:00
d141e4a1ed Upgrade opentelemetry dependencies 2023-10-30 14:50:06 +01:00
679975beec fix: datadog tracer 2023-10-27 09:14:05 +02:00
8faed97e74 Add a mention for the host header in metrics headers labels doc
Co-authored-by: Baptiste Mayelle <baptiste.mayelle@traefik.io>
2023-10-18 13:44:05 +02:00
0b4c582088 Update quic-go to v0.39.1 2023-10-17 17:00:06 +02:00
c7cd0df3b3 Prepare release v3.0.0-beta4 2023-10-12 09:48:05 +02:00
286181aa61 Merge v2.10 into v3.0 2023-10-11 17:33:55 +02:00
6a34f238ce Prepare release v2.10.5 2023-10-11 15:50:05 +02:00
4b2c763cf3 update x/net and grpc/grpc-go
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
Co-authored-by: lbenguigui <lbenguigui@gmail.com>
2023-10-11 12:48:05 +02:00
d03d8d53fd Add missing accessControlAllowOriginListRegex to middleware view 2023-10-11 09:52:05 +02:00
8d0979bfd0 Enable TLS for Consul Connect TCP services
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2023-09-29 15:26:05 +02:00
e95fde5652 Fix preflight response status in access logs
Co-authored-by: lbenguigui <lbenguigui@gmail.com>
2023-09-29 12:18:06 +02:00
ab7993428d Improve CNAME flattening to avoid unnecessary error logging 2023-09-28 12:00:06 +02:00
b966215e6c Move origin fields capture to service level
Co-authored-by: lbenguigui <lbenguigui@gmail.com>
2023-09-27 15:22:06 +02:00
b786f58f80 fix: false positive in url anonymization 2023-09-26 08:28:25 +02:00
173154cf59 Ignore ErrKeyNotFound error for the KV provider 2023-09-25 16:38:07 +02:00
4acec60e72 fix: wrong log level 2023-09-25 09:10:05 +02:00
c3880a69ca Update quic-go to v0.39.0 2023-09-25 09:08:07 +02:00
4d63eb30f9 Allow X-Forwarded-For delete operation
Co-authored-by: landrybe <lbenguigui@gmail.com>
2023-09-22 11:00:07 +02:00
0ee377bc9f Instruct people to send enhancements to the v3 branch 2023-09-18 22:08:05 +02:00
dbc679dc30 Updates business callout in the documentation 2023-09-13 18:38:05 +02:00
fc7f732029 doc: fix accessControlAllowHeaders examples 2023-09-12 23:52:05 +02:00
ba912e1a93 Change Arvancloud URL 2023-09-09 15:26:05 +02:00
3216c8ab10 Adjust forward auth to avoid connection leak 2023-09-09 12:36:05 +02:00
561c580701 Update quic-go to v0.38.1 2023-09-05 09:34:05 +02:00
3fd5c747a2 Update go-acme/lego to v4.14.0 2023-08-22 10:02:05 +02:00
b6b6cef3da Update quic-go to v0.38.0 2023-08-22 09:36:05 +02:00
d651d1e7cf Update quic-go to v0.37.6 2023-08-21 09:10:05 +02:00
6f22b9e0a7 Update quic-go to v0.37.5 2023-08-17 15:40:05 +02:00
f29325c679 Update to go1.21 2023-08-16 17:50:06 +02:00
57780d8004 Update go-acme/lego to v4.13.3 2023-08-14 15:30:06 +02:00
46f4a8541e fix minor typo in swarm example 2023-08-10 05:56:04 +02:00
1d85515aac Remove healthcheck interval configuration warning 2023-08-08 18:10:05 +02:00
55e00be36e Allow short healthcheck interval with long timeout 2023-08-08 16:40:05 +02:00
d6457e6cbb Set sameSite field for wrr load balancer sticky cookie 2023-08-08 15:12:06 +02:00
ca2b9e8e77 Fix GrpcWeb middleware to clear ContentLength after translating to normal gRPC message 2023-08-08 14:48:05 +02:00
d948784d38 correct minor typo in crd-acme docs 2023-08-08 10:00:05 +02:00
1ddb0afb24 fix: reduce disk usage during release
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2023-08-04 12:26:05 +02:00
f518676238 Replace old security form by the GitHub report system 2023-07-27 16:50:06 +02:00
db3e8a7f5a docs: describe the missing db parameter in redis provider 2023-07-27 16:02:05 +02:00
0bd367ebbd Prepare release v2.10.4 2023-07-24 16:44:05 +02:00
f4dc298406 fix: bad anchor on documentation 2023-07-24 16:18:05 +02:00
4f6c15cc14 Merge branch v3.0 into master 2023-07-24 14:00:27 +02:00
3f93e9ea71 Remove CodeQL workflow from PR 2023-07-24 14:00:05 +02:00
eb585740a1 Merge branch v2.10 into v3.0 2023-07-24 12:58:06 +02:00
1709f3854c Update go-acme/lego to v4.13.2 2023-07-24 09:32:05 +02:00
ebde81e91c chore: remove dead static configuration references 2023-07-24 08:40:05 +02:00
47faae25d7 fix: traceability of the middleware plugins 2023-07-20 15:02:07 +02:00
7792d197e6 Update go-acme/lego to v4.13.0 2023-07-20 14:36:07 +02:00
deb4235028 Add CodeQL workflow 2023-07-20 04:10:05 +02:00
7d66f439eb chore: fix PyYAML version 2023-07-19 21:39:14 +02:00
124ee3c48c chore: fix PyYAML version 2023-07-19 21:38:50 +02:00
bed6069e82 fix: avoid panic on resource backends 2023-07-19 17:36:06 +02:00
e29da5ad65 Updates the Hub tooltip content using a web component and adds an option to disable Hub button 2023-07-19 16:56:05 +02:00
48de3b0230 Add support for RISC-V 2023-07-19 12:34:05 +02:00
00048a8351 fix: integration test with Go v1.20.6 2023-07-18 18:50:05 +02:00
2df5defd36 chore: fix PyYAML version 2023-07-18 18:22:55 +02:00
aaa763b7af Upgrade docs build stack 2023-07-10 13:48:05 +02:00
8a68ece2cc Update maintainers guidelines 2023-07-03 15:10:05 +02:00
08b80c20f0 Remove documentation of old swarm options 2023-07-03 09:14:05 +02:00
d4daafa468 Fix migration guide heading 2023-06-26 16:02:05 +02:00
52d2d959af Prepare release v3.0.0-beta3 2023-06-22 01:18:05 +02:00
0a35fa096a Improve Kubernetes support documentation
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2023-06-21 10:06:05 +02:00
a7ef965412 Merge branch v2.10 into v3.0 2023-06-20 19:33:05 +02:00
0a861716d4 Update release documentation 2023-06-20 17:12:05 +02:00
4fbe9b81ec Remove support of the networking.k8s.io/v1beta1 APIVersion 2023-06-20 10:26:05 +02:00
5fd6913ee5 Fix OpenTelemetry metrics
Co-authored-by: LandryBe <[lbenguigui@gmail.com](mailto:lbenguigui@gmail.com)>
2023-06-20 09:12:05 +02:00
7741c68eaa Prepare release v2.10.3 2023-06-19 18:14:30 +02:00
18077ff69a Update go-acme/lego to v4.12.2 2023-06-19 18:08:05 +02:00
fa555d0d29 fix: Remove unnecessary data on release ci 2023-06-19 17:34:05 +02:00
0e5898b2f8 Minor Typo 2023-06-19 14:36:05 +02:00
aae76408e2 Prepare release v2.10.2 2023-06-19 12:00:06 +02:00
9cc9ed6a0c Fix typo 2023-06-17 21:52:05 +02:00
fecaec7a4a feat: new endpoint for collect 2023-06-16 23:08:05 +02:00
e62fe64ec9 Encode query semicolons
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2023-06-15 18:20:06 +02:00
6885e410f0 Support informational headers in middlewares redefining the response writer.
Co-authored-by: LandryBe <lbenguigui@gmail.com>
2023-06-14 17:42:44 +02:00
68ed875966 Update DataDog tracing dependency to v1.50.1 2023-06-14 17:00:06 +02:00
d1bdeb3a92 Fix missing trailer with custom errors middleware
Co-authored-by: LandryBe <lbenguigui@gmail.com>
2023-06-14 14:48:05 +02:00
878e7de56a Add business callouts 2023-06-09 09:18:05 +02:00
27353d0740 Update go-acme/lego to v4.12.1 2023-06-07 09:30:05 +02:00
60bc47d00e Merge branch v3.0 into master 2023-06-05 19:46:59 +02:00
606281a4a5 Merge branch v2.10 into v3.0 2023-06-05 11:43:02 +02:00
c5f23493ab chore: update linter 2023-06-05 10:24:06 +02:00
db515195f0 docs: fix over-indented yaml configuration of access logs 2023-06-04 08:00:05 +02:00
9aa57f362b fix: improve error messages related to plugins 2023-06-02 11:34:06 +02:00
6977b68b72 Fix multiple subsets endpoint 2023-05-31 11:40:05 +02:00
8d8717d421 Update go-acme/lego to v4.12.0 2023-05-29 13:04:05 +02:00
cf1cbb24df Merge branch v3.0 into master 2023-05-17 11:45:55 +02:00
981ad74870 Merge branch v2.10 into v3.0 2023-05-17 11:18:37 +02:00
021f37ff71 Do not check for wildcard domains for non DNS challenge 2023-05-16 16:00:06 +02:00
511762cbf3 fix: clean code related to Hub 2023-05-15 16:38:05 +02:00
466d7461b7 Split Docker provider 2023-05-10 15:28:05 +02:00
1522afe2ec doc: add logo for GitHub dark mode 2023-05-10 09:54:05 +02:00
9c73c4c584 Enable Prometheus provider cleanup when only the router's metrics level is activated
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2023-05-09 17:38:05 +02:00
8f206ce319 Update go-acme/lego to v4.11.0 2023-05-03 10:20:05 +02:00
65c59c9a09 Add FAQ documentation about TLS certificates 2023-04-28 17:56:05 +02:00
e044e2b765 chore: update CI base OS 2023-04-28 15:36:05 +02:00
7805c683e3 Prepare release v2.10.1 2023-04-27 16:46:11 +02:00
e38c0c3969 Update vulcand/oxy to be5cf38 2023-04-27 16:28:06 +02:00
619045eb4b Merge branch v3.0 into master 2023-04-26 14:04:43 +02:00
2cebd0a083 Merge branch v2.10 into v3.0 2023-04-26 11:44:44 +02:00
c0e03ae17d Update Structor to v1.13.2 2023-04-26 06:54:05 +02:00
9060522414 Fix v2.10 migration guide 2023-04-25 11:14:05 +02:00
bb4eb32b1c Prepare release v2.10.0 2023-04-24 15:38:05 +02:00
30f991effa Modify the Hub Button 2023-04-18 11:44:05 +02:00
fc071a5ebe Merge branch v2.10 into master 2023-04-18 09:20:53 +02:00
6082b22922 Update vulcand/oxy to 03de175b3822 2023-04-18 09:16:20 +02:00
5635687a3e fix: DeepCopy of PluginConf 2023-04-17 17:22:05 +02:00
a3f1009170 chore: update pull request template (#9847) 2023-04-17 15:57:41 +02:00
79c5f34156 Merge branch v2.10 into v3.0 2023-04-17 11:58:01 +02:00
928db9bc42 chore: update linter 2023-04-17 11:01:26 +02:00
c4bea197ab More details on for mTLS 2023-04-12 12:10:05 +02:00
mpl
e8878fe6ac Prepare release v2.10.0-rc2 2023-04-07 11:00:06 +02:00
mpl
f344239bef Merge branch 'v2.9' into v2.10 2023-04-06 18:44:23 +02:00
mpl
4ed3964b35 Prepare release v2.9.10 2023-04-06 18:10:03 +02:00
11966c2098 Improve concepts page 2023-04-05 14:44:06 +02:00
0d1bb72306 docs: update wording - add link descriptions 2023-04-05 14:16:06 +02:00
4c9765b52d Display period setting of the RateLimit middleware in the webui 2023-04-04 18:12:06 +02:00
5f514b0d16 Update Call To Actions 2023-04-04 16:42:06 +02:00
01f346f239 Add accessControlAllowHeaders example 2023-04-04 14:36:11 +02:00
be1b1a6489 chore: update linter 2023-04-03 10:06:06 +02:00
ae65d5ff78 Update Yaegi to v0.15.1 2023-03-30 12:10:05 +02:00
7fc07c31a0 docs: update wording 2023-03-29 17:16:05 +02:00
f2eda3aa6d chore: bump k8s.io/client-go from v0.22.1 to v0.26.3 2023-03-27 12:14:05 +02:00
ac9d88e5a2 Only warn about missing docker network when network_mode is not host or container 2023-03-24 01:26:07 +01:00
8174860770 Merge branch v3.0 into master 2023-03-22 16:54:12 +01:00
598caf6f78 Adjust quick start 2023-03-22 16:53:41 +01:00
77509b0913 fix: decrease parallel build during the release 2023-03-22 16:53:08 +01:00
8b47c5adf7 Remove deprecated code 2023-03-22 16:40:06 +01:00
a3bcf0f39e Merge branch v2.10 into v3.0 2023-03-22 12:52:38 +01:00
be702c2b61 Prepare release v2.10.0-rc1 2023-03-22 11:06:05 +01:00
54f6144ef2 Merge branch v2.9 into v2.10 2023-03-21 17:11:20 +01:00
a020ab640d Prepare release v2.9.9 2023-03-21 16:47:43 +01:00
7875826bd9 Merge branch v2.10 into v3.0 2023-03-21 16:45:33 +01:00
f7be1e97df Support multiple namespaces in the Nomad Provider 2023-03-21 15:50:06 +01:00
48a2c8e41c Fix Nomad client TLS defaults 2023-03-21 15:32:06 +01:00
mpl
358f47443e hub: get out of experimental.
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2023-03-20 21:14:05 +01:00
3b9e155807 docs: update order of log levels 2023-03-20 18:56:06 +01:00
2083e4bc16 feat: use env variable in github actions 2023-03-20 18:30:08 +01:00
c823879097 Add prometheus metric requests_total with headers
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2023-03-20 18:06:07 +01:00
4bc2305ed3 Expose ContainerName in Docker provider 2023-03-20 17:42:06 +01:00
99d779a546 Add support to send DataDog traces via Unix Socket 2023-03-20 17:16:08 +01:00
6e460cd652 Native Kubernetes service load-balancing 2023-03-20 16:46:05 +01:00
mpl
7c2af10bbd Fix open connections metric
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2023-03-20 16:02:06 +01:00
7af9d16208 Introduce traefik.io API Group CRDs 2023-03-20 15:38:08 +01:00
598a257ae1 Remove config reload failure metrics 2023-03-20 15:14:05 +01:00
b3f162a8a6 Fix default configuration settings for Nomad Provider 2023-03-20 10:44:05 +01:00
4aa3496092 Add HTTP 103 early hints unit test
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2023-03-17 16:46:06 +01:00
mpl
bbe6a5c07b doc: clarify ratelimit middleware 2023-03-14 14:58:06 +01:00
mpl
20e47d9102 compress: add no compress unit tests 2023-03-02 10:26:05 +01:00
21c455cf20 Remove User-Agent header removal from ReverseProxy director func 2023-02-28 17:06:05 +01:00
667b2a4078 Update vulcand/oxy to a0e9f7ff1040
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2023-02-27 15:24:21 +01:00
4ae07d91a4 Update go-acme/lego to v4.10.2 2023-02-27 09:36:06 +01:00
7bdf13ebdc Correcting variable name 'server address' in TCP Router 2023-02-23 23:38:05 +01:00
807feef176 Include user-defined default cert for traefik_tls_certs_not_after metric
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2023-02-23 16:14:06 +01:00
7202038649 chore: update to go1.20 2023-02-23 15:06:05 +01:00
dd710dbeb7 chore: update quic-go to v0.33.0 2023-02-23 10:54:05 +01:00
f26e250648 Mention PathPrefix matcher changes in V3 Migration Guide 2023-02-16 15:54:05 +01:00
80790cba17 Fix yaml indentation in the HTTP3 example 2023-02-16 14:36:05 +01:00
2e6e5cbd03 Prepare release v2.9.8 2023-02-15 16:02:06 +01:00
241fb5093a Merge current v2.9 into v3.0 2023-02-15 11:29:28 +01:00
ab36ea7844 fix: update golang.org/x/net to v0.7.0 2023-02-15 09:56:19 +01:00
cfef9d9df2 Prepare release v2.9.7 2023-02-14 16:09:19 +01:00
9ce69fbdef chore: update some dependencies 2023-02-14 15:44:21 +01:00
1a6dfe1f6b Adds the support for IPv6 in the TCP HostSNI matcher 2023-02-14 15:04:05 +01:00
e053eb6f17 Update go-acme/lego to v4.10.0 2023-02-10 11:36:10 +01:00
mpl
780936eff9 doc: add note about remoteaddr strategy 2023-02-09 17:34:06 +01:00
mpl
0503253cfe doc: add CNAME support and gotchas 2023-02-09 17:12:06 +01:00
39331e41a8 Update Yaegi to v0.15.0 2023-02-09 11:52:05 +01:00
044dc6a221 fix: go module 2023-02-03 15:24:05 +01:00
38f5024ed0 Differentiate UDP stream and TCP connection in logs 2023-01-31 16:00:10 +01:00
mpl
479878503d quic-go: bump to 89769f409f 2023-01-31 14:38:05 +01:00
6f6c1f7fec Update dependencies 2023-01-30 09:34:44 +01:00
e50bf21a84 Update Structor to v1.12.0 2023-01-23 10:44:04 +01:00
d66875f903 Update paerser to v0.2.0 2023-01-23 09:34:04 +01:00
707f84e2e4 Don't log EOF or timeout errors while peeking first bytes in Postgres StartTLS hook 2023-01-12 12:28:04 +01:00
f94298e867 Fix datasource variable of the Grafana dashboard 2023-01-11 15:16:06 +01:00
b995a11d63 Prevent panicking when a container has no network interfaces
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2023-01-11 15:14:05 +01:00
e1abf103c0 Add OpenTelemetry in observability overview
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2023-01-10 17:06:04 +01:00
f01a668d53 feat: update copyright to match new standard 2023-01-09 19:56:04 +01:00
8cd4923e72 Added router priority to webui's list and detail page 2023-01-09 17:24:05 +01:00
cd90b9761a Merge current v2.9 into v3.0 2023-01-09 16:21:45 +01:00
e82976e001 Add info admonition about routing to k8 services 2023-01-09 16:07:09 +01:00
f0f5f41fb9 Fix OpenTelemetry service name
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2023-01-06 09:10:05 +01:00
c9e9e8dee2 Further Let's Encrypt ratelimit warnings 2023-01-04 12:10:05 +01:00
0861c47e54 fix no rate limiting if average is 0 2023-01-03 16:16:05 +01:00
8bf68b7efd Grafana dashboard showing ms instead of s 2023-01-02 17:34:04 +01:00
e1e86763e3 Prevents superfluous WriteHeader call in the error middleware
Co-authored-by: LandryBe <lbenguigui@gmail.com>
2023-01-02 17:00:05 +01:00
b22aef7fff Merge branch v2.9 into v3.0 2023-01-02 15:20:39 +01:00
b9a175f5c2 Update copyright for 2023 2023-01-02 12:12:05 +01:00
a2016a2953 Detect dashboard assets content types
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2022-12-29 09:46:04 +01:00
c38d405cfd Remove containous/mux from HTTP muxer
Co-authored-by: Simon Delicata <simon.delicata@traefik.io>
2022-12-22 17:16:04 +01:00
8c98234c07 Add option to the Ingress provider to disable IngressClass lookup 2022-12-22 16:30:05 +01:00
d046af2e91 Add support for HTTPRequestRedirectFilter in k8s Gateway API 2022-12-22 15:02:05 +01:00
943238faba Remove InfluxDB v1 metrics middleware 2022-12-19 14:32:04 +01:00
2b67f1f66f Remove Marathon provider 2022-12-19 11:52:05 +01:00
943811fad6 Update submitting pull requests to include language about drafts 2022-12-19 11:42:04 +01:00
2ad1fd725a Remove Rancher v1 provider 2022-12-19 10:42:05 +01:00
7129f03dc9 fix: update opentelemetry dependency versions 2022-12-19 09:54:04 +01:00
29b8b6911e fix: sanitize X-Forwarded-Proto header in RedirectScheme middleware
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2022-12-16 10:34:04 +01:00
e7baf44a2e doc: Improve TLSStore CRD documentation 2022-12-15 14:32:06 +01:00
mpl
74ef79ea23 mitigate race against server readiness in test
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2022-12-15 11:18:05 +01:00
748254b6c5 doc: Update Grafana Official Dashboards 2022-12-13 16:16:06 +01:00
a08a428787 Support HostSNIRegexp in GatewayAPI TLS routes 2022-12-12 16:30:05 +01:00
3eeea2bb2b Add TCP Servers Transports support
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2022-12-09 09:58:05 +01:00
mpl
da93dab828 make file provider more resilient wrt first configuration
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
2022-12-09 09:48:04 +01:00
c2dac39da1 fix: detect dashboard content types
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2022-12-09 08:24:05 +01:00
e54ee89330 Prepare release v3.0.0-beta2 2022-12-07 17:26:04 +01:00
fdd3f2abef Moves HTTP/3 outside the experimental section 2022-12-07 17:02:05 +01:00
517917cd7c Merge current v2.9 into master 2022-12-07 15:55:46 +01:00
d97d3a6726 Prepare release v2.9.6 2022-12-07 15:14:05 +01:00
6c75052a13 Change traefik cmd error log to error level 2022-12-07 11:34:06 +01:00
a8df674dcf fix: flaky tests 2022-12-07 10:56:05 +01:00
abd569701f fix: update golang.org/x/net 2022-12-07 10:02:04 +01:00
mpl
7e3fe48b80 Handle broken TLS conf better
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2022-12-06 18:28:05 +01:00
8cf9385938 Rework Host and HostRegexp matchers
Co-authored-by: Simon Delicata <simon.delicata@traefik.io>
2022-12-06 10:40:06 +01:00
519ed8bde5 Prepare release v3.0.0-beta1 2022-12-05 16:58:04 +01:00
46a61ce9c8 Merge remote-tracking branch 'upstream/v2.9' into merge-branch-v2.9-into-master 2022-12-05 15:23:06 +01:00
778188ed34 fix: remove logs of the request 2022-12-05 11:30:05 +01:00
88603810a8 Add information about the Hub Agent 2022-12-01 14:30:06 +01:00
c7647b4938 doc: Update Helm installation section 2022-12-01 10:10:05 +01:00
af71443b61 Added networking example 2022-11-30 15:04:05 +01:00
c57876c116 Improve provider logs 2022-11-30 09:50:05 +01:00
0d81fac3fc Add OpenTelemetry tracing and metrics support 2022-11-29 15:34:05 +01:00
db287c4d31 Disable Content-Type auto-detection by default 2022-11-29 11:48:05 +01:00
4d86668af3 Update routing syntax
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
2022-11-28 15:48:05 +01:00
b93141992e Merge branch v2.9 into master 2022-11-28 09:01:53 +01:00
18d66d7432 Update go-acme/lego to v4.9.1 2022-11-28 08:48:04 +01:00
a3e4c85ec0 Remove deprecated options 2022-11-25 10:50:06 +01:00
bee86b5ac7 fix: log level 2022-11-25 09:52:04 +01:00
0ba51d62fa fix: flaky with shutdown tests 2022-11-24 17:06:07 +01:00
268d1edc8f Fix flaky healthcheck test 2022-11-24 16:32:05 +01:00
580e7fa774 fix: flaky tests on the configuration watcher 2022-11-24 16:00:06 +01:00
7c72780820 Add missing serialNumber passTLSClientCert option to middleware panel 2022-11-24 12:30:05 +01:00
46c266661c Add a status option to the service health check 2022-11-24 11:40:05 +01:00
61325d7b91 Merge branch v2.9 into master 2022-11-23 17:30:49 +01:00
68e8eb2435 Update k3s image to rancher/k3s:v1.20.15-k3s1 2022-11-23 17:28:04 +01:00
3f8aa13e68 Fix error when setting ServerUp metric labels 2022-11-23 16:04:05 +01:00
08279047ae Improve test logger assertions 2022-11-23 12:14:04 +01:00
3dd4968c41 Retry on plugin API calls 2022-11-23 11:42:04 +01:00
ba1ca68977 Merge branch v2.9 into master 2022-11-23 09:22:52 +01:00
81a5b1b4c8 Increase the timeout on plugin download 2022-11-22 18:30:05 +01:00
52e6ce95cf Update DataDog tracing dependency to v1.43.1 2022-11-22 15:12:06 +01:00
d547718fdd Support of allowEmptyServices in TraefikService 2022-11-22 10:18:04 +01:00
56f7515ecd New logger for the Traefik logs 2022-11-21 18:36:05 +01:00
mpl
af4e74c39d doc: clarify PathPrefix greediness 2022-11-21 17:30:06 +01:00
27c02b5a56 Log TLS client subject 2022-11-21 10:18:05 +01:00
f6b7940b76 Prepare release v2.9.5 (#9513) 2022-11-17 15:57:23 +01:00
f1b91a119d Create a new capture instance for each incoming request
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2022-11-17 10:26:06 +01:00
630de7481e Support SNI routing with Postgres STARTTLS connections
Co-authored-by: Michael Kuhnt <michael.kuhnt@daimler.com>
Co-authored-by: Julien Salleyron <julien@containo.us>
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2022-11-16 15:34:10 +01:00
fadee5e87b Rework servers load-balancer to use the WRR
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-11-16 11:38:07 +01:00
35d8281f4d docs(contributing): enhance wording of building-testing page 2022-11-15 19:34:04 +01:00
67d9c8da0b Add support for Brotli
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-11-15 10:56:08 +01:00
00de5c711a docs(contributing): add link descriptions and update wording 2022-11-15 10:28:07 +01:00
b935c80dbd docs: update helm repository 2022-11-14 16:04:16 +01:00
22c6630412 Removes the experimental tag on the Traefik Hub header 2022-11-09 00:12:05 +01:00
1a1cfd1adc Update and publish official Grafana Dashboard 2022-11-08 15:32:06 +01:00
240fb871b6 Support gRPC and gRPC-Web protocol in metrics 2022-11-08 10:52:09 +01:00
b2c4221429 Update vulcand/oxy to v1.4.2 2022-11-07 10:28:08 +01:00
d131ef57da chore: update nhooyr.io/websocket 2022-11-03 16:30:08 +01:00
97de552e06 chore: update github.com/opencontainers/runc 2022-11-03 16:28:05 +01:00
281fa25844 Merge branch v2.9 into master 2022-10-28 09:22:36 +02:00
454f552691 Prepare release v2.9.4 2022-10-27 20:40:05 +02:00
7258048403 Prepare release v2.9.3 2022-10-27 17:50:54 +02:00
bd3eaf4f5e Add GrpcWeb middleware
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-10-27 17:34:06 +02:00
15f7472091 Prepare release v2.9.2 2022-10-27 16:53:16 +02:00
a041a6b198 Handle capture on redefined http.responseWriters
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2022-10-27 16:08:06 +02:00
7582da9650 Update Yaegi to v0.14.3 2022-10-26 18:22:05 +02:00
7a6bfd3336 chore: change TCP middleware package 2022-10-26 17:42:07 +02:00
1b9873cae9 Renaming IPWhiteList to IPAllowList 2022-10-26 17:16:05 +02:00
e86f21ae7b Merge branch 'v2.9' into master 2022-10-24 11:24:41 +02:00
ccbbd0d766 Remove side effect on default transport tests 2022-10-24 10:52:04 +02:00
93212125e3 chore: bump github.com/BurntSushi/toml to v1.2.1 2022-10-23 14:16:05 +02:00
be3b798dd6 chore: update actions/cache to v3 2022-10-21 16:08:05 +02:00
8128d6ca26 Simplify dashboard rule example 2022-10-18 15:38:12 +02:00
194247caae Check if default servers transport spiffe config is not nil 2022-10-18 10:28:07 +02:00
cd0654026a Merge branch v2.9 into master 2022-10-17 18:53:37 +02:00
14ab1514dc chore: update linter 2022-10-17 12:00:10 +02:00
40242294d8 Fix links to gateway API guides 2022-10-17 10:52:08 +02:00
996eccf5b7 Remove unnecessary linting exclusions 2022-10-14 18:52:08 +02:00
b39ce8cc58 Support SPIFFE mTLS between Traefik and Backend servers 2022-10-14 17:16:08 +02:00
e9de061b84 Add v2.9 to release page 2022-10-14 16:04:07 +02:00
33f0aed5ea Support custom headers when fetching configuration through HTTP 2022-10-14 15:10:10 +02:00
0ca1c8aac3 fix: redis configuration type 2022-10-13 15:34:09 +02:00
2c550c284d Remove raw cert escape in PassTLSClientCert middleware 2022-10-13 15:08:08 +02:00
87815586be chore: update misspell 2022-10-11 18:18:09 +02:00
mpl
09d6383621 ISSUE_TEMPLATE: clarify maintainers involvement in issues closing 2022-10-11 14:30:08 +02:00
188ef84c4f Allow to define default entrypoints (for HTTP/TCP) 2022-10-11 09:36:08 +02:00
a5c520664a Merge branch v2.9 into master 2022-10-06 16:40:09 +02:00
39b0077725 chore: update linter 2022-10-04 20:38:09 +02:00
e2a9caf760 updated go-acme/lego to v4.9.0
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2022-10-04 12:36:09 +02:00
bc79796c38 prepare-release-v2.9.1 (#9410) 2022-10-03 16:17:58 +02:00
b1db81d8ac Prepare release v2.9.0 (#9409) 2022-10-03 15:43:04 +02:00
38d7011487 Add Tailscale certificate resolver
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2022-09-30 15:20:08 +02:00
ae7db879d9 Prepare release v2.9.0-rc5 2022-09-30 15:02:08 +02:00
dd34905ea9 Merge branch v2.8 into v2.9 2022-09-30 12:24:04 +02:00
3812e6f3cb Prepare release v2.8.8 2022-09-30 12:03:03 +02:00
627175694d Fix autoDiscoverClusters option documentation for ECS provider 2022-09-30 10:57:48 +02:00
82cf6c9577 Fix watch option description for Docker provider 2022-09-30 10:50:09 +02:00
63a1186d3e Update golang.org/x/net to latest version 2022-09-30 10:22:10 +02:00
f75f636e27 Improve documentation for publishedService and IP options 2022-09-29 10:14:08 +02:00
615dc7fd35 Prepare release v2.8.7 2022-09-23 16:22:38 +02:00
52b6b057f0 Prepare release v2.9.0-rc4 2022-09-23 16:01:00 +02:00
7b3faef4b3 Merge branch v2.8 into v2.9 2022-09-23 15:28:57 +02:00
7758880f3f Prepare release v2.8.6 2022-09-23 15:24:15 +02:00
d04903edb2 fix: query parameter matching with equal 2022-09-23 15:12:29 +02:00
a63d5c95a8 Rework metrics overview page 2022-09-23 11:06:09 +02:00
bb66950197 fix: acme panic 2022-09-23 10:42:09 +02:00
c4cc30ccc6 Merge branch v2.8 into v2.9 2022-09-23 09:07:13 +02:00
9cd54baca4 Optimize websocket headers handling
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-09-22 10:00:09 +02:00
7ac687a0a9 providers: simplify AddServer algorithms 2022-09-21 14:54:08 +02:00
83ae1021f6 fix: UDP loadbalancer tags not being used with Consul Catalog 2022-09-21 14:30:09 +02:00
033fccccc7 Support gRPC healthcheck 2022-09-20 16:54:08 +02:00
df99a9fb57 Add option to keep only healthy ECS tasks 2022-09-20 15:42:08 +02:00
67e3bc6380 Add documentation for ECS constraints option 2022-09-20 12:22:08 +02:00
d6b69e1347 Support multiple namespaces in the Nomad Provider 2022-09-19 16:26:08 +02:00
4bd055cf97 Merge branch v2.9 into master 2022-09-19 13:52:58 +02:00
4b291b2cf8 Merge branch v2.8 into v2.9 2022-09-19 11:53:00 +02:00
89870ad539 docs: fix link to RouteNamespaces 2022-09-19 11:26:08 +02:00
5bc03af75f Prepare release v2.9.0-rc3 2022-09-16 16:00:08 +02:00
30ec5c58fe Merge current v2.8 into v2.9 2022-09-16 14:57:07 +02:00
a4b447256b Add a note on case insensitive regex matching 2022-09-16 12:16:09 +02:00
1c9a7b8c61 Add documentation for json schema usage to validate config in the FAQ
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-09-16 09:54:09 +02:00
d06573de6c plugins: allow empty config 2022-09-15 11:00:09 +02:00
6c2c561d8f Prepare release v2.9.0-rc2 2022-09-14 17:33:51 +02:00
e5309a4601 chore: drop Windows arm v5/6/7 2022-09-14 17:29:26 +02:00
e9f98fb6eb Prepare release v2.9.0-rc1 (#9334) 2022-09-14 16:52:03 +02:00
b351266b2d Add support for ECS Anywhere 2022-09-14 16:22:08 +02:00
fd95560c66 fix: shellcheck 2022-09-14 15:10:08 +02:00
Qi
788f8fa951 Make the loadbalancers servers order random
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2022-09-14 14:42:08 +02:00
89dc466b23 Quiet down TCP RST packet error on read operation 2022-09-14 11:50:08 +02:00
ab8d7d2e78 Remove Pilot support 2022-09-14 10:56:08 +02:00
a002ccfce3 ACME Default Certificate
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2022-09-13 20:34:08 +02:00
693d5da1b9 Merge v2.8 into master 2022-09-13 17:17:58 +02:00
8ddc37d528 Prepare release v2.8.5 2022-09-13 17:13:58 +02:00
0cb2652f51 Update Yaegi to v0.14.2 2022-09-13 15:44:08 +02:00
fe8e7ab5b8 docs: update Docker Swarm link 2022-09-12 23:13:11 +02:00
d531963f95 Update valkeyrie to v1.0.0 2022-09-12 17:40:09 +02:00
d578ed7327 Add traffic size metrics
Co-authored-by: OmarElawady <omarelawady1998@gmail.com>
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2022-09-12 17:10:09 +02:00
10528c973a Add Datadog GlobalTags support 2022-09-12 15:14:08 +02:00
56a1ed4220 docs: update Docker Swarm Load Balancer link 2022-09-10 01:18:29 +02:00
37b6edb28c Added resources for businesses 2022-09-09 17:17:53 +02:00
44a2b85dba Display default TLS options in the dashboard 2022-09-09 12:46:09 +02:00
77c8d60092 fix: IPv6 addr in square brackets 2022-09-09 10:44:07 +02:00
b33c8cec0b Update deprecation notes about Pilot 2022-09-08 11:22:08 +02:00
52df1d63fe Use IPv6 address 2022-09-08 11:20:09 +02:00
c84378d649 Change default TLS options for more security 2022-09-08 10:56:08 +02:00
12dccc4fdd doc: add healthcheck timeout seconds to value 2022-09-05 17:22:08 +02:00
32e44816c9 Prepare release v2.8.4 2022-09-02 16:38:08 +02:00
23c74c9f2e Update deprecation notes about Pilot 2022-09-02 16:00:09 +02:00
9a82d96e68 Add missing networking apiGroup in Kubernetes RBACs examples and references 2022-09-02 12:18:08 +02:00
d9589878fb fix: allow starting Traefik even if plugin services have an issue 2022-09-02 11:44:08 +02:00
703de5331b Merge current v2.8 into master 2022-08-31 18:19:31 +02:00
d3e4d56a0d Fix Docker provider mem leak on operation retries
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2022-08-31 18:04:08 +02:00
adf82d72ae chore: update linter 2022-08-31 08:24:08 +02:00
25027d6df8 fix: don't retry on panic 2022-08-29 11:36:08 +02:00
e56dfeb7d5 fix a typo 2022-08-29 09:24:07 +02:00
5ca7fff7f6 doc: fix infobloc documentation 2022-08-25 10:34:09 +02:00
dfa1f3fc00 Fix k8s for example for rootCAs serversTransport 2022-08-24 16:16:08 +02:00
b26c45af2b chore: update paerser to v0.1.9 2022-08-19 15:58:08 +02:00
626da4c0ae Merge current v2.8 into master 2022-08-18 14:50:44 +02:00
9c02612f65 Update codegen docker image to golang:1.19 2022-08-18 11:24:08 +02:00
b3f4f6bb21 Prepare release v2.8.3 2022-08-12 16:19:31 +02:00
2cac58d9c0 Update paeser to v0.1.8 2022-08-12 16:08:07 +02:00
a553085689 Add migration guide for v2.8.3 2022-08-12 11:42:10 +02:00
6dd63e1702 Add missing context in backoff for Marathon 2022-08-12 10:44:08 +02:00
868ab7a5c8 fix: update paerser to v0.1.7 2022-08-12 09:48:07 +02:00
23c26d64ee Prepare release v2.8.2 2022-08-11 16:50:10 +02:00
63f9ec9c38 Remove request dump from IPWhitelist debug log and tracing message 2022-08-11 16:20:14 +02:00
40db06204b Update valkeyrie to a9a70ee 2022-08-11 15:42:07 +02:00
4755bb2f33 Control allocation and copy of labelNamesValues type
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-08-11 10:58:09 +02:00
45453b20fa chore: update to go1.19 2022-08-09 17:36:08 +02:00
40d2421db9 Add getting started guide for Kubernetes 2022-08-09 16:06:09 +02:00
af749f1864 Add a method option to the service Health Check 2022-08-08 15:22:07 +02:00
1576ad85b8 Place namespace before name in router key for Ingress 2022-08-04 10:22:08 +02:00
2a2ea759d1 Support Nomad canary deployment
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2022-08-01 17:52:08 +02:00
b4ee7bdcbe Bump paerser to v0.1.6 2022-08-01 15:12:08 +02:00
146991efda Fix wording of default behavior for namespaces option 2022-08-01 10:10:07 +02:00
ab94bbaece Merge current v2.8 into master 2022-07-25 17:31:51 +02:00
5a706296f2 chore: cleanup 2022-07-25 17:22:31 +02:00
5b3354b8ce Update Thank You page with proper branding and grammar fixes 2022-07-22 09:50:09 +02:00
7751fb24eb Update linter 2022-07-19 18:38:09 +02:00
f85f3b68aa Add support for reaching containers using host networking on Podman 2022-07-19 16:22:08 +02:00
b361608693 Lint markdown files 2022-07-18 12:22:08 +02:00
cdda9a18ab Upgrade quic-go to v0.28.0 2022-07-18 11:10:08 +02:00
3686f95832 Update CONTRIBUTING.md to contain all information in one place 2022-07-18 11:08:08 +02:00
2cb011f595 Fix service up gauge for Prometheus metrics
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
2022-07-18 10:36:11 +02:00
mpl
b7199a7a9b integration: use VPN for integration tests (for Mac)
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-07-13 18:32:08 +02:00
14eb56cf30 Update the PR guidelines in Contributing docs 2022-07-13 09:50:08 +02:00
ff2911d070 Refactor certificate domains matching func 2022-07-12 16:16:08 +02:00
f07fcd3d54 Add missing inline tag for YAML serialization 2022-07-12 12:12:08 +02:00
0e4b4c1a31 docs: update plugins doc 2022-07-12 11:48:13 +02:00
154d8470ab feat: remove netlify 2022-07-12 10:00:08 +02:00
c9520480c2 Prepare release v2.8.1 2022-07-11 16:02:09 +02:00
05c3486347 Update the language for advocating page 2022-07-08 10:28:08 +02:00
0231db05b4 Improve performances when Prometheus metrics are enabled 2022-07-07 18:00:09 +02:00
4dc379c601 Support ALPN for TCP + TLS routers 2022-07-07 16:58:09 +02:00
8f6463ba7a Support forwarded websocket protocol in RedirectScheme
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-07-06 11:54:08 +02:00
aff334ffb4 Add allowEmptyServices for Docker provider 2022-07-06 10:24:08 +02:00
28da781194 Add callout for anyone using Traefik to manage commercial applications 2022-07-05 10:02:09 +02:00
51a02caea3 Upgrade valkeyrie to v0.4.1 2022-07-04 15:50:09 +02:00
839bc7b3a8 Remove -a when building binary 2022-06-30 18:12:08 +02:00
9c79fafeeb Update deprecation notices 2022-06-30 14:34:08 +02:00
c51e590591 Merge current v2.8 into master 2022-06-30 10:24:37 +02:00
9c4b336f3b Prepare release v2.8.0 2022-06-29 17:38:37 +02:00
aa8fda5eae Merge current v2.7 into v2.8 2022-06-29 15:57:57 +02:00
8b22101236 Prepare release v2.7.3 2022-06-29 15:44:08 +02:00
3c1d5e0393 Move consulcatalog provider to only use health apis
Co-authored-by: Charles Zaffery <czaffery@roblox.com>
2022-06-29 12:04:09 +02:00
03598d395b Add documentation main, SANs and plugin CRD fields 2022-06-29 11:04:09 +02:00
9d61cb64a2 Ensure that the Datadog client is cleanly stopped 2022-06-29 10:34:08 +02:00
ba3f5b318c Merge current v2.8 into master 2022-06-28 09:30:51 +02:00
62e17c659e Prepare release v2.8.0-rc2 2022-06-27 17:05:11 +02:00
41748c3ae4 Merge current v2.7 into v2.8 2022-06-27 16:12:21 +02:00
65a317010b Prepare release v2.7.2 2022-06-27 15:52:08 +02:00
a887794313 Fix HostRegexp and Query muxers 2022-06-27 15:16:08 +02:00
77e1ce2877 Added useful links for commercial applications 2022-06-27 11:08:08 +02:00
470a4f6e5f Update to improve info section relevance 2022-06-27 10:32:08 +02:00
94141233f0 Add documentation to Traefik CRD properties
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-06-24 12:40:08 +02:00
467c8b31c3 Start polling HTTP provider at the beginning
Co-authored-by: Jason Quigley <jason@onecha.net>
2022-06-24 12:34:08 +02:00
ff17ac53df RedirectScheme redirects based on X-Forwarded-Proto header 2022-06-24 12:04:09 +02:00
55ba4356f2 Allow multiple listeners on same port in Gateway API provider 2022-06-23 11:58:09 +02:00
804b0ff2f2 Do not make multiple requests to the same URL for balancer healthcheck 2022-06-22 21:46:08 +02:00
818541d4d7 Update yaegi to v0.13.0 2022-06-21 19:56:08 +02:00
1b199730d2 docs: add missing info.serialNumber option to PassTLSClientCert middleware 2022-06-21 15:46:08 +02:00
f8f685193d Load plugin configuration field value from Kubernetes Secret
Co-authored-by: nnlquan <longquan0104@gmail.com>
2022-06-20 15:44:08 +02:00
6e535f8cef Use configured token in the Nomad client 2022-06-20 15:42:09 +02:00
23340c46e6 Add log when missing path in health check 2022-06-20 15:40:13 +02:00
5c15f5fe04 Update DataDog tracing dependency to v1.38.1
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2022-06-16 17:54:08 +02:00
ba7e9ed788 Add a note on how to handle server first protocols 2022-06-14 12:24:08 +02:00
9ccc8cfb25 Prepare release v2.8.0-rc1 2022-06-13 17:26:12 +02:00
9810bde68b Merge current v2.7 into master 2022-06-13 15:34:53 +02:00
251798a778 Prepare release v2.7.1 2022-06-13 15:30:08 +02:00
91f4ccf087 Add Traefik Hub button and deprecate Pilot
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
2022-06-13 11:04:08 +02:00
73306a1533 Hub documentation
Co-authored-by: jbdoumenjou <jb.doumenjou@gmail.com>
Co-authored-by: Baptiste Mayelle <baptiste.mayelle@traefik.io>
2022-06-13 10:02:08 +02:00
b3eb629785 Update the contributing docs for clarity and to encourage community activity 2022-06-10 19:06:10 +02:00
aa0b5466a9 Implement Traefik provider for Nomad orchestrator 2022-06-10 18:32:08 +02:00
becee5e393 feat: Reach the catalog of plugins from the Traefik dashboard 2022-06-10 17:08:07 +02:00
59e66dfce5 Merge current branch master into v2.7 2022-06-10 16:17:55 +02:00
9c59df5e9c fix: invalid placeholder in log message 2022-06-10 16:16:08 +02:00
2a88b25712 Update gateway api link from v1alpha1 to v1alpha2 2022-06-10 15:12:08 +02:00
b952f814c1 docs: fix rule expression render 2022-06-10 09:24:08 +02:00
f90e3817e8 Support multiple namespaces for Consul and ConsulCatalog providers
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-06-03 12:00:09 +02:00
6d6f8b28d7 Update go-acme/lego to v4.7.0 2022-06-02 13:00:08 +02:00
118d56fc40 Update the link for contributor swag 2022-06-02 09:36:08 +02:00
f352c34136 Merge current v2.7 into master 2022-06-01 13:39:20 +02:00
fbf90e6981 Update Gateway API links 2022-06-01 10:42:08 +02:00
607faace07 Fix typo in stripPrefix middleware docs 2022-05-30 14:10:08 +02:00
521109d3f2 Merge current v2.7 into master 2022-05-30 12:14:26 +02:00
Qi
ec25bdb9f9 Add destination address to debug log 2022-05-30 11:14:09 +02:00
mpl
685962545a docs: fix traefik version s/2.6/2.7/ 2022-05-25 18:14:08 +02:00
34d29e7a10 Prepare release v2.7.0 2022-05-24 18:58:08 +02:00
05f3e60366 Merge branch v2.6 into v2.7 2022-05-24 17:49:39 +02:00
5aa1220e5a Prepare release v2.6.7 2022-05-24 16:14:08 +02:00
mpl
c1919c6b24 Update Yaegi to v0.12.0 2022-05-23 12:52:08 +02:00
6349e2e28c Updated browserXssFilter key to camel case 2022-05-23 10:50:08 +02:00
e642365613 Fix panic when getting certificates with non-existing store
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
2022-05-19 17:12:08 +02:00
ac4086d0ac Fix TCP-TLS/HTTPS routing precedence
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2022-05-19 16:44:14 +02:00
d5ff301d90 Support certificates configuration in TLSStore CRD
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2022-05-19 16:42:09 +02:00
575d4ab431 Fix initial tcp lookup when address is not available 2022-05-19 16:40:09 +02:00
ede2be1f66 fix: skip Provide when TLS is nil 2022-05-19 15:00:16 +02:00
d134a993d0 docs: fix default priority of the entrypoint redirection 2022-05-19 08:56:07 +02:00
86cc6df374 feat: use dedicated entrypoint for the tunnels
Co-authored-by: Fernandez Ludovic <[ldez@users.noreply.github.com](mailto:ldez@users.noreply.github.com)>
2022-05-18 17:22:08 +02:00
32920ca65c Update linter 2022-05-17 15:48:08 +02:00
3ac708ddcb Fix log statement for ExternalName misconfig 2022-05-16 10:00:08 +02:00
0dac0c3a5b Fix typo in maintainers guidelines 2022-05-13 09:44:08 +02:00
9810120aff Upgrade to oxy v1.4.1 2022-05-11 09:12:08 +02:00
ae6e844143 Support URL replacement in errors middleware 2022-05-10 11:00:09 +02:00
a34e1c0747 Upgrade to oxy v1.4.0 2022-05-10 09:36:08 +02:00
c29ed24a06 Update jaeger-client-go to v2.30.0 2022-05-10 08:50:09 +02:00
619621f239 Merge branch v2.6 into v2.7 2022-05-04 10:20:46 +02:00
ff5cd9b592 Prepare Release v2.6.6 2022-05-03 18:53:05 +02:00
af855ef7b4 fix: generated placeholder for the webui 2022-05-03 18:46:16 +02:00
6559d63d3c Prepare release v2.6.5 2022-05-03 18:28:08 +02:00
4758cc0c8e Fix clean-webui target 2022-05-03 17:58:08 +02:00
e4ed829661 Prepare release v2.6.4 2022-05-03 16:32:08 +02:00
2968e5b61b fix: prevent failure of collected data 2022-05-03 15:54:08 +02:00
7d274e8088 Deprecate caOptional option in client TLS configuration 2022-04-28 14:58:08 +02:00
6c2eb6eef3 Filter out ECS anywhere instance IDs 2022-04-28 14:24:08 +02:00
95257d2ee1 Fix RenewInterval computation in ACME provider 2022-04-26 14:36:08 +02:00
707d355d4a Merge branch v2.7 into master 2022-04-21 11:40:16 +02:00
73ba7ed2d2 Merge branch v2.6 into v2.7 2022-04-21 10:59:46 +02:00
mpl
55addfefc8 Re-add missing writeheader call in flush
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-04-21 10:42:08 +02:00
mpl
0ecd85cc66 Fix bug for when custom page is large enough
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-04-20 16:42:09 +02:00
a9fe3f98c5 Update Yaegi to v0.11.3 2022-04-20 14:56:09 +02:00
77b2a88819 Fix Traefik community links in GitHub templates 2022-04-20 14:20:08 +02:00
44621ad28c Fix default for buffering middleware
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-04-19 15:32:08 +02:00
232e2c1e7d Fix regexp handling in redirect middleware 2022-04-15 17:24:08 +02:00
ad3625bef3 Improve documentation Makefile 2022-04-15 16:16:08 +02:00
7c4bf602f0 Add title and description metadata to documentation pages 2022-04-15 15:44:08 +02:00
ffdd693ff6 codegen: fix for users with large uids 2022-04-15 15:12:08 +02:00
85b0a47fe8 docs: fix certificateRefs in dynamic configuration 2022-04-15 13:52:08 +02:00
78822a8015 docs: add default mode for fields.names to access log 2022-04-15 12:48:08 +02:00
55cef21fbe Move accessLog.fields example to TOML section 2022-04-15 12:16:08 +02:00
2691ac1307 Add safe.directory to the build image 2022-04-15 11:56:08 +02:00
a51851247e Preflight requests are not forwarded to services 2022-04-11 17:22:09 +02:00
0e532a3634 Update dynamic and static configuration references 2022-04-06 11:06:08 +02:00
883422dc21 Upgrade quic-go to v0.27.0 2022-04-06 10:06:13 +02:00
c9daf16388 Add .PHONY to Makefile targets 2022-04-05 17:18:07 +02:00
b22945e185 Remove duplicate error logs 2022-04-05 15:54:07 +02:00
71150bcaaf Allow config of additonal CircuitBreaker params 2022-04-05 12:30:08 +02:00
8c56d1a338 Allow HTTP/2 max concurrent stream configuration 2022-04-04 11:46:07 +02:00
a49b537d9c Prepare release v2.7.0-rc2 2022-03-29 17:00:09 +02:00
45328ab719 Merge v2.6 into v2.7 2022-03-29 15:43:10 +02:00
4b755dc58d Prepare release v2.6.3 2022-03-29 15:00:09 +02:00
0f29e893f4 Return TLS unrecognized_name error when no certificate is available 2022-03-28 18:18:08 +02:00
e3adf93a74 fix: CI release 2022-03-28 17:36:07 +02:00
0d7d5a0318 Upgrade quic-go to v0.26.0 2022-03-28 17:08:09 +02:00
81f88dd998 Freeze python dependencies 2022-03-28 16:22:10 +02:00
b6bfa905db Fix slice parsing for plugins 2022-03-28 15:24:08 +02:00
c0b0f3f0f7 Fix hub tls documentation 2022-03-25 15:42:08 +01:00
16d7b89cb1 Fixing dependency to build doc 2022-03-24 21:40:08 +01:00
a4560fa20d Prepare release v2.7.0-rc1 2022-03-24 20:54:08 +01:00
fbdb6e6e78 Add Traefik Hub Integration (Experimental Feature) 2022-03-24 19:44:08 +01:00
8d58f33a28 Merge v2.6 into master 2022-03-24 17:22:56 +01:00
9398222db7 Prepare release v2.6.2 2022-03-24 17:14:57 +01:00
d2a2362be5 Add a Feature Deprecation page 2022-03-24 12:28:07 +01:00
4c0a3721d0 Plugins and token 2022-03-24 08:54:07 +01:00
ba2d09f6fb Update entrypoint.md to add consistent CLI syntax 2022-03-23 10:38:09 +01:00
7243e65b51 Fix certificates resolver typo 2022-03-23 09:26:08 +01:00
3bf4a8fbe2 Merge current v2.6 into master 2022-03-22 15:55:44 +01:00
23a6602cbf Bump paerser to v0.1.5 2022-03-22 11:04:08 +01:00
822b94c45d Add default certificate definition example for Kubernetes 2022-03-22 09:56:07 +01:00
0a776c3fd5 Fix small typo in Redis provider documentation 2022-03-21 17:32:07 +01:00
d7378a96ad chore: update linter 2022-03-21 10:42:08 +01:00
db4c6111fd Fix fenced code block typo in Buffering middleware page 2022-03-21 10:10:08 +01:00
2da7fa0397 Add HostSNIRegexp rule matcher for TCP 2022-03-18 16:04:08 +01:00
0d58e8d1ad Add Traefik Hub access and remove Pilot access 2022-03-18 11:06:08 +01:00
dad76e0478 Add muxer for TCP Routers 2022-03-17 18:02:08 +01:00
79aab5aab8 Add Failover service
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-03-17 12:02:09 +01:00
b02c651961 Add a deprecation notices section 2022-03-17 10:28:09 +01:00
0617a1b0e0 Fix routing overview examples 2022-03-16 15:00:08 +01:00
06749e71f2 Clarify concepts documentation page 2022-03-15 15:38:08 +01:00
6622027c7c Merge current v2.6 into master 2022-03-11 10:07:20 +01:00
401c171bbd Add a link to service on router detail view 2022-03-07 16:16:08 +01:00
mpl
a1e766e180 doc: fix, docker uses Label(), not Tag() 2022-03-07 11:48:09 +01:00
63bb770b9c Allow empty services in Kubernetes CRD 2022-03-07 11:08:07 +01:00
b3de9a040b Add a target that is a real resource to generate-webui 2022-03-04 15:28:07 +01:00
a59dbc4c79 Adjust rule length in routers documentation 2022-03-04 11:24:07 +01:00
40deefa868 Fix HostRegexp examples 2022-03-04 10:50:07 +01:00
491de0cf64 Enhance doc on static vs dynamic configuration 2022-03-03 20:18:07 +01:00
c7b24f4e9c Replace npm with yarn to install/run the webui 2022-03-03 18:08:07 +01:00
mpl
27a7563e33 Add simpler and faster debug Makefile target 2022-03-03 15:42:08 +01:00
25725e9b2f Merge current v2.6 into master 2022-02-21 14:07:27 +01:00
819de02101 Spelling 2022-02-21 12:40:09 +01:00
ce851a5929 Fix struct tag typo 2022-02-21 12:10:08 +01:00
7e390ef516 Fix brand typo 2022-02-21 10:50:08 +01:00
fb23bd5d26 Fix empty WebUI static assets directory 2022-02-18 15:44:08 +01:00
6974f54bfd docs: fix product name 2022-02-15 17:04:34 +01:00
aaf5aa4506 Configure advertised port using h3 server option
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2022-02-15 16:04:09 +01:00
371b6e3c86 chore: update linter 2022-02-15 14:56:53 +01:00
9297055ad8 Upgrade quic-go to v0.25.0 2022-02-15 10:16:08 +01:00
9e96089da6 Add s390x arch support 2022-02-15 10:08:08 +01:00
a79868fadc Merge current v2.6 into master 2022-02-15 09:09:16 +01:00
84a0810546 Prepare release v2.6.1 2022-02-14 17:44:08 +01:00
d9fbb5e25c Use CNAME for SNI check on host header
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2022-02-14 17:18:08 +01:00
e97aa6515b Update test certificates 2022-02-14 14:08:07 +01:00
6bcfba43c8 Rename Datadog span tags 2022-02-10 16:00:09 +01:00
0c83ee736c Apply the same approach as the rules system on the TLS configuration choice
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2022-02-10 10:42:07 +01:00
ca55dfe1c6 Support InfluxDB v2 metrics backend 2022-02-09 15:32:12 +01:00
4da33c2bc2 Fix metrics bucket key high cardinality 2022-02-09 09:58:08 +01:00
2d56be0ebb Fix Kubernetes TCP examples 2022-02-07 15:22:07 +01:00
5780dc2b15 Refactor configuration reload/throttling
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2022-02-07 11:58:04 +01:00
764bf59d4d Merge current v2.6 into master 2022-02-04 14:32:57 +01:00
6742dd8454 Fix mixups in metrics documentation 2022-02-03 15:16:12 +01:00
3ac755bd2f Add Hurricane Electric to acme documentation 2022-01-31 13:30:05 +01:00
7543709ecf Watch for Consul events to rebuild the dynamic configuration
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2022-01-28 17:16:07 +01:00
3ed72c4e46 Add domain to HTTP challenge errors 2022-01-27 10:58:04 +01:00
mpl
477fa15859 Clarify that ACME challenge is mandatory 2022-01-26 18:10:05 +01:00
1048348ae6 Merge current v2.6 into master 2022-01-25 18:19:40 +01:00
390eb9cb61 Explain a bit more around enabling HTTP3 2022-01-25 10:48:05 +01:00
5a1c936ede Prepare release v2.6.0 2022-01-24 17:58:04 +01:00
47ad6538f1 Merge current v2.5 into v2.6 2022-01-24 15:42:27 +01:00
9be44d8330 Configure Consul Catalog namespace at client level
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2022-01-24 15:30:05 +01:00
Ali
a4b354b33f Redact credentials before logging
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2022-01-24 11:08:05 +01:00
a70b864c55 Fix typo in metrics overview page 2022-01-21 09:54:07 +01:00
3bd5fc0f90 Prepare release v2.6.0-rc3 2022-01-20 18:58:07 +01:00
aabfb792af Merge current v2.5 into v2.6 2022-01-20 17:44:55 +01:00
e5e48d1cc1 Prepare release v2.5.7 2022-01-20 17:08:07 +01:00
42a110dd69 Adjust log level from info to debug
Co-authored-by: rhtenhove <rhtenhove@users.noreply.github.com>
2022-01-20 12:36:08 +01:00
64af364b02 Merge current v2.5 into v2.6 2022-01-20 09:48:51 +01:00
cf14b8fa92 Update go-acme/lego to v4.6.0 2022-01-20 09:38:07 +01:00
e7dc6ec025 Fix HTTP provider endpoint config example 2022-01-19 19:50:05 +01:00
f29e311b73 Support token authentication for Consul KV 2022-01-19 17:46:11 +01:00
a914ce2bd2 docs: fix instana tracer documentation link 2022-01-19 16:35:06 +01:00
b42a7c89e7 Merge current v2.5 into v2.6 2022-01-19 16:16:18 +01:00
67483c1b17 Exclude www.cloudxns.net from documentation verification 2022-01-19 16:10:08 +01:00
mpl
4071f1e7f2 Mitigate memory leak 2022-01-17 14:28:05 +01:00
577709fff3 fix: middleware plugins memory leak
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2022-01-14 12:22:06 +01:00
8cd45476ac Fix middleware regexp's display 2022-01-13 18:38:06 +01:00
cf14504fd5 Prepare release v2.6.0-rc2 2022-01-12 16:40:06 +01:00
b84829336d Support Consul KV Enterprise namespaces
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2022-01-12 14:42:21 +01:00
ba822acb23 Merge current v2.6 into master 2022-01-10 16:17:25 +01:00
d969e59911 Upgrade Instana tracer dependency 2022-01-10 16:08:20 +01:00
936b6148ff Merge current v2.5 into v2.6 2022-01-10 14:43:25 +01:00
a9776ceafc Improve regexp matcher documentation 2022-01-10 14:32:04 +01:00
e471239955 Remove typo in Kubernetes providers labelSelector examples 2022-01-06 11:58:07 +01:00
2e8156bfaa Update copyright for 2022 2022-01-06 11:34:05 +01:00
f5dd233a3b Merge current v2.6 into master 2021-12-29 17:35:32 +01:00
48ce6c32c1 Remove go-bindata from semaphore 2021-12-29 17:32:06 +01:00
4990239855 Merge current v2.5 into v2.6 2021-12-29 15:08:51 +01:00
5e2c929322 Fix broken jaeger documentation link 2021-12-29 15:06:04 +01:00
2b5355c849 Update golangci-lint install script 2021-12-23 15:44:05 +01:00
f21f71786a Prepare release v2.5.6 2021-12-22 17:22:04 +01:00
fc7f109cb2 Merge current v2.5 into v2.6 2021-12-22 15:02:51 +01:00
a711f0d037 fix: update goreleaser install link to use gist 2021-12-22 14:12:04 +01:00
98fc6ca441 Update Yaegi to v0.11.2 2021-12-22 09:24:05 +01:00
c10f1a3a36 Add missing API endpoints documentation 2021-12-21 14:48:05 +01:00
da092e653d Prepare release v2.6.0-rc1 2021-12-20 17:02:06 +01:00
bf29417136 Merge current v2.5 into master 2021-12-20 14:43:35 +01:00
79a14ce992 Fix passTLSClientCert CRD example name 2021-12-18 00:52:04 +01:00
99ce26f7b1 Correct documentation in middleware overview 2021-12-17 16:24:06 +01:00
16250361c3 chore: update golang.org/x/net dependency version 2021-12-16 11:52:04 +01:00
be44385b42 fix: process all X-Forwarded-For headers in the request 2021-12-14 15:36:07 +01:00
54c77ecb54 Prepare release v2.5.5 2021-12-10 17:52:04 +01:00
a30f0dcabd Update CODE_OF_CONDUCT.md 2021-12-09 11:00:06 +01:00
efef7dce4f plugins: start the go routine before calling Provide 2021-12-08 17:08:05 +01:00
1c9e4c6050 doc: align docker configuration example notes in basicauth HTTP middleware 2021-12-07 10:04:05 +01:00
89cd9e8ddd Merge current v2.5 into master 2021-12-06 17:39:06 +01:00
92093a8c09 Update go-acme/lego to v4.5.3 2021-12-06 15:44:04 +01:00
d970813c20 Support consul enterprise namespaces in consul catalog provider
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2021-12-03 19:30:07 +01:00
f69982aa9d docs: uniformize client TLS config documentation 2021-12-02 15:42:06 +01:00
82fdc569c2 docs: removing typo in consul-catalog provider doc 2021-12-01 15:58:05 +01:00
def0c1a526 Update yaegi to v0.11.1 2021-11-30 17:36:06 +01:00
93de7cf0c0 feat: add in flight connection middleware 2021-11-29 17:12:06 +01:00
ef2d03d96e fix: propagate source criterion config to RateLimit middleware in Kubernetes CRD 2021-11-26 12:10:11 +01:00
321c9421ea chore: update docker/cli and containerd dependency versions 2021-11-25 15:34:06 +01:00
5a225b4196 test: upgrade docker-compose
Co-authored-by: Rémi Buisson <remi.buisson@traefik.io>
2021-11-25 11:10:06 +01:00
95fabeae73 feat: rate-limit ceil Retry-After to superior integer 2021-11-16 16:38:11 +01:00
525a6cf5b2 docs: remove misleading metrics overview configuration 2021-11-16 09:38:12 +01:00
27ec0912d5 docs: health check use readiness probe in k8s 2021-11-15 11:14:06 +01:00
83a7f10c75 Refactor Exponential Backoff 2021-11-10 15:34:10 +01:00
0a5c9095ac feat: allow configuration of ACME certificates duration 2021-11-10 12:06:09 +01:00
0a31225e65 fixed minor spelling error in Regexp Syntax section 2021-11-09 16:50:11 +01:00
db4a92d877 fix: increase UDP read buffer length to max datagram size
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
2021-11-09 15:12:07 +01:00
9df053e3f5 Update yaegi v0.11.0 2021-11-09 14:30:09 +01:00
1f17731369 feat: add readIdleTimeout and pingTimeout config options to ServersTransport
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2021-11-09 12:16:08 +01:00
8e32d1913b Update gateway api provider to v1alpha2
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
2021-11-09 11:34:06 +01:00
e10a82a501 fix: git ignore autogen/ 2021-11-09 03:48:13 +01:00
ce47f200d5 Merge branch v2.5 into master 2021-11-08 22:41:43 +01:00
95dc43ce4a Prepare release v2.5.4 2021-11-08 18:36:13 +01:00
d91eefa74f fix: TCP/UDP wrr when all servers have a weight set to 0
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2021-11-08 17:58:12 +01:00
ffdfc13461 docs: fix typo in addRoutersLabels option title 2021-11-08 13:32:10 +01:00
a13b03ef3d docs: add named groups details to Regexp Syntax section 2021-11-08 10:06:05 +01:00
69d504c905 fix: git ignore webui/static/ 2021-11-05 18:02:05 +01:00
bda7e025a2 docs: remove link to microbadger.com 2021-11-05 17:28:06 +01:00
596f04eae8 chore: update linter 2021-11-04 09:50:11 +01:00
b39d226fb8 fix: use host's root CA set if ClientTLS ca is not defined
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
2021-11-03 17:38:07 +01:00
20dfb91948 docs: remove quotes in certificatesresolvers CLI examples 2021-10-28 18:14:14 +02:00
e033355225 fix: do not validate shell script in node-modules folder 2021-10-27 10:34:05 +02:00
56ed45ae70 docs: remove non-working kind config in IngressRouteTCP/UDP examples 2021-10-26 12:08:12 +02:00
d3ff0c2cd4 fix: do not require a TLS client cert when InsecureSkipVerify is false
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
2021-10-26 10:54:11 +02:00
566b205758 Clarify usage for cross provider references in Kubernetes ingress annotations 2021-10-26 10:30:13 +02:00
b537ccdb0c doc: update traefik image version 2021-10-25 17:18:12 +02:00
d9b8435a7d feat: rename networking.k8s.io/v1beta1 to networking.k8s.io/v1 2021-10-21 09:44:12 +02:00
c0ba4d177f fix: sourceCriterion documentation for InFlightReq and RateLimit middlewares 2021-10-19 14:40:06 +02:00
7377ab7b95 fix(ui): bug parsing weighted service provider name 2021-10-18 14:52:14 +02:00
207ac94ed0 Fix remove http scheme urls in documentation 2021-10-08 11:52:05 +02:00
fe32a7e584 fix: use EscapedPath as header value when RawPath is empty 2021-10-08 11:32:08 +02:00
25e12aee14 kubernetes: normalize middleware names in ingress route config 2021-10-07 15:40:05 +02:00
85dd45cb81 Add prefix to datadog metrics 2021-10-06 17:34:07 +02:00
32340252b2 Merge branch v2.5 into master 2021-10-06 11:55:12 +02:00
5d716f0149 Mention escaping escape characters in YAML for regex usage 2021-10-06 11:36:11 +02:00
918a343557 chore: update proxyprotocol and consul 2021-10-04 17:54:10 +02:00
969dd088a2 gateway api: support RouteNamespaces
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
2021-10-04 15:46:08 +02:00
89001ae9a4 Update go-acme/lego to v4.5.0 2021-10-01 09:20:08 +02:00
c99221fa34 Fix typo in KV providers documentation 2021-09-29 13:22:12 +02:00
9ef3fc84f9 Upgrade Instana tracer and make process profiling configurable 2021-09-29 11:52:08 +02:00
d28bcf24e5 docs: reword tracing config descriptions to be consistent 2021-09-29 10:40:14 +02:00
8d739c411b Move from deprecated ioutil to os and io packages 2021-09-28 15:30:14 +02:00
46c1600ada fix: forward request Host to errors middleware service
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2021-09-27 17:40:13 +02:00
126b32c579 fix: add missing RequireAnyClientCert value to TLSOption CRD 2021-09-24 11:32:07 +02:00
380514941c Merge current v2.5 into master 2021-09-23 16:10:03 +02:00
61ceb7a32c docs: replace links to French translation of k8s docs with English ones 2021-09-21 16:28:11 +02:00
07a3c37a23 Implement customizable minimum body size for compress middleware 2021-09-20 18:00:08 +02:00
c7e13eb082 Prepare release v2.5.3 2021-09-20 17:30:06 +02:00
6906a022ca Add cross namespace verification in Kubernetes CRD 2021-09-20 12:54:05 +02:00
8f0832d340 Add configurable tags to influxdb metrics 2021-09-17 09:08:07 +02:00
bda0dba131 fix: add peerCertURI config to k8s crd provider
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
2021-09-17 08:56:07 +02:00
76867e39ea Fix ServersTransport reference from IngressRoute service definition
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
2021-09-16 15:12:13 +02:00
6f8e8ea252 Ensure disableHTTP2 works with k8s crd 2021-09-16 12:18:08 +02:00
8e7881094f docs: add default proxy headers 2021-09-16 11:18:12 +02:00
7d09132a5c Update yaegi to v0.10.0 2021-09-16 10:20:07 +02:00
6f4a7fb604 chore: upgrade linter 2021-09-16 09:16:07 +02:00
6e28db513c Metrics router fix
Co-authored-by: Michael <michael.matur@gmail.com>
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2021-09-15 17:26:06 +02:00
2084201c8f fix: experimental image build
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
2021-09-15 12:10:06 +02:00
70359e5d27 Replace go-bindata with Go embed
Co-authored-by: nrwiersma <nick@wiersma.co.za>
2021-09-15 10:36:14 +02:00
a72d124551 Fix certChan defaulting on consul catalog provider 2021-09-14 17:12:12 +02:00
7ff13c3e3e Support Kubernetes basic-auth secrets
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2021-09-14 15:16:11 +02:00
55360c1eaf Add Tom Moulard in maintainers team 2021-09-14 10:42:14 +02:00
60ff50a675 Add HTTP3Config 2021-09-10 14:58:13 +02:00
ba3967aa16 Merge current v2.5 into master 2021-09-10 12:00:24 +02:00
fffa413121 Fix golang doc URLs 2021-09-10 11:42:07 +02:00
c011bdfdd8 docs: fix error in example (YAML) for TCP middleware whitelist 2021-09-06 09:30:09 +02:00
4235cef1b2 Merge current v2.5 into master 2021-09-03 09:13:34 +02:00
871e04cb12 Prepare release v2.5.2 2021-09-02 16:46:11 +02:00
287cebb498 Fix CRDs code and manifests generation 2021-09-02 14:40:08 +02:00
6c8d200373 Upgrade github.com/lucas-clemente/quic-go to v0.23.0 2021-09-02 12:06:10 +02:00
0ac6f80b50 Fix empty body error in mirror 2021-09-02 10:46:13 +02:00
2b73860ea5 Adds pathType for v1 ingresses examples 2021-09-02 10:20:12 +02:00
ddcb003b3b Bump go.elastic.co/apm version to v1.13.1 2021-09-02 09:56:11 +02:00
be52c5abb1 Fix http scheme urls in documentation 2021-08-31 18:54:06 +02:00
f81ceaef8a Merge current v2.5 into master 2021-08-30 14:51:57 +02:00
eb6c5fc34d Fix experimental images workflow 2021-08-30 14:24:12 +02:00
4fc16f26a3 Build experimental images 2021-08-30 12:20:14 +02:00
234d35f592 Fix alpine docker image to version 3.14 2021-08-30 11:38:12 +02:00
352a72a5d7 Update x/sys to support go 1.17 2021-08-25 21:00:11 +02:00
4d1ce986a6 Bumps alpine docker images to v1.14.1 2021-08-25 11:14:10 +02:00
531a8ff248 Prepare release v2.5.1 2021-08-20 18:27:12 +02:00
2644c1f598 Makes ALPN protocols configurable 2021-08-20 18:20:06 +02:00
fa53f7ec85 Conditional CloseNotify in header middleware 2021-08-19 18:02:07 +02:00
e05574af58 Adds MiddlewareTCP CRD documentation 2021-08-19 17:00:14 +02:00
fcfc976b13 Adds ContentType to middleware's overview table 2021-08-19 15:00:11 +02:00
78180a5fa7 Merge current v2.4 into v2.5 2021-08-19 11:45:19 +02:00
3445abe7ac Fix Kubernetes Gateway API documentation links 2021-08-19 11:18:11 +02:00
e0b442a48b Prepare release v2.5.0 2021-08-17 18:04:05 +02:00
bd1c84755b Update Go version to v1.17 2021-08-17 17:20:12 +02:00
a7194e96e0 Fix dashboard title for TCP middlewares 2021-08-17 15:02:15 +02:00
2bd60f9e60 Merge current v2.4 into v2.5 2021-08-17 10:05:22 +02:00
35a40c8727 Prepare release v2.4.14 2021-08-16 17:26:14 +02:00
7f62667569 Update mkdocs dependency version 2021-08-16 12:32:07 +02:00
fd4ba585ee fix: an example code error in doc 2021-08-16 10:08:08 +02:00
mpl
81eb46e36d Prepare release v2.5.0-rc6 2021-08-13 18:04:15 +02:00
mpl
b7700e77bf Update Go version 2021-08-13 17:42:09 +02:00
e73dd31619 redirect: fix comparison when explicit port request and implicit redirect port
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2021-08-11 17:10:12 +02:00
187ec26d8e Merge current v2.4 into v2.5 2021-08-05 18:09:23 +02:00
ef9b79f85c Remove unwanted trailing slash in key
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2021-08-05 18:02:12 +02:00
32d88a977d Avoid unauthorized midlleware cross namespace reference
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2021-08-05 17:42:08 +02:00
547c380961 fix: change machine type for release 2021-08-05 10:08:06 +02:00
848e23b489 fix: decrease semaphoreci machine type 2021-08-03 20:15:21 +02:00
d63cb1b4d6 Prepare release v2.5.0-rc5 2021-08-03 19:58:08 +02:00
c45de0d8bc fix: increase semaphoreci machine type 2021-08-03 19:45:33 +02:00
5c18967f06 Prepare release v2.5.0-rc4 2021-08-03 18:42:11 +02:00
e78f172f02 Merge current v2.4 into v2.5 2021-08-03 17:04:58 +02:00
mpl
4fc077a5d2 Prepare release v2.4.13 2021-07-30 16:50:07 +02:00
7f307d60c4 Kubernetes: detect changes for resources other than endpoints 2021-07-30 15:08:10 +02:00
b386964abc fix: remove hop-by-hop headers define in connection header beore some middleware
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2021-07-30 12:20:07 +02:00
817ac8f256 Add organizationalUnit to passtlscert middleware 2021-07-28 17:42:09 +02:00
c76d58d532 Merge current v2.5 into master 2021-07-28 15:21:46 +02:00
4b456f3b76 Merge current v2.4 into v2.5 2021-07-28 14:40:49 +02:00
319e3065f0 fix: upgrade k3s version 2021-07-28 14:28:11 +02:00
a48a8a97a1 fix: restore cache only once 2021-07-27 19:16:06 +02:00
8be434aaad Prepare release v2.4.12 2021-07-26 18:08:09 +02:00
mpl
d9fc775084 ratelimiter: use correct ttlSeconds value, and always call Set
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
Co-authored-by: Daniel Tomcej <daniel.tomcej@gmail.com>
2021-07-26 17:20:27 +02:00
f25139424a Merge remote-tracking branch 'origin/v2.5' into merge-back-v2.5-into-master 2021-07-23 13:14:26 +02:00
2d95c37ea4 Merge current v2.4 into v2.5 2021-07-23 11:26:15 +02:00
e12630ef06 feat: Add new CI system 2021-07-23 11:00:07 +02:00
48bd279311 Prepare release v2.5.0-rc3 2021-07-20 16:26:08 +02:00
36ffdf548d Merge v2.5 into master 2021-07-20 15:38:53 +02:00
a5b169c563 Merge current v2.4 into v2.5 2021-07-20 14:06:13 +02:00
bc5e621683 Get Kubernetes server version early 2021-07-20 13:02:10 +02:00
1e69939532 Update yaegi to v0.9.21 2021-07-20 11:58:06 +02:00
d8156ef625 Fix dashboard to display middleware details 2021-07-20 10:36:06 +02:00
c2c4dc9b58 Don't remove ingress config on API call failure 2021-07-19 20:06:07 +02:00
ffd4e207a4 Downgrade yaegi to v0.9.19 2021-07-19 18:54:04 +02:00
bd3271aff0 Merge current v2.4 into v2.5 2021-07-19 15:18:38 +02:00
0664f5a9ca Fix KV reference documentation 2021-07-19 14:54:14 +02:00
c515ace328 Library change for compress middleware to increase performance 2021-07-19 10:22:14 +02:00
8d4620dc53 check if defaultcertificate is defined in store 2021-07-19 09:58:14 +02:00
16f65f669b Update Gateway API version to v0.3.0
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
2021-07-15 17:20:08 +02:00
2a2f7f783f Prepare release v2.4.11 2021-07-15 16:48:11 +02:00
6ae50389e6 Update code generator for plugin's dyn conf 2021-07-15 15:58:08 +02:00
87fd51d7ec Fix migration guide 2021-07-15 14:40:13 +02:00
7e43e5615e Add Support for Consul Connect
Co-authored-by: Florian Apolloner <apollo13@users.noreply.github.com>
2021-07-15 14:02:11 +02:00
985f8778e9 fix doc verify script (#8266) 2021-07-15 00:09:51 +02:00
3a180e2afc Merge current v2.4 into v2.5 2021-07-13 18:12:29 +02:00
2f47bb0df6 Prepare release v2.4.10 2021-07-13 16:54:08 +02:00
7e0f0d9d11 Ignore http 1.0 request host missing errors 2021-07-13 15:30:20 +02:00
e1f5866989 Detect certificates content modifications
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2021-07-13 14:14:35 +02:00
3c1ed0d9b2 Disable ExternalName Services by default on Kubernetes providers 2021-07-13 12:54:09 +02:00
10ab39c33b Add *headers.responseModifier CloseNotify() 2021-07-13 12:28:07 +02:00
3072354ca5 Disable Cross-Namespace by default for IngressRoute provider 2021-07-13 10:48:05 +02:00
14499cd6e5 Fix: Add dedicated integration tests targets for CI 2021-07-12 18:32:10 +02:00
5d3dc3348e accesslog: multiple times the same header name. 2021-07-09 14:22:13 +02:00
ca2ff214c4 Merge current v2.5 into master 2021-06-30 11:56:49 +02:00
f8db285d5d Update generated and reference doc for plugins
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2021-06-29 17:02:13 +02:00
1f880662d6 Prepare release v2.5.0-rc2 2021-06-28 20:43:21 +02:00
febab86682 chore: increase goreleaser timeout. 2021-06-28 20:41:51 +02:00
8070dfef45 Prepare release v2.5.0-rc1 2021-06-28 18:00:12 +02:00
fc69f882c5 Merge current v2.4 into master 2021-06-28 10:07:17 +02:00
mpl
838a8e18d3 healthcheck: add support at the load-balancers of services level
Co-authored-by: Dmitry Sharshakov <d3dx12.xx@gmail.com>
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
2021-06-25 21:08:11 +02:00
5e3e47b484 Local private plugins.
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2021-06-25 15:50:09 +02:00
6d8512bda0 Add the list of available provider names 2021-06-24 18:34:05 +02:00
cd68cbd3ea Fix: malformed Kubernetes resource names and references in tests 2021-06-24 17:32:07 +02:00
55845c95bb docs: fix invalid subdomain 2021-06-24 11:28:05 +02:00
a243ac4dde Merge current v2.4 into master 2021-06-24 08:53:12 +02:00
a01cbb42c7 Convert issue templates to issue forms. 2021-06-24 08:52:13 +02:00
b5da5760a2 Typos in contributing section 2021-06-23 05:28:09 +02:00
c190b160e9 fix maintainers-guidelines page title 2021-06-23 00:40:10 +02:00
ce2e02b690 Merge current v2.4 into master 2021-06-22 14:44:56 +02:00
5dab09c42b Remove microbadger (Shutdown) 2021-06-22 10:00:11 +02:00
03b08d67f0 chore: upgrade linter 2021-06-22 00:08:06 +02:00
5841c9a7a5 Prepare release v2.4.9 2021-06-21 17:00:09 +02:00
ed9b1bea3f Use github action to check and verify doc 2021-06-21 16:04:13 +02:00
dca348359b add permissionsPolicy and deprecate featurePolicy 2021-06-21 15:16:13 +02:00
cf0759a48f Update documentation references 2021-06-21 11:54:08 +02:00
c9df233d24 Changing default file format for the snippets from TOML to YAML 2021-06-19 00:08:08 +02:00
99a23b0414 Use a dynamic buffer to handle client Hello SNI detection 2021-06-18 19:24:17 +02:00
95e0633b2f Create buffered signals channel 2021-06-18 18:43:10 +02:00
5ca210fa60 gateway-api: fix the "values" field in the example of httproute 2021-06-18 18:14:07 +02:00
2ccdc419d0 Override jaeger configuration with env variables 2021-06-18 18:10:05 +02:00
9af0e705a5 Update Elastic APM from 1.7.0 to 1.11.0 2021-06-17 09:52:05 +02:00
0a3e40332a Improve CA certificate loading from kubernetes secret 2021-06-14 18:06:10 +02:00
a758d18e51 Fixed BIND_DIR quoting 2021-06-14 16:26:07 +02:00
f15d05b22f tls Manager: do not build a default certificate for ACME challenges store
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2021-06-14 10:06:05 +02:00
fc9f41b955 Add TCP Middlewares support 2021-06-11 15:30:05 +02:00
fd1eae4f07 Adding formatting to the document. 2021-06-11 12:28:11 +02:00
51ee77b96f Explains Traefik HTTP response status codes
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
2021-06-11 10:00:14 +02:00
b03c5ff5ce Update go-acme/lego to v4.4.0 2021-06-08 23:50:05 +02:00
521fed1fea Elaborate on possible use of status codes with the errors middleware 2021-06-08 19:02:05 +02:00
679def0151 Add routing IP rule matcher
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2021-06-07 18:14:09 +02:00
mpl
2560626419 doc: clarify usage for ratelimit's excludedIPs 2021-06-07 17:46:14 +02:00
e5024d5d0a Upgrade Node version to LTS on webui folder 2021-06-03 12:00:09 +02:00
c10c7619d3 Adding Maintainers Guidelines 2021-06-02 18:02:06 +02:00
dd04c432e9 Support not in rules definition 2021-05-31 18:58:05 +02:00
b1fd3b8fc7 fix for review 2021-05-28 17:38:46 +02:00
456df0fc19 feat: Add ServersTransport annotation to k8s ingress provider 2021-05-28 17:38:46 +02:00
526f493e12 Removes headers middleware options 2021-05-28 09:24:14 +02:00
5632ee6378 Deprecates ssl redirect headers middleware options 2021-05-28 08:50:09 +02:00
1680f00091 Fix incorrect behaviour with multi-port endpoint subsets 2021-05-28 00:58:07 +02:00
376b6f90d9 docs: add pilot dashboard flag to static configuration file reference 2021-05-27 12:16:08 +02:00
21c0195d29 fix: ACME preferred chain. 2021-05-20 15:08:12 +02:00
56f845c71a gatewayapi: adding support for TCPRoute and TLSRoute
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
2021-05-20 11:50:12 +02:00
d6d639d4d7 docs: add examples for removing headers 2021-05-17 18:07:25 +02:00
e1e1fd640c Upgrade IngressClass to use v1 over v1Beta on Kube 1.19+ 2021-05-17 16:50:09 +02:00
2408eeceba Fix plugin unzip call on windows 2021-05-17 12:10:09 +02:00
6ae194934d fix: use defaultEntryPoints when no entryPoint is defined in a TCPRouter 2021-05-11 16:46:14 +02:00
63ef0f1cee Add plugin's support for provider
Co-authored-by: Julien Salleyron <julien@traefik.io>
2021-05-11 16:14:10 +02:00
de2437cfec kubernetes: remove logging of changed object with cast 2021-05-10 09:42:06 +02:00
32e08f3510 Add k8s provider option to create services without endpoints 2021-05-06 18:12:10 +02:00
40f21f41e1 Fix ingressRouteTCP external name service examples in documentation 2021-05-06 12:04:08 +02:00
ee12424795 Bump paerser to v0.1.4 2021-05-06 09:32:04 +02:00
0b48d5d0d2 Fix: regenerate crd 2021-05-05 17:50:04 +02:00
080cf98e51 Add router metrics 2021-04-30 10:22:04 +02:00
dc8d5ef744 Add a mechanism to format the sticky cookie value
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
2021-04-29 17:56:03 +02:00
70a02158e5 Add wildcard hostname rule to kubernetes gateway 2021-04-29 17:18:04 +02:00
ab71dad51a [kubernetes] ignore empty endpoint changes 2021-04-29 16:20:03 +02:00
0624cefc10 Merge branch 'master' into mrg-current-v2.4 2021-04-29 14:24:07 +02:00
56b26421a5 fix: remove linode link health check 2021-04-29 12:22:03 +02:00
ea8ba87aeb doc: fix a syntax error in ratelimit TOML configuration sample 2021-04-27 20:26:04 +02:00
08b258a2cb Update Yaegi to v0.9.17 2021-04-27 20:16:04 +02:00
ac486d3d1d Merge current branch v2.4 into master 2021-04-21 11:39:53 +02:00
e096bf6b62 fix: k8s gateway api link
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
2021-04-21 10:28:03 +02:00
e28b33b53b Upgrade github.com/lucas-clemente/quic-go 2021-04-18 00:38:03 +02:00
5814ba5322 Kubernetes ingress provider to search via all endpoints 2021-04-15 18:16:04 +02:00
be81ce244e Error span on 5xx only 2021-04-14 12:20:03 +02:00
d3a3aeb0fc Merge current branch v2.4 into master 2021-04-14 09:51:12 +02:00
fe6acdf4d2 Fix Kubernetes Gateway API documentation links 2021-04-13 18:26:03 +02:00
702e0a461a Merge current branch v2.4 into master 2021-04-13 14:17:39 +02:00
46d6da4fce Docs: installing deps for html-proofer
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
2021-04-13 14:02:04 +02:00
aa61835b78 correct annotation option 2021-04-06 17:18:03 +02:00
mpl
2a1e46c8b6 doc: typo fix 2021-04-01 12:05:03 +02:00
cb4fb973b2 Merge current branch v2.4 into master 2021-03-31 09:43:04 +02:00
513f6e9a68 Remove error when HTTProutes is empty
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
2021-03-30 16:32:03 +02:00
ad980334d1 doc: remove dead page. 2021-03-30 14:51:30 +02:00
d13d078351 Add ability to disable HTTP/2 in dynamic config 2021-03-29 14:32:03 +02:00
947798b44c Fix ServersTransport documentation 2021-03-29 14:18:03 +02:00
ed427616d4 chore: update linter 2021-03-29 09:20:03 +02:00
297921182c Add metrics documentation
Co-authored-by: Tom Moulard <tom.moulard@traefik.io>
2021-03-25 16:52:04 +01:00
31a5f3591f Allow to define datadogs metrics endpoint with env vars 2021-03-23 17:48:04 +01:00
32655b5b16 Prepare release v2.4.8 2021-03-23 16:34:04 +01:00
HMH
8947f85ddd Improve host name resolution for TCP proxy 2021-03-23 11:24:03 +01:00
a513a05b7a Raise errors for non-ASCII domain names in a router's rules 2021-03-22 21:16:04 +01:00
1e716a93ff Adding an option to (de)activate Pilot integration into the Traefik dashboard
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
2021-03-22 19:18:04 +01:00
06fc2c505f Doc: improve basic auth middleware httpasswd example 2021-03-22 15:26:03 +01:00
6fcea91d1f Add missing traefik. prefix across sample config 2021-03-19 09:12:04 +01:00
93d099a2f0 Fix travis docker image pulling for docs 2021-03-16 12:08:04 +01:00
29908098e4 Upgrade Ingress Handling to work with networkingv1/Ingress 2021-03-15 11:16:04 +01:00
e5983d96f7 updating docs to remove a no longer needed note 2021-03-15 10:46:03 +01:00
08e6ae07af Update to gateway-api v0.2.0
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2021-03-15 09:44:03 +01:00
49b46a9a3f server: updating go-proxyproto with security bugfix from upstream 2021-03-15 09:16:03 +01:00
36c316f39c Update go-acme/lego to v4.3.1 2021-03-12 14:38:07 +01:00
7e76abc067 Update go-acme/lego to v4.3.0 2021-03-11 09:52:04 +01:00
702e301990 Merge current branch v2.4 into master 2021-03-09 12:05:08 +01:00
b1e11f3e88 Prepare release v2.4.7 2021-03-08 18:04:03 +01:00
09d5f59701 fix: double close chan on TLS challenge
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2021-03-08 11:18:04 +01:00
3c8675bb8b Fix flaky tests.
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2021-03-08 09:58:04 +01:00
71ca237478 Add new GitHub issue chooser. 2021-03-08 09:40:04 +01:00
0e4b6d36fd Use Docker dependency directly without replace directive 2021-03-07 22:26:03 +01:00
e898080460 feature: tune transport buffer size to increase performance 2021-03-05 14:30:04 +01:00
bdba7d3adf Update to go1.16 2021-03-04 20:08:03 +01:00
606b43dc51 Clarify doc for ingressclass name in k8s 1.18+ 2021-03-04 09:24:03 +01:00
2e7833df49 chore: update linter. 2021-03-04 09:02:03 +01:00
ec0d03658d Fix ServersTransport documentation
Co-authored-by: mpl <mathieu.lonjaret@gmail.com>
2021-03-03 16:48:04 +01:00
992d4c1b94 Upgrade the CRD version from apiextensions.k8s.io/v1beta1 to apiextensions.k8s.io/v1
Co-authored-by: kevinpollet <pollet.kevin@gmail.com>
2021-03-03 15:32:04 +01:00
d2d7cf14e5 Bump paerser to v0.1.2 2021-03-03 12:46:03 +01:00
e658712d53 Filter ingress class resources by name
Co-authored-by: SantoDE <manuel.zapf@traefik.io>
2021-03-02 21:34:03 +01:00
40cd6ada4f Prepare release v2.4.6 2021-03-01 19:14:03 +01:00
c843c182e4 Address all shellcheck warnings 2021-02-26 14:34:04 +01:00
c35a8bdb15 Fixing doc for default value of checknewversion 2021-02-26 10:20:03 +01:00
dd0701dd16 fix: wait for file and internal before applying configurations
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2021-02-25 17:20:04 +01:00
32500773b8 Update Yaegi to v0.9.13 2021-02-24 17:06:03 +01:00
e7d3f4316f Fix typo in routing/services/index.md 2021-02-22 20:28:05 +01:00
438eec720a Merge v2.4 into master 2021-02-22 09:40:24 +01:00
4b38d7368f Fix reflink typo in file provider documentation 2021-02-19 18:48:03 +01:00
dce6a86900 Fix Kubernetes Gateway API documentation links 2021-02-19 17:16:03 +01:00
dc9c558c06 Prepare release v2.4.5 2021-02-18 18:04:03 +01:00
b8a466c571 Prepare release v2.4.4 2021-02-18 15:28:03 +01:00
bae28c5f57 Only allow iframes to be loaded from our domain 2021-02-18 14:54:03 +01:00
1b21f0723f Merge v2.4 into master 2021-02-16 11:12:09 +01:00
911c439858 Prepare release v2.4.3 2021-02-15 16:52:03 +01:00
f81f85cea2 Add missing doc about servers transport. 2021-02-15 12:04:04 +01:00
1325cc5cd0 Add seo support 2021-02-12 19:08:04 +01:00
951d61bfcd Apply content type exclusion on response
Co-authored-by: kevinpollet <pollet.kevin@gmail.com>
2021-02-12 12:12:03 +01:00
0937cba870 Provider documentation fixes 2021-02-11 19:04:03 +01:00
5597d7633d Fix TLS challenge timeout and validation error
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2021-02-11 16:32:03 +01:00
502c88ee3f Middleware documentation fixes 2021-02-11 14:34:04 +01:00
5ef6297daa Fixed typo in consul catalog tests. 2021-02-10 14:48:03 +01:00
9e33e23b8b Add HEAD as available option for Method 2021-02-04 17:04:04 +01:00
16d00ccffb Fix the static reference documentation for the internal redirection router. 2021-02-04 11:44:03 +01:00
d211437d6c Merge v2.4 into master 2021-02-04 10:40:53 +01:00
7996a42f76 Allow crossprovider service reference
Co-authored-by: Harold Ozouf <harold.ozouf@gmail.com>
2021-02-02 19:36:04 +01:00
f482e5e84a Prepare release v2.4.2 2021-02-02 18:06:04 +01:00
447c3567b4 Fix the redirect entrypoint default priority 2021-02-02 17:42:04 +01:00
3c5e6fe7f8 Fix the static configuration generation for environment variables 2021-02-02 17:10:03 +01:00
bf4a578bbb fix: infinite loop in forwarded header middleware.
Co-authored-by: kevinpollet <pollet.kevin@gmail.com>
2021-02-02 11:40:04 +01:00
4cabea069d Prepare Release v2.4.1 2021-02-01 17:14:04 +01:00
c53033a778 Fix aggregator test comment 2021-02-01 16:50:03 +01:00
ea8642e2a1 fix: reduce pressure of pilot services when errors occurs 2021-02-01 14:42:04 +01:00
73cea2d303 Fix missing serverstransport documentation 2021-02-01 13:58:03 +01:00
96a3468791 Fix servers transport not found 2021-02-01 12:36:03 +01:00
2065f4c003 Fix HTTP challenge router unexpected delayed creation 2021-01-28 16:16:05 +01:00
9a931e4dc9 fix: add support for multiple ingress classes 2021-01-28 15:08:04 +01:00
49ec62c757 Fix refresh interval option description in consulcatalog provider 2021-01-28 11:10:04 +01:00
a371f971fb chore: update linter. 2021-01-28 09:00:03 +01:00
5f9a84fc8b Fix typo in server transports documentation 2021-01-26 09:20:04 +01:00
2461e36ed4 Merge branch v2.4 into master 2021-01-25 12:42:23 +01:00
1305bf49a5 Fix plugin type on middleware endpoint response 2021-01-25 11:08:04 +01:00
da0a16e122 Update go-acme/lego to v4.2.0 2021-01-25 09:28:04 +01:00
fb10687168 fix: YAML syntax in providers docs 2021-01-22 09:02:04 +01:00
f0d78471af Forward Proxy-Authorization header to authentication server 2021-01-21 18:34:04 +01:00
a90b2a672e perf: improve forwarded header and recovery middlewares
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2021-01-21 10:04:04 +01:00
2bbb6fc427 Update sprig to v3.2.0 2021-01-20 15:10:04 +01:00
2747e240c1 Merge branch v2.4 into master 2021-01-20 10:50:21 +01:00
4b370930b5 Mutualize TLS version and cipher code 2021-01-20 04:08:03 +01:00
c74918321d Prepare release v2.4.0 2021-01-19 16:50:04 +01:00
b05a5c818d Add TLS version and cipher to the accessLog 2021-01-19 09:52:06 +01:00
41d22ef17e Improve kubernetes external name service support for UDP 2021-01-19 09:30:05 +01:00
bbee63fcf3 Add named port support to Kubernetes IngressRoute CRDs 2021-01-15 15:54:04 +01:00
b1ddd0e038 Merge branch v2.4 into master 2021-01-15 14:21:59 +01:00
8c5dc3b5cb Merge branch v2.3 into v2.4 2021-01-15 13:55:30 +01:00
afa05329d9 fix: structor latest tag. 2021-01-15 13:21:43 +01:00
dbbff393e1 Use GitHub Action to publish documentation. 2021-01-15 13:06:04 +01:00
f742671bbe Merge branch v2.4 into master 2021-01-14 18:29:48 +01:00
0dae829080 Merge branch v2.3 into v2.4 2021-01-14 17:56:52 +01:00
e62a00a3f5 Update copyright year for 2021 2021-01-13 16:50:03 +01:00
ab4c93dd2f New Traefik Labs doc theme 2021-01-13 11:54:04 +01:00
ed5321999c Merge branch v2.4 into master 2021-01-13 09:21:20 +01:00
fb21e3bb5c Prepare release v2.4.0-rc2 2021-01-12 16:30:04 +01:00
3595292f7f Merge branch v2.3 into v2.4 2021-01-12 09:21:00 +01:00
47fb6e036a Prepare release v2.3.7 2021-01-11 18:48:03 +01:00
92886c46ea Merge branch v2.3 into v2.4 2021-01-11 16:26:53 +01:00
83fa3f4cc8 Discrepancy in Traefik log levels 2021-01-11 15:42:04 +01:00
c24f75ce0b Update copyright year for 2021 2021-01-08 19:20:04 +01:00
63929b0341 Compile kubernetes ingress annotation regex only once 2021-01-07 18:56:03 +01:00
fc7ec17905 Feature: add udp timeout configuration 2021-01-07 17:16:03 +01:00
e5a01c7cc8 Add HTTP3 support (experimental)
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2021-01-07 14:48:04 +01:00
0509b6fdb9 Merge branch v2.4 into master 2021-01-06 18:59:45 +01:00
60d87f3c64 Merge back v2.3 into v2.4 2021-01-06 17:59:03 +01:00
5d800ba5fe Do a Docker login on Travis 2021-01-06 17:58:04 +01:00
759d17547a Use Datadog tracer environment variables to setup default config 2021-01-06 17:08:03 +01:00
d4f0a9ff62 Fix wildcard hostname issue 2021-01-05 12:26:04 +01:00
c4fa96c41e Add ECS to supported providers list 2021-01-04 10:58:03 +01:00
f54136b602 chore: update linter. 2020-12-29 10:54:03 +01:00
5dd1728bf8 webui: fix missing custom request and response header names 2020-12-27 20:48:04 +01:00
da1c9f48b7 docs: rephrase forwardauth.authRequestHeaders 2020-12-22 15:36:03 +01:00
0ec0e37532 Merge branch v2.3 into v2.4 2020-12-22 14:23:56 +01:00
544dc2eaa5 docs: fix broken links to docker-compose documentation 2020-12-22 14:20:03 +01:00
a3327c4430 Add TLS certs expiration metric 2020-12-18 18:44:03 +01:00
f8ae972e70 Merge branch v2.3 into v2.4 2020-12-18 10:15:01 +01:00
3ff83fc1f8 Prepare release v2.3.6 2020-12-17 17:02:04 +01:00
63f65e5b2a Disable router when a rule has an error 2020-12-17 10:06:03 +01:00
3140a4e0cd Prepare release v2.4.0-rc1 2020-12-16 16:42:04 +01:00
31038e0e12 Merge branch v2.3 into master 2020-12-16 15:22:34 +01:00
ac8e47579b Add missing quotes in errorpages k8s example yaml 2020-12-16 15:20:04 +01:00
ec0075e0d0 Extend marathon port discovery to allow port names as identifier 2020-12-16 12:32:03 +01:00
7900d266b1 Add jspdown to maintainers 2020-12-15 17:40:03 +01:00
c21597c593 Add Kubernetes Gateway Provider
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
2020-12-15 16:40:05 +01:00
ea418aa7d8 Merge branch v2.3 into master 2020-12-15 15:28:00 +01:00
5487015a83 Update Logrus to v1.7.0 2020-12-14 12:56:03 +01:00
418cccd307 Add configuration example for access log filePath 2020-12-14 12:34:05 +01:00
2a0760412c Update Yaegi to v0.9.8 2020-12-14 12:00:04 +01:00
eebbe64b36 Merge branch v2.3 into master 2020-12-11 10:58:00 +01:00
42d8e6d60d Prepare release v2.3.5 2020-12-10 16:48:04 +01:00
7ba907f261 IngressRoute: add an option to disable cross-namespace routing
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
2020-12-10 14:58:04 +01:00
c72769e2ea Fix TLS options fallback when domain and options are the same
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2020-12-09 14:16:03 +01:00
02d856b8a5 Documentation: Add spacing to sidebars so the last item is always visible 2020-12-07 18:24:04 +01:00
0d15ac8861 Fix UI bug on long service name 2020-12-07 14:14:03 +01:00
134a767a7f Update go-acme/lego to v4.1.3 2020-12-04 23:40:03 +01:00
7403b6fb82 Fix concatenation of IPv6 addresses and ports 2020-12-04 20:56:04 +01:00
64a65cadf3 Send anonymized dynamic configuration to Pilot
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2020-12-03 15:52:05 +01:00
121eaced49 Add example for multiple service per container 2020-12-03 09:36:03 +01:00
a488430f23 acme: add external account binding support. 2020-12-01 10:40:05 +01:00
b5db753e11 Improve setup readability.
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2020-12-01 10:04:04 +01:00
b0aa27db31 Display Proxy Protocol version for backend services in web dashboard. 2020-11-30 17:04:03 +01:00
512ed086bd Fix typos in migration guide 2020-11-27 11:18:04 +01:00
76e35a09b7 Prepare release v2.3.4 2020-11-24 17:06:04 +01:00
d2c1d39d42 Fix clusters option in ECS provider documentation 2020-11-24 14:50:03 +01:00
e9cccf6504 Do not evaluate templated URL in redirectRegex middleware 2020-11-24 14:16:03 +01:00
1c505903ff fix: invalid slice parsing. 2020-11-24 09:40:03 +01:00
53ed8e04ae Update go-acme/lego to v4.1.2 2020-11-23 12:00:03 +01:00
2112de6f15 Merge branch v2.3 into master 2020-11-20 11:30:07 +01:00
be0845af02 Apply labelSelector as a TweakListOptions for Kubernetes informers 2020-11-20 00:18:04 +01:00
f83a57b3da Prepare release v2.3.3 2020-11-19 18:31:09 +01:00
08264749f0 Update Yaegi to v0.9.7 2020-11-19 17:56:03 +01:00
a75819cae3 Filter out Helm secrets from informer caches
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2020-11-19 14:32:03 +01:00
9fb32a47ca Fix grammar in kubernetes ingress controller documentation 2020-11-19 10:04:04 +01:00
4f43c9ebb4 Fix missing allow-empty tag on ECS and Consul Catalog providers
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2020-11-19 00:12:03 +01:00
9177982334 Fix consul catalog panic when health and services are not in sync
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2020-11-17 17:30:03 +01:00
84b125bdde added support for tcp proxyProtocol v1&v2 to backend 2020-11-17 13:04:04 +01:00
52eeff9f9f fix: consulcatalog to update before the first interval 2020-11-16 20:44:04 +01:00
0fcccd35ff /bin/bash replaced with /usr/bin/env bash to match other scripts 2020-11-16 15:38:04 +01:00
598dcf6b62 Improve service name lookup on TCP routers 2020-11-13 12:48:04 +01:00
459200dd01 Forwardauth headers 2020-11-10 17:50:04 +01:00
af22cabc6f Fix docs for TLS 2020-11-10 17:28:04 +01:00
920e82f11a fix: translate configured server port into correct mapped host port 2020-11-09 17:12:05 +01:00
520fcf82ae Merge branch v2.3 into master. 2020-11-09 00:07:28 +01:00
9bdf9e1e02 Update Yaegi to v0.9.5 2020-11-08 23:42:03 +01:00
3a45f05e36 Update go-acme/lego to v4.1.0 2020-11-08 23:24:04 +01:00
8e3e387be7 Fix Traefik Proxy product nav in docs 2020-11-06 21:56:03 +01:00
267d0b7b5a chore: update linter. 2020-11-06 09:26:03 +01:00
74d1d55051 Feature: Exponential Backoff in Retry Middleware 2020-11-05 16:14:04 +01:00
3a8cb3f010 Add AccessControlAllowOriginListRegex field to deepcopy 2020-11-05 11:24:03 +01:00
f5b290b093 Add ECS menu to dynamic config reference 2020-11-03 17:40:04 +01:00
d38d11f02e Set kubernetes client User-Agent to something meaningful 2020-10-30 17:56:03 +01:00
af04e92cf2 Enable stats collection when pilot is enabled 2020-10-30 16:54:04 +01:00
4ea1c98ac9 Improve anonymize configuration 2020-10-30 12:44:05 +01:00
05333b9579 acme: new HTTP and TLS challenges implementations. 2020-10-29 15:40:04 +01:00
49cdb67ddc Middlewares: add forwardAuth.authResponseHeadersRegex 2020-10-29 15:10:04 +01:00
b5198e63c4 Allow to use regular expressions for AccessControlAllowOriginList 2020-10-29 10:52:03 +01:00
db007efe00 Ignore errors when setting keepalive period is not supported by the system 2020-10-28 15:32:04 +01:00
699cf71652 Merge branch v2.3 into master 2020-10-27 18:39:03 +01:00
a0c02f62a3 fix: exclude protected link from doc verify 2020-10-27 18:34:04 +01:00
ff7b814edc fix documentation 2020-10-27 12:46:04 +01:00
015f24a901 Propose kevinpollet to Maintainers 2020-10-26 17:18:04 +01:00
4fccde84bd Merge current v2.3 branch into master 2020-10-23 14:29:22 +02:00
ea459e9af0 fix: update Yaegi to v0.9.4 2020-10-23 11:30:04 +02:00
2dd5a53db2 Add missed tls config for yaml example 2020-10-23 11:00:05 +02:00
fc97ea7ee0 Use timezone without daylight saving time for logger formatter tests
Co-authored-by: jbdoumenjou <925513+jbdoumenjou@users.noreply.github.com>
2020-10-22 19:52:04 +02:00
582d2540af add links to contributors guide 2020-10-22 12:08:05 +02:00
6ad79dcd45 Clarify time-based field units 2020-10-22 11:36:03 +02:00
721896ba70 Resolve broken URLs causing make docs to fail 2020-10-20 23:02:04 +02:00
228270414c fix typo in providers overview documentation 2020-10-20 19:02:04 +02:00
2683df7b5b Fix ingress documentation 2020-10-20 14:16:04 +02:00
3e61d1f233 Prepare release v2.3.2 2020-10-19 20:22:04 +02:00
04c07227f2 fix: Consul Catalog address documentation. 2020-10-19 10:28:03 +02:00
2e8d99c5b8 Revise Traefik Pilot documentation section 2020-10-16 11:20:05 +02:00
c07301473b fix: update Yaegi to v0.9.4 2020-10-16 11:02:03 +02:00
b1ba42410b Moving Provider Namespace documentation topic to Configuration Discovery section 2020-10-15 14:54:04 +02:00
b80f89e3db Adding details about the default TLS options to the documentation 2020-10-15 14:12:04 +02:00
edb15a9346 fix: kv doc reference 2020-10-13 16:34:04 +02:00
714a4d4f2d Merge branch v2.3 into master 2020-10-09 12:41:38 +02:00
5c853766e8 fix: flaky integration tests 2020-10-09 09:32:03 +02:00
3567ae88ad Bump k8s client to v0.19.2 2020-10-08 17:12:04 +02:00
afcec56be4 Merge 'v2.3' into master. 2020-10-08 14:05:10 +02:00
d2435cf43b fix: restrict protocol for TLS Challenge. 2020-10-08 13:34:04 +02:00
556f7608db fix: use provider keytype instead of account keytype. 2020-10-08 12:58:04 +02:00
a4df4b028e fix: pilot static configuration documentation 2020-10-08 11:36:03 +02:00
63683d35fc doc: add YAML sample. 2020-10-08 10:38:05 +02:00
495344591f fix: versions in the PR template. 2020-10-08 00:48:03 +02:00
4e508499da Fix containous links in readme 2020-10-07 18:02:04 +02:00
326be29568 Filter ForwardAuth request headers 2020-10-07 16:36:04 +02:00
e4a3df3516 Fix broken logo 2020-10-07 10:46:04 +02:00
3506cbd5e9 fix: udp json struct tag 2020-10-02 17:38:04 +02:00
ab13019bde acme: Fix race condition in LocalStore during saving. 2020-09-30 12:04:04 +02:00
ddc663eac0 Prepare release v2.3.1 2020-09-29 17:36:04 +02:00
fc7002fbab Fix blank webui on some browsers 2020-09-28 12:14:04 +02:00
f2e53a3569 Re-add server up metrics 2020-09-26 13:30:03 +02:00
c5b4e589ff Update of the helm repo localisation 2020-09-25 12:18:04 +02:00
5e63ab619e Fix default value of docker client timeout 2020-09-25 09:14:04 +02:00
c9bbfa1272 chore: Added configuration files for generating the changelog of a release. 2020-09-25 01:32:03 +02:00
050968cbac Merge branch 'v2.3' into master. 2020-09-24 16:17:12 +02:00
8ca0d804d8 restore traefik logo 2020-09-24 16:02:03 +02:00
54e5a3607e Removes invalid items in the changelog. 2020-09-24 09:04:04 +02:00
cd947ae822 Merge branch 'v2.3' into master 2020-09-23 15:35:31 +02:00
2477e18c87 Prepare release v2.3.0 2020-09-23 12:44:04 +02:00
ef08e8b8a0 fix: precheck function. 2020-09-23 12:24:03 +02:00
f59bf16e82 Fix consul catalog router tag example 2020-09-23 11:56:03 +02:00
118c31eb8d Fix yaml documentation 2020-09-23 11:38:03 +02:00
476f16f0aa fix: remove old mixtus call. 2020-09-23 11:08:17 +02:00
b40d35b779 chore: apply new documentation style.
Co-authored-by: jbdoumenjou <jb.doumenjou@gmail.com>
2020-09-23 10:20:04 +02:00
8e016cf672 Prepare release v2.3.0-rc7 2020-09-18 17:20:03 +02:00
7e482e9f8b fix: pilot metrics unit for req duration. 2020-09-18 15:36:04 +02:00
6445befe87 fix: start of Traefik Pilot 2020-09-18 09:26:03 +02:00
86c099d629 Merge branch v2.3 into master 2020-09-17 12:32:18 +02:00
79af433381 Prepare release v2.3.0-rc6 2020-09-16 16:02:03 +02:00
c0f1e74bed chore: move to Traefik organization.
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2020-09-16 15:46:04 +02:00
9df89e66e3 Add the ingressclass resource in the ingress RBAC documentation 2020-09-15 18:34:04 +02:00
660375d6e4 fix: uint64 alignment in go-kit. 2020-09-15 18:22:04 +02:00
498e8545b6 feat: update more than one LoadBalancer ip
Co-authored-by: kevinpollet <pollet.kevin@gmail.com>
2020-09-15 13:48:32 +02:00
230c2e5cc2 chore: update linter. 2020-09-15 13:08:03 +02:00
3e60863e2d Moves pilot outside the experimental section. 2020-09-15 12:08:03 +02:00
4592626bbb Merge branch v2.2 into v2.3 2020-09-15 10:57:20 +02:00
b980c87eff Avoid Traefik Pilot iframe code in Traefik webui regarding notifications 2020-09-15 10:26:03 +02:00
0f7c322623 Improve documentation for usage of Kubernetes Ingress 2020-09-15 09:46:04 +02:00
76f42a3013 add ServersTransport on services 2020-09-11 15:40:03 +02:00
93b3d601d5 Fix typo when comparing exported data 2020-09-10 16:44:04 +02:00
56329e89bb Change wording 2020-09-08 17:52:03 +02:00
5c8b8149eb doc: fix typo in health check options 2020-09-08 10:54:04 +02:00
6075f7e8fd Merge branch v2.3 into master 2020-09-08 10:48:09 +02:00
ddf53494f0 fixed typo in buffering.md docs 2020-09-08 10:32:03 +02:00
cd1f03d4f4 Prepare release v2.3.0-rc5 2020-09-07 18:30:04 +02:00
8474a61f21 Merge branch v2.2 into v2.3 2020-09-07 16:30:17 +02:00
4ad0ab5433 Prepare release v2.2.11 2020-09-07 16:00:03 +02:00
66d151df77 Improve plugins builder. 2020-09-07 13:58:03 +02:00
2045b250fd Clarified hostname documentation for load balancer healthcheck 2020-09-07 10:30:04 +02:00
1dbee90d34 feat: allows to change the Pilot URL in the web UI in dev mode 2020-09-07 10:22:03 +02:00
eb7a6d925b fix: header middleware response writer. 2020-09-07 09:26:03 +02:00
3678bd5a93 Merge branch v2.2 into v2.3 2020-09-04 21:06:11 +02:00
2d1a973ee5 Prepare release v2.2.10 2020-09-04 17:40:03 +02:00
322f7b2ad4 Prepare release 2.2.9 2020-09-04 17:14:03 +02:00
41aa2672cd Update go-acme/lego to v4.0.1 2020-09-04 10:52:03 +02:00
f3090a452a doc: specify HostSNI rule removal only for HTTP routers 2020-09-02 17:16:04 +02:00
52790d3c37 Headers response modifier is directly applied by headers middleware
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2020-09-01 18:16:04 +02:00
3677252e17 Add missing IPStrategy struct tag for YAML 2020-09-01 17:34:04 +02:00
235d1d655d Add example for the IngressClass usage 2020-09-01 10:18:03 +02:00
29bd6faa18 Support configuring a HTTP client timeout in the Docker provider 2020-08-28 10:02:03 +02:00
69c0f38305 Merge branch v2.2 into v2.3 2020-08-27 12:54:50 +02:00
0399d0c4d6 Reorder migrations for v2 minor upgrades 2020-08-27 12:08:03 +02:00
3db47f0adc Fix & improve Grafana dashboards 2020-08-27 11:38:03 +02:00
483e2c43cf Merge branch v2.3 into master 2020-08-26 12:22:39 +02:00
3e3b7238e0 doc: Minor language improvement in TLS documentation 2020-08-25 17:10:04 +02:00
532b5865de doc: added tz section to access log 2020-08-25 14:38:04 +02:00
54b94f29e1 Add ability to dismiss pilot notification 2020-08-24 17:38:24 +02:00
b67a7215f6 chore: update linter. 2020-08-21 11:12:04 +02:00
e424cc7608 Prepare release v2.3.0-rc4 2020-08-19 17:46:05 +02:00
229008e76a docs: add missing apigroup to Kubernetes RBAC 2020-08-19 17:02:04 +02:00
584f4bc596 Update jaeger-client-go dependency to v2.25.0 2020-08-19 15:50:03 +02:00
1502d20def chore: move the parser to a dedicated package. 2020-08-17 18:04:03 +02:00
eecc2f4dd7 Update to go1.15 2020-08-17 12:02:03 +02:00
6fc110a71a doc: fix typo in migration guide 2020-08-15 16:04:03 +02:00
ca6b46533a Merge branch v2.2 into v2.3 2020-08-14 12:07:41 +02:00
a1fe29347a doc: fix dead link. 2020-08-14 11:36:05 +02:00
449afea4fc Allows multi-level KV prefixes 2020-08-11 17:42:05 +02:00
6e5dd35ee3 Merge branch v2.2 into v2.3 2020-08-11 17:21:44 +02:00
0d5d14d41a Pilot metrics provider
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2020-08-10 15:26:04 +02:00
3a42e457cf Add mixtus for documentation 2020-08-07 16:40:03 +02:00
5b05c990b0 Improve region resolution for ECS provider
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
2020-08-05 11:52:03 +02:00
9df0a6208b chore(webui): upgrade nodejs to Node current LTS 2020-08-03 18:18:03 +02:00
3214904cc7 kubernetes-crd: fix whitespace in configuration examples 2020-08-03 17:40:07 +02:00
ec775a016a doc: replace underscore by hyphen for k8s metadata names. 2020-08-03 17:30:04 +02:00
a2ca235fee Harmonize docs 2020-07-31 10:56:04 +02:00
de458b7357 doc: add security policies. 2020-07-29 12:42:03 +02:00
7c039ca223 Merge branch v2.3 into master. 2020-07-29 12:09:30 +02:00
3942962ef5 Prepare release v2.3.0-rc3 2020-07-28 19:16:04 +02:00
675655d437 Merge branch v2.2 into v2.3 2020-07-28 17:50:35 +02:00
dafb14ff37 Support Kubernetes Ingress pathType
Co-authored-by: jbdoumenjou <jb.doumenjou@gmail.com>
Co-authored-by: kevinpollet <pollet.kevin@gmail.com>
2020-07-28 17:50:04 +02:00
fc52d1cfba Prepare release v2.2.8 2020-07-28 17:34:03 +02:00
fdf2a68a11 doc: add name of used key for kubernetes client auth 2020-07-28 17:18:03 +02:00
3908ef611a Fix documenation for ECS 2020-07-28 10:44:05 +02:00
e63db782c1 fix: clean X-Forwarded-Prefix header for the dashboard. 2020-07-28 10:08:03 +02:00
a6c6127e33 spelling(docs/content/routing/providers/docker.md) 2020-07-28 01:02:03 +02:00
207d0bec78 Merge v2.2 into v2.3 2020-07-22 15:49:28 +02:00
1443c8d4c6 Add migration documentation for IngressClass 2020-07-21 18:06:04 +02:00
a136c46148 Use semantic versioning to enable ingress class support 2020-07-21 15:32:04 +02:00
bbbc18fd84 Prepare release 2.2.7 2020-07-20 18:48:04 +02:00
2c7f6e4def fix: drop host port to compare with SNI. 2020-07-20 18:32:03 +02:00
dcd0cda0c6 prefer NoError/Error over Nil/NotNil 2020-07-19 13:10:03 +02:00
ff16925f63 Prepare release v2.2.6 2020-07-17 17:54:04 +02:00
0b7aaa3643 Fix domain fronting
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2020-07-17 15:38:04 +02:00
44a244b1cb file parser: skip nil value. 2020-07-17 11:04:04 +02:00
1dc6f39b55 Update availability info 2020-07-17 10:08:03 +02:00
45f52ca29c fix: access logs header names filtering is case insensitive 2020-07-16 17:36:04 +02:00
fae2d93525 Get Entrypoints Port Address without protocol for redirect 2020-07-16 17:18:03 +02:00
25b74ce1f3 Add example for entrypoint on one ip address 2020-07-16 12:38:03 +02:00
4957e498af Prepare release v2.3.0-rc2 2020-07-15 22:00:19 +02:00
54ca1abd2b fix: goreleaser. 2020-07-15 21:58:16 +02:00
8f2951b275 Prepare release v2.3.0-rc1 2020-07-15 20:50:03 +02:00
720bef97e6 doc: add pilot and plugins documentation. 2020-07-15 20:14:04 +02:00
c42f1b7a50 feat: raw map parser. 2020-07-15 20:14:04 +02:00
0186c31d59 feat: plugins integration. 2020-07-15 20:14:04 +02:00
58bf1a2ca5 feat: Traefik Pilot WebUI 2020-07-15 20:14:04 +02:00
4a31544024 feat: Traefik Pilot integration.
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2020-07-15 20:14:04 +02:00
cb6ec507e2 Add new ingressClass support to ingress provider
* add new ingressClass

* add doc

* lint

* adjust behavior to look for a class with a specific controller

* remove looking strange test ingressclass

* return nil rather than en empty object

* change documentation

* apply @kevinpollet suggestion

* change order of processIngress to be correct and adjust tests

* review: clean.

* review: clean.

* Fix for review

Co-authored-by: Manuel Zapf <manuel@containo.us>
Co-authored-by: Fernandez Ludovic <ludovic@containo.us>
Co-authored-by: Michael <michael.matur@gmail.com>
2020-07-15 19:18:03 +02:00
1ef93fead7 Add HTTP Provider
* feat: add HTTP provider implementation

* refactor: add SetDefaults and struct tag for the new file parser

* feat: add TLS configuration property

* refactor: rework HTTP provider implementation

* feat: provide config only once if fetched config is unchanged

* style: lint

* ui: add HTTP provider icon

* tests: simplify and fix integration test

* docs: add reference config for file

* docs: move http reference config for file

Co-authored-by: Daniel Tomcej <daniel.tomcej@gmail.com>
2020-07-15 16:56:03 +02:00
285ded6e49 Add AWS ECS provider
* add ecs provider

* add ecs docs

* fix test after rebase

* add provider icon

* add missing addProvider call

* Fix for review

* Fix documentation

* Fix for review

* Fix documentation

* fix ctx usage

* autoDiscoverClusters setDefaults false

* Fix for review

* review: doc.

* Fix for review: add ctx in backoff retry

* review: linter.

Co-authored-by: Michael <michael.matur@gmail.com>
Co-authored-by: romain <romain@containo.us>
Co-authored-by: Fernandez Ludovic <ludovic@containo.us>
2020-07-15 16:28:04 +02:00
6e4f5821dc Merge branch 'v2.2' into master 2020-07-15 09:37:32 +02:00
a3df5b9a94 fix: documentation references. 2020-07-15 09:10:03 +02:00
04f0ebf776 Prepare release v2.2.5 2020-07-13 18:18:03 +02:00
0e97a3becd Revert domain fronting fix
* revert domain fronting changes

* reintroduce HostHeader rule

* add doc for removals
2020-07-13 17:58:03 +02:00
77a0cef9ce fix k8s crd to read contentType middleware into dynamic config
Co-authored-by: John Pekcan <apekcan@ea.com>
2020-07-13 12:30:03 +02:00
143e9b6f9c Fix default value for InsecureSNI when global is not set 2020-07-13 12:06:03 +02:00
06dcf8d8aa Prepare release v2.2.4 2020-07-10 19:16:04 +02:00
c315b4e064 Change the default value of insecureSNI
* fix: allow domain fronting by default

* review: typo.

* review: doc.

Co-authored-by: Fernandez Ludovic <ludovic@containo.us>
2020-07-10 18:48:03 +02:00
73ca7ad0c1 Merge remote-tracking branch 'upstream/v2.2' into mrg-current-v2.2 2020-07-10 11:23:49 +02:00
d7f517fbf5 Prepare release v2.2.3 2020-07-09 17:58:03 +02:00
b10cb84f33 Fix panic when using chain middleware. 2020-07-09 10:50:04 +02:00
a55f0cabdd Prepare release v2.2.2 2020-07-08 17:16:03 +02:00
d73c7ccf50 Fix triggering multiple concurrent requests to ACME 2020-07-08 12:54:04 +02:00
2b35397169 Disable domain fronting
Co-authored-by: jbdoumenjou <jb.doumenjou@gmail.com>
2020-07-08 12:18:03 +02:00
416c367778 Update Dashboard examples and move it after 'Router Rule' section 2020-07-08 09:26:03 +02:00
a20e90aa17 chore: update linter. 2020-07-07 14:42:03 +02:00
d698eba1e7 added required quotes to domains config
* added required quotes to domains config

otherwise syntax is incorrect

* review.

Co-authored-by: Fernandez Ludovic <ludovic@containo.us>
2020-07-03 15:18:03 +02:00
fe8e9414cf Change doc analytics. 2020-07-02 18:20:03 +02:00
ed216bea4d Add iOS specific icons
* Add iOS specific icons

* Remove extra line
2020-07-02 14:06:03 +02:00
3350b56057 Update go-acme/lego to v3.8.0 2020-07-02 13:56:03 +02:00
4d71f682b3 Fix race condition issues with provided dynamic configuration
* tests: add tests to show race condition on provider config

* fix: store a deep copy of previous provider config

* fix: send a deep copy of provdier config to watcher listener
2020-07-02 11:18:04 +02:00
607cda779d Add missing accessControlAllowOrigin list to middleware view
Headers middleware doesn't support `accessControlAllowOrigin` option
anymore, it should print a list of values from
`accessControlAllowOriginList`.
2020-07-02 10:56:03 +02:00
b61de07ca0 Remove checkStringQuoteValidity in loadIngressRouteConf
* remove checkStringQuoteValidity in loadIngressRouteConf

* remove checkStringQuoteValidity and related tests in crd

* remove checkStringQuoteValidity from ingress and related tests

Co-authored-by: traefiker <30906710+traefiker@users.noreply.github.com>
2020-07-02 10:34:04 +02:00
295ed76a1a fix certResolver typo 2020-07-01 14:42:04 +02:00
7669f41e8e Add custom ping http code when Traefik is terminating 2020-07-01 14:40:04 +02:00
8da051789f Fix statement about lego _FILE env var 2020-07-01 13:16:04 +02:00
30e0778ed2 Fix sticky cookie ingress annotation doc 2020-07-01 12:58:05 +02:00
7b1a256546 Update basicauth.md 2020-07-01 12:28:04 +02:00
cc4879fb76 Fix log field names in documentation 2020-07-01 12:14:04 +02:00
7c54a45950 Minor fix to Go templating documentation 2020-07-01 12:00:03 +02:00
73513f8371 Allow multiple secure middlewares to operate independently 2020-07-01 10:42:04 +02:00
dabf69abc7 Add rtribotte to maintainers 2020-06-18 17:50:04 +02:00
8d3d5c068c Provide username in log data on auth failure 2020-06-18 16:02:04 +02:00
cb1d0441e9 feat: use parser to load dynamic config from file. 2020-06-17 16:48:04 +02:00
8d827f98da Fix Headers middleware documentation, usage of proper bool 2020-06-17 10:22:03 +02:00
e5e46bf4ed Fix ipv6 handling in redirect middleware 2020-06-17 01:10:04 +02:00
mpl
9f32292473 internal handlers: support for response modifiers
Co-authored-by: Julien Salleyron <julien@containo.us>
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
2020-06-15 12:20:05 +02:00
7affeae480 Merge remote-tracking branch 'upstream/v2.2' into mrg-current-v2.2 2020-06-15 11:22:51 +02:00
b0f7b71453 refactor X-Forwarded-Proto 2020-06-10 14:32:03 +02:00
c0c540dc09 fix a broken link on Docker plugins documentation 2020-06-10 12:22:04 +02:00
7694ff1761 Fix v1-> v2 migration: unify domain name in documentation example 2020-06-09 12:18:04 +02:00
0d902671e5 Avoid overwriting already received UDP messages 2020-06-08 18:12:04 +02:00
fb90a7889a Fix doc url for Aurora DNS provider 2020-06-08 13:30:03 +02:00
48c73d6a34 Fix mem leak on UDP connections 2020-06-04 11:04:04 +02:00
12e462f383 Update kubernetes-crd.md 2020-06-03 17:24:04 +02:00
b7fe55b6be fix: dead link. 2020-06-03 16:22:04 +02:00
a1270d6cc7 Use specified network for "container" network mode 2020-05-28 19:58:04 +02:00
f874c389bd fixing typo in Provider KubernetesIngress at Routing documentation 2020-05-27 17:48:04 +02:00
8c5846c478 Fix healthcheck.interval in docs 2020-05-26 21:54:03 +02:00
dce807a329 Use "headers" instead of "header" in access log docs 2020-05-26 16:56:04 +02:00
7928e6d0cd Merge branch 'v2.2' into master 2020-05-18 18:37:11 +02:00
a98b726263 Fixes config samples regarding forceSlash option 2020-05-18 17:42:04 +02:00
42ec4e4e98 Fixed incorrect logging parameter in documentation 2020-05-18 17:20:04 +02:00
635e3fb9a8 Fix acme.md typo 2020-05-18 17:10:04 +02:00
5f0b6fde92 Upgrade Client-go to 0.18.2 2020-05-14 18:36:06 +02:00
04257afab7 Remove redundant paragraph in Kubernetes ingress documentation 2020-05-14 18:22:04 +02:00
mpl
b673969a0f Makefile: be consistent with host.docker.internal on all platforms 2020-05-14 18:00:08 +02:00
c52c40f061 Improve redirectScheme documentation 2020-05-14 17:30:06 +02:00
abdb5cc6cb Update Copyright 2020-05-12 19:04:04 +02:00
4a6817c64b Update go-acme/lego to v3.7.0 2020-05-11 19:54:04 +02:00
328611c619 Update linter 2020-05-11 12:06:07 +02:00
f12c27aa7c Improve acme CLI options in Let's Encrypt documentation 2020-05-04 23:36:03 +02:00
e22c62baba Fix wss in x-forwarded-proto 2020-04-30 18:00:04 +02:00
6b1158235e Merge branch 'v2.2' into master 2020-04-30 09:28:37 +02:00
efcaf64a43 Prepare release v2.2.1 2020-04-29 19:46:04 +02:00
f120301bc8 Disable distribution of the WebUI as PWA 2020-04-29 19:04:04 +02:00
mpl
4da63c9237 ratelimit: do not default to ipstrategy too early 2020-04-29 18:32:05 +02:00
97294df84f Update the documentation for helm chart 2020-04-29 17:32:05 +02:00
de42fc10b5 fix: cookie documentation. 2020-04-29 17:10:05 +02:00
e5c6b0d4ea Doc middleware compress content type 2020-04-29 11:26:04 +02:00
7c7ca7ef2b docs: Update kubernetes-crd-resource.yml 2020-04-28 17:18:04 +02:00
a813d32c53 Manage case for all Websocket headers 2020-04-27 18:12:04 +02:00
2f18e20cb0 Add polling for getOverview in toolbar 2020-04-27 17:48:05 +02:00
2ce2d63bda doc: add apiVersion for "kind: Middleware" 2020-04-27 17:26:06 +02:00
367e797d5f fix KV service docs for http:url and tcp:address 2020-04-27 17:18:04 +02:00
4fcf7bf2de Add sentence about the resource namespace and middleware 2020-04-27 11:32:05 +02:00
e1d51b51f2 Update go-acme/lego to v3.6.0 2020-04-24 14:58:05 +02:00
40b4032ea0 Add Access log chapter for migration v1->v2 2020-04-22 11:12:05 +02:00
756aa82aa9 Fix case-sensitive header Sec-Websocket-Version 2020-04-21 17:16:05 +02:00
fe5a4a26f8 Edit code indentation for correct alignment 2020-04-17 17:32:04 +02:00
2171cb7f3d fix: consider UDP when checking for empty config 2020-04-16 16:18:04 +02:00
f55a09862e doc: improve CRD documentation. 2020-04-15 17:38:05 +02:00
d0b21efd36 Added missing text a yaml file in Configuration 2020-04-15 17:26:05 +02:00
daf4258472 FIx wS heAder 2020-04-14 18:24:04 +02:00
Jan
619bc95b2b Update headers.md 2020-04-14 18:04:04 +02:00
76c2fa6d9a Add link to tracing with elastic 2020-04-14 17:50:05 +02:00
77bf3ac6ce Fix documentation about api.insecure defaults 2020-04-14 17:38:04 +02:00
0d7761f097 Fix typos in documentation 2020-04-08 18:54:03 +02:00
6c08d0b20b Fix documentation 2020-04-07 18:38:04 +02:00
148400ae0a Add note about health check in kubernetes 2020-04-07 17:16:03 +02:00
ac1657d86e Delete an unnecessary warning log 2020-04-03 17:06:06 +02:00
332c314d53 Fix bad address syntax in Global HTTP to HTTPS redirection v2 TOML 2020-04-02 13:20:05 +02:00
5c8d386881 It's just the one TLS, actually. 2020-03-31 17:08:05 +02:00
6f749c6414 Normalize default names for ConsulCatalog. 2020-03-30 19:12:05 +02:00
a6b6e1d101 Change the default priority on the router created by the redirect. 2020-03-30 14:50:05 +02:00
aa68cc2e63 Doc Fix for 2.2 Redirects 2020-03-28 13:02:04 +01:00
5560ab28f2 Prepare release v2.2.0 2020-03-25 17:46:04 +01:00
f624449ccb Delete an unnecessary warning log 2020-03-25 14:32:04 +01:00
mpl
69de5bb828 digest auth: use RequireAuthStale when appropriate 2020-03-25 14:28:04 +01:00
b54412e82e Merge branch v2.1 into v2.2 2020-03-24 14:18:39 +01:00
dd19fc3f3e Prepare release v2.1.9 2020-03-23 17:40:04 +01:00
dd436a689f Force http/1.1 for upgrade (Traefik v2) 2020-03-23 16:48:06 +01:00
ee06778cc2 fix: period field name. 2020-03-23 13:08:04 +01:00
b0c7fad81b doc: fix terminationDelay word case. 2020-03-23 11:48:04 +01:00
0c28630948 Fix sameSite (Traefik v2) 2020-03-23 11:24:05 +01:00
198320be8a Fix tab name 2020-03-21 20:22:04 +01:00
da8451c637 Prepare release v2.2.0-rc4 2020-03-19 18:10:05 +01:00
f54b8d8847 Merge branch v2.1 into v2.2 2020-03-19 17:53:34 +01:00
f4fb758629 Prepare release v2.1.8 2020-03-19 15:46:04 +01:00
b40fa61783 Fix memory leak in metrics
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2020-03-19 13:48:04 +01:00
94cd9e5337 Doc: fix wrong name of config format 2020-03-19 00:32:03 +01:00
15c9fc4051 Prepare release v2.2.0-rc3 2020-03-18 18:58:04 +01:00
2b28607a4e Merge remote-tracking branch 'upstream/v2.1' into v2.2 2020-03-18 18:16:08 +01:00
683d5d5a48 chore: skip openbsd/freebsd arm64 2020-03-18 17:21:20 +01:00
4f92ef5fa9 Prepare release v2.1.7 2020-03-18 15:50:05 +01:00
44221fba49 Fix entry point redirect behavior 2020-03-18 15:48:04 +01:00
mpl
63d7ed74f1 udp: replace concurrently reset timer with ticker
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2020-03-18 14:50:06 +01:00
9012f2d6b1 fix: Ingress TLS support
Co-authored-by: Julien Salleyron <julien@containo.us>
2020-03-18 13:30:04 +01:00
09224e4b04 fix: custom Host header. 2020-03-18 00:54:04 +01:00
668e6fd610 Fix wrong copy/pasted with service name warning 2020-03-18 00:32:04 +01:00
62c3025a76 Access log field quotes. 2020-03-17 12:36:04 +01:00
mpl
6e92c20edb docs: clarify multi-levels stickiness 2020-03-17 12:34:04 +01:00
60de577a5f Update go-acme/lego to v3.5.0 2020-03-16 17:28:05 +01:00
af58faafae Drop traefik from default entry points. 2020-03-16 16:54:04 +01:00
5adf74e6ce doc: Use neutral domains. 2020-03-13 22:50:05 +01:00
f4007a342c Improve ping documentation. 2020-03-13 18:12:04 +01:00
672234aaea docs: terminology, replace 'encoded' by 'hashed' 2020-03-13 17:30:04 +01:00
f19eebd3cc doc: fix typo. 2020-03-12 09:48:04 +01:00
37fb5298a0 Stop using fork of go-rancher-metadata 2020-03-12 00:00:04 +01:00
4280af4844 Update traefik install documentation 2020-03-11 18:28:05 +01:00
d67e06037e Prepare release v2.2.0-rc2 2020-03-11 18:12:04 +01:00
4ce90a7eb4 Remove @dduportal from the maintainers team (#6464) 2020-03-11 13:07:54 +01:00
mpl
4408c634b0 Specify passthrough for TCP/TLS in its own section 2020-03-10 17:28:04 +01:00
df351511de Fix example values for swarmModeRefreshSeconds 2020-03-10 16:08:05 +01:00
3b85dc9618 Improve kubernetes external name service support
Co-authored-by: jbdoumenjou <jb.doumenjou@gmail.com>
2020-03-10 12:46:05 +01:00
e511cfe2e4 Improve documentation for kubernetes ingress configuration
Co-authored-by: jbdoumenjou <jb.doumenjou@gmail.com>
2020-03-09 13:48:06 +01:00
d0f8c1834d Update migration documentation 2020-03-09 13:22:06 +01:00
d02bb28920 Router entry points on reload. 2020-03-09 11:12:05 +01:00
99861ac808 Fix broken documentation link 2020-03-06 10:30:06 +01:00
13ebd2c4e4 Update version references. 2020-03-05 21:46:04 +01:00
16c4807162 fix: update dockerignore. 2020-03-05 19:50:51 +01:00
11aa4a6be0 Prepare release v2.2.0-rc1 2020-03-05 19:12:04 +01:00
cf7f0f878a Support mirroring request body
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2020-03-05 18:30:07 +01:00
09c07f45ee Merge v2.1 into master. 2020-03-05 16:10:23 +01:00
b5d205b78c fix statsd scale for duration based metrics 2020-03-05 15:10:07 +01:00
ad6bf936d5 Add metrics about TLS 2020-03-05 13:30:05 +01:00
a6040c623b Entry point redirection and default routers configuration
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2020-03-05 12:46:05 +01:00
93a7af270f Update the k8s CRD documentation 2020-03-05 11:48:04 +01:00
082fb166a2 Rework access control origin configuration 2020-03-05 08:18:04 +01:00
dccc075f2c Add some missing doc. 2020-03-04 16:48:05 +01:00
5fdec48854 Added wildcard ACME example 2020-03-04 13:24:05 +01:00
fb51ebcba6 Disable default APM tracer. 2020-03-04 00:56:04 +01:00
67e17def56 Revert "Allow fsnotify to reload config files on k8s (or symlinks)" 2020-03-03 18:44:04 +01:00
353bd3d06f Added support for replacement containing escaped characters
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2020-03-03 16:20:05 +01:00
a7495f711b fix typo 2020-02-29 18:48:04 +01:00
e9d0a16a3b Merge 'v2.1' into master 2020-02-29 00:59:18 +01:00
5072735866 Prepare release v2.1.6 2020-02-28 18:30:05 +01:00
1746ed6e1c Prepare release v2.1.5 2020-02-28 18:02:05 +01:00
664cd940c5 fix: YML example of template for the file provider. 2020-02-28 14:52:05 +01:00
389536aff0 Add dark theme for Web UI 2020-02-27 21:30:04 +01:00
f6c6c2b2c0 Allow fsnotify to reload config files on k8s (or symlinks) 2020-02-26 17:50:07 +01:00
18d90ecd96 Do not follow redirects for the health check URLs 2020-02-26 17:28:04 +01:00
70fdfeb926 Use explicitly the word Kubernetes in the migration guide. 2020-02-26 16:38:05 +01:00
8c271cf40c Update to go1.14 2020-02-26 15:30:06 +01:00
665aeb34b2 Add UDP support in kubernetesCRD provider
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2020-02-26 12:28:05 +01:00
98f304f8b0 Use EDF schedule algorithm for WeightedRoundRobin 2020-02-26 11:56:05 +01:00
7a5d2a3bd9 WebUI: add udp pages 2020-02-26 11:12:05 +01:00
f4d62d3342 Fix docs and code to match in haystack tracing. 2020-02-26 11:10:06 +01:00
54df7b0a3c Update go-acme/lego to v3.4.0 2020-02-26 10:36:05 +01:00
9795a7c4a9 fix: consul-catalog use port from label instead of item port. 2020-02-25 23:00:04 +01:00
1557fda588 Consider SSLv2 as TLS in order to close the handshake correctly 2020-02-25 17:50:05 +01:00
1e7f34c271 Launch healhcheck only one time instead of two 2020-02-25 16:30:05 +01:00
d71e8ab7c9 Fix secret informer load 2020-02-25 15:14:04 +01:00
3b4c8ba439 Use consistent protocol determination 2020-02-25 10:12:04 +01:00
336dd1d5ba Update k3s. 2020-02-24 17:56:05 +01:00
a474e196ea Add TLSStores to Kubernetes CRD 2020-02-24 17:14:06 +01:00
101aefbfe8 Update dependencies 2020-02-24 16:06:05 +01:00
e04ebaa364 Fix typo in the godoc of TLS option MaxVersion 2020-02-21 17:48:05 +01:00
bb4de11c51 Add UDP in providers with labels 2020-02-20 22:24:05 +01:00
a20a5f1a44 Improvement of the unique name of the router for Ingress. 2020-02-18 17:34:05 +01:00
aab7043d45 Add information about filename and directory options. 2020-02-18 17:30:05 +01:00
ee6d28b25e Build all UDP services on an entrypoint 2020-02-17 18:02:04 +01:00
ef504f3eba Remove TLS cipher suites for TLS minVersion 1.3 2020-02-17 17:38:05 +01:00
86407871e6 Docs: Clarifying format of ingress endpoint service name 2020-02-17 17:30:06 +01:00
76bb2ef60c fix: dashboard example with k8s CRD. 2020-02-17 17:20:05 +01:00
beec65938e Improve documentation. 2020-02-17 11:04:04 +01:00
1c764052f7 Add http request scheme to logger 2020-02-17 10:46:04 +01:00
d501c0786f Early filter of the catalog services. 2020-02-13 10:26:04 +01:00
322c329c6f fix: use the right error in the log 2020-02-12 18:28:05 +01:00
7c430e5c9d Allow PreferServerCipherSuites as a TLS Option 2020-02-12 18:06:04 +01:00
94b2b6393f Add missing generated element for UDP. 2020-02-12 15:40:06 +01:00
4a1d20e8a3 Fix formatting in "Kubernetes Namespace" block 2020-02-12 14:26:05 +01:00
8762e5160d Let metrics libs handle the atomicity 2020-02-11 16:40:05 +01:00
c33348e80c fix: return an error when ping is not enabled. 2020-02-11 16:06:06 +01:00
0c90f6afa2 Fix traefik behavior when network_mode is host 2020-02-11 11:56:05 +01:00
mpl
115d42e0f0 UDP support
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2020-02-11 01:26:04 +01:00
6e43ab5897 Don't throw away valid configuration updates 2020-02-10 21:40:06 +01:00
8988c8f9af Decrease log level for client related error 2020-02-10 18:54:05 +01:00
aa21351d0d Merge branch v2.1 into master 2020-02-10 16:47:13 +01:00
97109db82b fix: KV flaky tests. 2020-02-10 15:48:06 +01:00
8bb625adb7 Minor readme improvements 2020-02-10 14:54:05 +01:00
ea2d65f8bb Update valkeyrie to fix the support of Redis. 2020-02-10 14:52:05 +01:00
1cf09d91bb Proxy API to Traefik in dev mode 2020-02-10 09:38:04 +01:00
cf2b97b656 Added link to community forum 2020-02-07 17:36:05 +01:00
2e8cbd81b4 Prepare release v2.1.4 2020-02-06 17:54:03 +01:00
b498c7bcbb Properly purge default certificate from stores before logging 2020-02-05 18:46:03 +01:00
e78843bdca fix a typo 2020-02-05 14:08:04 +01:00
2eaf3136f9 Minor documentation tweaks. 2020-02-04 21:20:04 +01:00
6b6ab9fe6d readme: update links to use HTTPS 2020-02-04 17:46:03 +01:00
f35b9a4509 Correct a trivial spelling mistake in the documentation. 2020-02-03 22:34:05 +01:00
349ce004f8 don't create http client for each request in forwardAuth middleware 2020-02-03 18:44:03 +01:00
1b63c95c4e Fix kubernetes providers shutdown and clean safe.Pool 2020-02-03 17:56:04 +01:00
c80d53e7e5 Update install-traefik.md 2020-02-03 17:18:04 +01:00
eb2028e0fa Add missing certResolver in IngressRoute examples. 2020-02-03 14:54:06 +01:00
03689251c5 Allow wildcard hosts in ingress provider 2020-02-03 11:24:06 +01:00
85c08312be Documentation fix for acme.md CLI 2020-02-02 13:50:03 +01:00
mpl
16288d171c use provider-qualified name when recursing for chain 2020-01-27 10:40:05 +01:00
87044c54f4 Improvement of the certificates resolvers logs 2020-01-24 16:30:07 +01:00
a4e8d3cb36 doc: use the same entry point name everywhere 2020-01-23 16:36:07 +01:00
dce6356d75 fix: etcd provider name. 2020-01-22 18:26:03 +01:00
mpl
c24e74efe3 systematically call updateIngressStatus 2020-01-22 03:44:04 +01:00
60e247862a Merge branch v2.1 into master 2020-01-21 18:41:46 +01:00
c796cd2250 Prepare release v2.1.3 2020-01-21 18:20:05 +01:00
c296a4a967 Remove Content-Type auto-detection
Co-authored-by: mpl <mathieu.lonjaret@gmail.com>
2020-01-21 18:06:03 +01:00
mpl
24192a3797 fix memleak in safe.Pool
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2020-01-20 17:42:05 +01:00
f84d947115 Use the calculated port when useBindPortIP is enabled 2020-01-20 15:56:05 +01:00
9544dece07 fix: invalid service definition. 2020-01-20 15:28:06 +01:00
6c4d7fd377 doc: adds an explanation of the global redirection pattern. 2020-01-20 15:04:09 +01:00
Jan
8d467ddd61 Adding an explanation how to use htpasswd for k8s secret 2020-01-20 13:24:05 +01:00
db28ee1ff7 Update golangci-lint version. 2020-01-19 23:00:06 +01:00
e378cb410c Update supported providers list. 2020-01-17 17:30:07 +01:00
144eee7fbf Update go-acme/lego to v3.3.0 2020-01-17 15:20:05 +01:00
72e702a15a Support 'networking.k8s.io/v1beta1' ingress apiVersion 2020-01-16 10:14:06 +01:00
6b7be462b8 Add Ingress annotations support
Co-authored-by: jbdoumenjou <jb.doumenjou@gmail.com>
2020-01-14 15:48:06 +01:00
4329d393e6 Update license date 2020-01-14 15:22:05 +01:00
4f52691f71 Add namespace attribute on IngressRouteTCP service 2020-01-14 12:14:05 +01:00
c132d71684 Fixed typo in k8s doc 2020-01-13 15:54:06 +01:00
8410f61c73 Fix small typo in user-guides documentation 2020-01-10 21:34:04 +01:00
cac76a182e Update APM client. 2020-01-10 11:48:07 +01:00
5b0e93552c Update Marathon.md 2020-01-10 02:40:03 +01:00
5eebd04d43 Fix typo in docker routing documentation 2020-01-09 16:34:05 +01:00
mpl
6f4aefffe7 Add period for rate limiter middleware 2020-01-08 11:44:04 +01:00
377c219fd9 Rename the non-exposed field "count" to "size" 2020-01-07 20:00:05 +01:00
da3d814c8b Merge branch 'v2.1' into master 2020-01-07 19:13:48 +01:00
4461ecfed1 Prepare release v2.1.2 2020-01-07 16:56:05 +01:00
bd676922c3 k8s Ingress: fix crash on rules with nil http 2020-01-07 16:26:08 +01:00
49356cadd4 fix(tracing): makes sure tracing headers are being propagated when using forwardAuth 2020-01-07 15:48:07 +01:00
c02f222005 Improves error message when a configuration file is empty. 2020-01-07 15:24:05 +01:00
d3977ce40e Improve documentation about Kubernetes IngressRoute 2020-01-07 11:26:05 +01:00
7283d7eb2f Log the ignored namespace only when needed 2020-01-07 10:46:04 +01:00
48252d284e Allow to run docker from Makefile in non-interactive mode 2020-01-06 16:58:04 +01:00
807dc46ad0 Handle respondingtimeout and better shutdown tests.
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2020-01-06 16:56:05 +01:00
0837ec9b70 Fix command for use websecure via CLI 2020-01-01 01:56:04 +01:00
b380522df8 fix: dashboard redirect loop 2019-12-24 17:36:04 +01:00
c127d34d32 fix: Malformed x-b3-traceid Header 2019-12-22 08:24:03 +01:00
bc0b97d5d8 Update ipwhitelist.md 2019-12-19 21:38:03 +01:00
431abe79f3 Query consul for service health separately 2019-12-19 11:00:07 +01:00
125470f110 Support SSH connection to Docker 2019-12-18 15:28:04 +01:00
4f669bdd66 Don't set user-agent to Go-http-client/1.1 2019-12-18 11:22:06 +01:00
8930236396 fix: invalid label/flag parsing. 2019-12-17 16:10:06 +01:00
b3c9a50ead Web UI: Polling on tables 2019-12-17 14:52:05 +01:00
4d0aee67be doc: remove section about templates 2019-12-17 14:30:06 +01:00
b501c6d5bf Added ExternalName https support for Kubernetes CRD, as done in v2.0 2019-12-16 21:48:03 +01:00
7dcee38b21 Use consistent name in ACME documentation 2019-12-13 15:46:06 +01:00
903c63ac13 add a documentation example for dashboard and api for kubernetes CRD 2019-12-13 10:36:04 +01:00
a98c9f99d1 Prepare release v2.1.1 2019-12-12 19:44:04 +01:00
7f085df240 chore: update some dependencies 2019-12-12 17:48:05 +01:00
b5ae141fb6 Add Migration Guide for Traefik v2.1 2019-12-12 17:06:05 +01:00
7eb866ffee Improve documentation about Traefik build. 2019-12-12 16:32:06 +01:00
mpl
61e59d74e0 CloseNotifier: return pointer instead of value 2019-12-12 15:12:05 +01:00
5f50d2e230 Add serial number certificate to forward headers 2019-12-12 00:32:03 +01:00
3f1484480e Web UI: Take off logic from generic table component 2019-12-11 23:14:04 +01:00
2d3fc613ec Merge branch 'v2.1' into master 2019-12-11 22:14:26 +01:00
e2982185d6 Prepare release v2.1.0 2019-12-11 18:40:04 +01:00
mpl
bdf4c6723f detect CloseNotify capability in accesslog and metrics 2019-12-10 18:18:04 +01:00
1d4f10bead Fix http/tcp resources pagination 2019-12-10 17:48:04 +01:00
aac3e2d4fb Several documentation fixes 2019-12-10 16:12:06 +01:00
87dd6badac Use valid condition in the service details panel UI 2019-12-10 15:34:06 +01:00
1b6c7af3eb Fix weighted service provider icon 2019-12-10 15:14:06 +01:00
5c091a1871 Merge branch 'v2.0' into v2.1 2019-12-09 18:48:20 +01:00
fb3839e096 Prepare release v2.0.7 2019-12-09 18:34:04 +01:00
eef3ca0295 Improve documentation for ACME/Let's Encrypt 2019-12-09 18:08:04 +01:00
c9dc0226fd fix: flaky Travis builds due to 'not get uid/gid' 2019-12-09 15:52:04 +01:00
1a7a3a4233 fix: remove double call to server Close. 2019-12-09 15:14:06 +01:00
d2e458f673 Remove mirroring impact in accesslog 2019-12-09 15:12:06 +01:00
e0f265db15 Make trailing slash more prominent for the "secure dashboard setup" too 2019-12-09 12:32:04 +01:00
39a3cefc21 fix: PassClientTLSCert middleware separators and formatting 2019-12-09 12:20:06 +01:00
89db08eb93 Improve documentation on file provider limitations with file system notifications 2019-12-09 11:48:05 +01:00
f40cf2cd8e The Cloudflare hint for the GLOBAL API KEY for CF MAIL/API_KEY 2019-12-09 11:42:06 +01:00
50bb69b796 Document LE caveats with Kubernetes on v2 2019-12-09 10:16:05 +01:00
Tim
a7d7c2b98b Fix Docker example in "Strip and Rewrite Path Prefixes" in migration guide 2019-12-06 00:42:04 +01:00
8dfc0d9dda readme: Fix link to file backend/provider documentation 2019-12-05 21:50:04 +01:00
0e6dce7093 Do not stop to listen on tcp listeners on temporary errors 2019-12-04 16:26:05 +01:00
ddbf4470a1 fix: debug endpoint when insecure API. 2019-12-04 15:28:07 +01:00
829649e905 Merge branch 'v2.1' into master 2019-12-03 10:43:25 +01:00
bc063ad773 Merge current v2.0 branch into v2.1 2019-12-03 10:40:05 +01:00
ef38810425 Upgrade python version to 3.7 for netlify 2019-12-03 10:16:05 +01:00
5ccca8d708 Prepare release v2.1.0-rc3 2019-12-02 19:10:04 +01:00
89919dbe36 Merge branch 'v2.0' into v2.1 2019-12-02 18:20:29 +01:00
ecd51a1428 Prepare release v2.0.6 2019-12-02 18:14:05 +01:00
4cb9eec257 Add custom help function to command 2019-12-02 17:34:06 +01:00
78097b96c9 Fix extraction for zipkin tracing 2019-12-02 14:18:07 +01:00
mpl
2af8589afd Do not give responsewriter or its headers to asynchronous logging goroutine
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2019-12-02 03:14:04 +01:00
cf1ace3a73 fix: consul catalog constraints. 2019-11-29 17:16:05 +01:00
efcc9d51d4 Healthcheck managed for all related services
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2019-11-29 12:40:05 +01:00
9b9f4be6a4 Add KV store providers (dynamic configuration only)
Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
2019-11-28 21:56:04 +01:00
a87c104172 Remove Request Headers CORS Preflight Requirement 2019-11-28 15:24:06 +01:00
028683666d Update deprecated function call in k8s providers 2019-11-28 00:04:04 +01:00
b2c59be8de Update router entrypoint example 2019-11-27 20:08:03 +01:00
2685e06528 Add Swarm section to the Docker Provider Documentation 2019-11-27 17:12:04 +01:00
a99673122e Service registered with same id on Consul Catalog 2019-11-27 16:24:06 +01:00
ba49012447 Mention the experimental Helm Chart in the installation section of documentation 2019-11-27 16:02:05 +01:00
fe8b090911 Elastic APM tracer implementation 2019-11-27 16:00:07 +01:00
c4a38de007 Web UI: Table infinite scroll 2019-11-27 15:06:06 +01:00
407eda0ba0 Web UI: Avoid unnecessary duplicated api calls 2019-11-27 12:04:05 +01:00
5b1dc0bfbd Change service name in rancher provider to make webui service details view work 2019-11-27 11:12:07 +01:00
772b260b37 fix: sub command help 2019-11-27 10:32:06 +01:00
bd75eddc8e Duration order consistency when multiplying number by time unit 2019-11-26 21:38:03 +01:00
00db3a0922 Web UI: Avoid some router properties to overflow their container 2019-11-23 23:18:04 +01:00
2bcc1b7fb4 Web UI: Sync toolbar table state with url query params 2019-11-20 19:02:05 +01:00
433c848c8d Web UI: Avoid polling on /api/entrypoints 2019-11-20 18:36:04 +01:00
abdb3b9475 Uses, if it exists, the ping entry point provided in the static configuration
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2019-11-20 18:34:05 +01:00
9761161163 Web UI: Fix displayed tcp service details 2019-11-20 18:26:10 +01:00
e5104021b1 doc: remove double quotes on CLI flags. 2019-11-19 10:18:05 +01:00
9ef4f47ba0 fix: changelog. 2019-11-15 22:06:23 +01:00
3bbc88f89a Prepare release v2.1.0-rc2 2019-11-15 20:32:03 +01:00
bfa61c8f67 fix: use MaxInt32. 2019-11-15 20:14:04 +01:00
3bdeb75cc2 Prepare release v2.1.0-rc1 2019-11-15 18:44:03 +01:00
ca9eaf383a Merge branch 'v2.0' into master 2019-11-15 13:34:41 +01:00
42a8d84a1f X-Forwarded-Proto must not skip the redirection. 2019-11-15 12:36:04 +01:00
3fd330c2fb Update go-acme/lego to 3.2.0 2019-11-15 12:06:05 +01:00
8f340afca1 Add back the security section from v1 2019-11-15 10:48:05 +01:00
e28d9426b9 doc: fix wrong acme information 2019-11-15 10:08:05 +01:00
b3078b75cd fix: location header rewrite.
Co-authored-by: Daniel Tomcej <daniel.tomcej@gmail.com>
2019-11-15 07:50:04 +01:00
424b97994e Fixed spelling error 2019-11-15 00:42:04 +01:00
mpl
f30a52c2dc Support for all services kinds (and sticky) in CRD
Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2019-11-14 19:28:04 +01:00
1db22f4a1b Prepare release v2.0.5 2019-11-14 18:22:04 +01:00
424e2a9439 Add internal provider
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2019-11-14 16:40:05 +01:00
2ee2e29262 Fix empty address for registering service without IP 2019-11-14 11:10:06 +01:00
7afd2dbd20 fix: stripPrefix middleware with empty resulting path. 2019-11-14 10:32:05 +01:00
cdb2446e32 Update ACME storage docs to remove reference to KV store in CE 2019-11-14 08:22:04 +01:00
ac8c9215cd Update tooling used for documentation 2019-11-14 00:22:03 +01:00
dfca01e469 fix typo in v1 to v2 migration guide 2019-11-13 00:34:04 +01:00
SKP
ca1d980746 Added configurable prefix for statsd metrics collection 2019-11-12 18:18:04 +01:00
587d3f9012 Wrong endpoint on the TLS secret example 2019-11-12 17:02:05 +01:00
e30ab07439 Dashboard example with swarm 2019-11-12 15:40:05 +01:00
e6e026f420 Fix rate limiting and SSE 2019-11-12 11:06:05 +01:00
2036518813 Use alpine for v2 experimental images. 2019-11-12 10:44:05 +01:00
7536f5e83c fix: metric with services LB. 2019-11-12 10:24:05 +01:00
229402594f docs: remove field api.entryPoint 2019-11-08 15:00:06 +01:00
97873ddb5d slashes ended up in bad place. 2019-11-08 14:28:05 +01:00
dbf303d5d6 Fix quickstart link in README 2019-11-08 09:44:04 +01:00
7346b3e326 Adds missed quotes in api.md 2019-11-06 12:22:05 +01:00
93cf947e2a Improve building documentation 2019-11-05 18:10:03 +01:00
c37ad5c8bf Double dollar on docker-compose config 2019-11-05 13:22:04 +01:00
5a3e325742 Add tls option for Elliptic Curve Preferences 2019-11-03 15:54:04 +01:00
c5ec12cd56 feat: add consul catalog options 2019-10-31 11:56:05 +01:00
3410541a2f Conditionnal compression based on Content-Type 2019-10-31 11:36:05 +01:00
80a68de91b Upgrades zipkin library to avoid errors when using textMap. 2019-10-30 12:46:04 +01:00
1f39083555 Add support for MaxVersion in tls.Options 2019-10-29 12:58:05 +01:00
5f8fb6c226 fix: Consul Catalog documentation. 2019-10-29 12:32:05 +01:00
d66dd01438 Merge branch 'v2.0' into master 2019-10-29 09:52:45 +01:00
6d3bad1ae0 Fix error in link description for priority 2019-10-28 23:20:03 +01:00
8b8b1427f6 Prepare release v2.0.4 2019-10-28 21:10:50 +01:00
e2d971f20e fix: release timeout. 2019-10-28 20:58:05 +01:00
9d17e8826b Prepare release v2.0.3 2019-10-28 17:50:05 +01:00
531c581cd5 Fix a typo in routing documentation for Docker 2019-10-28 17:42:05 +01:00
f790b9aa54 Add example for changing the port used by traefik to connect to a service 2019-10-28 15:50:06 +01:00
8f000423ed fix: default tracing backend. 2019-10-28 12:26:05 +01:00
4990f6c22d Allow Default Certificate to work on macOS 10.15 2019-10-28 11:52:04 +01:00
mpl
d447a50b73 Prepare release v1.7.18 2019-10-28 11:52:04 +01:00
cbecfad4df Prepare release v1.7.17 2019-10-28 11:52:04 +01:00
770a7f11a7 Avoid closing stdout when the accesslog handler is closed
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
Co-authored-by: jlevesy <julien.levesy@containo.us>
2019-10-28 11:52:04 +01:00
27a65f8745 Add note clarifying client certificate header 2019-10-28 11:52:04 +01:00
5cd06c03f0 Prepare release v1.7.16 2019-10-28 11:52:04 +01:00
43e5092c46 Prepare release v1.7.15 2019-10-28 11:52:04 +01:00
mpl
a239e3fba6 error pages: do not buffer response when it's not an error 2019-10-28 11:52:04 +01:00
743d772a80 doc: @ is not authorized in names definition. 2019-10-28 11:04:05 +01:00
1f734630b9 Improve documentation of the router rules for API and dashboard 2019-10-25 17:32:04 +02:00
355fe6195e Add documentation about backtick for rule definition. 2019-10-25 17:16:05 +02:00
d22bd5b42d Fix ldflags using incorrect pkg url 2019-10-25 16:48:06 +02:00
5327ce543b Remove unnecessary reload of the configuration. 2019-10-25 15:46:05 +02:00
3747eb59ea fix: deep copy of passHostHeader on ServersLoadBalancer. 2019-10-25 14:40:05 +02:00
2b00ab3432 fix: skip akamai url verify. 2019-10-25 14:02:09 +02:00
a6cdd701e2 Set proxy protocol logger to DEBUG level 2019-10-24 10:02:06 +02:00
c8984e6a6a Use debug for log about skipping addition of cert 2019-10-24 01:10:04 +02:00
9179aa52cf Fix Security Headers Doc 2019-10-23 11:48:05 +02:00
2042fdf3bd fix typo for stripPrefix in tab File (YAML) 2019-10-20 23:40:03 +02:00
d1c3372dc4 fix ForwardAuth tls.skipverify examples 2019-10-18 11:50:05 +02:00
3884a68889 fix: add stacktrace when recover. 2019-10-18 11:30:05 +02:00
0ec84ec597 Adding support for HTTPs backends with Kubernetes ExternalName services 2019-10-18 11:12:05 +02:00
6a9d21e9aa Fix spelling mistake: "founded" -> "found" 2019-10-18 10:54:05 +02:00
a829d44b51 Let instana/go-sensor handle default agent host 2019-10-16 22:30:05 +02:00
554e3e9e6e fix incorrect DNS reference 2019-10-16 16:40:04 +02:00
904b3b5b0b Remove obsolete v2 remark from README 2019-10-16 16:26:05 +02:00
14bdc0e57a Fix consul catalog documentation 2019-10-16 10:36:04 +02:00
02bdc1dcb9 Clarify unit of duration field in access log 2019-10-16 10:34:04 +02:00
7be2db6e86 Add Consul Catalog provider 2019-10-15 17:34:08 +02:00
b586ae2f25 Remove deadcode. 2019-10-15 16:36:05 +02:00
d0ed814669 Update jaeger dependencies 2019-10-15 16:30:06 +02:00
8492a702b2 Migration guide: pathprefixstrip migration 2019-10-14 17:26:05 +02:00
0048156379 chore(node/webui): update node to 12.11 version 2019-10-14 17:18:04 +02:00
cb3328dca3 Normalize service and router names for ingress. 2019-10-14 11:18:04 +02:00
e7b7ae94b0 fix: add filename in the file provider logs. 2019-10-11 17:20:05 +02:00
17ce295c30 Fix acme storage file docker mounting example 2019-10-11 14:34:06 +02:00
4e9166759d Merge branch 'v2.0' into master 2019-10-10 00:30:01 +02:00
d5e3bb1b6d Prepare release v2.0.2 2019-10-09 19:12:05 +02:00
7e4e5ec6e4 Add a service sticky details vue component 2019-10-09 17:34:05 +02:00
f2656e62dc fix: default router name for k8s ingress. 2019-10-09 17:16:07 +02:00
83de97e547 fix misspelling on documentation landing page 2019-10-09 16:56:05 +02:00
b552efe770 Update apiVersion in documentation descriptor 2019-10-09 14:56:04 +02:00
1663c7c8e7 fix: ovh client int overflow. 2019-10-09 14:48:04 +02:00
1a6bef1a7e doc: update issues and PRs templates. 2019-10-09 14:28:04 +02:00
ff31e75ccc ci: reduce memory consumption of the linter 2019-10-09 11:48:04 +02:00
c87a37f804 Improve ciphersuite examples 2019-10-08 14:38:04 +02:00
76ead096aa Update 04-ingressroutes.yml 2019-10-07 15:20:06 +02:00
668ff71470 Replace ambiguous cli help message wording 2019-10-07 15:12:05 +02:00
538d5e8be4 TLS_RSA_WITH_AES_256_GCM_SHA384 is considered weak 2019-10-07 15:02:06 +02:00
b2b142a037 State clearly, that they are mutual exclusive 2019-10-07 14:48:05 +02:00
3ebed4ff40 Clarifies how to configure and access the dashboard in the api & dashboard documentations 2019-10-07 14:38:06 +02:00
a2cd69b654 Fix typo in log 2019-10-07 13:12:05 +02:00
cfc14671ed Remove deprecated videos 2019-10-07 12:52:22 +02:00
ed4b2f74ff Update scope of services and middlewares 2019-10-07 12:50:04 +02:00
dd53be7a1b typo in cli command 2019-10-07 12:32:07 +02:00
c83d7916c9 fix: typo in healthCheck examples 2019-10-07 10:14:04 +02:00
0865962f8d fix: remove extra backtick from routers docs 2019-10-07 09:58:03 +02:00
9691085bc2 Fix yaml domains example 2019-10-07 09:48:04 +02:00
b243d1c599 Add overview to API documentation 2019-10-07 09:38:04 +02:00
db6e404bda Typo in documentation 2019-10-02 16:32:05 +02:00
6f63e24dbb Add a response forwarding section to the service documentation 2019-10-01 13:26:04 +02:00
0082fe8173 $ needs escaping in docker-compose.yml 2019-09-30 18:32:04 +02:00
mpl
06d37b2a94 document providersThrottleDuration 2019-09-30 18:24:04 +02:00
48f11900d3 fix: default passHostHeader for file provider. 2019-09-30 18:12:04 +02:00
230cd28ac9 fix: return an error instead of panic. 2019-09-30 17:52:04 +02:00
mpl
86261f2b0a document serversTransport 2019-09-30 17:16:05 +02:00
30ad00fa65 doc: fix influxDB and statsD case in configuration page. 2019-09-30 14:56:05 +02:00
33a1499bdd fix: panic with metrics recorder. 2019-09-30 14:42:04 +02:00
211fa18ac2 Add the pass host header section to the services documentation 2019-09-30 11:26:06 +02:00
4c5250e850 Fix misleading text 2019-09-30 09:12:04 +02:00
788024685f Fixed typo in routing/providers/docker documentation 2019-09-27 13:08:03 +02:00
b5f07d2995 Change instances of "dymanic" to "dynamic" 2019-09-26 18:20:04 +02:00
mpl
8d7af21ff3 Prepare release v2.0.1 2019-09-26 18:02:05 +02:00
dce9278193 Add the router priority documentation 2019-09-26 15:16:05 +02:00
mpl
c6e783e7c3 clarify automatic service creation/assignment with labels 2019-09-26 12:48:05 +02:00
c8fa059064 fix: docker service name. 2019-09-26 12:26:05 +02:00
29efac3e5e fix: update linter. 2019-09-26 11:00:06 +02:00
027d313df5 fix: improve log for invalid middleware. 2019-09-26 10:04:04 +02:00
ea78808e74 fix doc about file.filename 2019-09-26 09:24:04 +02:00
mpl
6f6f999129 Do not initialize list of middlewares if not needed
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2019-09-25 18:20:04 +02:00
b16ebd529b Update Casing on STS Header Directive 2019-09-25 16:50:16 +02:00
mpl
25deecd405 add indent to fix notes 2019-09-23 18:58:03 +02:00
2471f893e7 Merge branch 'v2.0' into master 2019-09-23 17:26:52 +02:00
17480abe85 YAML I love you 2019-09-23 17:00:06 +02:00
bfde17b4d7 Improve routing documentation 2019-09-23 14:32:04 +02:00
76263a9610 Improve TLS documentation. 2019-09-23 11:22:05 +02:00
855468e776 fix: typo in TOML for HTTP to HTTPS redirection 2019-09-23 10:30:04 +02:00
beceea9421 Wrong acme example. 2019-09-20 18:44:03 +02:00
dabc139fab doc: Flags and labels are case insensitive. 2019-09-20 17:16:05 +02:00
mpl
41aea2e336 document that /dashboard should be preferred over / 2019-09-20 17:08:04 +02:00
f929346c18 Improve documentation for the TLS section of the provider connection. 2019-09-20 17:00:05 +02:00
e699662b1e Improve the migration guide 2019-09-20 16:44:04 +02:00
90057318c8 Flag names don't need a consistent case. 2019-09-20 16:36:04 +02:00
mpl
6f2eaf3009 fixed doc typoes 2019-09-19 16:20:05 +02:00
e8fc16dc09 fix indentation for tab on migration guide 2019-09-19 11:10:04 +02:00
0f1911ba68 Return an actual server status updater 2019-09-18 17:56:05 +02:00
94699fbe00 Update links in readme. 2019-09-18 15:08:05 +02:00
mpl
a380317e2c fix typo for kubectl version 2019-09-18 12:16:04 +02:00
64bcdd4398 Improve the Migration Guide 2019-09-18 08:38:05 +02:00
56e0580aa5 Merge branch 'v2.0' into master 2019-09-17 17:37:22 +02:00
7f0c9c239e fix: CNAME of the docs. 2019-09-17 17:12:04 +02:00
e0a1592e6e Fix case-sensitive header in websocket 2019-09-17 16:12:04 +02:00
3d784a14f9 Prepare release v2.0.0 2019-09-16 18:28:04 +02:00
47a9b086ea Disable collect data by default. 2019-09-16 17:26:06 +02:00
e70c8a7b46 Fix error in the documentation for CLI configuration example 2019-09-16 16:36:03 +02:00
673351d821 Fix typo in documentation 2019-09-16 15:34:05 +02:00
4b966f1f82 Web UI graph names. 2019-09-16 15:18:06 +02:00
93626de01c fix: invalid hash for github.com/labbsr0x/goh 2019-09-16 10:44:03 +02:00
7847b7685d Prepare release v2.0.0-rc4 2019-09-13 20:52:04 +02:00
255e88fbf6 Fix kubernetes id name 2019-09-13 20:44:04 +02:00
685c6dc00c Add weighted round robin load balancer on TCP
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2019-09-13 20:00:06 +02:00
8e18d37b3d fix: logger and context. 2019-09-13 19:28:04 +02:00
b4c7b90c9e fix: boolean flag parsing with map. 2019-09-13 19:10:04 +02:00
b55be9fdea On client CloseWrite, do CloseWrite instead of Close for backend
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2019-09-13 17:46:04 +02:00
401b3afa3b Add passHostHeader and responseForwarding in IngressRoute
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2019-09-13 16:46:04 +02:00
7fa3537015 fix a service with one server .yaml example 2019-09-13 11:30:05 +02:00
149ed91afb fix: passHostHeader in the webUI. 2019-09-13 08:24:04 +02:00
887826ee68 Improve documentation about API and Dashboard. 2019-09-12 16:22:03 +02:00
7357d5eae2 fix: services configuration documentation. 2019-09-12 10:18:04 +02:00
e4e2a188c5 Merge branch 'v2.0' into master 2019-09-11 15:21:50 +02:00
e40e3af760 Prepare release v2.0.0-rc3 2019-09-10 18:58:03 +02:00
24a2788081 Prepare release v1.7.14 2019-09-10 18:30:05 +02:00
mpl
1388266102 Finish kubernetes throttling refactoring 2019-09-10 18:30:05 +02:00
43af0b051f Throttle Kubernetes config refresh 2019-09-10 18:30:05 +02:00
6e8138e19b Update golangci-lint 2019-09-10 17:52:04 +02:00
fb8edd86d5 k8s ErrorPage middleware now uses k8s service 2019-09-10 17:24:03 +02:00
34be181706 Add provider in middleware chain 2019-09-10 16:12:05 +02:00
fcc1109e76 Add more pages in the WebUI 2019-09-10 14:40:05 +02:00
mpl
2b828765e3 Improve rate limiter tests
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2019-09-09 20:02:04 +02:00
25f4c23ab2 Write HTTP server logs into the global logger. 2019-09-09 14:52:04 +02:00
be90b20a5d fix: TLS domains with IngressRoute. 2019-09-09 13:52:04 +02:00
232c113dae Misc documentation fixes 2019-09-09 10:36:08 +02:00
mpl
605a9b2817 Default to CLF when accesslog format is unsupported 2019-09-09 09:24:03 +02:00
d044c0f4cc New API security 2019-09-06 15:08:04 +02:00
1959e1fd44 Auth middlewares in kubernetes CRD uses secrets 2019-09-05 13:42:04 +02:00
mpl
6712423dd1 misc documentation fixes 2019-09-05 10:48:04 +02:00
3689990bd5 Enhance the Retry Middleware Documentation
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2019-09-04 17:28:03 +02:00
81a1f618f9 Update to go 1.13 2019-09-04 11:16:03 +02:00
b77bb690de Prepare release v2.0.0-rc2 2019-09-03 21:18:03 +02:00
f843f260ee fix: stripPrefix and stripPrefixRegex. 2019-09-03 20:32:03 +02:00
770b3739e0 The chain middleware in k8s use middlewareRef 2019-09-03 19:20:04 +02:00
261e7c1744 Fix some documentation issues 2019-09-03 18:02:05 +02:00
10acbb8d92 Don't panic with undefined middleware 2019-09-03 15:22:05 +02:00
a917115a85 fix buffering middleware 2019-09-03 15:02:05 +02:00
b8ed6f1588 Re enable ratelimit integration tests 2019-09-03 14:34:04 +02:00
3ed57e01a6 Update go version to go 1.13rc2 2019-09-03 12:18:03 +02:00
cb7c5a8ca1 Update Zipkin OpenTracing driver to latest 0.4.3 release 2019-09-03 11:52:04 +02:00
07eb9c5970 Update restrictions in the documentation. 2019-09-02 03:26:04 -07:00
306e5081d9 fix: Datadog case. 2019-09-02 03:18:04 -07:00
259c7adc81 deep-copy for MirrorService 2019-09-02 02:54:04 -07:00
af9762cf32 Improve API for the web UI 2019-09-02 02:38:04 -07:00
17554202f6 fix: stripPrefixRegex documentation. 2019-09-02 01:52:04 -07:00
0d9cf697fa Base of the migration guide
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2019-08-31 00:28:04 -07:00
df0dd2f5e6 Add errors about unknown entryPoint in runtime api 2019-08-29 03:38:04 -07:00
38508f9a9c Fix recovered panic when websocket is mirrored 2019-08-29 01:28:05 -07:00
b113972bcf Fix trailing slash with check new version 2019-08-29 00:56:04 -07:00
72e67bf4e9 Rest provider icon in the webui 2019-08-28 05:52:05 -07:00
a20a6636b4 Merge v2.0.0-rc1 into master 2019-08-27 01:59:33 +02:00
da8aa2d8e4 Prepare release v2.0.0-rc1 2019-08-26 10:36:03 -07:00
602a2ea541 Adds mirroring service 2019-08-26 10:00:04 -07:00
fd24b1898e Add a new dashboard page. 2019-08-26 18:15:41 +02:00
89150e1164 Update to go1.13rc1 2019-08-26 06:06:05 -07:00
e1831c4c60 Add support proxyprotocol v2 2019-08-26 05:40:04 -07:00
mpl
4ec90c5c0d Add rate limiter, rename maxConn into inFlightReq
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
2019-08-26 03:20:06 -07:00
a8c73f7baf Ensure WaitGroup.Done() is always called 2019-08-26 01:54:05 -07:00
6fed76a687 WeightedRoundRobin load balancer
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2019-08-26 01:30:05 -07:00
84de444325 Bump x/sys to support Risc-V architecture 2019-08-23 07:36:04 -07:00
0fbd87ca87 Fix: CRD user guide 2019-08-23 07:20:05 -07:00
99797502eb docker-compose labels require $'s to be escaped 2019-08-20 08:08:05 -07:00
16bd0b9ca8 Removed extra colon before the 8080 docker port 2019-08-15 07:44:04 -07:00
5fdfa963f4 fix: lego version. 2019-08-15 06:52:03 -07:00
1d86e71331 fix: invalid pseudo version. 2019-08-14 14:54:03 -07:00
9e3f549341 Add TLS-enabled Router 2019-08-14 10:16:06 -07:00
2895ad21f3 Correct Kubernetes Ingress and IngressRoute port heuristic for choosing HTTPS 2019-08-14 09:58:04 -07:00
5731ae7f47 Fix url.Parse due to go1.12.8 changes. 2019-08-14 09:16:04 -07:00
51f7d9a07f Split runtime.go 2019-08-14 08:28:04 -07:00
6be390c795 feat(webui): add doc and version in navbar 2019-08-12 08:48:04 -07:00
0f32de4aa2 tests: improve timeout.
- upgrade k3s to v0.8.0
2019-08-12 05:06:04 -07:00
5d01452648 doc: contributing guide. 2019-08-12 05:06:04 -07:00
51b0508512 scripts: makefile, dockerfile, travis, ... 2019-08-12 05:06:04 -07:00
4c5e7a238d chore: go module 2019-08-12 05:06:04 -07:00
f327b7b499 chore: ignore vendor. 2019-08-12 05:06:04 -07:00
306e86c9c6 kill: the vendor. 2019-08-12 05:06:04 -07:00
9024f1b444 doc: update lego. 2019-08-12 00:36:04 -07:00
fc26e8c194 Prepare release v1.7.13 2019-08-12 00:36:04 -07:00
ffd8e5667c Wrr loadbalancer honors old weight on recovered servers 2019-08-12 00:36:04 -07:00
9299c3abc7 Add missing KeyUsages for default generated certificate 2019-08-12 00:36:04 -07:00
88ebac942e Merge branch 'v2.0' into master. 2019-08-06 21:26:59 +02:00
63a07fe6cf Add a docker-compose & let's encrypt user-guide 2019-08-06 08:46:04 -07:00
c2d440a914 chore: update docker and k8s 2019-08-05 09:24:03 -07:00
2b5c7f9e91 [Docs] YAML indent for domains under TLS section 2019-08-05 08:22:04 -07:00
91e63dea47 Apply the case of the CLI flags for the configuration 2019-08-05 06:22:03 -07:00
cd164de776 Add Feature-Policy header support 2019-07-29 07:12:05 -07:00
c0ef5ce512 Fix prometheus metrics 2019-07-24 12:38:03 +02:00
7c852fbf33 refactor(webui): use components to split Home concerns 2019-07-22 11:06:04 +02:00
28500989bc Improve acme logs. 2019-07-22 10:16:04 +02:00
75c99a0491 doc: improve examples. 2019-07-22 09:58:04 +02:00
8b4ba3cb67 Fix malformed rule 2019-07-22 09:24:04 +02:00
Jan
3ef2971c3f Fix acme example 2019-07-19 18:06:03 +02:00
a5aa8c6006 Prepare release v2.0.0-beta1 2019-07-19 17:18:03 +02:00
Jan
022d14abe1 Fixed a typo in label. 2019-07-19 17:00:05 +02:00
1800b0b69c Improve error on router without service.
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2019-07-19 16:42:04 +02:00
c39a550b00 Lets encrypt documentation typo 2019-07-19 15:52:03 +02:00
mpl
092aa8fa6d API: remove configuration of Entrypoint and Middlewares
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2019-07-19 12:28:07 +02:00
f75f73f3d2 Certificate resolvers.
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
2019-07-19 11:52:04 +02:00
e3627e9cba Disable RateLimit temporarily 2019-07-19 10:50:05 +02:00
mpl
d5f4934acf Add documentation about Kubernetes Ingress provider 2019-07-19 09:50:04 +02:00
693bd7e110 Add a basic Traefik install guide 2019-07-19 09:24:04 +02:00
4d8dcdc623 feat(webui/dashboard): init new dashboard 2019-07-18 22:36:04 +02:00
8e97af8dc3 Add Metrics 2019-07-18 21:36:05 +02:00
4dc448056c fix: TLS configuration from directory. 2019-07-18 16:26:05 +02:00
68c349bbfa Manage status for TCP element in the endpoint overview. 2019-07-18 15:56:04 +02:00
75aedc8e94 Fixed doc link for AlibabaCloud 2019-07-17 20:12:04 +02:00
8b08f89d2c Allows logs to use local time zone instead of UTC
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2019-07-17 20:12:04 +02:00
889b38f75a Improve tracing documentation 2019-07-16 09:54:04 +02:00
a17ac23457 Update Dynamic Configuration Reference for both Docker and Marathon 2019-07-16 06:48:03 +02:00
mpl
6fdd48509e config: deal with multiple errors and their criticality
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2019-07-15 17:04:04 +02:00
62800116d3 Add Jaeger collector endpoint 2019-07-15 14:52:04 +02:00
1bccbf061b refactor(webui): use @vue/cli to bootstrap new ui 2019-07-15 10:58:03 +02:00
093658836e Restrict traefik.toml to static configuration. 2019-07-15 10:22:03 +02:00
f49800e56a user guide: fix a mistake in the deployment definition 2019-07-15 10:00:06 +02:00
e478dbeb85 Docker URL 2019-07-15 07:06:03 +02:00
51486b18fa Enhance REST provider 2019-07-13 01:24:03 +02:00
48d98dcf45 Update docker version for build 2019-07-12 21:14:03 +02:00
2c7cfd1c68 Expand Client Auth Type configuration 2019-07-12 17:50:04 +02:00
7a4b4c941c Update dep version 2019-07-12 15:36:04 +02:00
608ccb0ca1 Update golangci-lint 2019-07-12 15:04:03 +02:00
3f6ea04048 Properly add response headers for CORS 2019-07-12 11:46:04 +02:00
74c5ec70a9 Improve API endpoints 2019-07-12 11:10:03 +02:00
c8bf8e896a Move dynamic config into a dedicated package. 2019-07-10 09:26:04 +02:00
09cc1161c9 Generate deepcopy for configuration struct 2019-07-09 15:18:04 +02:00
8ab33db51a Renamed kubernetes provider in kubernetesIngress provider 2019-07-08 21:36:03 +02:00
cc4258bf9d Remove X-Forwarded-(Uri, Method, Tls-Client-Cert and Tls-Client-Cert-Info) from untrusted IP 2019-07-08 17:56:04 +02:00
0ee5d3d83f Automatic generation of the doc for the CLI flags and env vars. 2019-07-08 11:00:04 +02:00
c39aa5e857 Add scheme to IngressRoute. 2019-07-05 17:24:04 +02:00
mpl
39aae4167e TLSOptions: handle conflict: same host name, different TLS options
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2019-07-03 19:22:05 +02:00
9db9143366 Improve providers documentation. 2019-07-02 17:36:04 +02:00
06df6017df Merge branch 'v2.0' into master 2019-07-02 13:35:09 +02:00
49814b92fe Prepare release v2.0.0-alpha8 2019-07-01 19:36:04 +02:00
260b5d6b0d Add gRPC user guide 2019-07-01 15:28:04 +02:00
4360ca14c1 Use h2c from x/net to handle h2c requests
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2019-07-01 15:08:04 +02:00
c7d336f958 Use the same case everywhere 2019-07-01 11:30:05 +02:00
f6436663eb Make HTTP Keep-Alive timeout configurable for backend connections 2019-06-28 00:36:04 +02:00
84d7c65039 Improve tracing 2019-06-28 00:16:04 +02:00
4245096be4 Define a TLS section to group TLS, TLSOptions, and TLSStores.
Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
2019-06-27 23:58:03 +02:00
c9b2a07bc7 Drop headers by default in access logs. 2019-06-27 16:04:03 +02:00
e69d4cba88 Support YAML for the dynamic configuration. 2019-06-26 18:18:04 +02:00
mpl
96962dd21f Handle cross-provider middleware in kubernetes CRD
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2019-06-26 14:14:05 +02:00
36d48224b5 fix: error log message. 2019-06-26 09:10:03 +02:00
15b5433f1a Merge branch 'v2.0' into master 2019-06-25 20:16:20 +02:00
53779d6ceb Adding content-header to api endpoints 2019-06-25 17:44:03 +02:00
mpl
e7e268b3bd doc/crd-acme: specify required kubectl version 2019-06-25 14:50:04 +02:00
ca2f76fe1f Update Slack support channel references to Discourse community forum 2019-06-25 10:08:04 +02:00
4d44ab9628 Change the loading resource order 2019-06-24 16:40:06 +02:00
dd62051e6c Improve middleware documentation. 2019-06-24 06:04:03 +02:00
fdb1701d1b Prepare release v2.0.0-alpha7 2019-06-21 17:46:02 +02:00
80b35575df Define TLS options on the Router configuration for Kubernetes
Co-authored-by: juliens <julien@containo.us>
2019-06-21 17:18:05 +02:00
69cf05df9a Fix panic in tls manager 2019-06-21 16:32:04 +02:00
69a1817c3f Improve some parts of the documentation. 2019-06-21 10:54:04 +02:00
a918dcd5a4 Filter env vars configuration 2019-06-21 10:08:04 +02:00
adc9a65ae3 Use name@provider instead of provider@name. 2019-06-21 09:54:04 +02:00
1e779f7135 Fix some CLI bugs 2019-06-21 09:40:04 +02:00
fe68e9e243 New constraints management.
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2019-06-21 09:24:04 +02:00
890d02638b Merge branch v2.0 into master 2019-06-20 11:37:47 +02:00
e9792b446f Change the provider separator from . to @ 2019-06-20 00:40:05 +02:00
mpl
4012599264 docs: rewrite of the HTTPS and TLS section
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2019-06-19 19:00:06 +02:00
mpl
429b1d8574 API: new contract
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2019-06-19 18:34:04 +02:00
a34876d700 Display an error when help is called on a non existing command. 2019-06-19 14:08:05 +02:00
68ecf78f0e Upgrade k3s version 2019-06-18 22:32:05 +02:00
38344b342d Prepare release v2.0.0-alpha6. 2019-06-18 18:10:06 +02:00
346ff96de2 Kubernetes CRD documentation fixes 2019-06-18 12:20:04 +02:00
31614bebc4 Don't allow non flag arguments by default. 2019-06-18 12:10:06 +02:00
be888b59a6 doc: fix middleware names for CRD. 2019-06-18 09:50:05 +02:00
6069df6cbd fix: revert deploy script. 2019-06-17 23:40:05 +02:00
5e7b6e4860 fix: deploy script. 2019-06-17 22:14:05 +02:00
ea6fa6e889 Prepare release v2.0.0-alpha5 2019-06-17 19:38:04 +02:00
3e914256ce Update headers middleware docs for kubernetes crd 2019-06-17 18:30:05 +02:00
85ce16b34f Define TLS options on the Router configuration
Co-authored-by: juliens <julien@containo.us>
2019-06-17 18:14:08 +02:00
d306c8fd50 change doc references to scheme[Rr]edirect -> redirect[Ss]cheme 2019-06-17 18:00:07 +02:00
8d7eccad5d New static configuration loading system.
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2019-06-17 11:48:05 +02:00
d18edd6f77 HttpOnly and Secure flags on the affinity cookie 2019-06-13 00:42:06 +02:00
cad3704efd Add Mathieu Lonjaret to maintainers 2019-06-12 23:04:03 +02:00
9a4b455c3f Correct typo in documentation on rate limiting 2019-06-12 17:22:07 +02:00
01c8798e4e Update docker api version 2019-06-12 02:54:03 +02:00
61744fba11 Prepare release v1.7.12 2019-06-12 02:54:03 +02:00
0034bef6b9 Update lego. 2019-06-12 02:54:03 +02:00
63c3ed3931 Add missing callback on close of hijacked connections 2019-06-12 02:54:03 +02:00
8a5db8a3ee Adds a log fields documentation. 2019-06-12 02:54:03 +02:00
adc2b62c22 Upgraded DataDog tracing library to 1.14.0 2019-06-12 02:54:03 +02:00
1f2fe08c33 Allow SANs for wildcards domain. 2019-06-12 02:54:03 +02:00
77b1933833 Fix Kubernetes Docs for Middlewares 2019-06-11 20:42:04 +02:00
mpl
c4df78b4b9 Add support for TCP (in kubernetes CRD)
Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
2019-06-11 15:12:04 +02:00
c1dc783512 Remove first byte wait when tcp catches all 2019-06-07 19:30:07 +02:00
518a37e776 rework loadbalancer support 2019-06-05 22:18:06 +02:00
b143101f82 Specify that Rancher provider is for 1.x only 2019-06-04 00:46:05 +02:00
2be6f4d153 Docs: improve the "reading path" for new contributers 2019-05-27 18:22:04 +02:00
ac612734c8 fix the documentation about middleware labels. 2019-05-27 18:10:04 +02:00
ffe69c67fc Entry points CLI description. 2019-05-27 18:02:06 +02:00
b3057a0ec3 Fix typo in the CRD documentation 2019-05-27 10:24:04 +02:00
mpl
563f059e73 Fix typos in data collection message 2019-05-21 17:12:09 +02:00
6bbe7262ef documentation remove traefik.port. 2019-05-20 11:14:04 +02:00
55a1a81010 Fixed readme misspelling 2019-05-17 13:40:04 +02:00
97ec764db7 Fix typos in documentation 2019-05-17 13:32:05 +02:00
mpl
f6df556eb0 API: expose runtime representation
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
2019-05-16 10:58:06 +02:00
5cd9396dae Fix regression on plumbing scripts for developer usages 2019-05-14 19:58:04 +02:00
886a6bdbe0 Add shell script linting with shellcheck for better portability 2019-05-10 17:24:06 +02:00
ab60e702d2 Remove old docs folder. 2019-05-10 10:16:05 +02:00
17141b3589 Remove timeout/interval from the ACME Provider 2019-05-10 09:58:05 +02:00
8f23243cb8 Add note about ACME renewal 2019-05-09 15:22:05 +02:00
c2345c6e9a Don't add TCP proxy when error occurs during creation. 2019-05-09 14:30:06 +02:00
2617de2cdd Clarify docs with labels in Swarm Mode 2019-05-09 08:32:04 +02:00
9cf6827ccc Added support for Haystack tracing 2019-05-09 00:14:04 +02:00
681892148e fix: typo in routing example. 2019-05-06 18:28:04 +02:00
558452a143 Fixed spelling typo 2019-05-06 17:44:04 +02:00
5a173fa968 Allow matching with FQDN hosts with trailing periods 2019-05-06 17:16:03 +02:00
72397ef90c Fix make validate on MacOS outside container 2019-05-06 09:40:03 +02:00
79ad4b4544 Clarification of the correct pronunciation of the word "Traefik" 2019-05-03 12:14:04 +02:00
49f3713c4f docker-compose basic auth needs dubble dollar signs 2019-05-03 10:16:06 +02:00
4b5c3ccf58 Adds a reference to the middleware overview. 2019-04-29 19:36:07 +02:00
21dec70971 Fix strip prefix documentation 2019-04-29 19:00:05 +02:00
0f2b774ea1 fix: Rancher documentation. 2019-04-26 11:48:04 +02:00
e929caf15a Prepare release v1.7.11 2019-04-26 11:26:04 +02:00
8d848c3d60 fix: update lego. 2019-04-26 11:26:04 +02:00
b8b0c8f3e5 compress link fixed 2019-04-25 17:54:05 +02:00
15e78da7eb Minor fix in documentation 2019-04-24 18:04:08 +02:00
d80700810f Review documentation 2019-04-24 17:44:04 +02:00
c1de6abf23 Fix a typo in documentation 2019-04-23 17:40:04 +02:00
11f04a453e Merge branch v2.0 to master. 2019-04-17 13:49:49 +02:00
01b916eaa0 Prepare release v2.0.0-alpha4. 2019-04-17 12:10:04 +02:00
62c03b3318 k8s static configuration explanation 2019-04-17 11:48:05 +02:00
65679af61d Remove dumpcerts.sh 2019-04-17 11:36:04 +02:00
821ad31cf6 Enhance Marathon documentation 2019-04-17 10:58:04 +02:00
mpl
ea750ad813 Improve log message about redundant TLS certificate 2019-04-17 10:38:04 +02:00
3d7633f4a6 Forward all header values from forward auth response 2019-04-17 10:38:04 +02:00
d356ef1c5b Documentation Update: Hosting.de wildcard support tested 2019-04-17 10:38:04 +02:00
fce762febf Update Wildcard Domain documentation 2019-04-17 10:38:04 +02:00
535280c162 doc: middleware -> middlewares. 2019-04-17 09:34:04 +02:00
bb8a193244 log.loglevel becomes log.level in configuration 2019-04-16 15:30:09 +02:00
e6bdfa1d29 Checksum file name. 2019-04-16 14:50:05 +02:00
d1d2611665 Handle TCP in the marathon provider
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2019-04-15 18:22:07 +02:00
8389b46b5c Use the same case every where for entryPoints. 2019-04-15 11:14:05 +02:00
b9f826554c Adds a note in traefik.sample.toml 2019-04-12 19:42:03 +02:00
0750235712 fix: configuration for integration tests. 2019-04-09 17:24:05 +02:00
ee0e014617 Insensitive case for allow-empty value. 2019-04-09 16:50:06 +02:00
2e20394af4 Update the middleware documentation 2019-04-08 17:14:08 +02:00
6ab991ebf4 Fix typo in tracing docs 2019-04-08 17:00:08 +02:00
ef8894ef26 Fix EOF error 2019-04-08 12:24:05 +02:00
8b4efa1760 Get Structor version from CI env var. 2019-04-08 08:46:04 +02:00
mpl
b0b8b75258 Fix doc about removing headers 2019-04-05 15:18:04 +02:00
2e19e45aa4 Remove github.com/satori/go.uuid. 2019-04-05 12:44:03 +02:00
e1d097ea20 Add Rancher provider again 2019-04-05 12:22:04 +02:00
ed12366d52 Update tracing dependencies 2019-04-05 11:58:06 +02:00
4919b638f9 Improve the Documentation with a Reference Section 2019-04-05 11:32:04 +02:00
mpl
49563e638b Fix response modifier initial building
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2019-04-04 11:50:04 +02:00
07d0eb9ae6 Adds middlewares examples for k8s. 2019-04-03 14:32:04 +02:00
mpl
336135c392 Set X-Forwarded-* headers
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2019-04-02 16:56:04 +02:00
d2b38e6ac4 Enable CORS configuration 2019-04-02 10:40:04 +02:00
883f90dded fix: remove invalid commas. 2019-04-01 17:56:04 +02:00
58e82743f8 Update to v2.0 readme links 2019-04-01 17:14:03 +02:00
51a0994d2d Update certificates for some Docker images 2019-04-01 16:48:08 +02:00
da20db862d fix: validation system 2019-04-01 15:30:07 +02:00
d6c9f51082 Prepare release v1.7.10 2019-03-29 18:46:04 +01:00
08d7bb0d08 Remove thoas/stats fork 2019-03-29 18:46:04 +01:00
1bcb3d8cc2 Added support for configuring trace headers for DataDog tracing 2019-03-29 18:46:04 +01:00
c17de070fb fix: update lego. 2019-03-29 18:46:04 +01:00
b893374dc1 Add _FILE Environment Variable Documentation 2019-03-29 18:46:04 +01:00
fe532ed4f2 Fix two minor nits in Traefik 2.0 docs 2019-03-29 16:38:04 +01:00
7baa752a9d Merge 'v2.0.0-alpha3' into master 2019-03-29 15:38:45 +01:00
6377a19b12 Prepare release v2.0.0-alpha3. 2019-03-29 15:34:04 +01:00
ca7ea68a6a Adds notes about incompatibility between 1.X and 2.X configurations. 2019-03-29 13:12:05 +01:00
a45f285a5c Enhance middleware examples. 2019-03-29 12:34:05 +01:00
fa2c57f7cb Review Makefile 2019-03-28 11:42:06 +01:00
mpl
0779c6a139 Full ACME+CRD example
Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
2019-03-27 15:16:04 +01:00
2916f540c1 Remove BaseProvider 2019-03-27 15:02:06 +01:00
7932e317c8 Clarify that manual dnsChallenge provider works only when run as docker run -it 2019-03-27 12:08:04 +01:00
fd26cf265d Fix some minors errors on the documentation 2019-03-26 16:32:06 +01:00
mpl
3e76c25887 Document the TLS with ACME case
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
2019-03-26 11:12:04 +01:00
a0e2f47679 Update traefik.sample.toml 2019-03-25 17:20:04 +01:00
d70add10ab Fix typos in docs 2019-03-25 16:54:03 +01:00
119d0134e0 Documentation Updates: docker-compose examples 2019-03-22 15:22:08 +01:00
2e085fa253 Remove old links in readme 2019-03-22 15:16:06 +01:00
f8f7edd124 Fix panic while server shutdown 2019-03-21 15:54:07 +01:00
79ecff7b42 Fix Getting started 2019-03-21 15:34:04 +01:00
0f2c4fb5f4 Add support for tcp labels in docker provider 2019-03-21 15:22:06 +01:00
ec1952157b Fix typo in forwardauth middleware documentation 2019-03-20 16:36:10 +01:00
cd38359458 Fix dead maintainers link on the README.md 2019-03-20 16:30:07 +01:00
8a86777db8 Prepare release v2.0.0-alpha2 2019-03-19 19:24:07 +01:00
e7033071b9 change docs and adjust dashboard for v2 alpha
Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
2019-03-19 17:54:10 +01:00
mpl
f99a473436 Fix log msgs about label selector 2019-03-19 17:30:04 +01:00
mpl
c4b7e8f288 doc: kubernetes CRD provider
Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
2019-03-19 16:44:06 +01:00
f346251719 Fix new build system for experimental Docker image. 2019-03-19 12:24:04 +01:00
4c3cf87f62 New build system for experimental Docker image. 2019-03-19 11:50:03 +01:00
cb417b8077 Fix problem in aggregator provider 2019-03-19 10:04:04 +01:00
076d6abfe4 Change deploy script. 2019-03-19 09:04:04 +01:00
82308c9a53 chore: release draft mode. 2019-03-18 17:20:42 +01:00
5d35079809 Prepare release v2.0.0-alpha1 2019-03-18 15:18:04 +01:00
50e24f461c Remove IngressEndpoint in CRD provider 2019-03-18 14:38:04 +01:00
37886892c8 Adds a maintainer's page into the documentation. 2019-03-18 12:04:04 +01:00
72ffa91fe0 Clean old 2019-03-18 11:30:07 +01:00
9908137638 Enhance acme page. 2019-03-18 10:50:05 +01:00
f3ecc040c8 (re)Add update ingress status 2019-03-18 10:10:04 +01:00
e271378a97 Clean files during tests. 2019-03-18 09:34:03 +01:00
5d050ae3ac Allow user to configure traefik log 2019-03-15 15:46:06 +01:00
615ceab597 Fix lock problem in server 2019-03-15 10:04:05 +01:00
f1b085fa36 Move code to pkg 2019-03-15 09:42:03 +01:00
bd4c822670 Update anonymize/collect 2019-03-14 19:32:03 +01:00
mpl
03d5a95bde Remove everything templates related 2019-03-14 17:32:11 +01:00
e2ec64947a Update the file provider documentation 2019-03-14 16:46:05 +01:00
dabd9e2208 New packaging system. 2019-03-14 16:22:04 +01:00
4c060a78cc Custom resource definition
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2019-03-14 15:56:06 +01:00
cfaf47c8a2 Use rule HostSNI in documentation 2019-03-14 12:16:03 +01:00
87da7520de Migrate to go-acme/lego. 2019-03-14 11:04:04 +01:00
4a68d29ce2 Add a new protocol
Co-authored-by: Gérald Croës <gerald@containo.us>
2019-03-14 09:30:04 +01:00
0ca2149408 Synchronize documentation 2019-03-13 16:40:05 +01:00
0cfaab02c0 k8s integration tests 2019-03-11 14:54:05 +01:00
2d54065082 feat(webui): migrate to a work in progress webui 2019-03-08 14:08:03 +01:00
3cfbe7cf6d Travis: switch fallback dockerfile for structor 2019-03-06 16:22:06 +01:00
e2d8a95c91 Update the kubernetes provider 2019-03-06 16:22:06 +01:00
3419f9aeb9 Remove the bug command 2019-03-05 18:14:03 +01:00
ebded2cbc0 feat: new linting system. 2019-03-04 16:40:05 +01:00
fb617044e0 Update to Go1.12
Co-authored-by: juliens <julien@containo.us>
2019-03-01 11:48:04 +01:00
5a0b5470e7 Fixed dead link in README.md 2019-02-28 16:44:03 +01:00
6b4144ad10 fix: image links. 2019-02-27 14:58:04 +01:00
8f16ff9c49 chore(webui): dropping rxjs-compat in favor of pipe 2019-02-26 16:48:07 +01:00
ac6b11037d Documentation Revamp
Co-authored-by: jbdoumenjou <jb.doumenjou@gmail.com>
2019-02-26 14:50:07 +01:00
848e45c22c Adds Kubernetes provider support
Co-authored-by: Julien Salleyron <julien@containo.us>
2019-02-21 23:08:05 +01:00
2c0bf335ba Update Structor to v1.4.0 2019-02-21 10:38:03 +01:00
aef24dd74b Instana tracer implementation 2019-02-18 16:52:03 +01:00
c2c6aee18a Applies new goimports recommendations. 2019-02-18 07:52:03 +01:00
6451b47621 Prepare release v1.7.9 2019-02-13 17:26:04 +01:00
2b2cfdfb32 Updates of Lego. 2019-02-13 17:26:04 +01:00
5f4d440493 Fixes the display of the associativity rules. 2019-02-13 17:26:04 +01:00
5f0451affe Fixed curl example 2019-02-13 17:26:04 +01:00
156f6b8d3c Add Tracing Header Context Name option for Jaeger 2019-02-13 17:26:04 +01:00
f0ee2890b2 app-root on non-explicit path include "/" in the redirect 2019-02-13 17:26:04 +01:00
16c283c91a Update default value in docs of buckets for Prometheus 2019-02-13 17:26:04 +01:00
db13dbdf46 fix missing trailers with retry 2019-02-13 17:26:04 +01:00
06905cb14a handle errors when working with rancher 2019-02-13 17:26:04 +01:00
6ea9c4dd3f doc: update change log. 2019-02-13 17:26:04 +01:00
c5c8382742 chore(webui): format code with prettier 2019-02-05 18:18:04 +01:00
115ddc6a4a refactor: applies linting. 2019-02-05 17:10:03 +01:00
54ca0ce34f chore(lint): include lint in build process 2019-02-05 16:50:05 +01:00
f19c497621 Updates Backoff 2019-02-04 16:38:08 +01:00
0561a20c06 chore(webui): upgrade angular cli version 2019-02-01 16:30:06 +01:00
162490dadf chore(webui): ignore target/dependencies in docker copy 2019-02-01 00:20:04 +01:00
30087794ba chore(webui): update docker node version 2019-02-01 00:04:04 +01:00
9ebe3c38b2 New rule syntax
Co-authored-by: jbdoumenjou <jb.doumenjou@gmail.com>
2019-01-30 16:24:07 +01:00
7155f0d50d Prepare release v1.7.8 2019-01-30 14:00:05 +01:00
75e05ca142 Check for dynamic tls updates on configuration preload 2019-01-30 14:00:05 +01:00
5d4423910d Fixes docker swarm mode refresh second for KV. 2019-01-30 14:00:05 +01:00
0de1ff8634 Support Datadog tracer priority sampling 2019-01-30 14:00:05 +01:00
e5fb1ffeb7 Updates lego. 2019-01-30 14:00:05 +01:00
8c53318dac Generic awsvpc support, not just Fargate 2019-01-30 14:00:05 +01:00
0d6f259adc Cache exising task definitions to avoid rate limiting 2019-01-30 14:00:05 +01:00
85ab0e6e70 Minor formatting fixes 2019-01-30 14:00:05 +01:00
a18294d417 Route priorities: document minimum priority value 2019-01-30 14:00:05 +01:00
fecd0ca391 Note about quotes for entrypoint definition with docker-compose 2019-01-30 14:00:05 +01:00
97bd92c76f Assert that test timeout service is ready. 2019-01-30 14:00:05 +01:00
rbq
49b89c30d8 Allow Træfik to update Ingress status 2019-01-30 14:00:05 +01:00
8228a8e3f7 doc: more detailed info about Google Cloud DNS. 2019-01-30 14:00:05 +01:00
78be3df99a Tested wildcard ACME challenge with DNSimple 2019-01-30 14:00:05 +01:00
2f0db9a974 doc missing information about statistics parameter 2019-01-30 14:00:05 +01:00
227fab3867 fix: update lego. 2019-01-30 14:00:05 +01:00
9537449b07 Happy 2019 2019-01-30 14:00:05 +01:00
246b245959 Adds Marathon support.
Co-authored-by: Julien Salleyron <julien@containo.us>
2019-01-29 17:54:05 +01:00
a433e469cc SchemeRedirect Middleware
Co-authored-by: jbdoumenjou <jb.doumenjou@gmail.com>
2019-01-22 08:30:04 +01:00
04958c6951 Adds default rule system on Docker provider.
Co-authored-by: Julien Salleyron <julien@containo.us>
2019-01-21 19:06:02 +01:00
b54c956c5e Adds Docker provider support
Co-authored-by: Julien Salleyron <julien@containo.us>
2019-01-18 15:18:04 +01:00
8735263930 Enables the use of elements declared in other providers 2019-01-15 14:28:04 +01:00
a79d6aa669 Add forwarded headers on entry point configuration 2019-01-15 09:44:03 +01:00
7efafa5a2c Migrates the pass client tls cert middleware 2019-01-09 11:28:04 +01:00
0b436563bd refactor: remove old acme provider. 2019-01-08 14:32:04 +01:00
5d379dc3e3 Prepare release v1.7.7 2019-01-08 14:32:04 +01:00
8c60774c6a Add Pass TLS Cert Issuer and Domain Component 2019-01-08 14:32:04 +01:00
9b2423aaba Update Lego 2019-01-08 14:32:04 +01:00
fc8c24e987 Retry middleware : store headers per attempts and propagate them when responding. 2019-01-08 14:32:04 +01:00
d7bd69714d Redirection status codes for methods different than GET 2019-01-08 14:32:04 +01:00
099bbb8be7 Skip TLS section with no secret in Kubernetes ingress 2019-01-08 14:32:04 +01:00
c29a69a60d Harden Traefik systemd service 2019-01-08 14:32:04 +01:00
69e4f35d9a Test and exit for jq error before domain loop 2019-01-08 14:32:04 +01:00
ff40467207 Fix html-proofer and nokogiri version 2019-01-08 14:32:04 +01:00
190c6c661f Letsencrypt - Add info on httpreq format 2019-01-08 14:32:04 +01:00
e633799c14 Proposing a small update to documentation 2019-01-08 14:32:04 +01:00
f7c6c562a5 Allow empty path with App-root annotation 2019-01-08 14:32:04 +01:00
bc6e9d5042 Check for watched namespace before getting kubernetes objects 2019-01-08 14:32:04 +01:00
a0b1d54012 kubernetes: sort and uniq TLS secrets 2019-01-08 14:32:04 +01:00
60b5286f8c Check for anchors (hashes) for external links on the documentation 2019-01-08 14:32:04 +01:00
aa3ea17a8f Rephrase the traefik.backend definition in documentation 2019-01-08 14:32:04 +01:00
698621f127 Update broken link for Docker service constraints 2019-01-08 14:32:04 +01:00
906f4fe8f7 dep: fix constraint with dep >= 0.5.0 2019-01-07 16:48:03 +01:00
ddf199566c Prepare release v1.7.6 2018-12-17 15:18:03 +01:00
a47d770e71 Fix label segmentation when using custom prefix 2018-12-17 15:18:03 +01:00
057498ed01 Support canary weight for external name service 2018-12-05 14:32:03 +01:00
fa562dc916 Query params in health check 2018-12-05 14:32:03 +01:00
0be895febb frame-deny should be set to true to enable the header 2018-12-05 14:32:03 +01:00
11a0078966 Labels parser. 2018-12-04 14:24:04 +01:00
92f8e5cd3f Prepare release v1.7.5 2018-12-04 11:42:03 +01:00
5b3762be08 Implement Case-insensitive SNI matching 2018-12-04 11:42:03 +01:00
3b01488c8d [docker backend] - Add config flag to set refreshSeconds for swarmmode ticker 2018-12-04 11:42:03 +01:00
2f65572247 Filter ECS tasks by LastStatus before adding to list of service tasks 2018-12-04 11:42:03 +01:00
e42ddfc3d6 Log configuration errors from providers and keeps listening 2018-12-04 11:42:03 +01:00
d63636243c Fix upgrade flaeg 2018-12-04 11:42:03 +01:00
a0b9c0d007 Fix unannonced trailers problem when body is empty 2018-12-04 11:42:03 +01:00
1f7a4174ba Matcher associativity rule. 2018-12-04 11:42:03 +01:00
761c58e040 Add a "Security Consideration" section in the Docker's backend section of the documentation 2018-12-04 11:42:03 +01:00
01c3d3905c Remove Deprecated StorageFile 2018-12-03 11:54:04 +01:00
c815a732ef Migrate rest provider 2018-12-03 11:32:05 +01:00
5d91c7e15c Remove old global config and use new static config 2018-11-27 17:42:04 +01:00
c39d21c178 Update swarm mode endpoint 2018-11-26 11:02:05 +01:00
b6498cdcbc Cherry pick v1.7 into master 2018-11-19 16:40:03 +01:00
a09dfa3ce1 Dynamic Configuration Refactoring 2018-11-14 10:18:03 +01:00
d3ae88f108 Merge tag 'v1.7.4' into master 2018-10-30 12:34:00 +01:00
6a55772cda Rename Docker_Acme.md to Readme.md 2018-10-16 10:54:03 +02:00
6dcb51a4bd Merge 'v1.7.3' into master 2018-10-15 13:13:48 +02:00
94a6f8426b Merge branch 'v1.7' into master 2018-10-09 11:19:55 +02:00
32f7fb8bff Make Zipkin trace rate configurable 2018-10-09 10:18:02 +02:00
51650c1412 Add Gerald, Jean-Baptiste and Damien to maintainers 2018-10-08 16:46:03 +02:00
05f052b092 Merge branch 'v1.7.2' into master 2018-10-05 13:51:23 +02:00
1431ac5751 Basic Auth custom realm 2018-10-04 16:46:03 +02:00
f9689d1562 fix broken links in readme.md 2018-10-03 08:56:03 +02:00
5eae95ee46 Add master overhaul notice 2018-10-01 16:06:04 +02:00
5acd43efaf Add health check timeout parameter 2018-09-27 20:16:03 +02:00
f10516deb7 Merge v1.7.0 into master 2018-09-25 15:06:03 +02:00
fdf14cd101 Merge 'v1.7' into master 2018-09-18 15:48:28 +02:00
bd4846aa9c Merge branch 'v1.7' into master 2018-09-07 19:33:01 +02:00
4055654e9b Merge branch 'v1.7' into master 2018-08-28 17:04:39 +02:00
00728e711c IPStrategy for selecting IP in whitelist 2018-08-24 16:20:03 +02:00
1ec4e03738 Remove etcd v2 2018-08-07 19:12:03 +02:00
9cd47dd2aa Small code enhancements 2018-08-06 20:00:03 +02:00
015cd7a3d0 Remove deprecated elements 2018-08-06 17:20:03 +02:00
e92b01c528 Merge current v1.7 into master 2018-08-06 14:58:03 +02:00
dad0e75121 Merge branch 'v1.7' into master 2018-08-02 17:28:44 +02:00
c159e316be Migrate Compress from bool to struct 2018-08-02 17:14:03 +02:00
43d22d7a2f Small code enhancements on providers 2018-08-01 16:58:03 +02:00
6f6ebb8025 Updates for jaeger tracing client. 2018-08-01 13:52:03 +02:00
4809476c19 Move prometheusState.reset() to test file. 2018-08-01 11:20:03 +02:00
d727761e5d No need for npm progress=false 2018-08-01 10:56:03 +02:00
8627256e74 Remove Deprecated Step 1 2018-07-31 19:28:03 +02:00
1d53077fc7 Complete maintainers processes 2018-07-31 08:50:03 +02:00
4b480ece13 Complete maintainers processes 2018-07-27 16:28:03 +02:00
a23a9228da Merge branch 'v1.7' into master 2018-07-25 17:58:56 +02:00
f611ef0edd Removes templates 2018-07-23 11:56:02 +02:00
d8f69700e6 Merge branch 'v1.7' into master 2018-07-19 17:33:28 +02:00
3bb04142f3 fix: some DNS provider link. 2018-07-18 13:30:03 +02:00
d53fbb9d7f Merge branch 'v1.7' into master 2018-07-17 19:12:09 +02:00
5ce4a2d05c Add HTTP authentification to influxdb metric backend 2018-07-11 17:50:03 +02:00
7205 changed files with 364828 additions and 1479893 deletions

View File

@ -1,3 +1,5 @@
dist/
!dist/traefik
!dist/**/traefik
site/
vendor/
.idea/

2
.gitattributes vendored
View File

@ -1 +1 @@
# vendor/github.com/xenolf/lego/providers/dns/cloudxns/cloudxns.go eol=crlf
# vendor/github.com/go-acme/lego/providers/dns/cloudxns/cloudxns.go eol=crlf

24
.github/CODEOWNERS vendored
View File

@ -1,24 +0,0 @@
provider/kubernetes/** @containous/kubernetes
provider/rancher/** @containous/rancher
provider/marathon/** @containous/marathon
provider/docker/** @containous/docker
docs/user-guide/kubernetes.md @containous/kubernetes
docs/user-guide/marathon.md @containous/marathon
docs/user-guide/swarm.md @containous/docker
docs/user-guide/swarm-mode.md @containous/docker
docs/configuration/backends/docker.md @containous/docker
docs/configuration/backends/kubernetes.md @containous/kubernetes
docs/configuration/backends/marathon.md @containous/marathon
docs/configuration/backends/rancher.md @containous/rancher
examples/k8s/ @containous/kubernetes
examples/compose-k8s.yaml @containous/kubernetes
examples/k8s.namespace.yaml @containous/kubernetes
examples/compose-rancher.yml @containous/rancher
examples/compose-marathon.yml @containous/marathon
vendor/github.com/gambol99/go-marathon @containous/marathon
vendor/github.com/rancher @containous/rancher
vendor/k8s.io/ @containous/kubernetes

3
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,3 @@
# These are supported funding model platforms
github: traefik

View File

@ -1,29 +1,33 @@
<!-- PLEASE FOLLOW THE ISSUE TEMPLATE TO HELP TRIAGE AND SUPPORT! -->
### Do you want to request a *feature* or report a *bug*?
<!--
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:
- Stack Overflow (using the "traefik" tag): https://stackoverflow.com/questions/tagged/traefik
- the Traefik community Slack channel: https://slack.traefik.io
- the Traefik community forum: https://community.traefik.io/
-->
### Do you want to request a *feature* or report a *bug*?
Bug
<!--
If you intend to ask a support question: DO NOT FILE AN ISSUE.
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/.
-->
### What did you do?
<!--
HOW TO WRITE A GOOD ISSUE?
HOW TO WRITE A GOOD BUG REPORT?
- Respect the issue template as much as possible.
- If possible, use the command `traefik bug`. See https://www.youtube.com/watch?v=Lyz62L8m93I.
- The title should be short and descriptive.
- Explain the conditions which led you to report this issue: the context.
- The context should lead to something, an idea or a problem that youre facing.
@ -43,13 +47,12 @@ HOW TO WRITE A GOOD ISSUE?
### Output of `traefik version`: (_What version of Traefik are you using?_)
<!--
`latest` is not considered as a valid version.
For the Traefik Docker image:
docker run [IMAGE] version
ex: docker run traefik version
For the alpine Traefik Docker image:
docker run [IMAGE] traefik version
ex: docker run traefik traefik version
-->
```
@ -61,12 +64,13 @@ For the alpine Traefik Docker image:
```toml
# (paste your configuration here)
```
<!--
Add more configuration information here.
-->
### If applicable, please paste the log output at DEBUG level (`--logLevel=DEBUG` switch)
### If applicable, please paste the log output in DEBUG level (`--log.level=DEBUG` switch)
```
(paste your output here)

View File

@ -1,78 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
---
<!--
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:
- Stack Overflow (using the "traefik" tag): https://stackoverflow.com/questions/tagged/traefik
- the Traefik community Slack channel: https://slack.traefik.io
-->
### Do you want to request a *feature* or report a *bug*?
Bug
### What did you do?
<!--
HOW TO WRITE A GOOD BUG REPORT?
- Respect the issue template as much as possible.
- If possible, use the command `traefik bug`. See https://www.youtube.com/watch?v=Lyz62L8m93I.
- The title should be short and descriptive.
- Explain the conditions which led you to report this issue: the context.
- The context should lead to something, an idea or a problem that youre facing.
- Remain clear and concise.
- Format your messages to help the reader focus on what matters and understand the structure of your message, use Markdown syntax https://help.github.com/articles/github-flavored-markdown
-->
### What did you expect to see?
### What did you see instead?
### Output of `traefik version`: (_What version of Traefik are you using?_)
<!--
For the Traefik Docker image:
docker run [IMAGE] version
ex: docker run traefik version
For the alpine Traefik Docker image:
docker run [IMAGE] traefik version
ex: docker run traefik traefik version
-->
```
(paste your output here)
```
### What is your environment & configuration (arguments, toml, provider, platform, ...)?
```toml
# (paste your configuration here)
```
<!--
Add more configuration information here.
-->
### If applicable, please paste the log output in DEBUG level (`--logLevel=DEBUG` switch)
```
(paste your output here)
```

View File

@ -1,37 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
---
<!--
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:
- Stack Overflow (using the "traefik" tag): https://stackoverflow.com/questions/tagged/traefik
- the Traefik community Slack channel: https://slack.traefik.io
-->
### Do you want to request a *feature* or report a *bug*?
Feature
### What did you expect to see?
<!--
HOW TO WRITE A GOOD ISSUE?
- Respect the issue template as much as possible.
- If possible, use the command `traefik bug`. See https://www.youtube.com/watch?v=Lyz62L8m93I.
- The title should be short and descriptive.
- Explain the conditions which led you to report this issue: the context.
- The context should lead to something, an idea or a problem that youre facing.
- Remain clear and concise.
- Format your messages to help the reader focus on what matters and understand the structure of your message, use Markdown syntax https://help.github.com/articles/github-flavored-markdown
-->

82
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@ -0,0 +1,82 @@
name: Bug Report (Traefik)
description: Create a report to help us improve.
body:
- type: checkboxes
id: terms
attributes:
label: Welcome!
description: |
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/).
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.traefik.io) and didn't find any.
required: true
- type: textarea
attributes:
label: What did you do?
description: |
How to write a good bug report?
- Respect the issue template as much as possible.
- The title should be short and descriptive.
- Explain the conditions which led you to report this issue: the context.
- The context should lead to something, an idea or a problem that youre facing.
- Remain clear and concise.
- Format your messages to help the reader focus on what matters and understand the structure of your message, use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown)
placeholder: What did you do?
validations:
required: true
- type: textarea
attributes:
label: What did you see instead?
placeholder: What did you see instead?
validations:
required: true
- type: textarea
attributes:
label: What version of Traefik are you using?
description: |
`latest` is not considered as a valid version.
Output of `traefik version`.
For the Traefik Docker image (`docker run [IMAGE] version`), example:
```console
$ docker run traefik version
```
placeholder: Paste your output here.
validations:
required: true
- type: textarea
attributes:
label: What is your environment & configuration?
description: arguments, toml, provider, platform, ...
placeholder: Add information here.
value: |
```yaml
# (paste your configuration here)
```
Add more configuration information here.
validations:
required: true
- type: textarea
attributes:
label: If applicable, please paste the log output in DEBUG level
description: "`--log.level=DEBUG` switch."
placeholder: Paste your output here.
validations:
required: false

8
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Traefik Community Support
url: https://community.traefik.io/
about: If you have a question, or are looking for advice, please post on our Discuss forum! The community loves to chime in to help. Happy Coding!
- name: Traefik Helm Chart Issues
url: https://github.com/traefik/traefik-helm-chart
about: Are you submitting an issue or feature enhancement for the Traefik helm chart? Please post in the traefik-helm-chart GitHub Issues.

View File

@ -0,0 +1,33 @@
name: Feature Request (Traefik)
description: Suggest an idea for this project.
body:
- type: checkboxes
id: terms
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.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.traefik.io) and didn't find any.
required: true
- type: textarea
attributes:
label: What did you expect to see?
description: |
How to write a good issue?
- Respect the issue template as much as possible.
- The title should be short and descriptive.
- Explain the conditions which led you to report this issue: the context.
- The context should lead to something, an idea or a problem that youre facing.
- Remain clear and concise.
- Format your messages to help the reader focus on what matters and understand the structure of your message, use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown)
placeholder: What did you expect to see?
validations:
required: true

View File

@ -1,18 +1,18 @@
<!--
PLEASE READ THIS MESSAGE.
HOW TO WRITE A GOOD PULL REQUEST?
Documentation:
- for Traefik v2: use branch v2.11 (fixes only)
- for Traefik v3: use branch v3.5
- Make it small.
- Do only one thing.
- Avoid re-formatting.
- Make sure the code builds.
- Make sure all tests pass.
- Add tests.
- Write useful descriptions and titles.
- Address review comments in terms of additional commits.
- Do not amend/squash existing ones unless the PR is trivial.
- Read the contributing guide: https://github.com/containous/traefik/blob/master/CONTRIBUTING.md.
Bug:
- for Traefik v2: use branch v2.11 (security fixes only)
- for Traefik v3: use branch v3.5
Enhancements:
- use branch master
HOW TO WRITE A GOOD PULL REQUEST? https://doc.traefik.io/traefik/contributing/submitting-pull-requests/
-->

81
.github/workflows/build.yaml vendored Normal file
View File

@ -0,0 +1,81 @@
name: Build Binaries
on:
pull_request:
branches:
- '*'
paths-ignore:
- 'docs/**'
- '**.md'
- 'script/gcg/**'
env:
GO_VERSION: '1.24'
CGO_ENABLED: 0
jobs:
build-webui:
uses: ./.github/workflows/template-webui.yaml
build:
runs-on: ubuntu-latest
strategy:
matrix:
os: [ darwin, freebsd, linux, openbsd, windows ]
arch: [ amd64, arm64 ]
include:
- os: freebsd
arch: 386
- os: linux
arch: 386
- os: linux
arch: arm
goarm: 6
- os: linux
arch: arm
goarm: 7
- os: linux
arch: ppc64le
- os: linux
arch: riscv64
- os: linux
arch: s390x
- os: openbsd
arch: 386
- os: windows
arch: 386
needs:
- build-webui
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
env:
ImageOS: ${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.goarm }}
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Artifact webui
uses: actions/download-artifact@v4
with:
name: webui.tar.gz
- name: Untar webui
run: |
tar xvf webui.tar.gz
rm webui.tar.gz
- name: Build
env:
GOOS: ${{ matrix.os }}
GOARCH: ${{ matrix.arch }}
GOARM: ${{ matrix.goarm }}
run: make binary

25
.github/workflows/check_doc.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: Check Documentation
on:
pull_request:
branches:
- '*'
jobs:
docs:
name: Check, verify and build documentation
runs-on: ubuntu-latest
steps:
- name: Check out code
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
View 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}}"

53
.github/workflows/documentation.yml vendored Normal file
View File

@ -0,0 +1,53 @@
name: Build and Publish Documentation
on:
workflow_dispatch: {}
push:
branches:
- master
- v*
env:
STRUCTOR_VERSION: v1.13.2
MIXTUS_VERSION: v0.4.1
jobs:
docs:
name: Doc Process
runs-on: ubuntu-latest
if: github.repository == 'traefik/traefik'
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Install Structor ${{ env.STRUCTOR_VERSION }}
run: curl -sSfL https://raw.githubusercontent.com/traefik/structor/master/godownloader.sh | sh -s -- -b $HOME/bin ${STRUCTOR_VERSION}
- name: Install Seo-doc
run: curl -sSfL https://raw.githubusercontent.com/traefik/seo-doc/master/godownloader.sh | sh -s -- -b "${HOME}/bin"
- name: Install Mixtus ${{ env.MIXTUS_VERSION }}
run: curl -sSfL https://raw.githubusercontent.com/traefik/mixtus/master/godownloader.sh | sh -s -- -b $HOME/bin ${MIXTUS_VERSION}
- name: Build documentation
run: |
STRUCTOR_LATEST_TAG=$(curl -s https://api.github.com/repos/traefik/traefik/releases/latest | jq -r '.tag_name')
$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
- name: Apply seo
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=traefik --src-repo-name=traefik
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN_REPO }}

70
.github/workflows/experimental.yaml vendored Normal file
View File

@ -0,0 +1,70 @@
name: Build experimental image on branch
on:
push:
branches:
- master
- v*
env:
GO_VERSION: '1.24'
CGO_ENABLED: 0
jobs:
build-webui:
if: github.repository == 'traefik/traefik'
uses: ./.github/workflows/template-webui.yaml
experimental:
if: github.repository == 'traefik/traefik'
name: Build experimental image on branch
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
env:
ImageOS: ${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.goarm }}
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Build
run: make generate binary
- name: Branch name
run: echo ${GITHUB_REF##*/}
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Artifact webui
uses: actions/download-artifact@v4
with:
name: webui.tar.gz
- name: Untar webui
run: |
tar xvf webui.tar.gz
rm webui.tar.gz
- name: Build docker experimental image
env:
DOCKER_BUILDX_ARGS: "--push"
run: |
make multi-arch-image-experimental-${GITHUB_REF##*/}

138
.github/workflows/release.yaml vendored Normal file
View File

@ -0,0 +1,138 @@
name: Release
on:
push:
tags:
- 'v*.*.*'
env:
GO_VERSION: '1.24'
CGO_ENABLED: 0
VERSION: ${{ github.ref_name }}
TRAEFIKER_EMAIL: "traefiker@traefik.io"
CODENAME: chabichou
jobs:
build-webui:
if: github.ref_type == 'tag' && github.repository == 'traefik/traefik'
uses: ./.github/workflows/template-webui.yaml
build:
if: github.ref_type == 'tag' && github.repository == 'traefik/traefik'
runs-on: ubuntu-latest
strategy:
matrix:
os: [ linux-amd64, linux-386, linux-arm, linux-arm64, linux-ppc64le, linux-s390x, linux-riscv64, darwin, windows-amd64, windows-arm64, windows-386, freebsd, openbsd ]
needs:
- build-webui
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
env:
# Ensure cache consistency on Linux, see https://github.com/actions/setup-go/pull/383
ImageOS: ${{ matrix.os }}
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Artifact webui
uses: actions/download-artifact@v4
with:
name: webui.tar.gz
- name: Untar webui
run: |
tar xvf webui.tar.gz
rm webui.tar.gz
- name: Go generate
run: go generate
- name: Generate goreleaser file
run: |
GORELEASER_CONFIG_FILE_PATH=$(go run ./internal/release "${{ matrix.os }}")
echo "GORELEASER_CONFIG_FILE_PATH=$GORELEASER_CONFIG_FILE_PATH" >> $GITHUB_ENV
- name: Build with goreleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
# 'latest', 'nightly', or a semver
version: '~> v2'
args: release --clean --timeout="90m" --config "${{ env.GORELEASER_CONFIG_FILE_PATH }}"
- name: Artifact binaries
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}-binaries
path: |
dist/**/*_checksums.txt
dist/**/*.tar.gz
dist/**/*.zip
retention-days: 1
release:
if: github.ref_type == 'tag' && github.repository == 'traefik/traefik'
runs-on: ubuntu-latest
needs:
- build
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Artifact webui
uses: actions/download-artifact@v4
with:
name: webui.tar.gz
- name: Untar webui
run: |
tar xvf webui.tar.gz
rm webui.tar.gz
- name: Retrieve the secret and decode it to a file
env:
TRAEFIKER_RSA: ${{ secrets.TRAEFIKER_RSA }}
run: |
mkdir -p ~/.ssh
echo "${TRAEFIKER_RSA}" | base64 --decode > ~/.ssh/traefiker_rsa
- name: Download All Artifacts
uses: actions/download-artifact@v4
with:
path: dist/
pattern: "*-binaries"
merge-multiple: true
- name: Publish Release
env:
GH_TOKEN: ${{ github.token }}
run: |
cat dist/**/*_checksums.txt >> "dist/traefik_${VERSION}_checksums.txt"
rm dist/**/*_checksums.txt
tar cfz "dist/traefik-${VERSION}.src.tar.gz" \
--exclude-vcs \
--exclude .idea \
--exclude .travis \
--exclude .semaphoreci \
--exclude .github \
--exclude dist .
chown -R "$(id -u)":"$(id -g)" dist/
gh release create ${VERSION} ./dist/**/traefik*.{zip,tar.gz} ./dist/traefik*.{tar.gz,txt} --repo traefik/traefik --title ${VERSION} --notes ${VERSION} --latest=false
./script/deploy.sh

View File

@ -0,0 +1,26 @@
name: Sync Docker Images
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *" # Run every day
jobs:
sync:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
if: github.repository == 'traefik/traefik'
steps:
- uses: actions/checkout@v4
- uses: imjasonh/setup-crane@v0.4
- name: Sync
run: |
EXCLUDED_TAGS="1.7.9-alpine v1.0.0-beta.392 v1.0.0-beta.404 v1.0.0-beta.704 v1.0.0-rc1 v1.7.9-alpine"
EXCLUDED_REGEX=$(echo $EXCLUDED_TAGS | sed 's/ /|/g')
diff <(crane ls traefik) <(crane ls ghcr.io/traefik/traefik) | grep '^<' | awk '{print $2}' | while read -r tag; do [[ "$tag" =~ ^($EXCLUDED_REGEX)$ ]] || (echo "Processing image: traefik:$tag"; crane cp "traefik:$tag" "ghcr.io/traefik/traefik:$tag"); done
crane cp traefik:latest ghcr.io/traefik/traefik:latest

40
.github/workflows/template-webui.yaml vendored Normal file
View File

@ -0,0 +1,40 @@
name: Build Web UI
on:
workflow_call: {}
jobs:
build-webui:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Enable corepack
run: corepack enable
- 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: |
tar czvf webui.tar.gz ./webui/static/
- name: Artifact webui
uses: actions/upload-artifact@v4
with:
name: webui.tar.gz
path: webui.tar.gz
retention-days: 1

41
.github/workflows/test-conformance.yaml vendored Normal file
View File

@ -0,0 +1,41 @@
name: Test K8s Gateway API conformance
on:
pull_request:
branches:
- '*'
paths:
- '.github/workflows/test-conformance.yaml'
- 'pkg/provider/kubernetes/gateway/**'
- 'integration/fixtures/k8s-conformance/**'
- 'integration/k8s_conformance_test.go'
env:
GO_VERSION: '1.23'
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: |
mkdir webui/static
touch webui/static/index.html
- name: K8s Gateway API conformance test and report
run: |
make test-gateway-api-conformance
git diff --exit-code

109
.github/workflows/test-integration.yaml vendored Normal file
View File

@ -0,0 +1,109 @@
name: Test Integration
on:
pull_request:
branches:
- '*'
paths-ignore:
- 'docs/**'
- '**.md'
- 'script/gcg/**'
env:
GO_VERSION: '1.24'
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 }}
check-latest: true
- name: Avoid generating webui
run: |
mkdir webui/static
touch webui/static/index.html
- name: Build binary
run: make binary-linux-amd64
- name: Save go cache build
uses: actions/cache/save@v4
with:
path: |
~/.cache/go-build
key: ${{ runner.os }}-go-build-cache-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}
- name: Artifact traefik binary
uses: actions/upload-artifact@v4
with:
name: traefik
path: ./dist/linux/amd64/traefik
retention-days: 1
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 }}
check-latest: true
- name: Avoid generating webui
run: |
mkdir webui/static
touch webui/static/index.html
- name: Download traefik binary
uses: actions/download-artifact@v4
with:
name: traefik
path: ./dist/linux/amd64/
- name: Make binary executable
run: chmod +x ./dist/linux/amd64/traefik
- name: Restore go cache build
uses: actions/cache/restore@v4
with:
path: |
~/.cache/go-build
key: ${{ runner.os }}-go-build-cache-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}
- name: Generate go test Slice
id: test_split
uses: hashicorp-forge/go-test-split-action@v2.0.0
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

93
.github/workflows/test-unit.yaml vendored Normal file
View File

@ -0,0 +1,93 @@
name: Test Unit
on:
pull_request:
branches:
- '*'
paths-ignore:
- 'docs/**'
- '**.md'
- 'script/gcg/**'
env:
GO_VERSION: '1.24'
jobs:
generate-packages:
name: List Go Packages
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
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 }}
check-latest: true
- name: Generate matrix
id: set-matrix
run: |
matrix_output=$(go run ./internal/testsci/genmatrix.go)
echo "$matrix_output"
echo "$matrix_output" >> $GITHUB_OUTPUT
test-unit:
runs-on: ubuntu-latest
needs: generate-packages
strategy:
matrix:
package: ${{ fromJson(needs.generate-packages.outputs.matrix) }}
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 }}
check-latest: true
- name: Avoid generating webui
run: |
mkdir webui/static
touch webui/static/index.html
- name: Tests
run: |
go test -v -parallel 8 ${{ matrix.package.group }}
test-ui-unit:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Enable corepack
run: corepack enable
- 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
working-directory: ./webui
env:
VITE_APP_BASE_API_URL: "/api"
run: |
yarn install
yarn test:unit:ci

94
.github/workflows/validate.yaml vendored Normal file
View File

@ -0,0 +1,94 @@
name: Validate
on:
pull_request:
branches:
- '*'
env:
GO_VERSION: '1.24'
GOLANGCI_LINT_VERSION: v2.0.2
MISSPELL_VERSION: v0.6.0
jobs:
lint:
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 }}
check-latest: true
- name: Avoid generating webui
run: |
mkdir webui/static
touch webui/static/index.html
- name: golangci-lint
uses: golangci/golangci-lint-action@v7
with:
version: "${{ env.GOLANGCI_LINT_VERSION }}"
validate:
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 }}
check-latest: true
- name: Install misspell ${{ env.MISSPELL_VERSION }}
run: curl -sfL https://raw.githubusercontent.com/golangci/misspell/HEAD/install-misspell.sh | sh -s -- -b $(go env GOPATH)/bin ${MISSPELL_VERSION}
- name: Avoid generating webui
run: |
mkdir webui/static
touch webui/static/index.html
- name: Validate
run: make validate-files
validate-generate:
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 }}
check-latest: true
- name: go generate
run: |
make generate
git diff --exit-code
- name: go mod tidy
run: |
go mod tidy
git diff --exit-code
- name: make generate-crd
run: |
make generate-crd
git diff --exit-code

23
.gitignore vendored
View File

@ -1,15 +1,22 @@
/dist
/autogen/genstatic/gen.go
.idea/
.intellij/
*.iml
.vscode/
.DS_Store
/dist
/webui/.tmp/
/site/
/docs/site/
/autogen/
/traefik
/traefik.toml
/static/
/webui/.tmp/
.vscode/
/site/
/traefik.yml
*.log
*.exe
.DS_Store
/examples/acme/acme.json
cover.out
vendor/
plugins-storage/
plugins-local/
traefik_changelog.md
integration/tailscale.secret
integration/conformance-reports/**/experimental-dev-default-report.yaml

328
.golangci.yml Normal file
View File

@ -0,0 +1,328 @@
version: "2"
formatters:
enable:
- gci
- gofumpt
exclusions:
generated: lax
paths:
- pkg/provider/kubernetes/crd/generated/
linters:
default: all
disable:
- bodyclose # too many false-positive
- containedctx # too many false-positive
- contextcheck # too many false-positive
- cyclop # duplicate of gocyclo
- dupl # Too strict
- err113 # Too strict
- exhaustive # Not relevant
- exhaustruct # Not relevant
- forcetypeassert # Too strict
- gochecknoglobals
- gochecknoinits
- gocognit # Too strict
- gocyclo # FIXME must be fixed
- gosec # Too strict
- gosmopolitan # not relevant
- ireturn # Not relevant
- lll # Not relevant
- maintidx # kind of duplicate of gocyclo
- makezero # Not relevant
- mnd # Too strict
- nestif # Too many false-positive.
- nilnil # Not relevant
- nlreturn # Not relevant
- noctx # Too strict
- nonamedreturns # Too strict
- paralleltest # Not relevant
- prealloc # Too many false-positive.
- rowserrcheck # not relevant (SQL)
- sqlclosecheck # not relevant (SQL)
- tagliatelle # Too strict
- testpackage # Too strict
- tparallel # Not relevant
- varnamelen # Not relevant
- wrapcheck # Too strict
- wsl # Too strict
settings:
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
errcheck:
exclude-functions:
- fmt.Fprintln
forbidigo:
forbid:
- pattern: ^print(ln)?$
- pattern: ^spew\.Print(f|ln)?$
- pattern: ^spew\.Dump$
funlen:
lines: -1
statements: 120
goconst:
min-len: 3
min-occurrences: 4
gocyclo:
min-complexity: 14
godox:
keywords:
- FIXME
gomoddirectives:
toolchain-pattern: go1\.\d+\.\d+$
tool-forbidden: true
go-version-pattern: ^1\.\d+(\.0)?$
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
govet:
enable-all: true
disable:
- shadow
- fieldalignment
importas:
no-unaliased: true
alias:
- pkg: github.com/docker/compose/v2/pkg/api
alias: composeapi
# Standard Kubernetes rewrites:
- pkg: k8s.io/api/core/v1
alias: corev1
- pkg: k8s.io/api/networking/v1
alias: netv1
- pkg: k8s.io/api/networking/v1beta1
alias: netv1beta1
- pkg: k8s.io/api/admission/v1
alias: admv1
- pkg: k8s.io/api/admission/v1beta1
alias: admv1beta1
- pkg: k8s.io/api/extensions/v1beta1
alias: extv1beta1
- pkg: k8s.io/apimachinery/pkg/apis/meta/v1
alias: metav1
- pkg: k8s.io/apimachinery/pkg/types
alias: ktypes
- pkg: k8s.io/apimachinery/pkg/api/errors
alias: kerror
- pkg: k8s.io/client-go/kubernetes
alias: kclientset
- pkg: k8s.io/client-go/informers
alias: kinformers
- pkg: k8s.io/client-go/testing
alias: ktesting
- pkg: k8s.io/apimachinery/pkg/runtime/schema
alias: kschema
- pkg: k8s.io/client-go/kubernetes/scheme
alias: kscheme
- pkg: k8s.io/apimachinery/pkg/version
alias: kversion
- pkg: k8s.io/client-go/kubernetes/fake
alias: kubefake
- pkg: k8s.io/client-go/discovery/fake
alias: discoveryfake
# Kubernetes Gateway rewrites:
- pkg: sigs.k8s.io/gateway-api/pkg/client/clientset/gateway/versioned
alias: gateclientset
- pkg: sigs.k8s.io/gateway-api/pkg/client/informers/gateway/externalversions
alias: gateinformers
- pkg: sigs.k8s.io/gateway-api/apis/v1alpha2
alias: gatev1alpha2
# Traefik Kubernetes rewrites:
- pkg: github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1
alias: traefikv1alpha1
- pkg: github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned
alias: traefikclientset
- pkg: github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/informers/externalversions
alias: traefikinformers
- pkg: github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme
alias: traefikscheme
- pkg: github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake
alias: traefikcrdfake
misspell:
locale: US
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
tagalign:
align: false
sort: true
order:
- description
- json
- toml
- yaml
- yml
- label
- label-slice-as-struct
- file
- kv
- export
testifylint:
disable:
- suite-dont-use-pkg
- require-error
- go-require
perfsprint:
err-error: true
errorf: true
sprintf1: true
strconcat: false
staticcheck:
checks:
- all
- '-SA1019'
- '-ST1000'
- '-ST1003'
- '-ST1016'
- '-ST1020'
- '-ST1021'
- '-ST1022'
- '-QF1001'
- '-QF1008' # TODO must be fixed
exclusions:
generated: lax
presets:
- comments
- std-error-handling
rules:
- path: (.+)_test.go
linters:
- canonicalheader
- fatcontext
- funlen
- goconst
- godot
- path: (.+)_test.go
text: ' always receives '
linters:
- unparam
- 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/provider/kubernetes/ingress-nginx/kubernetes.go
text: Function 'loadConfiguration' has too many statements
linters:
- funlen
- path: pkg/tracing/haystack/logger.go
linters:
- goprintffuncname
- path: pkg/tracing/tracing.go
text: printf-like formatting function 'SetErrorWithEvent' should be named 'SetErrorWithEventf'
linters:
- goprintffuncname
- path: pkg/tls/tlsmanager_test.go
text: 'SA1019: config.ClientCAs.Subjects has been deprecated since Go 1.18'
- path: pkg/types/tls_test.go
text: 'SA1019: tlsConfig.RootCAs.Subjects has been deprecated since Go 1.18'
- path: pkg/provider/kubernetes/(crd|gateway)/client.go
linters:
- interfacebloat
- path: pkg/metrics/metrics.go
linters:
- interfacebloat
- path: integration/healthcheck_test.go
text: Duplicate words \(wsp2,\) found
linters:
- dupword
- path: pkg/types/domain_test.go
text: Duplicate words \(sub\) found
linters:
- dupword
- path: pkg/provider/kubernetes/gateway/client_mock_test.go
text: 'unusedwrite: unused write to field'
linters:
- govet
- path: pkg/provider/acme/local_store.go
linters:
- musttag
- path: pkg/tls/certificate.go
text: the methods of "Certificates" use pointer receiver and non-pointer receiver.
linters:
- recvcheck
- path: pkg/config/static/static_config.go
source: 'errors.New\("Consul Catalog provider'
text: 'ST1005: error strings should not be capitalized'
- path: pkg/config/static/static_config.go
source: 'errors.New\("Consul provider'
text: 'ST1005: error strings should not be capitalized'
- path: pkg/config/static/static_config.go
source: 'errors.New\("Nomad provider'
text: 'ST1005: error strings should not be capitalized'
- path: (.+)\.go
text: 'struct-tag: unknown option ''inline'' in JSON tag'
linters:
- revive
- path: (.+)\.go
text: 'struct-tag: unknown option ''omitzero'' in TOML tag'
linters:
- revive
- path: (.+)\.go$
text: 'SA1019: http.CloseNotifier has been deprecated' # FIXME must be fixed
- path: (.+)\.go$
text: 'SA1019: cfg.(SSLRedirect|SSLTemporaryRedirect|SSLHost|SSLForceHost|FeaturePolicy) is deprecated'
- path: (.+)\.go$
text: 'SA1019: c.Providers.(ConsulCatalog|Consul|Nomad).Namespace is deprecated'
- path: (.+)\.go$
text: 'SA1019: dockertypes.ContainerNode is deprecated'
- path: pkg/provider/kubernetes/crd/kubernetes.go
text: "Function 'loadConfigurationFromCRD' has too many statements"
linters:
- funlen
- path: pkg/plugins/middlewarewasm.go
text: 'the methods of "wasmMiddlewareBuilder" use pointer receiver and non-pointer receiver.'
linters:
- recvcheck
- path: pkg/proxy/httputil/bufferpool.go
text: 'SA6002: argument should be pointer-like to avoid allocations'
paths:
- pkg/provider/kubernetes/crd/generated/
issues:
max-issues-per-linter: 0
max-same-issues: 0

View File

@ -1,42 +0,0 @@
{
"Vendor": true,
"Sort": [
"path",
"line",
"column",
"severity",
"linter"
],
"Test": true,
"Cyclo": 15,
"Enable": [
"gotypex",
"nakedret",
"vet",
"goimports",
"golint",
"ineffassign",
"gotype",
"misspell",
"structcheck",
"gosimple",
"unconvert",
"varcheck",
"errcheck",
"unused",
"deadcode",
"staticcheck"
],
"Disable": [
"gas",
"maligned",
"interfacer",
"goconst",
"gocyclo",
"vetshadow"
],
"Exclude": [
"autogen/.*"
],
"Deadline": "5m"
}

69
.goreleaser.yml.tmpl Normal file
View File

@ -0,0 +1,69 @@
project_name: traefik
version: 2
[[if .GOARCH]]
dist: "./dist/[[ .GOOS ]]-[[ .GOARCH ]]"
[[else]]
dist: "./dist/[[ .GOOS ]]"
[[end]]
builds:
- binary: traefik
main: ./cmd/traefik/
env:
- CGO_ENABLED=0
ldflags:
- -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:
- "[[ .GOOS ]]"
goarch:
[[if .GOARCH]]
- "[[ .GOARCH ]]"
[[else]]
- amd64
- '386'
- arm
- arm64
- ppc64le
- s390x
- riscv64
[[end]]
goarm:
- '7'
- '6'
ignore:
- goos: darwin
goarch: '386'
- goos: openbsd
goarch: arm
- goos: openbsd
goarch: arm64
- goos: freebsd
goarch: arm
- goos: freebsd
goarch: arm64
- goos: windows
goarch: arm
changelog:
disable: true
archives:
- id: traefik
name_template: '{{ .ProjectName }}_v{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
format: tar.gz
format_overrides:
- goos: windows
format: zip
files:
- LICENSE.md
- CHANGELOG.md
checksum:
name_template: "{{ .ProjectName }}_v{{ .Version }}_checksums.txt"
release:
disable: true

View File

@ -1,10 +0,0 @@
- repo: git://github.com/pre-commit/pre-commit-hooks
sha: 44e1753f98b0da305332abe26856c3e621c5c439
hooks:
- id: detect-private-key
- repo: git://github.com/containous/pre-commit-hooks
sha: 35e641b5107671e94102b0ce909648559e568d61
hooks:
- id: goFmt
- id: goLint
- id: goErrcheck

13
.semaphore/semaphore.yml Normal file
View File

@ -0,0 +1,13 @@
version: v1.0
name: Traefik Release - deprecated
agent:
machine:
type: f1-standard-2
os_image: ubuntu2204
blocks:
- name: 'Do nothing'
task:
jobs:
- name: 'Do nothing'
commands:
- echo "Do nothing"

View File

@ -1,4 +0,0 @@
#!/usr/bin/env bash
set -e
sudo rm -rf static

View File

@ -1,6 +0,0 @@
#!/usr/bin/env bash
set -e
if [ -n "$SHOULD_TEST" ]; then ci_retry make pull-images; fi
if [ -n "$SHOULD_TEST" ]; then ci_retry make test-integration; fi

View File

@ -1,8 +0,0 @@
#!/usr/bin/env bash
set -e
ci_retry make validate
if [ -n "$SHOULD_TEST" ]; then ci_retry make test-unit; fi
if [ -n "$SHOULD_TEST" ]; then make -j${N_MAKE_JOBS} crossbinary-default-parallel; fi

View File

@ -1,16 +0,0 @@
#!/usr/bin/env bash
set -e
export DOCKER_VERSION=17.03.1
source .semaphoreci/vars
if [ -z "${PULL_REQUEST_NUMBER}" ]; then SHOULD_TEST="-*-"; else TEMP_STORAGE=$(curl --silent https://patch-diff.githubusercontent.com/raw/containous/traefik/pull/${PULL_REQUEST_NUMBER}.diff | patch --dry-run -p1 -R); fi
if [ -n "$TEMP_STORAGE" ]; then SHOULD_TEST=$(echo "$TEMP_STORAGE" | grep -Ev '(.md|.yaml|.yml)' || :); fi
if [ -n "$SHOULD_TEST" ]; then sudo -E apt-get -yq update; fi
if [ -n "$SHOULD_TEST" ]; then sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install docker-ce=${DOCKER_VERSION}*; fi
if [ -n "$SHOULD_TEST" ]; then docker version; fi

View File

@ -1,37 +0,0 @@
#!/usr/bin/env bash
set -e
export REPO='containous/traefik'
if VERSION=$(git describe --exact-match --abbrev=0 --tags);
then
export VERSION
else
export VERSION=''
fi
export CODENAME=maroilles
export N_MAKE_JOBS=2
function ci_retry {
local NRETRY=3
local NSLEEP=5
local n=0
until [ $n -ge $NRETRY ]
do
"$@" && break
n=$[$n+1]
echo "$@ failed, attempt ${n}/${NRETRY}"
sleep $NSLEEP
done
[ $n -lt $NRETRY ]
}
export -f ci_retry

View File

@ -1,64 +0,0 @@
sudo: required
dist: trusty
git:
depth: false
services:
- docker
env:
global:
- REPO: $TRAVIS_REPO_SLUG
- VERSION: $TRAVIS_TAG
- CODENAME: maroilles
- N_MAKE_JOBS: 2
script:
- echo "Skipping tests... (Tests are executed on SemaphoreCI)"
- if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then make docs-verify; fi
before_deploy:
- >
if ! [ "$BEFORE_DEPLOY_RUN" ]; then
export BEFORE_DEPLOY_RUN=1;
sudo -E apt-get -yq update;
sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install docker-ce=${DOCKER_VERSION}*;
docker version;
make image;
if [ "$TRAVIS_TAG" ]; then
make -j${N_MAKE_JOBS} crossbinary-parallel;
tar cfz dist/traefik-${VERSION}.src.tar.gz --exclude-vcs --exclude dist .;
fi;
curl -sI https://github.com/containous/structor/releases/latest | grep -Fi Location | tr -d '\r' | sed "s/tag/download/g" | awk -F " " '{ print $2 "/structor_linux-amd64"}' | wget --output-document=$GOPATH/bin/structor -i -;
chmod +x $GOPATH/bin/structor;
structor -o containous -r traefik --dockerfile-url="https://raw.githubusercontent.com/containous/traefik/master/docs.Dockerfile" --menu.js-url="https://raw.githubusercontent.com/containous/structor/master/traefik-menu.js.gotmpl" --rqts-url="https://raw.githubusercontent.com/containous/structor/master/requirements-override.txt" --exp-branch=master --debug;
fi
deploy:
- provider: releases
api_key: ${GITHUB_TOKEN}
file: dist/traefik*
skip_cleanup: true
file_glob: true
on:
repo: containous/traefik
tags: true
- provider: script
script: sh script/deploy.sh
skip_cleanup: true
on:
repo: containous/traefik
tags: true
- provider: script
script: sh script/deploy-docker.sh
skip_cleanup: true
on:
repo: containous/traefik
- provider: pages
edge: false
github_token: ${GITHUB_TOKEN}
local_dir: site
skip_cleanup: true
on:
repo: containous/traefik
all_branches: true

Binary file not shown.

10716
CHANGELOG.md

File diff suppressed because it is too large Load Diff

View File

@ -2,17 +2,11 @@
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
@ -22,53 +16,52 @@ include:
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its 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. Representation of a project may be
further defined and clarified by project maintainers.
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.
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@containo.us
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.
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.
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.
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 inappropriate 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]
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@ -1,289 +1,11 @@
# Contributing
## Building
Here are some guidelines that should help to start contributing to the project.
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.
- [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](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)
### Method 1: Using `Docker` and `Makefile`
You need to run the `binary` target. This will create binaries for Linux platform in the `dist` folder.
```bash
$ make binary
docker build -t "traefik-dev:no-more-godep-ever" -f build.Dockerfile .
Sending build context to Docker daemon 295.3 MB
Step 0 : FROM golang:1.11-alpine
---> 8c6473912976
Step 1 : RUN go get github.com/golang/dep/cmd/dep
[...]
docker run --rm -v "/var/run/docker.sock:/var/run/docker.sock" -it -e OS_ARCH_ARG -e OS_PLATFORM_ARG -e TESTFLAGS -v "/home/user/go/src/github.com/containous/traefik/"dist":/go/src/github.com/containous/traefik/"dist"" "traefik-dev:no-more-godep-ever" ./script/make.sh generate binary
---> Making bundle: generate (in .)
removed 'gen.go'
---> Making bundle: binary (in .)
$ ls dist/
traefik*
```
### Method 2: Using `go`
##### Setting up your `go` environment
- You need `go` v1.9+
- It is recommended you clone Traefik into a directory like `~/go/src/github.com/containous/traefik` (This is the official golang workspace hierarchy, and will allow dependencies to resolve properly)
- Set your `GOPATH` and `PATH` variable to be set to `~/go` via:
```bash
export GOPATH=~/go
export PATH=$PATH:$GOPATH/bin
```
> Note: You will want to add those 2 export lines to your `.bashrc` or `.bash_profile`
- Verify your environment is setup properly by running `$ go env`. Depending on your OS and environment you should see output similar to:
```bash
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/<yourusername>/go"
GORACE=""
## more go env's will be listed
```
##### Build Traefik
Once your environment is set up and the Traefik repository cloned you can build Traefik. You need get `go-bindata` once to be able to use `go generate` command as part of the build. The steps to build are:
```bash
cd ~/go/src/github.com/containous/traefik
# Get go-bindata. Please note, the ellipses are required
go get github.com/containous/go-bindata/...
# Start build
# generate
# (required to merge non-code components into the final binary, such as the web dashboard and provider's Go templates)
go generate
# Standard go build
go build ./cmd/traefik
# run other commands like tests
```
You will find the Traefik executable in the `~/go/src/github.com/containous/traefik` folder as `traefik`.
### Updating the templates
If you happen to update the provider templates (in `/templates`), you need to run `go generate` to update the `autogen` package.
### Setting up dependency management
[dep](https://github.com/golang/dep) is not required for building; however, it is necessary to modify dependencies (i.e., add, update, or remove third-party packages)
You need to use [dep](https://github.com/golang/dep) >= O.4.1.
If you want to add a dependency, use `dep ensure -add` to have [dep](https://github.com/golang/dep) put it into the vendor folder and update the dep manifest/lock files (`Gopkg.toml` and `Gopkg.lock`, respectively).
A following `make dep-prune` run should be triggered to trim down the size of the vendor folder.
The final result must be committed into VCS.
Here's a full example using dep to add a new dependency:
```bash
# install the new main dependency github.com/foo/bar and minimize vendor size
$ dep ensure -add github.com/foo/bar
# generate (Only required to integrate other components such as web dashboard)
$ go generate
# Standard go build
$ go build ./cmd/traefik
# run other commands like tests
```
### Tests
#### Method 1: `Docker` and `make`
You can run unit tests using the `test-unit` target and the
integration test using the `test-integration` 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/containous/traefik/dist:/go/src/github.com/containous/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 .)
+ go test -cover -coverprofile=cover.out .
ok github.com/containous/traefik 0.005s coverage: 4.1% of statements
Test success
```
For development purposes, you can specify which tests to run by using:
```bash
# Run every tests in the MyTest suite
TESTFLAGS="-check.f MyTestSuite" 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
```
More: https://labix.org/gocheck
#### Method 2: `go`
Unit tests can be run from the cloned directory by `$ go test ./...` which should return `ok` similar to:
```
ok _/home/user/go/src/github/containous/traefik 0.004s
```
Integration tests must be run from the `integration/` directory and require the `-integration` switch to be passed like this: `$ cd integration && go test -integration ./...`.
## Documentation
The [documentation site](http://docs.traefik.io/) is built with [mkdocs](http://mkdocs.org/)
### Building Documentation
#### Method 1: `Docker` and `make`
You can build the documentation and serve it locally with livereloading, using the `docs` target:
```bash
$ make docs
docker build -t traefik-docs -f docs.Dockerfile .
# […]
docker run --rm -v /home/user/go/github/containous/traefik:/mkdocs -p 8000:8000 traefik-docs mkdocs serve
# […]
[I 170828 20:47:48 server:283] Serving on http://0.0.0.0:8000
[I 170828 20:47:48 handlers:60] Start watching changes
[I 170828 20:47:48 handlers:62] Start detecting changes
```
And go to [http://127.0.0.1:8000](http://127.0.0.1:8000).
If you only want to build the documentation without serving it locally, you can use the following command:
```bash
$ make docs-build
...
```
#### Method 2: `mkdocs`
First make sure you have python and pip installed
```bash
$ python --version
Python 2.7.2
$ pip --version
pip 1.5.2
```
Then install mkdocs with pip
```bash
pip install --user -r requirements.txt
```
To build documentation locally and serve it locally,
run `mkdocs serve` in the root directory,
this should start a server locally to preview your changes.
```bash
$ mkdocs serve
INFO - Building documentation...
INFO - Cleaning site directory
[I 160505 22:31:24 server:281] Serving on http://127.0.0.1:8000
[I 160505 22:31:24 handlers:59] Start watching changes
[I 160505 22:31:24 handlers:61] Start detecting changes
```
### Verify Documentation
You can verify that the documentation meets some expectations, as checking for dead links, html markup validity.
```bash
$ make docs-verify
docker build -t traefik-docs-verify ./script/docs-verify-docker-image ## Build Validator image
...
docker run --rm -v /home/travis/build/containous/traefik:/app traefik-docs-verify ## Check for dead links and w3c compliance
=== Checking HTML content...
Running ["HtmlCheck", "ImageCheck", "ScriptCheck", "LinkCheck"] on /app/site/basics/index.html on *.html...
```
If you recently changed the documentation, do not forget to clean it to have it rebuilt:
```bash
$ make docs-clean docs-verify
...
```
## How to Write a Good Issue
Please keep in mind that the GitHub issue tracker is not intended as a general support forum, but for reporting bugs and feature requests.
For end-user related support questions, refer to one of the following:
- the Traefik community Slack channel: [![Join the chat at https://slack.traefik.io](https://img.shields.io/badge/style-register-green.svg?style=social&label=Slack)](https://slack.traefik.io)
- [Stack Overflow](https://stackoverflow.com/questions/tagged/traefik) (using the `traefik` tag)
### Title
The title must be short and descriptive. (~60 characters)
### Description
- Respect the issue template as much as possible. [template](.github/ISSUE_TEMPLATE.md)
- If it's possible use the command `traefik bug`. See https://www.youtube.com/watch?v=Lyz62L8m93I.
- Explain the conditions which led you to write this issue: the context.
- The context should lead to something, an idea or a problem that youre facing.
- Remain clear and concise.
- Format your messages to help the reader focus on what matters and understand the structure of your message, use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown)
## How to Write a Good Pull Request
### Title
The title must be short and descriptive. (~60 characters)
### Description
- Respect the pull request template as much as possible. [template](.github/PULL_REQUEST_TEMPLATE.md)
- Explain the conditions which led you to write this PR: the context.
- The context should lead to something, an idea or a problem that youre facing.
- Remain clear and concise.
- Format your messages to help the reader focus on what matters and understand the structure of your message, use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown)
### Content
- Make it small.
- Do only one thing.
- Write useful descriptions and titles.
- Avoid re-formatting.
- Make sure the code builds.
- Make sure all tests pass.
- Add tests.
- Address review comments in terms of additional commits.
- Do not amend/squash existing ones unless the PR is trivial.
- If a PR involves changes to third-party dependencies, the commits pertaining to the vendor folder and the manifest/lock file(s) should be committed separated.
Read [10 tips for better pull requests](http://blog.ploeh.dk/2015/01/15/10-tips-for-better-pull-requests/).
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).

View File

@ -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.22
RUN apk add --no-cache --no-progress ca-certificates tzdata
ARG TARGETPLATFORM
COPY ./dist/$TARGETPLATFORM/traefik /
EXPOSE 80
VOLUME ["/tmp"]
ENTRYPOINT ["/traefik"]

1829
Gopkg.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,266 +0,0 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
[[constraint]]
branch = "master"
name = "github.com/ArthurHlt/go-eureka-client"
[[constraint]]
branch = "master"
name = "github.com/BurntSushi/toml"
[[constraint]]
branch = "master"
name = "github.com/BurntSushi/ty"
[[constraint]]
branch = "master"
name = "github.com/NYTimes/gziphandler"
[[constraint]]
branch = "containous-fork"
name = "github.com/abbot/go-http-auth"
source = "github.com/containous/go-http-auth"
[[constraint]]
branch = "master"
name = "github.com/armon/go-proxyproto"
[[constraint]]
name = "github.com/aws/aws-sdk-go"
version = "1.13.11"
[[constraint]]
branch = "master"
name = "github.com/cenk/backoff"
[[constraint]]
name = "github.com/containous/flaeg"
version = "1.3.0"
[[constraint]]
branch = "master"
name = "github.com/containous/mux"
[[constraint]]
name = "github.com/containous/staert"
version = "3.1.1"
[[constraint]]
name = "github.com/containous/traefik-extra-service-fabric"
version = "1.3.0"
[[constraint]]
name = "github.com/coreos/go-systemd"
version = "14.0.0"
[[constraint]]
branch = "master"
name = "github.com/docker/leadership"
source = "github.com/containous/leadership"
[[constraint]]
name = "github.com/eapache/channels"
version = "1.1.0"
[[constraint]]
branch = "master"
name = "github.com/elazarl/go-bindata-assetfs"
[[constraint]]
branch = "fork-containous"
name = "github.com/go-check/check"
source = "github.com/containous/check"
[[override]]
branch = "fork-containous"
name = "github.com/go-check/check"
source = "github.com/containous/check"
[[constraint]]
name = "github.com/go-kit/kit"
version = "0.7.0"
[[constraint]]
branch = "master"
name = "github.com/gorilla/websocket"
[[constraint]]
name = "github.com/hashicorp/consul"
version = "1.0.6"
[[constraint]]
name = "github.com/influxdata/influxdb"
version = "1.3.7"
[[constraint]]
branch = "master"
name = "github.com/jjcollinge/servicefabric"
[[constraint]]
branch = "master"
name = "github.com/abronan/valkeyrie"
[[constraint]]
name = "github.com/mesosphere/mesos-dns"
source = "https://github.com/containous/mesos-dns.git"
[[constraint]]
branch = "master"
name = "github.com/mitchellh/copystructure"
[[constraint]]
branch = "master"
name = "github.com/mitchellh/hashstructure"
[[constraint]]
branch = "master"
name = "github.com/mitchellh/mapstructure"
[[constraint]]
name = "github.com/opentracing/opentracing-go"
version = "1.0.2"
[[constraint]]
branch = "containous-fork"
name = "github.com/rancher/go-rancher-metadata"
source = "github.com/containous/go-rancher-metadata"
[[constraint]]
branch = "master"
name = "github.com/ryanuber/go-glob"
[[constraint]]
name = "github.com/satori/go.uuid"
version = "1.1.0"
[[constraint]]
branch = "master"
name = "github.com/stvp/go-udp-testing"
[[constraint]]
name = "github.com/stretchr/testify"
version = "1.2.1"
[[constraint]]
name = "github.com/uber/jaeger-client-go"
version = "2.9.0"
[[constraint]]
name = "github.com/uber/jaeger-lib"
version = "1.1.0"
[[constraint]]
branch = "v1"
name = "github.com/unrolled/secure"
[[constraint]]
name = "github.com/vdemeester/shakers"
version = "0.1.0"
[[constraint]]
branch = "master"
name = "github.com/vulcand/oxy"
[[constraint]]
branch = "master"
name = "github.com/xenolf/lego"
# version = "1.0.0"
[[constraint]]
name = "google.golang.org/grpc"
version = "1.5.2"
[[constraint]]
name = "gopkg.in/fsnotify.v1"
source = "github.com/fsnotify/fsnotify"
version = "1.4.2"
[[constraint]]
name = "k8s.io/client-go"
version = "6.0.0"
[[constraint]]
name = "k8s.io/api"
version = "kubernetes-1.9.0"
[[constraint]]
name = "k8s.io/apimachinery"
version = "kubernetes-1.9.0"
[[constraint]]
branch = "master"
name = "github.com/libkermit/docker"
[[constraint]]
branch = "master"
name = "github.com/libkermit/docker-check"
[[constraint]]
branch = "master"
name = "github.com/libkermit/compose"
[[constraint]]
name = "github.com/docker/docker"
revision = "7848b8beb9d38a98a78b75f78e05f8d2255f9dfe"
[[override]]
name = "github.com/docker/docker"
revision = "7848b8beb9d38a98a78b75f78e05f8d2255f9dfe"
[[override]]
name = "github.com/docker/cli"
revision = "6b63d7b96a41055baddc3fa71f381c7f60bd5d8e"
[[override]]
name = "github.com/docker/distribution"
revision = "edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c"
[[override]]
branch = "master"
name = "github.com/docker/libcompose"
[[override]]
name = "github.com/Nvveen/Gotty"
revision = "a8b993ba6abdb0e0c12b0125c603323a71c7790c"
source = "github.com/ijc25/Gotty"
[[override]]
# ALWAYS keep this override
name = "github.com/mailgun/timetools"
revision = "7e6055773c5137efbeb3bd2410d705fe10ab6bfd"
[[override]]
branch = "master"
name = "github.com/miekg/dns"
[prune]
non-go = true
go-tests = true
unused-packages = true
[[constraint]]
name = "github.com/patrickmn/go-cache"
version = "2.1.0"
[[constraint]]
name = "gopkg.in/DataDog/dd-trace-go.v1"
version = "1.0.0"

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2016-2018 Containous SAS
Copyright (c) 2016-2020 Containous SAS; 2020-2025 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

View File

@ -1,155 +0,0 @@
# Maintainers
## The team
* 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 [@marco-jantke](https://github.com/marco-jantke)
* Michaël Matur [@mmatur](https://github.com/mmatur)
## PR review process:
* The status `needs-design-review` is only used in complex/heavy/tricky PRs.
* From `1` to `2`: 1 comment that says “design LGTM” (by a senior maintainer).
* From `2` to `3`: 3 LGTM approvals by any maintainer.
* If needed, a specific maintainer familiar with a particular domain can be requested for the review.
We use [PRM](https://github.com/ldez/prm) to manage locally pull requests.
## Bots
### [Myrmica Lobicornis](https://github.com/containous/lobicornis/)
**Update and Merge Pull Request**
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.
To preserve commits, add `bot/merge-method-rebase` before `status/3-needs-merge`.
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 is used when:
- Updating the vendors from previously reviewed PRs
- Merging branches into the master
- Preparing the release
### [Myrmica Bibikoffi](https://github.com/containous/bibikoffi/)
* closes stale issues [cron]
* use some criterion as number of days between creation, last update, labels, ...
### [Myrmica Aloba](https://github.com/containous/aloba)
**Manage GitHub labels**
* Add labels on new PR [GitHub WebHook]
* Add milestone to a new PR based on a branch version (1.4, 1.3, ...) [GitHub WebHook]
* Add and remove `contributor/waiting-for-corrections` label when a review request changes [GitHub WebHook]
* Weekly report of PR status on Slack (CaptainPR) [cron]
## Labels
A maintainer that looks at an issue/PR must define its `kind/*`, `area/*`, and `status/*`.
### 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/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/marathon`: Marathon related.
* `area/provider/mesos`: Mesos related.
* `area/provider/rancher`: Rancher related.
* `area/provider/zk`: Zoo Keeper related.
* `area/sticky-session`: Sticky session related.
* `area/tls`: TLS related.
* `area/websocket`: WebSocket related.
* `area/webui`: Web UI related.
### Priority
* `priority/P0`: needs a hot fix. **(only for issue)**
* `priority/P1`: needs to be fixed the next release. **(only for issue)**
* `priority/P2`: needs to be fixed in the future. **(only for issue)**
* `priority/P3`: maybe. **(only for issue)**
### PR size
* `size/S`: small PR. **(only for PR)** _[bot only]_
* `size/M`: medium PR. **(only for PR)** _[bot only]_
* `size/L`: large PR. **(only for PR)** _[bot only]_
### 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]_

311
Makefile
View File

@ -1,151 +1,198 @@
.PHONY: all docs-verify docs docs-clean docs-build
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.
SRCS = $(shell git ls-files '*.go' | grep -v '^vendor/')
BIND_DIR := "dist"
TRAEFIK_MOUNT := -v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/containous/traefik/$(BIND_DIR)"
TAG_NAME := $(shell git describe --abbrev=0 --tags --exact-match)
SHA := $(shell git rev-parse HEAD)
VERSION_GIT := $(if $(TAG_NAME),$(TAG_NAME),$(SHA))
VERSION := $(if $(VERSION),$(VERSION),$(VERSION_GIT))
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),"containous/traefik")
INTEGRATION_OPTS := $(if $(MAKE_DOCKER_HOST),-e "DOCKER_HOST=$(MAKE_DOCKER_HOST)", -e "TEST_CONTAINER=1" -v "/var/run/docker.sock:/var/run/docker.sock")
TRAEFIK_DOC_IMAGE := traefik-docs
TRAEFIK_DOC_VERIFY_IMAGE := $(TRAEFIK_DOC_IMAGE)-verify
BIN_NAME := traefik
CODENAME ?= cheddar
DOCKER_BUILD_ARGS := $(if $(DOCKER_VERSION), "--build-arg=DOCKER_VERSION=$(DOCKER_VERSION)",)
DOCKER_RUN_OPTS := $(TRAEFIK_ENVS) $(TRAEFIK_MOUNT) "$(TRAEFIK_DEV_IMAGE)"
DOCKER_RUN_TRAEFIK := docker run $(INTEGRATION_OPTS) -it $(DOCKER_RUN_OPTS)
DOCKER_RUN_TRAEFIK_NOTTY := docker run $(INTEGRATION_OPTS) -i $(DOCKER_RUN_OPTS)
DOCKER_RUN_DOC_PORT := 8000
DOCKER_RUN_DOC_MOUNT := -v $(CURDIR):/mkdocs
DOCKER_RUN_DOC_OPTS := --rm $(DOCKER_RUN_DOC_MOUNT) -p $(DOCKER_RUN_DOC_PORT):8000
DATE := $(shell date -u '+%Y-%m-%d_%I:%M:%S%p')
# Default build target
GOOS := $(shell go env GOOS)
GOARCH := $(shell go env GOARCH)
GOGC ?=
print-%: ; @echo $*=$($*)
LINT_EXECUTABLES = misspell shellcheck
default: binary
DOCKER_BUILD_PLATFORMS ?= linux/amd64,linux/arm64
all: generate-webui build ## validate all checks, build linux binary, run all tests\ncross non-linux binaries
$(DOCKER_RUN_TRAEFIK) ./script/make.sh
binary: generate-webui build ## build the linux binary
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate binary
crossbinary: generate-webui build ## cross build the non-linux binaries
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate crossbinary
crossbinary-parallel:
$(MAKE) generate-webui
$(MAKE) build crossbinary-default crossbinary-others
crossbinary-default: generate-webui build
$(DOCKER_RUN_TRAEFIK_NOTTY) ./script/make.sh generate crossbinary-default
crossbinary-default-parallel:
$(MAKE) generate-webui
$(MAKE) build crossbinary-default
crossbinary-others: generate-webui build
$(DOCKER_RUN_TRAEFIK_NOTTY) ./script/make.sh generate crossbinary-others
crossbinary-others-parallel:
$(MAKE) generate-webui
$(MAKE) build crossbinary-others
test: build ## run the unit and integration tests
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate test-unit binary test-integration
test-unit: build ## run the unit tests
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate test-unit
test-integration: build ## run the integration tests
$(DOCKER_RUN_TRAEFIK) ./script/make.sh generate binary test-integration
TEST_HOST=1 ./script/make.sh test-integration
validate: build ## validate code, vendor and autogen
$(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-gofmt validate-govet validate-golint validate-misspell validate-vendor validate-autogen
build: dist
docker build $(DOCKER_BUILD_ARGS) -t "$(TRAEFIK_DEV_IMAGE)" -f build.Dockerfile .
build-webui:
docker build -t traefik-webui -f webui/Dockerfile webui
build-no-cache: dist
docker build --no-cache -t "$(TRAEFIK_DEV_IMAGE)" -f build.Dockerfile .
shell: build ## start a shell inside the build env
$(DOCKER_RUN_TRAEFIK) /bin/bash
image-dirty: binary ## build a docker traefik image
docker build -t $(TRAEFIK_IMAGE) .
image: clear-static binary ## clean up static directory and build a docker traefik image
docker build -t $(TRAEFIK_IMAGE) .
docs-image:
docker build -t $(TRAEFIK_DOC_IMAGE) -f docs.Dockerfile .
docs: docs-image
docker run $(DOCKER_RUN_DOC_OPTS) $(TRAEFIK_DOC_IMAGE) mkdocs serve
docs-build: site
docs-verify: site
docker build -t $(TRAEFIK_DOC_VERIFY_IMAGE) ./script/docs-verify-docker-image ## Build Validator image
docker run --rm -v $(CURDIR):/app $(TRAEFIK_DOC_VERIFY_IMAGE) ## Check for dead links and w3c compliance
site: docs-image
docker run $(DOCKER_RUN_DOC_OPTS) $(TRAEFIK_DOC_IMAGE) mkdocs build
docs-clean:
rm -rf $(CURDIR)/site
clear-static:
rm -rf static
.PHONY: default
#? default: Run `make generate` and `make binary`
default: generate binary
#? dist: Create the "dist" directory
dist:
mkdir dist
mkdir -p dist
run-dev:
.PHONY: build-webui-image
#? build-webui-image: Build WebUI Docker image
build-webui-image:
docker build -t traefik-webui -f webui/buildx.Dockerfile webui
.PHONY: clean-webui
#? clean-webui: Clean WebUI static generated assets
clean-webui:
rm -rf webui/static
webui/static/index.html:
$(MAKE) build-webui-image
docker run --rm -v "$(PWD)/webui/static":'/src/webui/static' traefik-webui yarn build:prod
docker run --rm -v "$(PWD)/webui/static":'/src/webui/static' traefik-webui chown -R $(shell id -u):$(shell id -g) ./static
.PHONY: generate-webui
#? generate-webui: Generate WebUI
generate-webui: webui/static/index.html
.PHONY: generate
#? generate: Generate code (Dynamic and Static configuration documentation reference files)
generate:
go generate
go build ./cmd/traefik
./traefik
generate-webui: build-webui
if [ ! -d "static" ]; then \
mkdir -p static; \
docker run --rm -v "$$PWD/static":'/src/static' traefik-webui npm run build; \
echo 'For more informations show `webui/readme.md`' > $$PWD/static/DONT-EDIT-FILES-IN-THIS-DIRECTORY.md; \
fi
.PHONY: binary
#? binary: Build the binary
binary: generate-webui dist
@echo SHA: $(VERSION) $(CODENAME) $(DATE)
CGO_ENABLED=0 GOGC=${GOGC} 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
binary-linux-arm64: export GOOS := linux
binary-linux-arm64: export GOARCH := arm64
binary-linux-arm64:
@$(MAKE) binary
binary-linux-amd64: export GOOS := linux
binary-linux-amd64: export GOARCH := amd64
binary-linux-amd64:
@$(MAKE) binary
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:
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
# In case of a new Minor/Major version, the k8sConformanceTraefikVersion needs to be updated.
GOOS=$(GOOS) GOARCH=$(GOARCH) go test ./integration -v -test.run K8sConformanceSuite -k8sConformance -k8sConformanceTraefikVersion="v3.5" $(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
.PHONY: lint
#? lint: Run golangci-lint
lint:
script/validate-golint
golangci-lint run
.PHONY: validate-files
#? validate-files: Validate code and docs
validate-files:
$(foreach exec,$(LINT_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
.PHONY: validate
#? validate: Validate code, docs, and vendor
validate: lint validate-files
# 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 .
.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
.PHONY: docs-serve
#? docs-serve: Serve the documentation site locally
docs-serve:
make -C ./docs docs-serve
.PHONY: docs-pull-images
#? docs-pull-images: Pull image for doc building
docs-pull-images:
make -C ./docs docs-pull-images
.PHONY: generate-crd
#? generate-crd: Generate CRD clientset and CRD manifests
generate-crd:
@$(CURDIR)/script/code-gen.sh
.PHONY: generate-genconf
#? generate-genconf: Generate code from dynamic configuration github.com/traefik/genconf
generate-genconf:
go run ./cmd/internal/gen/
.PHONY: release-packages
#? release-packages: Create packages for the release
release-packages: generate-webui
$(CURDIR)/script/release-packages.sh
.PHONY: fmt
#? fmt: Format the Code
fmt:
gofmt -s -l -w $(SRCS)
pull-images:
grep --no-filename -E '^\s+image:' ./integration/resources/compose/*.yml | awk '{print $$2}' | sort | uniq | xargs -P 6 -n 1 docker pull
dep-ensure:
dep ensure -v
./script/prune-dep.sh
dep-prune:
./script/prune-dep.sh
help: ## this help
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $$2);printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
.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/^/ /'

113
README.md
View File

@ -1,19 +1,21 @@
<p align="center">
<img src="docs/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>
[![Build Status SemaphoreCI](https://semaphoreci.com/api/v1/containous/traefik/branches/master/shields_badge.svg)](https://semaphoreci.com/containous/traefik)
[![Docs](https://img.shields.io/badge/docs-current-brightgreen.svg)](https://docs.traefik.io)
[![Go Report Card](https://goreportcard.com/badge/containous/traefik)](http://goreportcard.com/report/containous/traefik)
[![](https://images.microbadger.com/badges/image/traefik.svg)](https://microbadger.com/images/traefik)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/containous/traefik/blob/master/LICENSE.md)
[![Join the chat at https://slack.traefik.io](https://img.shields.io/badge/style-register-green.svg?style=social&label=Slack)](https://slack.traefik.io)
[![Build Status SemaphoreCI](https://traefik-oss.semaphoreci.com/badges/traefik/branches/master.svg?style=shields)](https://traefik-oss.semaphoreci.com/projects/traefik)
[![Docs](https://img.shields.io/badge/docs-current-brightgreen.svg)](https://doc.traefik.io/traefik)
[![Go Report Card](https://goreportcard.com/badge/traefik/traefik)](https://goreportcard.com/report/traefik/traefik)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/traefik/traefik/blob/master/LICENSE.md)
[![Join the community support forum at https://community.traefik.io/](https://img.shields.io/badge/style-register-green.svg?style=social&label=Discourse)](https://community.traefik.io/)
[![Twitter](https://img.shields.io/twitter/follow/traefik.svg?style=social)](https://twitter.com/intent/follow?screen_name=traefik)
Traefik 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 (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), [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.
---
@ -23,18 +25,19 @@ Pointing Traefik at your orchestrator should be the _only_ configuration step yo
**[Supported backends](#supported-backends)** .
**[Quickstart](#quickstart)** .
**[Web UI](#web-ui)** .
**[Test it](#test-it)** .
**[Documentation](#documentation)** .
. **[Support](#support)** .
**[Release cycle](#release-cycle)** .
**[Contributing](#contributing)** .
**[Maintainers](#maintainers)** .
**[Plumbing](#plumbing)** .
**[Credits](#credits)** .
---
:warning: When migrating to a new major version of Traefik, please refer to the [migration guide](https://doc.traefik.io/traefik/migration/v2-to-v3/) to ensure a smooth transition and to be aware of any breaking changes.
## Overview
Imagine that you have deployed a bunch of microservices with the help of an orchestrator (like Swarm or Kubernetes) or a service registry (like etcd or consul).
@ -50,7 +53,7 @@ Traefik listens to your service registry/orchestrator API and instantly generate
**Run Traefik and let it do the work for you!**
_(But if you'd rather configure some of your routes manually, Traefik supports that too!)_
![Architecture](docs/img/architecture.png)
![Architecture](docs/content/assets/img/traefik-architecture.png)
## Features
@ -58,68 +61,52 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t
- Supports multiple load balancing algorithms
- Provides HTTPS to your microservices by leveraging [Let's Encrypt](https://letsencrypt.org) (wildcard certificates support)
- Circuit breakers, retry
- High Availability with cluster mode (beta)
- 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 a [tiny](https://microbadger.com/images/traefik) [official](https://hub.docker.com/r/_/traefik/) docker image
- 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://docs.traefik.io/configuration/backends/docker) / [Swarm mode](https://docs.traefik.io/configuration/backends/docker#docker-swarm-mode)
- [Kubernetes](https://docs.traefik.io/configuration/backends/kubernetes)
- [Mesos](https://docs.traefik.io/configuration/backends/mesos) / [Marathon](https://docs.traefik.io/configuration/backends/marathon)
- [Rancher](https://docs.traefik.io/configuration/backends/rancher) (API, Metadata)
- [Azure Service Fabric](https://docs.traefik.io/configuration/backends/servicefabric)
- [Consul Catalog](https://docs.traefik.io/configuration/backends/consulcatalog)
- [Consul](https://docs.traefik.io/configuration/backends/consul) / [Etcd](https://docs.traefik.io/configuration/backends/etcd) / [Zookeeper](https://docs.traefik.io/configuration/backends/zookeeper) / [BoltDB](https://docs.traefik.io/configuration/backends/boltdb)
- [Eureka](https://docs.traefik.io/configuration/backends/eureka)
- [Amazon ECS](https://docs.traefik.io/configuration/backends/ecs)
- [Amazon DynamoDB](https://docs.traefik.io/configuration/backends/dynamodb)
- [File](https://docs.traefik.io/configuration/backends/file)
- [Rest](https://docs.traefik.io/configuration/backends/rest)
- [Docker](https://doc.traefik.io/traefik/providers/docker/) / [Swarm mode](https://doc.traefik.io/traefik/providers/docker/)
- [Kubernetes](https://doc.traefik.io/traefik/providers/kubernetes-crd/)
- [ECS](https://doc.traefik.io/traefik/providers/ecs/)
- [File](https://doc.traefik.io/traefik/providers/file/)
## Quickstart
To get your hands on Traefik, you can use the [5-Minute Quickstart](http://docs.traefik.io/#the-traefik-quickstart-using-docker) in our documentation (you will need Docker).
Alternatively, if you don't want to install anything on your computer, you can try Traefik online in this great [Katacoda tutorial](https://www.katacoda.com/courses/traefik/deploy-load-balancer) that shows how to load balance requests between multiple Docker containers.
If you are looking for a more comprehensive and real use-case example, you can also check [Play-With-Docker](http://training.play-with-docker.com/traefik-load-balancing/) to see how to load balance between multiple nodes.
To get your hands on Traefik, you can use the [5-Minute Quickstart](https://doc.traefik.io/traefik/getting-started/quick-start/) in our documentation (you will need Docker).
## Web UI
You can access the simple HTML frontend of Traefik.
![Web UI Providers](docs/img/web.frontend.png)
![Web UI Health](docs/img/traefik-health.png)
![Web UI Providers](docs/content/assets/img/webui-dashboard.png)
## Documentation
You can find the complete documentation at [https://docs.traefik.io](https://docs.traefik.io).
A collection of contributions around Traefik can be found at [https://awesome.traefik.io](https://awesome.traefik.io).
You can find the complete documentation of Traefik v3 at [https://doc.traefik.io/traefik/](https://doc.traefik.io/traefik/).
## Support
To get community support, you can:
- join the Traefik community Slack channel: [![Join the chat at https://slack.traefik.io](https://img.shields.io/badge/style-register-green.svg?style=social&label=Slack)](https://slack.traefik.io)
- use [Stack Overflow](https://stackoverflow.com/questions/tagged/traefik) (using the `traefik` tag)
If you need commercial support, please contact [Containo.us](https://containo.us) by mail: <mailto:support@containo.us>.
- join the Traefik community forum: [![Join the chat at https://community.traefik.io/](https://img.shields.io/badge/style-register-green.svg?style=social&label=Discourse)](https://community.traefik.io/)
If you need commercial support, please contact [Traefik.io](https://traefik.io) by mail: <mailto:support@traefik.io>.
## Download
- Grab the latest binary from the [releases](https://github.com/containous/traefik/releases) page and run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/master/traefik.sample.toml):
- Grab the latest binary from the [releases](https://github.com/traefik/traefik/releases) page and run it with the [sample configuration file](https://raw.githubusercontent.com/traefik/traefik/master/traefik.sample.toml):
```shell
./traefik --configFile=traefik.toml
```
- Or use the official tiny Docker image and run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/master/traefik.sample.toml):
- Or use the official tiny Docker image and run it with the [sample configuration file](https://raw.githubusercontent.com/traefik/traefik/master/traefik.sample.toml):
```shell
docker run -d -p 8080:8080 -p 80:80 -v $PWD/traefik.toml:/etc/traefik/traefik.toml traefik
@ -128,24 +115,18 @@ docker run -d -p 8080:8080 -p 80:80 -v $PWD/traefik.toml:/etc/traefik/traefik.to
- Or get the sources:
```shell
git clone https://github.com/containous/traefik
git clone https://github.com/traefik/traefik
```
## Introductory Videos
Here is a talk given by [Emile Vauge](https://github.com/emilevauge) at [GopherCon 2017](https://gophercon.com/).
You will learn Traefik basics in less than 10 minutes.
[![Traefik GopherCon 2017](https://img.youtube.com/vi/RgudiksfL-k/0.jpg)](https://www.youtube.com/watch?v=RgudiksfL-k)
Here is a talk given by [Ed Robinson](https://github.com/errm) at [ContainerCamp UK](https://container.camp) conference.
You will learn fundamental Traefik features and see some demos with Kubernetes.
[![Traefik ContainerCamp UK](https://img.youtube.com/vi/aFtpIShV60I/0.jpg)](https://www.youtube.com/watch?v=aFtpIShV60I)
You can find high level and deep dive videos on [videos.traefik.io](https://videos.traefik.io).
## Maintainers
[Information about process and maintainers](MAINTAINER.md)
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 [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
@ -156,24 +137,24 @@ By participating in this project, you agree to abide by its terms.
## Release Cycle
- We release a new version (e.g. 1.1.0, 1.2.0, 1.3.0) every other month.
- Release Candidates are available before the release (e.g. 1.1.0-rc1, 1.1.0-rc2, 1.1.0-rc3, 1.1.0-rc4, before 1.1.0)
- Bug-fixes (e.g. 1.1.1, 1.1.2, 1.2.1, 1.2.3) are released as needed (no additional features are delivered in those versions, bug-fixes only)
- We usually release 3/4 new versions (e.g. 1.1.0, 1.2.0, 1.3.0) per year.
- Release Candidates are available before the release (e.g. 1.1.0-rc1, 1.1.0-rc2, 1.1.0-rc3, 1.1.0-rc4, before 1.1.0).
- Bug-fixes (e.g. 1.1.1, 1.1.2, 1.2.1, 1.2.3) are released as needed (no additional features are delivered in those versions, bug-fixes only).
Each version is supported until the next one is released (e.g. 1.1.x will be supported until 1.2.0 is out)
Each version is supported until the next one is released (e.g. 1.1.x will be supported until 1.2.0 is out).
We use [Semantic Versioning](http://semver.org/)
We use [Semantic Versioning](https://semver.org/).
## Mailing lists
## Mailing Lists
- General announcements, new releases: mail at news+subscribe@traefik.io or on [the online viewer](https://groups.google.com/a/traefik.io/forum/#!forum/news)
- General announcements, new releases: mail at news+subscribe@traefik.io or on [the online viewer](https://groups.google.com/a/traefik.io/forum/#!forum/news).
- Security announcements: mail at security+subscribe@traefik.io or on [the online viewer](https://groups.google.com/a/traefik.io/forum/#!forum/security).
## Credits
Kudos to [Peka](http://peka.byethost11.com/photoblog/) for his awesome work on the logo ![logo](docs/img/traefik.icon.png).
Kudos to [Peka](https://www.instagram.com/pierroks/) for his awesome work on the gopher's logo!.
Traefik's logo is licensed under the Creative Commons 3.0 Attributions license.
The gopher's logo of Traefik is licensed under the Creative Commons 3.0 Attributions license.
Traefik's logo was inspired by the gopher stickers made by Takuya Ueda (https://twitter.com/tenntenn).
The original Go gopher was designed by Renee French (http://reneefrench.blogspot.com/).
The gopher's logo of Traefik was inspired by the gopher stickers made by [Takuya Ueda](https://twitter.com/tenntenn).
The original Go gopher was designed by [Renee French](https://reneefrench.blogspot.com/).

30
SECURITY.md Normal file
View File

@ -0,0 +1,30 @@
# Security Policy
You can join our security mailing list to be aware of the latest announcements from our security team.
You can subscribe by sending an email 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).
## Supported Versions
- We usually release 3/4 new versions (e.g. 1.1.0, 1.2.0, 1.3.0) per year.
- Release Candidates are available before the release (e.g. 1.1.0-rc1, 1.1.0-rc2, 1.1.0-rc3, 1.1.0-rc4, before 1.1.0).
- Bug-fixes (e.g. 1.1.1, 1.1.2, 1.2.1, 1.2.3) are released as needed (no additional features are delivered in those versions, bug-fixes only).
Each version is supported until the next one is released (e.g. 1.1.x will be supported until 1.2.0 is out).
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: |
| `< 1.7.x` | :x: |
## 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,
by creating a [security advisory](https://github.com/traefik/traefik/security/advisories).

View File

@ -1,333 +0,0 @@
package acme
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"fmt"
"reflect"
"regexp"
"sort"
"strings"
"sync"
"time"
"github.com/containous/traefik/log"
acmeprovider "github.com/containous/traefik/provider/acme"
"github.com/containous/traefik/types"
"github.com/xenolf/lego/acme"
)
// Account is used to store lets encrypt registration info
type Account struct {
Email string
Registration *acme.RegistrationResource
PrivateKey []byte
KeyType acme.KeyType
DomainsCertificate DomainsCertificates
ChallengeCerts map[string]*ChallengeCert
HTTPChallenge map[string]map[string][]byte
}
// ChallengeCert stores a challenge certificate
type ChallengeCert struct {
Certificate []byte
PrivateKey []byte
certificate *tls.Certificate
}
// Init account struct
func (a *Account) Init() error {
err := a.DomainsCertificate.Init()
if err != nil {
return err
}
err = a.RemoveAccountV1Values()
if err != nil {
log.Errorf("Unable to remove ACME Account V1 values during account initialization: %v", err)
}
for _, cert := range a.ChallengeCerts {
if cert.certificate == nil {
certificate, err := tls.X509KeyPair(cert.Certificate, cert.PrivateKey)
if err != nil {
return err
}
cert.certificate = &certificate
}
if cert.certificate.Leaf == nil {
leaf, err := x509.ParseCertificate(cert.certificate.Certificate[0])
if err != nil {
return err
}
cert.certificate.Leaf = leaf
}
}
return nil
}
// NewAccount creates an account
func NewAccount(email string, certs []*DomainsCertificate, keyTypeValue string) (*Account, error) {
keyType := acmeprovider.GetKeyType(keyTypeValue)
// Create a user. New accounts need an email and private key to start
privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return nil, err
}
domainsCerts := DomainsCertificates{Certs: certs}
err = domainsCerts.Init()
if err != nil {
return nil, err
}
return &Account{
Email: email,
PrivateKey: x509.MarshalPKCS1PrivateKey(privateKey),
KeyType: keyType,
DomainsCertificate: DomainsCertificates{Certs: domainsCerts.Certs},
ChallengeCerts: map[string]*ChallengeCert{}}, nil
}
// GetEmail returns email
func (a *Account) GetEmail() string {
return a.Email
}
// GetRegistration returns lets encrypt registration resource
func (a *Account) GetRegistration() *acme.RegistrationResource {
return a.Registration
}
// GetPrivateKey returns private key
func (a *Account) GetPrivateKey() crypto.PrivateKey {
if privateKey, err := x509.ParsePKCS1PrivateKey(a.PrivateKey); err == nil {
return privateKey
}
log.Errorf("Cannot unmarshall private key %+v", a.PrivateKey)
return nil
}
// RemoveAccountV1Values removes ACME account V1 values
func (a *Account) RemoveAccountV1Values() error {
// Check if ACME Account is in ACME V1 format
if a.Registration != nil {
isOldRegistration, err := regexp.MatchString(acmeprovider.RegistrationURLPathV1Regexp, a.Registration.URI)
if err != nil {
return err
}
if isOldRegistration {
a.reset()
}
}
return nil
}
func (a *Account) reset() {
log.Debug("Reset ACME account object.")
a.Email = ""
a.Registration = nil
a.PrivateKey = nil
}
// Certificate is used to store certificate info
type Certificate struct {
Domain string
CertURL string
CertStableURL string
PrivateKey []byte
Certificate []byte
}
// DomainsCertificates stores a certificate for multiple domains
type DomainsCertificates struct {
Certs []*DomainsCertificate
lock sync.RWMutex
}
func (dc *DomainsCertificates) Len() int {
return len(dc.Certs)
}
func (dc *DomainsCertificates) Swap(i, j int) {
dc.Certs[i], dc.Certs[j] = dc.Certs[j], dc.Certs[i]
}
func (dc *DomainsCertificates) Less(i, j int) bool {
if reflect.DeepEqual(dc.Certs[i].Domains, dc.Certs[j].Domains) {
return dc.Certs[i].tlsCert.Leaf.NotAfter.After(dc.Certs[j].tlsCert.Leaf.NotAfter)
}
if dc.Certs[i].Domains.Main == dc.Certs[j].Domains.Main {
return strings.Join(dc.Certs[i].Domains.SANs, ",") < strings.Join(dc.Certs[j].Domains.SANs, ",")
}
return dc.Certs[i].Domains.Main < dc.Certs[j].Domains.Main
}
func (dc *DomainsCertificates) removeDuplicates() {
sort.Sort(dc)
for i := 0; i < len(dc.Certs); i++ {
for i2 := i + 1; i2 < len(dc.Certs); i2++ {
if reflect.DeepEqual(dc.Certs[i].Domains, dc.Certs[i2].Domains) {
// delete
log.Warnf("Remove duplicate cert: %+v, expiration :%s", dc.Certs[i2].Domains, dc.Certs[i2].tlsCert.Leaf.NotAfter.String())
dc.Certs = append(dc.Certs[:i2], dc.Certs[i2+1:]...)
i2--
}
}
}
}
func (dc *DomainsCertificates) removeEmpty() {
var certs []*DomainsCertificate
for _, cert := range dc.Certs {
if cert.Certificate != nil && len(cert.Certificate.Certificate) > 0 && len(cert.Certificate.PrivateKey) > 0 {
certs = append(certs, cert)
}
}
dc.Certs = certs
}
// Init DomainsCertificates
func (dc *DomainsCertificates) Init() error {
dc.lock.Lock()
defer dc.lock.Unlock()
dc.removeEmpty()
for _, domainsCertificate := range dc.Certs {
tlsCert, err := tls.X509KeyPair(domainsCertificate.Certificate.Certificate, domainsCertificate.Certificate.PrivateKey)
if err != nil {
return err
}
domainsCertificate.tlsCert = &tlsCert
if domainsCertificate.tlsCert.Leaf == nil {
leaf, err := x509.ParseCertificate(domainsCertificate.tlsCert.Certificate[0])
if err != nil {
return err
}
domainsCertificate.tlsCert.Leaf = leaf
}
}
dc.removeDuplicates()
return nil
}
func (dc *DomainsCertificates) renewCertificates(acmeCert *Certificate, domain types.Domain) error {
dc.lock.Lock()
defer dc.lock.Unlock()
for _, domainsCertificate := range dc.Certs {
if reflect.DeepEqual(domain, domainsCertificate.Domains) {
tlsCert, err := tls.X509KeyPair(acmeCert.Certificate, acmeCert.PrivateKey)
if err != nil {
return err
}
domainsCertificate.Certificate = acmeCert
domainsCertificate.tlsCert = &tlsCert
return nil
}
}
return fmt.Errorf("certificate to renew not found for domain %s", domain.Main)
}
func (dc *DomainsCertificates) addCertificateForDomains(acmeCert *Certificate, domain types.Domain) (*DomainsCertificate, error) {
dc.lock.Lock()
defer dc.lock.Unlock()
tlsCert, err := tls.X509KeyPair(acmeCert.Certificate, acmeCert.PrivateKey)
if err != nil {
return nil, err
}
cert := DomainsCertificate{Domains: domain, Certificate: acmeCert, tlsCert: &tlsCert}
dc.Certs = append(dc.Certs, &cert)
return &cert, nil
}
func (dc *DomainsCertificates) getCertificateForDomain(domainToFind string) (*DomainsCertificate, bool) {
dc.lock.RLock()
defer dc.lock.RUnlock()
for _, domainsCertificate := range dc.Certs {
for _, domain := range domainsCertificate.Domains.ToStrArray() {
if strings.HasPrefix(domain, "*.") && types.MatchDomain(domainToFind, domain) {
return domainsCertificate, true
}
if domain == domainToFind {
return domainsCertificate, true
}
}
}
return nil, false
}
func (dc *DomainsCertificates) exists(domainToFind types.Domain) (*DomainsCertificate, bool) {
dc.lock.RLock()
defer dc.lock.RUnlock()
for _, domainsCertificate := range dc.Certs {
if reflect.DeepEqual(domainToFind, domainsCertificate.Domains) {
return domainsCertificate, true
}
}
return nil, false
}
func (dc *DomainsCertificates) toDomainsMap() map[string]*tls.Certificate {
domainsCertificatesMap := make(map[string]*tls.Certificate)
for _, domainCertificate := range dc.Certs {
certKey := domainCertificate.Domains.Main
if domainCertificate.Domains.SANs != nil {
sort.Strings(domainCertificate.Domains.SANs)
for _, dnsName := range domainCertificate.Domains.SANs {
if dnsName != domainCertificate.Domains.Main {
certKey += fmt.Sprintf(",%s", dnsName)
}
}
}
domainsCertificatesMap[certKey] = domainCertificate.tlsCert
}
return domainsCertificatesMap
}
// DomainsCertificate contains a certificate for multiple domains
type DomainsCertificate struct {
Domains types.Domain
Certificate *Certificate
tlsCert *tls.Certificate
}
func (dc *DomainsCertificate) needRenew() bool {
for _, c := range dc.tlsCert.Certificate {
crt, err := x509.ParseCertificate(c)
if err != nil {
// If there's an error, we assume the cert is broken, and needs update
return true
}
// <= 30 days left, renew certificate
if crt.NotAfter.Before(time.Now().Add(24 * 30 * time.Hour)) {
return true
}
}
return false
}

View File

@ -1,835 +0,0 @@
package acme
import (
"context"
"crypto/tls"
"errors"
"fmt"
"io/ioutil"
fmtlog "log"
"net"
"net/http"
"net/url"
"reflect"
"strings"
"sync"
"time"
"github.com/BurntSushi/ty/fun"
"github.com/cenk/backoff"
"github.com/containous/flaeg"
"github.com/containous/mux"
"github.com/containous/staert"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/log"
acmeprovider "github.com/containous/traefik/provider/acme"
"github.com/containous/traefik/safe"
"github.com/containous/traefik/types"
"github.com/containous/traefik/version"
"github.com/eapache/channels"
"github.com/sirupsen/logrus"
"github.com/xenolf/lego/acme"
legolog "github.com/xenolf/lego/log"
"github.com/xenolf/lego/providers/dns"
)
var (
// OSCPMustStaple enables OSCP stapling as from https://github.com/xenolf/lego/issues/270
OSCPMustStaple = false
)
// ACME allows to connect to lets encrypt and retrieve certs
// Deprecated Please use provider/acme/Provider
type ACME struct {
Email string `description:"Email address used for registration"`
Domains []types.Domain `description:"SANs (alternative domains) to each main domain using format: --acme.domains='main.com,san1.com,san2.com' --acme.domains='main.net,san1.net,san2.net'"`
Storage string `description:"File or key used for certificates storage."`
StorageFile string // Deprecated
OnDemand bool `description:"(Deprecated) Enable on demand certificate generation. This will request a certificate from Let's Encrypt during the first TLS handshake for a hostname that does not yet have a certificate."` // Deprecated
OnHostRule bool `description:"Enable certificate generation on frontends Host rules."`
CAServer string `description:"CA server to use."`
EntryPoint string `description:"Entrypoint to proxy acme challenge to."`
KeyType string `description:"KeyType used for generating certificate private key. Allow value 'EC256', 'EC384', 'RSA2048', 'RSA4096', 'RSA8192'. Default to 'RSA4096'"`
DNSChallenge *acmeprovider.DNSChallenge `description:"Activate DNS-01 Challenge"`
HTTPChallenge *acmeprovider.HTTPChallenge `description:"Activate HTTP-01 Challenge"`
TLSChallenge *acmeprovider.TLSChallenge `description:"Activate TLS-ALPN-01 Challenge"`
DNSProvider string `description:"(Deprecated) Activate DNS-01 Challenge"` // Deprecated
DelayDontCheckDNS flaeg.Duration `description:"(Deprecated) Assume DNS propagates after a delay in seconds rather than finding and querying nameservers."` // Deprecated
ACMELogging bool `description:"Enable debug logging of ACME actions."`
OverrideCertificates bool `description:"Enable to override certificates in key-value store when using storeconfig"`
client *acme.Client
store cluster.Store
challengeHTTPProvider *challengeHTTPProvider
challengeTLSProvider *challengeTLSProvider
checkOnDemandDomain func(domain string) bool
jobs *channels.InfiniteChannel
TLSConfig *tls.Config `description:"TLS config in case wildcard certs are used"`
dynamicCerts *safe.Safe
resolvingDomains map[string]struct{}
resolvingDomainsMutex sync.RWMutex
}
func (a *ACME) init() error {
acme.UserAgent = fmt.Sprintf("containous-traefik/%s", version.Version)
if a.ACMELogging {
legolog.Logger = fmtlog.New(log.WriterLevel(logrus.InfoLevel), "legolog: ", 0)
} else {
legolog.Logger = fmtlog.New(ioutil.Discard, "", 0)
}
a.jobs = channels.NewInfiniteChannel()
// Init the currently resolved domain map
a.resolvingDomains = make(map[string]struct{})
return nil
}
// AddRoutes add routes on internal router
func (a *ACME) AddRoutes(router *mux.Router) {
router.Methods(http.MethodGet).
Path(acme.HTTP01ChallengePath("{token}")).
Handler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
if a.challengeHTTPProvider == nil {
rw.WriteHeader(http.StatusNotFound)
return
}
vars := mux.Vars(req)
if token, ok := vars["token"]; ok {
domain, _, err := net.SplitHostPort(req.Host)
if err != nil {
log.Debugf("Unable to split host and port: %v. Fallback to request host.", err)
domain = req.Host
}
tokenValue := a.challengeHTTPProvider.getTokenValue(token, domain)
if len(tokenValue) > 0 {
rw.WriteHeader(http.StatusOK)
rw.Write(tokenValue)
return
}
}
rw.WriteHeader(http.StatusNotFound)
}))
}
// CreateClusterConfig creates a tls.config using ACME configuration in cluster mode
func (a *ACME) CreateClusterConfig(leadership *cluster.Leadership, tlsConfig *tls.Config, certs *safe.Safe, checkOnDemandDomain func(domain string) bool) error {
err := a.init()
if err != nil {
return err
}
if len(a.Storage) == 0 {
return errors.New("empty Store, please provide a key for certs storage")
}
a.checkOnDemandDomain = checkOnDemandDomain
a.dynamicCerts = certs
tlsConfig.GetCertificate = a.getCertificate
a.TLSConfig = tlsConfig
listener := func(object cluster.Object) error {
account := object.(*Account)
account.Init()
if !leadership.IsLeader() {
a.client, err = a.buildACMEClient(account)
if err != nil {
log.Errorf("Error building ACME client %+v: %s", object, err.Error())
}
}
return nil
}
datastore, err := cluster.NewDataStore(
leadership.Pool.Ctx(),
staert.KvSource{
Store: leadership.Store,
Prefix: a.Storage,
},
&Account{},
listener)
if err != nil {
return err
}
a.store = datastore
a.challengeTLSProvider = &challengeTLSProvider{store: a.store}
ticker := time.NewTicker(24 * time.Hour)
leadership.Pool.AddGoCtx(func(ctx context.Context) {
log.Info("Starting ACME renew job...")
defer log.Info("Stopped ACME renew job...")
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
a.renewCertificates()
}
}
})
leadership.AddListener(a.leadershipListener)
return nil
}
func (a *ACME) leadershipListener(elected bool) error {
if elected {
_, err := a.store.Load()
if err != nil {
return err
}
transaction, object, err := a.store.Begin()
if err != nil {
return err
}
account := object.(*Account)
account.Init()
// Reset Account values if caServer changed, thus registration URI can be updated
if account != nil && account.Registration != nil && !isAccountMatchingCaServer(account.Registration.URI, a.CAServer) {
log.Info("Account URI does not match the current CAServer. The account will be reset")
account.reset()
}
var needRegister bool
if account == nil || len(account.Email) == 0 {
domainsCerts := DomainsCertificates{Certs: []*DomainsCertificate{}}
if account != nil {
domainsCerts = account.DomainsCertificate
}
account, err = NewAccount(a.Email, domainsCerts.Certs, a.KeyType)
if err != nil {
return err
}
needRegister = true
} else if len(account.KeyType) == 0 {
// Set the KeyType if not already defined in the account
account.KeyType = acmeprovider.GetKeyType(a.KeyType)
}
a.client, err = a.buildACMEClient(account)
if err != nil {
return err
}
if needRegister {
// New users will need to register; be sure to save it
log.Debug("Register...")
reg, err := a.client.Register(true)
if err != nil {
return err
}
account.Registration = reg
}
err = transaction.Commit(account)
if err != nil {
return err
}
a.retrieveCertificates()
a.renewCertificates()
a.runJobs()
}
return nil
}
func isAccountMatchingCaServer(accountURI string, serverURI string) bool {
aru, err := url.Parse(accountURI)
if err != nil {
log.Infof("Unable to parse account.Registration URL : %v", err)
return false
}
cau, err := url.Parse(serverURI)
if err != nil {
log.Infof("Unable to parse CAServer URL : %v", err)
return false
}
return cau.Hostname() == aru.Hostname()
}
func (a *ACME) getCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
domain := types.CanonicalDomain(clientHello.ServerName)
account := a.store.Get().(*Account)
if challengeCert, ok := a.challengeTLSProvider.getCertificate(domain); ok {
log.Debugf("ACME got challenge %s", domain)
return challengeCert, nil
}
if providedCertificate := a.getProvidedCertificate(domain); providedCertificate != nil {
return providedCertificate, nil
}
if domainCert, ok := account.DomainsCertificate.getCertificateForDomain(domain); ok {
log.Debugf("ACME got domain cert %s", domain)
return domainCert.tlsCert, nil
}
if a.OnDemand {
if a.checkOnDemandDomain != nil && !a.checkOnDemandDomain(domain) {
return nil, nil
}
return a.loadCertificateOnDemand(clientHello)
}
log.Debugf("No certificate found or generated for %s", domain)
return nil, nil
}
func (a *ACME) retrieveCertificates() {
a.jobs.In() <- func() {
log.Info("Retrieving ACME certificates...")
a.deleteUnnecessaryDomains()
for i := 0; i < len(a.Domains); i++ {
domain := a.Domains[i]
// check if cert isn't already loaded
account := a.store.Get().(*Account)
if _, exists := account.DomainsCertificate.exists(domain); !exists {
var domains []string
domains = append(domains, domain.Main)
domains = append(domains, domain.SANs...)
domains, err := a.getValidDomains(domains, true)
if err != nil {
log.Errorf("Error validating ACME certificate for domain %q: %s", domains, err)
continue
}
certificateResource, err := a.getDomainsCertificates(domains)
if err != nil {
log.Errorf("Error getting ACME certificate for domain %q: %s", domains, err)
continue
}
transaction, object, err := a.store.Begin()
if err != nil {
log.Errorf("Error creating ACME store transaction from domain %q: %s", domain, err)
continue
}
account = object.(*Account)
_, err = account.DomainsCertificate.addCertificateForDomains(certificateResource, domain)
if err != nil {
log.Errorf("Error adding ACME certificate for domain %q: %s", domains, err)
continue
}
if err = transaction.Commit(account); err != nil {
log.Errorf("Error Saving ACME account %+v: %s", account, err)
continue
}
}
}
log.Info("Retrieved ACME certificates")
}
}
func (a *ACME) renewCertificates() {
a.jobs.In() <- func() {
log.Info("Testing certificate renew...")
account := a.store.Get().(*Account)
for _, certificateResource := range account.DomainsCertificate.Certs {
if certificateResource.needRenew() {
log.Infof("Renewing certificate from LE : %+v", certificateResource.Domains)
renewedACMECert, err := a.renewACMECertificate(certificateResource)
if err != nil {
log.Errorf("Error renewing certificate from LE: %v", err)
continue
}
operation := func() error {
return a.storeRenewedCertificate(certificateResource, renewedACMECert)
}
notify := func(err error, time time.Duration) {
log.Warnf("Renewed certificate storage error: %v, retrying in %s", err, time)
}
ebo := backoff.NewExponentialBackOff()
ebo.MaxElapsedTime = 60 * time.Second
err = backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify)
if err != nil {
log.Errorf("Datastore cannot sync: %v", err)
continue
}
}
}
}
}
func (a *ACME) renewACMECertificate(certificateResource *DomainsCertificate) (*Certificate, error) {
renewedCert, err := a.client.RenewCertificate(acme.CertificateResource{
Domain: certificateResource.Certificate.Domain,
CertURL: certificateResource.Certificate.CertURL,
CertStableURL: certificateResource.Certificate.CertStableURL,
PrivateKey: certificateResource.Certificate.PrivateKey,
Certificate: certificateResource.Certificate.Certificate,
}, true, OSCPMustStaple)
if err != nil {
return nil, err
}
log.Infof("Renewed certificate from LE: %+v", certificateResource.Domains)
return &Certificate{
Domain: renewedCert.Domain,
CertURL: renewedCert.CertURL,
CertStableURL: renewedCert.CertStableURL,
PrivateKey: renewedCert.PrivateKey,
Certificate: renewedCert.Certificate,
}, nil
}
func (a *ACME) storeRenewedCertificate(certificateResource *DomainsCertificate, renewedACMECert *Certificate) error {
transaction, object, err := a.store.Begin()
if err != nil {
return fmt.Errorf("error during transaction initialization for renewing certificate: %v", err)
}
log.Infof("Renewing certificate in data store : %+v ", certificateResource.Domains)
account := object.(*Account)
err = account.DomainsCertificate.renewCertificates(renewedACMECert, certificateResource.Domains)
if err != nil {
return fmt.Errorf("error renewing certificate in datastore: %v ", err)
}
log.Infof("Commit certificate renewed in data store : %+v", certificateResource.Domains)
if err = transaction.Commit(account); err != nil {
return fmt.Errorf("error saving ACME account %+v: %v", account, err)
}
oldAccount := a.store.Get().(*Account)
for _, oldCertificateResource := range oldAccount.DomainsCertificate.Certs {
if oldCertificateResource.Domains.Main == certificateResource.Domains.Main && strings.Join(oldCertificateResource.Domains.SANs, ",") == strings.Join(certificateResource.Domains.SANs, ",") && certificateResource.Certificate != renewedACMECert {
return fmt.Errorf("renewed certificate not stored: %+v", certificateResource.Domains)
}
}
log.Infof("Certificate successfully renewed in data store: %+v", certificateResource.Domains)
return nil
}
func dnsOverrideDelay(delay flaeg.Duration) error {
var err error
if delay > 0 {
log.Debugf("Delaying %d rather than validating DNS propagation", delay)
acme.PreCheckDNS = func(_, _ string) (bool, error) {
time.Sleep(time.Duration(delay))
return true, nil
}
} else if delay < 0 {
err = fmt.Errorf("invalid negative DelayBeforeCheck: %d", delay)
}
return err
}
func (a *ACME) buildACMEClient(account *Account) (*acme.Client, error) {
log.Debug("Building ACME client...")
caServer := "https://acme-v02.api.letsencrypt.org/directory"
if len(a.CAServer) > 0 {
caServer = a.CAServer
}
client, err := acme.NewClient(caServer, account, account.KeyType)
if err != nil {
return nil, err
}
// DNS challenge
if a.DNSChallenge != nil && len(a.DNSChallenge.Provider) > 0 {
log.Debugf("Using DNS Challenge provider: %s", a.DNSChallenge.Provider)
err = dnsOverrideDelay(a.DNSChallenge.DelayBeforeCheck)
if err != nil {
return nil, err
}
acmeprovider.SetRecursiveNameServers(a.DNSChallenge.Resolvers)
acmeprovider.SetPropagationCheck(a.DNSChallenge.DisablePropagationCheck)
var provider acme.ChallengeProvider
provider, err = dns.NewDNSChallengeProviderByName(a.DNSChallenge.Provider)
if err != nil {
return nil, err
}
client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.TLSALPN01})
err = client.SetChallengeProvider(acme.DNS01, provider)
return client, err
}
// HTTP challenge
if a.HTTPChallenge != nil && len(a.HTTPChallenge.EntryPoint) > 0 {
log.Debug("Using HTTP Challenge provider.")
client.ExcludeChallenges([]acme.Challenge{acme.DNS01, acme.TLSALPN01})
a.challengeHTTPProvider = &challengeHTTPProvider{store: a.store}
err = client.SetChallengeProvider(acme.HTTP01, a.challengeHTTPProvider)
return client, err
}
// TLS Challenge
if a.TLSChallenge != nil {
log.Debug("Using TLS Challenge provider.")
client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.DNS01})
err = client.SetChallengeProvider(acme.TLSALPN01, a.challengeTLSProvider)
return client, err
}
return nil, errors.New("ACME challenge not specified, please select TLS or HTTP or DNS Challenge")
}
func (a *ACME) loadCertificateOnDemand(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
domain := types.CanonicalDomain(clientHello.ServerName)
account := a.store.Get().(*Account)
if certificateResource, ok := account.DomainsCertificate.getCertificateForDomain(domain); ok {
return certificateResource.tlsCert, nil
}
certificate, err := a.getDomainsCertificates([]string{domain})
if err != nil {
return nil, err
}
log.Debugf("Got certificate on demand for domain %s", domain)
transaction, object, err := a.store.Begin()
if err != nil {
return nil, err
}
account = object.(*Account)
cert, err := account.DomainsCertificate.addCertificateForDomains(certificate, types.Domain{Main: domain})
if err != nil {
return nil, err
}
if err = transaction.Commit(account); err != nil {
return nil, err
}
return cert.tlsCert, nil
}
// LoadCertificateForDomains loads certificates from ACME for given domains
func (a *ACME) LoadCertificateForDomains(domains []string) {
a.jobs.In() <- func() {
log.Debugf("LoadCertificateForDomains %v...", domains)
domains, err := a.getValidDomains(domains, false)
if err != nil {
log.Errorf("Error getting valid domain: %v", err)
return
}
operation := func() error {
if a.client == nil {
return errors.New("ACME client still not built")
}
return nil
}
notify := func(err error, time time.Duration) {
log.Errorf("Error getting ACME client: %v, retrying in %s", err, time)
}
ebo := backoff.NewExponentialBackOff()
ebo.MaxElapsedTime = 30 * time.Second
err = backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify)
if err != nil {
log.Errorf("Error getting ACME client: %v", err)
return
}
account := a.store.Get().(*Account)
// Check provided certificates
uncheckedDomains := a.getUncheckedDomains(domains, account)
if len(uncheckedDomains) == 0 {
return
}
a.addResolvingDomains(uncheckedDomains)
defer a.removeResolvingDomains(uncheckedDomains)
certificate, err := a.getDomainsCertificates(uncheckedDomains)
if err != nil {
log.Errorf("Error getting ACME certificates %+v : %v", uncheckedDomains, err)
return
}
log.Debugf("Got certificate for domains %+v", uncheckedDomains)
transaction, object, err := a.store.Begin()
if err != nil {
log.Errorf("Error creating transaction %+v : %v", uncheckedDomains, err)
return
}
var domain types.Domain
if len(uncheckedDomains) > 1 {
domain = types.Domain{Main: uncheckedDomains[0], SANs: uncheckedDomains[1:]}
} else {
domain = types.Domain{Main: uncheckedDomains[0]}
}
account = object.(*Account)
_, err = account.DomainsCertificate.addCertificateForDomains(certificate, domain)
if err != nil {
log.Errorf("Error adding ACME certificates %+v : %v", uncheckedDomains, err)
return
}
if err = transaction.Commit(account); err != nil {
log.Errorf("Error Saving ACME account %+v: %v", account, err)
return
}
}
}
func (a *ACME) addResolvingDomains(resolvingDomains []string) {
a.resolvingDomainsMutex.Lock()
defer a.resolvingDomainsMutex.Unlock()
for _, domain := range resolvingDomains {
a.resolvingDomains[domain] = struct{}{}
}
}
func (a *ACME) removeResolvingDomains(resolvingDomains []string) {
a.resolvingDomainsMutex.Lock()
defer a.resolvingDomainsMutex.Unlock()
for _, domain := range resolvingDomains {
delete(a.resolvingDomains, domain)
}
}
// Get provided certificate which check a domains list (Main and SANs)
// from static and dynamic provided certificates
func (a *ACME) getProvidedCertificate(domains string) *tls.Certificate {
log.Debugf("Looking for provided certificate to validate %s...", domains)
cert := searchProvidedCertificateForDomains(domains, a.TLSConfig.NameToCertificate)
if cert == nil && a.dynamicCerts != nil && a.dynamicCerts.Get() != nil {
cert = searchProvidedCertificateForDomains(domains, a.dynamicCerts.Get().(map[string]*tls.Certificate))
}
if cert == nil {
log.Debugf("No provided certificate found for domains %s, get ACME certificate.", domains)
}
return cert
}
func searchProvidedCertificateForDomains(domain string, certs map[string]*tls.Certificate) *tls.Certificate {
// Use regex to test for provided certs that might have been added into TLSConfig
for certDomains := range certs {
domainChecked := false
for _, certDomain := range strings.Split(certDomains, ",") {
domainChecked = types.MatchDomain(domain, certDomain)
if domainChecked {
break
}
}
if domainChecked {
log.Debugf("Domain %q checked by provided certificate %q", domain, certDomains)
return certs[certDomains]
}
}
return nil
}
// Get provided certificate which check a domains list (Main and SANs)
// from static and dynamic provided certificates
func (a *ACME) getUncheckedDomains(domains []string, account *Account) []string {
a.resolvingDomainsMutex.RLock()
defer a.resolvingDomainsMutex.RUnlock()
log.Debugf("Looking for provided certificate to validate %s...", domains)
allCerts := make(map[string]*tls.Certificate)
// Get static certificates
for domains, certificate := range a.TLSConfig.NameToCertificate {
allCerts[domains] = certificate
}
// Get dynamic certificates
if a.dynamicCerts != nil && a.dynamicCerts.Get() != nil {
for domains, certificate := range a.dynamicCerts.Get().(map[string]*tls.Certificate) {
allCerts[domains] = certificate
}
}
// Get ACME certificates
if account != nil {
for domains, certificate := range account.DomainsCertificate.toDomainsMap() {
allCerts[domains] = certificate
}
}
// Get currently resolved domains
for domain := range a.resolvingDomains {
if _, ok := allCerts[domain]; !ok {
allCerts[domain] = &tls.Certificate{}
}
}
// Get Configuration Domains
for i := 0; i < len(a.Domains); i++ {
allCerts[a.Domains[i].Main] = &tls.Certificate{}
for _, san := range a.Domains[i].SANs {
allCerts[san] = &tls.Certificate{}
}
}
return searchUncheckedDomains(domains, allCerts)
}
func searchUncheckedDomains(domains []string, certs map[string]*tls.Certificate) []string {
var uncheckedDomains []string
for _, domainToCheck := range domains {
if !isDomainAlreadyChecked(domainToCheck, certs) {
uncheckedDomains = append(uncheckedDomains, domainToCheck)
}
}
if len(uncheckedDomains) == 0 {
log.Debugf("No ACME certificate to generate for domains %q.", domains)
} else {
log.Debugf("Domains %q need ACME certificates generation for domains %q.", domains, strings.Join(uncheckedDomains, ","))
}
return uncheckedDomains
}
func (a *ACME) getDomainsCertificates(domains []string) (*Certificate, error) {
var cleanDomains []string
for _, domain := range domains {
canonicalDomain := types.CanonicalDomain(domain)
cleanDomain := acme.UnFqdn(canonicalDomain)
if canonicalDomain != cleanDomain {
log.Warnf("FQDN detected, please remove the trailing dot: %s", canonicalDomain)
}
cleanDomains = append(cleanDomains, cleanDomain)
}
log.Debugf("Loading ACME certificates %s...", cleanDomains)
bundle := true
certificate, err := a.client.ObtainCertificate(cleanDomains, bundle, nil, OSCPMustStaple)
if err != nil {
return nil, fmt.Errorf("cannot obtain certificates: %+v", err)
}
log.Debugf("Loaded ACME certificates %s", cleanDomains)
return &Certificate{
Domain: certificate.Domain,
CertURL: certificate.CertURL,
CertStableURL: certificate.CertStableURL,
PrivateKey: certificate.PrivateKey,
Certificate: certificate.Certificate,
}, nil
}
func (a *ACME) runJobs() {
safe.Go(func() {
for job := range a.jobs.Out() {
function := job.(func())
function()
}
})
}
// getValidDomains checks if given domain is allowed to generate a ACME certificate and return it
func (a *ACME) getValidDomains(domains []string, wildcardAllowed bool) ([]string, error) {
// Check if the domains array is empty or contains only one empty value
if len(domains) == 0 || (len(domains) == 1 && len(domains[0]) == 0) {
return nil, errors.New("unable to generate a certificate when no domain is given")
}
if strings.HasPrefix(domains[0], "*") {
if !wildcardAllowed {
return nil, fmt.Errorf("unable to generate a wildcard certificate for domain %q from a 'Host' rule", strings.Join(domains, ","))
}
if a.DNSChallenge == nil && len(a.DNSProvider) == 0 {
return nil, fmt.Errorf("unable to generate a wildcard certificate for domain %q : ACME needs a DNSChallenge", strings.Join(domains, ","))
}
if strings.HasPrefix(domains[0], "*.*") {
return nil, fmt.Errorf("unable to generate a wildcard certificate for domain %q : ACME does not allow '*.*' wildcard domain", strings.Join(domains, ","))
}
}
for _, san := range domains[1:] {
if strings.HasPrefix(san, "*") {
return nil, fmt.Errorf("unable to generate a certificate for domains %q: SANs can not be a wildcard domain", strings.Join(domains, ","))
}
}
domains = fun.Map(types.CanonicalDomain, domains).([]string)
return domains, nil
}
func isDomainAlreadyChecked(domainToCheck string, existentDomains map[string]*tls.Certificate) bool {
for certDomains := range existentDomains {
for _, certDomain := range strings.Split(certDomains, ",") {
if types.MatchDomain(domainToCheck, certDomain) {
return true
}
}
}
return false
}
// deleteUnnecessaryDomains deletes from the configuration :
// - Duplicated domains
// - Domains which are checked by wildcard domain
func (a *ACME) deleteUnnecessaryDomains() {
var newDomains []types.Domain
for idxDomainToCheck, domainToCheck := range a.Domains {
keepDomain := true
for idxDomain, domain := range a.Domains {
if idxDomainToCheck == idxDomain {
continue
}
if reflect.DeepEqual(domain, domainToCheck) {
if idxDomainToCheck > idxDomain {
log.Warnf("The domain %v is duplicated in the configuration but will be process by ACME only once.", domainToCheck)
keepDomain = false
}
break
}
var newDomainsToCheck []string
// Check if domains can be validated by the wildcard domain
domainsMap := make(map[string]*tls.Certificate)
domainsMap[domain.Main] = &tls.Certificate{}
if len(domain.SANs) > 0 {
domainsMap[strings.Join(domain.SANs, ",")] = &tls.Certificate{}
}
for _, domainProcessed := range domainToCheck.ToStrArray() {
if idxDomain < idxDomainToCheck && isDomainAlreadyChecked(domainProcessed, domainsMap) {
// The domain is duplicated in a CN
log.Warnf("Domain %q is duplicated in the configuration or validated by the domain %v. It will be processed once.", domainProcessed, domain)
continue
} else if domain.Main != domainProcessed && strings.HasPrefix(domain.Main, "*") && types.MatchDomain(domainProcessed, domain.Main) {
// Check if a wildcard can validate the domain
log.Warnf("Domain %q will not be processed by ACME provider because it is validated by the wildcard %q", domainProcessed, domain.Main)
continue
}
newDomainsToCheck = append(newDomainsToCheck, domainProcessed)
}
// Delete the domain if both Main and SANs can be validated by the wildcard domain
// otherwise keep the unchecked values
if newDomainsToCheck == nil {
keepDomain = false
break
}
domainToCheck.Set(newDomainsToCheck)
}
if keepDomain {
newDomains = append(newDomains, domainToCheck)
}
}
a.Domains = newDomains
}

View File

@ -1,43 +0,0 @@
{
"Email": "test@traefik.io",
"Registration": {
"body": {
"resource": "reg",
"id": 3,
"key": {
"kty": "RSA",
"n": "y5a71suIqvEtovDmDVQ3SSNagk5IVCFI_TvqWpEXSrdbcDE2C-PTEtEUJuLkYwygcpiWYbPmXgdS628vQCw5Uo4DeDyHiuysJOWBLaWow3p9goOdhnPbGBq0liIR9xXyRoctdipVk8UiO9scWsu4jMBM3sMr7_yBWPfYYiLEQmZGFO3iE7Oqr55h_kncHIj5lUQY1j_jkftqxlxUB5_0quyJ7l915j5QY--eY7h4GEhRvx0TlUpi-CnRtRblGeDDDilXZD6bQN2962WdKecsmRaYx-ttLz6jCPXz2VDJRWNcIS501ne2Zh3hzw_DS6IRd2GIia1Wg4sisi9epC9sumXPHi6xzR6-_i_nsFjdtTkUcV8HmorOYoc820KQVZaLScxa8e7-ixpOd6mr6AIbEf7dBAkb9f_iK3GwpqKD8yNcaj1EQgNSyJSjnKSulXI_GwkGnuXe00Qpb1a8ha5Z8yWg7XmZZnJyAZrmK60RfwRNQ1rO5ioerNUBJ2KYTYNzVjBdob9Ug6Cjh4bEKNNjqcbjQ50_Z97Vw40xzpDQ_fYllc6n92eSuv6olxFJTmK7EhHuanDzITngaqei3zL9RwQ7P-1jfEZ03qmGrQYYqXcsS46PQ8cE-frzY2mKp16pRNCG7-03gKVGV0JHyW1aYbevNUk7OumCAXhC2YOigBk",
"e": "AQAB"
},
"contact": [
"mailto:test@traefik.io"
],
"agreement": "http://boulder:4000/terms/v1"
},
"uri": "http://127.0.0.1:4000/acme/reg/3",
"new_authzr_uri": "http://127.0.0.1:4000/acme/new-authz",
"terms_of_service": "http://boulder:4000/terms/v1"
},
"PrivateKey": "MIIJJwIBAAKCAgEAy5a71suIqvEtovDmDVQ3SSNagk5IVCFI/TvqWpEXSrdbcDE2C+PTEtEUJuLkYwygcpiWYbPmXgdS628vQCw5Uo4DeDyHiuysJOWBLaWow3p9goOdhnPbGBq0liIR9xXyRoctdipVk8UiO9scWsu4jMBM3sMr7/yBWPfYYiLEQmZGFO3iE7Oqr55h/kncHIj5lUQY1j/jkftqxlxUB5/0quyJ7l915j5QY++eY7h4GEhRvx0TlUpi+CnRtRblGeDDDilXZD6bQN2962WdKecsmRaYx+ttLz6jCPXz2VDJRWNcIS501ne2Zh3hzw/DS6IRd2GIia1Wg4sisi9epC9sumXPHi6xzR6+/i/nsFjdtTkUcV8HmorOYoc820KQVZaLScxa8e7+ixpOd6mr6AIbEf7dBAkb9f/iK3GwpqKD8yNcaj1EQgNSyJSjnKSulXI/GwkGnuXe00Qpb1a8ha5Z8yWg7XmZZnJyAZrmK60RfwRNQ1rO5ioerNUBJ2KYTYNzVjBdob9Ug6Cjh4bEKNNjqcbjQ50/Z97Vw40xzpDQ/fYllc6n92eSuv6olxFJTmK7EhHuanDzITngaqei3zL9RwQ7P+1jfEZ03qmGrQYYqXcsS46PQ8cE+frzY2mKp16pRNCG7+03gKVGV0JHyW1aYbevNUk7OumCAXhC2YOigBkCAwEAAQKCAgA8XW1EuwTC6tAFSDhuK1JZNUpY6K05hMUHkQRj5jFpzgQmt/C2hc7H/YZkIVJmrA/G6sdsINNlffZwKH9yH6q/d6w/snLeFl7UcdhjmIL5sxAT6sKCY0fLVd/FxERfZvp3Pw2Tw+mr7v+/j7BQm6cU1M/2HRiiB9SydIqMTpKyvXB6NC6ceOFbQTL9GxlQvKyEPbS/kiH/3vRB7I5d1GfPZmNfcp6ark9X0my8VK4HRSo36H8t/OhrfLrZXvh/O82aHVf0OTv/d8AgU/jNu+XVXoXegUfWglQFDChJf1KuaE+g5w1tqgFDNgkGRD475soXA6xgZi0Iw/B9tN3zALzT4IiAW1q72feeTgKOMA2zGtKXxQZZSOV+DuWFZNz/tT7XqGQThqxM09CHv2WGOe80vobtegXYTUt90hysrqIZmBW5XYdzQlJh1KWTtfCaTrWd47kbGvhkEPc8aA3Ji4/AqfkVXiqwaLu+MSlgzPpRj7U7UAIDqnpZjgttgLp74Ujnk3bTaUzdyyNqYDBG3IFGr/Sv+2GQDAUn/PYRJKWr0BteqOzX9zvW3zY8g9CYVXfK/AW3RMWLV8ly6vH/gWqa9gEuzRNRlzjUU6/HCVbUx3UT8RMWH2TQ0uuQZr5JX1iTwjeeT0dEIly1NnRQC92wcrE4UUTBEF3krGVpDBf0AQKCAQEA4jB8w+2fwzbF8X+gCODcY7sTeJRunzGy+jbdaLkcThuylga+6W3ZgWx0BD30ql9K2mouCVu86fCTnBeXXEC3QoTdgw/EzJ83+4JU3QSDdzs9Ta9vLHyvrpUkQfZ8UZpeLLmFsmsBMbBbnfw0S1TzXDsgrAc+G4tia8nO/Iqu75kEMGzmHQAvmN3iSqc1aTS4qumbB19g+v+csq9NEht4F9jt39KotG+OD3MxCxtMu7vxAkJRjFFcgcbb2Rtqe/kQEKA1vLEAJg27lV4k8XibCSerVUR6IzT8WZHrNiXmpRguTLl2k8uFUdCOOx6aLGyRVJ6+8SgIsMR540vnxwQzEQKCAQEA5mu2wtWT19mvXopC3easPsXIPzc5oaRkqfWZYT1KHcVQ7NIXsE3vCjcf/3igZ8l/FVQ4G4fpk/GoTqlpV5Aq/JHCpVOR2O69uB+W4kWgliejpHvF9gszzAYnC8lIXqDbWiinBhmm3ii8sDGAoBaSDw5NMUq3mI+nd8zZ+jx1bLBczDafmQ0YKr8k0YaROxIgoBgDOQDdSqG387lwzpza2DKI5Al3HfS42zjT0RmBahPiuT2aEoUZmIYuvFY0fEjfkpbdvLyexHfZCILRUGlG1nAwASFg86lp+mFSBJ3E3cvbP0CpbFGxon5u4Ao3/7htoOh6huh7MQ91h41fv1hsiQKCAQAe7WRR4e7jYVzlbX7zV9Oqq0y5QwpxJ/mB7viNNiphn7Xmf5uhDU0dPjgK0HHgzdDNVpFe5DVLg4KbaDpg+dRU+xfSsNhG5kpgUGzMH67eIbJ7Kc64tX/MDkZ74nkTK1lPIjrer3TlV2jfjDmWR1JTPR51hzP9ziwx8tEjhM7woeqJuIoqUvkvHL+xV3WdIgFSFUkGVAtNpp/FauTN4gWktRupbAN3UH2LLUP6ccwnK0aD+Y9u8T0F3av33qDLvL1umIlgeI89pMkOXmYMwmHoeY0axpcwszECCkqwB7SmxEyoXv+Qq9ZZ3ntkKAYKpvmkKWSQUtoFWYgVBS727mMRAoIBABLdwusU/bPwuPEutObiWjwRiaHTbb6UbUGVQGe70vO5EjUxxorC9s2JUe9i+w9EakleyfFHIZLheHxoVp26yio/7QYIX6q5cYM/4uTH+qwQts9i6wSISkdsQYovguNsnEk3huVy+Dy8bSaoBvYUowTkkOF2Uq4FJRskBLz+ckbh8dcuqcaoUdA+Mk+NixqhE1bIYIssTPItZ5hnGJtyMGD/UkIJnF0ximk4r+8w/W2oDypHpvPZPg1E/1KgZE/Az7166NDpSL6haX3O6ECDPi+Uo/mTuBJ7TpgXm9WQ7WuTo3H8Y2LhFYBOhdmGPKuNeDxyjIW7R0rvDxp4MtzB6rECggEAJIl7/qp1lxUQPQJRTsEYBkOtdRw0IGG1Rcj0emhHaBN05c9opCy+Osb7mVeU5ZiULe5kD02phL+36pEumprz7QzN46Y5pZc8AQ2W/QkeL4Wo9U9QzczvQQzc1EqrBkzvQTZtBhn4DRzz0IuTn1beVyHtBZeNpBFgMQFv9VYQuUNwFoTOkkQrBRnYbXH6KEnhF3c/1Hzi4KHVdHdfZ3LH7KFQJ34xio0q2tWQSQYeybmwOXdd9sxpz/Y4KBS9fqm7UrwnPK8yuOc05HLEaws+1iam5YyJprlQo3mGKe0wRztwn44HDeQr70LlFm0lzigVAv0hSiWO1Q5hJL7nDu8m/Q==",
"DomainsCertificate": {
"Certs": [
{
"Domains": {
"Main": "local1.com",
"SANs": [
"test1.local1.com",
"test2.local1.com"
]
},
"Certificate": {
"Domain": "local1.com",
"CertURL": "http://127.0.0.1:4000/acme/cert/ffc4f3f14def9ee6ec6a0522b5c0baa3379d",
"CertStableURL": "",
"PrivateKey": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKS1FJQkFBS0NBZ0VBdVNoTTR4enF6cE5YcFNaNnAvZnQrRmt5VmgyK1BSZXJUelV0OERRSng2UkVjQS9FCnN2RnNIVmNOSkZMS2twYTNlOEd3SUZBakJQNnJPK3hoR1JjWlJrdENON1gyOW5LZFhGbHZkYzJxd0hyTFF5WWkKTTB3ODhTck41VERiNi96TWU2dTB0dERiYWtDbDd6ZEJKUXJ6a1h5ZU1MeVkzTUs3aVkrMHpwL2JqMVhvbk5DdQpaQStkZ3hsMVNrV01DVUYvQk9HNWFyT1hwb0x4S0dQWGdzV3hOTVNLVmJKSHczL3ZqNTViZU92Um5lT3BNWlhvCmMwOWpZT3VBakNka1Z5czBSWHJLNWNCRDRMbVRXdnN4MFdTK2VMVHlGTTdQTHVZM3lEWkNNWEhjVmlqRHhnbFMKYjB1ZVRQcGFUWEQwYkxqZ0RNOUVEdE15ZEJzMUNPWlpPWG9ickN5Q2I1eWxTOFdVd1NzVXM1UldxZnlVbnAvcgpSNGx2c2RZOWRVZjRPdkNMVnJvWWk5NWFGc1Zxa0xLOExuL0Eyc3kxYWlDTnR4RmpKOXRXbWU0V0NhdzRoU0YvCkR4NWVNNWNYR2JSYXduVlZJQlZXeHhzNTBPMFJlUWRvbXBQZEFNS1RDWk9SRmxYaDdOWTdxQVdWRGtpdzhyam8Kekd3Ni9XdjlOR3hTNTliKzc0YVAxcjBxOTZ2RS9Rdi8zTCtjbjhiN0lBLytPYmFKdzhIT3RGbXc4RjBxQkN3MAprYWVVSloxb1JueGFYQUo4RHhHREpFOVdNUzh0QmJtVm16YkxoRkMzeDdVc0xGeTBrSzh1SFBFT3dQb2NKNUFUCkE1UHBvclNEMmFleHA0Z3VqYVp5c1JManpmY0dnaTdva0JFNlZVNWVqRE1iYS9lNERQNEJQUVg5VmtVQ0F3RUEKQVFLQ0FnQmZjMWdYcUp1ZmZMT3REcVlpbXh4UmIrSVVKT2NpWldaSndmZDVvY244NGtEcHFDZFZ2RUZvNnF4NgpzamQ5MURhb2xOUHdCSC9aSGxRMTR3aTNQNEluQzdzS0wwTXVEeTN5SXFUa0RPOWVwSzdPWWdVMWZyTFgvS0lCCjZlc2x2Ny9HYldFTzhhSjdKdktqM0U4NEFtcEg4UDgzenJIYTlJUnJTT3NEcmNNcEpEZHpSOXp1OW1IVDZMYmYKWC9UdC9KYTNkSW42YUxUZ0FSYkRKSjAvN0J3TFFOcXpqT0dUOWdzUWRhbGdMK2x5eEo4L1ViRndhRmVwNmgzdApvbzBHcHQ0ZWgwdTdueDhlNVd3Q2RnWmJsTnpnS3grMC9Gd3dLRHhQZVRFc2ZpOEJONmlkR2NjbVdzd3prTWdtCnJmbERaeGNSWTNRSlZIVHBCL0dTTWZXRFBPQ3dRdGltQk1WN3kxM2hPMTdPWXpSNDBMZnpUalJBbmtna2V2eWYKcFowb3dLR3o4QS9haHhRWWJmYVQ5VEhXV0wrYUpYeUhFanBKckp5aTg3UExVbzhsOFVydU56MDRWNXpLOFJPbgo2cG9EWmVtbm1EYWRlU09pK3hZRWlGT1NwSXNWbzlpcm9jUGFKN2YzYWpiNUU4RHpuN1o1MmhzL2R6akpLcFZJCm5mVDFkUU9SZEowSXRUNlRlQ2RTL0dpS25IS1RtNjR2T21IbmlJcm8rUGRhUmFjV0IrTUJ0VytRd0cyUStyRGkKc3g4NlpQbHRpTVpLMDZ5TVlyVHZUdGk2aFVGaUY5cWh4b3RGazdNQkNrZlIwYUVhaUREQUpKNm1jb1lpRUQ2QgpBVGJhVmpVaGNaUiswYkRST25PN0ozRk5rZmx3K2dMaVhvcXFRRW9pU2ZWb2h5SWY3UUtDQVFFQThjYTM5K0g4CjN3L2Qrcm0yUGNhM0RMQnBYaWU4Z3ZYcGpjazVYSkpvSGVmbnJjZWQrcFpXaTZEYncwYld0MEdtYkxmVjJNSlAKV2I1aTZzSXhmdkN3YlFqbHY0UnExMVA5ZEswT3poMnVpKzZ6cXVBMG5YTVcrN0lJS0cvdDhmS2NJZGRRNnRGcwpFclFVTFBDak56ODA2cHBiSlhPRmVvMW1BK293TGhHNlA3dDhCdlZHSk1NaTNxejNlSUNuVVE2eDNFY01ITXNuClhrM21DUzI1WUZaNk96cytFK254cGVraTAzZmQwblp3UE1jdElHZys1c3hleE9zREsrTHlvb2FqQnc5N0oyUzIKcUNNWXFtT0tLcmxEQ3Y1WmQ4dlZLN3hXVmpKRVhGTTNMZ2pieHBRcCtuVXNVVWxwS01LOVlGS0lRREl0RU9aMApWcWExTXJaOElzN1l5d0tDQVFFQXhBemZIa2pIVGlvTHdZbG5EcEk0MWlOTDh5Y0ZBallrTC94dWhPU2tlVkE4CjdRWDZPZUpDekR3Z0FUYXVqOWR6Y0wwby9yTndWV0xWcnQ3OXk3YnJvVDdFREZKWVNTY25GRXNMTlVWSXRncGkKckNSUXJTL1F2TkVGTmE5K0pRc1dmYkdBNHdIUTFaSjI4MFp1cWMvNlEyUi9kZVh3cUZBQVBHN2NIcEhHWlR6ZQoyRmFRUHFLRkV4WlEyZkpvRys0SVBRNHVQVERybXlGMmVUWXk2T3BaaDBHbWJRYlVTa1dFWDlQRmF1cHJIWVdGCk8wK25DaVVPNVRaMFZoaGR2dUNKMWdPclZHYzhBUlJtUVZ1aUNEWTZCaGlvVTU0ZmZsSXlDTXZ5a3MwcmRXZ3MKWVJ2TmN4TXNlRGJpTDRKSURkMHhiN1d4VUdmVjRVNHZPMks5Vms1N0x3S0NBUUVBMkd1eE1jcXd1RnRUc0tPYwpaaUFDcXZFZTRKRmhSVGtySHlnSW1MelZSaS9ZU3M1c3MycnZmWDA0T3N5bVZ0UUZUVHdoeUMzbktjWXFkVW52ClZGblBFMHJyblV2Qzk0elBUQ205SHZPaTBzK1JORndOdlFMUWgrME5NR1ZBOFZyaU44aXRQZ1RJWU5XaFdianQKNFA1TE45V0QwVHBmT1J4cFBRZmNxT0JsZjdjcmhtNzNvdUNwemZtMmE3OStCaWpKUFF5NzR1cFhDeXRmeHNlUApNSlU0Uk56NjdJaDFMclpKM2xGbDFvYitZT2xKazhDOHpZd1RLT0hWck9zeGxobyt4SXN2Q2t3MDFMelZ6Mi9hCnRmT3Y5NTlHSnQzbXE0ZWpJUFZPQy9iUlpmdTMvMEdSY2dpQTZ5SnpaM0VxWTVaOU1EbTU3VzdjcE5RRlRxZmEKNXEyUmtRS0NBUUErNGhZSzQ3TXg2aUNkTWxKaEJSdS82OUJucktOWm96NFdPalRFNFlXejk3MmpGU0Mrd2tsRQpzeUJjNDBvNGp4WFRHb2wwc04rZU03WndnY3dNTko3OXVHRXZ4cFhVMlA4YTdqc3BHaEVKZXVsTlo5U015R0orCnZkaWE4TEJZZDJiK2FCbjhOay9pd1Rqd0xTNC92NXI1Vk5uaFdpRElDK2tYZVVPWGRwQ1pWbDN3TEV2V0cxRHQKMzJHTmxzZzM5VENsVE5BZUJudjc1VTdYOEQrQ0gvRVpoa0E0aGxFL2hXN0JRZTczclRzd1creHhLc3BjWWFpVwpjdEg3NzVMYUw3Rm1lUVRTYk01OVZpcTZXZ2J0OVY3Rko5R09DSkQzZHF2ZjBITDlEVndjSzQ3WWt3OWlFc3RYCnY5cnEvREhhYUpGNzBGNlFlTTNNbDhSa212WTZJYkEzQW9JQkFRRGt6RmZLeG9HQ3dWUDlua3k4NmFQSjFvd2kKc2FDZEx6RjRWTENRZzkrUXJITzEyY0p5MFFQUnJ2cUQyMGp1cDFlOWJhWVZzbkdYc1FZTFg2NVR6UzJSSCtlSAp6S0NPTTdnMVE3djMxNWpjMDMvN1lQck4rb3RrV0VBOUkyaDZjUE1vY3c0aERTNk02OFlxQVlKTS9RclVhenZhCnhBTFJaZEVkQW1xWDA4VHhuY1hRUEVxYkk0ZnlSZ2pVM1BYR3RRaFFFbERpR2kwbThjQTJNTXdsR1RmbTdOSXgKaENjZ2ZkL296TEp2VUhiMkxLRi82cXEySmJVRHlOMkVoK0xSZUJjdnp6Y1grZE5MdGQxY0Uvcm1SM2hMbWxmNgo3KzRpTVMxK0t1eWV3VlJVUEE1c1F1aUYyVUVoeEs1MUpZK1FpOG9HbERKdGRrOXB3QlZNN1F0WW9KVEwKLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0K",
"Certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZvakNDQklxZ0F3SUJBZ0lUQVAvRTgvRk43NTdtN0dvRklyWEF1cU0zblRBTkJna3Foa2lHOXcwQkFRc0YKQURBZk1SMHdHd1lEVlFRRERCUm9NbkJ3ZVNCb01tTnJaWElnWm1GclpTQkRRVEFlRncweE9EQXhNVFV3TnpJNQpNREJhRncweE9EQTBNVFV3TnpJNU1EQmFNRVF4RXpBUkJnTlZCQU1UQ214dlkyRnNNUzVqYjIweExUQXJCZ05WCkJBVVRKR1ptWXpSbU0yWXhOR1JsWmpsbFpUWmxZelpoTURVeU1tSTFZekJpWVdFek16YzVaRENDQWlJd0RRWUoKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBTGtvVE9NYzZzNlRWNlVtZXFmMzdmaFpNbFlkdmowWApxMDgxTGZBMENjZWtSSEFQeExMeGJCMVhEU1JTeXBLV3QzdkJzQ0JRSXdUK3F6dnNZUmtYR1VaTFFqZTE5dlp5Cm5WeFpiM1hOcXNCNnkwTW1Jak5NUFBFcXplVXcyK3Y4ekh1cnRMYlEyMnBBcGU4M1FTVUs4NUY4bmpDOG1OekMKdTRtUHRNNmYyNDlWNkp6UXJtUVBuWU1aZFVwRmpBbEJmd1RodVdxemw2YUM4U2hqMTRMRnNUVEVpbFd5UjhOLwo3NCtlVzNqcjBaM2pxVEdWNkhOUFkyRHJnSXduWkZjck5FVjZ5dVhBUStDNWsxcjdNZEZrdm5pMDhoVE96eTdtCk44ZzJRakZ4M0ZZb3c4WUpVbTlMbmt6NldrMXc5R3k0NEF6UFJBN1RNblFiTlFqbVdUbDZHNndzZ20rY3BVdkYKbE1FckZMT1VWcW44bEo2ZjYwZUpiN0hXUFhWSCtEcndpMWE2R0l2ZVdoYkZhcEN5dkM1L3dOck10V29namJjUgpZeWZiVnBudUZnbXNPSVVoZnc4ZVhqT1hGeG0wV3NKMVZTQVZWc2NiT2REdEVYa0hhSnFUM1FEQ2t3bVRrUlpWCjRleldPNmdGbFE1SXNQSzQ2TXhzT3Yxci9UUnNVdWZXL3UrR2o5YTlLdmVyeFAwTC85eS9uSi9HK3lBUC9qbTIKaWNQQnpyUlpzUEJkS2dRc05KR25sQ1dkYUVaOFdsd0NmQThSZ3lSUFZqRXZMUVc1bFpzMnk0UlF0OGUxTEN4Ywp0SkN2TGh6eERzRDZIQ2VRRXdPVDZhSzBnOW1uc2FlSUxvMm1jckVTNDgzM0JvSXU2SkFST2xWT1hvd3pHMnYzCnVBeitBVDBGL1ZaRkFnTUJBQUdqZ2dHd01JSUJyREFPQmdOVkhROEJBZjhFQkFNQ0JhQXdIUVlEVlIwbEJCWXcKRkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ01Bd0dBMVVkRXdFQi93UUNNQUF3SFFZRFZSME9CQllFRk5LZQpBVUZYc2Z2N2lML0lYVVBXdzY2ZU5jQnhNQjhHQTFVZEl3UVlNQmFBRlB0NFR4TDVZQldETEo4WGZ6UVpzeTQyCjZrR0pNR1lHQ0NzR0FRVUZCd0VCQkZvd1dEQWlCZ2dyQmdFRkJRY3dBWVlXYUhSMGNEb3ZMekV5Tnk0d0xqQXUKTVRvME1EQXlMekF5QmdnckJnRUZCUWN3QW9ZbWFIUjBjRG92THpFeU55NHdMakF1TVRvME1EQXdMMkZqYldVdgphWE56ZFdWeUxXTmxjblF3T1FZRFZSMFJCREl3TUlJS2JHOWpZV3d4TG1OdmJZSVFkR1Z6ZERFdWJHOWpZV3d4CkxtTnZiWUlRZEdWemRESXViRzlqWVd3eExtTnZiVEFuQmdOVkhSOEVJREFlTUJ5Z0dxQVloaFpvZEhSd09pOHYKWlhoaGJYQnNaUzVqYjIwdlkzSnNNR0VHQTFVZElBUmFNRmd3Q0FZR1o0RU1BUUlCTUV3R0F5b0RCREJGTUNJRwpDQ3NHQVFVRkJ3SUJGaFpvZEhSd09pOHZaWGhoYlhCc1pTNWpiMjB2WTNCek1COEdDQ3NHQVFVRkJ3SUNNQk1NCkVVUnZJRmRvWVhRZ1ZHaHZkU0JYYVd4ME1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ3A0Q2FxZlR4THNQTzQKS2JueDJZdEc4bTN3MC9keTVVR1VRNjZHbGxPVTk0L2I0MmNhbTRuNUZrTWlpZ01IaUx4c2JZVXh0cDZKQ3R5cQpLKzFNcDFWWEtSTTVKbFBTNWRIaWhxdHk1U3BrTUhjampwQSs3U2YyVWtoNmpKRWYxTUVJY2JnWnpJRk5IT0hYClVUUUppVFhKcno3blJDZnlQWFZtbWErUGtIRlU4R0VEVzJGOVptU1kzVFBiQWhiWkV2UkZubjUrR1lxbkZuancKWWw3Y0I2MXYwRzVpOGQwbnVvbTB4a2hiNTU3Y3BiZHhLblhsaFU4N2RZSTR5SUdPdUFGUWpYcXFXN2NIZCtXUQpWSDB2dFA3cEgrRmt2YnY4WkkxMHMrNU5ZcCtzZjFQZGQxekJsRmdNSGF3dnFFYUg3SU9sejdkajlCdmtVc0dpClhxQWVqQnFPCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVpakNDQTNLZ0F3SUJBZ0lDRWswd0RRWUpLb1pJaHZjTkFRRUxCUUF3S3pFcE1DY0dBMVVFQXd3Z1kyRmoKYTJ4cGJtY2dZM0o1Y0hSdlozSmhjR2hsY2lCbVlXdGxJRkpQVDFRd0hoY05NVFV4TURJeE1qQXhNVFV5V2hjTgpNakF4TURFNU1qQXhNVFV5V2pBZk1SMHdHd1lEVlFRREV4Um9ZWEJ3ZVNCb1lXTnJaWElnWm1GclpTQkRRVENDCkFTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTUlLUjNtYUJjVVNzbmNYWXpRVDEzRDUKTnIrWjNtTHhNTWgzVFVkdDZzQUNtcWJKMGJ0UmxnWGZNdE5MTTJPVTFJNmEzSnUrdElaU2RuMnYyMUpCd3Z4VQp6cFpRNHp5MmNpbUlpTVFEWkNRSEp3ekM5R1puOEhhVzA5MWl6OUgwR28zQTdXRFh3WU5tc2RMTlJpMDBvMTRVCmpvYVZxYVBzWXJaV3ZSS2FJUnFhVTBoSG1TMEFXd1FTdk4vOTNpTUlYdXlpd3l3bWt3S2JXbm54Q1EvZ3NjdEsKRlV0Y05yd0V4OVdnajZLbGh3RFR5STFRV1NCYnhWWU55VWdQRnpLeHJTbXdNTzB5TmZmN2hvK1FUOXg1K1kvNwpYRTU5UzRNYzRaWHhjWEtldy9nU2xOOVU1bXZUK0QyQmhEdGtDdXBkZnNaTkNRV3AyN0ErYi9EbXJGSTlOcXNDCkF3RUFBYU9DQWNJd2dnRytNQklHQTFVZEV3RUIvd1FJTUFZQkFmOENBUUF3UXdZRFZSMGVCRHd3T3FFNE1BYUMKQkM1dGFXd3dDb2NJQUFBQUFBQUFBQUF3SW9jZ0FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQpBQUFBQUFBd0RnWURWUjBQQVFIL0JBUURBZ0dHTUg4R0NDc0dBUVVGQndFQkJITXdjVEF5QmdnckJnRUZCUWN3CkFZWW1hSFIwY0RvdkwybHpjbWN1ZEhKMWMzUnBaQzV2WTNOd0xtbGtaVzUwY25WemRDNWpiMjB3T3dZSUt3WUIKQlFVSE1BS0dMMmgwZEhBNkx5OWhjSEJ6TG1sa1pXNTBjblZ6ZEM1amIyMHZjbTl2ZEhNdlpITjBjbTl2ZEdOaAplRE11Y0Rkak1COEdBMVVkSXdRWU1CYUFGT21rUCs2ZXBlYnkxZGQ1WUR5VHBpNGtqcGVxTUZRR0ExVWRJQVJOCk1Fc3dDQVlHWjRFTUFRSUJNRDhHQ3lzR0FRUUJndDhUQVFFQk1EQXdMZ1lJS3dZQkJRVUhBZ0VXSW1oMGRIQTYKTHk5amNITXVjbTl2ZEMxNE1TNXNaWFJ6Wlc1amNubHdkQzV2Y21jd1BBWURWUjBmQkRVd016QXhvQytnTFlZcgphSFIwY0RvdkwyTnliQzVwWkdWdWRISjFjM1F1WTI5dEwwUlRWRkpQVDFSRFFWZ3pRMUpNTG1OeWJEQWRCZ05WCkhRNEVGZ1FVKzNoUEV2bGdGWU1zbnhkL05CbXpMamJxUVlrd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFBMFkKQWVMWE9rbHg0aGhDaWtVVWwrQmRuRmZuMWcwVzVBaVFMVk5JT0w2UG5xWHUwd2puaE55aHFkd25maFlNbm95NAppZFJoNGxCNnB6OEdmOXBubExkL0RuV1NWM2dTKy9JL21BbDFkQ2tLYnk2SDJWNzkwZTZJSG1JSzJLWW0zam0rClUrK0ZJZEdwQmRzUVRTZG1pWC9yQXl1eE1ETTBhZE1rTkJ3VGZRbVpRQ3o2bkdIdzFRY1NQWk12WnBzQzhTa3YKZWt6eHNqRjFvdE9yTVVQTlBRdnRUV3JWeDhHbFIycWZ4LzR4YlFhMXYyZnJOdkZCQ21PNTlnb3oram5XdmZUdApqMk5qd0RaN3ZsTUJzUG0xNmRiS1lDODQwdXZSb1pqeHFzZGMzQ2hDWmpxaW1GcWxORy94b1BBOCtkVGljWnpDClhFOWlqUEljdlc2eTFhYTNiR3c9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
}
}
]
},
"ChallengeCerts": {}
}

View File

@ -1,824 +0,0 @@
package acme
import (
"crypto/tls"
"encoding/base64"
"net/http"
"net/http/httptest"
"reflect"
"sort"
"sync"
"testing"
"time"
acmeprovider "github.com/containous/traefik/provider/acme"
"github.com/containous/traefik/tls/generate"
"github.com/containous/traefik/types"
"github.com/stretchr/testify/assert"
"github.com/xenolf/lego/acme"
)
func TestDomainsSet(t *testing.T) {
testCases := []struct {
input string
expected types.Domains
}{
{
input: "",
expected: types.Domains{},
},
{
input: "foo1.com",
expected: types.Domains{
types.Domain{Main: "foo1.com"},
},
},
{
input: "foo2.com,bar.net",
expected: types.Domains{
types.Domain{
Main: "foo2.com",
SANs: []string{"bar.net"},
},
},
},
{
input: "foo3.com,bar1.net,bar2.net,bar3.net",
expected: types.Domains{
types.Domain{
Main: "foo3.com",
SANs: []string{"bar1.net", "bar2.net", "bar3.net"},
},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.input, func(t *testing.T) {
t.Parallel()
domains := types.Domains{}
domains.Set(test.input)
assert.Exactly(t, test.expected, domains)
})
}
}
func TestDomainsSetAppend(t *testing.T) {
testCases := []struct {
input string
expected types.Domains
}{
{
input: "",
expected: types.Domains{},
},
{
input: "foo1.com",
expected: types.Domains{
types.Domain{Main: "foo1.com"},
},
},
{
input: "foo2.com,bar.net",
expected: types.Domains{
types.Domain{Main: "foo1.com"},
types.Domain{
Main: "foo2.com",
SANs: []string{"bar.net"},
},
},
},
{
input: "foo3.com,bar1.net,bar2.net,bar3.net",
expected: types.Domains{
types.Domain{Main: "foo1.com"},
types.Domain{
Main: "foo2.com",
SANs: []string{"bar.net"},
},
types.Domain{
Main: "foo3.com",
SANs: []string{"bar1.net", "bar2.net", "bar3.net"},
},
},
},
}
// append to
domains := types.Domains{}
for _, test := range testCases {
t.Run(test.input, func(t *testing.T) {
domains.Set(test.input)
assert.Exactly(t, test.expected, domains)
})
}
}
func TestCertificatesRenew(t *testing.T) {
foo1Cert, foo1Key, _ := generate.KeyPair("foo1.com", time.Now())
foo2Cert, foo2Key, _ := generate.KeyPair("foo2.com", time.Now())
domainsCertificates := DomainsCertificates{
lock: sync.RWMutex{},
Certs: []*DomainsCertificate{
{
Domains: types.Domain{
Main: "foo1.com"},
Certificate: &Certificate{
Domain: "foo1.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: foo1Key,
Certificate: foo1Cert,
},
},
{
Domains: types.Domain{
Main: "foo2.com"},
Certificate: &Certificate{
Domain: "foo2.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: foo2Key,
Certificate: foo2Cert,
},
},
},
}
foo1Cert, foo1Key, _ = generate.KeyPair("foo1.com", time.Now())
newCertificate := &Certificate{
Domain: "foo1.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: foo1Key,
Certificate: foo1Cert,
}
err := domainsCertificates.renewCertificates(newCertificate, types.Domain{Main: "foo1.com"})
if err != nil {
t.Errorf("Error in renewCertificates :%v", err)
}
if len(domainsCertificates.Certs) != 2 {
t.Errorf("Expected domainsCertificates length %d %+v\nGot %+v", 2, domainsCertificates.Certs, len(domainsCertificates.Certs))
}
if !reflect.DeepEqual(domainsCertificates.Certs[0].Certificate, newCertificate) {
t.Errorf("Expected new certificate %+v \nGot %+v", newCertificate, domainsCertificates.Certs[0].Certificate)
}
}
func TestRemoveDuplicates(t *testing.T) {
now := time.Now()
fooCert, fooKey, _ := generate.KeyPair("foo.com", now)
foo24Cert, foo24Key, _ := generate.KeyPair("foo.com", now.Add(24*time.Hour))
foo48Cert, foo48Key, _ := generate.KeyPair("foo.com", now.Add(48*time.Hour))
barCert, barKey, _ := generate.KeyPair("bar.com", now)
domainsCertificates := DomainsCertificates{
lock: sync.RWMutex{},
Certs: []*DomainsCertificate{
{
Domains: types.Domain{
Main: "foo.com"},
Certificate: &Certificate{
Domain: "foo.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: foo24Key,
Certificate: foo24Cert,
},
},
{
Domains: types.Domain{
Main: "foo.com"},
Certificate: &Certificate{
Domain: "foo.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: foo48Key,
Certificate: foo48Cert,
},
},
{
Domains: types.Domain{
Main: "foo.com"},
Certificate: &Certificate{
Domain: "foo.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: fooKey,
Certificate: fooCert,
},
},
{
Domains: types.Domain{
Main: "bar.com"},
Certificate: &Certificate{
Domain: "bar.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: barKey,
Certificate: barCert,
},
},
{
Domains: types.Domain{
Main: "foo.com"},
Certificate: &Certificate{
Domain: "foo.com",
CertURL: "url",
CertStableURL: "url",
PrivateKey: foo48Key,
Certificate: foo48Cert,
},
},
},
}
domainsCertificates.Init()
if len(domainsCertificates.Certs) != 2 {
t.Errorf("Expected domainsCertificates length %d %+v\nGot %+v", 2, domainsCertificates.Certs, len(domainsCertificates.Certs))
}
for _, cert := range domainsCertificates.Certs {
switch cert.Domains.Main {
case "bar.com":
continue
case "foo.com":
if !cert.tlsCert.Leaf.NotAfter.Equal(now.Add(48 * time.Hour).Truncate(1 * time.Second)) {
t.Errorf("Bad expiration %s date for domain %+v, now %s", cert.tlsCert.Leaf.NotAfter.String(), cert, now.Add(48*time.Hour).Truncate(1*time.Second).String())
}
default:
t.Errorf("Unknown domain %+v", cert)
}
}
}
func TestNoPreCheckOverride(t *testing.T) {
acme.PreCheckDNS = nil // Irreversable - but not expecting real calls into this during testing process
err := dnsOverrideDelay(0)
if err != nil {
t.Errorf("Error in dnsOverrideDelay :%v", err)
}
if acme.PreCheckDNS != nil {
t.Error("Unexpected change to acme.PreCheckDNS when leaving DNS verification as is.")
}
}
func TestSillyPreCheckOverride(t *testing.T) {
err := dnsOverrideDelay(-5)
if err == nil {
t.Error("Missing expected error in dnsOverrideDelay!")
}
}
func TestPreCheckOverride(t *testing.T) {
acme.PreCheckDNS = nil // Irreversable - but not expecting real calls into this during testing process
err := dnsOverrideDelay(5)
if err != nil {
t.Errorf("Error in dnsOverrideDelay :%v", err)
}
if acme.PreCheckDNS == nil {
t.Error("No change to acme.PreCheckDNS when meant to be adding enforcing override function.")
}
}
func TestAcmeClientCreation(t *testing.T) {
acme.PreCheckDNS = nil // Irreversable - but not expecting real calls into this during testing process
// Lengthy setup to avoid external web requests - oh for easier golang testing!
account := &Account{Email: "f@f"}
account.PrivateKey, _ = base64.StdEncoding.DecodeString(`
MIIBPAIBAAJBAMp2Ni92FfEur+CAvFkgC12LT4l9D53ApbBpDaXaJkzzks+KsLw9zyAxvlrfAyTCQ
7tDnEnIltAXyQ0uOFUUdcMCAwEAAQJAK1FbipATZcT9cGVa5x7KD7usytftLW14heQUPXYNV80r/3
lmnpvjL06dffRpwkYeN8DATQF/QOcy3NNNGDw/4QIhAPAKmiZFxA/qmRXsuU8Zhlzf16WrNZ68K64
asn/h3qZrAiEA1+wFR3WXCPIolOvd7AHjfgcTKQNkoMPywU4FYUNQ1AkCIQDv8yk0qPjckD6HVCPJ
llJh9MC0svjevGtNlxJoE3lmEQIhAKXy1wfZ32/XtcrnENPvi6lzxI0T94X7s5pP3aCoPPoJAiEAl
cijFkALeQp/qyeXdFld2v9gUN3eCgljgcl0QweRoIc=---`)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{
"GPHhmRVEDas": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417",
"keyChange": "https://foo/acme/key-change",
"meta": {
"termsOfService": "https://boulder:4431/terms/v7"
},
"newAccount": "https://foo/acme/new-acct",
"newNonce": "https://foo/acme/new-nonce",
"newOrder": "https://foo/acme/new-order",
"revokeCert": "https://foo/acme/revoke-cert"
}`))
}))
defer ts.Close()
a := ACME{DNSChallenge: &acmeprovider.DNSChallenge{Provider: "manual", DelayBeforeCheck: 10}, CAServer: ts.URL}
client, err := a.buildACMEClient(account)
if err != nil {
t.Errorf("Error in buildACMEClient: %v", err)
}
if client == nil {
t.Error("No client from buildACMEClient!")
}
if acme.PreCheckDNS == nil {
t.Error("No change to acme.PreCheckDNS when meant to be adding enforcing override function.")
}
}
func TestAcme_getUncheckedCertificates(t *testing.T) {
mm := make(map[string]*tls.Certificate)
mm["*.containo.us"] = &tls.Certificate{}
mm["traefik.acme.io"] = &tls.Certificate{}
dm := make(map[string]struct{})
dm["*.traefik.wtf"] = struct{}{}
a := ACME{TLSConfig: &tls.Config{NameToCertificate: mm}, resolvingDomains: dm}
domains := []string{"traefik.containo.us", "trae.containo.us", "foo.traefik.wtf"}
uncheckedDomains := a.getUncheckedDomains(domains, nil)
assert.Empty(t, uncheckedDomains)
domains = []string{"traefik.acme.io", "trae.acme.io"}
uncheckedDomains = a.getUncheckedDomains(domains, nil)
assert.Len(t, uncheckedDomains, 1)
domainsCertificates := DomainsCertificates{Certs: []*DomainsCertificate{
{
tlsCert: &tls.Certificate{},
Domains: types.Domain{
Main: "*.acme.wtf",
SANs: []string{"trae.acme.io"},
},
},
}}
account := Account{DomainsCertificate: domainsCertificates}
uncheckedDomains = a.getUncheckedDomains(domains, &account)
assert.Empty(t, uncheckedDomains)
domains = []string{"traefik.containo.us", "trae.containo.us", "traefik.wtf"}
uncheckedDomains = a.getUncheckedDomains(domains, nil)
assert.Len(t, uncheckedDomains, 1)
}
func TestAcme_getProvidedCertificate(t *testing.T) {
mm := make(map[string]*tls.Certificate)
mm["*.containo.us"] = &tls.Certificate{}
mm["traefik.acme.io"] = &tls.Certificate{}
a := ACME{TLSConfig: &tls.Config{NameToCertificate: mm}}
domain := "traefik.containo.us"
certificate := a.getProvidedCertificate(domain)
assert.NotNil(t, certificate)
domain = "trae.acme.io"
certificate = a.getProvidedCertificate(domain)
assert.Nil(t, certificate)
}
func TestAcme_getValidDomain(t *testing.T) {
testCases := []struct {
desc string
domains []string
wildcardAllowed bool
dnsChallenge *acmeprovider.DNSChallenge
expectedErr string
expectedDomains []string
}{
{
desc: "valid wildcard",
domains: []string{"*.traefik.wtf"},
dnsChallenge: &acmeprovider.DNSChallenge{},
wildcardAllowed: true,
expectedErr: "",
expectedDomains: []string{"*.traefik.wtf"},
},
{
desc: "no wildcard",
domains: []string{"traefik.wtf", "foo.traefik.wtf"},
dnsChallenge: &acmeprovider.DNSChallenge{},
expectedErr: "",
wildcardAllowed: true,
expectedDomains: []string{"traefik.wtf", "foo.traefik.wtf"},
},
{
desc: "unauthorized wildcard",
domains: []string{"*.traefik.wtf"},
dnsChallenge: &acmeprovider.DNSChallenge{},
wildcardAllowed: false,
expectedErr: "unable to generate a wildcard certificate for domain \"*.traefik.wtf\" from a 'Host' rule",
expectedDomains: nil,
},
{
desc: "no domain",
domains: []string{},
dnsChallenge: nil,
wildcardAllowed: true,
expectedErr: "unable to generate a certificate when no domain is given",
expectedDomains: nil,
},
{
desc: "no DNSChallenge",
domains: []string{"*.traefik.wtf", "foo.traefik.wtf"},
dnsChallenge: nil,
wildcardAllowed: true,
expectedErr: "unable to generate a wildcard certificate for domain \"*.traefik.wtf,foo.traefik.wtf\" : ACME needs a DNSChallenge",
expectedDomains: nil,
},
{
desc: "unauthorized wildcard with SAN",
domains: []string{"*.*.traefik.wtf", "foo.traefik.wtf"},
dnsChallenge: &acmeprovider.DNSChallenge{},
wildcardAllowed: true,
expectedErr: "unable to generate a wildcard certificate for domain \"*.*.traefik.wtf,foo.traefik.wtf\" : ACME does not allow '*.*' wildcard domain",
expectedDomains: nil,
},
{
desc: "wildcard with SANs",
domains: []string{"*.traefik.wtf", "traefik.wtf"},
dnsChallenge: &acmeprovider.DNSChallenge{},
wildcardAllowed: true,
expectedErr: "",
expectedDomains: []string{"*.traefik.wtf", "traefik.wtf"},
},
{
desc: "unexpected SANs",
domains: []string{"*.traefik.wtf", "*.acme.wtf"},
dnsChallenge: &acmeprovider.DNSChallenge{},
wildcardAllowed: true,
expectedErr: "unable to generate a certificate for domains \"*.traefik.wtf,*.acme.wtf\": SANs can not be a wildcard domain",
expectedDomains: nil,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
a := ACME{}
if test.dnsChallenge != nil {
a.DNSChallenge = test.dnsChallenge
}
domains, err := a.getValidDomains(test.domains, test.wildcardAllowed)
if len(test.expectedErr) > 0 {
assert.EqualError(t, err, test.expectedErr, "Unexpected error.")
} else {
assert.Equal(t, len(test.expectedDomains), len(domains), "Unexpected domains.")
}
})
}
}
func TestAcme_getCertificateForDomain(t *testing.T) {
testCases := []struct {
desc string
domain string
dc *DomainsCertificates
expected *DomainsCertificate
expectedFound bool
}{
{
desc: "non-wildcard exact match",
domain: "foo.traefik.wtf",
dc: &DomainsCertificates{
Certs: []*DomainsCertificate{
{
Domains: types.Domain{
Main: "foo.traefik.wtf",
},
},
},
},
expected: &DomainsCertificate{
Domains: types.Domain{
Main: "foo.traefik.wtf",
},
},
expectedFound: true,
},
{
desc: "non-wildcard no match",
domain: "bar.traefik.wtf",
dc: &DomainsCertificates{
Certs: []*DomainsCertificate{
{
Domains: types.Domain{
Main: "foo.traefik.wtf",
},
},
},
},
expected: nil,
expectedFound: false,
},
{
desc: "wildcard match",
domain: "foo.traefik.wtf",
dc: &DomainsCertificates{
Certs: []*DomainsCertificate{
{
Domains: types.Domain{
Main: "*.traefik.wtf",
},
},
},
},
expected: &DomainsCertificate{
Domains: types.Domain{
Main: "*.traefik.wtf",
},
},
expectedFound: true,
},
{
desc: "wildcard no match",
domain: "foo.traefik.wtf",
dc: &DomainsCertificates{
Certs: []*DomainsCertificate{
{
Domains: types.Domain{
Main: "*.bar.traefik.wtf",
},
},
},
},
expected: nil,
expectedFound: false,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
got, found := test.dc.getCertificateForDomain(test.domain)
assert.Equal(t, test.expectedFound, found)
assert.Equal(t, test.expected, got)
})
}
}
func TestRemoveEmptyCertificates(t *testing.T) {
now := time.Now()
fooCert, fooKey, _ := generate.KeyPair("foo.com", now)
acmeCert, acmeKey, _ := generate.KeyPair("acme.wtf", now.Add(24*time.Hour))
barCert, barKey, _ := generate.KeyPair("bar.com", now)
testCases := []struct {
desc string
dc *DomainsCertificates
expectedDc *DomainsCertificates
}{
{
desc: "No empty certificate",
dc: &DomainsCertificates{
Certs: []*DomainsCertificate{
{
Certificate: &Certificate{
Certificate: fooCert,
PrivateKey: fooKey,
},
Domains: types.Domain{
Main: "foo.com",
},
},
{
Certificate: &Certificate{
Certificate: acmeCert,
PrivateKey: acmeKey,
},
Domains: types.Domain{
Main: "acme.wtf",
},
},
{
Certificate: &Certificate{
Certificate: barCert,
PrivateKey: barKey,
},
Domains: types.Domain{
Main: "bar.com",
},
},
},
},
expectedDc: &DomainsCertificates{
Certs: []*DomainsCertificate{
{
Certificate: &Certificate{
Certificate: fooCert,
PrivateKey: fooKey,
},
Domains: types.Domain{
Main: "foo.com",
},
},
{
Certificate: &Certificate{
Certificate: acmeCert,
PrivateKey: acmeKey,
},
Domains: types.Domain{
Main: "acme.wtf",
},
},
{
Certificate: &Certificate{
Certificate: barCert,
PrivateKey: barKey,
},
Domains: types.Domain{
Main: "bar.com",
},
},
},
},
},
{
desc: "First certificate is nil",
dc: &DomainsCertificates{
Certs: []*DomainsCertificate{
{
Domains: types.Domain{
Main: "foo.com",
},
},
{
Certificate: &Certificate{
Certificate: acmeCert,
PrivateKey: acmeKey,
},
Domains: types.Domain{
Main: "acme.wtf",
},
},
{
Certificate: &Certificate{
Certificate: barCert,
PrivateKey: barKey,
},
Domains: types.Domain{
Main: "bar.com",
},
},
},
},
expectedDc: &DomainsCertificates{
Certs: []*DomainsCertificate{
{
Certificate: &Certificate{
Certificate: acmeCert,
PrivateKey: acmeKey,
},
Domains: types.Domain{
Main: "acme.wtf",
},
},
{
Certificate: &Certificate{
Certificate: nil,
PrivateKey: barKey,
},
Domains: types.Domain{
Main: "bar.com",
},
},
},
},
},
{
desc: "Last certificate is empty",
dc: &DomainsCertificates{
Certs: []*DomainsCertificate{
{
Certificate: &Certificate{
Certificate: fooCert,
PrivateKey: fooKey,
},
Domains: types.Domain{
Main: "foo.com",
},
},
{
Certificate: &Certificate{
Certificate: acmeCert,
PrivateKey: acmeKey,
},
Domains: types.Domain{
Main: "acme.wtf",
},
},
{
Certificate: &Certificate{},
Domains: types.Domain{
Main: "bar.com",
},
},
},
},
expectedDc: &DomainsCertificates{
Certs: []*DomainsCertificate{
{
Certificate: &Certificate{
Certificate: fooCert,
PrivateKey: fooKey,
},
Domains: types.Domain{
Main: "foo.com",
},
},
{
Certificate: &Certificate{
Certificate: acmeCert,
PrivateKey: acmeKey,
},
Domains: types.Domain{
Main: "acme.wtf",
},
},
},
},
},
{
desc: "First and last certificates are nil or empty",
dc: &DomainsCertificates{
Certs: []*DomainsCertificate{
{
Domains: types.Domain{
Main: "foo.com",
},
},
{
Certificate: &Certificate{
Certificate: acmeCert,
PrivateKey: acmeKey,
},
Domains: types.Domain{
Main: "acme.wtf",
},
},
{
Certificate: &Certificate{},
Domains: types.Domain{
Main: "bar.com",
},
},
},
},
expectedDc: &DomainsCertificates{
Certs: []*DomainsCertificate{
{
Certificate: &Certificate{
Certificate: acmeCert,
PrivateKey: acmeKey,
},
Domains: types.Domain{
Main: "acme.wtf",
},
},
},
},
},
{
desc: "All certificates are nil or empty",
dc: &DomainsCertificates{
Certs: []*DomainsCertificate{
{
Domains: types.Domain{
Main: "foo.com",
},
},
{
Domains: types.Domain{
Main: "foo24.com",
},
},
{
Certificate: &Certificate{},
Domains: types.Domain{
Main: "bar.com",
},
},
},
},
expectedDc: &DomainsCertificates{
Certs: []*DomainsCertificate{},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
a := &Account{DomainsCertificate: *test.dc}
a.Init()
assert.Equal(t, len(test.expectedDc.Certs), len(a.DomainsCertificate.Certs))
sort.Sort(&a.DomainsCertificate)
sort.Sort(test.expectedDc)
for key, value := range test.expectedDc.Certs {
assert.Equal(t, value.Domains.Main, a.DomainsCertificate.Certs[key].Domains.Main)
}
})
}
}

View File

@ -1,104 +0,0 @@
package acme
import (
"fmt"
"sync"
"time"
"github.com/cenk/backoff"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/xenolf/lego/acme"
)
var _ acme.ChallengeProviderTimeout = (*challengeHTTPProvider)(nil)
type challengeHTTPProvider struct {
store cluster.Store
lock sync.RWMutex
}
func (c *challengeHTTPProvider) getTokenValue(token, domain string) []byte {
log.Debugf("Looking for an existing ACME challenge for token %v...", token)
c.lock.RLock()
defer c.lock.RUnlock()
account := c.store.Get().(*Account)
if account.HTTPChallenge == nil {
return []byte{}
}
var result []byte
operation := func() error {
var ok bool
if result, ok = account.HTTPChallenge[token][domain]; !ok {
return fmt.Errorf("cannot find challenge for token %v", token)
}
return nil
}
notify := func(err error, time time.Duration) {
log.Errorf("Error getting challenge for token retrying in %s", time)
}
ebo := backoff.NewExponentialBackOff()
ebo.MaxElapsedTime = 60 * time.Second
err := backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify)
if err != nil {
log.Errorf("Error getting challenge for token: %v", err)
return []byte{}
}
return result
}
func (c *challengeHTTPProvider) Present(domain, token, keyAuth string) error {
log.Debugf("Challenge Present %s", domain)
c.lock.Lock()
defer c.lock.Unlock()
transaction, object, err := c.store.Begin()
if err != nil {
return err
}
account := object.(*Account)
if account.HTTPChallenge == nil {
account.HTTPChallenge = map[string]map[string][]byte{}
}
if _, ok := account.HTTPChallenge[token]; !ok {
account.HTTPChallenge[token] = map[string][]byte{}
}
account.HTTPChallenge[token][domain] = []byte(keyAuth)
return transaction.Commit(account)
}
func (c *challengeHTTPProvider) CleanUp(domain, token, keyAuth string) error {
log.Debugf("Challenge CleanUp %s", domain)
c.lock.Lock()
defer c.lock.Unlock()
transaction, object, err := c.store.Begin()
if err != nil {
return err
}
account := object.(*Account)
if _, ok := account.HTTPChallenge[token]; ok {
if _, domainOk := account.HTTPChallenge[token][domain]; domainOk {
delete(account.HTTPChallenge[token], domain)
}
if len(account.HTTPChallenge[token]) == 0 {
delete(account.HTTPChallenge, token)
}
}
return transaction.Commit(account)
}
func (c *challengeHTTPProvider) Timeout() (timeout, interval time.Duration) {
return 60 * time.Second, 5 * time.Second
}

View File

@ -1,127 +0,0 @@
package acme
import (
"crypto/tls"
"fmt"
"strings"
"sync"
"time"
"github.com/cenk/backoff"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/xenolf/lego/acme"
)
var _ acme.ChallengeProviderTimeout = (*challengeTLSProvider)(nil)
type challengeTLSProvider struct {
store cluster.Store
lock sync.RWMutex
}
func (c *challengeTLSProvider) getCertificate(domain string) (cert *tls.Certificate, exists bool) {
log.Debugf("Looking for an existing ACME challenge for %s...", domain)
if !strings.HasSuffix(domain, ".acme.invalid") {
return nil, false
}
c.lock.RLock()
defer c.lock.RUnlock()
account := c.store.Get().(*Account)
if account.ChallengeCerts == nil {
return nil, false
}
account.Init()
var result *tls.Certificate
operation := func() error {
for _, cert := range account.ChallengeCerts {
for _, dns := range cert.certificate.Leaf.DNSNames {
if domain == dns {
result = cert.certificate
return nil
}
}
}
return fmt.Errorf("cannot find challenge cert for domain %s", domain)
}
notify := func(err error, time time.Duration) {
log.Errorf("Error getting cert: %v, retrying in %s", err, time)
}
ebo := backoff.NewExponentialBackOff()
ebo.MaxElapsedTime = 60 * time.Second
err := backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify)
if err != nil {
log.Errorf("Error getting cert: %v", err)
return nil, false
}
return result, true
}
func (c *challengeTLSProvider) Present(domain, token, keyAuth string) error {
log.Debugf("Challenge Present %s", domain)
cert, err := tlsALPN01ChallengeCert(domain, keyAuth)
if err != nil {
return err
}
c.lock.Lock()
defer c.lock.Unlock()
transaction, object, err := c.store.Begin()
if err != nil {
return err
}
account := object.(*Account)
if account.ChallengeCerts == nil {
account.ChallengeCerts = map[string]*ChallengeCert{}
}
account.ChallengeCerts[domain] = cert
return transaction.Commit(account)
}
func (c *challengeTLSProvider) CleanUp(domain, token, keyAuth string) error {
log.Debugf("Challenge CleanUp %s", domain)
c.lock.Lock()
defer c.lock.Unlock()
transaction, object, err := c.store.Begin()
if err != nil {
return err
}
account := object.(*Account)
delete(account.ChallengeCerts, domain)
return transaction.Commit(account)
}
func (c *challengeTLSProvider) Timeout() (timeout, interval time.Duration) {
return 60 * time.Second, 5 * time.Second
}
func tlsALPN01ChallengeCert(domain, keyAuth string) (*ChallengeCert, error) {
tempCertPEM, rsaPrivPEM, err := acme.TLSALPNChallengeBlocks(domain, keyAuth)
if err != nil {
return nil, err
}
certificate, err := tls.X509KeyPair(tempCertPEM, rsaPrivPEM)
if err != nil {
return nil, err
}
return &ChallengeCert{Certificate: tempCertPEM, PrivateKey: rsaPrivPEM, certificate: &certificate}, nil
}

View File

@ -1,177 +0,0 @@
package acme
import (
"encoding/json"
"io/ioutil"
"os"
"github.com/containous/traefik/log"
"github.com/containous/traefik/provider/acme"
)
// LocalStore is a store using a file as storage
type LocalStore struct {
file string
}
// NewLocalStore create a LocalStore
func NewLocalStore(file string) *LocalStore {
return &LocalStore{
file: file,
}
}
// Get loads file into store and returns the Account
func (s *LocalStore) Get() (*Account, error) {
account := &Account{}
hasData, err := acme.CheckFile(s.file)
if err != nil {
return nil, err
}
if hasData {
f, err := os.Open(s.file)
if err != nil {
return nil, err
}
defer f.Close()
file, err := ioutil.ReadAll(f)
if err != nil {
return nil, err
}
if err := json.Unmarshal(file, &account); err != nil {
return nil, err
}
}
return account, nil
}
// ConvertToNewFormat converts old acme.json format to the new one and store the result into the file (used for the backward compatibility)
func ConvertToNewFormat(fileName string) {
localStore := acme.NewLocalStore(fileName)
storeAccount, err := localStore.GetAccount()
if err != nil {
log.Errorf("Failed to read new account, ACME data conversion is not available : %v", err)
return
}
storeCertificates, err := localStore.GetCertificates()
if err != nil {
log.Errorf("Failed to read new certificates, ACME data conversion is not available : %v", err)
return
}
if storeAccount == nil {
localStore := NewLocalStore(fileName)
account, err := localStore.Get()
if err != nil {
log.Errorf("Failed to read old account, ACME data conversion is not available : %v", err)
return
}
// Convert ACME data from old to new format
newAccount := &acme.Account{}
if account != nil && len(account.Email) > 0 {
err = backupACMEFile(fileName, account)
if err != nil {
log.Errorf("Unable to create a backup for the V1 formatted ACME file: %v", err)
return
}
err = account.RemoveAccountV1Values()
if err != nil {
log.Errorf("Unable to remove ACME Account V1 values during format conversion: %v", err)
return
}
newAccount = &acme.Account{
PrivateKey: account.PrivateKey,
Registration: account.Registration,
Email: account.Email,
KeyType: account.KeyType,
}
var newCertificates []*acme.Certificate
for _, cert := range account.DomainsCertificate.Certs {
newCertificates = append(newCertificates, &acme.Certificate{
Certificate: cert.Certificate.Certificate,
Key: cert.Certificate.PrivateKey,
Domain: cert.Domains,
})
}
// If account is in the old format, storeCertificates is nil or empty and has to be initialized
storeCertificates = newCertificates
}
// Store the data in new format into the file even if account is nil
// to delete Account in ACME v1 format and keeping the certificates
newLocalStore := acme.NewLocalStore(fileName)
newLocalStore.SaveDataChan <- &acme.StoredData{Account: newAccount, Certificates: storeCertificates}
}
}
func backupACMEFile(originalFileName string, account interface{}) error {
// write account to file
data, err := json.MarshalIndent(account, "", " ")
if err != nil {
return err
}
return ioutil.WriteFile(originalFileName+".bak", data, 0600)
}
// FromNewToOldFormat converts new acme account to the old one (used for the backward compatibility)
func FromNewToOldFormat(fileName string) (*Account, error) {
localStore := acme.NewLocalStore(fileName)
storeAccount, err := localStore.GetAccount()
if err != nil {
return nil, err
}
storeCertificates, err := localStore.GetCertificates()
if err != nil {
return nil, err
}
// Convert ACME Account from new to old format
// (Needed by the KV stores)
var account *Account
if storeAccount != nil {
account = &Account{
Email: storeAccount.Email,
PrivateKey: storeAccount.PrivateKey,
Registration: storeAccount.Registration,
DomainsCertificate: DomainsCertificates{},
KeyType: storeAccount.KeyType,
}
}
// Convert ACME Certificates from new to old format
// (Needed by the KV stores)
if len(storeCertificates) > 0 {
// Account can be nil if data are migrated from new format
// with a ACME V1 Account
if account == nil {
account = &Account{}
}
for _, cert := range storeCertificates {
_, err := account.DomainsCertificate.addCertificateForDomains(&Certificate{
Domain: cert.Domain.Main,
Certificate: cert.Certificate,
PrivateKey: cert.Key,
}, cert.Domain)
if err != nil {
return nil, err
}
}
}
return account, nil
}

View File

@ -1,31 +0,0 @@
package acme
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
func TestGet(t *testing.T) {
acmeFile := "./acme_example.json"
folder, prefix := filepath.Split(acmeFile)
tmpFile, err := ioutil.TempFile(folder, prefix)
defer os.Remove(tmpFile.Name())
assert.NoError(t, err)
fileContent, err := ioutil.ReadFile(acmeFile)
assert.NoError(t, err)
tmpFile.Write(fileContent)
localStore := NewLocalStore(tmpFile.Name())
account, err := localStore.Get()
assert.NoError(t, err)
assert.Len(t, account.DomainsCertificate.Certs, 1)
}

View File

@ -1,136 +0,0 @@
package anonymize
import (
"encoding/json"
"fmt"
"reflect"
"regexp"
"github.com/mitchellh/copystructure"
"github.com/mvdan/xurls"
)
const (
maskShort = "xxxx"
maskLarge = maskShort + maskShort + maskShort + maskShort + maskShort + maskShort + maskShort + maskShort
)
// Do configuration.
func Do(baseConfig interface{}, indent bool) (string, error) {
anomConfig, err := copystructure.Copy(baseConfig)
if err != nil {
return "", err
}
val := reflect.ValueOf(anomConfig)
err = doOnStruct(val)
if err != nil {
return "", err
}
configJSON, err := marshal(anomConfig, indent)
if err != nil {
return "", err
}
return doOnJSON(string(configJSON)), nil
}
func doOnJSON(input string) string {
mailExp := regexp.MustCompile(`\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3}"`)
return xurls.Relaxed.ReplaceAllString(mailExp.ReplaceAllString(input, maskLarge+"\""), maskLarge)
}
func doOnStruct(field reflect.Value) error {
switch field.Kind() {
case reflect.Ptr:
if !field.IsNil() {
if err := doOnStruct(field.Elem()); err != nil {
return err
}
}
case reflect.Struct:
for i := 0; i < field.NumField(); i++ {
fld := field.Field(i)
stField := field.Type().Field(i)
if !isExported(stField) {
continue
}
if stField.Tag.Get("export") == "true" {
if err := doOnStruct(fld); err != nil {
return err
}
} else {
if err := reset(fld, stField.Name); err != nil {
return err
}
}
}
case reflect.Map:
for _, key := range field.MapKeys() {
if err := doOnStruct(field.MapIndex(key)); err != nil {
return err
}
}
case reflect.Slice:
for j := 0; j < field.Len(); j++ {
if err := doOnStruct(field.Index(j)); err != nil {
return err
}
}
}
return nil
}
func reset(field reflect.Value, name string) error {
if !field.CanSet() {
return fmt.Errorf("cannot reset field %s", name)
}
switch field.Kind() {
case reflect.Ptr:
if !field.IsNil() {
field.Set(reflect.Zero(field.Type()))
}
case reflect.Struct:
if field.IsValid() {
field.Set(reflect.Zero(field.Type()))
}
case reflect.String:
if field.String() != "" {
field.Set(reflect.ValueOf(maskShort))
}
case reflect.Map:
if field.Len() > 0 {
field.Set(reflect.MakeMap(field.Type()))
}
case reflect.Slice:
if field.Len() > 0 {
field.Set(reflect.MakeSlice(field.Type(), 0, 0))
}
case reflect.Interface:
if !field.IsNil() {
return reset(field.Elem(), "")
}
default:
// Primitive type
field.Set(reflect.Zero(field.Type()))
}
return nil
}
// isExported return true is a struct field is exported, else false
func isExported(f reflect.StructField) bool {
if f.PkgPath != "" && !f.Anonymous {
return false
}
return true
}
func marshal(anomConfig interface{}, indent bool) ([]byte, error) {
if indent {
return json.MarshalIndent(anomConfig, "", " ")
}
return json.Marshal(anomConfig)
}

View File

@ -1,700 +0,0 @@
package anonymize
import (
"crypto/tls"
"os"
"testing"
"time"
"github.com/containous/flaeg"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/api"
"github.com/containous/traefik/configuration"
"github.com/containous/traefik/middlewares"
"github.com/containous/traefik/provider"
acmeprovider "github.com/containous/traefik/provider/acme"
"github.com/containous/traefik/provider/boltdb"
"github.com/containous/traefik/provider/consul"
"github.com/containous/traefik/provider/consulcatalog"
"github.com/containous/traefik/provider/docker"
"github.com/containous/traefik/provider/dynamodb"
"github.com/containous/traefik/provider/ecs"
"github.com/containous/traefik/provider/etcd"
"github.com/containous/traefik/provider/eureka"
"github.com/containous/traefik/provider/file"
"github.com/containous/traefik/provider/kubernetes"
"github.com/containous/traefik/provider/kv"
"github.com/containous/traefik/provider/marathon"
"github.com/containous/traefik/provider/mesos"
"github.com/containous/traefik/provider/rancher"
"github.com/containous/traefik/provider/zk"
"github.com/containous/traefik/safe"
traefiktls "github.com/containous/traefik/tls"
"github.com/containous/traefik/types"
"github.com/elazarl/go-bindata-assetfs"
"github.com/thoas/stats"
)
func TestDo_globalConfiguration(t *testing.T) {
config := &configuration.GlobalConfiguration{}
config.GraceTimeOut = flaeg.Duration(666 * time.Second)
config.Debug = true
config.CheckNewVersion = true
config.AccessLogsFile = "AccessLogsFile"
config.AccessLog = &types.AccessLog{
FilePath: "AccessLog FilePath",
Format: "AccessLog Format",
}
config.TraefikLogsFile = "TraefikLogsFile"
config.LogLevel = "LogLevel"
config.EntryPoints = configuration.EntryPoints{
"foo": {
Address: "foo Address",
TLS: &traefiktls.TLS{
MinVersion: "foo MinVersion",
CipherSuites: []string{"foo CipherSuites 1", "foo CipherSuites 2", "foo CipherSuites 3"},
Certificates: traefiktls.Certificates{
{CertFile: "CertFile 1", KeyFile: "KeyFile 1"},
{CertFile: "CertFile 2", KeyFile: "KeyFile 2"},
},
ClientCA: traefiktls.ClientCA{
Files: traefiktls.FilesOrContents{"foo ClientCAFiles 1", "foo ClientCAFiles 2", "foo ClientCAFiles 3"},
Optional: false,
},
},
Redirect: &types.Redirect{
Replacement: "foo Replacement",
Regex: "foo Regex",
EntryPoint: "foo EntryPoint",
},
Auth: &types.Auth{
Basic: &types.Basic{
UsersFile: "foo Basic UsersFile",
Users: types.Users{"foo Basic Users 1", "foo Basic Users 2", "foo Basic Users 3"},
},
Digest: &types.Digest{
UsersFile: "foo Digest UsersFile",
Users: types.Users{"foo Digest Users 1", "foo Digest Users 2", "foo Digest Users 3"},
},
Forward: &types.Forward{
Address: "foo Address",
TLS: &types.ClientTLS{
CA: "foo CA",
Cert: "foo Cert",
Key: "foo Key",
InsecureSkipVerify: true,
},
TrustForwardHeader: true,
},
},
WhitelistSourceRange: []string{"foo WhitelistSourceRange 1", "foo WhitelistSourceRange 2", "foo WhitelistSourceRange 3"},
Compress: true,
ProxyProtocol: &configuration.ProxyProtocol{
TrustedIPs: []string{"127.0.0.1/32", "192.168.0.1"},
},
},
"fii": {
Address: "fii Address",
TLS: &traefiktls.TLS{
MinVersion: "fii MinVersion",
CipherSuites: []string{"fii CipherSuites 1", "fii CipherSuites 2", "fii CipherSuites 3"},
Certificates: traefiktls.Certificates{
{CertFile: "CertFile 1", KeyFile: "KeyFile 1"},
{CertFile: "CertFile 2", KeyFile: "KeyFile 2"},
},
ClientCA: traefiktls.ClientCA{
Files: traefiktls.FilesOrContents{"fii ClientCAFiles 1", "fii ClientCAFiles 2", "fii ClientCAFiles 3"},
Optional: false,
},
},
Redirect: &types.Redirect{
Replacement: "fii Replacement",
Regex: "fii Regex",
EntryPoint: "fii EntryPoint",
},
Auth: &types.Auth{
Basic: &types.Basic{
UsersFile: "fii Basic UsersFile",
Users: types.Users{"fii Basic Users 1", "fii Basic Users 2", "fii Basic Users 3"},
},
Digest: &types.Digest{
UsersFile: "fii Digest UsersFile",
Users: types.Users{"fii Digest Users 1", "fii Digest Users 2", "fii Digest Users 3"},
},
Forward: &types.Forward{
Address: "fii Address",
TLS: &types.ClientTLS{
CA: "fii CA",
Cert: "fii Cert",
Key: "fii Key",
InsecureSkipVerify: true,
},
TrustForwardHeader: true,
},
},
WhitelistSourceRange: []string{"fii WhitelistSourceRange 1", "fii WhitelistSourceRange 2", "fii WhitelistSourceRange 3"},
Compress: true,
ProxyProtocol: &configuration.ProxyProtocol{
TrustedIPs: []string{"127.0.0.1/32", "192.168.0.1"},
},
},
}
config.Cluster = &types.Cluster{
Node: "Cluster Node",
Store: &types.Store{
Prefix: "Cluster Store Prefix",
// ...
},
}
config.Constraints = types.Constraints{
{
Key: "Constraints Key 1",
Regex: "Constraints Regex 2",
MustMatch: true,
},
{
Key: "Constraints Key 1",
Regex: "Constraints Regex 2",
MustMatch: true,
},
}
config.ACME = &acme.ACME{
Email: "acme Email",
Domains: []types.Domain{
{
Main: "Domains Main",
SANs: []string{"Domains acme SANs 1", "Domains acme SANs 2", "Domains acme SANs 3"},
},
},
Storage: "Storage",
StorageFile: "StorageFile",
OnDemand: true,
OnHostRule: true,
CAServer: "CAServer",
EntryPoint: "EntryPoint",
DNSChallenge: &acmeprovider.DNSChallenge{Provider: "DNSProvider"},
DelayDontCheckDNS: 666,
ACMELogging: true,
TLSConfig: &tls.Config{
InsecureSkipVerify: true,
// ...
},
}
config.DefaultEntryPoints = configuration.DefaultEntryPoints{"DefaultEntryPoints 1", "DefaultEntryPoints 2", "DefaultEntryPoints 3"}
config.ProvidersThrottleDuration = flaeg.Duration(666 * time.Second)
config.MaxIdleConnsPerHost = 666
config.IdleTimeout = flaeg.Duration(666 * time.Second)
config.InsecureSkipVerify = true
config.RootCAs = traefiktls.FilesOrContents{"RootCAs 1", "RootCAs 2", "RootCAs 3"}
config.Retry = &configuration.Retry{
Attempts: 666,
}
config.HealthCheck = &configuration.HealthCheckConfig{
Interval: flaeg.Duration(666 * time.Second),
}
config.API = &api.Handler{
EntryPoint: "traefik",
Dashboard: true,
Debug: true,
CurrentConfigurations: &safe.Safe{},
Statistics: &types.Statistics{
RecentErrors: 666,
},
Stats: &stats.Stats{
Uptime: time.Now(),
Pid: 666,
ResponseCounts: map[string]int{"foo": 1},
TotalResponseCounts: map[string]int{"bar": 1},
TotalResponseTime: time.Now(),
},
StatsRecorder: &middlewares.StatsRecorder{},
DashboardAssets: &assetfs.AssetFS{
Asset: func(path string) ([]byte, error) {
return nil, nil
},
AssetDir: func(path string) ([]string, error) {
return nil, nil
},
AssetInfo: func(path string) (os.FileInfo, error) {
return nil, nil
},
Prefix: "fii",
},
}
config.RespondingTimeouts = &configuration.RespondingTimeouts{
ReadTimeout: flaeg.Duration(666 * time.Second),
WriteTimeout: flaeg.Duration(666 * time.Second),
IdleTimeout: flaeg.Duration(666 * time.Second),
}
config.ForwardingTimeouts = &configuration.ForwardingTimeouts{
DialTimeout: flaeg.Duration(666 * time.Second),
ResponseHeaderTimeout: flaeg.Duration(666 * time.Second),
}
config.Docker = &docker.Provider{
BaseProvider: provider.BaseProvider{
Watch: true,
Filename: "docker Filename",
Constraints: types.Constraints{
{
Key: "docker Constraints Key 1",
Regex: "docker Constraints Regex 2",
MustMatch: true,
},
{
Key: "docker Constraints Key 1",
Regex: "docker Constraints Regex 2",
MustMatch: true,
},
},
Trace: true,
DebugLogGeneratedTemplate: true,
},
Endpoint: "docker Endpoint",
Domain: "docker Domain",
TLS: &types.ClientTLS{
CA: "docker CA",
Cert: "docker Cert",
Key: "docker Key",
InsecureSkipVerify: true,
},
ExposedByDefault: true,
UseBindPortIP: true,
SwarmMode: true,
}
config.File = &file.Provider{
BaseProvider: provider.BaseProvider{
Watch: true,
Filename: "file Filename",
Constraints: types.Constraints{
{
Key: "file Constraints Key 1",
Regex: "file Constraints Regex 2",
MustMatch: true,
},
{
Key: "file Constraints Key 1",
Regex: "file Constraints Regex 2",
MustMatch: true,
},
},
Trace: true,
DebugLogGeneratedTemplate: true,
},
Directory: "file Directory",
}
config.Web = &configuration.WebCompatibility{
Address: "web Address",
CertFile: "web CertFile",
KeyFile: "web KeyFile",
ReadOnly: true,
Statistics: &types.Statistics{
RecentErrors: 666,
},
Metrics: &types.Metrics{
Prometheus: &types.Prometheus{
Buckets: types.Buckets{6.5, 6.6, 6.7},
},
Datadog: &types.Datadog{
Address: "Datadog Address",
PushInterval: "Datadog PushInterval",
},
StatsD: &types.Statsd{
Address: "StatsD Address",
PushInterval: "StatsD PushInterval",
},
},
Path: "web Path",
Auth: &types.Auth{
Basic: &types.Basic{
UsersFile: "web Basic UsersFile",
Users: types.Users{"web Basic Users 1", "web Basic Users 2", "web Basic Users 3"},
},
Digest: &types.Digest{
UsersFile: "web Digest UsersFile",
Users: types.Users{"web Digest Users 1", "web Digest Users 2", "web Digest Users 3"},
},
Forward: &types.Forward{
Address: "web Address",
TLS: &types.ClientTLS{
CA: "web CA",
Cert: "web Cert",
Key: "web Key",
InsecureSkipVerify: true,
},
TrustForwardHeader: true,
},
},
Debug: true,
}
config.Marathon = &marathon.Provider{
BaseProvider: provider.BaseProvider{
Watch: true,
Filename: "marathon Filename",
Constraints: types.Constraints{
{
Key: "marathon Constraints Key 1",
Regex: "marathon Constraints Regex 2",
MustMatch: true,
},
{
Key: "marathon Constraints Key 1",
Regex: "marathon Constraints Regex 2",
MustMatch: true,
},
},
Trace: true,
DebugLogGeneratedTemplate: true,
},
Endpoint: "",
Domain: "",
ExposedByDefault: true,
GroupsAsSubDomains: true,
DCOSToken: "",
MarathonLBCompatibility: true,
TLS: &types.ClientTLS{
CA: "marathon CA",
Cert: "marathon Cert",
Key: "marathon Key",
InsecureSkipVerify: true,
},
DialerTimeout: flaeg.Duration(666 * time.Second),
KeepAlive: flaeg.Duration(666 * time.Second),
ForceTaskHostname: true,
Basic: &marathon.Basic{
HTTPBasicAuthUser: "marathon HTTPBasicAuthUser",
HTTPBasicPassword: "marathon HTTPBasicPassword",
},
RespectReadinessChecks: true,
}
config.ConsulCatalog = &consulcatalog.Provider{
BaseProvider: provider.BaseProvider{
Watch: true,
Filename: "ConsulCatalog Filename",
Constraints: types.Constraints{
{
Key: "ConsulCatalog Constraints Key 1",
Regex: "ConsulCatalog Constraints Regex 2",
MustMatch: true,
},
{
Key: "ConsulCatalog Constraints Key 1",
Regex: "ConsulCatalog Constraints Regex 2",
MustMatch: true,
},
},
Trace: true,
DebugLogGeneratedTemplate: true,
},
Endpoint: "ConsulCatalog Endpoint",
Domain: "ConsulCatalog Domain",
ExposedByDefault: true,
Prefix: "ConsulCatalog Prefix",
FrontEndRule: "ConsulCatalog FrontEndRule",
}
config.Kubernetes = &kubernetes.Provider{
BaseProvider: provider.BaseProvider{
Watch: true,
Filename: "k8s Filename",
Constraints: types.Constraints{
{
Key: "k8s Constraints Key 1",
Regex: "k8s Constraints Regex 2",
MustMatch: true,
},
{
Key: "k8s Constraints Key 1",
Regex: "k8s Constraints Regex 2",
MustMatch: true,
},
},
Trace: true,
DebugLogGeneratedTemplate: true,
},
Endpoint: "k8s Endpoint",
Token: "k8s Token",
CertAuthFilePath: "k8s CertAuthFilePath",
DisablePassHostHeaders: true,
Namespaces: kubernetes.Namespaces{"k8s Namespaces 1", "k8s Namespaces 2", "k8s Namespaces 3"},
LabelSelector: "k8s LabelSelector",
}
config.Mesos = &mesos.Provider{
BaseProvider: provider.BaseProvider{
Watch: true,
Filename: "mesos Filename",
Constraints: types.Constraints{
{
Key: "mesos Constraints Key 1",
Regex: "mesos Constraints Regex 2",
MustMatch: true,
},
{
Key: "mesos Constraints Key 1",
Regex: "mesos Constraints Regex 2",
MustMatch: true,
},
},
Trace: true,
DebugLogGeneratedTemplate: true,
},
Endpoint: "mesos Endpoint",
Domain: "mesos Domain",
ExposedByDefault: true,
GroupsAsSubDomains: true,
ZkDetectionTimeout: 666,
RefreshSeconds: 666,
IPSources: "mesos IPSources",
StateTimeoutSecond: 666,
Masters: []string{"mesos Masters 1", "mesos Masters 2", "mesos Masters 3"},
}
config.Eureka = &eureka.Provider{
BaseProvider: provider.BaseProvider{
Watch: true,
Filename: "eureka Filename",
Constraints: types.Constraints{
{
Key: "eureka Constraints Key 1",
Regex: "eureka Constraints Regex 2",
MustMatch: true,
},
{
Key: "eureka Constraints Key 1",
Regex: "eureka Constraints Regex 2",
MustMatch: true,
},
},
Trace: true,
DebugLogGeneratedTemplate: true,
},
Endpoint: "eureka Endpoint",
Delay: flaeg.Duration(30 * time.Second),
RefreshSeconds: flaeg.Duration(30 * time.Second),
}
config.ECS = &ecs.Provider{
BaseProvider: provider.BaseProvider{
Watch: true,
Filename: "ecs Filename",
Constraints: types.Constraints{
{
Key: "ecs Constraints Key 1",
Regex: "ecs Constraints Regex 2",
MustMatch: true,
},
{
Key: "ecs Constraints Key 1",
Regex: "ecs Constraints Regex 2",
MustMatch: true,
},
},
Trace: true,
DebugLogGeneratedTemplate: true,
},
Domain: "ecs Domain",
ExposedByDefault: true,
RefreshSeconds: 666,
Clusters: ecs.Clusters{"ecs Clusters 1", "ecs Clusters 2", "ecs Clusters 3"},
Cluster: "ecs Cluster",
AutoDiscoverClusters: true,
Region: "ecs Region",
AccessKeyID: "ecs AccessKeyID",
SecretAccessKey: "ecs SecretAccessKey",
}
config.Rancher = &rancher.Provider{
BaseProvider: provider.BaseProvider{
Watch: true,
Filename: "rancher Filename",
Constraints: types.Constraints{
{
Key: "rancher Constraints Key 1",
Regex: "rancher Constraints Regex 2",
MustMatch: true,
},
{
Key: "rancher Constraints Key 1",
Regex: "rancher Constraints Regex 2",
MustMatch: true,
},
},
Trace: true,
DebugLogGeneratedTemplate: true,
},
APIConfiguration: rancher.APIConfiguration{
Endpoint: "rancher Endpoint",
AccessKey: "rancher AccessKey",
SecretKey: "rancher SecretKey",
},
API: &rancher.APIConfiguration{
Endpoint: "rancher Endpoint",
AccessKey: "rancher AccessKey",
SecretKey: "rancher SecretKey",
},
Metadata: &rancher.MetadataConfiguration{
IntervalPoll: true,
Prefix: "rancher Metadata Prefix",
},
Domain: "rancher Domain",
RefreshSeconds: 666,
ExposedByDefault: true,
EnableServiceHealthFilter: true,
}
config.DynamoDB = &dynamodb.Provider{
BaseProvider: provider.BaseProvider{
Watch: true,
Filename: "dynamodb Filename",
Constraints: types.Constraints{
{
Key: "dynamodb Constraints Key 1",
Regex: "dynamodb Constraints Regex 2",
MustMatch: true,
},
{
Key: "dynamodb Constraints Key 1",
Regex: "dynamodb Constraints Regex 2",
MustMatch: true,
},
},
Trace: true,
DebugLogGeneratedTemplate: true,
},
AccessKeyID: "dynamodb AccessKeyID",
RefreshSeconds: 666,
Region: "dynamodb Region",
SecretAccessKey: "dynamodb SecretAccessKey",
TableName: "dynamodb TableName",
Endpoint: "dynamodb Endpoint",
}
config.Etcd = &etcd.Provider{
Provider: kv.Provider{
BaseProvider: provider.BaseProvider{
Watch: true,
Filename: "etcd Filename",
Constraints: types.Constraints{
{
Key: "etcd Constraints Key 1",
Regex: "etcd Constraints Regex 2",
MustMatch: true,
},
{
Key: "etcd Constraints Key 1",
Regex: "etcd Constraints Regex 2",
MustMatch: true,
},
},
Trace: true,
DebugLogGeneratedTemplate: true,
},
Endpoint: "etcd Endpoint",
Prefix: "etcd Prefix",
TLS: &types.ClientTLS{
CA: "etcd CA",
Cert: "etcd Cert",
Key: "etcd Key",
InsecureSkipVerify: true,
},
Username: "etcd Username",
Password: "etcd Password",
},
}
config.Zookeeper = &zk.Provider{
Provider: kv.Provider{
BaseProvider: provider.BaseProvider{
Watch: true,
Filename: "zk Filename",
Constraints: types.Constraints{
{
Key: "zk Constraints Key 1",
Regex: "zk Constraints Regex 2",
MustMatch: true,
},
{
Key: "zk Constraints Key 1",
Regex: "zk Constraints Regex 2",
MustMatch: true,
},
},
Trace: true,
DebugLogGeneratedTemplate: true,
},
Endpoint: "zk Endpoint",
Prefix: "zk Prefix",
TLS: &types.ClientTLS{
CA: "zk CA",
Cert: "zk Cert",
Key: "zk Key",
InsecureSkipVerify: true,
},
Username: "zk Username",
Password: "zk Password",
},
}
config.Boltdb = &boltdb.Provider{
Provider: kv.Provider{
BaseProvider: provider.BaseProvider{
Watch: true,
Filename: "boltdb Filename",
Constraints: types.Constraints{
{
Key: "boltdb Constraints Key 1",
Regex: "boltdb Constraints Regex 2",
MustMatch: true,
},
{
Key: "boltdb Constraints Key 1",
Regex: "boltdb Constraints Regex 2",
MustMatch: true,
},
},
Trace: true,
DebugLogGeneratedTemplate: true,
},
Endpoint: "boltdb Endpoint",
Prefix: "boltdb Prefix",
TLS: &types.ClientTLS{
CA: "boltdb CA",
Cert: "boltdb Cert",
Key: "boltdb Key",
InsecureSkipVerify: true,
},
Username: "boltdb Username",
Password: "boltdb Password",
},
}
config.Consul = &consul.Provider{
Provider: kv.Provider{
BaseProvider: provider.BaseProvider{
Watch: true,
Filename: "consul Filename",
Constraints: types.Constraints{
{
Key: "consul Constraints Key 1",
Regex: "consul Constraints Regex 2",
MustMatch: true,
},
{
Key: "consul Constraints Key 1",
Regex: "consul Constraints Regex 2",
MustMatch: true,
},
},
Trace: true,
DebugLogGeneratedTemplate: true,
},
Endpoint: "consul Endpoint",
Prefix: "consul Prefix",
TLS: &types.ClientTLS{
CA: "consul CA",
Cert: "consul Cert",
Key: "consul Key",
InsecureSkipVerify: true,
},
Username: "consul Username",
Password: "consul Password",
},
}
cleanJSON, err := Do(config, true)
if err != nil {
t.Fatal(err, cleanJSON)
}
}

View File

@ -1,237 +0,0 @@
package anonymize
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_doOnJSON(t *testing.T) {
baseConfiguration := `
{
"GraceTimeOut": 10000000000,
"Debug": false,
"CheckNewVersion": true,
"AccessLogsFile": "",
"TraefikLogsFile": "",
"LogLevel": "ERROR",
"EntryPoints": {
"http": {
"Network": "",
"Address": ":80",
"TLS": null,
"Redirect": {
"EntryPoint": "https",
"Regex": "",
"Replacement": ""
},
"Auth": null,
"Compress": false
},
"https": {
"Address": ":443",
"TLS": {
"MinVersion": "",
"CipherSuites": null,
"Certificates": null,
"ClientCAFiles": null
},
"Redirect": null,
"Auth": null,
"Compress": false
}
},
"Cluster": null,
"Constraints": [],
"ACME": {
"Email": "foo@bar.com",
"Domains": [
{
"Main": "foo@bar.com",
"SANs": null
},
{
"Main": "foo@bar.com",
"SANs": null
}
],
"Storage": "",
"StorageFile": "/acme/acme.json",
"OnDemand": true,
"OnHostRule": true,
"CAServer": "",
"EntryPoint": "https",
"DNSProvider": "",
"DelayDontCheckDNS": 0,
"ACMELogging": false,
"TLSConfig": null
},
"DefaultEntryPoints": [
"https",
"http"
],
"ProvidersThrottleDuration": 2000000000,
"MaxIdleConnsPerHost": 200,
"IdleTimeout": 180000000000,
"InsecureSkipVerify": false,
"Retry": null,
"HealthCheck": {
"Interval": 30000000000
},
"Docker": null,
"File": null,
"Web": null,
"Marathon": null,
"Consul": null,
"ConsulCatalog": null,
"Etcd": null,
"Zookeeper": null,
"Boltdb": null,
"Kubernetes": null,
"Mesos": null,
"Eureka": null,
"ECS": null,
"Rancher": null,
"DynamoDB": null,
"ConfigFile": "/etc/traefik/traefik.toml"
}
`
expectedConfiguration := `
{
"GraceTimeOut": 10000000000,
"Debug": false,
"CheckNewVersion": true,
"AccessLogsFile": "",
"TraefikLogsFile": "",
"LogLevel": "ERROR",
"EntryPoints": {
"http": {
"Network": "",
"Address": ":80",
"TLS": null,
"Redirect": {
"EntryPoint": "https",
"Regex": "",
"Replacement": ""
},
"Auth": null,
"Compress": false
},
"https": {
"Address": ":443",
"TLS": {
"MinVersion": "",
"CipherSuites": null,
"Certificates": null,
"ClientCAFiles": null
},
"Redirect": null,
"Auth": null,
"Compress": false
}
},
"Cluster": null,
"Constraints": [],
"ACME": {
"Email": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"Domains": [
{
"Main": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"SANs": null
},
{
"Main": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"SANs": null
}
],
"Storage": "",
"StorageFile": "/acme/acme.json",
"OnDemand": true,
"OnHostRule": true,
"CAServer": "",
"EntryPoint": "https",
"DNSProvider": "",
"DelayDontCheckDNS": 0,
"ACMELogging": false,
"TLSConfig": null
},
"DefaultEntryPoints": [
"https",
"http"
],
"ProvidersThrottleDuration": 2000000000,
"MaxIdleConnsPerHost": 200,
"IdleTimeout": 180000000000,
"InsecureSkipVerify": false,
"Retry": null,
"HealthCheck": {
"Interval": 30000000000
},
"Docker": null,
"File": null,
"Web": null,
"Marathon": null,
"Consul": null,
"ConsulCatalog": null,
"Etcd": null,
"Zookeeper": null,
"Boltdb": null,
"Kubernetes": null,
"Mesos": null,
"Eureka": null,
"ECS": null,
"Rancher": null,
"DynamoDB": null,
"ConfigFile": "/etc/traefik/traefik.toml"
}
`
anomConfiguration := doOnJSON(baseConfiguration)
if anomConfiguration != expectedConfiguration {
t.Errorf("Got %s, want %s.", anomConfiguration, expectedConfiguration)
}
}
func Test_doOnJSON_simple(t *testing.T) {
testCases := []struct {
name string
input string
expectedOutput string
}{
{
name: "email",
input: `{
"email1": "goo@example.com",
"email2": "foo.bargoo@example.com",
"email3": "foo.bargoo@example.com.us"
}`,
expectedOutput: `{
"email1": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"email2": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"email3": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}`,
},
{
name: "url",
input: `{
"URL": "foo domain.com foo",
"URL": "foo sub.domain.com foo",
"URL": "foo sub.sub.domain.com foo",
"URL": "foo sub.sub.sub.domain.com.us foo"
}`,
expectedOutput: `{
"URL": "foo xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx foo",
"URL": "foo xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx foo",
"URL": "foo xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx foo",
"URL": "foo xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx foo"
}`,
},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
output := doOnJSON(test.input)
assert.Equal(t, test.expectedOutput, output)
})
}
}

View File

@ -1,176 +0,0 @@
package anonymize
import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
)
type Courgette struct {
Ji string
Ho string
}
type Tomate struct {
Ji string
Ho string
}
type Carotte struct {
Name string
Value int
Courgette Courgette
ECourgette Courgette `export:"true"`
Pourgette *Courgette
EPourgette *Courgette `export:"true"`
Aubergine map[string]string
EAubergine map[string]string `export:"true"`
SAubergine map[string]Tomate
ESAubergine map[string]Tomate `export:"true"`
PSAubergine map[string]*Tomate
EPAubergine map[string]*Tomate `export:"true"`
}
func Test_doOnStruct(t *testing.T) {
testCase := []struct {
name string
base *Carotte
expected *Carotte
hasError bool
}{
{
name: "primitive",
base: &Carotte{
Name: "koko",
Value: 666,
},
expected: &Carotte{
Name: "xxxx",
},
},
{
name: "struct",
base: &Carotte{
Name: "koko",
Courgette: Courgette{
Ji: "huu",
},
},
expected: &Carotte{
Name: "xxxx",
},
},
{
name: "pointer",
base: &Carotte{
Name: "koko",
Pourgette: &Courgette{
Ji: "hoo",
},
},
expected: &Carotte{
Name: "xxxx",
Pourgette: nil,
},
},
{
name: "export struct",
base: &Carotte{
Name: "koko",
ECourgette: Courgette{
Ji: "huu",
},
},
expected: &Carotte{
Name: "xxxx",
ECourgette: Courgette{
Ji: "xxxx",
},
},
},
{
name: "export pointer struct",
base: &Carotte{
Name: "koko",
ECourgette: Courgette{
Ji: "huu",
},
},
expected: &Carotte{
Name: "xxxx",
ECourgette: Courgette{
Ji: "xxxx",
},
},
},
{
name: "export map string/string",
base: &Carotte{
Name: "koko",
EAubergine: map[string]string{
"foo": "bar",
},
},
expected: &Carotte{
Name: "xxxx",
EAubergine: map[string]string{
"foo": "bar",
},
},
},
{
name: "export map string/pointer",
base: &Carotte{
Name: "koko",
EPAubergine: map[string]*Tomate{
"foo": {
Ji: "fdskljf",
},
},
},
expected: &Carotte{
Name: "xxxx",
EPAubergine: map[string]*Tomate{
"foo": {
Ji: "xxxx",
},
},
},
},
{
name: "export map string/struct (UNSAFE)",
base: &Carotte{
Name: "koko",
ESAubergine: map[string]Tomate{
"foo": {
Ji: "JiJiJi",
},
},
},
expected: &Carotte{
Name: "xxxx",
ESAubergine: map[string]Tomate{
"foo": {
Ji: "JiJiJi",
},
},
},
hasError: true,
},
}
for _, test := range testCase {
t.Run(test.name, func(t *testing.T) {
val := reflect.ValueOf(test.base).Elem()
err := doOnStruct(val)
if !test.hasError && err != nil {
t.Fatal(err)
}
if test.hasError && err == nil {
t.Fatal("Got no error but want an error.")
}
assert.EqualValues(t, test.expected, test.base)
})
}
}

View File

@ -1,39 +0,0 @@
package api
import (
"net/http"
"github.com/containous/mux"
"github.com/containous/traefik/log"
"github.com/elazarl/go-bindata-assetfs"
)
// DashboardHandler expose dashboard routes
type DashboardHandler struct {
Assets *assetfs.AssetFS
}
// AddRoutes add dashboard routes on a router
func (g DashboardHandler) AddRoutes(router *mux.Router) {
if g.Assets == nil {
log.Error("No assets for dashboard")
return
}
// Expose dashboard
router.Methods(http.MethodGet).
Path("/").
HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
http.Redirect(response, request, request.Header.Get("X-Forwarded-Prefix")+"/dashboard/", 302)
})
router.Methods(http.MethodGet).
Path("/dashboard/status").
HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
http.Redirect(response, request, "/dashboard/", 302)
})
router.Methods(http.MethodGet).
PathPrefix("/dashboard/").
Handler(http.StripPrefix("/dashboard/", http.FileServer(g.Assets)))
}

View File

@ -1,48 +0,0 @@
package api
import (
"expvar"
"fmt"
"net/http"
"net/http/pprof"
"runtime"
"github.com/containous/mux"
)
func init() {
expvar.Publish("Goroutines", expvar.Func(goroutines))
}
func goroutines() interface{} {
return runtime.NumGoroutine()
}
// DebugHandler expose debug routes
type DebugHandler struct{}
// AddRoutes add debug routes on a router
func (g DebugHandler) AddRoutes(router *mux.Router) {
router.Methods(http.MethodGet).Path("/debug/vars").
HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
fmt.Fprint(w, "{\n")
first := true
expvar.Do(func(kv expvar.KeyValue) {
if !first {
fmt.Fprint(w, ",\n")
}
first = false
fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value)
})
fmt.Fprint(w, "\n}\n")
})
runtime.SetBlockProfileRate(1)
runtime.SetMutexProfileFraction(5)
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/cmdline").HandlerFunc(pprof.Cmdline)
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/profile").HandlerFunc(pprof.Profile)
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/symbol").HandlerFunc(pprof.Symbol)
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/trace").HandlerFunc(pprof.Trace)
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/").HandlerFunc(pprof.Index)
}

View File

@ -1,252 +0,0 @@
package api
import (
"net/http"
"github.com/containous/mux"
"github.com/containous/traefik/log"
"github.com/containous/traefik/middlewares"
"github.com/containous/traefik/safe"
"github.com/containous/traefik/types"
"github.com/containous/traefik/version"
"github.com/elazarl/go-bindata-assetfs"
thoas_stats "github.com/thoas/stats"
"github.com/unrolled/render"
)
// Handler expose api routes
type Handler struct {
EntryPoint string `description:"EntryPoint" export:"true"`
Dashboard bool `description:"Activate dashboard" export:"true"`
Debug bool `export:"true"`
CurrentConfigurations *safe.Safe
Statistics *types.Statistics `description:"Enable more detailed statistics" export:"true"`
Stats *thoas_stats.Stats `json:"-"`
StatsRecorder *middlewares.StatsRecorder `json:"-"`
DashboardAssets *assetfs.AssetFS `json:"-"`
}
var (
templatesRenderer = render.New(render.Options{
Directory: "nowhere",
})
)
// AddRoutes add api routes on a router
func (p Handler) AddRoutes(router *mux.Router) {
if p.Debug {
DebugHandler{}.AddRoutes(router)
}
router.Methods(http.MethodGet).Path("/api").HandlerFunc(p.getConfigHandler)
router.Methods(http.MethodGet).Path("/api/providers").HandlerFunc(p.getConfigHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}").HandlerFunc(p.getProviderHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/backends").HandlerFunc(p.getBackendsHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/backends/{backend}").HandlerFunc(p.getBackendHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/backends/{backend}/servers").HandlerFunc(p.getServersHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/backends/{backend}/servers/{server}").HandlerFunc(p.getServerHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/frontends").HandlerFunc(p.getFrontendsHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/frontends/{frontend}").HandlerFunc(p.getFrontendHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/frontends/{frontend}/routes").HandlerFunc(p.getRoutesHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/frontends/{frontend}/routes/{route}").HandlerFunc(p.getRouteHandler)
// health route
router.Methods(http.MethodGet).Path("/health").HandlerFunc(p.getHealthHandler)
version.Handler{}.AddRoutes(router)
if p.Dashboard {
DashboardHandler{Assets: p.DashboardAssets}.AddRoutes(router)
}
}
func getProviderIDFromVars(vars map[string]string) string {
providerID := vars["provider"]
// TODO: Deprecated
if providerID == "rest" {
providerID = "web"
}
return providerID
}
func (p Handler) getConfigHandler(response http.ResponseWriter, request *http.Request) {
currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations)
err := templatesRenderer.JSON(response, http.StatusOK, currentConfigurations)
if err != nil {
log.Error(err)
}
}
func (p Handler) getProviderHandler(response http.ResponseWriter, request *http.Request) {
providerID := getProviderIDFromVars(mux.Vars(request))
currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations)
if provider, ok := currentConfigurations[providerID]; ok {
err := templatesRenderer.JSON(response, http.StatusOK, provider)
if err != nil {
log.Error(err)
}
} else {
http.NotFound(response, request)
}
}
func (p Handler) getBackendsHandler(response http.ResponseWriter, request *http.Request) {
providerID := getProviderIDFromVars(mux.Vars(request))
currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations)
if provider, ok := currentConfigurations[providerID]; ok {
err := templatesRenderer.JSON(response, http.StatusOK, provider.Backends)
if err != nil {
log.Error(err)
}
} else {
http.NotFound(response, request)
}
}
func (p Handler) getBackendHandler(response http.ResponseWriter, request *http.Request) {
vars := mux.Vars(request)
providerID := getProviderIDFromVars(vars)
backendID := vars["backend"]
currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations)
if provider, ok := currentConfigurations[providerID]; ok {
if backend, ok := provider.Backends[backendID]; ok {
err := templatesRenderer.JSON(response, http.StatusOK, backend)
if err != nil {
log.Error(err)
}
return
}
}
http.NotFound(response, request)
}
func (p Handler) getServersHandler(response http.ResponseWriter, request *http.Request) {
vars := mux.Vars(request)
providerID := getProviderIDFromVars(vars)
backendID := vars["backend"]
currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations)
if provider, ok := currentConfigurations[providerID]; ok {
if backend, ok := provider.Backends[backendID]; ok {
err := templatesRenderer.JSON(response, http.StatusOK, backend.Servers)
if err != nil {
log.Error(err)
}
return
}
}
http.NotFound(response, request)
}
func (p Handler) getServerHandler(response http.ResponseWriter, request *http.Request) {
vars := mux.Vars(request)
providerID := getProviderIDFromVars(vars)
backendID := vars["backend"]
serverID := vars["server"]
currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations)
if provider, ok := currentConfigurations[providerID]; ok {
if backend, ok := provider.Backends[backendID]; ok {
if server, ok := backend.Servers[serverID]; ok {
err := templatesRenderer.JSON(response, http.StatusOK, server)
if err != nil {
log.Error(err)
}
return
}
}
}
http.NotFound(response, request)
}
func (p Handler) getFrontendsHandler(response http.ResponseWriter, request *http.Request) {
providerID := getProviderIDFromVars(mux.Vars(request))
currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations)
if provider, ok := currentConfigurations[providerID]; ok {
err := templatesRenderer.JSON(response, http.StatusOK, provider.Frontends)
if err != nil {
log.Error(err)
}
} else {
http.NotFound(response, request)
}
}
func (p Handler) getFrontendHandler(response http.ResponseWriter, request *http.Request) {
vars := mux.Vars(request)
providerID := getProviderIDFromVars(vars)
frontendID := vars["frontend"]
currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations)
if provider, ok := currentConfigurations[providerID]; ok {
if frontend, ok := provider.Frontends[frontendID]; ok {
err := templatesRenderer.JSON(response, http.StatusOK, frontend)
if err != nil {
log.Error(err)
}
return
}
}
http.NotFound(response, request)
}
func (p Handler) getRoutesHandler(response http.ResponseWriter, request *http.Request) {
vars := mux.Vars(request)
providerID := getProviderIDFromVars(vars)
frontendID := vars["frontend"]
currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations)
if provider, ok := currentConfigurations[providerID]; ok {
if frontend, ok := provider.Frontends[frontendID]; ok {
err := templatesRenderer.JSON(response, http.StatusOK, frontend.Routes)
if err != nil {
log.Error(err)
}
return
}
}
http.NotFound(response, request)
}
func (p Handler) getRouteHandler(response http.ResponseWriter, request *http.Request) {
vars := mux.Vars(request)
providerID := getProviderIDFromVars(vars)
frontendID := vars["frontend"]
routeID := vars["route"]
currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations)
if provider, ok := currentConfigurations[providerID]; ok {
if frontend, ok := provider.Frontends[frontendID]; ok {
if route, ok := frontend.Routes[routeID]; ok {
err := templatesRenderer.JSON(response, http.StatusOK, route)
if err != nil {
log.Error(err)
}
return
}
}
}
http.NotFound(response, request)
}
// healthResponse combines data returned by thoas/stats with statistics (if
// they are enabled).
type healthResponse struct {
*thoas_stats.Data
*middlewares.Stats
}
func (p *Handler) getHealthHandler(response http.ResponseWriter, request *http.Request) {
health := &healthResponse{Data: p.Stats.Data()}
if p.StatsRecorder != nil {
health.Stats = p.StatsRecorder.Data()
}
err := templatesRenderer.JSON(response, http.StatusOK, health)
if err != nil {
log.Error(err)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,27 +0,0 @@
FROM golang:1.11-alpine
RUN apk --update upgrade \
&& apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar \
&& rm -rf /var/cache/apk/*
RUN go get github.com/containous/go-bindata/... \
&& go get golang.org/x/lint/golint \
&& go get github.com/kisielk/errcheck \
&& go get github.com/client9/misspell/cmd/misspell
# Which docker version to test on
ARG DOCKER_VERSION=17.03.2
ARG DEP_VERSION=0.4.1
# Download dep binary to bin folder in $GOPATH
RUN mkdir -p /usr/local/bin \
&& curl -fsSL -o /usr/local/bin/dep https://github.com/golang/dep/releases/download/v${DEP_VERSION}/dep-linux-amd64 \
&& chmod +x /usr/local/bin/dep
# Download docker
RUN mkdir -p /usr/local/bin \
&& curl -fL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}-ce.tgz \
| tar -xzC /usr/local/bin --transform 's#^.+/##x'
WORKDIR /go/src/github.com/containous/traefik
COPY . /go/src/github.com/containous/traefik

View File

@ -1,247 +0,0 @@
package cluster
import (
"context"
"encoding/json"
"fmt"
"sync"
"time"
"github.com/abronan/valkeyrie/store"
"github.com/cenk/backoff"
"github.com/containous/staert"
"github.com/containous/traefik/job"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/satori/go.uuid"
)
// Metadata stores Object plus metadata
type Metadata struct {
object Object
Object []byte
Lock string
}
// NewMetadata returns new Metadata
func NewMetadata(object Object) *Metadata {
return &Metadata{object: object}
}
// Marshall marshalls object
func (m *Metadata) Marshall() error {
var err error
m.Object, err = json.Marshal(m.object)
return err
}
func (m *Metadata) unmarshall() error {
if len(m.Object) == 0 {
return nil
}
return json.Unmarshal(m.Object, m.object)
}
// Listener is called when Object has been changed in KV store
type Listener func(Object) error
var _ Store = (*Datastore)(nil)
// Datastore holds a struct synced in a KV store
type Datastore struct {
kv staert.KvSource
ctx context.Context
localLock *sync.RWMutex
meta *Metadata
lockKey string
listener Listener
}
// NewDataStore creates a Datastore
func NewDataStore(ctx context.Context, kvSource staert.KvSource, object Object, listener Listener) (*Datastore, error) {
datastore := Datastore{
kv: kvSource,
ctx: ctx,
meta: &Metadata{object: object},
lockKey: kvSource.Prefix + "/lock",
localLock: &sync.RWMutex{},
listener: listener,
}
err := datastore.watchChanges()
if err != nil {
return nil, err
}
return &datastore, nil
}
func (d *Datastore) watchChanges() error {
stopCh := make(chan struct{})
kvCh, err := d.kv.Watch(d.lockKey, stopCh, nil)
if err != nil {
return fmt.Errorf("error while watching key %s: %v", d.lockKey, err)
}
safe.Go(func() {
ctx, cancel := context.WithCancel(d.ctx)
operation := func() error {
for {
select {
case <-ctx.Done():
stopCh <- struct{}{}
return nil
case _, ok := <-kvCh:
if !ok {
cancel()
return err
}
err = d.reload()
if err != nil {
return err
}
if d.listener != nil {
err := d.listener(d.meta.object)
if err != nil {
log.Errorf("Error calling datastore listener: %s", err)
}
}
}
}
}
notify := func(err error, time time.Duration) {
log.Errorf("Error in watch datastore: %+v, retrying in %s", err, time)
}
err := backoff.RetryNotify(safe.OperationWithRecover(operation), job.NewBackOff(backoff.NewExponentialBackOff()), notify)
if err != nil {
log.Errorf("Error in watch datastore: %v", err)
}
})
return nil
}
func (d *Datastore) reload() error {
log.Debug("Datastore reload")
_, err := d.Load()
return err
}
// Begin creates a transaction with the KV store.
func (d *Datastore) Begin() (Transaction, Object, error) {
id := uuid.NewV4().String()
log.Debugf("Transaction %s begins", id)
remoteLock, err := d.kv.NewLock(d.lockKey, &store.LockOptions{TTL: 20 * time.Second, Value: []byte(id)})
if err != nil {
return nil, nil, err
}
stopCh := make(chan struct{})
ctx, cancel := context.WithCancel(d.ctx)
var errLock error
go func() {
_, errLock = remoteLock.Lock(stopCh)
cancel()
}()
select {
case <-ctx.Done():
if errLock != nil {
return nil, nil, errLock
}
case <-d.ctx.Done():
stopCh <- struct{}{}
return nil, nil, d.ctx.Err()
}
// we got the lock! Now make sure we are synced with KV store
operation := func() error {
meta := d.get()
if meta.Lock != id {
return fmt.Errorf("object lock value: expected %s, got %s", id, meta.Lock)
}
return nil
}
notify := func(err error, time time.Duration) {
log.Errorf("Datastore sync error: %v, retrying in %s", err, time)
err = d.reload()
if err != nil {
log.Errorf("Error reloading: %+v", err)
}
}
ebo := backoff.NewExponentialBackOff()
ebo.MaxElapsedTime = 60 * time.Second
err = backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify)
if err != nil {
return nil, nil, fmt.Errorf("datastore cannot sync: %v", err)
}
// we synced with KV store, we can now return Setter
return &datastoreTransaction{
Datastore: d,
remoteLock: remoteLock,
id: id,
}, d.meta.object, nil
}
func (d *Datastore) get() *Metadata {
d.localLock.RLock()
defer d.localLock.RUnlock()
return d.meta
}
// Load load atomically a struct from the KV store
func (d *Datastore) Load() (Object, error) {
d.localLock.Lock()
defer d.localLock.Unlock()
// clear Object first, as mapstructure's decoder doesn't have ZeroFields set to true for merging purposes
d.meta.Object = d.meta.Object[:0]
err := d.kv.LoadConfig(d.meta)
if err != nil {
return nil, err
}
err = d.meta.unmarshall()
if err != nil {
return nil, err
}
return d.meta.object, nil
}
// Get atomically a struct from the KV store
func (d *Datastore) Get() Object {
d.localLock.RLock()
defer d.localLock.RUnlock()
return d.meta.object
}
var _ Transaction = (*datastoreTransaction)(nil)
type datastoreTransaction struct {
*Datastore
remoteLock store.Locker
dirty bool
id string
}
// Commit allows to set an object in the KV store
func (s *datastoreTransaction) Commit(object Object) error {
s.localLock.Lock()
defer s.localLock.Unlock()
if s.dirty {
return fmt.Errorf("transaction already used, please begin a new one")
}
s.Datastore.meta.object = object
err := s.Datastore.meta.Marshall()
if err != nil {
return fmt.Errorf("marshall error: %s", err)
}
err = s.kv.StoreConfig(s.Datastore.meta)
if err != nil {
return fmt.Errorf("StoreConfig error: %s", err)
}
err = s.remoteLock.Unlock()
if err != nil {
return fmt.Errorf("unlock error: %s", err)
}
s.dirty = true
log.Debugf("Transaction committed %s", s.id)
return nil
}

View File

@ -1,146 +0,0 @@
package cluster
import (
"context"
"net/http"
"time"
"github.com/cenk/backoff"
"github.com/containous/mux"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/containous/traefik/types"
"github.com/docker/leadership"
"github.com/unrolled/render"
)
const clusterLeaderKeySuffix = "/leader"
var templatesRenderer = render.New(render.Options{
Directory: "nowhere",
})
// Leadership allows leadership election using a KV store
type Leadership struct {
*safe.Pool
*types.Cluster
candidate *leadership.Candidate
leader *safe.Safe
listeners []LeaderListener
}
// NewLeadership creates a leadership
func NewLeadership(ctx context.Context, cluster *types.Cluster) *Leadership {
return &Leadership{
Pool: safe.NewPool(ctx),
Cluster: cluster,
candidate: leadership.NewCandidate(cluster.Store, cluster.Store.Prefix+clusterLeaderKeySuffix, cluster.Node, 20*time.Second),
listeners: []LeaderListener{},
leader: safe.New(false),
}
}
// LeaderListener is called when leadership has changed
type LeaderListener func(elected bool) error
// Participate tries to be a leader
func (l *Leadership) Participate(pool *safe.Pool) {
pool.GoCtx(func(ctx context.Context) {
log.Debugf("Node %s running for election", l.Cluster.Node)
defer log.Debugf("Node %s no more running for election", l.Cluster.Node)
backOff := backoff.NewExponentialBackOff()
operation := func() error {
return l.run(ctx, l.candidate)
}
notify := func(err error, time time.Duration) {
log.Errorf("Leadership election error %+v, retrying in %s", err, time)
}
err := backoff.RetryNotify(safe.OperationWithRecover(operation), backOff, notify)
if err != nil {
log.Errorf("Cannot elect leadership %+v", err)
}
})
}
// AddListener adds a leadership listener
func (l *Leadership) AddListener(listener LeaderListener) {
l.listeners = append(l.listeners, listener)
}
// Resign resigns from being a leader
func (l *Leadership) Resign() {
l.candidate.Resign()
log.Infof("Node %s resigned", l.Cluster.Node)
}
func (l *Leadership) run(ctx context.Context, candidate *leadership.Candidate) error {
electedCh, errCh := candidate.RunForElection()
for {
select {
case elected := <-electedCh:
l.onElection(elected)
case err := <-errCh:
return err
case <-ctx.Done():
l.candidate.Resign()
return nil
}
}
}
func (l *Leadership) onElection(elected bool) {
if elected {
log.Infof("Node %s elected leader ♚", l.Cluster.Node)
l.leader.Set(true)
l.Start()
} else {
log.Infof("Node %s elected worker ♝", l.Cluster.Node)
l.leader.Set(false)
l.Stop()
}
for _, listener := range l.listeners {
err := listener(elected)
if err != nil {
log.Errorf("Error calling Leadership listener: %s", err)
}
}
}
type leaderResponse struct {
Leader bool `json:"leader"`
LeaderNode string `json:"leader_node"`
}
func (l *Leadership) getLeaderHandler(response http.ResponseWriter, request *http.Request) {
leaderNode := ""
leaderKv, err := l.Cluster.Store.Get(l.Cluster.Store.Prefix+clusterLeaderKeySuffix, nil)
if err != nil {
log.Error(err)
} else {
leaderNode = string(leaderKv.Value)
}
leader := &leaderResponse{Leader: l.IsLeader(), LeaderNode: leaderNode}
status := http.StatusOK
if !leader.Leader {
// Set status to be `429`, as this will typically cause load balancers to stop sending requests to the instance without removing them from rotation.
status = http.StatusTooManyRequests
}
err = templatesRenderer.JSON(response, status, leader)
if err != nil {
log.Error(err)
}
}
// IsLeader returns true if current node is leader
func (l *Leadership) IsLeader() bool {
return l.leader.Get().(bool)
}
// AddRoutes add dashboard routes on a router
func (l *Leadership) AddRoutes(router *mux.Router) {
// Expose cluster leader
router.Methods(http.MethodGet).Path("/api/cluster/leader").HandlerFunc(l.getLeaderHandler)
}

View File

@ -1,16 +0,0 @@
package cluster
// Object is the struct to store
type Object interface{}
// Store is a generic interface to represents a storage
type Store interface {
Load() (Object, error)
Get() Object
Begin() (Transaction, Object, error)
}
// Transaction allows to set a struct in the KV store
type Transaction interface {
Commit(object Object) error
}

View File

@ -1,171 +0,0 @@
package bug
import (
"bytes"
"fmt"
"net/url"
"os/exec"
"runtime"
"text/template"
"github.com/containous/flaeg"
"github.com/containous/traefik/anonymize"
"github.com/containous/traefik/cmd"
"github.com/containous/traefik/cmd/version"
)
const (
bugTracker = "https://github.com/containous/traefik/issues/new"
bugTemplate = `<!--
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, refer to one of the following:
- Stack Overflow (using the "traefik" tag): https://stackoverflow.com/questions/tagged/traefik
- the Traefik community Slack channel: https://slack.traefik.io
-->
### Do you want to request a *feature* or report a *bug*?
(If you intend to ask a support question: **DO NOT FILE AN ISSUE**.
Use [Stack Overflow](https://stackoverflow.com/questions/tagged/traefik)
or [Slack](https://slack.traefik.io) instead.)
### What did you do?
<!--
HOW TO WRITE A GOOD ISSUE?
- Respect the issue template as more as possible.
- If it's possible use the command ` + "`" + "traefik bug" + "`" + `. See https://www.youtube.com/watch?v=Lyz62L8m93I.
- The title must be short and descriptive.
- Explain the conditions which led you to write this issue: the context.
- The context should lead to something, an idea or a problem that youre facing.
- Remain clear and concise.
- Format your messages to help the reader focus on what matters and understand the structure of your message, use Markdown syntax https://help.github.com/articles/github-flavored-markdown
-->
### What did you expect to see?
### What did you see instead?
### Output of ` + "`" + `traefik version` + "`" + `: (_What version of Traefik are you using?_)
` + "```" + `
{{.Version}}
` + "```" + `
### What is your environment & configuration (arguments, toml, provider, platform, ...)?
` + "```" + `json
{{.Configuration}}
` + "```" + `
<!--
Add more configuration information here.
-->
### If applicable, please paste the log output at DEBUG level (` + "`" + `--logLevel=DEBUG` + "`" + ` switch)
` + "```" + `
(paste your output here)
` + "```" + `
`
)
// NewCmd builds a new Bug command
func NewCmd(traefikConfiguration *cmd.TraefikConfiguration, traefikPointersConfiguration *cmd.TraefikConfiguration) *flaeg.Command {
// version Command init
return &flaeg.Command{
Name: "bug",
Description: `Report an issue on Traefik bugtracker`,
Config: traefikConfiguration,
DefaultPointersConfig: traefikPointersConfiguration,
Run: runCmd(traefikConfiguration),
Metadata: map[string]string{
"parseAllSources": "true",
},
}
}
func runCmd(traefikConfiguration *cmd.TraefikConfiguration) func() error {
return func() error {
body, err := createReport(traefikConfiguration)
if err != nil {
return err
}
sendReport(body)
return nil
}
}
func createReport(traefikConfiguration *cmd.TraefikConfiguration) (string, error) {
var versionPrint bytes.Buffer
if err := version.GetPrint(&versionPrint); err != nil {
return "", err
}
tmpl, err := template.New("bug").Parse(bugTemplate)
if err != nil {
return "", err
}
config, err := anonymize.Do(traefikConfiguration, true)
if err != nil {
return "", err
}
v := struct {
Version string
Configuration string
}{
Version: versionPrint.String(),
Configuration: config,
}
var bug bytes.Buffer
if err := tmpl.Execute(&bug, v); err != nil {
return "", err
}
return bug.String(), nil
}
func sendReport(body string) {
URL := bugTracker + "?body=" + url.QueryEscape(body)
if err := openBrowser(URL); err != nil {
fmt.Printf("Please file a new issue at %s using this template:\n\n", bugTracker)
fmt.Print(body)
}
}
func openBrowser(URL string) error {
var err error
switch runtime.GOOS {
case "linux":
err = exec.Command("xdg-open", URL).Start()
case "windows":
err = exec.Command("rundll32", "url.dll,FileProtocolHandler", URL).Start()
case "darwin":
err = exec.Command("open", URL).Start()
default:
err = fmt.Errorf("unsupported platform")
}
return err
}

View File

@ -1,67 +0,0 @@
package bug
import (
"testing"
"github.com/containous/traefik/anonymize"
"github.com/containous/traefik/cmd"
"github.com/containous/traefik/configuration"
"github.com/containous/traefik/provider/file"
"github.com/containous/traefik/tls"
"github.com/containous/traefik/types"
"github.com/stretchr/testify/assert"
)
func Test_createReport(t *testing.T) {
traefikConfiguration := &cmd.TraefikConfiguration{
ConfigFile: "FOO",
GlobalConfiguration: configuration.GlobalConfiguration{
EntryPoints: configuration.EntryPoints{
"goo": &configuration.EntryPoint{
Address: "hoo.bar",
Auth: &types.Auth{
Basic: &types.Basic{
UsersFile: "foo Basic UsersFile",
Users: types.Users{"foo Basic Users 1", "foo Basic Users 2", "foo Basic Users 3"},
},
Digest: &types.Digest{
UsersFile: "foo Digest UsersFile",
Users: types.Users{"foo Digest Users 1", "foo Digest Users 2", "foo Digest Users 3"},
},
},
},
},
File: &file.Provider{
Directory: "BAR",
},
RootCAs: tls.FilesOrContents{"fllf"},
},
}
report, err := createReport(traefikConfiguration)
assert.NoError(t, err, report)
// exported anonymous configuration
assert.NotContains(t, "web Basic Users ", report)
assert.NotContains(t, "foo Digest Users ", report)
assert.NotContains(t, "hoo.bar", report)
}
func Test_anonymize_traefikConfiguration(t *testing.T) {
traefikConfiguration := &cmd.TraefikConfiguration{
ConfigFile: "FOO",
GlobalConfiguration: configuration.GlobalConfiguration{
EntryPoints: configuration.EntryPoints{
"goo": &configuration.EntryPoint{
Address: "hoo.bar",
},
},
File: &file.Provider{
Directory: "BAR",
},
},
}
_, err := anonymize.Do(traefikConfiguration, true)
assert.NoError(t, err)
assert.Equal(t, "hoo.bar", traefikConfiguration.GlobalConfiguration.EntryPoints["goo"].Address)
}

View File

@ -3,341 +3,36 @@ package cmd
import (
"time"
"github.com/containous/flaeg"
"github.com/containous/traefik-extra-service-fabric"
"github.com/containous/traefik/api"
"github.com/containous/traefik/configuration"
"github.com/containous/traefik/middlewares/accesslog"
"github.com/containous/traefik/middlewares/tracing"
"github.com/containous/traefik/middlewares/tracing/datadog"
"github.com/containous/traefik/middlewares/tracing/jaeger"
"github.com/containous/traefik/middlewares/tracing/zipkin"
"github.com/containous/traefik/ping"
"github.com/containous/traefik/provider/boltdb"
"github.com/containous/traefik/provider/consul"
"github.com/containous/traefik/provider/consulcatalog"
"github.com/containous/traefik/provider/docker"
"github.com/containous/traefik/provider/dynamodb"
"github.com/containous/traefik/provider/ecs"
"github.com/containous/traefik/provider/etcd"
"github.com/containous/traefik/provider/eureka"
"github.com/containous/traefik/provider/file"
"github.com/containous/traefik/provider/kubernetes"
"github.com/containous/traefik/provider/marathon"
"github.com/containous/traefik/provider/mesos"
"github.com/containous/traefik/provider/rancher"
"github.com/containous/traefik/provider/rest"
"github.com/containous/traefik/provider/zk"
"github.com/containous/traefik/types"
sf "github.com/jjcollinge/servicefabric"
ptypes "github.com/traefik/paerser/types"
"github.com/traefik/traefik/v3/pkg/config/static"
)
// TraefikConfiguration holds GlobalConfiguration and other stuff
type TraefikConfiguration struct {
configuration.GlobalConfiguration `mapstructure:",squash" export:"true"`
ConfigFile string `short:"c" description:"Configuration file to use (TOML)." export:"true"`
// TraefikCmdConfiguration wraps the static configuration and extra parameters.
type TraefikCmdConfiguration struct {
static.Configuration `export:"true"`
// ConfigFile is the path to the configuration file.
ConfigFile string `description:"Configuration file to use. If specified all other flags are ignored." export:"true"`
}
// NewTraefikDefaultPointersConfiguration creates a TraefikConfiguration with pointers default values
func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration {
// default Docker
var defaultDocker docker.Provider
defaultDocker.Watch = true
defaultDocker.ExposedByDefault = true
defaultDocker.Endpoint = "unix:///var/run/docker.sock"
defaultDocker.SwarmMode = false
// default File
var defaultFile file.Provider
defaultFile.Watch = true
defaultFile.Filename = "" // needs equivalent to viper.ConfigFileUsed()
// default Rest
var defaultRest rest.Provider
defaultRest.EntryPoint = configuration.DefaultInternalEntryPointName
// TODO: Deprecated - Web provider, use REST provider instead
var defaultWeb configuration.WebCompatibility
defaultWeb.Address = ":8080"
defaultWeb.Statistics = &types.Statistics{
RecentErrors: 10,
}
// TODO: Deprecated - default Metrics
defaultWeb.Metrics = &types.Metrics{
Prometheus: &types.Prometheus{
Buckets: types.Buckets{0.1, 0.3, 1.2, 5},
EntryPoint: configuration.DefaultInternalEntryPointName,
},
Datadog: &types.Datadog{
Address: "localhost:8125",
PushInterval: "10s",
},
StatsD: &types.Statsd{
Address: "localhost:8125",
PushInterval: "10s",
},
InfluxDB: &types.InfluxDB{
Address: "localhost:8089",
Protocol: "udp",
PushInterval: "10s",
},
}
// default Marathon
var defaultMarathon marathon.Provider
defaultMarathon.Watch = true
defaultMarathon.Endpoint = "http://127.0.0.1:8080"
defaultMarathon.ExposedByDefault = true
defaultMarathon.Constraints = types.Constraints{}
defaultMarathon.DialerTimeout = flaeg.Duration(5 * time.Second)
defaultMarathon.ResponseHeaderTimeout = flaeg.Duration(60 * time.Second)
defaultMarathon.TLSHandshakeTimeout = flaeg.Duration(5 * time.Second)
defaultMarathon.KeepAlive = flaeg.Duration(10 * time.Second)
// default Consul
var defaultConsul consul.Provider
defaultConsul.Watch = true
defaultConsul.Endpoint = "127.0.0.1:8500"
defaultConsul.Prefix = "traefik"
defaultConsul.Constraints = types.Constraints{}
// default CatalogProvider
var defaultConsulCatalog consulcatalog.Provider
defaultConsulCatalog.Endpoint = "127.0.0.1:8500"
defaultConsulCatalog.ExposedByDefault = true
defaultConsulCatalog.Constraints = types.Constraints{}
defaultConsulCatalog.Prefix = "traefik"
defaultConsulCatalog.FrontEndRule = "Host:{{.ServiceName}}.{{.Domain}}"
defaultConsulCatalog.Stale = false
// default Etcd
var defaultEtcd etcd.Provider
defaultEtcd.Watch = true
defaultEtcd.Endpoint = "127.0.0.1:2379"
defaultEtcd.Prefix = "/traefik"
defaultEtcd.Constraints = types.Constraints{}
// default Zookeeper
var defaultZookeeper zk.Provider
defaultZookeeper.Watch = true
defaultZookeeper.Endpoint = "127.0.0.1:2181"
defaultZookeeper.Prefix = "traefik"
defaultZookeeper.Constraints = types.Constraints{}
// default Boltdb
var defaultBoltDb boltdb.Provider
defaultBoltDb.Watch = true
defaultBoltDb.Endpoint = "127.0.0.1:4001"
defaultBoltDb.Prefix = "/traefik"
defaultBoltDb.Constraints = types.Constraints{}
// default Kubernetes
var defaultKubernetes kubernetes.Provider
defaultKubernetes.Watch = true
defaultKubernetes.Constraints = types.Constraints{}
// default Mesos
var defaultMesos mesos.Provider
defaultMesos.Watch = true
defaultMesos.Endpoint = "http://127.0.0.1:5050"
defaultMesos.ExposedByDefault = true
defaultMesos.Constraints = types.Constraints{}
defaultMesos.RefreshSeconds = 30
defaultMesos.ZkDetectionTimeout = 30
defaultMesos.StateTimeoutSecond = 30
// default ECS
var defaultECS ecs.Provider
defaultECS.Watch = true
defaultECS.ExposedByDefault = true
defaultECS.AutoDiscoverClusters = false
defaultECS.Clusters = ecs.Clusters{"default"}
defaultECS.RefreshSeconds = 15
defaultECS.Constraints = types.Constraints{}
// default Rancher
var defaultRancher rancher.Provider
defaultRancher.Watch = true
defaultRancher.ExposedByDefault = true
defaultRancher.RefreshSeconds = 15
// default DynamoDB
var defaultDynamoDB dynamodb.Provider
defaultDynamoDB.Constraints = types.Constraints{}
defaultDynamoDB.RefreshSeconds = 15
defaultDynamoDB.TableName = "traefik"
defaultDynamoDB.Watch = true
// default Eureka
var defaultEureka eureka.Provider
defaultEureka.RefreshSeconds = flaeg.Duration(30 * time.Second)
// default ServiceFabric
var defaultServiceFabric servicefabric.Provider
defaultServiceFabric.APIVersion = sf.DefaultAPIVersion
defaultServiceFabric.RefreshSeconds = 10
// default Ping
var defaultPing = ping.Handler{
EntryPoint: "traefik",
}
// default TraefikLog
defaultTraefikLog := types.TraefikLog{
Format: "common",
FilePath: "",
}
// default AccessLog
defaultAccessLog := types.AccessLog{
Format: accesslog.CommonFormat,
FilePath: "",
Filters: &types.AccessLogFilters{},
Fields: &types.AccessLogFields{
DefaultMode: types.AccessLogKeep,
Headers: &types.FieldHeaders{
DefaultMode: types.AccessLogKeep,
},
},
}
// default HealthCheckConfig
healthCheck := configuration.HealthCheckConfig{
Interval: flaeg.Duration(configuration.DefaultHealthCheckInterval),
}
// default RespondingTimeouts
respondingTimeouts := configuration.RespondingTimeouts{
IdleTimeout: flaeg.Duration(configuration.DefaultIdleTimeout),
}
// default ForwardingTimeouts
forwardingTimeouts := configuration.ForwardingTimeouts{
DialTimeout: flaeg.Duration(configuration.DefaultDialTimeout),
}
// default Tracing
defaultTracing := tracing.Tracing{
Backend: "jaeger",
ServiceName: "traefik",
SpanNameLimit: 0,
Jaeger: &jaeger.Config{
SamplingServerURL: "http://localhost:5778/sampling",
SamplingType: "const",
SamplingParam: 1.0,
LocalAgentHostPort: "127.0.0.1:6831",
},
Zipkin: &zipkin.Config{
HTTPEndpoint: "http://localhost:9411/api/v1/spans",
SameSpan: false,
ID128Bit: true,
Debug: false,
},
DataDog: &datadog.Config{
LocalAgentHostPort: "localhost:8126",
GlobalTag: "",
Debug: false,
},
}
// default LifeCycle
defaultLifeCycle := configuration.LifeCycle{
GraceTimeOut: flaeg.Duration(configuration.DefaultGraceTimeout),
}
// default ApiConfiguration
defaultAPI := api.Handler{
EntryPoint: "traefik",
Dashboard: true,
}
defaultAPI.Statistics = &types.Statistics{
RecentErrors: 10,
}
// default Metrics
defaultMetrics := types.Metrics{
Prometheus: &types.Prometheus{
Buckets: types.Buckets{0.1, 0.3, 1.2, 5},
EntryPoint: configuration.DefaultInternalEntryPointName,
},
Datadog: &types.Datadog{
Address: "localhost:8125",
PushInterval: "10s",
},
StatsD: &types.Statsd{
Address: "localhost:8125",
PushInterval: "10s",
},
InfluxDB: &types.InfluxDB{
Address: "localhost:8089",
Protocol: "udp",
PushInterval: "10s",
},
}
defaultResolver := configuration.HostResolverConfig{
CnameFlattening: false,
ResolvConfig: "/etc/resolv.conf",
ResolvDepth: 5,
}
defaultConfiguration := configuration.GlobalConfiguration{
Docker: &defaultDocker,
File: &defaultFile,
Web: &defaultWeb,
Rest: &defaultRest,
Marathon: &defaultMarathon,
Consul: &defaultConsul,
ConsulCatalog: &defaultConsulCatalog,
Etcd: &defaultEtcd,
Zookeeper: &defaultZookeeper,
Boltdb: &defaultBoltDb,
Kubernetes: &defaultKubernetes,
Mesos: &defaultMesos,
ECS: &defaultECS,
Rancher: &defaultRancher,
Eureka: &defaultEureka,
DynamoDB: &defaultDynamoDB,
Retry: &configuration.Retry{},
HealthCheck: &healthCheck,
RespondingTimeouts: &respondingTimeouts,
ForwardingTimeouts: &forwardingTimeouts,
TraefikLog: &defaultTraefikLog,
AccessLog: &defaultAccessLog,
LifeCycle: &defaultLifeCycle,
Ping: &defaultPing,
API: &defaultAPI,
Metrics: &defaultMetrics,
Tracing: &defaultTracing,
HostResolver: &defaultResolver,
}
return &TraefikConfiguration{
GlobalConfiguration: defaultConfiguration,
}
}
// NewTraefikConfiguration creates a TraefikConfiguration with default values
func NewTraefikConfiguration() *TraefikConfiguration {
return &TraefikConfiguration{
GlobalConfiguration: configuration.GlobalConfiguration{
AccessLogsFile: "",
TraefikLogsFile: "",
EntryPoints: map[string]*configuration.EntryPoint{},
Constraints: types.Constraints{},
DefaultEntryPoints: []string{"http"},
ProvidersThrottleDuration: flaeg.Duration(2 * time.Second),
MaxIdleConnsPerHost: 200,
IdleTimeout: flaeg.Duration(0),
HealthCheck: &configuration.HealthCheckConfig{
Interval: flaeg.Duration(configuration.DefaultHealthCheckInterval),
},
LifeCycle: &configuration.LifeCycle{
GraceTimeOut: flaeg.Duration(configuration.DefaultGraceTimeout),
},
// NewTraefikConfiguration creates a TraefikCmdConfiguration with default values.
func NewTraefikConfiguration() *TraefikCmdConfiguration {
return &TraefikCmdConfiguration{
Configuration: static.Configuration{
Global: &static.Global{
CheckNewVersion: true,
},
EntryPoints: make(static.EntryPoints),
Providers: &static.Providers{
ProvidersThrottleDuration: ptypes.Duration(2 * time.Second),
},
ServersTransport: &static.ServersTransport{
MaxIdleConnsPerHost: 200,
},
TCPServersTransport: &static.TCPServersTransport{
DialTimeout: ptypes.Duration(30 * time.Second),
DialKeepAlive: ptypes.Duration(15 * time.Second),
},
},
ConfigFile: "",
}
}

View File

@ -1,22 +0,0 @@
package cmd
import (
"context"
"os"
"os/signal"
"syscall"
)
// ContextWithSignal create a context cancelled when SIGINT or SIGTERM are notified
func ContextWithSignal(ctx context.Context) context.Context {
newCtx, cancel := context.WithCancel(ctx)
signals := make(chan os.Signal)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM)
go func() {
select {
case <-signals:
cancel()
}
}()
return newCtx
}

View File

@ -1,41 +1,40 @@
package healthcheck
import (
"crypto/tls"
"errors"
"fmt"
"net/http"
"os"
"time"
"github.com/containous/flaeg"
"github.com/containous/traefik/cmd"
"github.com/containous/traefik/configuration"
"github.com/traefik/paerser/cli"
"github.com/traefik/traefik/v3/pkg/config/static"
)
// NewCmd builds a new HealthCheck command
func NewCmd(traefikConfiguration *cmd.TraefikConfiguration, traefikPointersConfiguration *cmd.TraefikConfiguration) *flaeg.Command {
return &flaeg.Command{
// NewCmd builds a new HealthCheck command.
func NewCmd(traefikConfiguration *static.Configuration, loaders []cli.ResourceLoader) *cli.Command {
return &cli.Command{
Name: "healthcheck",
Description: `Calls traefik /ping to check health (web provider must be enabled)`,
Config: traefikConfiguration,
DefaultPointersConfig: traefikPointersConfiguration,
Description: `Calls Traefik /ping endpoint (disabled by default) to check the health of Traefik.`,
Configuration: traefikConfiguration,
Run: runCmd(traefikConfiguration),
Metadata: map[string]string{
"parseAllSources": "true",
},
Resources: loaders,
}
}
func runCmd(traefikConfiguration *cmd.TraefikConfiguration) func() error {
return func() error {
traefikConfiguration.GlobalConfiguration.SetEffectiveConfiguration(traefikConfiguration.ConfigFile)
func runCmd(traefikConfiguration *static.Configuration) func(_ []string) error {
return func(_ []string) error {
traefikConfiguration.SetEffectiveConfiguration()
resp, errPing := Do(traefikConfiguration.GlobalConfiguration)
resp, errPing := Do(*traefikConfiguration)
if resp != nil {
resp.Body.Close()
}
if errPing != nil {
fmt.Printf("Error calling healthcheck: %s\n", errPing)
os.Exit(1)
}
if resp.StatusCode != http.StatusOK {
fmt.Printf("Bad healthcheck status: %s\n", resp.Status)
os.Exit(1)
@ -46,28 +45,35 @@ func runCmd(traefikConfiguration *cmd.TraefikConfiguration) func() error {
}
}
// Do try to do a healthcheck
func Do(globalConfiguration configuration.GlobalConfiguration) (*http.Response, error) {
if globalConfiguration.Ping == nil {
// Do try to do a healthcheck.
func Do(staticConfiguration static.Configuration) (*http.Response, error) {
if staticConfiguration.Ping == nil {
return nil, errors.New("please enable `ping` to use health check")
}
pingEntryPoint, ok := globalConfiguration.EntryPoints[globalConfiguration.Ping.EntryPoint]
ep := staticConfiguration.Ping.EntryPoint
if ep == "" {
ep = "traefik"
}
pingEntryPoint, ok := staticConfiguration.EntryPoints[ep]
if !ok {
return nil, errors.New("missing `ping` entrypoint")
return nil, fmt.Errorf("ping: missing %s entry point", ep)
}
client := &http.Client{Timeout: 5 * time.Second}
protocol := "http"
if pingEntryPoint.TLS != nil {
protocol = "https"
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client.Transport = tr
}
// TODO Handle TLS on ping etc...
// if pingEntryPoint.TLS != nil {
// protocol = "https"
// tr := &http.Transport{
// TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
// }
// client.Transport = tr
// }
path := "/"
if globalConfiguration.Web != nil {
path = globalConfiguration.Web.Path
}
return client.Head(protocol + "://" + pingEntryPoint.Address + path + "ping")
return client.Head(protocol + "://" + pingEntryPoint.GetAddress() + path + "ping")
}

View File

@ -0,0 +1,332 @@
package main
import (
"bytes"
"fmt"
"go/format"
"go/importer"
"go/token"
"go/types"
"io"
"log"
"os"
"path"
"path/filepath"
"reflect"
"slices"
"sort"
"strings"
"golang.org/x/tools/imports"
)
// File a kind of AST element that represents a file.
type File struct {
Package string
Imports []string
Elements []Element
}
// Element is a simplified version of a symbol.
type Element struct {
Name string
Value string
}
// Centrifuge a centrifuge.
// Generate Go Structures from Go structures.
type Centrifuge struct {
IncludedImports []string
ExcludedTypes []string
ExcludedFiles []string
TypeCleaner func(types.Type, string) string
PackageCleaner func(string) string
rootPkg string
fileSet *token.FileSet
pkg *types.Package
}
// NewCentrifuge creates a new Centrifuge.
func NewCentrifuge(rootPkg string) (*Centrifuge, error) {
fileSet := token.NewFileSet()
pkg, err := importer.ForCompiler(fileSet, "source", nil).Import(rootPkg)
if err != nil {
return nil, err
}
return &Centrifuge{
fileSet: fileSet,
pkg: pkg,
rootPkg: rootPkg,
TypeCleaner: func(typ types.Type, _ string) string {
return typ.String()
},
PackageCleaner: func(s string) string {
return s
},
}, nil
}
// Run runs the code extraction and the code generation.
func (c Centrifuge) Run(dest string, pkgName string) error {
files := c.run(c.pkg.Scope(), c.rootPkg, pkgName)
err := fileWriter{baseDir: dest}.Write(files)
if err != nil {
return err
}
for _, p := range c.pkg.Imports() {
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 {
return err
}
}
}
return err
}
func (c Centrifuge) run(sc *types.Scope, rootPkg string, pkgName string) map[string]*File {
files := map[string]*File{}
for _, name := range sc.Names() {
if slices.Contains(c.ExcludedTypes, name) {
continue
}
o := sc.Lookup(name)
if !o.Exported() {
continue
}
filename := filepath.Base(c.fileSet.File(o.Pos()).Name())
if slices.Contains(c.ExcludedFiles, path.Join(rootPkg, filename)) {
continue
}
fl, ok := files[filename]
if !ok {
files[filename] = &File{Package: pkgName}
fl = files[filename]
}
elt := Element{
Name: name,
}
switch ob := o.(type) {
case *types.TypeName:
switch obj := ob.Type().(*types.Named).Underlying().(type) {
case *types.Struct:
elt.Value = c.writeStruct(name, obj, rootPkg, fl)
case *types.Map:
elt.Value = fmt.Sprintf("type %s map[%s]%s\n", name, obj.Key().String(), c.TypeCleaner(obj.Elem(), rootPkg))
case *types.Slice:
elt.Value = fmt.Sprintf("type %s []%v\n", name, c.TypeCleaner(obj.Elem(), rootPkg))
case *types.Basic:
elt.Value = fmt.Sprintf("type %s %v\n", name, obj.Name())
default:
log.Printf("OTHER TYPE::: %s %T\n", name, o.Type().(*types.Named).Underlying())
continue
}
default:
log.Printf("OTHER::: %s %T\n", name, o)
continue
}
if len(elt.Value) > 0 {
fl.Elements = append(fl.Elements, elt)
}
}
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 := range obj.NumFields() {
field := obj.Field(i)
if !field.Exported() {
continue
}
fPkg := c.PackageCleaner(extractPackage(field.Type()))
if fPkg != "" && fPkg != rootPkg {
elt.Imports = append(elt.Imports, fPkg)
}
fType := c.TypeCleaner(field.Type(), rootPkg)
if field.Embedded() {
b.WriteString(fmt.Sprintf("\t%s\n", fType))
continue
}
values, ok := lookupTagValue(obj.Tag(i), "json")
if len(values) > 0 && values[0] == "-" {
continue
}
b.WriteString(fmt.Sprintf("\t%s %s", field.Name(), fType))
if ok {
b.WriteString(fmt.Sprintf(" `json:\"%s\"`", strings.Join(values, ",")))
}
b.WriteString("\n")
}
b.WriteString("}\n")
return b.String()
}
func lookupTagValue(raw, key string) ([]string, bool) {
value, ok := reflect.StructTag(raw).Lookup(key)
if !ok {
return nil, ok
}
values := strings.Split(value, ",")
if len(values) < 1 {
return nil, true
}
return values, true
}
func extractPackage(t types.Type) string {
switch tu := t.(type) {
case *types.Named:
return tu.Obj().Pkg().Path()
case *types.Slice:
if v, ok := tu.Elem().(*types.Named); ok {
return v.Obj().Pkg().Path()
}
return ""
case *types.Map:
if v, ok := tu.Elem().(*types.Named); ok {
return v.Obj().Pkg().Path()
}
return ""
case *types.Pointer:
return extractPackage(tu.Elem())
default:
return ""
}
}
type fileWriter struct {
baseDir string
}
func (f fileWriter) Write(files map[string]*File) error {
err := os.MkdirAll(f.baseDir, 0o755)
if err != nil {
return err
}
for name, file := range files {
err = f.writeFile(name, file)
if err != nil {
return err
}
}
return nil
}
func (f fileWriter) writeFile(name string, desc *File) error {
if len(desc.Elements) == 0 {
return nil
}
filename := filepath.Join(f.baseDir, name)
file, err := os.Create(filename)
if err != nil {
return fmt.Errorf("failed to create file: %w", err)
}
defer func() { _ = file.Close() }()
b := bytes.NewBufferString("package ")
b.WriteString(desc.Package)
b.WriteString("\n")
b.WriteString("// Code generated by centrifuge. DO NOT EDIT.\n")
b.WriteString("\n")
f.writeImports(b, desc.Imports)
b.WriteString("\n")
for _, elt := range desc.Elements {
b.WriteString(elt.Value)
b.WriteString("\n")
}
// gofmt
source, err := format.Source(b.Bytes())
if err != nil {
log.Println(b.String())
return fmt.Errorf("failed to format sources: %w", err)
}
// goimports
process, err := imports.Process(filename, source, nil)
if err != nil {
log.Println(string(source))
return fmt.Errorf("failed to format imports: %w", err)
}
_, err = file.Write(process)
if err != nil {
return err
}
return nil
}
func (f fileWriter) writeImports(b io.StringWriter, imports []string) {
if len(imports) == 0 {
return
}
uniq := map[string]struct{}{}
sort.Strings(imports)
_, _ = b.WriteString("import (\n")
for _, s := range imports {
if _, exist := uniq[s]; exist {
continue
}
uniq[s] = struct{}{}
_, _ = b.WriteString(fmt.Sprintf(` "%s"`+"\n", s))
}
_, _ = b.WriteString(")\n")
}

124
cmd/internal/gen/main.go Normal file
View File

@ -0,0 +1,124 @@
package main
import (
"fmt"
"go/build"
"go/types"
"log"
"os"
"path"
"path/filepath"
"strings"
)
const rootPkg = "github.com/traefik/traefik/v3/pkg/config/dynamic"
const (
destModuleName = "github.com/traefik/genconf"
destPkg = "dynamic"
)
const marsh = `package %s
import "encoding/json"
type JSONPayload struct {
*Configuration
}
func (c JSONPayload) MarshalJSON() ([]byte, error) {
if c.Configuration == nil {
return nil, nil
}
return json.Marshal(c.Configuration)
}
`
// main generate Go Structures from Go structures.
// Allows to create an external module (destModuleName) used by the plugin's providers
// that contains Go structs of the dynamic configuration and nothing else.
// These Go structs do not have any non-exported fields and do not rely on any external dependencies.
func main() {
dest := filepath.Join(path.Join(build.Default.GOPATH, "src"), destModuleName, destPkg)
log.Println("Output:", dest)
err := run(dest)
if err != nil {
log.Fatal(err)
}
}
func run(dest string) error {
centrifuge, err := NewCentrifuge(rootPkg)
if err != nil {
return err
}
centrifuge.IncludedImports = []string{
"github.com/traefik/traefik/v3/pkg/tls",
"github.com/traefik/traefik/v3/pkg/types",
}
centrifuge.ExcludedTypes = []string{
// tls
"CertificateStore", "Manager",
// dynamic
"Message", "Configurations",
// types
"HTTPCodeRanges", "HostResolverConfig",
}
centrifuge.ExcludedFiles = []string{
"github.com/traefik/traefik/v3/pkg/types/logs.go",
"github.com/traefik/traefik/v3/pkg/types/metrics.go",
}
centrifuge.TypeCleaner = cleanType
centrifuge.PackageCleaner = cleanPackage
err = centrifuge.Run(dest, destPkg)
if err != nil {
return err
}
return os.WriteFile(filepath.Join(dest, "marshaler.go"), []byte(fmt.Sprintf(marsh, destPkg)), 0o666)
}
func cleanType(typ types.Type, base string) string {
if typ.String() == "github.com/traefik/traefik/v3/pkg/types.FileOrContent" {
return "string"
}
if typ.String() == "[]github.com/traefik/traefik/v3/pkg/types.FileOrContent" {
return "[]string"
}
if typ.String() == "github.com/traefik/paerser/types.Duration" {
return "string"
}
if strings.Contains(typ.String(), base) {
return strings.ReplaceAll(typ.String(), base+".", "")
}
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()
}
func cleanPackage(src string) string {
switch src {
case "github.com/traefik/paerser/types":
return ""
case "github.com/traefik/traefik/v3/pkg/tls":
return path.Join(destModuleName, destPkg, "tls")
case "github.com/traefik/traefik/v3/pkg/types":
return path.Join(destModuleName, destPkg, "types")
default:
return src
}
}

View File

@ -1,211 +0,0 @@
package storeconfig
import (
"encoding/json"
"fmt"
"io/ioutil"
stdlog "log"
"os"
"github.com/abronan/valkeyrie/store"
"github.com/containous/flaeg"
"github.com/containous/staert"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/cmd"
"github.com/containous/traefik/log"
)
// NewCmd builds a new StoreConfig command
func NewCmd(traefikConfiguration *cmd.TraefikConfiguration, traefikPointersConfiguration *cmd.TraefikConfiguration) *flaeg.Command {
return &flaeg.Command{
Name: "storeconfig",
Description: `Store the static traefik configuration into a Key-value stores. Traefik will not start.`,
Config: traefikConfiguration,
DefaultPointersConfig: traefikPointersConfiguration,
Metadata: map[string]string{
"parseAllSources": "true",
},
}
}
// Run store config in KV
func Run(kv *staert.KvSource, traefikConfiguration *cmd.TraefikConfiguration) func() error {
return func() error {
if kv == nil {
return fmt.Errorf("error using command storeconfig, no Key-value store defined")
}
fileConfig := traefikConfiguration.GlobalConfiguration.File
if fileConfig != nil {
traefikConfiguration.GlobalConfiguration.File = nil
if len(fileConfig.Filename) == 0 && len(fileConfig.Directory) == 0 {
fileConfig.Filename = traefikConfiguration.ConfigFile
}
}
jsonConf, err := json.Marshal(traefikConfiguration.GlobalConfiguration)
if err != nil {
return err
}
stdlog.Printf("Storing configuration: %s\n", jsonConf)
err = kv.StoreConfig(traefikConfiguration.GlobalConfiguration)
if err != nil {
return err
}
if fileConfig != nil {
jsonConf, err = json.Marshal(fileConfig)
if err != nil {
return err
}
stdlog.Printf("Storing file configuration: %s\n", jsonConf)
config, err := fileConfig.BuildConfiguration()
if err != nil {
return err
}
stdlog.Print("Writing config to KV")
err = kv.StoreConfig(config)
if err != nil {
return err
}
}
if traefikConfiguration.GlobalConfiguration.ACME != nil {
account := &acme.Account{}
// Migrate ACME data from file to KV store if needed
if len(traefikConfiguration.GlobalConfiguration.ACME.StorageFile) > 0 {
account, err = migrateACMEData(traefikConfiguration.GlobalConfiguration.ACME.StorageFile)
if err != nil {
return err
}
}
accountInitialized, err := keyExists(kv, traefikConfiguration.GlobalConfiguration.ACME.Storage)
if err != nil && err != store.ErrKeyNotFound {
return err
}
// Check to see if ACME account object is already in kv store
if traefikConfiguration.GlobalConfiguration.ACME.OverrideCertificates || !accountInitialized {
// Store the ACME Account into the KV Store
// Certificates in KV Store will be overridden
meta := cluster.NewMetadata(account)
err = meta.Marshall()
if err != nil {
return err
}
source := staert.KvSource{
Store: kv,
Prefix: traefikConfiguration.GlobalConfiguration.ACME.Storage,
}
err = source.StoreConfig(meta)
if err != nil {
return err
}
}
// Force to delete storagefile
return kv.Delete(kv.Prefix + "/acme/storagefile")
}
return nil
}
}
func keyExists(source *staert.KvSource, key string) (bool, error) {
list, err := source.List(key, nil)
if err != nil {
return false, err
}
return len(list) > 0, nil
}
// migrateACMEData allows migrating data from acme.json file to KV store in function of the file format
func migrateACMEData(fileName string) (*acme.Account, error) {
f, err := os.Open(fileName)
if err != nil {
return nil, err
}
defer f.Close()
file, err := ioutil.ReadAll(f)
if err != nil {
return nil, err
}
// Check if the storage file is not empty before to get data
account := &acme.Account{}
if len(file) > 0 {
accountFromNewFormat, err := acme.FromNewToOldFormat(fileName)
if err != nil {
return nil, err
}
if accountFromNewFormat == nil {
// convert ACME json file to KV store (used for backward compatibility)
localStore := acme.NewLocalStore(fileName)
account, err = localStore.Get()
if err != nil {
return nil, err
}
err = account.RemoveAccountV1Values()
if err != nil {
return nil, err
}
} else {
account = accountFromNewFormat
}
} else {
log.Warnf("No data will be imported from the storageFile %q because it is empty.", fileName)
}
err = account.Init()
return account, err
}
// CreateKvSource creates KvSource
// TLS support is enable for Consul and Etcd backends
func CreateKvSource(traefikConfiguration *cmd.TraefikConfiguration) (*staert.KvSource, error) {
var kv *staert.KvSource
var kvStore store.Store
var err error
switch {
case traefikConfiguration.Consul != nil:
kvStore, err = traefikConfiguration.Consul.CreateStore()
kv = &staert.KvSource{
Store: kvStore,
Prefix: traefikConfiguration.Consul.Prefix,
}
case traefikConfiguration.Etcd != nil:
kvStore, err = traefikConfiguration.Etcd.CreateStore()
kv = &staert.KvSource{
Store: kvStore,
Prefix: traefikConfiguration.Etcd.Prefix,
}
case traefikConfiguration.Zookeeper != nil:
kvStore, err = traefikConfiguration.Zookeeper.CreateStore()
kv = &staert.KvSource{
Store: kvStore,
Prefix: traefikConfiguration.Zookeeper.Prefix,
}
case traefikConfiguration.Boltdb != nil:
kvStore, err = traefikConfiguration.Boltdb.CreateStore()
kv = &staert.KvSource{
Store: kvStore,
Prefix: traefikConfiguration.Boltdb.Prefix,
}
}
return kv, err
}

114
cmd/traefik/logger.go Normal file
View File

@ -0,0 +1,114 @@
package main
import (
"context"
"errors"
"fmt"
"io"
stdlog "log"
"os"
"strings"
"time"
"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"
"gopkg.in/natefinch/lumberjack.v2"
)
func init() {
// hide the first logs before the setup of the logger.
zerolog.SetGlobalLevel(zerolog.ErrorLevel)
}
func setupLogger(ctx context.Context, staticConfiguration *static.Configuration) error {
// Validate that the experimental flag is set up at this point,
// rather than validating the static configuration before the setupLogger call.
// This ensures that validation messages are not logged using an un-configured logger.
if staticConfiguration.Log != nil && staticConfiguration.Log.OTLP != nil &&
(staticConfiguration.Experimental == nil || !staticConfiguration.Experimental.OTLPLogs) {
return errors.New("the experimental OTLPLogs feature must be enabled to use OTLP logging")
}
// configure log format
w := getLogWriter(staticConfiguration)
// configure log level
logLevel := getLogLevel(staticConfiguration)
zerolog.SetGlobalLevel(logLevel)
// create logger
logger := zerolog.New(w).With().Timestamp()
if logLevel <= zerolog.DebugLevel {
logger = logger.Caller()
}
log.Logger = logger.Logger().Level(logLevel)
if staticConfiguration.Log != nil && staticConfiguration.Log.OTLP != nil {
var err error
log.Logger, err = logs.SetupOTelLogger(ctx, log.Logger, staticConfiguration.Log.OTLP)
if err != nil {
return fmt.Errorf("setting up OpenTelemetry logger: %w", err)
}
}
zerolog.DefaultContextLogger = &log.Logger
// 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))
return nil
}
func getLogWriter(staticConfiguration *static.Configuration) io.Writer {
if staticConfiguration.Log != nil && staticConfiguration.Log.OTLP != nil {
return io.Discard
}
var w io.Writer = os.Stdout
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
}

83
cmd/traefik/plugins.go Normal file
View File

@ -0,0 +1,83 @@
package main
import (
"fmt"
"github.com/traefik/traefik/v3/pkg/config/static"
"github.com/traefik/traefik/v3/pkg/plugins"
)
const outputDir = "./plugins-storage/"
func createPluginBuilder(staticConfiguration *static.Configuration) (*plugins.Builder, error) {
client, plgs, localPlgs, err := initPlugins(staticConfiguration)
if err != nil {
return nil, err
}
return plugins.NewBuilder(client, plgs, localPlgs)
}
func initPlugins(staticCfg *static.Configuration) (*plugins.Client, map[string]plugins.Descriptor, map[string]plugins.LocalDescriptor, error) {
err := checkUniquePluginNames(staticCfg.Experimental)
if err != nil {
return nil, nil, nil, err
}
var client *plugins.Client
plgs := map[string]plugins.Descriptor{}
if hasPlugins(staticCfg) {
opts := plugins.ClientOptions{
Output: outputDir,
}
var err error
client, err = plugins.NewClient(opts)
if err != nil {
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, fmt.Errorf("unable to set up plugins environment: %w", err)
}
plgs = staticCfg.Experimental.Plugins
}
localPlgs := map[string]plugins.LocalDescriptor{}
if hasLocalPlugins(staticCfg) {
err := plugins.SetupLocalPlugins(staticCfg.Experimental.LocalPlugins)
if err != nil {
return nil, nil, nil, err
}
localPlgs = staticCfg.Experimental.LocalPlugins
}
return client, plgs, localPlgs, nil
}
func checkUniquePluginNames(e *static.Experimental) error {
if e == nil {
return nil
}
for s := range e.LocalPlugins {
if _, ok := e.Plugins[s]; ok {
return fmt.Errorf("the plugin's name %q must be unique", s)
}
}
return nil
}
func hasPlugins(staticCfg *static.Configuration) bool {
return staticCfg.Experimental != nil && len(staticCfg.Experimental.Plugins) > 0
}
func hasLocalPlugins(staticCfg *static.Configuration) bool {
return staticCfg.Experimental != nil && len(staticCfg.Experimental.LocalPlugins) > 0
}

View File

@ -2,339 +2,616 @@ package main
import (
"context"
"encoding/json"
fmtlog "log"
"crypto/x509"
"fmt"
"io"
stdlog "log"
"maps"
"net/http"
"os"
"path/filepath"
"reflect"
"os/signal"
"slices"
"strings"
"syscall"
"time"
"github.com/cenk/backoff"
"github.com/containous/flaeg"
"github.com/containous/staert"
"github.com/containous/traefik/autogen/genstatic"
"github.com/containous/traefik/cmd"
"github.com/containous/traefik/cmd/bug"
"github.com/containous/traefik/cmd/healthcheck"
"github.com/containous/traefik/cmd/storeconfig"
cmdVersion "github.com/containous/traefik/cmd/version"
"github.com/containous/traefik/collector"
"github.com/containous/traefik/configuration"
"github.com/containous/traefik/configuration/router"
"github.com/containous/traefik/job"
"github.com/containous/traefik/log"
"github.com/containous/traefik/provider/ecs"
"github.com/containous/traefik/provider/kubernetes"
"github.com/containous/traefik/safe"
"github.com/containous/traefik/server"
"github.com/containous/traefik/server/uuid"
traefiktls "github.com/containous/traefik/tls"
"github.com/containous/traefik/types"
"github.com/containous/traefik/version"
"github.com/coreos/go-systemd/daemon"
"github.com/elazarl/go-bindata-assetfs"
"github.com/ogier/pflag"
"github.com/coreos/go-systemd/v22/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/vulcand/oxy/roundrobin"
"github.com/spiffe/go-spiffe/v2/workloadapi"
"github.com/traefik/paerser/cli"
"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/proxy"
"github.com/traefik/traefik/v3/pkg/proxy/httputil"
"github.com/traefik/traefik/v3/pkg/redactor"
"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
traefikConfiguration := cmd.NewTraefikConfiguration()
traefikPointersConfiguration := cmd.NewTraefikDefaultPointersConfiguration()
tConfig := cmd.NewTraefikConfiguration()
// traefik Command init
traefikCmd := &flaeg.Command{
loaders := []cli.ResourceLoader{&tcli.DeprecationLoader{}, &tcli.FileLoader{}, &tcli.FlagLoader{}, &tcli.EnvLoader{}}
cmdTraefik := &cli.Command{
Name: "traefik",
Description: `traefik is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease.
Description: `Traefik is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease.
Complete documentation is available at https://traefik.io`,
Config: traefikConfiguration,
DefaultPointersConfig: traefikPointersConfiguration,
Run: func() error {
runCmd(&traefikConfiguration.GlobalConfiguration, traefikConfiguration.ConfigFile)
return nil
Configuration: tConfig,
Resources: loaders,
Run: func(_ []string) error {
return runCmd(&tConfig.Configuration)
},
}
// storeconfig Command init
storeConfigCmd := storeconfig.NewCmd(traefikConfiguration, traefikPointersConfiguration)
// init flaeg source
f := flaeg.New(traefikCmd, os.Args[1:])
// add custom parsers
f.AddParser(reflect.TypeOf(configuration.EntryPoints{}), &configuration.EntryPoints{})
f.AddParser(reflect.TypeOf(configuration.DefaultEntryPoints{}), &configuration.DefaultEntryPoints{})
f.AddParser(reflect.TypeOf(traefiktls.FilesOrContents{}), &traefiktls.FilesOrContents{})
f.AddParser(reflect.TypeOf(types.Constraints{}), &types.Constraints{})
f.AddParser(reflect.TypeOf(kubernetes.Namespaces{}), &kubernetes.Namespaces{})
f.AddParser(reflect.TypeOf(ecs.Clusters{}), &ecs.Clusters{})
f.AddParser(reflect.TypeOf([]types.Domain{}), &types.Domains{})
f.AddParser(reflect.TypeOf(types.DNSResolvers{}), &types.DNSResolvers{})
f.AddParser(reflect.TypeOf(types.Buckets{}), &types.Buckets{})
f.AddParser(reflect.TypeOf(types.StatusCodes{}), &types.StatusCodes{})
f.AddParser(reflect.TypeOf(types.FieldNames{}), &types.FieldNames{})
f.AddParser(reflect.TypeOf(types.FieldHeaderNames{}), &types.FieldHeaderNames{})
// add commands
f.AddCommand(cmdVersion.NewCmd())
f.AddCommand(bug.NewCmd(traefikConfiguration, traefikPointersConfiguration))
f.AddCommand(storeConfigCmd)
f.AddCommand(healthcheck.NewCmd(traefikConfiguration, traefikPointersConfiguration))
usedCmd, err := f.GetCommand()
err := cmdTraefik.AddCommand(healthcheck.NewCmd(&tConfig.Configuration, loaders))
if err != nil {
fmtlog.Println(err)
stdlog.Println(err)
os.Exit(1)
}
if _, err := f.Parse(usedCmd); err != nil {
if err == pflag.ErrHelp {
os.Exit(0)
}
fmtlog.Printf("Error parsing command: %s\n", err)
os.Exit(1)
}
// staert init
s := staert.NewStaert(traefikCmd)
// init TOML source
toml := staert.NewTomlSource("traefik", []string{traefikConfiguration.ConfigFile, "/etc/traefik/", "$HOME/.traefik/", "."})
// add sources to staert
s.AddSource(toml)
s.AddSource(f)
if _, err := s.LoadConfig(); err != nil {
fmtlog.Printf("Error reading TOML config file %s : %s\n", toml.ConfigFileUsed(), err)
os.Exit(1)
}
traefikConfiguration.ConfigFile = toml.ConfigFileUsed()
kv, err := storeconfig.CreateKvSource(traefikConfiguration)
err = cmdTraefik.AddCommand(cmdVersion.NewCmd())
if err != nil {
fmtlog.Printf("Error creating kv store: %s\n", err)
stdlog.Println(err)
os.Exit(1)
}
storeConfigCmd.Run = storeconfig.Run(kv, traefikConfiguration)
// if a KV Store is enable and no sub-command called in args
if kv != nil && usedCmd == traefikCmd {
if traefikConfiguration.Cluster == nil {
traefikConfiguration.Cluster = &types.Cluster{Node: uuid.Get()}
}
if traefikConfiguration.Cluster.Store == nil {
traefikConfiguration.Cluster.Store = &types.Store{Prefix: kv.Prefix, Store: kv.Store}
}
s.AddSource(kv)
operation := func() error {
_, err := s.LoadConfig()
return err
}
notify := func(err error, time time.Duration) {
log.Errorf("Load config error: %+v, retrying in %s", err, time)
}
err := backoff.RetryNotify(safe.OperationWithRecover(operation), job.NewBackOff(backoff.NewExponentialBackOff()), notify)
err = cli.Execute(cmdTraefik)
if err != nil {
fmtlog.Printf("Error loading configuration: %s\n", err)
os.Exit(1)
}
log.Error().Err(err).Msg("Command error")
logrus.Exit(1)
}
if err := s.Run(); err != nil {
fmtlog.Printf("Error running traefik: %s\n", err)
os.Exit(1)
logrus.Exit(0)
}
os.Exit(0)
}
func runCmd(staticConfiguration *static.Configuration) error {
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()
func runCmd(globalConfiguration *configuration.GlobalConfiguration, configFile string) {
configureLogging(globalConfiguration)
if len(configFile) > 0 {
log.Infof("Using TOML configuration file %s", configFile)
if err := setupLogger(ctx, staticConfiguration); err != nil {
return fmt.Errorf("setting up logger: %w", err)
}
http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment
if globalConfiguration.AllowMinWeightZero {
roundrobin.SetDefaultWeight(0)
staticConfiguration.SetEffectiveConfiguration()
if err := staticConfiguration.ValidateConfiguration(); err != nil {
return err
}
globalConfiguration.SetEffectiveConfiguration(configFile)
globalConfiguration.ValidateConfiguration()
log.Info().Str("version", version.Version).
Msgf("Traefik version %s built on %s", version.Version, version.BuildDate)
log.Infof("Traefik version %s built on %s", version.Version, version.BuildDate)
jsonConf, err := json.Marshal(globalConfiguration)
redactedStaticConfiguration, err := redactor.RemoveCredentials(staticConfiguration)
if err != nil {
log.Error(err)
log.Debugf("Global configuration loaded [struct] %#v", globalConfiguration)
log.Error().Err(err).Msg("Could not redact static configuration")
} else {
log.Debugf("Global configuration loaded %s", string(jsonConf))
log.Debug().RawJSON("staticConfiguration", []byte(redactedStaticConfiguration)).Msg("Static configuration loaded [json]")
}
if globalConfiguration.API != nil && globalConfiguration.API.Dashboard {
globalConfiguration.API.DashboardAssets = &assetfs.AssetFS{Asset: genstatic.Asset, AssetInfo: genstatic.AssetInfo, AssetDir: genstatic.AssetDir, Prefix: "static"}
}
if globalConfiguration.CheckNewVersion {
if staticConfiguration.Global.CheckNewVersion {
checkNewVersion()
}
stats(globalConfiguration)
stats(staticConfiguration)
providerAggregator := configuration.NewProviderAggregator(globalConfiguration)
acmeprovider, err := globalConfiguration.InitACMEProvider()
svr, err := setupServer(staticConfiguration)
if err != nil {
log.Errorf("Unable to initialize ACME provider: %v", err)
} else if acmeprovider != nil {
err = providerAggregator.AddProvider(acmeprovider)
if err != nil {
log.Errorf("Unable to add ACME provider to the providers list: %v", err)
acmeprovider = nil
}
return err
}
entryPoints := map[string]server.EntryPoint{}
for entryPointName, config := range globalConfiguration.EntryPoints {
entryPoint := server.EntryPoint{
Configuration: config,
if staticConfiguration.Ping != nil {
staticConfiguration.Ping.WithContext(ctx)
}
internalRouter := router.NewInternalRouterAggregator(*globalConfiguration, entryPointName)
if acmeprovider != nil {
if acmeprovider.HTTPChallenge != nil && entryPointName == acmeprovider.HTTPChallenge.EntryPoint {
internalRouter.AddRouter(acmeprovider)
}
// TLS ALPN 01
if acmeprovider.TLSChallenge != nil && acmeprovider.HTTPChallenge == nil && acmeprovider.DNSChallenge == nil {
entryPoint.TLSALPNGetter = acmeprovider.GetTLSALPNCertificate
}
if acmeprovider.OnDemand && entryPointName == acmeprovider.EntryPoint {
entryPoint.OnDemandListener = acmeprovider.ListenRequest
}
if entryPointName == acmeprovider.EntryPoint {
entryPoint.CertificateStore = traefiktls.NewCertificateStore()
acmeprovider.SetCertificateStore(entryPoint.CertificateStore)
log.Debugf("Setting Acme Certificate store from Entrypoint: %s", entryPointName)
}
}
entryPoint.InternalRouter = internalRouter
entryPoints[entryPointName] = entryPoint
}
svr := server.NewServer(*globalConfiguration, providerAggregator, entryPoints)
if acmeprovider != nil && acmeprovider.OnHostRule {
acmeprovider.SetConfigListenerChan(make(chan types.Configuration))
svr.AddListener(acmeprovider.ListenConfiguration)
}
ctx := cmd.ContextWithSignal(context.Background())
if globalConfiguration.Ping != nil {
globalConfiguration.Ping.WithContext(ctx)
}
svr.StartWithContext(ctx)
svr.Start(ctx)
defer svr.Close()
sent, err := daemon.SdNotify(false, "READY=1")
if !sent && err != nil {
log.Error("Fail to notify", err)
log.Error().Err(err).Msg("Failed to notify")
}
t, err := daemon.SdWatchdogEnabled(false)
if err != nil {
log.Error("Problem with watchdog", err)
log.Error().Err(err).Msg("Could not enable Watchdog")
} else if t != 0 {
// Send a ping each half time given
t = t / 2
log.Info("Watchdog activated with timer each ", t)
t /= 2
log.Info().Msgf("Watchdog activated with timer duration %s", t)
safe.Go(func() {
tick := time.Tick(t)
for range tick {
_, errHealthCheck := healthcheck.Do(*globalConfiguration)
if globalConfiguration.Ping == nil || errHealthCheck == nil {
resp, errHealthCheck := healthcheck.Do(*staticConfiguration)
if resp != nil {
_ = resp.Body.Close()
}
if staticConfiguration.Ping == nil || errHealthCheck == nil {
if ok, _ := daemon.SdNotify(false, "WATCHDOG=1"); !ok {
log.Error("Fail to tick watchdog")
log.Error().Msg("Fail to tick watchdog")
}
} else {
log.Error(errHealthCheck)
log.Error().Err(errHealthCheck).Send()
}
}
})
}
svr.Wait()
log.Info("Shutting down")
logrus.Exit(0)
log.Info().Msg("Shutting down")
return nil
}
func configureLogging(globalConfiguration *configuration.GlobalConfiguration) {
// configure default log flags
fmtlog.SetFlags(fmtlog.Lshortfile | fmtlog.LstdFlags)
func setupServer(staticConfiguration *static.Configuration) (*server.Server, error) {
providerAggregator := aggregator.NewProviderAggregator(*staticConfiguration.Providers)
// 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 := strings.ToLower(globalConfiguration.LogLevel)
if levelStr == "" {
levelStr = "error"
if globalConfiguration.Debug {
levelStr = "debug"
}
}
level, err := logrus.ParseLevel(levelStr)
ctx := context.Background()
routinesPool := safe.NewPool(ctx)
// adds internal provider
err := providerAggregator.AddProvider(traefik.New(*staticConfiguration))
if err != nil {
log.Error("Error getting level", err)
}
log.SetLevel(level)
// configure log output file
logFile := globalConfiguration.TraefikLogsFile
if len(logFile) > 0 {
log.Warn("top-level traefikLogsFile has been deprecated -- please use traefiklog.filepath")
}
if globalConfiguration.TraefikLog != nil && len(globalConfiguration.TraefikLog.FilePath) > 0 {
logFile = globalConfiguration.TraefikLog.FilePath
return nil, err
}
// configure log format
var formatter logrus.Formatter
if globalConfiguration.TraefikLog != nil && globalConfiguration.TraefikLog.Format == "json" {
formatter = &logrus.JSONFormatter{}
} else {
disableColors := len(logFile) > 0
formatter = &logrus.TextFormatter{DisableColors: disableColors, FullTimestamp: true, DisableSorting: true}
}
log.SetFormatter(formatter)
// ACME
if len(logFile) > 0 {
dir := filepath.Dir(logFile)
tlsManager := traefiktls.NewManager(staticConfiguration.OCSP)
routinesPool.GoCtx(tlsManager.Run)
if err := os.MkdirAll(dir, 0755); err != nil {
log.Errorf("Failed to create log path %s: %s", dir, err)
httpChallengeProvider := acme.NewChallengeHTTP()
tlsChallengeProvider := acme.NewChallengeTLSALPN()
err = providerAggregator.AddProvider(tlsChallengeProvider)
if err != nil {
return nil, err
}
err = log.OpenFile(logFile)
logrus.RegisterExitHandler(func() {
if err := log.CloseFile(); err != nil {
log.Error("Error closing log", err)
acmeProviders := initACMEProvider(staticConfiguration, providerAggregator, tlsManager, httpChallengeProvider, tlsChallengeProvider, routinesPool)
// 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(ctx, staticConfiguration.AccessLog)
tracer, tracerCloser := setupTracing(ctx, staticConfiguration.Tracing)
observabilityMgr := middleware.NewObservabilityMgr(*staticConfiguration, metricsRegistry, semConvMetricRegistry, accessLog, tracer, tracerCloser)
// Entrypoints
serverEntryPointsTCP, err := server.NewTCPEntryPoints(staticConfiguration.EntryPoints, staticConfiguration.HostResolver, metricsRegistry)
if err != nil {
return nil, err
}
serverEntryPointsUDP, err := server.NewUDPEntryPoints(staticConfiguration.EntryPoints)
if err != nil {
return nil, err
}
if staticConfiguration.API != nil {
version.DisableDashboardAd = staticConfiguration.API.DisableDashboardAd
}
// Plugins
pluginLogger := log.Ctx(ctx).With().Logger()
hasPlugins := staticConfiguration.Experimental != nil && (staticConfiguration.Experimental.Plugins != nil || staticConfiguration.Experimental.LocalPlugins != nil)
if hasPlugins {
pluginsList := slices.Collect(maps.Keys(staticConfiguration.Experimental.Plugins))
pluginsList = append(pluginsList, slices.Collect(maps.Keys(staticConfiguration.Experimental.LocalPlugins))...)
pluginLogger = pluginLogger.With().Strs("plugins", pluginsList).Logger()
pluginLogger.Info().Msg("Loading plugins...")
}
pluginBuilder, err := createPluginBuilder(staticConfiguration)
if err != nil && staticConfiguration.Experimental != nil && staticConfiguration.Experimental.AbortOnPluginFailure {
return nil, fmt.Errorf("plugin: failed to create plugin builder: %w", err)
}
if err != nil {
pluginLogger.Err(err).Msg("Plugins are disabled because an error has occurred.")
} else if hasPlugins {
pluginLogger.Info().Msg("Plugins loaded.")
}
// 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)
}
err = providerAggregator.AddProvider(p)
if err != nil {
return nil, fmt.Errorf("plugin: failed to add provider: %w", err)
}
}
// Service manager factory
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.")
}
transportManager := service.NewTransportManager(spiffeX509Source)
var proxyBuilder service.ProxyBuilder = httputil.NewProxyBuilder(transportManager, semConvMetricRegistry)
if staticConfiguration.Experimental != nil && staticConfiguration.Experimental.FastProxy != nil {
proxyBuilder = proxy.NewSmartBuilder(transportManager, proxyBuilder, *staticConfiguration.Experimental.FastProxy)
}
dialerManager := tcp.NewDialerManager(spiffeX509Source)
acmeHTTPHandler := getHTTPChallengeHandler(acmeProviders, httpChallengeProvider)
managerFactory := service.NewManagerFactory(*staticConfiguration, routinesPool, observabilityMgr, transportManager, proxyBuilder, acmeHTTPHandler)
// Router factory
routerFactory, err := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, observabilityMgr, pluginBuilder, dialerManager)
if err != nil {
return nil, fmt.Errorf("creating router factory: %w", err)
}
// Watcher
watcher := server.NewConfigurationWatcher(
routinesPool,
providerAggregator,
getDefaultsEntrypoints(staticConfiguration),
"internal",
)
// TLS
watcher.AddListener(func(conf dynamic.Configuration) {
ctx := context.Background()
tlsManager.UpdateConfigs(ctx, conf.TLS.Stores, conf.TLS.Options, conf.TLS.Certificates)
gauge := metricsRegistry.TLSCertsNotAfterTimestampGauge()
for _, certificate := range tlsManager.GetServerCertificates() {
appendCertMetric(gauge, certificate)
}
})
// Metrics
watcher.AddListener(func(_ dynamic.Configuration) {
metricsRegistry.ConfigReloadsCounter().Add(1)
metricsRegistry.LastConfigReloadSuccessGauge().Set(float64(time.Now().Unix()))
})
// Server Transports
watcher.AddListener(func(conf dynamic.Configuration) {
transportManager.Update(conf.HTTP.ServersTransports)
proxyBuilder.Update(conf.HTTP.ServersTransports)
dialerManager.Update(conf.TCP.ServersTransports)
})
// Switch router
watcher.AddListener(switchRouter(routerFactory, serverEntryPointsTCP, serverEntryPointsUDP))
// Metrics
if metricsRegistry.IsEpEnabled() || metricsRegistry.IsRouterEnabled() || metricsRegistry.IsSvcEnabled() {
var eps []string
for key := range serverEntryPointsTCP {
eps = append(eps, key)
}
watcher.AddListener(func(conf dynamic.Configuration) {
metrics.OnConfigurationUpdate(conf, eps)
})
}
// TLS challenge
watcher.AddListener(tlsChallengeProvider.ListenConfiguration)
// 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 {
if rt.TLS == nil || rt.TLS.CertResolver == "" {
continue
}
if _, ok := resolverNames[rt.TLS.CertResolver]; !ok {
log.Error().Err(err).Str(logs.RouterName, rtName).Str("certificateResolver", rt.TLS.CertResolver).
Msg("Router uses a nonexistent certificate resolver")
}
}
})
return server.NewServer(routinesPool, serverEntryPointsTCP, serverEntryPointsUDP, watcher, observabilityMgr), nil
}
func getHTTPChallengeHandler(acmeProviders []*acme.Provider, httpChallengeProvider http.Handler) http.Handler {
var acmeHTTPHandler http.Handler
for _, p := range acmeProviders {
if p != nil && p.HTTPChallenge != nil {
acmeHTTPHandler = httpChallengeProvider
break
}
}
return acmeHTTPHandler
}
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 {
log.Error("Error opening file", err)
// Should never happen because Traefik should not start if protocol is invalid.
log.Error().Err(err).Msg("Invalid protocol")
}
if protocol != "udp" && name != static.DefaultInternalEntryPointName {
defaultEntryPoints = append(defaultEntryPoints, name)
}
}
slices.Sort(defaultEntryPoints)
return defaultEntryPoints
}
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)
serverEntryPointsTCP.Switch(routers)
serverEntryPointsUDP.Switch(udpRouters)
}
}
// 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, routinesPool *safe.Pool) []*acme.Provider {
localStores := map[string]*acme.LocalStore{}
var resolvers []*acme.Provider
for name, resolver := range c.CertificatesResolvers {
if resolver.ACME == nil {
continue
}
if localStores[resolver.ACME.Storage] == nil {
localStores[resolver.ACME.Storage] = acme.NewLocalStore(resolver.ACME.Storage, routinesPool)
}
p := &acme.Provider{
Configuration: resolver.ACME,
Store: localStores[resolver.ACME.Storage],
ResolverName: name,
HTTPChallengeProvider: httpChallengeProvider,
TLSChallengeProvider: tlsChallengeProvider,
}
if err := providerAggregator.AddProvider(p); err != nil {
log.Error().Err(err).Str("resolver", name).Msg("The ACME resolve is skipped from the resolvers list")
continue
}
p.SetTLSManager(tlsManager)
p.SetConfigListenerChan(make(chan dynamic.Configuration))
resolvers = append(resolvers, p)
}
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
}
var registries []metrics.Registry
if metricsConfig.Prometheus != nil {
logger := log.With().Str(logs.MetricsProviderName, "prometheus").Logger()
prometheusRegister := metrics.RegisterPrometheus(logger.WithContext(context.Background()), metricsConfig.Prometheus)
if prometheusRegister != nil {
registries = append(registries, prometheusRegister)
logger.Debug().Msg("Configured Prometheus metrics")
}
}
if metricsConfig.Datadog != nil {
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 {
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.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
}
func appendCertMetric(gauge gokitmetrics.Gauge, certificate *x509.Certificate) {
slices.Sort(certificate.DNSNames)
labels := []string{
"cn", certificate.Subject.CommonName,
"serial", certificate.SerialNumber.String(),
"sans", strings.Join(certificate.DNSNames, ","),
}
notAfter := float64(certificate.NotAfter.Unix())
gauge.With(labels...).Set(notAfter)
}
func setupAccessLog(ctx context.Context, conf *types.AccessLog) *accesslog.Handler {
if conf == nil {
return nil
}
accessLoggerMiddleware, err := accesslog.NewHandler(ctx, conf)
if err != nil {
log.Warn().Err(err).Msg("Unable to create access logger")
return nil
}
return accessLoggerMiddleware
}
func setupTracing(ctx context.Context, conf *static.Tracing) (*tracing.Tracer, io.Closer) {
if conf == nil {
return nil, nil
}
tracer, closer, err := tracing.NewTracing(ctx, conf)
if err != nil {
log.Warn().Err(err).Msg("Unable to create tracer")
return nil, nil
}
return tracer, closer
}
func checkNewVersion() {
@ -346,30 +623,30 @@ func checkNewVersion() {
})
}
func stats(globalConfiguration *configuration.GlobalConfiguration) {
if globalConfiguration.SendAnonymousUsage {
log.Info(`
Stats collection is enabled.
Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.
Help us improve Traefik by leaving this feature on :)
More details on: https://docs.traefik.io/basics/#collected-data
`)
collect(globalConfiguration)
func stats(staticConfiguration *static.Configuration) {
logger := log.With().Logger()
if staticConfiguration.Global.SendAnonymousUsage {
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 {
log.Info(`
logger.Info().Msg(`
Stats collection is disabled.
Help us improve Traefik by turning this feature on :)
More details on: https://docs.traefik.io/basics/#collected-data
More details on: https://doc.traefik.io/traefik/contributing/data-collection/
`)
}
}
func collect(globalConfiguration *configuration.GlobalConfiguration) {
func collect(staticConfiguration *static.Configuration) {
ticker := time.Tick(24 * time.Hour)
safe.Go(func() {
for time.Sleep(10 * time.Minute); ; <-ticker {
if err := collector.Collect(globalConfiguration); err != nil {
log.Debug(err)
if err := collector.Collect(staticConfiguration); err != nil {
log.Debug().Err(err).Send()
}
}
})

186
cmd/traefik/traefik_test.go Normal file
View File

@ -0,0 +1,186 @@
package main
import (
"crypto/x509"
"encoding/pem"
"strings"
"testing"
"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.
// generated from src/crypto/tls:
// go run generate_cert.go --rsa-bits 1024 --host foo.org,foo.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
const fooCert = `-----BEGIN CERTIFICATE-----
MIICHzCCAYigAwIBAgIQXQFLeYRwc5X21t457t2xADANBgkqhkiG9w0BAQsFADAS
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
iQKBgQDCjn67GSs/khuGC4GNN+tVo1S+/eSHwr/hWzhfMqO7nYiXkFzmxi+u14CU
Pda6WOeps7T2/oQEFMxKKg7zYOqkLSbjbE0ZfosopaTvEsZm/AZHAAvoOrAsIJOn
SEiwy8h0tLA4z1SNR6rmIVQWyqBZEPAhBTQM1z7tFp48FakCFwIDAQABo3QwcjAO
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
AwEB/zAdBgNVHQ4EFgQUDHG3ASzeUezElup9zbPpBn/vjogwGwYDVR0RBBQwEoIH
Zm9vLm9yZ4IHZm9vLmNvbTANBgkqhkiG9w0BAQsFAAOBgQBT+VLMbB9u27tBX8Aw
ZrGY3rbNdBGhXVTksrjiF+6ZtDpD3iI56GH9zLxnqvXkgn3u0+Ard5TqF/xmdwVw
NY0V/aWYfcL2G2auBCQrPvM03ozRnVUwVfP23eUzX2ORNHCYhd2ObQx4krrhs7cJ
SWxtKwFlstoXY3K2g9oRD9UxdQ==
-----END CERTIFICATE-----`
// BarCert is a PEM-encoded TLS cert.
// generated from src/crypto/tls:
// go run generate_cert.go --rsa-bits 1024 --host bar.org,bar.com --ca --start-date "Jan 1 00:00:00 1970" --duration=10000h
const barCert = `-----BEGIN CERTIFICATE-----
MIICHTCCAYagAwIBAgIQcuIcNEXzBHPoxna5S6wG4jANBgkqhkiG9w0BAQsFADAS
MRAwDgYDVQQKEwdBY21lIENvMB4XDTcwMDEwMTAwMDAwMFoXDTcxMDIyMTE2MDAw
MFowEjEQMA4GA1UEChMHQWNtZSBDbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
gYEAqtcrP+KA7D6NjyztGNIPMup9KiBMJ8QL+preog/YHR7SQLO3kGFhpS3WKMab
SzMypC3ZX1PZjBP5ZzwaV3PFbuwlCkPlyxR2lOWmullgI7mjY0TBeYLDIclIzGRp
mpSDDSpkW1ay2iJDSpXjlhmwZr84hrCU7BRTQJo91fdsRTsCAwEAAaN0MHIwDgYD
VR0PAQH/BAQDAgKkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMB
Af8wHQYDVR0OBBYEFK8jnzFQvBAgWtfzOyXY4VSkwrTXMBsGA1UdEQQUMBKCB2Jh
ci5vcmeCB2Jhci5jb20wDQYJKoZIhvcNAQELBQADgYEAJz0ifAExisC/ZSRhWuHz
7qs1i6Nd4+YgEVR8dR71MChP+AMxucY1/ajVjb9xlLys3GPE90TWSdVppabEVjZY
Oq11nPKc50ItTt8dMku6t0JHBmzoGdkN0V4zJCBqdQJxhop8JpYJ0S9CW0eT93h3
ipYQSsmIINGtMXJ8VkP/MlM=
-----END CERTIFICATE-----`
type gaugeMock struct {
metrics map[string]float64
labels string
}
func (g gaugeMock) With(labelValues ...string) metrics.Gauge {
g.labels = strings.Join(labelValues, ",")
return g
}
func (g gaugeMock) Set(value float64) {
g.metrics[g.labels] = value
}
func (g gaugeMock) Add(delta float64) {
panic("implement me")
}
func TestAppendCertMetric(t *testing.T) {
testCases := []struct {
desc string
certs []string
expected map[string]float64
}{
{
desc: "No certs",
certs: []string{},
expected: map[string]float64{},
},
{
desc: "One cert",
certs: []string{fooCert},
expected: map[string]float64{
"cn,,serial,123624926713171615935660664614975025408,sans,foo.com,foo.org": 3.6e+09,
},
},
{
desc: "Two certs",
certs: []string{fooCert, barCert},
expected: map[string]float64{
"cn,,serial,123624926713171615935660664614975025408,sans,foo.com,foo.org": 3.6e+09,
"cn,,serial,152706022658490889223053211416725817058,sans,bar.com,bar.org": 3.6e+07,
},
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
gauge := &gaugeMock{
metrics: map[string]float64{},
}
for _, cert := range test.certs {
block, _ := pem.Decode([]byte(cert))
parsedCert, err := x509.ParseCertificate(block.Bytes)
require.NoError(t, err)
appendCertMetric(gauge, parsedCert)
}
assert.Equal(t, test.expected, gauge.metrics)
})
}
}
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)
})
}
}

View File

@ -7,8 +7,8 @@ import (
"runtime"
"text/template"
"github.com/containous/flaeg"
"github.com/containous/traefik/version"
"github.com/traefik/paerser/cli"
"github.com/traefik/traefik/v3/pkg/version"
)
var versionTemplate = `Version: {{.Version}}
@ -17,25 +17,23 @@ Go version: {{.GoVersion}}
Built: {{.BuildTime}}
OS/Arch: {{.Os}}/{{.Arch}}`
// NewCmd builds a new Version command
func NewCmd() *flaeg.Command {
return &flaeg.Command{
// NewCmd builds a new Version command.
func NewCmd() *cli.Command {
return &cli.Command{
Name: "version",
Description: `Print version`,
Config: struct{}{},
DefaultPointersConfig: struct{}{},
Run: func() error {
Description: `Shows the current Traefik version.`,
Configuration: nil,
Run: func(_ []string) error {
if err := GetPrint(os.Stdout); err != nil {
return err
}
fmt.Print("\n")
return nil
},
}
}
// GetPrint write Printable version
// GetPrint write Printable version.
func GetPrint(wr io.Writer) error {
tmpl, err := template.New("").Parse(versionTemplate)
if err != nil {

View File

@ -1,79 +0,0 @@
package collector
import (
"bytes"
"encoding/base64"
"encoding/json"
"net"
"net/http"
"strconv"
"time"
"github.com/containous/traefik/anonymize"
"github.com/containous/traefik/configuration"
"github.com/containous/traefik/log"
"github.com/containous/traefik/version"
"github.com/mitchellh/hashstructure"
)
// collectorURL URL where the stats are send
const collectorURL = "https://collect.traefik.io/619df80498b60f985d766ce62f912b7c"
// Collected data
type data struct {
Version string
Codename string
BuildDate string
Configuration string
Hash string
}
// Collect anonymous data.
func Collect(globalConfiguration *configuration.GlobalConfiguration) error {
anonConfig, err := anonymize.Do(globalConfiguration, false)
if err != nil {
return err
}
log.Infof("Anonymous stats sent to %s: %s", collectorURL, anonConfig)
hashConf, err := hashstructure.Hash(globalConfiguration, nil)
if err != nil {
return err
}
data := &data{
Version: version.Version,
Codename: version.Codename,
BuildDate: version.BuildDate,
Hash: strconv.FormatUint(hashConf, 10),
Configuration: base64.StdEncoding.EncodeToString([]byte(anonConfig)),
}
buf := new(bytes.Buffer)
err = json.NewEncoder(buf).Encode(data)
if err != nil {
return err
}
_, err = makeHTTPClient().Post(collectorURL, "application/json; charset=utf-8", buf)
return err
}
func makeHTTPClient() *http.Client {
dialer := &net.Dialer{
Timeout: configuration.DefaultDialTimeout,
KeepAlive: 30 * time.Second,
DualStack: true,
}
transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: dialer.DialContext,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
return &http.Client{Transport: transport}
}

View File

@ -1,578 +0,0 @@
package configuration
import (
"fmt"
"strings"
"time"
"github.com/containous/flaeg"
"github.com/containous/traefik-extra-service-fabric"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/api"
"github.com/containous/traefik/log"
"github.com/containous/traefik/middlewares/tracing"
"github.com/containous/traefik/middlewares/tracing/datadog"
"github.com/containous/traefik/middlewares/tracing/jaeger"
"github.com/containous/traefik/middlewares/tracing/zipkin"
"github.com/containous/traefik/ping"
acmeprovider "github.com/containous/traefik/provider/acme"
"github.com/containous/traefik/provider/boltdb"
"github.com/containous/traefik/provider/consul"
"github.com/containous/traefik/provider/consulcatalog"
"github.com/containous/traefik/provider/docker"
"github.com/containous/traefik/provider/dynamodb"
"github.com/containous/traefik/provider/ecs"
"github.com/containous/traefik/provider/etcd"
"github.com/containous/traefik/provider/eureka"
"github.com/containous/traefik/provider/file"
"github.com/containous/traefik/provider/kubernetes"
"github.com/containous/traefik/provider/marathon"
"github.com/containous/traefik/provider/mesos"
"github.com/containous/traefik/provider/rancher"
"github.com/containous/traefik/provider/rest"
"github.com/containous/traefik/provider/zk"
"github.com/containous/traefik/tls"
"github.com/containous/traefik/types"
"github.com/pkg/errors"
lego "github.com/xenolf/lego/acme"
)
const (
// DefaultInternalEntryPointName the name of the default internal entry point
DefaultInternalEntryPointName = "traefik"
// DefaultHealthCheckInterval is the default health check interval.
DefaultHealthCheckInterval = 30 * time.Second
// DefaultDialTimeout when connecting to a backend server.
DefaultDialTimeout = 30 * time.Second
// DefaultIdleTimeout before closing an idle connection.
DefaultIdleTimeout = 180 * time.Second
// DefaultGraceTimeout controls how long Traefik serves pending requests
// prior to shutting down.
DefaultGraceTimeout = 10 * time.Second
// DefaultAcmeCAServer is the default ACME API endpoint
DefaultAcmeCAServer = "https://acme-v02.api.letsencrypt.org/directory"
)
// GlobalConfiguration holds global configuration (with providers, etc.).
// It's populated from the traefik configuration file passed as an argument to the binary.
type GlobalConfiguration struct {
LifeCycle *LifeCycle `description:"Timeouts influencing the server life cycle" export:"true"`
GraceTimeOut flaeg.Duration `short:"g" description:"(Deprecated) Duration to give active requests a chance to finish before Traefik stops" export:"true"` // Deprecated
Debug bool `short:"d" description:"Enable debug mode" export:"true"`
CheckNewVersion bool `description:"Periodically check if a new version has been released" export:"true"`
SendAnonymousUsage bool `description:"send periodically anonymous usage statistics" export:"true"`
AccessLogsFile string `description:"(Deprecated) Access logs file" export:"true"` // Deprecated
AccessLog *types.AccessLog `description:"Access log settings" export:"true"`
TraefikLogsFile string `description:"(Deprecated) Traefik logs file. Stdout is used when omitted or empty" export:"true"` // Deprecated
TraefikLog *types.TraefikLog `description:"Traefik log settings" export:"true"`
Tracing *tracing.Tracing `description:"OpenTracing configuration" export:"true"`
LogLevel string `short:"l" description:"Log level" export:"true"`
EntryPoints EntryPoints `description:"Entrypoints definition using format: --entryPoints='Name:http Address::8000 Redirect.EntryPoint:https' --entryPoints='Name:https Address::4442 TLS:tests/traefik.crt,tests/traefik.key;prod/traefik.crt,prod/traefik.key'" export:"true"`
Cluster *types.Cluster
Constraints types.Constraints `description:"Filter services by constraint, matching with service tags" export:"true"`
ACME *acme.ACME `description:"Enable ACME (Let's Encrypt): automatic SSL" export:"true"`
DefaultEntryPoints DefaultEntryPoints `description:"Entrypoints to be used by frontends that do not specify any entrypoint" export:"true"`
ProvidersThrottleDuration flaeg.Duration `description:"Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time." export:"true"`
MaxIdleConnsPerHost int `description:"If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used" export:"true"`
IdleTimeout flaeg.Duration `description:"(Deprecated) maximum amount of time an idle (keep-alive) connection will remain idle before closing itself." export:"true"` // Deprecated
InsecureSkipVerify bool `description:"Disable SSL certificate verification" export:"true"`
RootCAs tls.FilesOrContents `description:"Add cert file for self-signed certificate"`
Retry *Retry `description:"Enable retry sending request if network error" export:"true"`
HealthCheck *HealthCheckConfig `description:"Health check parameters" export:"true"`
RespondingTimeouts *RespondingTimeouts `description:"Timeouts for incoming requests to the Traefik instance" export:"true"`
ForwardingTimeouts *ForwardingTimeouts `description:"Timeouts for requests forwarded to the backend servers" export:"true"`
AllowMinWeightZero bool `description:"Allow weight to take 0 as minimum real value." export:"true"` // Deprecated
KeepTrailingSlash bool `description:"Do not remove trailing slash." export:"true"` // Deprecated
Web *WebCompatibility `description:"(Deprecated) Enable Web backend with default settings" export:"true"` // Deprecated
Docker *docker.Provider `description:"Enable Docker backend with default settings" export:"true"`
File *file.Provider `description:"Enable File backend with default settings" export:"true"`
Marathon *marathon.Provider `description:"Enable Marathon backend with default settings" export:"true"`
Consul *consul.Provider `description:"Enable Consul backend with default settings" export:"true"`
ConsulCatalog *consulcatalog.Provider `description:"Enable Consul catalog backend with default settings" export:"true"`
Etcd *etcd.Provider `description:"Enable Etcd backend with default settings" export:"true"`
Zookeeper *zk.Provider `description:"Enable Zookeeper backend with default settings" export:"true"`
Boltdb *boltdb.Provider `description:"Enable Boltdb backend with default settings" export:"true"`
Kubernetes *kubernetes.Provider `description:"Enable Kubernetes backend with default settings" export:"true"`
Mesos *mesos.Provider `description:"Enable Mesos backend with default settings" export:"true"`
Eureka *eureka.Provider `description:"Enable Eureka backend with default settings" export:"true"`
ECS *ecs.Provider `description:"Enable ECS backend with default settings" export:"true"`
Rancher *rancher.Provider `description:"Enable Rancher backend with default settings" export:"true"`
DynamoDB *dynamodb.Provider `description:"Enable DynamoDB backend with default settings" export:"true"`
ServiceFabric *servicefabric.Provider `description:"Enable Service Fabric backend with default settings" export:"true"`
Rest *rest.Provider `description:"Enable Rest backend with default settings" export:"true"`
API *api.Handler `description:"Enable api/dashboard" export:"true"`
Metrics *types.Metrics `description:"Enable a metrics exporter" export:"true"`
Ping *ping.Handler `description:"Enable ping" export:"true"`
HostResolver *HostResolverConfig `description:"Enable CNAME Flattening" export:"true"`
}
// WebCompatibility is a configuration to handle compatibility with deprecated web provider options
type WebCompatibility struct {
Address string `description:"(Deprecated) Web administration port" export:"true"`
CertFile string `description:"(Deprecated) SSL certificate" export:"true"`
KeyFile string `description:"(Deprecated) SSL certificate" export:"true"`
ReadOnly bool `description:"(Deprecated) Enable read only API" export:"true"`
Statistics *types.Statistics `description:"(Deprecated) Enable more detailed statistics" export:"true"`
Metrics *types.Metrics `description:"(Deprecated) Enable a metrics exporter" export:"true"`
Path string `description:"(Deprecated) Root path for dashboard and API" export:"true"`
Auth *types.Auth `export:"true"`
Debug bool `export:"true"`
}
func (gc *GlobalConfiguration) handleWebDeprecation() {
if gc.Web != nil {
log.Warn("web provider configuration is deprecated, you should use these options : api, rest provider, ping and metrics")
if gc.API != nil || gc.Metrics != nil || gc.Ping != nil || gc.Rest != nil {
log.Warn("web option is ignored if you use it with one of these options : api, rest provider, ping or metrics")
return
}
gc.EntryPoints[DefaultInternalEntryPointName] = &EntryPoint{
Address: gc.Web.Address,
Auth: gc.Web.Auth,
}
if gc.Web.CertFile != "" {
gc.EntryPoints[DefaultInternalEntryPointName].TLS = &tls.TLS{
Certificates: []tls.Certificate{
{
CertFile: tls.FileOrContent(gc.Web.CertFile),
KeyFile: tls.FileOrContent(gc.Web.KeyFile),
},
},
}
}
if gc.API == nil {
gc.API = &api.Handler{
EntryPoint: DefaultInternalEntryPointName,
Statistics: gc.Web.Statistics,
Dashboard: true,
}
}
if gc.Ping == nil {
gc.Ping = &ping.Handler{
EntryPoint: DefaultInternalEntryPointName,
}
}
if gc.Metrics == nil {
gc.Metrics = gc.Web.Metrics
}
if !gc.Debug {
gc.Debug = gc.Web.Debug
}
}
}
// SetEffectiveConfiguration adds missing configuration parameters derived from existing ones.
// It also takes care of maintaining backwards compatibility.
func (gc *GlobalConfiguration) SetEffectiveConfiguration(configFile string) {
if len(gc.EntryPoints) == 0 {
gc.EntryPoints = map[string]*EntryPoint{"http": {
Address: ":80",
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
}}
gc.DefaultEntryPoints = []string{"http"}
}
gc.handleWebDeprecation()
if (gc.API != nil && gc.API.EntryPoint == DefaultInternalEntryPointName) ||
(gc.Ping != nil && gc.Ping.EntryPoint == DefaultInternalEntryPointName) ||
(gc.Metrics != nil && gc.Metrics.Prometheus != nil && gc.Metrics.Prometheus.EntryPoint == DefaultInternalEntryPointName) ||
(gc.Rest != nil && gc.Rest.EntryPoint == DefaultInternalEntryPointName) {
if _, ok := gc.EntryPoints[DefaultInternalEntryPointName]; !ok {
gc.EntryPoints[DefaultInternalEntryPointName] = &EntryPoint{Address: ":8080"}
}
}
for entryPointName := range gc.EntryPoints {
entryPoint := gc.EntryPoints[entryPointName]
// ForwardedHeaders must be remove in the next breaking version
if entryPoint.ForwardedHeaders == nil {
entryPoint.ForwardedHeaders = &ForwardedHeaders{Insecure: true}
}
if len(entryPoint.WhitelistSourceRange) > 0 {
log.Warnf("Deprecated configuration found: %s. Please use %s.", "whiteListSourceRange", "whiteList.sourceRange")
if entryPoint.WhiteList == nil {
entryPoint.WhiteList = &types.WhiteList{
SourceRange: entryPoint.WhitelistSourceRange,
}
entryPoint.WhitelistSourceRange = nil
}
}
if entryPoint.TLS != nil && entryPoint.TLS.DefaultCertificate == nil && len(entryPoint.TLS.Certificates) > 0 {
log.Infof("No tls.defaultCertificate given for %s: using the first item in tls.certificates as a fallback.", entryPointName)
entryPoint.TLS.DefaultCertificate = &entryPoint.TLS.Certificates[0]
}
}
// Make sure LifeCycle isn't nil to spare nil checks elsewhere.
if gc.LifeCycle == nil {
gc.LifeCycle = &LifeCycle{}
}
// Prefer legacy grace timeout parameter for backwards compatibility reasons.
if gc.GraceTimeOut > 0 {
log.Warn("top-level grace period configuration has been deprecated -- please use lifecycle grace period")
gc.LifeCycle.GraceTimeOut = gc.GraceTimeOut
}
if gc.Docker != nil {
if len(gc.Docker.Filename) != 0 && gc.Docker.TemplateVersion != 2 {
log.Warn("Template version 1 is deprecated, please use version 2, see TemplateVersion.")
gc.Docker.TemplateVersion = 1
} else {
gc.Docker.TemplateVersion = 2
}
}
if gc.Marathon != nil {
if len(gc.Marathon.Filename) != 0 && gc.Marathon.TemplateVersion != 2 {
log.Warn("Template version 1 is deprecated, please use version 2, see TemplateVersion.")
gc.Marathon.TemplateVersion = 1
} else {
gc.Marathon.TemplateVersion = 2
}
}
if gc.Mesos != nil {
if len(gc.Mesos.Filename) != 0 && gc.Mesos.TemplateVersion != 2 {
log.Warn("Template version 1 is deprecated, please use version 2, see TemplateVersion.")
gc.Mesos.TemplateVersion = 1
} else {
gc.Mesos.TemplateVersion = 2
}
}
if gc.Eureka != nil {
if gc.Eureka.Delay != 0 {
log.Warn("Delay has been deprecated -- please use RefreshSeconds")
gc.Eureka.RefreshSeconds = gc.Eureka.Delay
}
}
if gc.ECS != nil {
if len(gc.ECS.Filename) != 0 && gc.ECS.TemplateVersion != 2 {
log.Warn("Template version 1 is deprecated, please use version 2, see TemplateVersion.")
gc.ECS.TemplateVersion = 1
} else {
gc.ECS.TemplateVersion = 2
}
}
if gc.ConsulCatalog != nil {
if len(gc.ConsulCatalog.Filename) != 0 && gc.ConsulCatalog.TemplateVersion != 2 {
log.Warn("Template version 1 is deprecated, please use version 2, see TemplateVersion.")
gc.ConsulCatalog.TemplateVersion = 1
} else {
gc.ConsulCatalog.TemplateVersion = 2
}
}
if gc.Rancher != nil {
if len(gc.Rancher.Filename) != 0 && gc.Rancher.TemplateVersion != 2 {
log.Warn("Template version 1 is deprecated, please use version 2, see TemplateVersion.")
gc.Rancher.TemplateVersion = 1
} else {
gc.Rancher.TemplateVersion = 2
}
// Ensure backwards compatibility for now
if len(gc.Rancher.AccessKey) > 0 ||
len(gc.Rancher.Endpoint) > 0 ||
len(gc.Rancher.SecretKey) > 0 {
if gc.Rancher.API == nil {
gc.Rancher.API = &rancher.APIConfiguration{
AccessKey: gc.Rancher.AccessKey,
SecretKey: gc.Rancher.SecretKey,
Endpoint: gc.Rancher.Endpoint,
}
}
log.Warn("Deprecated configuration found: rancher.[accesskey|secretkey|endpoint]. " +
"Please use rancher.api.[accesskey|secretkey|endpoint] instead.")
}
if gc.Rancher.Metadata != nil && len(gc.Rancher.Metadata.Prefix) == 0 {
gc.Rancher.Metadata.Prefix = "latest"
}
}
if gc.API != nil {
gc.API.Debug = gc.Debug
}
if gc.Web != nil && (gc.Web.Path == "" || !strings.HasSuffix(gc.Web.Path, "/")) {
gc.Web.Path += "/"
}
if gc.File != nil {
gc.File.TraefikFile = configFile
}
gc.initACMEProvider()
gc.initTracing()
}
func (gc *GlobalConfiguration) initTracing() {
if gc.Tracing != nil {
switch gc.Tracing.Backend {
case jaeger.Name:
if gc.Tracing.Jaeger == nil {
gc.Tracing.Jaeger = &jaeger.Config{
SamplingServerURL: "http://localhost:5778/sampling",
SamplingType: "const",
SamplingParam: 1.0,
LocalAgentHostPort: "127.0.0.1:6831",
}
}
if gc.Tracing.Zipkin != nil {
log.Warn("Zipkin configuration will be ignored")
gc.Tracing.Zipkin = nil
}
if gc.Tracing.DataDog != nil {
log.Warn("DataDog configuration will be ignored")
gc.Tracing.DataDog = nil
}
case zipkin.Name:
if gc.Tracing.Zipkin == nil {
gc.Tracing.Zipkin = &zipkin.Config{
HTTPEndpoint: "http://localhost:9411/api/v1/spans",
SameSpan: false,
ID128Bit: true,
Debug: false,
}
}
if gc.Tracing.Jaeger != nil {
log.Warn("Jaeger configuration will be ignored")
gc.Tracing.Jaeger = nil
}
if gc.Tracing.DataDog != nil {
log.Warn("DataDog configuration will be ignored")
gc.Tracing.DataDog = nil
}
case datadog.Name:
if gc.Tracing.DataDog == nil {
gc.Tracing.DataDog = &datadog.Config{
LocalAgentHostPort: "localhost:8126",
GlobalTag: "",
Debug: false,
}
}
if gc.Tracing.Zipkin != nil {
log.Warn("Zipkin configuration will be ignored")
gc.Tracing.Zipkin = nil
}
if gc.Tracing.Jaeger != nil {
log.Warn("Jaeger configuration will be ignored")
gc.Tracing.Jaeger = nil
}
default:
log.Warnf("Unknown tracer %q", gc.Tracing.Backend)
return
}
}
}
func (gc *GlobalConfiguration) initACMEProvider() {
if gc.ACME != nil {
gc.ACME.CAServer = getSafeACMECAServer(gc.ACME.CAServer)
if gc.ACME.DNSChallenge != nil && gc.ACME.HTTPChallenge != nil {
log.Warn("Unable to use DNS challenge and HTTP challenge at the same time. Fallback to DNS challenge.")
gc.ACME.HTTPChallenge = nil
}
if gc.ACME.DNSChallenge != nil && gc.ACME.TLSChallenge != nil {
log.Warn("Unable to use DNS challenge and TLS challenge at the same time. Fallback to DNS challenge.")
gc.ACME.TLSChallenge = nil
}
if gc.ACME.HTTPChallenge != nil && gc.ACME.TLSChallenge != nil {
log.Warn("Unable to use HTTP challenge and TLS challenge at the same time. Fallback to TLS challenge.")
gc.ACME.HTTPChallenge = nil
}
for _, domain := range gc.ACME.Domains {
if domain.Main != lego.UnFqdn(domain.Main) {
log.Warnf("FQDN detected, please remove the trailing dot: %s", domain.Main)
}
for _, san := range domain.SANs {
if san != lego.UnFqdn(san) {
log.Warnf("FQDN detected, please remove the trailing dot: %s", san)
}
}
}
// TODO: to remove in the future
if len(gc.ACME.StorageFile) > 0 && len(gc.ACME.Storage) == 0 {
log.Warn("ACME.StorageFile is deprecated, use ACME.Storage instead")
gc.ACME.Storage = gc.ACME.StorageFile
}
if len(gc.ACME.DNSProvider) > 0 {
log.Warn("ACME.DNSProvider is deprecated, use ACME.DNSChallenge instead")
gc.ACME.DNSChallenge = &acmeprovider.DNSChallenge{Provider: gc.ACME.DNSProvider, DelayBeforeCheck: gc.ACME.DelayDontCheckDNS}
}
if gc.ACME.OnDemand {
log.Warn("ACME.OnDemand is deprecated")
}
}
}
// InitACMEProvider create an acme provider from the ACME part of globalConfiguration
func (gc *GlobalConfiguration) InitACMEProvider() (*acmeprovider.Provider, error) {
if gc.ACME != nil {
if len(gc.ACME.Storage) == 0 {
// Delete the ACME configuration to avoid starting ACME in cluster mode
gc.ACME = nil
return nil, errors.New("unable to initialize ACME provider with no storage location for the certificates")
}
// TODO: Remove when Provider ACME will replace totally ACME
// If provider file, use Provider ACME instead of ACME
if gc.Cluster == nil {
provider := &acmeprovider.Provider{}
provider.Configuration = &acmeprovider.Configuration{
KeyType: gc.ACME.KeyType,
OnHostRule: gc.ACME.OnHostRule,
OnDemand: gc.ACME.OnDemand,
Email: gc.ACME.Email,
Storage: gc.ACME.Storage,
HTTPChallenge: gc.ACME.HTTPChallenge,
DNSChallenge: gc.ACME.DNSChallenge,
TLSChallenge: gc.ACME.TLSChallenge,
Domains: gc.ACME.Domains,
ACMELogging: gc.ACME.ACMELogging,
CAServer: gc.ACME.CAServer,
EntryPoint: gc.ACME.EntryPoint,
}
store := acmeprovider.NewLocalStore(provider.Storage)
provider.Store = store
acme.ConvertToNewFormat(provider.Storage)
gc.ACME = nil
return provider, nil
}
}
return nil, nil
}
func getSafeACMECAServer(caServerSrc string) string {
if len(caServerSrc) == 0 {
return DefaultAcmeCAServer
}
if strings.HasPrefix(caServerSrc, "https://acme-v01.api.letsencrypt.org") {
caServer := strings.Replace(caServerSrc, "v01", "v02", 1)
log.Warnf("The CA server %[1]q refers to a v01 endpoint of the ACME API, please change to %[2]q. Fallback to %[2]q.", caServerSrc, caServer)
return caServer
}
if strings.HasPrefix(caServerSrc, "https://acme-staging.api.letsencrypt.org") {
caServer := strings.Replace(caServerSrc, "https://acme-staging.api.letsencrypt.org", "https://acme-staging-v02.api.letsencrypt.org", 1)
log.Warnf("The CA server %[1]q refers to a v01 endpoint of the ACME API, please change to %[2]q. Fallback to %[2]q.", caServerSrc, caServer)
return caServer
}
return caServerSrc
}
// ValidateConfiguration validate that configuration is coherent
func (gc *GlobalConfiguration) ValidateConfiguration() {
if gc.ACME != nil {
if _, ok := gc.EntryPoints[gc.ACME.EntryPoint]; !ok {
log.Fatalf("Unknown entrypoint %q for ACME configuration", gc.ACME.EntryPoint)
} else {
if gc.EntryPoints[gc.ACME.EntryPoint].TLS == nil {
log.Fatalf("Entrypoint %q has no TLS configuration for ACME configuration", gc.ACME.EntryPoint)
}
}
}
}
// DefaultEntryPoints holds default entry points
type DefaultEntryPoints []string
// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func (dep *DefaultEntryPoints) String() string {
return strings.Join(*dep, ",")
}
// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (dep *DefaultEntryPoints) Set(value string) error {
entrypoints := strings.Split(value, ",")
if len(entrypoints) == 0 {
return fmt.Errorf("bad DefaultEntryPoints format: %s", value)
}
for _, entrypoint := range entrypoints {
*dep = append(*dep, entrypoint)
}
return nil
}
// Get return the EntryPoints map
func (dep *DefaultEntryPoints) Get() interface{} {
return *dep
}
// SetValue sets the EntryPoints map with val
func (dep *DefaultEntryPoints) SetValue(val interface{}) {
*dep = val.(DefaultEntryPoints)
}
// Type is type of the struct
func (dep *DefaultEntryPoints) Type() string {
return "defaultentrypoints"
}
// Retry contains request retry config
type Retry struct {
Attempts int `description:"Number of attempts" export:"true"`
}
// HealthCheckConfig contains health check configuration parameters.
type HealthCheckConfig struct {
Interval flaeg.Duration `description:"Default periodicity of enabled health checks" export:"true"`
}
// RespondingTimeouts contains timeout configurations for incoming requests to the Traefik instance.
type RespondingTimeouts struct {
ReadTimeout flaeg.Duration `description:"ReadTimeout is the maximum duration for reading the entire request, including the body. If zero, no timeout is set" export:"true"`
WriteTimeout flaeg.Duration `description:"WriteTimeout is the maximum duration before timing out writes of the response. If zero, no timeout is set" export:"true"`
IdleTimeout flaeg.Duration `description:"IdleTimeout is the maximum amount duration an idle (keep-alive) connection will remain idle before closing itself. Defaults to 180 seconds. If zero, no timeout is set" export:"true"`
}
// ForwardingTimeouts contains timeout configurations for forwarding requests to the backend servers.
type ForwardingTimeouts struct {
DialTimeout flaeg.Duration `description:"The amount of time to wait until a connection to a backend server can be established. Defaults to 30 seconds. If zero, no timeout exists" export:"true"`
ResponseHeaderTimeout flaeg.Duration `description:"The amount of time to wait for a server's response headers after fully writing the request (including its body, if any). If zero, no timeout exists" export:"true"`
}
// LifeCycle contains configurations relevant to the lifecycle (such as the
// shutdown phase) of Traefik.
type LifeCycle struct {
RequestAcceptGraceTimeout flaeg.Duration `description:"Duration to keep accepting requests before Traefik initiates the graceful shutdown procedure"`
GraceTimeOut flaeg.Duration `description:"Duration to give active requests a chance to finish before Traefik stops"`
}
// HostResolverConfig contain configuration for CNAME Flattening
type HostResolverConfig struct {
CnameFlattening bool `description:"A flag to enable/disable CNAME flattening" export:"true"`
ResolvConfig string `description:"resolv.conf used for DNS resolving" export:"true"`
ResolvDepth int `description:"The maximal depth of DNS recursive resolving" export:"true"`
}

View File

@ -1,268 +0,0 @@
package configuration
import (
"testing"
"time"
"github.com/containous/flaeg"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/middlewares/tracing"
"github.com/containous/traefik/middlewares/tracing/jaeger"
"github.com/containous/traefik/middlewares/tracing/zipkin"
"github.com/containous/traefik/provider"
acmeprovider "github.com/containous/traefik/provider/acme"
"github.com/containous/traefik/provider/file"
"github.com/stretchr/testify/assert"
)
const defaultConfigFile = "traefik.toml"
func TestSetEffectiveConfigurationGraceTimeout(t *testing.T) {
testCases := []struct {
desc string
legacyGraceTimeout time.Duration
lifeCycleGraceTimeout time.Duration
wantGraceTimeout time.Duration
}{
{
desc: "legacy grace timeout given only",
legacyGraceTimeout: 5 * time.Second,
wantGraceTimeout: 5 * time.Second,
},
{
desc: "legacy and life cycle grace timeouts given",
legacyGraceTimeout: 5 * time.Second,
lifeCycleGraceTimeout: 12 * time.Second,
wantGraceTimeout: 5 * time.Second,
},
{
desc: "legacy grace timeout omitted",
legacyGraceTimeout: 0,
lifeCycleGraceTimeout: 12 * time.Second,
wantGraceTimeout: 12 * time.Second,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
gc := &GlobalConfiguration{
GraceTimeOut: flaeg.Duration(test.legacyGraceTimeout),
}
if test.lifeCycleGraceTimeout > 0 {
gc.LifeCycle = &LifeCycle{
GraceTimeOut: flaeg.Duration(test.lifeCycleGraceTimeout),
}
}
gc.SetEffectiveConfiguration(defaultConfigFile)
assert.Equal(t, test.wantGraceTimeout, time.Duration(gc.LifeCycle.GraceTimeOut))
})
}
}
func TestSetEffectiveConfigurationFileProviderFilename(t *testing.T) {
testCases := []struct {
desc string
fileProvider *file.Provider
wantFileProviderFilename string
wantFileProviderTraefikFile string
}{
{
desc: "no filename for file provider given",
fileProvider: &file.Provider{},
wantFileProviderFilename: "",
wantFileProviderTraefikFile: defaultConfigFile,
},
{
desc: "filename for file provider given",
fileProvider: &file.Provider{BaseProvider: provider.BaseProvider{Filename: "other.toml"}},
wantFileProviderFilename: "other.toml",
wantFileProviderTraefikFile: defaultConfigFile,
},
{
desc: "directory for file provider given",
fileProvider: &file.Provider{Directory: "/"},
wantFileProviderFilename: "",
wantFileProviderTraefikFile: defaultConfigFile,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
gc := &GlobalConfiguration{
File: test.fileProvider,
}
gc.SetEffectiveConfiguration(defaultConfigFile)
assert.Equal(t, test.wantFileProviderFilename, gc.File.Filename)
assert.Equal(t, test.wantFileProviderTraefikFile, gc.File.TraefikFile)
})
}
}
func TestSetEffectiveConfigurationTracing(t *testing.T) {
testCases := []struct {
desc string
tracing *tracing.Tracing
expected *tracing.Tracing
}{
{
desc: "no tracing configuration",
tracing: &tracing.Tracing{},
expected: &tracing.Tracing{},
},
{
desc: "tracing bad backend name",
tracing: &tracing.Tracing{
Backend: "powpow",
},
expected: &tracing.Tracing{
Backend: "powpow",
},
},
{
desc: "tracing jaeger backend name",
tracing: &tracing.Tracing{
Backend: "jaeger",
Zipkin: &zipkin.Config{
HTTPEndpoint: "http://localhost:9411/api/v1/spans",
SameSpan: false,
ID128Bit: true,
Debug: false,
},
},
expected: &tracing.Tracing{
Backend: "jaeger",
Jaeger: &jaeger.Config{
SamplingServerURL: "http://localhost:5778/sampling",
SamplingType: "const",
SamplingParam: 1.0,
LocalAgentHostPort: "127.0.0.1:6831",
},
Zipkin: nil,
},
},
{
desc: "tracing zipkin backend name",
tracing: &tracing.Tracing{
Backend: "zipkin",
Jaeger: &jaeger.Config{
SamplingServerURL: "http://localhost:5778/sampling",
SamplingType: "const",
SamplingParam: 1.0,
LocalAgentHostPort: "127.0.0.1:6831",
},
},
expected: &tracing.Tracing{
Backend: "zipkin",
Jaeger: nil,
Zipkin: &zipkin.Config{
HTTPEndpoint: "http://localhost:9411/api/v1/spans",
SameSpan: false,
ID128Bit: true,
Debug: false,
},
},
},
{
desc: "tracing zipkin backend name value override",
tracing: &tracing.Tracing{
Backend: "zipkin",
Jaeger: &jaeger.Config{
SamplingServerURL: "http://localhost:5778/sampling",
SamplingType: "const",
SamplingParam: 1.0,
LocalAgentHostPort: "127.0.0.1:6831",
},
Zipkin: &zipkin.Config{
HTTPEndpoint: "http://powpow:9411/api/v1/spans",
SameSpan: true,
ID128Bit: true,
Debug: true,
},
},
expected: &tracing.Tracing{
Backend: "zipkin",
Jaeger: nil,
Zipkin: &zipkin.Config{
HTTPEndpoint: "http://powpow:9411/api/v1/spans",
SameSpan: true,
ID128Bit: true,
Debug: true,
},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
gc := &GlobalConfiguration{
Tracing: test.tracing,
}
gc.SetEffectiveConfiguration(defaultConfigFile)
assert.Equal(t, test.expected, gc.Tracing)
})
}
}
func TestInitACMEProvider(t *testing.T) {
testCases := []struct {
desc string
acmeConfiguration *acme.ACME
expectedConfiguration *acmeprovider.Provider
noError bool
}{
{
desc: "No ACME configuration",
acmeConfiguration: nil,
expectedConfiguration: nil,
noError: true,
},
{
desc: "ACME configuration with storage",
acmeConfiguration: &acme.ACME{Storage: "foo/acme.json"},
expectedConfiguration: &acmeprovider.Provider{Configuration: &acmeprovider.Configuration{Storage: "foo/acme.json"}},
noError: true,
},
{
desc: "ACME configuration with no storage",
acmeConfiguration: &acme.ACME{},
expectedConfiguration: nil,
noError: false,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
gc := &GlobalConfiguration{
ACME: test.acmeConfiguration,
}
configuration, err := gc.InitACMEProvider()
assert.True(t, (err == nil) == test.noError)
if test.expectedConfiguration == nil {
assert.Nil(t, configuration)
} else {
assert.Equal(t, test.expectedConfiguration.Storage, configuration.Storage)
}
})
}
}

View File

@ -1,296 +0,0 @@
package configuration
import (
"fmt"
"strings"
"github.com/containous/traefik/log"
"github.com/containous/traefik/tls"
"github.com/containous/traefik/types"
)
// EntryPoint holds an entry point configuration of the reverse proxy (ip, port, TLS...)
type EntryPoint struct {
Address string
TLS *tls.TLS `export:"true"`
Redirect *types.Redirect `export:"true"`
Auth *types.Auth `export:"true"`
WhitelistSourceRange []string // Deprecated
WhiteList *types.WhiteList `export:"true"`
Compress bool `export:"true"`
ProxyProtocol *ProxyProtocol `export:"true"`
ForwardedHeaders *ForwardedHeaders `export:"true"`
}
// ProxyProtocol contains Proxy-Protocol configuration
type ProxyProtocol struct {
Insecure bool `export:"true"`
TrustedIPs []string
}
// ForwardedHeaders Trust client forwarding headers
type ForwardedHeaders struct {
Insecure bool `export:"true"`
TrustedIPs []string
}
// EntryPoints holds entry points configuration of the reverse proxy (ip, port, TLS...)
type EntryPoints map[string]*EntryPoint
// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func (ep EntryPoints) String() string {
return fmt.Sprintf("%+v", map[string]*EntryPoint(ep))
}
// Get return the EntryPoints map
func (ep *EntryPoints) Get() interface{} {
return *ep
}
// SetValue sets the EntryPoints map with val
func (ep *EntryPoints) SetValue(val interface{}) {
*ep = val.(EntryPoints)
}
// Type is type of the struct
func (ep *EntryPoints) Type() string {
return "entrypoints"
}
// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (ep *EntryPoints) Set(value string) error {
result := parseEntryPointsConfiguration(value)
var whiteListSourceRange []string
if len(result["whitelistsourcerange"]) > 0 {
whiteListSourceRange = strings.Split(result["whitelistsourcerange"], ",")
}
compress := toBool(result, "compress")
configTLS, err := makeEntryPointTLS(result)
if err != nil {
return err
}
(*ep)[result["name"]] = &EntryPoint{
Address: result["address"],
TLS: configTLS,
Auth: makeEntryPointAuth(result),
Redirect: makeEntryPointRedirect(result),
Compress: compress,
WhitelistSourceRange: whiteListSourceRange,
WhiteList: makeWhiteList(result),
ProxyProtocol: makeEntryPointProxyProtocol(result),
ForwardedHeaders: makeEntryPointForwardedHeaders(result),
}
return nil
}
func makeWhiteList(result map[string]string) *types.WhiteList {
var wl *types.WhiteList
if rawRange, ok := result["whitelist_sourcerange"]; ok {
wl = &types.WhiteList{
SourceRange: strings.Split(rawRange, ","),
UseXForwardedFor: toBool(result, "whitelist_usexforwardedfor"),
}
}
return wl
}
func makeEntryPointAuth(result map[string]string) *types.Auth {
var basic *types.Basic
if v, ok := result["auth_basic_users"]; ok {
basic = &types.Basic{
Users: strings.Split(v, ","),
RemoveHeader: toBool(result, "auth_basic_removeheader"),
}
}
var digest *types.Digest
if v, ok := result["auth_digest_users"]; ok {
digest = &types.Digest{
Users: strings.Split(v, ","),
RemoveHeader: toBool(result, "auth_digest_removeheader"),
}
}
var forward *types.Forward
if address, ok := result["auth_forward_address"]; ok {
var clientTLS *types.ClientTLS
cert := result["auth_forward_tls_cert"]
key := result["auth_forward_tls_key"]
insecureSkipVerify := toBool(result, "auth_forward_tls_insecureskipverify")
if len(cert) > 0 && len(key) > 0 || insecureSkipVerify {
clientTLS = &types.ClientTLS{
CA: result["auth_forward_tls_ca"],
CAOptional: toBool(result, "auth_forward_tls_caoptional"),
Cert: cert,
Key: key,
InsecureSkipVerify: insecureSkipVerify,
}
}
var authResponseHeaders []string
if v, ok := result["auth_forward_authresponseheaders"]; ok {
authResponseHeaders = strings.Split(v, ",")
}
forward = &types.Forward{
Address: address,
TLS: clientTLS,
TrustForwardHeader: toBool(result, "auth_forward_trustforwardheader"),
AuthResponseHeaders: authResponseHeaders,
}
}
var auth *types.Auth
if basic != nil || digest != nil || forward != nil {
auth = &types.Auth{
Basic: basic,
Digest: digest,
Forward: forward,
HeaderField: result["auth_headerfield"],
}
}
return auth
}
func makeEntryPointProxyProtocol(result map[string]string) *ProxyProtocol {
var proxyProtocol *ProxyProtocol
ppTrustedIPs := result["proxyprotocol_trustedips"]
if len(result["proxyprotocol_insecure"]) > 0 || len(ppTrustedIPs) > 0 {
proxyProtocol = &ProxyProtocol{
Insecure: toBool(result, "proxyprotocol_insecure"),
}
if len(ppTrustedIPs) > 0 {
proxyProtocol.TrustedIPs = strings.Split(ppTrustedIPs, ",")
}
}
if proxyProtocol != nil && proxyProtocol.Insecure {
log.Warn("ProxyProtocol.Insecure:true is dangerous. Please use 'ProxyProtocol.TrustedIPs:IPs' and remove 'ProxyProtocol.Insecure:true'")
}
return proxyProtocol
}
func makeEntryPointForwardedHeaders(result map[string]string) *ForwardedHeaders {
// TODO must be changed to false by default in the next breaking version.
forwardedHeaders := &ForwardedHeaders{Insecure: true}
if _, ok := result["forwardedheaders_insecure"]; ok {
forwardedHeaders.Insecure = toBool(result, "forwardedheaders_insecure")
}
fhTrustedIPs := result["forwardedheaders_trustedips"]
if len(fhTrustedIPs) > 0 {
// TODO must be removed in the next breaking version.
forwardedHeaders.Insecure = toBool(result, "forwardedheaders_insecure")
forwardedHeaders.TrustedIPs = strings.Split(fhTrustedIPs, ",")
}
return forwardedHeaders
}
func makeEntryPointRedirect(result map[string]string) *types.Redirect {
var redirect *types.Redirect
if len(result["redirect_entrypoint"]) > 0 || len(result["redirect_regex"]) > 0 || len(result["redirect_replacement"]) > 0 {
redirect = &types.Redirect{
EntryPoint: result["redirect_entrypoint"],
Regex: result["redirect_regex"],
Replacement: result["redirect_replacement"],
Permanent: toBool(result, "redirect_permanent"),
}
}
return redirect
}
func makeEntryPointTLS(result map[string]string) (*tls.TLS, error) {
var configTLS *tls.TLS
if len(result["tls"]) > 0 {
certs := tls.Certificates{}
if err := certs.Set(result["tls"]); err != nil {
return nil, err
}
configTLS = &tls.TLS{
Certificates: certs,
}
} else if len(result["tls_acme"]) > 0 {
configTLS = &tls.TLS{
Certificates: tls.Certificates{},
}
}
if configTLS != nil {
if len(result["ca"]) > 0 {
files := tls.FilesOrContents{}
files.Set(result["ca"])
optional := toBool(result, "ca_optional")
configTLS.ClientCA = tls.ClientCA{
Files: files,
Optional: optional,
}
}
if len(result["tls_minversion"]) > 0 {
configTLS.MinVersion = result["tls_minversion"]
}
if len(result["tls_ciphersuites"]) > 0 {
configTLS.CipherSuites = strings.Split(result["tls_ciphersuites"], ",")
}
if len(result["tls_snistrict"]) > 0 {
configTLS.SniStrict = toBool(result, "tls_snistrict")
}
if len(result["tls_defaultcertificate_cert"]) > 0 && len(result["tls_defaultcertificate_key"]) > 0 {
configTLS.DefaultCertificate = &tls.Certificate{
CertFile: tls.FileOrContent(result["tls_defaultcertificate_cert"]),
KeyFile: tls.FileOrContent(result["tls_defaultcertificate_key"]),
}
}
}
return configTLS, nil
}
func parseEntryPointsConfiguration(raw string) map[string]string {
sections := strings.Fields(raw)
config := make(map[string]string)
for _, part := range sections {
field := strings.SplitN(part, ":", 2)
name := strings.ToLower(strings.Replace(field[0], ".", "_", -1))
if len(field) > 1 {
config[name] = field[1]
} else {
if strings.EqualFold(name, "TLS") {
config["tls_acme"] = "TLS"
} else {
config[name] = ""
}
}
}
return config
}
func toBool(conf map[string]string, key string) bool {
if val, ok := conf[key]; ok {
return strings.EqualFold(val, "true") ||
strings.EqualFold(val, "enable") ||
strings.EqualFold(val, "on")
}
return false
}

View File

@ -1,493 +0,0 @@
package configuration
import (
"testing"
"github.com/containous/traefik/tls"
"github.com/containous/traefik/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_parseEntryPointsConfiguration(t *testing.T) {
testCases := []struct {
name string
value string
expectedResult map[string]string
}{
{
name: "all parameters",
value: "Name:foo " +
"Address::8000 " +
"TLS:goo,gii " +
"TLS " +
"TLS.MinVersion:VersionTLS11 " +
"TLS.CipherSuites:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA " +
"CA:car " +
"CA.Optional:true " +
"Redirect.EntryPoint:https " +
"Redirect.Regex:http://localhost/(.*) " +
"Redirect.Replacement:http://mydomain/$1 " +
"Redirect.Permanent:true " +
"Compress:true " +
"ProxyProtocol.TrustedIPs:192.168.0.1 " +
"ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24 " +
"Auth.Basic.Users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 " +
"Auth.Basic.RemoveHeader:true " +
"Auth.Digest.Users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e " +
"Auth.Digest.RemoveHeader:true " +
"Auth.HeaderField:X-WebAuth-User " +
"Auth.Forward.Address:https://authserver.com/auth " +
"Auth.Forward.AuthResponseHeaders:X-Auth,X-Test,X-Secret " +
"Auth.Forward.TrustForwardHeader:true " +
"Auth.Forward.TLS.CA:path/to/local.crt " +
"Auth.Forward.TLS.CAOptional:true " +
"Auth.Forward.TLS.Cert:path/to/foo.cert " +
"Auth.Forward.TLS.Key:path/to/foo.key " +
"Auth.Forward.TLS.InsecureSkipVerify:true " +
"WhiteListSourceRange:10.42.0.0/16,152.89.1.33/32,afed:be44::/16 " +
"whiteList.sourceRange:10.42.0.0/16,152.89.1.33/32,afed:be44::/16 " +
"whiteList.useXForwardedFor:true ",
expectedResult: map[string]string{
"address": ":8000",
"auth_basic_users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
"auth_basic_removeheader": "true",
"auth_digest_users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e",
"auth_digest_removeheader": "true",
"auth_forward_address": "https://authserver.com/auth",
"auth_forward_authresponseheaders": "X-Auth,X-Test,X-Secret",
"auth_forward_tls_ca": "path/to/local.crt",
"auth_forward_tls_caoptional": "true",
"auth_forward_tls_cert": "path/to/foo.cert",
"auth_forward_tls_insecureskipverify": "true",
"auth_forward_tls_key": "path/to/foo.key",
"auth_forward_trustforwardheader": "true",
"auth_headerfield": "X-WebAuth-User",
"ca": "car",
"ca_optional": "true",
"compress": "true",
"forwardedheaders_trustedips": "10.0.0.3/24,20.0.0.3/24",
"name": "foo",
"proxyprotocol_trustedips": "192.168.0.1",
"redirect_entrypoint": "https",
"redirect_permanent": "true",
"redirect_regex": "http://localhost/(.*)",
"redirect_replacement": "http://mydomain/$1",
"tls": "goo,gii",
"tls_acme": "TLS",
"tls_ciphersuites": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"tls_minversion": "VersionTLS11",
"whitelistsourcerange": "10.42.0.0/16,152.89.1.33/32,afed:be44::/16",
"whitelist_sourcerange": "10.42.0.0/16,152.89.1.33/32,afed:be44::/16",
"whitelist_usexforwardedfor": "true",
},
},
{
name: "compress on",
value: "name:foo Compress:on",
expectedResult: map[string]string{
"name": "foo",
"compress": "on",
},
},
{
name: "TLS",
value: "Name:foo TLS:goo TLS",
expectedResult: map[string]string{
"name": "foo",
"tls": "goo",
"tls_acme": "TLS",
},
},
}
for _, test := range testCases {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
conf := parseEntryPointsConfiguration(test.value)
assert.Len(t, conf, len(test.expectedResult))
assert.Equal(t, test.expectedResult, conf)
})
}
}
func Test_toBool(t *testing.T) {
testCases := []struct {
name string
value string
key string
expectedBool bool
}{
{
name: "on",
value: "on",
key: "foo",
expectedBool: true,
},
{
name: "true",
value: "true",
key: "foo",
expectedBool: true,
},
{
name: "enable",
value: "enable",
key: "foo",
expectedBool: true,
},
{
name: "arbitrary string",
value: "bar",
key: "foo",
expectedBool: false,
},
{
name: "no existing entry",
value: "bar",
key: "fii",
expectedBool: false,
},
}
for _, test := range testCases {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
conf := map[string]string{
"foo": test.value,
}
result := toBool(conf, test.key)
assert.Equal(t, test.expectedBool, result)
})
}
}
func TestEntryPoints_Set(t *testing.T) {
testCases := []struct {
name string
expression string
expectedEntryPointName string
expectedEntryPoint *EntryPoint
}{
{
name: "all parameters camelcase",
expression: "Name:foo " +
"Address::8000 " +
"TLS:goo,gii;foo,fii " +
"TLS " +
"TLS.MinVersion:VersionTLS11 " +
"TLS.CipherSuites:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA " +
"CA:car " +
"CA.Optional:true " +
"Redirect.EntryPoint:https " +
"Redirect.Regex:http://localhost/(.*) " +
"Redirect.Replacement:http://mydomain/$1 " +
"Redirect.Permanent:true " +
"Compress:true " +
"ProxyProtocol.TrustedIPs:192.168.0.1 " +
"ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24 " +
"Auth.Basic.Users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 " +
"Auth.Basic.RemoveHeader:true " +
"Auth.Digest.Users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e " +
"Auth.Digest.RemoveHeader:true " +
"Auth.HeaderField:X-WebAuth-User " +
"Auth.Forward.Address:https://authserver.com/auth " +
"Auth.Forward.AuthResponseHeaders:X-Auth,X-Test,X-Secret " +
"Auth.Forward.TrustForwardHeader:true " +
"Auth.Forward.TLS.CA:path/to/local.crt " +
"Auth.Forward.TLS.CAOptional:true " +
"Auth.Forward.TLS.Cert:path/to/foo.cert " +
"Auth.Forward.TLS.Key:path/to/foo.key " +
"Auth.Forward.TLS.InsecureSkipVerify:true " +
"WhiteListSourceRange:10.42.0.0/16,152.89.1.33/32,afed:be44::/16 " +
"whiteList.sourceRange:10.42.0.0/16,152.89.1.33/32,afed:be44::/16 " +
"whiteList.useXForwardedFor:true ",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
Address: ":8000",
TLS: &tls.TLS{
MinVersion: "VersionTLS11",
CipherSuites: []string{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"},
Certificates: tls.Certificates{
{
CertFile: tls.FileOrContent("goo"),
KeyFile: tls.FileOrContent("gii"),
},
{
CertFile: tls.FileOrContent("foo"),
KeyFile: tls.FileOrContent("fii"),
},
},
ClientCA: tls.ClientCA{
Files: tls.FilesOrContents{"car"},
Optional: true,
},
},
Redirect: &types.Redirect{
EntryPoint: "https",
Regex: "http://localhost/(.*)",
Replacement: "http://mydomain/$1",
Permanent: true,
},
Auth: &types.Auth{
Basic: &types.Basic{
RemoveHeader: true,
Users: types.Users{
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
},
},
Digest: &types.Digest{
RemoveHeader: true,
Users: types.Users{
"test:traefik:a2688e031edb4be6a3797f3882655c05",
"test2:traefik:518845800f9e2bfb1f1f740ec24f074e",
},
},
Forward: &types.Forward{
Address: "https://authserver.com/auth",
AuthResponseHeaders: []string{"X-Auth", "X-Test", "X-Secret"},
TLS: &types.ClientTLS{
CA: "path/to/local.crt",
CAOptional: true,
Cert: "path/to/foo.cert",
Key: "path/to/foo.key",
InsecureSkipVerify: true,
},
TrustForwardHeader: true,
},
HeaderField: "X-WebAuth-User",
},
WhitelistSourceRange: []string{
"10.42.0.0/16",
"152.89.1.33/32",
"afed:be44::/16",
},
WhiteList: &types.WhiteList{
SourceRange: []string{
"10.42.0.0/16",
"152.89.1.33/32",
"afed:be44::/16",
},
UseXForwardedFor: true,
},
Compress: true,
ProxyProtocol: &ProxyProtocol{
Insecure: false,
TrustedIPs: []string{"192.168.0.1"},
},
ForwardedHeaders: &ForwardedHeaders{
Insecure: false,
TrustedIPs: []string{
"10.0.0.3/24",
"20.0.0.3/24",
},
},
},
},
{
name: "all parameters lowercase",
expression: "Name:foo " +
"address::8000 " +
"tls:goo,gii;foo,fii " +
"tls " +
"tls.minversion:VersionTLS11 " +
"tls.ciphersuites:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA " +
"ca:car " +
"ca.Optional:true " +
"redirect.entryPoint:https " +
"redirect.regex:http://localhost/(.*) " +
"redirect.replacement:http://mydomain/$1 " +
"redirect.permanent:true " +
"compress:true " +
"whiteListSourceRange:10.42.0.0/16,152.89.1.33/32,afed:be44::/16 " +
"proxyProtocol.TrustedIPs:192.168.0.1 " +
"forwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24 " +
"auth.basic.users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 " +
"auth.digest.users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e " +
"auth.headerField:X-WebAuth-User " +
"auth.forward.address:https://authserver.com/auth " +
"auth.forward.authResponseHeaders:X-Auth,X-Test,X-Secret " +
"auth.forward.trustForwardHeader:true " +
"auth.forward.tls.ca:path/to/local.crt " +
"auth.forward.tls.caOptional:true " +
"auth.forward.tls.cert:path/to/foo.cert " +
"auth.forward.tls.key:path/to/foo.key " +
"auth.forward.tls.insecureSkipVerify:true ",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
Address: ":8000",
TLS: &tls.TLS{
MinVersion: "VersionTLS11",
CipherSuites: []string{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"},
Certificates: tls.Certificates{
{
CertFile: tls.FileOrContent("goo"),
KeyFile: tls.FileOrContent("gii"),
},
{
CertFile: tls.FileOrContent("foo"),
KeyFile: tls.FileOrContent("fii"),
},
},
ClientCA: tls.ClientCA{
Files: tls.FilesOrContents{"car"},
Optional: true,
},
},
Redirect: &types.Redirect{
EntryPoint: "https",
Regex: "http://localhost/(.*)",
Replacement: "http://mydomain/$1",
Permanent: true,
},
Auth: &types.Auth{
Basic: &types.Basic{
Users: types.Users{
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
},
},
Digest: &types.Digest{
Users: types.Users{
"test:traefik:a2688e031edb4be6a3797f3882655c05",
"test2:traefik:518845800f9e2bfb1f1f740ec24f074e",
},
},
Forward: &types.Forward{
Address: "https://authserver.com/auth",
AuthResponseHeaders: []string{"X-Auth", "X-Test", "X-Secret"},
TLS: &types.ClientTLS{
CA: "path/to/local.crt",
CAOptional: true,
Cert: "path/to/foo.cert",
Key: "path/to/foo.key",
InsecureSkipVerify: true,
},
TrustForwardHeader: true,
},
HeaderField: "X-WebAuth-User",
},
WhitelistSourceRange: []string{
"10.42.0.0/16",
"152.89.1.33/32",
"afed:be44::/16",
},
Compress: true,
ProxyProtocol: &ProxyProtocol{
Insecure: false,
TrustedIPs: []string{"192.168.0.1"},
},
ForwardedHeaders: &ForwardedHeaders{
Insecure: false,
TrustedIPs: []string{
"10.0.0.3/24",
"20.0.0.3/24",
},
},
},
},
{
name: "default",
expression: "Name:foo",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
},
},
{
name: "ForwardedHeaders insecure true",
expression: "Name:foo ForwardedHeaders.Insecure:true",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
},
},
{
name: "ForwardedHeaders insecure false",
expression: "Name:foo ForwardedHeaders.Insecure:false",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
ForwardedHeaders: &ForwardedHeaders{Insecure: false},
},
},
{
name: "ForwardedHeaders TrustedIPs",
expression: "Name:foo ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
ForwardedHeaders: &ForwardedHeaders{
TrustedIPs: []string{"10.0.0.3/24", "20.0.0.3/24"},
},
},
},
{
name: "ProxyProtocol insecure true",
expression: "Name:foo ProxyProtocol.Insecure:true",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
ProxyProtocol: &ProxyProtocol{Insecure: true},
},
},
{
name: "ProxyProtocol insecure false",
expression: "Name:foo ProxyProtocol.Insecure:false",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
ProxyProtocol: &ProxyProtocol{},
},
},
{
name: "ProxyProtocol TrustedIPs",
expression: "Name:foo ProxyProtocol.TrustedIPs:10.0.0.3/24,20.0.0.3/24",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
ProxyProtocol: &ProxyProtocol{
TrustedIPs: []string{"10.0.0.3/24", "20.0.0.3/24"},
},
},
},
{
name: "compress on",
expression: "Name:foo Compress:on",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
Compress: true,
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
},
},
{
name: "compress true",
expression: "Name:foo Compress:true",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
Compress: true,
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
eps := EntryPoints{}
err := eps.Set(test.expression)
require.NoError(t, err)
ep := eps[test.expectedEntryPointName]
assert.EqualValues(t, test.expectedEntryPoint, ep)
})
}
}

View File

@ -1,113 +0,0 @@
package configuration
import (
"encoding/json"
"github.com/containous/traefik/log"
"github.com/containous/traefik/provider"
"github.com/containous/traefik/safe"
"github.com/containous/traefik/types"
)
// ProviderAggregator aggregate providers
type ProviderAggregator struct {
providers []provider.Provider
constraints types.Constraints
}
// NewProviderAggregator return an aggregate of all the providers configured in GlobalConfiguration
func NewProviderAggregator(gc *GlobalConfiguration) ProviderAggregator {
provider := ProviderAggregator{
constraints: gc.Constraints,
}
if gc.Docker != nil {
provider.quietAddProvider(gc.Docker)
}
if gc.Marathon != nil {
provider.quietAddProvider(gc.Marathon)
}
if gc.File != nil {
provider.quietAddProvider(gc.File)
}
if gc.Rest != nil {
provider.quietAddProvider(gc.Rest)
}
if gc.Consul != nil {
provider.quietAddProvider(gc.Consul)
}
if gc.ConsulCatalog != nil {
provider.quietAddProvider(gc.ConsulCatalog)
}
if gc.Etcd != nil {
provider.quietAddProvider(gc.Etcd)
}
if gc.Zookeeper != nil {
provider.quietAddProvider(gc.Zookeeper)
}
if gc.Boltdb != nil {
provider.quietAddProvider(gc.Boltdb)
}
if gc.Kubernetes != nil {
provider.quietAddProvider(gc.Kubernetes)
}
if gc.Mesos != nil {
provider.quietAddProvider(gc.Mesos)
}
if gc.Eureka != nil {
provider.quietAddProvider(gc.Eureka)
}
if gc.ECS != nil {
provider.quietAddProvider(gc.ECS)
}
if gc.Rancher != nil {
provider.quietAddProvider(gc.Rancher)
}
if gc.DynamoDB != nil {
provider.quietAddProvider(gc.DynamoDB)
}
if gc.ServiceFabric != nil {
provider.quietAddProvider(gc.ServiceFabric)
}
return provider
}
func (p *ProviderAggregator) quietAddProvider(provider provider.Provider) {
err := p.AddProvider(provider)
if err != nil {
log.Errorf("Error initializing provider %T: %v", provider, err)
}
}
// AddProvider add a provider in the providers map
func (p *ProviderAggregator) AddProvider(provider provider.Provider) error {
err := provider.Init(p.constraints)
if err != nil {
return err
}
p.providers = append(p.providers, provider)
return nil
}
// Init the provider
func (p ProviderAggregator) Init(_ types.Constraints) error {
return nil
}
// Provide call the provide method of every providers
func (p ProviderAggregator) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool) error {
for _, p := range p.providers {
jsonConf, err := json.Marshal(p)
if err != nil {
log.Debugf("Unable to marshal provider conf %T with error: %v", p, err)
}
log.Infof("Starting provider %T %s", p, jsonConf)
currentProvider := p
safe.Go(func() {
err := currentProvider.Provide(configurationChan, pool)
if err != nil {
log.Errorf("Error starting provider %T: %v", p, err)
}
})
}
return nil
}

View File

@ -1,132 +0,0 @@
package router
import (
"github.com/containous/mux"
"github.com/containous/traefik/configuration"
"github.com/containous/traefik/log"
"github.com/containous/traefik/metrics"
"github.com/containous/traefik/middlewares"
mauth "github.com/containous/traefik/middlewares/auth"
"github.com/containous/traefik/types"
"github.com/urfave/negroni"
)
// NewInternalRouterAggregator Create a new internalRouterAggregator
func NewInternalRouterAggregator(globalConfiguration configuration.GlobalConfiguration, entryPointName string) *InternalRouterAggregator {
var serverMiddlewares []negroni.Handler
if globalConfiguration.EntryPoints[entryPointName].WhiteList != nil {
ipWhitelistMiddleware, err := middlewares.NewIPWhiteLister(
globalConfiguration.EntryPoints[entryPointName].WhiteList.SourceRange,
globalConfiguration.EntryPoints[entryPointName].WhiteList.UseXForwardedFor)
if err != nil {
log.Fatalf("Error creating whitelist middleware: %s", err)
}
if ipWhitelistMiddleware != nil {
serverMiddlewares = append(serverMiddlewares, ipWhitelistMiddleware)
}
}
if globalConfiguration.EntryPoints[entryPointName].Auth != nil {
authMiddleware, err := mauth.NewAuthenticator(globalConfiguration.EntryPoints[entryPointName].Auth, nil)
if err != nil {
log.Fatalf("Error creating authenticator middleware: %s", err)
}
serverMiddlewares = append(serverMiddlewares, authMiddleware)
}
router := InternalRouterAggregator{}
routerWithPrefix := InternalRouterAggregator{}
routerWithPrefixAndMiddleware := InternalRouterAggregator{}
if globalConfiguration.Metrics != nil && globalConfiguration.Metrics.Prometheus != nil && globalConfiguration.Metrics.Prometheus.EntryPoint == entryPointName {
routerWithPrefixAndMiddleware.AddRouter(metrics.PrometheusHandler{})
}
if globalConfiguration.Rest != nil && globalConfiguration.Rest.EntryPoint == entryPointName {
routerWithPrefixAndMiddleware.AddRouter(globalConfiguration.Rest)
}
if globalConfiguration.API != nil && globalConfiguration.API.EntryPoint == entryPointName {
routerWithPrefixAndMiddleware.AddRouter(globalConfiguration.API)
}
if globalConfiguration.Ping != nil && globalConfiguration.Ping.EntryPoint == entryPointName {
routerWithPrefix.AddRouter(globalConfiguration.Ping)
}
if globalConfiguration.ACME != nil && globalConfiguration.ACME.HTTPChallenge != nil && globalConfiguration.ACME.HTTPChallenge.EntryPoint == entryPointName {
router.AddRouter(globalConfiguration.ACME)
}
realRouterWithMiddleware := WithMiddleware{router: &routerWithPrefixAndMiddleware, routerMiddlewares: serverMiddlewares}
if globalConfiguration.Web != nil && globalConfiguration.Web.Path != "" {
router.AddRouter(&WithPrefix{PathPrefix: globalConfiguration.Web.Path, Router: &routerWithPrefix})
router.AddRouter(&WithPrefix{PathPrefix: globalConfiguration.Web.Path, Router: &realRouterWithMiddleware})
} else {
router.AddRouter(&routerWithPrefix)
router.AddRouter(&realRouterWithMiddleware)
}
return &router
}
// WithMiddleware router with internal middleware
type WithMiddleware struct {
router types.InternalRouter
routerMiddlewares []negroni.Handler
}
// AddRoutes Add routes to the router
func (wm *WithMiddleware) AddRoutes(systemRouter *mux.Router) {
realRouter := systemRouter.PathPrefix("/").Subrouter()
wm.router.AddRoutes(realRouter)
if len(wm.routerMiddlewares) > 0 {
realRouter.Walk(wrapRoute(wm.routerMiddlewares))
}
}
// WithPrefix router which add a prefix
type WithPrefix struct {
Router types.InternalRouter
PathPrefix string
}
// AddRoutes Add routes to the router
func (wp *WithPrefix) AddRoutes(systemRouter *mux.Router) {
realRouter := systemRouter.PathPrefix("/").Subrouter()
if wp.PathPrefix != "" {
realRouter = systemRouter.PathPrefix(wp.PathPrefix).Subrouter()
realRouter.StrictSlash(true)
realRouter.SkipClean(true)
}
wp.Router.AddRoutes(realRouter)
}
// InternalRouterAggregator InternalRouter that aggregate other internalRouter
type InternalRouterAggregator struct {
internalRouters []types.InternalRouter
}
// AddRouter add a router in the aggregator
func (r *InternalRouterAggregator) AddRouter(router types.InternalRouter) {
r.internalRouters = append(r.internalRouters, router)
}
// AddRoutes Add routes to the router
func (r *InternalRouterAggregator) AddRoutes(systemRouter *mux.Router) {
for _, router := range r.internalRouters {
router.AddRoutes(systemRouter)
}
}
// wrapRoute with middlewares
func wrapRoute(middlewares []negroni.Handler) func(*mux.Route, *mux.Router, []*mux.Route) error {
return func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
middles := append(middlewares, negroni.Wrap(route.GetHandler()))
route.Handler(negroni.New(middles...))
return nil
}
}

View File

@ -1,346 +0,0 @@
package router
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/containous/mux"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/api"
"github.com/containous/traefik/configuration"
"github.com/containous/traefik/ping"
acmeprovider "github.com/containous/traefik/provider/acme"
"github.com/containous/traefik/safe"
"github.com/containous/traefik/types"
"github.com/stretchr/testify/assert"
"github.com/urfave/negroni"
)
func TestNewInternalRouterAggregatorWithWebPath(t *testing.T) {
currentConfiguration := &safe.Safe{}
currentConfiguration.Set(types.Configurations{})
globalConfiguration := configuration.GlobalConfiguration{
Web: &configuration.WebCompatibility{
Path: "/prefix",
},
API: &api.Handler{
EntryPoint: "traefik",
CurrentConfigurations: currentConfiguration,
},
Ping: &ping.Handler{
EntryPoint: "traefik",
},
ACME: &acme.ACME{
HTTPChallenge: &acmeprovider.HTTPChallenge{
EntryPoint: "traefik",
},
},
EntryPoints: configuration.EntryPoints{
"traefik": &configuration.EntryPoint{},
},
}
testCases := []struct {
desc string
testedURL string
expectedStatusCode int
}{
{
desc: "Ping without prefix",
testedURL: "/ping",
expectedStatusCode: 502,
},
{
desc: "Ping with prefix",
testedURL: "/prefix/ping",
expectedStatusCode: 200,
},
{
desc: "acme without prefix",
testedURL: "/.well-known/acme-challenge/token",
expectedStatusCode: 404,
},
{
desc: "api without prefix",
testedURL: "/api",
expectedStatusCode: 502,
},
{
desc: "api with prefix",
testedURL: "/prefix/api",
expectedStatusCode: 200,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
router := NewInternalRouterAggregator(globalConfiguration, "traefik")
internalMuxRouter := mux.NewRouter()
router.AddRoutes(internalMuxRouter)
internalMuxRouter.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadGateway)
})
recorder := httptest.NewRecorder()
request := httptest.NewRequest(http.MethodGet, test.testedURL, nil)
internalMuxRouter.ServeHTTP(recorder, request)
assert.Equal(t, test.expectedStatusCode, recorder.Code)
})
}
}
func TestNewInternalRouterAggregatorWithAuth(t *testing.T) {
currentConfiguration := &safe.Safe{}
currentConfiguration.Set(types.Configurations{})
globalConfiguration := configuration.GlobalConfiguration{
API: &api.Handler{
EntryPoint: "traefik",
CurrentConfigurations: currentConfiguration,
},
Ping: &ping.Handler{
EntryPoint: "traefik",
},
ACME: &acme.ACME{
HTTPChallenge: &acmeprovider.HTTPChallenge{
EntryPoint: "traefik",
},
},
EntryPoints: configuration.EntryPoints{
"traefik": &configuration.EntryPoint{
Auth: &types.Auth{
Basic: &types.Basic{
Users: types.Users{"test:test"},
},
},
},
},
}
testCases := []struct {
desc string
testedURL string
expectedStatusCode int
}{
{
desc: "Wrong url",
testedURL: "/wrong",
expectedStatusCode: 502,
},
{
desc: "Ping without auth",
testedURL: "/ping",
expectedStatusCode: 200,
},
{
desc: "acme without auth",
testedURL: "/.well-known/acme-challenge/token",
expectedStatusCode: 404,
},
{
desc: "api with auth",
testedURL: "/api",
expectedStatusCode: 401,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
router := NewInternalRouterAggregator(globalConfiguration, "traefik")
internalMuxRouter := mux.NewRouter()
router.AddRoutes(internalMuxRouter)
internalMuxRouter.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadGateway)
})
recorder := httptest.NewRecorder()
request := httptest.NewRequest(http.MethodGet, test.testedURL, nil)
internalMuxRouter.ServeHTTP(recorder, request)
assert.Equal(t, test.expectedStatusCode, recorder.Code)
})
}
}
func TestNewInternalRouterAggregatorWithAuthAndPrefix(t *testing.T) {
currentConfiguration := &safe.Safe{}
currentConfiguration.Set(types.Configurations{})
globalConfiguration := configuration.GlobalConfiguration{
Web: &configuration.WebCompatibility{
Path: "/prefix",
},
API: &api.Handler{
EntryPoint: "traefik",
CurrentConfigurations: currentConfiguration,
},
Ping: &ping.Handler{
EntryPoint: "traefik",
},
ACME: &acme.ACME{
HTTPChallenge: &acmeprovider.HTTPChallenge{
EntryPoint: "traefik",
},
},
EntryPoints: configuration.EntryPoints{
"traefik": &configuration.EntryPoint{
Auth: &types.Auth{
Basic: &types.Basic{
Users: types.Users{"test:test"},
},
},
},
},
}
testCases := []struct {
desc string
testedURL string
expectedStatusCode int
}{
{
desc: "Ping without prefix",
testedURL: "/ping",
expectedStatusCode: 502,
},
{
desc: "Ping without auth and with prefix",
testedURL: "/prefix/ping",
expectedStatusCode: 200,
},
{
desc: "acme without auth and without prefix",
testedURL: "/.well-known/acme-challenge/token",
expectedStatusCode: 404,
},
{
desc: "api with auth and prefix",
testedURL: "/prefix/api",
expectedStatusCode: 401,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
router := NewInternalRouterAggregator(globalConfiguration, "traefik")
internalMuxRouter := mux.NewRouter()
router.AddRoutes(internalMuxRouter)
internalMuxRouter.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadGateway)
})
recorder := httptest.NewRecorder()
request := httptest.NewRequest(http.MethodGet, test.testedURL, nil)
internalMuxRouter.ServeHTTP(recorder, request)
assert.Equal(t, test.expectedStatusCode, recorder.Code)
})
}
}
type MockInternalRouterFunc func(systemRouter *mux.Router)
func (m MockInternalRouterFunc) AddRoutes(systemRouter *mux.Router) {
m(systemRouter)
}
func TestWithMiddleware(t *testing.T) {
router := WithMiddleware{
router: MockInternalRouterFunc(func(systemRouter *mux.Router) {
systemRouter.Handle("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("router"))
}))
}),
routerMiddlewares: []negroni.Handler{
negroni.HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
rw.Write([]byte("before middleware1|"))
next.ServeHTTP(rw, r)
rw.Write([]byte("|after middleware1"))
}),
negroni.HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
rw.Write([]byte("before middleware2|"))
next.ServeHTTP(rw, r)
rw.Write([]byte("|after middleware2"))
}),
},
}
internalMuxRouter := mux.NewRouter()
router.AddRoutes(internalMuxRouter)
recorder := httptest.NewRecorder()
request := httptest.NewRequest(http.MethodGet, "/test", nil)
internalMuxRouter.ServeHTTP(recorder, request)
obtained := recorder.Body.String()
assert.Equal(t, "before middleware1|before middleware2|router|after middleware2|after middleware1", obtained)
}
func TestWithPrefix(t *testing.T) {
testCases := []struct {
desc string
prefix string
testedURL string
expectedStatusCode int
}{
{
desc: "No prefix",
testedURL: "/test",
expectedStatusCode: 200,
},
{
desc: "With prefix and wrong url",
prefix: "/prefix",
testedURL: "/test",
expectedStatusCode: 404,
},
{
desc: "With prefix",
prefix: "/prefix",
testedURL: "/prefix/test",
expectedStatusCode: 200,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
router := WithPrefix{
Router: MockInternalRouterFunc(func(systemRouter *mux.Router) {
systemRouter.Handle("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}))
}),
PathPrefix: test.prefix,
}
internalMuxRouter := mux.NewRouter()
router.AddRoutes(internalMuxRouter)
recorder := httptest.NewRecorder()
request := httptest.NewRequest(http.MethodGet, test.testedURL, nil)
internalMuxRouter.ServeHTTP(recorder, request)
assert.Equal(t, test.expectedStatusCode, recorder.Code)
})
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,170 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2017 Brian 'redbeard' Harrington <redbeard@dead-city.org>
#
# dumpcerts.sh - A simple utility to explode a Traefik acme.json file into a
# directory of certificates and a private key
#
# Usage - dumpcerts.sh /etc/traefik/acme.json /etc/ssl/
#
# Dependencies -
# util-linux
# openssl
# jq
# The MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Exit codes:
# 1 - A component is missing or could not be read
# 2 - There was a problem reading acme.json
# 4 - The destination certificate directory does not exist
# 8 - Missing private key
set -o errexit
set -o pipefail
set -o nounset
USAGE="$(basename "$0") <path to acme> <destination cert directory>"
# Platform variations
case "$(uname)" in
'Linux')
# On Linux, -d should always work. --decode does not work with Alpine's busybox-binary
CMD_DECODE_BASE64="base64 -d"
;;
*)
# Max OS-X supports --decode and -D, but --decode may be supported by other platforms as well.
CMD_DECODE_BASE64="base64 --decode"
;;
esac
# Allow us to exit on a missing jq binary
exit_jq() {
echo "
You must have the binary 'jq' to use this.
jq is available at: https://stedolan.github.io/jq/download/
${USAGE}" >&2
exit 1
}
bad_acme() {
echo "
There was a problem parsing your acme.json file.
${USAGE}" >&2
exit 2
}
if [ $# -ne 2 ]; then
echo "
Insufficient number of parameters.
${USAGE}" >&2
exit 1
fi
readonly acmefile="${1}"
readonly certdir="${2%/}"
if [ ! -r "${acmefile}" ]; then
echo "
There was a problem reading from '${acmefile}'
We need to read this file to explode the JSON bundle... exiting.
${USAGE}" >&2
exit 2
fi
if [ ! -d "${certdir}" ]; then
echo "
Path ${certdir} does not seem to be a directory
We need a directory in which to explode the JSON bundle... exiting.
${USAGE}" >&2
exit 4
fi
jq=$(command -v jq) || exit_jq
priv=$(${jq} -e -r '.Account.PrivateKey' "${acmefile}") || bad_acme
if [ ! -n "${priv}" ]; then
echo "
There didn't seem to be a private key in ${acmefile}.
Please ensure that there is a key in this file and try again." >&2
exit 8
fi
# If they do not exist, create the needed subdirectories for our assets
# and place each in a variable for later use, normalizing the path
mkdir -p "${certdir}"/{certs,private}
pdir="${certdir}/private/"
cdir="${certdir}/certs/"
# Save the existing umask, change the default mode to 600, then
# after writing the private key switch it back to the default
oldumask=$(umask)
umask 177
trap 'umask ${oldumask}' EXIT
# traefik stores the private key in stripped base64 format but the certificates
# bundled as a base64 object without stripping headers. This normalizes the
# headers and formatting.
#
# In testing this out it was a balance between the following mechanisms:
# gawk:
# echo ${priv} | awk 'BEGIN {print "-----BEGIN RSA PRIVATE KEY-----"}
# {gsub(/.{64}/,"&\n")}1
# END {print "-----END RSA PRIVATE KEY-----"}' > "${pdir}/letsencrypt.key"
#
# openssl:
# echo -e "-----BEGIN RSA PRIVATE KEY-----\n${priv}\n-----END RSA PRIVATE KEY-----" \
# | openssl rsa -inform pem -out "${pdir}/letsencrypt.key"
#
# and sed:
# echo "-----BEGIN RSA PRIVATE KEY-----" > "${pdir}/letsencrypt.key"
# echo ${priv} | sed -E 's/(.{64})/\1\n/g' >> "${pdir}/letsencrypt.key"
# sed -i '$ d' "${pdir}/letsencrypt.key"
# echo "-----END RSA PRIVATE KEY-----" >> "${pdir}/letsencrypt.key"
# openssl rsa -noout -in "${pdir}/letsencrypt.key" -check # To check if the key is valid
# In the end, openssl was chosen because most users will need this script
# *because* of openssl combined with the fact that it will refuse to write the
# key if it does not parse out correctly. The other mechanisms were left as
# comments so that the user can choose the mechanism most appropriate to them.
echo -e "-----BEGIN RSA PRIVATE KEY-----\n${priv}\n-----END RSA PRIVATE KEY-----" \
| openssl rsa -inform pem -out "${pdir}/letsencrypt.key"
# Process the certificates for each of the domains in acme.json
for domain in $(jq -r '.Certificates[].Domain.Main' ${acmefile}); do
# Traefik stores a cert bundle for each domain. Within this cert
# bundle there is both proper the certificate and the Let's Encrypt CA
echo "Extracting cert bundle for ${domain}"
cert=$(jq -e -r --arg domain "$domain" '.Certificates[] |
select (.Domain.Main == $domain )| .Certificate' ${acmefile}) || bad_acme
echo "${cert}" | ${CMD_DECODE_BASE64} > "${cdir}/${domain}.crt"
echo "Extracting private key for ${domain}"
key=$(jq -e -r --arg domain "$domain" '.Certificates[] |
select (.Domain.Main == $domain )| .Key' ${acmefile}) || bad_acme
echo "${key}" | ${CMD_DECODE_BASE64} > "${pdir}/${domain}.key"
done

View File

@ -1,11 +1,41 @@
[Unit]
Description=Traefik
Documentation=https://doc.traefik.io/traefik/
#After=network-online.target
#AssertFileIsExecutable=/usr/bin/traefik
#AssertPathExists=/etc/traefik/traefik.toml
[Service]
# Run traefik as its own user (create new user with: useradd -r -s /bin/false -U -M traefik)
#User=traefik
#AmbientCapabilities=CAP_NET_BIND_SERVICE
# configure service behavior
Type=notify
ExecStart=/usr/bin/traefik --configFile=/etc/traefik.toml
#ExecStart=/usr/bin/traefik --configFile=/etc/traefik/traefik.toml
Restart=always
WatchdogSec=1s
# lock down system access
# prohibit any operating system and configuration modification
#ProtectSystem=strict
# create separate, new (and empty) /tmp and /var/tmp filesystems
#PrivateTmp=true
# make /home directories inaccessible
#ProtectHome=true
# turns off access to physical devices (/dev/...)
#PrivateDevices=true
# make kernel settings (procfs and sysfs) read-only
#ProtectKernelTunables=true
# make cgroups /sys/fs/cgroup read-only
#ProtectControlGroups=true
# allow writing of acme.json
#ReadWritePaths=/etc/traefik/acme.json
# depending on log and entrypoint configuration, you may need to allow writing to other paths, too
# limit number of processes in this unit
#LimitNPROC=1
[Install]
WantedBy=multi-user.target

View File

@ -1,10 +0,0 @@
FROM alpine:3.7
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/bin
COPY requirements.txt /mkdocs/
WORKDIR /mkdocs
VOLUME /mkdocs
RUN apk --no-cache --no-progress add py-pip \
&& pip install --user -r requirements.txt

1
docs/.dockerignore Normal file
View File

@ -0,0 +1 @@
site/

13
docs/.markdownlint.json Normal file
View File

@ -0,0 +1,13 @@
{
"no-hard-tabs": false,
"MD007": { "indent": 4 },
"MD009": false,
"MD013": false,
"MD024": false,
"MD025": false,
"MD026": false,
"MD033": false,
"MD034": false,
"MD036": false,
"MD046": false
}

View File

@ -1 +0,0 @@
docs.traefik.io

65
docs/Makefile Normal file
View File

@ -0,0 +1,65 @@
#######
# This Makefile contains all targets related to the documentation
#######
DOCS_VERIFY_SKIP ?= false
DOCS_LINT_SKIP ?= false
TRAEFIK_DOCS_BUILD_IMAGE ?= traefik-docs
TRAEFIK_DOCS_CHECK_IMAGE ?= $(TRAEFIK_DOCS_BUILD_IMAGE)-check
SITE_DIR := $(CURDIR)/site
DOCKER_RUN_DOC_PORT := 8000
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
# 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
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:
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)

View File

@ -1,770 +0,0 @@
# Basics
## Concepts
Let's take our example from the [overview](/#overview) again:
> Imagine that you have deployed a bunch of microservices on your infrastructure. You probably used a service registry (like etcd or consul) and/or an orchestrator (swarm, Mesos/Marathon) to manage all these services.
> If you want your users to access some of your microservices from the Internet, you will have to use a reverse proxy and configure it using virtual hosts or prefix paths:
> - domain `api.domain.com` will point the microservice `api` in your private network
> - path `domain.com/web` will point the microservice `web` in your private network
> - domain `backoffice.domain.com` will point the microservices `backoffice` in your private network, load-balancing between your multiple instances
> ![Architecture](img/architecture.png)
Let's zoom on Traefik and have an overview of its internal architecture:
![Architecture](img/internal.png)
- Incoming requests end on [entrypoints](#entrypoints), as the name suggests, they are the network entry points into Traefik (listening port, SSL, traffic redirection...).
- Traffic is then forwarded to a matching [frontend](#frontends). A frontend defines routes from [entrypoints](#entrypoints) to [backends](#backends).
Routes are created using requests fields (`Host`, `Path`, `Headers`...) and can match or not a request.
- The [frontend](#frontends) will then send the request to a [backend](#backends). A backend can be composed by one or more [servers](#servers), and by a load-balancing strategy.
- Finally, the [server](#servers) will forward the request to the corresponding microservice in the private network.
### Entrypoints
Entrypoints are the network entry points into Traefik.
They can be defined using:
- a port (80, 443...)
- SSL (Certificates, Keys, authentication with a client certificate signed by a trusted CA...)
- redirection to another entrypoint (redirect `HTTP` to `HTTPS`)
Here is an example of entrypoints definition:
```toml
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "tests/traefik.crt"
keyFile = "tests/traefik.key"
```
- Two entrypoints are defined `http` and `https`.
- `http` listens on port `80` and `https` on port `443`.
- We enable SSL on `https` by giving a certificate and a key.
- We also redirect all the traffic from entrypoint `http` to `https`.
And here is another example with client certificate authentication:
```toml
[entryPoints]
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[entryPoints.https.tls.ClientCA]
files = ["tests/clientca1.crt", "tests/clientca2.crt"]
optional = false
[[entryPoints.https.tls.certificates]]
certFile = "tests/traefik.crt"
keyFile = "tests/traefik.key"
```
- We enable SSL on `https` by giving a certificate and a key.
- One or several files containing Certificate Authorities in PEM format are added.
- It is possible to have multiple CA:s in the same file or keep them in separate files.
### Frontends
A frontend consists of a set of rules that determine how incoming requests are forwarded from an entrypoint to a backend.
Rules may be classified in one of two groups: Modifiers and matchers.
#### Modifiers
Modifier rules only modify the request. They do not have any impact on routing decisions being made.
Following is the list of existing modifier rules:
- `AddPrefix: /products`: Add path prefix to the existing request path prior to forwarding the request to the backend.
- `ReplacePath: /serverless-path`: Replaces the path and adds the old path to the `X-Replaced-Path` header. Useful for mapping to AWS Lambda or Google Cloud Functions.
- `ReplacePathRegex: ^/api/v2/(.*) /api/$1`: Replaces the path with a regular expression and adds the old path to the `X-Replaced-Path` header. Separate the regular expression and the replacement by a space.
#### Matchers
Matcher rules determine if a particular request should be forwarded to a backend.
Separate multiple rule values by `,` (comma) in order to enable ANY semantics (i.e., forward a request if any rule matches).
Does not work for `Headers` and `HeadersRegexp`.
Separate multiple rule values by `;` (semicolon) in order to enable ALL semantics (i.e., forward a request if all rules match).
Following is the list of existing matcher rules along with examples:
| Matcher | Description |
|------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `Headers: Content-Type, application/json` | Match HTTP header. It accepts a comma-separated key/value pair where both key and value must be literals. |
| `HeadersRegexp: Content-Type, application/(text/json)` | Match HTTP header. It accepts a comma-separated key/value pair where the key must be a literal and the value may be a literal or a regular expression. |
| `Host: traefik.io, www.traefik.io` | Match request host. It accepts a sequence of literal hosts. |
| `HostRegexp: traefik.io, {subdomain:[a-z]+}.traefik.io` | Match request host. It accepts a sequence of literal and regular expression hosts. |
| `Method: GET, POST, PUT` | Match request HTTP method. It accepts a sequence of HTTP methods. |
| `Path: /products/, /articles/{category}/{id:[0-9]+}` | Match exact request path. It accepts a sequence of literal and regular expression paths. |
| `PathStrip: /products/` | Match exact path and strip off the path prior to forwarding the request to the backend. It accepts a sequence of literal paths. |
| `PathStripRegex: /articles/{category}/{id:[0-9]+}` | Match exact path and strip off the path prior to forwarding the request to the backend. It accepts a sequence of literal and regular expression paths. |
| `PathPrefix: /products/, /articles/{category}/{id:[0-9]+}` | Match request prefix path. It accepts a sequence of literal and regular expression prefix paths. |
| `PathPrefixStrip: /products/` | Match request prefix path and strip off the path prefix prior to forwarding the request to the backend. It accepts a sequence of literal prefix paths. Starting with Traefik 1.3, the stripped prefix path will be available in the `X-Forwarded-Prefix` header. |
| `PathPrefixStripRegex: /articles/{category}/{id:[0-9]+}` | Match request prefix path and strip off the path prefix prior to forwarding the request to the backend. It accepts a sequence of literal and regular expression prefix paths. Starting with Traefik 1.3, the stripped prefix path will be available in the `X-Forwarded-Prefix` header. |
| `Query: foo=bar, bar=baz` | Match Query String parameters. It accepts a sequence of key=value pairs. |
In order to use regular expressions with Host and Path matchers, you must declare an arbitrarily named variable followed by the colon-separated regular expression, all enclosed in curly braces. Any pattern supported by [Go's regexp package](https://golang.org/pkg/regexp/) may be used (example: `/posts/{id:[0-9]+}`).
!!! note
The variable has no special meaning; however, it is required by the [gorilla/mux](https://github.com/gorilla/mux) dependency which embeds the regular expression and defines the syntax.
You can optionally enable `passHostHeader` to forward client `Host` header to the backend.
You can also optionally configure the `passTLSClientCert` option to pass the Client certificates to the backend in a specific header.
##### Path Matcher Usage Guidelines
This section explains when to use the various path matchers.
Use `Path` if your backend listens on the exact path only. For instance, `Path: /products` would match `/products` but not `/products/shoes`.
Use a `*Prefix*` matcher if your backend listens on a particular base path but also serves requests on sub-paths.
For instance, `PathPrefix: /products` would match `/products` but also `/products/shoes` and `/products/shirts`.
Since the path is forwarded as-is, your backend is expected to listen on `/products`.
Use a `*Strip` matcher if your backend listens on the root path (`/`) but should be routeable on a specific prefix.
For instance, `PathPrefixStrip: /products` would match `/products` but also `/products/shoes` and `/products/shirts`.
Since the path is stripped prior to forwarding, your backend is expected to listen on `/`.
If your backend is serving assets (e.g., images or Javascript files), chances are it must return properly constructed relative URLs.
Continuing on the 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).
The `X-Forwarded-Prefix` header (available since Traefik 1.3) can be queried to build such URLs dynamically.
Instead of distinguishing your backends by path only, you can add a Host matcher to the mix.
That way, namespacing of your backends happens on the basis of hosts in addition to paths.
#### Examples
Here is an example of frontends definition:
```toml
[frontends]
[frontends.frontend1]
backend = "backend2"
[frontends.frontend1.routes.test_1]
rule = "Host:test.localhost,test2.localhost"
[frontends.frontend2]
backend = "backend1"
passHostHeader = true
[frontends.frontend2.passTLSClientCert]
pem = true
priority = 10
entrypoints = ["https"] # overrides defaultEntryPoints
[frontends.frontend2.routes.test_1]
rule = "HostRegexp:localhost,{subdomain:[a-z]+}.localhost"
[frontends.frontend3]
backend = "backend2"
[frontends.frontend3.routes.test_1]
rule = "Host:test3.localhost;Path:/test"
```
- Three frontends are defined: `frontend1`, `frontend2` and `frontend3`
- `frontend1` will forward the traffic to the `backend2` if the rule `Host:test.localhost,test2.localhost` is matched
- `frontend2` will forward the traffic to the `backend1` if the rule `HostRegexp:localhost,{subdomain:[a-z]+}.localhost` is matched (forwarding client `Host` header to the backend)
- `frontend3` will forward the traffic to the `backend2` if the rules `Host:test3.localhost` **AND** `Path:/test` are matched
#### Combining multiple rules
As seen in the previous example, you can combine multiple rules.
In TOML file, you can use multiple routes:
```toml
[frontends.frontend3]
backend = "backend2"
[frontends.frontend3.routes.test_1]
rule = "Host:test3.localhost"
[frontends.frontend3.routes.test_2]
rule = "Path:/test"
```
Here `frontend3` will forward the traffic to the `backend2` if the rules `Host:test3.localhost` **AND** `Path:/test` are matched.
You can also use the notation using a `;` separator, same result:
```toml
[frontends.frontend3]
backend = "backend2"
[frontends.frontend3.routes.test_1]
rule = "Host:test3.localhost;Path:/test"
```
Finally, you can create a rule to bind multiple domains or Path to a frontend, using the `,` separator:
```toml
[frontends.frontend2]
[frontends.frontend2.routes.test_1]
rule = "Host:test1.localhost,test2.localhost"
[frontends.frontend3]
backend = "backend2"
[frontends.frontend3.routes.test_1]
rule = "Path:/test1,/test2"
```
#### Rules Order
When combining `Modifier` rules with `Matcher` rules, it is important to remember that `Modifier` rules **ALWAYS** apply after the `Matcher` rules.
The following rules are both `Matchers` and `Modifiers`, so the `Matcher` portion of the rule will apply first, and the `Modifier` will apply later.
- `PathStrip`
- `PathStripRegex`
- `PathPrefixStrip`
- `PathPrefixStripRegex`
`Modifiers` will be applied in a pre-determined order regardless of their order in the `rule` configuration section.
1. `PathStrip`
2. `PathPrefixStrip`
3. `PathStripRegex`
4. `PathPrefixStripRegex`
5. `AddPrefix`
6. `ReplacePath`
#### Priorities
By default, routes will be sorted (in descending order) using rules length (to avoid path overlap):
`PathPrefix:/foo;Host:foo.com` (length == 28) will be matched before `PathPrefixStrip:/foobar` (length == 23) will be matched before `PathPrefix:/foo,/bar` (length == 20).
You can customize priority by frontend. The priority value override the rule length during sorting:
```toml
[frontends]
[frontends.frontend1]
backend = "backend1"
priority = 20
passHostHeader = true
[frontends.frontend1.routes.test_1]
rule = "PathPrefix:/to"
[frontends.frontend2]
backend = "backend2"
passHostHeader = true
[frontends.frontend2.routes.test_1]
rule = "PathPrefix:/toto"
```
Here, `frontend1` will be matched before `frontend2` (`20 > 16`).
#### Custom headers
Custom headers can be configured through the frontends, to add headers to either requests or responses that match the frontend's rules.
This allows for setting headers such as `X-Script-Name` to be added to the request, or custom headers to be added to the response.
!!! warning
If the custom header name is the same as one header name of the request or response, it will be replaced.
In this example, all matches to the path `/cheese` will have the `X-Script-Name` header added to the proxied request and the `X-Custom-Response-Header` header added to the response.
```toml
[frontends]
[frontends.frontend1]
backend = "backend1"
[frontends.frontend1.headers.customresponseheaders]
X-Custom-Response-Header = "True"
[frontends.frontend1.headers.customrequestheaders]
X-Script-Name = "test"
[frontends.frontend1.routes.test_1]
rule = "PathPrefixStrip:/cheese"
```
In this second example, all matches to the path `/cheese` will have the `X-Script-Name` header added to the proxied request, the `X-Custom-Request-Header` header removed from the request, and the `X-Custom-Response-Header` header removed from the response.
```toml
[frontends]
[frontends.frontend1]
backend = "backend1"
[frontends.frontend1.headers.customresponseheaders]
X-Custom-Response-Header = ""
[frontends.frontend1.headers.customrequestheaders]
X-Script-Name = "test"
X-Custom-Request-Header = ""
[frontends.frontend1.routes.test_1]
rule = "PathPrefixStrip:/cheese"
```
#### Security headers
Security related headers (HSTS headers, SSL redirection, Browser XSS filter, etc) can be added and configured per frontend in a similar manner to the custom headers above.
This functionality allows for some easy security features to quickly be set.
An example of some of the security headers:
```toml
[frontends]
[frontends.frontend1]
backend = "backend1"
[frontends.frontend1.headers]
FrameDeny = true
[frontends.frontend1.routes.test_1]
rule = "PathPrefixStrip:/cheddar"
[frontends.frontend2]
backend = "backend2"
[frontends.frontend2.headers]
SSLRedirect = true
[frontends.frontend2.routes.test_1]
rule = "PathPrefixStrip:/stilton"
```
In this example, traffic routed through the first frontend will have the `X-Frame-Options` header set to `DENY`, and the second will only allow HTTPS request through, otherwise will return a 301 HTTPS redirect.
!!! note
The detailed documentation for those security headers can be found in [unrolled/secure](https://github.com/unrolled/secure#available-options).
### Backends
A backend is responsible to load-balance the traffic coming from one or more frontends to a set of http servers.
#### Servers
Servers are simply defined using a `url`. You can also apply a custom `weight` to each server (this will be used by load-balancing).
!!! note
Paths in `url` are ignored. Use `Modifier` to specify paths instead.
Here is an example of backends and servers definition:
```toml
[backends]
[backends.backend1]
# ...
[backends.backend1.servers.server1]
url = "http://172.17.0.2:80"
weight = 10
[backends.backend1.servers.server2]
url = "http://172.17.0.3:80"
weight = 1
[backends.backend2]
# ...
[backends.backend2.servers.server1]
url = "https://172.17.0.4:443"
weight = 1
[backends.backend2.servers.server2]
url = "https://172.17.0.5:443"
weight = 2
[backends.backend3]
# ...
[backends.backend3.servers.server1]
url = "h2c://172.17.0.6:80"
weight = 1
```
- Two backends are defined: `backend1` and `backend2`
- `backend1` will forward the traffic to two servers: `172.17.0.2:80` with weight `10` and `172.17.0.3:80` with weight `1`.
- `backend2` will forward the traffic to two servers: `172.17.0.4:443` with weight `1` and `172.17.0.5:443` with weight `2` both using TLS.
- `backend3` will forward the traffic to: `172.17.0.6:80` with weight `1` using HTTP2 without TLS.
#### Load-balancing
Various methods of load-balancing are supported:
- `wrr`: Weighted Round Robin.
- `drr`: Dynamic Round Robin: increases weights on servers that perform better than others.
It also rolls back to original weights if the servers have changed.
#### Circuit breakers
A circuit breaker can also be applied to a backend, preventing high loads on failing servers.
Initial state is Standby. CB observes the statistics and does not modify the request.
In case the condition matches, CB enters Tripped state, where it responds with predefined code or redirects to another frontend.
Once Tripped timer expires, CB enters Recovering state and resets all stats.
In case the condition does not match and recovery timer expires, CB enters Standby state.
It can be configured using:
- Methods: `LatencyAtQuantileMS`, `NetworkErrorRatio`, `ResponseCodeRatio`
- Operators: `AND`, `OR`, `EQ`, `NEQ`, `LT`, `LE`, `GT`, `GE`
For example:
- `NetworkErrorRatio() > 0.5`: watch error ratio over 10 second sliding window for a frontend.
- `LatencyAtQuantileMS(50.0) > 50`: watch latency at quantile in milliseconds.
- `ResponseCodeRatio(500, 600, 0, 600) > 0.5`: ratio of response codes in ranges [500-600) and [0-600).
Here is an example of backends and servers definition:
```toml
[backends]
[backends.backend1]
[backends.backend1.circuitbreaker]
expression = "NetworkErrorRatio() > 0.5"
[backends.backend1.servers.server1]
url = "http://172.17.0.2:80"
weight = 10
[backends.backend1.servers.server2]
url = "http://172.17.0.3:80"
weight = 1
```
- `backend1` will forward the traffic to two servers: `http://172.17.0.2:80"` with weight `10` and `http://172.17.0.3:80` with weight `1` using default `wrr` load-balancing strategy.
- a circuit breaker is added on `backend1` using the expression `NetworkErrorRatio() > 0.5`: watch error ratio over 10 second sliding window
#### Maximum connections
To proactively prevent backends from being overwhelmed with high load, a maximum connection limit can also be applied to each backend.
Maximum connections can be configured by specifying an integer value for `maxconn.amount` and `maxconn.extractorfunc` which is a strategy used to determine how to categorize requests in order to evaluate the maximum connections.
For example:
```toml
[backends]
[backends.backend1]
[backends.backend1.maxconn]
amount = 10
extractorfunc = "request.host"
# ...
```
- `backend1` will return `HTTP code 429 Too Many Requests` if there are already 10 requests in progress for the same Host header.
- Another possible value for `extractorfunc` is `client.ip` which will categorize requests based on client source ip.
- Lastly `extractorfunc` can take the value of `request.header.ANY_HEADER` which will categorize requests based on `ANY_HEADER` that you provide.
#### Sticky sessions
Sticky sessions are supported with both load balancers.
When sticky sessions are enabled, a cookie is set on the initial request.
The default cookie name is an abbreviation of a sha1 (ex: `_1d52e`).
On subsequent requests, the client will be directed to the backend stored in the cookie if it is still healthy.
If not, a new backend will be assigned.
```toml
[backends]
[backends.backend1]
# Enable sticky session
[backends.backend1.loadbalancer.stickiness]
# Customize the cookie name
#
# Optional
# Default: a sha1 (6 chars)
#
# cookieName = "my_cookie"
```
The deprecated way:
```toml
[backends]
[backends.backend1]
[backends.backend1.loadbalancer]
sticky = true
```
#### Health Check
A health check can be configured in order to remove a backend from LB rotation as long as it keeps returning HTTP status codes other than `2xx` or `3xx` to HTTP GET requests periodically carried out by Traefik.
The check is defined by a path appended to the backend URL and an interval (given in a format understood by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration)) specifying how often the health check should be executed (the default being 30 seconds).
Each backend must respond to the health check within 5 seconds.
By default, the port of the backend server is used, however, this may be overridden.
A recovering backend returning `2xx` or `3xx` responses again is being returned to the LB rotation pool.
For example:
```toml
[backends]
[backends.backend1]
[backends.backend1.healthcheck]
path = "/health"
interval = "10s"
```
To use a different port for the health check:
```toml
[backends]
[backends.backend1]
[backends.backend1.healthcheck]
path = "/health"
interval = "10s"
port = 8080
```
To use a different scheme for the health check:
```toml
[backends]
[backends.backend1]
[backends.backend1.healthcheck]
path = "/health"
interval = "10s"
scheme = "http"
```
Additional http headers and hostname to health check request can be specified, for instance:
```toml
[backends]
[backends.backend1]
[backends.backend1.healthcheck]
path = "/health"
interval = "10s"
hostname = "myhost.com"
port = 8080
[backends.backend1.healthcheck.headers]
My-Custom-Header = "foo"
My-Header = "bar"
```
## Configuration
Traefik's configuration has two parts:
- The [static Traefik configuration](/basics#static-traefik-configuration) which is loaded only at the beginning.
- The [dynamic Traefik configuration](/basics#dynamic-traefik-configuration) which can be hot-reloaded (no need to restart the process).
### Static Traefik configuration
The static configuration is the global configuration which is setting up connections to configuration backends and entrypoints.
Traefik can be configured using many configuration sources with the following precedence order.
Each item takes precedence over the item below it:
- [Key-value store](/basics/#key-value-stores)
- [Arguments](/basics/#arguments)
- [Configuration file](/basics/#configuration-file)
- Default
It means that arguments override configuration file, and key-value store overrides arguments.
!!! note
the provider-enabling argument parameters (e.g., `--docker`) set all default values for the specific provider.
It must not be used if a configuration source with less precedence wants to set a non-default provider value.
#### Configuration file
By default, Traefik will try to find a `traefik.toml` in the following places:
- `/etc/traefik/`
- `$HOME/.traefik/`
- `.` _the working directory_
You can override this by setting a `configFile` argument:
```bash
traefik --configFile=foo/bar/myconfigfile.toml
```
Please refer to the [global configuration](/configuration/commons) section to get documentation on it.
#### Arguments
Each argument (and command) is described in the help section:
```bash
traefik --help
```
Note that all default values will be displayed as well.
#### Key-value stores
Traefik supports several Key-value stores:
- [Consul](https://consul.io)
- [etcd](https://coreos.com/etcd/)
- [ZooKeeper](https://zookeeper.apache.org/)
- [boltdb](https://github.com/boltdb/bolt)
Please refer to the [User Guide Key-value store configuration](/user-guide/kv-config/) section to get documentation on it.
### Dynamic Traefik configuration
The dynamic configuration concerns :
- [Frontends](/basics/#frontends)
- [Backends](/basics/#backends)
- [Servers](/basics/#servers)
- HTTPS Certificates
Traefik can hot-reload those rules which could be provided by [multiple configuration backends](/configuration/commons).
We only need to enable `watch` option to make Traefik watch configuration backend changes and generate its configuration automatically.
Routes to services will be created and updated instantly at any changes.
Please refer to the [configuration backends](/configuration/commons) section to get documentation on it.
## Commands
### traefik
Usage:
```bash
traefik [command] [--flag=flag_argument]
```
List of Traefik available commands with description :
- `version` : Print version
- `storeconfig` : Store the static Traefik configuration into a Key-value stores. Please refer to the [Store Traefik configuration](/user-guide/kv-config/#store-configuration-in-key-value-store) section to get documentation on it.
- `bug`: The easiest way to submit a pre-filled issue.
- `healthcheck`: Calls Traefik `/ping` to check health.
Each command may have related flags.
All those related flags will be displayed with :
```bash
traefik [command] --help
```
Each command is described at the beginning of the help section:
```bash
traefik --help
# or
docker run traefik[:version] --help
# ex: docker run traefik:1.5 --help
```
### Command: bug
Here is the easiest way to submit a pre-filled issue on [Traefik GitHub](https://github.com/containous/traefik).
```bash
traefik bug
```
Watch [this demo](https://www.youtube.com/watch?v=Lyz62L8m93I).
### Command: healthcheck
This command allows to check the health of Traefik. Its exit status is `0` if Traefik is healthy and `1` if it is unhealthy.
This can be used with Docker [HEALTHCHECK](https://docs.docker.com/engine/reference/builder/#healthcheck) instruction or any other health check orchestration mechanism.
!!! note
The [`ping`](/configuration/ping) must be enabled to allow the `healthcheck` command to call `/ping`.
```bash
traefik healthcheck
```
```bash
OK: http://:8082/ping
```
## Collected Data
**This feature is disabled by default.**
You can read the public proposal on this topic [here](https://github.com/containous/traefik/issues/2369).
### Why ?
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 more important (for example, which configuration backend is used and which is not used).
### What ?
Once a day (the first call begins 10 minutes after the start of Traefik), we collect:
- the Traefik version
- a hash of the configuration
- an **anonymous version** of the static configuration:
- token, user name, password, URL, IP, domain, email, etc, are removed
!!! note
We do not collect the dynamic configuration (frontends & backends).
!!! note
We do not collect data behind the scenes to run advertising programs or to sell such data to third-party.
#### Here is an example
- Source configuration:
```toml
[entryPoints]
[entryPoints.http]
address = ":80"
[api]
[Docker]
endpoint = "tcp://10.10.10.10:2375"
domain = "foo.bir"
exposedByDefault = true
swarmMode = true
[Docker.TLS]
ca = "dockerCA"
cert = "dockerCert"
key = "dockerKey"
insecureSkipVerify = true
[ECS]
domain = "foo.bar"
exposedByDefault = true
clusters = ["foo-bar"]
region = "us-west-2"
accessKeyID = "AccessKeyID"
secretAccessKey = "SecretAccessKey"
```
- Obfuscated and anonymous configuration:
```toml
[entryPoints]
[entryPoints.http]
address = ":80"
[api]
[Docker]
endpoint = "xxxx"
domain = "xxxx"
exposedByDefault = true
swarmMode = true
[Docker.TLS]
ca = "xxxx"
cert = "xxxx"
key = "xxxx"
insecureSkipVerify = false
[ECS]
domain = "xxxx"
exposedByDefault = true
clusters = []
region = "us-west-2"
accessKeyID = "xxxx"
secretAccessKey = "xxxx"
```
### Show me the code !
If you want to dig into more details, here is the source code of the collecting system: [collector.go](https://github.com/containous/traefik/blob/master/collector/collector.go)
By default we anonymize all configuration fields, except fields tagged with `export=true`.
You can check all fields in the [godoc](https://godoc.org/github.com/containous/traefik/configuration#GlobalConfiguration).
### How to enable this ?
You can enable the collecting system by:
- adding this line in the configuration TOML file:
```toml
# Send anonymous usage data
#
# Optional
# Default: false
#
sendAnonymousUsage = true
```
- adding this flag in the CLI:
```bash
./traefik --sendAnonymousUsage=true
```

View File

@ -1,214 +0,0 @@
# Benchmarks
## Configuration
I would like to thanks [vincentbernat](https://github.com/vincentbernat) from [exoscale.ch](https://www.exoscale.ch) who kindly provided the infrastructure needed for the benchmarks.
I used 4 VMs for the tests with the following configuration:
- 32 GB RAM
- 8 CPU Cores
- 10 GB SSD
- Ubuntu 14.04 LTS 64-bit
## Setup
1. One VM used to launch the benchmarking tool [wrk](https://github.com/wg/wrk)
2. One VM for Traefik (v1.0.0-beta.416) / nginx (v1.4.6)
3. Two VMs for 2 backend servers in go [whoami](https://github.com/containous/whoami/)
Each VM has been tuned using the following limits:
```bash
sysctl -w fs.file-max="9999999"
sysctl -w fs.nr_open="9999999"
sysctl -w net.core.netdev_max_backlog="4096"
sysctl -w net.core.rmem_max="16777216"
sysctl -w net.core.somaxconn="65535"
sysctl -w net.core.wmem_max="16777216"
sysctl -w net.ipv4.ip_local_port_range="1025 65535"
sysctl -w net.ipv4.tcp_fin_timeout="30"
sysctl -w net.ipv4.tcp_keepalive_time="30"
sysctl -w net.ipv4.tcp_max_syn_backlog="20480"
sysctl -w net.ipv4.tcp_max_tw_buckets="400000"
sysctl -w net.ipv4.tcp_no_metrics_save="1"
sysctl -w net.ipv4.tcp_syn_retries="2"
sysctl -w net.ipv4.tcp_synack_retries="2"
sysctl -w net.ipv4.tcp_tw_recycle="1"
sysctl -w net.ipv4.tcp_tw_reuse="1"
sysctl -w vm.min_free_kbytes="65536"
sysctl -w vm.overcommit_memory="1"
ulimit -n 9999999
```
### Nginx
Here is the config Nginx file use `/etc/nginx/nginx.conf`:
```
user www-data;
worker_processes auto;
worker_rlimit_nofile 200000;
pid /var/run/nginx.pid;
events {
worker_connections 10000;
use epoll;
multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 300;
keepalive_requests 10000;
types_hash_max_size 2048;
open_file_cache max=200000 inactive=300s;
open_file_cache_valid 300s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
server_tokens off;
dav_methods off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log combined;
error_log /var/log/nginx/error.log warn;
gzip off;
gzip_vary off;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*.conf;
}
```
Here is the Nginx vhost file used:
```
upstream whoami {
server IP-whoami1:80;
server IP-whoami2:80;
keepalive 300;
}
server {
listen 8001;
server_name test.traefik;
access_log off;
error_log /dev/null crit;
if ($host != "test.traefik") {
return 404;
}
location / {
proxy_pass http://whoami;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header X-Forwarded-Host $host;
}
}
```
### Traefik
Here is the `traefik.toml` file used:
```toml
maxIdleConnsPerHost = 100000
defaultEntryPoints = ["http"]
[entryPoints]
[entryPoints.http]
address = ":8000"
[file]
[backends]
[backends.backend1]
[backends.backend1.servers.server1]
url = "http://IP-whoami1:80"
weight = 1
[backends.backend1.servers.server2]
url = "http://IP-whoami2:80"
weight = 1
[frontends]
[frontends.frontend1]
backend = "backend1"
[frontends.frontend1.routes.test_1]
rule = "Host: test.traefik"
```
## Results
### whoami:
```shell
wrk -t20 -c1000 -d60s -H "Host: test.traefik" --latency http://IP-whoami:80/bench
Running 1m test @ http://IP-whoami:80/bench
20 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 70.28ms 134.72ms 1.91s 89.94%
Req/Sec 2.92k 742.42 8.78k 68.80%
Latency Distribution
50% 10.63ms
75% 75.64ms
90% 205.65ms
99% 668.28ms
3476705 requests in 1.00m, 384.61MB read
Socket errors: connect 0, read 0, write 0, timeout 103
Requests/sec: 57894.35
Transfer/sec: 6.40MB
```
### nginx:
```shell
wrk -t20 -c1000 -d60s -H "Host: test.traefik" --latency http://IP-nginx:8001/bench
Running 1m test @ http://IP-nginx:8001/bench
20 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 101.25ms 180.09ms 1.99s 89.34%
Req/Sec 1.69k 567.69 9.39k 72.62%
Latency Distribution
50% 15.46ms
75% 129.11ms
90% 302.44ms
99% 846.59ms
2018427 requests in 1.00m, 298.36MB read
Socket errors: connect 0, read 0, write 0, timeout 90
Requests/sec: 33591.67
Transfer/sec: 4.97MB
```
### Traefik:
```shell
wrk -t20 -c1000 -d60s -H "Host: test.traefik" --latency http://IP-traefik:8000/bench
Running 1m test @ http://IP-traefik:8000/bench
20 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 91.72ms 150.43ms 2.00s 90.50%
Req/Sec 1.43k 266.37 2.97k 69.77%
Latency Distribution
50% 19.74ms
75% 121.98ms
90% 237.39ms
99% 687.49ms
1705073 requests in 1.00m, 188.63MB read
Socket errors: connect 0, read 0, write 0, timeout 7
Requests/sec: 28392.44
Transfer/sec: 3.14MB
```
## Conclusion
Traefik is obviously slower than Nginx, but not so much: Traefik can serve 28392 requests/sec and Nginx 33591 requests/sec which gives a ratio of 85%.
Not bad for young project :) !
Some areas of possible improvements:
- Use [GO_REUSEPORT](https://github.com/kavu/go_reuseport) listener
- Run a separate server instance per CPU core with `GOMAXPROCS=1` (it appears during benchmarks that there is a lot more context switches with Traefik than with nginx)

41
docs/check.Dockerfile Normal file
View File

@ -0,0 +1,41 @@
FROM alpine:3.22
RUN apk --no-cache --no-progress add \
build-base \
gcompat \
libcurl \
libxml2-dev \
libxslt-dev \
ruby \
ruby-bigdecimal \
ruby-dev \
ruby-ffi \
zlib-dev
RUN gem install nokogiri --version 1.18.6 --no-document -- --use-system-libraries
RUN gem install html-proofer --version 5.0.10 --no-document -- --use-system-libraries
# After Ruby, some NodeJS YAY!
RUN apk --no-cache --no-progress add \
git \
nodejs \
npm
RUN npm install --global \
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
RUN apk --no-cache --no-progress add \
ca-certificates \
curl \
tini
COPY ./scripts/verify.sh /verify.sh
COPY ./scripts/lint.sh /lint.sh
WORKDIR /app
VOLUME ["/tmp","/app"]
ENTRYPOINT ["/sbin/tini","-g","sh"]

Some files were not shown because too many files have changed in this diff Show More