Add a new protocol

Co-authored-by: Gérald Croës <gerald@containo.us>
This commit is contained in:
Julien Salleyron 2019-03-14 09:30:04 +01:00 committed by Traefiker Bot
parent 0ca2149408
commit 4a68d29ce2
231 changed files with 6895 additions and 4395 deletions

View file

@ -58,7 +58,6 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t
- Supports multiple load balancing algorithms - Supports multiple load balancing algorithms
- Provides HTTPS to your microservices by leveraging [Let's Encrypt](https://letsencrypt.org) (wildcard certificates support) - Provides HTTPS to your microservices by leveraging [Let's Encrypt](https://letsencrypt.org) (wildcard certificates support)
- Circuit breakers, retry - Circuit breakers, retry
- High Availability with cluster mode (beta)
- See the magic through its clean web UI - See the magic through its clean web UI
- Websocket, HTTP/2, GRPC ready - Websocket, HTTP/2, GRPC ready
- Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB) - Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB)

View file

@ -1,15 +1,14 @@
package anonymize package anonymize
import ( import (
"crypto/tls"
"os" "os"
"testing" "testing"
"time" "time"
"github.com/containous/flaeg/parse" "github.com/containous/flaeg/parse"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/config/static" "github.com/containous/traefik/config/static"
"github.com/containous/traefik/provider" "github.com/containous/traefik/provider"
"github.com/containous/traefik/provider/acme"
acmeprovider "github.com/containous/traefik/provider/acme" acmeprovider "github.com/containous/traefik/provider/acme"
"github.com/containous/traefik/provider/file" "github.com/containous/traefik/provider/file"
traefiktls "github.com/containous/traefik/tls" traefiktls "github.com/containous/traefik/tls"
@ -45,14 +44,6 @@ func TestDo_globalConfiguration(t *testing.T) {
IdleTimeout: parse.Duration(111 * time.Second), IdleTimeout: parse.Duration(111 * time.Second),
}, },
}, },
TLS: &traefiktls.TLS{
MinVersion: "foo MinVersion",
CipherSuites: []string{"foo CipherSuites 1", "foo CipherSuites 2", "foo CipherSuites 3"},
ClientCA: traefiktls.ClientCA{
Files: traefiktls.FilesOrContents{"foo ClientCAFiles 1", "foo ClientCAFiles 2", "foo ClientCAFiles 3"},
Optional: false,
},
},
ProxyProtocol: &static.ProxyProtocol{ ProxyProtocol: &static.ProxyProtocol{
TrustedIPs: []string{"127.0.0.1/32", "192.168.0.1"}, TrustedIPs: []string{"127.0.0.1/32", "192.168.0.1"},
}, },
@ -66,20 +57,12 @@ func TestDo_globalConfiguration(t *testing.T) {
IdleTimeout: parse.Duration(111 * time.Second), IdleTimeout: parse.Duration(111 * time.Second),
}, },
}, },
TLS: &traefiktls.TLS{
MinVersion: "fii MinVersion",
CipherSuites: []string{"fii CipherSuites 1", "fii CipherSuites 2", "fii CipherSuites 3"},
ClientCA: traefiktls.ClientCA{
Files: traefiktls.FilesOrContents{"fii ClientCAFiles 1", "fii ClientCAFiles 2", "fii ClientCAFiles 3"},
Optional: false,
},
},
ProxyProtocol: &static.ProxyProtocol{ ProxyProtocol: &static.ProxyProtocol{
TrustedIPs: []string{"127.0.0.1/32", "192.168.0.1"}, TrustedIPs: []string{"127.0.0.1/32", "192.168.0.1"},
}, },
}, },
} }
config.ACME = &acme.ACME{ config.ACME = &acme.Configuration{
Email: "acme Email", Email: "acme Email",
Domains: []types.Domain{ Domains: []types.Domain{
{ {
@ -88,16 +71,11 @@ func TestDo_globalConfiguration(t *testing.T) {
}, },
}, },
Storage: "Storage", Storage: "Storage",
OnDemand: true,
OnHostRule: true, OnHostRule: true,
CAServer: "CAServer", CAServer: "CAServer",
EntryPoint: "EntryPoint", EntryPoint: "EntryPoint",
DNSChallenge: &acmeprovider.DNSChallenge{Provider: "DNSProvider"}, DNSChallenge: &acmeprovider.DNSChallenge{Provider: "DNSProvider"},
ACMELogging: true, ACMELogging: true,
TLSConfig: &tls.Config{
InsecureSkipVerify: true,
// ...
},
} }
config.Providers = &static.Providers{ config.Providers = &static.Providers{
ProvidersThrottleDuration: parse.Duration(111 * time.Second), ProvidersThrottleDuration: parse.Duration(111 * time.Second),

View file

@ -58,7 +58,7 @@ func Test_doOnJSON(t *testing.T) {
"DNSProvider": "", "DNSProvider": "",
"DelayDontCheckDNS": 0, "DelayDontCheckDNS": 0,
"ACMELogging": false, "ACMELogging": false,
"TLSConfig": null "TLSOptions": null
}, },
"DefaultEntryPoints": [ "DefaultEntryPoints": [
"https", "https",
@ -141,7 +141,7 @@ func Test_doOnJSON(t *testing.T) {
"DNSProvider": "", "DNSProvider": "",
"DelayDontCheckDNS": 0, "DelayDontCheckDNS": 0,
"ACMELogging": false, "ACMELogging": false,
"TLSConfig": null "TLSOptions": null
}, },
"DefaultEntryPoints": [ "DefaultEntryPoints": [
"https", "https",

View file

@ -65,19 +65,20 @@ type jsonRenderer interface {
} }
// Append add api routes on a router // Append add api routes on a router
func (p Handler) Append(router *mux.Router) { func (h Handler) Append(router *mux.Router) {
if p.Debug { if h.Debug {
DebugHandler{}.Append(router) DebugHandler{}.Append(router)
} }
router.Methods(http.MethodGet).Path("/api/providers").HandlerFunc(p.getProvidersHandler) router.Methods(http.MethodGet).Path("/api/rawdata").HandlerFunc(h.getRawData)
router.Methods(http.MethodGet).Path("/api/providers/{provider}").HandlerFunc(p.getProviderHandler) router.Methods(http.MethodGet).Path("/api/providers").HandlerFunc(h.getProvidersHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/routers").HandlerFunc(p.getRoutersHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}").HandlerFunc(h.getProviderHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/routers/{router}").HandlerFunc(p.getRouterHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}/routers").HandlerFunc(h.getRoutersHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/middlewares").HandlerFunc(p.getMiddlewaresHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}/routers/{router}").HandlerFunc(h.getRouterHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/middlewares/{middleware}").HandlerFunc(p.getMiddlewareHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}/middlewares").HandlerFunc(h.getMiddlewaresHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/services").HandlerFunc(p.getServicesHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}/middlewares/{middleware}").HandlerFunc(h.getMiddlewareHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/services/{service}").HandlerFunc(p.getServiceHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}/services").HandlerFunc(h.getServicesHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/services/{service}").HandlerFunc(h.getServiceHandler)
// FIXME stats // FIXME stats
// health route // health route
@ -85,15 +86,30 @@ func (p Handler) Append(router *mux.Router) {
version.Handler{}.Append(router) version.Handler{}.Append(router)
if p.Dashboard { if h.Dashboard {
DashboardHandler{Assets: p.DashboardAssets}.Append(router) DashboardHandler{Assets: h.DashboardAssets}.Append(router)
} }
} }
func (p Handler) getProvidersHandler(rw http.ResponseWriter, request *http.Request) { func (h Handler) getRawData(rw http.ResponseWriter, request *http.Request) {
if h.CurrentConfigurations != nil {
currentConfigurations, ok := h.CurrentConfigurations.Get().(config.Configurations)
if !ok {
rw.WriteHeader(http.StatusOK)
return
}
err := templateRenderer.JSON(rw, http.StatusOK, currentConfigurations)
if err != nil {
log.FromContext(request.Context()).Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
}
}
}
func (h Handler) getProvidersHandler(rw http.ResponseWriter, request *http.Request) {
// FIXME handle currentConfiguration // FIXME handle currentConfiguration
if p.CurrentConfigurations != nil { if h.CurrentConfigurations != nil {
currentConfigurations, ok := p.CurrentConfigurations.Get().(config.Configurations) currentConfigurations, ok := h.CurrentConfigurations.Get().(config.Configurations)
if !ok { if !ok {
rw.WriteHeader(http.StatusOK) rw.WriteHeader(http.StatusOK)
return return
@ -115,10 +131,10 @@ func (p Handler) getProvidersHandler(rw http.ResponseWriter, request *http.Reque
} }
} }
func (p Handler) getProviderHandler(rw http.ResponseWriter, request *http.Request) { func (h Handler) getProviderHandler(rw http.ResponseWriter, request *http.Request) {
providerID := mux.Vars(request)["provider"] providerID := mux.Vars(request)["provider"]
currentConfigurations := p.CurrentConfigurations.Get().(config.Configurations) currentConfigurations := h.CurrentConfigurations.Get().(config.Configurations)
provider, ok := currentConfigurations[providerID] provider, ok := currentConfigurations[providerID]
if !ok { if !ok {
@ -126,8 +142,13 @@ func (p Handler) getProviderHandler(rw http.ResponseWriter, request *http.Reques
return return
} }
if provider.HTTP == nil {
http.NotFound(rw, request)
return
}
var routers []ResourceIdentifier var routers []ResourceIdentifier
for name := range provider.Routers { for name := range provider.HTTP.Routers {
routers = append(routers, ResourceIdentifier{ routers = append(routers, ResourceIdentifier{
ID: name, ID: name,
Path: "/api/providers/" + providerID + "/routers", Path: "/api/providers/" + providerID + "/routers",
@ -135,7 +156,7 @@ func (p Handler) getProviderHandler(rw http.ResponseWriter, request *http.Reques
} }
var services []ResourceIdentifier var services []ResourceIdentifier
for name := range provider.Services { for name := range provider.HTTP.Services {
services = append(services, ResourceIdentifier{ services = append(services, ResourceIdentifier{
ID: name, ID: name,
Path: "/api/providers/" + providerID + "/services", Path: "/api/providers/" + providerID + "/services",
@ -143,7 +164,7 @@ func (p Handler) getProviderHandler(rw http.ResponseWriter, request *http.Reques
} }
var middlewares []ResourceIdentifier var middlewares []ResourceIdentifier
for name := range provider.Middlewares { for name := range provider.HTTP.Middlewares {
middlewares = append(middlewares, ResourceIdentifier{ middlewares = append(middlewares, ResourceIdentifier{
ID: name, ID: name,
Path: "/api/providers/" + providerID + "/middlewares", Path: "/api/providers/" + providerID + "/middlewares",
@ -159,10 +180,10 @@ func (p Handler) getProviderHandler(rw http.ResponseWriter, request *http.Reques
} }
} }
func (p Handler) getRoutersHandler(rw http.ResponseWriter, request *http.Request) { func (h Handler) getRoutersHandler(rw http.ResponseWriter, request *http.Request) {
providerID := mux.Vars(request)["provider"] providerID := mux.Vars(request)["provider"]
currentConfigurations := p.CurrentConfigurations.Get().(config.Configurations) currentConfigurations := h.CurrentConfigurations.Get().(config.Configurations)
provider, ok := currentConfigurations[providerID] provider, ok := currentConfigurations[providerID]
if !ok { if !ok {
@ -170,8 +191,13 @@ func (p Handler) getRoutersHandler(rw http.ResponseWriter, request *http.Request
return return
} }
if provider.HTTP == nil {
http.NotFound(rw, request)
return
}
var routers []RouterRepresentation var routers []RouterRepresentation
for name, router := range provider.Routers { for name, router := range provider.HTTP.Routers {
routers = append(routers, RouterRepresentation{Router: router, ID: name}) routers = append(routers, RouterRepresentation{Router: router, ID: name})
} }
@ -182,11 +208,11 @@ func (p Handler) getRoutersHandler(rw http.ResponseWriter, request *http.Request
} }
} }
func (p Handler) getRouterHandler(rw http.ResponseWriter, request *http.Request) { func (h Handler) getRouterHandler(rw http.ResponseWriter, request *http.Request) {
providerID := mux.Vars(request)["provider"] providerID := mux.Vars(request)["provider"]
routerID := mux.Vars(request)["router"] routerID := mux.Vars(request)["router"]
currentConfigurations := p.CurrentConfigurations.Get().(config.Configurations) currentConfigurations := h.CurrentConfigurations.Get().(config.Configurations)
provider, ok := currentConfigurations[providerID] provider, ok := currentConfigurations[providerID]
if !ok { if !ok {
@ -194,7 +220,12 @@ func (p Handler) getRouterHandler(rw http.ResponseWriter, request *http.Request)
return return
} }
router, ok := provider.Routers[routerID] if provider.HTTP == nil {
http.NotFound(rw, request)
return
}
router, ok := provider.HTTP.Routers[routerID]
if !ok { if !ok {
http.NotFound(rw, request) http.NotFound(rw, request)
return return
@ -207,10 +238,10 @@ func (p Handler) getRouterHandler(rw http.ResponseWriter, request *http.Request)
} }
} }
func (p Handler) getMiddlewaresHandler(rw http.ResponseWriter, request *http.Request) { func (h Handler) getMiddlewaresHandler(rw http.ResponseWriter, request *http.Request) {
providerID := mux.Vars(request)["provider"] providerID := mux.Vars(request)["provider"]
currentConfigurations := p.CurrentConfigurations.Get().(config.Configurations) currentConfigurations := h.CurrentConfigurations.Get().(config.Configurations)
provider, ok := currentConfigurations[providerID] provider, ok := currentConfigurations[providerID]
if !ok { if !ok {
@ -218,8 +249,13 @@ func (p Handler) getMiddlewaresHandler(rw http.ResponseWriter, request *http.Req
return return
} }
if provider.HTTP == nil {
http.NotFound(rw, request)
return
}
var middlewares []MiddlewareRepresentation var middlewares []MiddlewareRepresentation
for name, middleware := range provider.Middlewares { for name, middleware := range provider.HTTP.Middlewares {
middlewares = append(middlewares, MiddlewareRepresentation{Middleware: middleware, ID: name}) middlewares = append(middlewares, MiddlewareRepresentation{Middleware: middleware, ID: name})
} }
@ -230,11 +266,11 @@ func (p Handler) getMiddlewaresHandler(rw http.ResponseWriter, request *http.Req
} }
} }
func (p Handler) getMiddlewareHandler(rw http.ResponseWriter, request *http.Request) { func (h Handler) getMiddlewareHandler(rw http.ResponseWriter, request *http.Request) {
providerID := mux.Vars(request)["provider"] providerID := mux.Vars(request)["provider"]
middlewareID := mux.Vars(request)["middleware"] middlewareID := mux.Vars(request)["middleware"]
currentConfigurations := p.CurrentConfigurations.Get().(config.Configurations) currentConfigurations := h.CurrentConfigurations.Get().(config.Configurations)
provider, ok := currentConfigurations[providerID] provider, ok := currentConfigurations[providerID]
if !ok { if !ok {
@ -242,7 +278,12 @@ func (p Handler) getMiddlewareHandler(rw http.ResponseWriter, request *http.Requ
return return
} }
middleware, ok := provider.Middlewares[middlewareID] if provider.HTTP == nil {
http.NotFound(rw, request)
return
}
middleware, ok := provider.HTTP.Middlewares[middlewareID]
if !ok { if !ok {
http.NotFound(rw, request) http.NotFound(rw, request)
return return
@ -255,10 +296,10 @@ func (p Handler) getMiddlewareHandler(rw http.ResponseWriter, request *http.Requ
} }
} }
func (p Handler) getServicesHandler(rw http.ResponseWriter, request *http.Request) { func (h Handler) getServicesHandler(rw http.ResponseWriter, request *http.Request) {
providerID := mux.Vars(request)["provider"] providerID := mux.Vars(request)["provider"]
currentConfigurations := p.CurrentConfigurations.Get().(config.Configurations) currentConfigurations := h.CurrentConfigurations.Get().(config.Configurations)
provider, ok := currentConfigurations[providerID] provider, ok := currentConfigurations[providerID]
if !ok { if !ok {
@ -266,8 +307,13 @@ func (p Handler) getServicesHandler(rw http.ResponseWriter, request *http.Reques
return return
} }
if provider.HTTP == nil {
http.NotFound(rw, request)
return
}
var services []ServiceRepresentation var services []ServiceRepresentation
for name, service := range provider.Services { for name, service := range provider.HTTP.Services {
services = append(services, ServiceRepresentation{Service: service, ID: name}) services = append(services, ServiceRepresentation{Service: service, ID: name})
} }
@ -278,11 +324,11 @@ func (p Handler) getServicesHandler(rw http.ResponseWriter, request *http.Reques
} }
} }
func (p Handler) getServiceHandler(rw http.ResponseWriter, request *http.Request) { func (h Handler) getServiceHandler(rw http.ResponseWriter, request *http.Request) {
providerID := mux.Vars(request)["provider"] providerID := mux.Vars(request)["provider"]
serviceID := mux.Vars(request)["service"] serviceID := mux.Vars(request)["service"]
currentConfigurations := p.CurrentConfigurations.Get().(config.Configurations) currentConfigurations := h.CurrentConfigurations.Get().(config.Configurations)
provider, ok := currentConfigurations[providerID] provider, ok := currentConfigurations[providerID]
if !ok { if !ok {
@ -290,7 +336,12 @@ func (p Handler) getServiceHandler(rw http.ResponseWriter, request *http.Request
return return
} }
service, ok := provider.Services[serviceID] if provider.HTTP == nil {
http.NotFound(rw, request)
return
}
service, ok := provider.HTTP.Services[serviceID]
if !ok { if !ok {
http.NotFound(rw, request) http.NotFound(rw, request)
return return

View file

@ -30,11 +30,13 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers", path: "/api/providers",
configuration: config.Configurations{ configuration: config.Configurations{
"foo": { "foo": {
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{ Routers: map[string]*config.Router{
"bar": {EntryPoints: []string{"foo", "bar"}}, "bar": {EntryPoints: []string{"foo", "bar"}},
}, },
}, },
}, },
},
expected: expected{statusCode: http.StatusOK, body: `[{"id":"foo","path":"/api/providers/foo"}]`}, expected: expected{statusCode: http.StatusOK, body: `[{"id":"foo","path":"/api/providers/foo"}]`},
}, },
{ {
@ -42,6 +44,7 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers/foo", path: "/api/providers/foo",
configuration: config.Configurations{ configuration: config.Configurations{
"foo": { "foo": {
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{ Routers: map[string]*config.Router{
"bar": {EntryPoints: []string{"foo", "bar"}}, "bar": {EntryPoints: []string{"foo", "bar"}},
}, },
@ -59,6 +62,7 @@ func TestHandler_Configuration(t *testing.T) {
}, },
}, },
}, },
},
expected: expected{statusCode: http.StatusOK, body: `{"routers":[{"id":"bar","path":"/api/providers/foo/routers"}],"middlewares":[{"id":"bar","path":"/api/providers/foo/middlewares"}],"services":[{"id":"foo","path":"/api/providers/foo/services"}]}`}, expected: expected{statusCode: http.StatusOK, body: `{"routers":[{"id":"bar","path":"/api/providers/foo/routers"}],"middlewares":[{"id":"bar","path":"/api/providers/foo/middlewares"}],"services":[{"id":"foo","path":"/api/providers/foo/services"}]}`},
}, },
{ {
@ -72,11 +76,13 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers/foo/routers", path: "/api/providers/foo/routers",
configuration: config.Configurations{ configuration: config.Configurations{
"foo": { "foo": {
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{ Routers: map[string]*config.Router{
"bar": {EntryPoints: []string{"foo", "bar"}}, "bar": {EntryPoints: []string{"foo", "bar"}},
}, },
}, },
}, },
},
expected: expected{statusCode: http.StatusOK, body: `[{"entryPoints":["foo","bar"],"id":"bar"}]`}, expected: expected{statusCode: http.StatusOK, body: `[{"entryPoints":["foo","bar"],"id":"bar"}]`},
}, },
{ {
@ -84,11 +90,13 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers/foo/routers/bar", path: "/api/providers/foo/routers/bar",
configuration: config.Configurations{ configuration: config.Configurations{
"foo": { "foo": {
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{ Routers: map[string]*config.Router{
"bar": {EntryPoints: []string{"foo", "bar"}}, "bar": {EntryPoints: []string{"foo", "bar"}},
}, },
}, },
}, },
},
expected: expected{statusCode: http.StatusOK, body: `{"entryPoints":["foo","bar"]}`}, expected: expected{statusCode: http.StatusOK, body: `{"entryPoints":["foo","bar"]}`},
}, },
{ {
@ -104,6 +112,7 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers/foo/services", path: "/api/providers/foo/services",
configuration: config.Configurations{ configuration: config.Configurations{
"foo": { "foo": {
HTTP: &config.HTTPConfiguration{
Services: map[string]*config.Service{ Services: map[string]*config.Service{
"foo": { "foo": {
LoadBalancer: &config.LoadBalancerService{ LoadBalancer: &config.LoadBalancerService{
@ -113,6 +122,7 @@ func TestHandler_Configuration(t *testing.T) {
}, },
}, },
}, },
},
expected: expected{statusCode: http.StatusOK, body: `[{"loadbalancer":{"method":"wrr","passHostHeader":false},"id":"foo"}]`}, expected: expected{statusCode: http.StatusOK, body: `[{"loadbalancer":{"method":"wrr","passHostHeader":false},"id":"foo"}]`},
}, },
{ {
@ -120,6 +130,7 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers/foo/services/foo", path: "/api/providers/foo/services/foo",
configuration: config.Configurations{ configuration: config.Configurations{
"foo": { "foo": {
HTTP: &config.HTTPConfiguration{
Services: map[string]*config.Service{ Services: map[string]*config.Service{
"foo": { "foo": {
LoadBalancer: &config.LoadBalancerService{ LoadBalancer: &config.LoadBalancerService{
@ -129,6 +140,7 @@ func TestHandler_Configuration(t *testing.T) {
}, },
}, },
}, },
},
expected: expected{statusCode: http.StatusOK, body: `{"loadbalancer":{"method":"wrr","passHostHeader":false}}`}, expected: expected{statusCode: http.StatusOK, body: `{"loadbalancer":{"method":"wrr","passHostHeader":false}}`},
}, },
{ {
@ -144,6 +156,7 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers/foo/middlewares", path: "/api/providers/foo/middlewares",
configuration: config.Configurations{ configuration: config.Configurations{
"foo": { "foo": {
HTTP: &config.HTTPConfiguration{
Middlewares: map[string]*config.Middleware{ Middlewares: map[string]*config.Middleware{
"bar": { "bar": {
AddPrefix: &config.AddPrefix{Prefix: "bar"}, AddPrefix: &config.AddPrefix{Prefix: "bar"},
@ -151,6 +164,7 @@ func TestHandler_Configuration(t *testing.T) {
}, },
}, },
}, },
},
expected: expected{statusCode: http.StatusOK, body: `[{"addPrefix":{"prefix":"bar"},"id":"bar"}]`}, expected: expected{statusCode: http.StatusOK, body: `[{"addPrefix":{"prefix":"bar"},"id":"bar"}]`},
}, },
{ {
@ -158,6 +172,7 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers/foo/middlewares/bar", path: "/api/providers/foo/middlewares/bar",
configuration: config.Configurations{ configuration: config.Configurations{
"foo": { "foo": {
HTTP: &config.HTTPConfiguration{
Middlewares: map[string]*config.Middleware{ Middlewares: map[string]*config.Middleware{
"bar": { "bar": {
AddPrefix: &config.AddPrefix{Prefix: "bar"}, AddPrefix: &config.AddPrefix{Prefix: "bar"},
@ -165,6 +180,7 @@ func TestHandler_Configuration(t *testing.T) {
}, },
}, },
}, },
},
expected: expected{statusCode: http.StatusOK, body: `{"addPrefix":{"prefix":"bar"}}`}, expected: expected{statusCode: http.StatusOK, body: `{"addPrefix":{"prefix":"bar"}}`},
}, },
{ {

View file

@ -45,7 +45,7 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
newConfig := config.Configuration{ newConfig := config.HTTPConfiguration{
Routers: make(map[string]*config.Router), Routers: make(map[string]*config.Router),
Middlewares: make(map[string]*config.Middleware), Middlewares: make(map[string]*config.Middleware),
Services: make(map[string]*config.Service), Services: make(map[string]*config.Service),

View file

@ -1,7 +1,6 @@
package healthcheck package healthcheck
import ( import (
"crypto/tls"
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
@ -59,13 +58,14 @@ func Do(staticConfiguration static.Configuration) (*http.Response, error) {
client := &http.Client{Timeout: 5 * time.Second} client := &http.Client{Timeout: 5 * time.Second}
protocol := "http" protocol := "http"
if pingEntryPoint.TLS != nil { // FIXME Handle TLS on ping etc...
protocol = "https" // if pingEntryPoint.TLS != nil {
tr := &http.Transport{ // protocol = "https"
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // tr := &http.Transport{
} // TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
client.Transport = tr // }
} // client.Transport = tr
// }
path := "/" path := "/"

View file

@ -8,8 +8,6 @@ import (
"github.com/abronan/valkeyrie/store" "github.com/abronan/valkeyrie/store"
"github.com/containous/flaeg" "github.com/containous/flaeg"
"github.com/containous/staert" "github.com/containous/staert"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/cmd" "github.com/containous/traefik/cmd"
) )
@ -17,7 +15,7 @@ import (
func NewCmd(traefikConfiguration *cmd.TraefikConfiguration, traefikPointersConfiguration *cmd.TraefikConfiguration) *flaeg.Command { func NewCmd(traefikConfiguration *cmd.TraefikConfiguration, traefikPointersConfiguration *cmd.TraefikConfiguration) *flaeg.Command {
return &flaeg.Command{ return &flaeg.Command{
Name: "storeconfig", Name: "storeconfig",
Description: `Store the static traefik configuration into a Key-value stores. Traefik will not start.`, Description: `Stores the static traefik configuration into a Key-value stores. Traefik will not start.`,
Config: traefikConfiguration, Config: traefikConfiguration,
DefaultPointersConfig: traefikPointersConfiguration, DefaultPointersConfig: traefikPointersConfiguration,
Metadata: map[string]string{ Metadata: map[string]string{
@ -71,48 +69,48 @@ func Run(kv *staert.KvSource, traefikConfiguration *cmd.TraefikConfiguration) fu
} }
} }
if traefikConfiguration.Configuration.ACME != nil { // if traefikConfiguration.Configuration.ACME != nil {
account := &acme.Account{} // account := &acme.Account{}
//
accountInitialized, err := keyExists(kv, traefikConfiguration.Configuration.ACME.Storage) // accountInitialized, err := keyExists(kv, traefikConfiguration.Configuration.ACME.Storage)
if err != nil && err != store.ErrKeyNotFound { // if err != nil && err != store.ErrKeyNotFound {
return err // return err
} // }
//
// Check to see if ACME account object is already in kv store // // Check to see if ACME account object is already in kv store
if traefikConfiguration.Configuration.ACME.OverrideCertificates || !accountInitialized { // if traefikConfiguration.Configuration.ACME.OverrideCertificates || !accountInitialized {
//
// Store the ACME Account into the KV Store // // Stores the ACME Account into the KV Store
// Certificates in KV Store will be overridden // // Certificates in KV Stores will be overridden
meta := cluster.NewMetadata(account) // meta := cluster.NewMetadata(account)
err = meta.Marshall() // err = meta.Marshall()
if err != nil { // if err != nil {
return err // return err
} // }
//
source := staert.KvSource{ // source := staert.KvSource{
Store: kv, // Store: kv,
Prefix: traefikConfiguration.Configuration.ACME.Storage, // Prefix: traefikConfiguration.Configuration.ACME.Storage,
} // }
//
err = source.StoreConfig(meta) // err = source.StoreConfig(meta)
if err != nil { // if err != nil {
return err // return err
} // }
} // }
} // }
return nil return nil
} }
} }
func keyExists(source *staert.KvSource, key string) (bool, error) { // func keyExists(source *staert.KvSource, key string) (bool, error) {
list, err := source.List(key, nil) // list, err := source.List(key, nil)
if err != nil { // if err != nil {
return false, err // return false, err
} // }
//
return len(list) > 0, nil // return len(list) > 0, nil
} // }
// CreateKvSource creates KvSource // CreateKvSource creates KvSource
// TLS support is enable for Consul and Etcd backends // TLS support is enable for Consul and Etcd backends

View file

@ -245,36 +245,29 @@ func runCmd(staticConfiguration *static.Configuration, configFile string) error
} }
} }
serverEntryPoints := make(server.EntryPoints) serverEntryPointsTCP := make(server.TCPEntryPoints)
for entryPointName, config := range staticConfiguration.EntryPoints { for entryPointName, config := range staticConfiguration.EntryPoints {
ctx := log.With(context.Background(), log.Str(log.EntryPointName, entryPointName)) ctx := log.With(context.Background(), log.Str(log.EntryPointName, entryPointName))
logger := log.FromContext(ctx) serverEntryPointsTCP[entryPointName], err = server.NewTCPEntryPoint(ctx, config)
serverEntryPoint, err := server.NewEntryPoint(ctx, config)
if err != nil { if err != nil {
return fmt.Errorf("error while building entryPoint %s: %v", entryPointName, err) return fmt.Errorf("error while building entryPoint %s: %v", entryPointName, err)
} }
serverEntryPointsTCP[entryPointName].RouteAppenderFactory = router.NewRouteAppenderFactory(*staticConfiguration, entryPointName, acmeProvider)
serverEntryPoint.RouteAppenderFactory = router.NewRouteAppenderFactory(*staticConfiguration, entryPointName, acmeProvider)
if acmeProvider != nil && entryPointName == acmeProvider.EntryPoint {
logger.Debugf("Setting Acme Certificate store from Entrypoint")
acmeProvider.SetCertificateStore(serverEntryPoint.Certs)
if acmeProvider.OnDemand {
serverEntryPoint.OnDemandListener = acmeProvider.ListenRequest
} }
// TLS ALPN 01 tlsManager := traefiktls.NewManager()
if acmeProvider.TLSChallenge != nil && acmeProvider.HTTPChallenge == nil && acmeProvider.DNSChallenge == nil {
serverEntryPoint.TLSALPNGetter = acmeProvider.GetTLSALPNCertificate if acmeProvider != nil {
acmeProvider.SetTLSManager(tlsManager)
if acmeProvider.TLSChallenge != nil &&
acmeProvider.HTTPChallenge == nil &&
acmeProvider.DNSChallenge == nil {
tlsManager.TLSAlpnGetter = acmeProvider.GetTLSALPNCertificate
} }
} }
serverEntryPoints[entryPointName] = serverEntryPoint svr := server.NewServer(*staticConfiguration, providerAggregator, serverEntryPointsTCP, tlsManager)
}
svr := server.NewServer(*staticConfiguration, providerAggregator, serverEntryPoints)
if acmeProvider != nil && acmeProvider.OnHostRule { if acmeProvider != nil && acmeProvider.OnHostRule {
acmeProvider.SetConfigListenerChan(make(chan config.Configuration)) acmeProvider.SetConfigListenerChan(make(chan config.Configuration))

View file

@ -18,6 +18,23 @@ type Router struct {
Service string `json:"service,omitempty" toml:",omitempty"` Service string `json:"service,omitempty" toml:",omitempty"`
Rule string `json:"rule,omitempty" toml:",omitempty"` Rule string `json:"rule,omitempty" toml:",omitempty"`
Priority int `json:"priority,omitempty" toml:"priority,omitzero"` Priority int `json:"priority,omitempty" toml:"priority,omitzero"`
TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitzero" label:"allowEmpty"`
}
// RouterTLSConfig holds the TLS configuration for a router
type RouterTLSConfig struct{}
// TCPRouter holds the router configuration.
type TCPRouter struct {
EntryPoints []string `json:"entryPoints"`
Service string `json:"service,omitempty" toml:",omitempty"`
Rule string `json:"rule,omitempty" toml:",omitempty"`
TLS *RouterTCPTLSConfig `json:"tls,omitempty" toml:"tls,omitzero" label:"allowEmpty"`
}
// RouterTCPTLSConfig holds the TLS configuration for a router
type RouterTCPTLSConfig struct {
Passthrough bool `json:"passthrough,omitempty" toml:"passthrough,omitzero"`
} }
// LoadBalancerService holds the LoadBalancerService configuration. // LoadBalancerService holds the LoadBalancerService configuration.
@ -30,6 +47,12 @@ type LoadBalancerService struct {
ResponseForwarding *ResponseForwarding `json:"forwardingResponse,omitempty" toml:",omitempty"` ResponseForwarding *ResponseForwarding `json:"forwardingResponse,omitempty" toml:",omitempty"`
} }
// TCPLoadBalancerService holds the LoadBalancerService configuration.
type TCPLoadBalancerService struct {
Servers []TCPServer `json:"servers,omitempty" toml:",omitempty" label-slice-as-struct:"server"`
Method string `json:"method,omitempty" toml:",omitempty"`
}
// Mergeable tells if the given service is mergeable. // Mergeable tells if the given service is mergeable.
func (l *LoadBalancerService) Mergeable(loadBalancer *LoadBalancerService) bool { func (l *LoadBalancerService) Mergeable(loadBalancer *LoadBalancerService) bool {
savedServers := l.Servers savedServers := l.Servers
@ -71,6 +94,12 @@ type Server struct {
Weight int `json:"weight"` Weight int `json:"weight"`
} }
// TCPServer holds a TCP Server configuration
type TCPServer struct {
Address string `json:"address" label:"-"`
Weight int `json:"weight"`
}
// SetDefaults Default values for a Server. // SetDefaults Default values for a Server.
func (s *Server) SetDefaults() { func (s *Server) SetDefaults() {
s.Weight = 1 s.Weight = 1
@ -175,18 +204,37 @@ type Message struct {
Configuration *Configuration Configuration *Configuration
} }
// Configuration is the root of the dynamic configuration
type Configuration struct {
HTTP *HTTPConfiguration
TCP *TCPConfiguration
TLS []*traefiktls.Configuration `json:"-" label:"-"`
TLSOptions map[string]traefiktls.TLS
TLSStores map[string]traefiktls.Store
}
// Configurations is for currentConfigurations Map. // Configurations is for currentConfigurations Map.
type Configurations map[string]*Configuration type Configurations map[string]*Configuration
// Configuration FIXME better name? // HTTPConfiguration FIXME better name?
type Configuration struct { type HTTPConfiguration struct {
Routers map[string]*Router `json:"routers,omitempty" toml:",omitempty"` Routers map[string]*Router `json:"routers,omitempty" toml:",omitempty"`
Middlewares map[string]*Middleware `json:"middlewares,omitempty" toml:",omitempty"` Middlewares map[string]*Middleware `json:"middlewares,omitempty" toml:",omitempty"`
Services map[string]*Service `json:"services,omitempty" toml:",omitempty"` Services map[string]*Service `json:"services,omitempty" toml:",omitempty"`
TLS []*traefiktls.Configuration `json:"-" label:"-"` }
// TCPConfiguration FIXME better name?
type TCPConfiguration struct {
Routers map[string]*TCPRouter `json:"routers,omitempty" toml:",omitempty"`
Services map[string]*TCPService `json:"services,omitempty" toml:",omitempty"`
} }
// Service holds a service configuration (can only be of one type at the same time). // Service holds a service configuration (can only be of one type at the same time).
type Service struct { type Service struct {
LoadBalancer *LoadBalancerService `json:"loadbalancer,omitempty" toml:",omitempty,omitzero"` LoadBalancer *LoadBalancerService `json:"loadbalancer,omitempty" toml:",omitempty,omitzero"`
} }
// TCPService holds a tcp service configuration (can only be of one type at the same time).
type TCPService struct {
LoadBalancer *TCPLoadBalancerService `json:"loadbalancer,omitempty" toml:",omitempty,omitzero"`
}

View file

@ -5,14 +5,12 @@ import (
"strings" "strings"
"github.com/containous/traefik/log" "github.com/containous/traefik/log"
"github.com/containous/traefik/tls"
) )
// EntryPoint holds the entry point configuration. // EntryPoint holds the entry point configuration.
type EntryPoint struct { type EntryPoint struct {
Address string Address string
Transport *EntryPointsTransport Transport *EntryPointsTransport
TLS *tls.TLS
ProxyProtocol *ProxyProtocol ProxyProtocol *ProxyProtocol
ForwardedHeaders *ForwardedHeaders ForwardedHeaders *ForwardedHeaders
} }
@ -65,14 +63,8 @@ func (ep *EntryPoints) Type() string {
func (ep *EntryPoints) Set(value string) error { func (ep *EntryPoints) Set(value string) error {
result := parseEntryPointsConfiguration(value) result := parseEntryPointsConfiguration(value)
configTLS, err := makeEntryPointTLS(result)
if err != nil {
return err
}
(*ep)[result["name"]] = &EntryPoint{ (*ep)[result["name"]] = &EntryPoint{
Address: result["address"], Address: result["address"],
TLS: configTLS,
ProxyProtocol: makeEntryPointProxyProtocol(result), ProxyProtocol: makeEntryPointProxyProtocol(result),
ForwardedHeaders: makeEntryPointForwardedHeaders(result), ForwardedHeaders: makeEntryPointForwardedHeaders(result),
} }
@ -100,55 +92,6 @@ func makeEntryPointProxyProtocol(result map[string]string) *ProxyProtocol {
return proxyProtocol return proxyProtocol
} }
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{}
} else if len(result["tls_acme"]) > 0 {
configTLS = &tls.TLS{}
}
if configTLS != nil {
if len(result["ca"]) > 0 {
files := tls.FilesOrContents{}
if err := files.Set(result["ca"]); err != nil {
return nil, err
}
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 { func parseEntryPointsConfiguration(raw string) map[string]string {
sections := strings.Fields(raw) sections := strings.Fields(raw)

View file

@ -3,7 +3,6 @@ package static
import ( import (
"testing" "testing"
"github.com/containous/traefik/tls"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -18,10 +17,6 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
name: "all parameters", name: "all parameters",
value: "Name:foo " + value: "Name:foo " +
"Address::8000 " + "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:car " +
"CA.Optional:true " + "CA.Optional:true " +
"Redirect.EntryPoint:https " + "Redirect.EntryPoint:https " +
@ -76,10 +71,6 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
"redirect_permanent": "true", "redirect_permanent": "true",
"redirect_regex": "http://localhost/(.*)", "redirect_regex": "http://localhost/(.*)",
"redirect_replacement": "http://mydomain/$1", "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",
"whitelist_sourcerange": "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_ipstrategy_depth": "3", "whitelist_ipstrategy_depth": "3",
"whitelist_ipstrategy_excludedips": "10.0.0.3/24,20.0.0.3/24", "whitelist_ipstrategy_excludedips": "10.0.0.3/24,20.0.0.3/24",
@ -95,15 +86,6 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
"compress": "on", "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 { for _, test := range testCases {
@ -185,23 +167,12 @@ func TestEntryPoints_Set(t *testing.T) {
name: "all parameters camelcase", name: "all parameters camelcase",
expression: "Name:foo " + expression: "Name:foo " +
"Address::8000 " + "Address::8000 " +
"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:car " +
"CA.Optional:true " + "CA.Optional:true " +
"ProxyProtocol.TrustedIPs:192.168.0.1 ", "ProxyProtocol.TrustedIPs:192.168.0.1 ",
expectedEntryPointName: "foo", expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{ expectedEntryPoint: &EntryPoint{
Address: ":8000", 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"},
ClientCA: tls.ClientCA{
Files: tls.FilesOrContents{"car"},
Optional: true,
},
},
ProxyProtocol: &ProxyProtocol{ ProxyProtocol: &ProxyProtocol{
Insecure: false, Insecure: false,
TrustedIPs: []string{"192.168.0.1"}, TrustedIPs: []string{"192.168.0.1"},
@ -223,14 +194,6 @@ func TestEntryPoints_Set(t *testing.T) {
expectedEntryPointName: "foo", expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{ expectedEntryPoint: &EntryPoint{
Address: ":8000", 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"},
ClientCA: tls.ClientCA{
Files: tls.FilesOrContents{"car"},
Optional: true,
},
},
ProxyProtocol: &ProxyProtocol{ ProxyProtocol: &ProxyProtocol{
Insecure: false, Insecure: false,
TrustedIPs: []string{"192.168.0.1"}, TrustedIPs: []string{"192.168.0.1"},

View file

@ -6,7 +6,6 @@ import (
"time" "time"
"github.com/containous/flaeg/parse" "github.com/containous/flaeg/parse"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/log" "github.com/containous/traefik/log"
"github.com/containous/traefik/old/provider/boltdb" "github.com/containous/traefik/old/provider/boltdb"
"github.com/containous/traefik/old/provider/consul" "github.com/containous/traefik/old/provider/consul"
@ -70,7 +69,7 @@ type Configuration struct {
HostResolver *types.HostResolverConfig `description:"Enable CNAME Flattening" export:"true"` HostResolver *types.HostResolverConfig `description:"Enable CNAME Flattening" export:"true"`
ACME *acme.ACME `description:"Enable ACME (Let's Encrypt): automatic SSL" export:"true"` ACME *acmeprovider.Configuration `description:"Enable ACME (Let's Encrypt): automatic SSL" export:"true"`
} }
// Global holds the global configuration. // Global holds the global configuration.
@ -338,10 +337,6 @@ func (c *Configuration) initACMEProvider() {
log.Warn("Unable to use HTTP challenge and TLS challenge at the same time. Fallback to TLS challenge.") log.Warn("Unable to use HTTP challenge and TLS challenge at the same time. Fallback to TLS challenge.")
c.ACME.HTTPChallenge = nil c.ACME.HTTPChallenge = nil
} }
if c.ACME.OnDemand {
log.Warn("ACME.OnDemand is deprecated")
}
} }
} }
@ -349,18 +344,11 @@ func (c *Configuration) initACMEProvider() {
func (c *Configuration) InitACMEProvider() (*acmeprovider.Provider, error) { func (c *Configuration) InitACMEProvider() (*acmeprovider.Provider, error) {
if c.ACME != nil { if c.ACME != nil {
if len(c.ACME.Storage) == 0 { if len(c.ACME.Storage) == 0 {
// Delete the ACME configuration to avoid starting ACME in cluster mode
c.ACME = nil
return nil, errors.New("unable to initialize ACME provider with no storage location for the certificates") return nil, errors.New("unable to initialize ACME provider with no storage location for the certificates")
} }
provider := &acmeprovider.Provider{} return &acmeprovider.Provider{
provider.Configuration = convertACMEChallenge(c.ACME) Configuration: c.ACME,
}, nil
store := acmeprovider.NewLocalStore(provider.Storage)
provider.Store = store
acme.ConvertToNewFormat(provider.Storage)
c.ACME = nil
return provider, nil
} }
return nil, nil return nil, nil
} }
@ -368,13 +356,27 @@ func (c *Configuration) InitACMEProvider() (*acmeprovider.Provider, error) {
// ValidateConfiguration validate that configuration is coherent // ValidateConfiguration validate that configuration is coherent
func (c *Configuration) ValidateConfiguration() { func (c *Configuration) ValidateConfiguration() {
if c.ACME != nil { if c.ACME != nil {
if _, ok := c.EntryPoints[c.ACME.EntryPoint]; !ok { for _, domain := range c.ACME.Domains {
log.Fatalf("Unknown entrypoint %q for ACME configuration", c.ACME.EntryPoint) if domain.Main != dns01.UnFqdn(domain.Main) {
} else if c.EntryPoints[c.ACME.EntryPoint].TLS == nil { log.Warnf("FQDN detected, please remove the trailing dot: %s", domain.Main)
log.Fatalf("Entrypoint %q has no TLS configuration for ACME configuration", c.ACME.EntryPoint) }
for _, san := range domain.SANs {
if san != dns01.UnFqdn(san) {
log.Warnf("FQDN detected, please remove the trailing dot: %s", san)
} }
} }
} }
}
// FIXME Validate store config?
// if c.ACME != nil {
// if _, ok := c.EntryPoints[c.ACME.EntryPoint]; !ok {
// log.Fatalf("Unknown entrypoint %q for ACME configuration", c.ACME.EntryPoint)
// }
// else if c.EntryPoints[c.ACME.EntryPoint].TLS == nil {
// log.Fatalf("Entrypoint %q has no TLS configuration for ACME configuration", c.ACME.EntryPoint)
// }
// }
}
func getSafeACMECAServer(caServerSrc string) string { func getSafeACMECAServer(caServerSrc string) string {
if len(caServerSrc) == 0 { if len(caServerSrc) == 0 {
@ -395,47 +397,3 @@ func getSafeACMECAServer(caServerSrc string) string {
return caServerSrc return caServerSrc
} }
// Deprecated
func convertACMEChallenge(oldACMEChallenge *acme.ACME) *acmeprovider.Configuration {
conf := &acmeprovider.Configuration{
KeyType: oldACMEChallenge.KeyType,
OnHostRule: oldACMEChallenge.OnHostRule,
OnDemand: oldACMEChallenge.OnDemand,
Email: oldACMEChallenge.Email,
Storage: oldACMEChallenge.Storage,
ACMELogging: oldACMEChallenge.ACMELogging,
CAServer: oldACMEChallenge.CAServer,
EntryPoint: oldACMEChallenge.EntryPoint,
}
for _, domain := range oldACMEChallenge.Domains {
if domain.Main != dns01.UnFqdn(domain.Main) {
log.Warnf("FQDN detected, please remove the trailing dot: %s", domain.Main)
}
for _, san := range domain.SANs {
if san != dns01.UnFqdn(san) {
log.Warnf("FQDN detected, please remove the trailing dot: %s", san)
}
}
conf.Domains = append(conf.Domains, domain)
}
if oldACMEChallenge.HTTPChallenge != nil {
conf.HTTPChallenge = &acmeprovider.HTTPChallenge{
EntryPoint: oldACMEChallenge.HTTPChallenge.EntryPoint,
}
}
if oldACMEChallenge.DNSChallenge != nil {
conf.DNSChallenge = &acmeprovider.DNSChallenge{
Provider: oldACMEChallenge.DNSChallenge.Provider,
DelayBeforeCheck: oldACMEChallenge.DNSChallenge.DelayBeforeCheck,
}
}
if oldACMEChallenge.TLSChallenge != nil {
conf.TLSChallenge = &acmeprovider.TLSChallenge{}
}
return conf
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 458 KiB

After

Width:  |  Height:  |  Size: 361 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 KiB

After

Width:  |  Height:  |  Size: 376 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 KiB

After

Width:  |  Height:  |  Size: 377 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 KiB

After

Width:  |  Height:  |  Size: 378 KiB

View file

@ -48,8 +48,8 @@ Once a day (the first call begins 10 minutes after the start of Traefik), we col
??? example "Original configuration" ??? example "Original configuration"
```toml ```toml
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":80" address = ":80"
[api] [api]
@ -78,8 +78,8 @@ Once a day (the first call begins 10 minutes after the start of Traefik), we col
??? example "Resulting Obfuscated Configuration" ??? example "Resulting Obfuscated Configuration"
```toml ```toml
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":80" address = ":80"
[api] [api]

View file

@ -24,7 +24,7 @@ You no longer need to create and synchronize configuration files cluttered with
!!! note "Many different rules" !!! note "Many different rules"
In the example above, we used the request [path](../routing/routers.md#rule) to determine which service was in charge, but of course you can use many other different [rules](../routing/routers.md#rule). In the example above, we used the request [path](../routing/routers/index.md#rule) to determine which service was in charge, but of course you can use many other different [rules](../routing/routers/index.md#rule).
!!! note "Updating the requests" !!! note "Updating the requests"

View file

@ -3,29 +3,27 @@
Automatic HTTPS Automatic HTTPS
{: .subtitle } {: .subtitle }
Traefik can automatically generate certificates for your domains using an ACME provider (like Let's Encrypt). You can configure Traefik to use an ACME provider (like Let's Encrypt) for automatic certificate generation.
!!! warning "Let's Encrypt and Rate Limiting" !!! warning "Let's Encrypt and Rate Limiting"
Note that Let's Encrypt has [rate limiting](https://letsencrypt.org/docs/rate-limits). Note that Let's Encrypt API has [rate limiting](https://letsencrypt.org/docs/rate-limits).
## Configuration Examples ## Configuration Examples
??? example "Configuring ACME on the Https EntryPoint" ??? example "Enabling ACME"
```toml ```toml
[entryPoints] [entrypoints]
[entryPoints.web] [entrypoints.web]
address = ":80" address = ":80"
[entryPoints.http-tls] [entrypoints.http-tls]
address = ":443" address = ":443"
[entryPoints.http-tls.tls] # enabling TLS
[acme] [acme] # every router with TLS enabled will now be able to use ACME for its certificates
email = "your-email@your-domain.org" email = "your-email@your-domain.org"
storage = "acme.json" storage = "acme.json"
entryPoint = "http-tls" # acme is enabled on http-tls onHostRule = true # dynamic generation based on the Host() & HostSNI() matchers
onHostRule = true # dynamic generation based on the Host() matcher
[acme.httpChallenge] [acme.httpChallenge]
entryPoint = "web" # used during the challenge entryPoint = "web" # used during the challenge
``` ```
@ -33,18 +31,16 @@ Traefik can automatically generate certificates for your domains using an ACME p
??? example "Configuring Wildcard Certificates" ??? example "Configuring Wildcard Certificates"
```toml ```toml
[entryPoints] [entrypoints]
[entryPoints.web] [entrypoints.web]
address = ":80" address = ":80"
[entryPoints.http-tls] [entrypoints.http-tls]
address = ":443" address = ":443"
[entryPoints.https.tls] # enabling TLS
[acme] [acme]
email = "your-email@your-domain.org" email = "your-email@your-domain.org"
storage = "acme.json" storage = "acme.json"
entryPoint = "http-tls" # acme is enabled on http-tls
[acme.dnsChallenge] [acme.dnsChallenge]
provider = "xxx" provider = "xxx"
@ -65,17 +61,15 @@ Traefik can automatically generate certificates for your domains using an ACME p
Use the `TLS-ALPN-01` challenge to generate and renew ACME certificates by provisioning a TLS certificate. Use the `TLS-ALPN-01` challenge to generate and renew ACME certificates by provisioning a TLS certificate.
??? example "Using an EntryPoint Called https for the `tlsChallenge`" ??? example "Configuring the `tlsChallenge`"
```toml ```toml
[acme] [acme]
# ...
entryPoint = "https"
[acme.tlsChallenge] [acme.tlsChallenge]
``` ```
!!! note !!! note
As described on the Let's Encrypt [community forum](https://community.letsencrypt.org/t/support-for-ports-other-than-80-and-443/3419/72), when using the `TLS-ALPN-01` challenge, `acme.entryPoint` must be reachable by Let's Encrypt through port 443. As described on the Let's Encrypt [community forum](https://community.letsencrypt.org/t/support-for-ports-other-than-80-and-443/3419/72), when using the `TLS-ALPN-01` challenge, Traefik must be reachable by Let's Encrypt through port 443.
#### `httpChallenge` #### `httpChallenge`
@ -86,7 +80,6 @@ Use the `HTTP-01` challenge to generate and renew ACME certificates by provision
```toml ```toml
[acme] [acme]
# ... # ...
entryPoint = "https"
[acme.httpChallenge] [acme.httpChallenge]
entryPoint = "http" entryPoint = "http"
``` ```
@ -233,6 +226,7 @@ As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/stagi
[[acme.domains]] [[acme.domains]]
main = "*.local1.com" main = "*.local1.com"
sans = ["local1.com"] sans = ["local1.com"]
# ... # ...
``` ```
@ -263,7 +257,7 @@ The [Supported `provider` table](#dnschallenge) indicates if they allow generati
### onHostRule ### onHostRule
Enable certificate generation on [routers](routers.md) `Host` rules (for routers active on the `acme.entryPoint`). Enable certificate generation on [routers](../routing/routers/index.md) `Host` & `HostSNI` rules.
This will request a certificate from Let's Encrypt for each router with a Host rule. This will request a certificate from Let's Encrypt for each router with a Host rule.

View file

@ -0,0 +1,145 @@
# HTTPS & TLS
Traefik supports HTTPS & TLS, and is able to accept new certificates / updates over time (without being restarted).
TLS is enabled at the [router](../routing/routers/index.md) level, but some options are configured in dedicated sections (`tlsOptions` & `tlsStores`) described in this section.
## Configuration Example
??? example "Configuring a Default Certificate"
```toml
[tlsStores]
[tlsStores.default]
[tlsStores.default.defaultCertificate]
certFile = "path/to/cert.crt"
keyFile = "path/to/cert.key"
```
??? example "Configuring a Minimum TLS Version"
```toml
[tlsOptions]
[tlsOptions.default]
minVersion = "VersionTLS12"
```
??? example "Defining Certificates"
```toml
[[tls]]
[tls.certificate]
certFile = "/path/to/domain.cert"
keyFile = "/path/to/domain.key"
[[tls]]
[tls.certificate]
certFile = "/path/to/other-domain.cert"
keyFile = "/path/to/other-domain.key"
```
!!! important "File Provider Only"
In the above example, we've used the [file provider](../providers/file.md) to handle the TLS configuration (tlsStores, tlsOptions, and TLS certificates).
In its current alpha version, it is the only available method to configure these elements.
Of course, these options are hot reloaded and can be updated at runtime (they belong to the [dynamic configuration](../getting-started/configuration-overview.md)).
## Configuration Options
### Dynamic Certificates
To add / remove TLS certificates while Traefik is running, the [file provider](../providers/file.md) supports Dynamic TLS certificates in its `[[tls]]` section.
!!! example "Defining Certificates"
```toml
[[tls]]
stores = ["default"]
[tls.certificate]
certFile = "/path/to/domain.cert"
keyFile = "/path/to/domain.key"
[[tls]]
stores = ["default"]
[tls.certificate]
certFile = "/path/to/other-domain.cert"
keyFile = "/path/to/other-domain.key"
```
??? note "Stores"
During the alpha version, the stores option will be ignored and be automatically set to ["default"].
### Mutual Authentication
Traefik supports both optional and non optional (defaut value) mutual authentication.
- When `optional = false`, Traefik accepts connections only from client presenting a certificate signed by a CA listed in `ClientCA.files`.
- When `optional = true`, Traefik authorizes connections from client presenting a certificate signed by an unknown CA.
!!! example "Non Optional Mutual Authentication"
In the following example, both `snitest.com` and `snitest.org` will require client certificates.
```toml
[tlsOptions]
[tlsOptions.default]
[tlsOptions.default.ClientCA]
files = ["tests/clientca1.crt", "tests/clientca2.crt"]
optional = false
```
??? note "ClientCA.files"
You can use a file per `CA:s`, or a single file containing multiple `CA:s` (in `PEM` format).
`ClientCA.files` is not optional: every client will have to present a valid certificate. (This requirement will apply to every server certificate declared in the entrypoint.)
### Minimum TLS Version
!!! example "Min TLS version & [cipherSuites](https://godoc.org/crypto/tls#pkg-constants)"
```toml
[tlsOptions]
[tlsOptions.default]
minVersion = "VersionTLS12"
cipherSuites = [
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_256_GCM_SHA384"
]
```
### Strict SNI Checking
With strict SNI checking, Traefik won't allow connections without a matching certificate.
!!! example "Strict SNI"
```toml
[tlsOptions]
[tlsOptions.default]
sniStrict = true
```
### Default Certificate
Traefik can use a default certificate for connections without a SNI, or without a matching domain.
If no default certificate is provided, Traefik generates and uses a self-signed certificate.
!!! example "Setting a Default Certificate"
```toml
[tlsStores]
[tlsStores.default]
[tlsStores.default.defaultCertificate]
certFile = "path/to/cert.crt"
keyFile = "path/to/cert.key"
```
??? note "Only One Default Certificate"
There can only be one `defaultCertificate` per tlsOptions.
??? note "Default TLS Store"
During the alpha version, there is only one globally available TLS Store (`default`).

View file

@ -1,2 +1,2 @@
!!! info "More On Routers" !!! info "More On Routers"
Learn more about routers and their configuration options in the [dedicated section](../routing/routers.md). Learn more about routers and their configuration options in the [dedicated section](../routing/routers/index.md).

View file

@ -12,8 +12,8 @@ The AddPrefix middleware updates the URL Path of the request before forwarding i
??? example "File -- Prefixing with /foo" ??? example "File -- Prefixing with /foo"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.add-foo.AddPrefix] [http.middlewares.add-foo.AddPrefix]
prefix = "/foo" prefix = "/foo"
``` ```
@ -23,7 +23,7 @@ The AddPrefix middleware updates the URL Path of the request before forwarding i
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.middlewares.add-bar.addprefix.prefix=/bar" - "traefik.http.middlewares.add-bar.addprefix.prefix=/bar"
``` ```
## Configuration Options ## Configuration Options

View file

@ -12,8 +12,8 @@ The BasicAuth middleware is a quick way to restrict access to your services to k
??? example "File -- Declaring the user list" ??? example "File -- Declaring the user list"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.test-auth.basicauth] [http.middlewares.test-auth.basicauth]
users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"] "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"]
``` ```
@ -24,7 +24,7 @@ The BasicAuth middleware is a quick way to restrict access to your services to k
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.middlewares.declared-users-only.basicauth.usersFile=path-to-file.ext", - "traefik.http.middlewares.declared-users-only.basicauth.usersFile=path-to-file.ext",
``` ```
## Configuration Options ## Configuration Options
@ -73,7 +73,7 @@ You can customize the header field for the authenticated user using the `headerF
??? example "File -- Passing Authenticated Users to Services Via Headers" ??? example "File -- Passing Authenticated Users to Services Via Headers"
```toml ```toml
[Middlewares.my-auth.basicauth] [http.middlewares.my-auth.basicauth]
usersFile = "path-to-file.ext" usersFile = "path-to-file.ext"
headerField = "X-WebAuth-User" # header for the authenticated user headerField = "X-WebAuth-User" # header for the authenticated user
``` ```

View file

@ -16,8 +16,8 @@ This can help services deal with large data (multipart/form-data for example), a
??? example "File -- Sets the maximum request body to 2Mb" ??? example "File -- Sets the maximum request body to 2Mb"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.2Mb-limit.buffering] [http.middlewares.2Mb-limit.buffering]
maxRequestBodyBytes = 250000 maxRequestBodyBytes = 250000
``` ```
@ -27,7 +27,7 @@ This can help services deal with large data (multipart/form-data for example), a
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.middlewares.1Mb-memory.buffering.memRequestBodyBytes=125000", - "traefik.http.middlewares.1Mb-memory.buffering.memRequestBodyBytes=125000",
``` ```
## Configuration Options ## Configuration Options

View file

@ -14,27 +14,27 @@ It makes reusing the same groups easier.
```toml ```toml
# ... # ...
[Routers] [http.routers]
[Routers.router1] [http.routers.router1]
service = "service1" service = "service1"
middlewares = ["secured"] middlewares = ["secured"]
rule = "Host: mydomain" rule = "Host: mydomain"
[Middlewares] [http.middlewares]
[Middlewares.secured.Chain] [http.middlewares.secured.Chain]
middlewares = ["https-only", "known-ips", "auth-users"] middlewares = ["https-only", "known-ips", "auth-users"]
[Middlewares.auth-users.BasicAuth] [http.middlewares.auth-users.BasicAuth]
users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"] users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"]
[Middlewares.https-only.SchemeRedirect] [http.middlewares.https-only.SchemeRedirect]
scheme = "https" scheme = "https"
[Middlewares.known-ips.ipWhiteList] [http.middlewares.known-ips.ipWhiteList]
sourceRange = ["192.168.1.7", "x.x.x.x", "x.x.x.x"] sourceRange = ["192.168.1.7", "x.x.x.x", "x.x.x.x"]
[Services] [http.services]
[Services.service1] [http.services.service1]
[Services.service1.LoadBalancer] [http.services.service1.LoadBalancer]
[[Services.service1.LoadBalancer.Servers]] [[http.services.service1.LoadBalancer.Servers]]
URL = "http://127.0.0.1:80" URL = "http://127.0.0.1:80"
Weight = 1 Weight = 1
``` ```

View file

@ -26,8 +26,8 @@ To assess if your system is healthy, the circuit breaker constantly monitors the
??? example "Latency Check -- Using Toml" ??? example "Latency Check -- Using Toml"
```toml ```toml
[middlewares] [http.middlewares]
[middlewares.latency-check.circuitbreaker] [http.middlewares.latency-check.circuitbreaker]
expression = "LatencyAtQuantileMS(50.0) > 100" expression = "LatencyAtQuantileMS(50.0) > 100"
``` ```
@ -38,7 +38,7 @@ To assess if your system is healthy, the circuit breaker constantly monitors the
container-definition: container-definition:
image: image-name image: image-name
labels: labels:
- "traefik.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100" - "traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100"
``` ```
## Possible States ## Possible States

View file

@ -12,8 +12,8 @@ The Compress middleware enables the gzip compression.
??? example "File -- enable gzip compression" ??? example "File -- enable gzip compression"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.test-compress.Compress] [http.middlewares.test-compress.Compress]
``` ```
??? example "Docker -- enable gzip compression" ??? example "Docker -- enable gzip compression"
@ -22,7 +22,7 @@ The Compress middleware enables the gzip compression.
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.middlewares.test-compress.compress=true", - "traefik.http.middlewares.test-compress.compress=true",
``` ```
## Notes ## Notes

View file

@ -12,8 +12,8 @@ The DigestAuth middleware is a quick way to restrict access to your services to
??? example "File -- Declaring the user list" ??? example "File -- Declaring the user list"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.test-auth.digestauth] [http.middlewares.test-auth.digestauth]
users = ["test:traefik:a2688e031edb4be6a3797f3882655c05", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"] users = ["test:traefik:a2688e031edb4be6a3797f3882655c05", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"]
``` ```
@ -23,7 +23,7 @@ The DigestAuth middleware is a quick way to restrict access to your services to
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.middlewares.declared-users-only.digestauth.usersFile=path-to-file.ext", - "traefik.http.middlewares.declared-users-only.digestauth.usersFile=path-to-file.ext",
``` ```
!!! tip !!! tip
@ -68,7 +68,7 @@ You can customize the header field for the authenticated user using the `headerF
??? example "File -- Passing Authenticated Users to Services Via Headers" ??? example "File -- Passing Authenticated Users to Services Via Headers"
```toml ```toml
[Middlewares.my-auth.digestauth] [http.middlewares.my-auth.digestauth]
usersFile = "path-to-file.ext" usersFile = "path-to-file.ext"
headerField = "X-WebAuth-User" # header for the authenticated user headerField = "X-WebAuth-User" # header for the authenticated user
``` ```

View file

@ -15,18 +15,18 @@ The ErrorPage middleware returns a custom page in lieu of the default, according
??? example "File -- Custom Error Page for 5XX" ??? example "File -- Custom Error Page for 5XX"
```toml ```toml
[Routers] [http.routers]
[Routers.router1] [http.routers.router1]
Service = "my-service" Service = "my-service"
Rule = Host(`my-domain`) Rule = Host(`my-domain`)
[Middlewares] [http.middlewares]
[Middlewares.5XX-errors.Errors] [http.middlewares.5XX-errors.Errors]
status = ["500-599"] status = ["500-599"]
service = "error-handler-service" service = "error-handler-service"
query = "/error.html" query = "/error.html"
[Services] [http.services]
# ... definition of error-handler-service and my-service # ... definition of error-handler-service and my-service
``` ```
@ -36,9 +36,9 @@ The ErrorPage middleware returns a custom page in lieu of the default, according
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.middlewares.test-errorpage.errors.status=500-599", - "traefik.http.middlewares.test-errorpage.errors.status=500-599",
- "traefik.middlewares.test-errorpage.errors.service=serviceError", - "traefik.http.middlewares.test-errorpage.errors.service=serviceError",
- "traefik.middlewares.test-errorpage.errors.query=/{status}.html", - "traefik.http.middlewares.test-errorpage.errors.query=/{status}.html",
``` ```

View file

@ -14,13 +14,13 @@ Otherwise, the response from the authentication server is returned.
??? example "File -- Forward authentication to authserver.com" ??? example "File -- Forward authentication to authserver.com"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.test-auth.forwardauth] [http.middlewares.test-auth.forwardauth]
address = "https://authserver.com/auth" address = "https://authserver.com/auth"
trustForwardHeader = true trustForwardHeader = true
authResponseHeaders = ["X-Auth-User", "X-Secret"] authResponseHeaders = ["X-Auth-User", "X-Secret"]
[Middlewares.test-auth.forwardauth.tls] [http.middlewares.test-auth.forwardauth.tls]
ca = "path/to/local.crt" ca = "path/to/local.crt"
caOptional = true caOptional = true
cert = "path/to/foo.cert" cert = "path/to/foo.cert"
@ -33,14 +33,14 @@ Otherwise, the response from the authentication server is returned.
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.Middlewares.test-auth.ForwardAuth.Address=https://authserver.com/auth" - "traefik.http.middlewares.test-auth.ForwardAuth.Address=https://authserver.com/auth"
- "traefik.Middlewares.test-auth.ForwardAuth.AuthResponseHeaders=X-Auth-User, X-Secret" - "traefik.http.middlewares.test-auth.ForwardAuth.AuthResponseHeaders=X-Auth-User, X-Secret"
- "traefik.Middlewares.test-auth.ForwardAuth.TLS.CA=path/to/local.crt" - "traefik.http.middlewares.test-auth.ForwardAuth.TLS.CA=path/to/local.crt"
- "traefik.Middlewares.test-auth.ForwardAuth.TLS.CAOptional=true" - "traefik.http.middlewares.test-auth.ForwardAuth.TLS.CAOptional=true"
- "traefik.Middlewares.test-auth.ForwardAuth.TLS.Cert=path/to/foo.cert" - "traefik.http.middlewares.test-auth.ForwardAuth.TLS.Cert=path/to/foo.cert"
- "traefik.Middlewares.test-auth.ForwardAuth.TLS.InsecureSkipVerify=true" - "traefik.http.middlewares.test-auth.ForwardAuth.TLS.InsecureSkipVerify=true"
- "traefik.Middlewares.test-auth.ForwardAuth.TLS.Key=path/to/foo.key" - "traefik.http.middlewares.test-auth.ForwardAuth.TLS.Key=path/to/foo.key"
- "traefik.Middlewares.test-auth.ForwardAuth.TrustForwardHeader=true" - "traefik.http.middlewares.test-auth.ForwardAuth.TrustForwardHeader=true"
``` ```

View file

@ -16,11 +16,11 @@ Add the `X-Script-Name` header to the proxied request and the `X-Custom-Response
??? example "File" ??? example "File"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.testHeader.headers] [http.middlewares.testHeader.headers]
[Middlewares.testHeader.headers.CustomRequestHeaders] [http.middlewares.testHeader.headers.CustomRequestHeaders]
X-Script-Name = "test" X-Script-Name = "test"
[Middlewares.testHeader.headers.CustomResponseHeaders] [http.middlewares.testHeader.headers.CustomResponseHeaders]
X-Custom-Response-Header = "True" X-Custom-Response-Header = "True"
``` ```
@ -30,8 +30,8 @@ Add the `X-Script-Name` header to the proxied request and the `X-Custom-Response
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.Middlewares.testHeader.Headers.CustomRequestHeaders.X-Script-Name=test", - "traefik.http.middlewares.testHeader.Headers.CustomRequestHeaders.X-Script-Name=test",
- "traefik.Middlewares.testHeader.Headers.CustomResponseHeaders.X-Custom-Response-Header=True", - "traefik.http.middlewares.testHeader.Headers.CustomResponseHeaders.X-Custom-Response-Header=True",
``` ```
### Adding and Removing Headers ### Adding and Removing Headers
@ -41,11 +41,11 @@ Add the `X-Script-Name` header to the proxied request and the `X-Custom-Response
??? example "File" ??? example "File"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.testHeader.headers] [http.middlewares.testHeader.headers]
[Middlewares.testHeader.headers.CustomRequestHeaders] [http.middlewares.testHeader.headers.CustomRequestHeaders]
X-Script-Name = "test" X-Script-Name = "test"
[Middlewares.testHeader.headers.CustomResponseHeaders] [http.middlewares.testHeader.headers.CustomResponseHeaders]
X-Custom-Response-Header = "True" X-Custom-Response-Header = "True"
``` ```
@ -55,8 +55,8 @@ Add the `X-Script-Name` header to the proxied request and the `X-Custom-Response
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.Middlewares.testHeader.Headers.CustomRequestHeaders.X-Script-Name=test", - "traefik.http.middlewares.testHeader.Headers.CustomRequestHeaders.X-Script-Name=test",
- "traefik.Middlewares.testHeader.Headers.CustomResponseHeaders.X-Custom-Response-Header=True", - "traefik.http.middlewares.testHeader.Headers.CustomResponseHeaders.X-Custom-Response-Header=True",
``` ```
### Using Security Headers ### Using Security Headers
@ -67,8 +67,8 @@ This functionality allows for some easy security features to quickly be set.
??? example "File" ??? example "File"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.testHeader.headers] [http.middlewares.testHeader.headers]
FrameDeny = true FrameDeny = true
SSLRedirect = true SSLRedirect = true
``` ```
@ -79,8 +79,8 @@ This functionality allows for some easy security features to quickly be set.
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.Middlewares.testHeader.Headers.FrameDeny=true", - "traefik.http.middlewares.testHeader.Headers.FrameDeny=true",
- "traefik.Middlewares.testHeader.Headers.SSLRedirect=true", - "traefik.http.middlewares.testHeader.Headers.SSLRedirect=true",
``` ```
## Configuration Options ## Configuration Options

View file

@ -12,8 +12,8 @@ IPWhitelist accepts / refuses requests based on the client IP.
??? example "File -- Accepts request from defined IP" ??? example "File -- Accepts request from defined IP"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.test-ipwhitelist.ipWhiteList] [http.middlewares.test-ipwhitelist.ipWhiteList]
sourceRange = ["127.0.0.1/32", "192.168.1.7"] sourceRange = ["127.0.0.1/32", "192.168.1.7"]
``` ```
@ -23,7 +23,7 @@ IPWhitelist accepts / refuses requests based on the client IP.
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.Middlewares.Middleware9.IPWhiteList.SourceRange=127.0.0.1/32, 192.168.1.7" - "traefik.http.middlewares.Middleware9.IPWhiteList.SourceRange=127.0.0.1/32, 192.168.1.7"
``` ```
## Configuration Options ## Configuration Options
@ -55,10 +55,10 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take th
??? example "File -- Whitelisting Based on `X-Forwarded-For` with `depth=2`" ??? example "File -- Whitelisting Based on `X-Forwarded-For` with `depth=2`"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.test-ipwhitelist.ipWhiteList] [http.middlewares.test-ipwhitelist.ipWhiteList]
sourceRange = ["127.0.0.1/32", "192.168.1.7"] sourceRange = ["127.0.0.1/32", "192.168.1.7"]
[Middlewares.test-ipwhitelist.ipWhiteList.ipStrategy] [http.middlewares.test-ipwhitelist.ipWhiteList.ipStrategy]
depth = 2 depth = 2
``` ```
@ -68,8 +68,8 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take th
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.Middlewares.testIPwhitelist.ipWhiteList.SourceRange=127.0.0.1/32, 192.168.1.7" - "traefik.http.middlewares.testIPwhitelist.ipWhiteList.SourceRange=127.0.0.1/32, 192.168.1.7"
- "traefik.middlewares.testIPwhitelist.ipwhitelist.ipstrategy.depth=2" - "traefik.http.middlewares.testIPwhitelist.ipwhitelist.ipstrategy.depth=2"
``` ```
!!! note !!! note
@ -97,9 +97,9 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take th
??? example "File -- Exclude from `X-Forwarded-For`" ??? example "File -- Exclude from `X-Forwarded-For`"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.test-ipwhitelist.ipWhiteList] [http.middlewares.test-ipwhitelist.ipWhiteList]
[Middlewares.test-ipwhitelist.ipWhiteList.ipStrategy] [http.middlewares.test-ipwhitelist.ipWhiteList.ipStrategy]
excludedIPs = ["127.0.0.1/32", "192.168.1.7"] excludedIPs = ["127.0.0.1/32", "192.168.1.7"]
``` ```
@ -109,5 +109,5 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take th
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.middlewares.testIPwhitelist.ipwhitelist.ipstrategy.excludedIPs=127.0.0.1/32, 192.168.1.7" - "traefik.http.middlewares.testIPwhitelist.ipwhitelist.ipstrategy.excludedIPs=127.0.0.1/32, 192.168.1.7"
``` ```

View file

@ -12,8 +12,8 @@ To proactively prevent services from being overwhelmed with high load, a maximum
??? example "File -- Limiting to 10 simultaneous connections" ??? example "File -- Limiting to 10 simultaneous connections"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.test-maxconn.maxconn] [http.middlewares.test-maxconn.maxconn]
amount = 10 amount = 10
``` ```
@ -23,7 +23,7 @@ To proactively prevent services from being overwhelmed with high load, a maximum
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.middlewares.test-maxconn.maxconn.amount=10" - "traefik.http.middlewares.test-maxconn.maxconn.amount=10"
``` ```
## Configuration Options ## Configuration Options

View file

@ -5,7 +5,7 @@ Tweaking the Request
![Overview](../assets/img/middleware/overview.png) ![Overview](../assets/img/middleware/overview.png)
Attached to the routers, pieces of middleware are a mean of tweaking the requests before they are sent to your [service](../routing/services.md) (or before the answer from the services are sent to the clients). Attached to the routers, pieces of middleware are a mean of tweaking the requests before they are sent to your [service](../routing/services/index.md) (or before the answer from the services are sent to the clients).
There are many different available middlewares in Traefik, some can modify the request, the headers, some are in charge of redirections, some add authentication, and so on. There are many different available middlewares in Traefik, some can modify the request, the headers, some are in charge of redirections, some add authentication, and so on.
@ -19,21 +19,21 @@ Pieces of middleware can be combined in chains to fit every scenario.
[providers] [providers]
[providers.file] [providers.file]
[Routers] [http.routers]
[Routers.router1] [http.routers.router1]
Service = "myService" Service = "myService"
Middlewares = ["foo-add-prefix"] Middlewares = ["foo-add-prefix"]
Rule = "Host: example.com" Rule = "Host: example.com"
[Middlewares] [http.middlewares]
[Middlewares.foo-add-prefix.AddPrefix] [http.middlewares.foo-add-prefix.AddPrefix]
prefix = "/foo" prefix = "/foo"
[Services] [http.services]
[Services.service1] [http.services.service1]
[Services.service1.LoadBalancer] [http.services.service1.LoadBalancer]
[[Services.service1.LoadBalancer.Servers]] [[http.services.service1.LoadBalancer.Servers]]
URL = "http://127.0.0.1:80" URL = "http://127.0.0.1:80"
Weight = 1 Weight = 1
``` ```
@ -45,7 +45,7 @@ Pieces of middleware can be combined in chains to fit every scenario.
whoami: whoami:
image: containous/whoami # A container that exposes an API to show its IP address image: containous/whoami # A container that exposes an API to show its IP address
labels: labels:
- "traefik.middlewares.foo-add-prefix.addprefix.prefix=/foo", - "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo",
``` ```
## Advanced Configuration ## Advanced Configuration
@ -63,8 +63,8 @@ If you use multiple `providers` and wish to reference a middleware declared in a
[providers] [providers]
[providers.file] [providers.file]
[middlewares] [http.middlewares]
[middlewares.add-foo-prefix.AddPrefix] [http.middlewares.add-foo-prefix.AddPrefix]
prefix = "/foo" prefix = "/foo"
``` ```
@ -76,7 +76,7 @@ If you use multiple `providers` and wish to reference a middleware declared in a
labels: labels:
# Attach file.add-foo-prefix middleware (declared in file) # Attach file.add-foo-prefix middleware (declared in file)
- "traefik.routers.middlewares=file.add-foo-prefix", - "traefik.http.routers.middlewares=file.add-foo-prefix",
``` ```
## Available Middlewares ## Available Middlewares

View file

@ -12,8 +12,8 @@ PassTLSClientCert adds in header the selected data from the passed client tls ce
??? example "File -- Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header" ??? example "File -- Pass the escaped pem in the `X-Forwarded-Tls-Client-Cert` header"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.test-passtlsclientcert.passtlsclientcert] [http.middlewares.test-passtlsclientcert.passtlsclientcert]
pem = true pem = true
``` ```
@ -23,19 +23,19 @@ PassTLSClientCert adds in header the selected data from the passed client tls ce
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.middlewares.Middleware11.passtlsclientcert.pem=true" - "traefik.http.middlewares.Middleware11.passtlsclientcert.pem=true"
``` ```
??? example "File -- Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header" ??? example "File -- Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.test-passtlsclientcert.passtlsclientcert] [http.middlewares.test-passtlsclientcert.passtlsclientcert]
[Middlewares.test-passtlsclientcert.passtlsclientcert.info] [http.middlewares.test-passtlsclientcert.passtlsclientcert.info]
notAfter = true notAfter = true
notBefore = true notBefore = true
sans = true sans = true
[Middlewares.test-passtlsclientcert.passtlsclientcert.info.subject] [http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject]
country = true country = true
province = true province = true
locality = true locality = true
@ -43,7 +43,7 @@ PassTLSClientCert adds in header the selected data from the passed client tls ce
commonName = true commonName = true
serialNumber = true serialNumber = true
domainComponent = true domainComponent = true
[Middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer] [http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer]
country = true country = true
province = true province = true
locality = true locality = true
@ -59,23 +59,23 @@ PassTLSClientCert adds in header the selected data from the passed client tls ce
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.country=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.country=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.domaincomponent=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.domaincomponent=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.locality=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.locality=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.organization=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.organization=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.province=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.province=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber=true"
``` ```
## Configuration Options ## Configuration Options

View file

@ -12,11 +12,11 @@ The RateLimit middleware ensures that services will receive a _fair_ number of r
??? example "Limit to 100 requests every 10 seconds (with a possible burst of 200)" ??? example "Limit to 100 requests every 10 seconds (with a possible burst of 200)"
```toml ```toml
[middlewares] [http.middlewares]
[middlewares.fair-ratelimit.ratelimit] [http.middlewares.fair-ratelimit.ratelimit]
extractorfunc = "client.ip" extractorfunc = "client.ip"
[middlewares.fair-ratelimit.ratelimit.rateset1] [http.middlewares.fair-ratelimit.ratelimit.rateset1]
period = "10s" period = "10s"
average = 100 average = 100
burst = 200 burst = 200
@ -25,16 +25,16 @@ The RateLimit middleware ensures that services will receive a _fair_ number of r
??? example "Combine multiple limits" ??? example "Combine multiple limits"
```toml ```toml
[middlewares] [http.middlewares]
[middlewares.fair-ratelimit.ratelimit] [http.middlewares.fair-ratelimit.ratelimit]
extractorfunc = "client.ip" extractorfunc = "client.ip"
[middlewares.fair-ratelimit.ratelimit.rateset1] [http.middlewares.fair-ratelimit.ratelimit.rateset1]
period = "10s" period = "10s"
average = 100 average = 100
burst = 200 burst = 200
[middlewares.fair-ratelimit.ratelimit.rateset2] [http.middlewares.fair-ratelimit.ratelimit.rateset2]
period = "3s" period = "3s"
average = 5 average = 5
burst = 10 burst = 10

View file

@ -12,8 +12,8 @@ RegexRedirect redirect a request from an url to another with regex matching and
??? example "File -- Redirect with domain replacement" ??? example "File -- Redirect with domain replacement"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.test-redirectregex.redirectregex] [http.middlewares.test-redirectregex.redirectregex]
regex = "^http://localhost/(.*)" regex = "^http://localhost/(.*)"
replacement = "http://mydomain/$1" replacement = "http://mydomain/$1"
``` ```
@ -24,8 +24,8 @@ RegexRedirect redirect a request from an url to another with regex matching and
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.Middlewares.test-redirectregex.redirectregex.regex=^http://localhost/(.*)" - "traefik.http.middlewares.test-redirectregex.redirectregex.regex=^http://localhost/(.*)"
- "traefik.Middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$1" - "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$1"
``` ```
## Configuration Options ## Configuration Options

View file

@ -12,8 +12,8 @@ RegexRedirect redirect request from a scheme to another.
??? example "File -- Redirect to https" ??? example "File -- Redirect to https"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.test-redirectscheme.redirectscheme] [http.middlewares.test-redirectscheme.redirectscheme]
scheme = "https" scheme = "https"
``` ```
@ -23,7 +23,7 @@ RegexRedirect redirect request from a scheme to another.
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.Middlewares.test-redirectscheme.redirectscheme.scheme=https" - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https"
``` ```
## Configuration Options ## Configuration Options

View file

@ -12,8 +12,8 @@ Replace the path of the request url.
??? example "File -- Replace the path by /foo" ??? example "File -- Replace the path by /foo"
```toml ```toml
[Middlewares] [http.middlewares]
[Middlewares.test-replacepath.ReplacePath] [http.middlewares.test-replacepath.ReplacePath]
path = "/foo" path = "/foo"
``` ```
@ -23,7 +23,7 @@ Replace the path of the request url.
a-container: a-container:
image: a-container-image image: a-container-image
labels: labels:
- "traefik.middlewares.test-replacepath.replacepath.path=/foo" - "traefik.http.middlewares.test-replacepath.replacepath.path=/foo"
``` ```
## Configuration Options ## Configuration Options

View file

@ -8,8 +8,8 @@ Checking the Health of Your Traefik Instances
??? example "Enabling /ping on the http EntryPoint" ??? example "Enabling /ping on the http EntryPoint"
```toml ```toml
[entryPoints] [entrypoints]
[entrypoints.http] [entrypoints.web]
address = ":80" address = ":80"
[ping] [ping]
@ -19,13 +19,13 @@ Checking the Health of Your Traefik Instances
??? example "Enabling /ping on the https EntryPoint" ??? example "Enabling /ping on the https EntryPoint"
```toml ```toml
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":80" address = ":80"
[entryPoints.https] [entrypoints.web-secure]
address = ":443" address = ":443"
[entryPoints.https.tls] [entrypoints.web-secure.tls]
[ping] [ping]
entryPoint = "https" entryPoint = "https"
@ -34,11 +34,11 @@ Checking the Health of Your Traefik Instances
??? example "Enabling /ping on a dedicated EntryPoint" ??? example "Enabling /ping on a dedicated EntryPoint"
```toml ```toml
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":80" address = ":80"
[entryPoints.ping] [entrypoints.ping]
address = ":8082" address = ":8082"
[ping] [ping]

View file

@ -29,7 +29,7 @@ Attach labels to your containers and let Traefik do the rest!
my-container: my-container:
# ... # ...
labels: labels:
- traefik.services.my-container.rule=Host(my-domain) - traefik.http.services.my-container.rule=Host(my-domain)
``` ```
??? example "Configuring Docker Swarm & Deploying / Exposing Services" ??? example "Configuring Docker Swarm & Deploying / Exposing Services"
@ -53,7 +53,7 @@ Attach labels to your containers and let Traefik do the rest!
my-container: my-container:
deploy: deploy:
labels: labels:
- traefik.services.my-container.rule=Host(my-domain) - traefik.http.services.my-container.rule=Host(my-domain)
``` ```
!!! important "Labels in Docker Swarm Mode" !!! important "Labels in Docker Swarm Mode"
@ -193,25 +193,25 @@ Defines the polling interval (in seconds) in Swarm Mode.
### General ### General
Traefik creates, for each container, a corresponding [service](../routing/services.md) and [router](../routing/routers.md). Traefik creates, for each container, a corresponding [service](../routing/services/index.md) and [router](../routing/routers/index.md).
The Service automatically gets a server per instance of the container, and the router gets a default rule attached to it, based on the container name. The Service automatically gets a server per instance of the container, and the router gets a default rule attached to it, based on the container name.
### Routers ### Routers
To update the configuration of the Router automatically attached to the container, add labels starting with `traefik.routers.{name-of-your-choice}.` and followed by the option you want to change. For example, to change the rule, you could add the label `traefik.routers.my-container.rule=Host(my-domain)`. To update the configuration of the Router automatically attached to the container, add labels starting with `traefik.routers.{name-of-your-choice}.` and followed by the option you want to change. For example, to change the rule, you could add the label `traefik.http.routers.my-container.rule=Host(my-domain)`.
Every [Router](../routing/routers.md) parameter can be updated this way. Every [Router](../routing/routers/index.md) parameter can be updated this way.
### Services ### Services
To update the configuration of the Service automatically attached to the container, add labels starting with `traefik.services.{name-of-your-choice}.`, followed by the option you want to change. For example, to change the load balancer method, you'd add the label `traefik.services.{name-of-your-choice}.loadbalancer.method=drr`. To update the configuration of the Service automatically attached to the container, add labels starting with `traefik.http.services.{name-of-your-choice}.`, followed by the option you want to change. For example, to change the load balancer method, you'd add the label `traefik.http.services.{name-of-your-choice}.loadbalancer.method=drr`.
Every [Service](../routing/services.md) parameter can be updated this way. Every [Service](../routing/services/index.md) parameter can be updated this way.
### Middleware ### Middleware
You can declare pieces of middleware using labels starting with `traefik.middlewares.{name-of-your-choice}.`, followed by the middleware type/options. For example, to declare a middleware [`schemeredirect`](../middlewares/redirectscheme.md) named `my-redirect`, you'd write `traefik.middlewares.my-redirect.schemeredirect.scheme: https`. You can declare pieces of middleware using labels starting with `traefik.http.middlewares.{name-of-your-choice}.`, followed by the middleware type/options. For example, to declare a middleware [`schemeredirect`](../middlewares/redirectscheme.md) named `my-redirect`, you'd write `traefik.http.middlewares.my-redirect.schemeredirect.scheme: https`.
??? example "Declaring and Referencing a Middleware" ??? example "Declaring and Referencing a Middleware"
@ -220,8 +220,8 @@ You can declare pieces of middleware using labels starting with `traefik.middlew
my-container: my-container:
# ... # ...
labels: labels:
- traefik.middlewares.my-redirect.schemeredirect.scheme=https - traefik.http.middlewares.my-redirect.schemeredirect.scheme=https
- traefik.routers.middlewares=my-redirect - traefik.http.routers.middlewares=my-redirect
``` ```
!!! warning "Conflicts in Declaration" !!! warning "Conflicts in Declaration"

View file

@ -7,12 +7,11 @@ Every Options for ACME
```toml ```toml
# Sample entrypoint configuration when using ACME. # Sample entrypoint configuration when using ACME.
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":80" address = ":80"
[entryPoints.https] [entrypoints.web-secure]
address = ":443" address = ":443"
[entryPoints.https.tls]
# Enable ACME (Let's Encrypt): automatic SSL. # Enable ACME (Let's Encrypt): automatic SSL.
[acme] [acme]
@ -36,12 +35,6 @@ Every Options for ACME
storage = "acme.json" storage = "acme.json"
# or `storage = "traefik/acme/account"` if using KV store. # or `storage = "traefik/acme/account"` if using KV store.
# Entrypoint to proxy acme apply certificates to.
#
# Required
#
entryPoint = "https"
# Deprecated, replaced by [acme.dnsChallenge]. # Deprecated, replaced by [acme.dnsChallenge].
# #
# Optional. # Optional.

View file

@ -6,86 +6,21 @@ Every Options for EntryPoints
## TOML ## TOML
```toml ```toml
defaultEntryPoints = ["http", "https"]
# ...
# ... # ...
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":80" address = ":80"
[entryPoints.http.compress]
[entryPoints.http.clientIPStrategy] [entrypoints.web.proxyProtocol]
depth = 5
excludedIPs = ["127.0.0.1/32", "192.168.1.7"]
[entryPoints.http.whitelist]
sourceRange = ["10.42.0.0/16", "152.89.1.33/32", "afed:be44::/16"]
[entryPoints.http.whitelist.IPStrategy]
depth = 5
excludedIPs = ["127.0.0.1/32", "192.168.1.7"]
[entryPoints.http.tls]
minVersion = "VersionTLS12"
cipherSuites = [
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_256_GCM_SHA384"
]
[[entryPoints.http.tls.certificates]]
certFile = "path/to/my.cert"
keyFile = "path/to/my.key"
[[entryPoints.http.tls.certificates]]
certFile = "path/to/other.cert"
keyFile = "path/to/other.key"
# ...
[entryPoints.http.tls.clientCA]
files = ["path/to/ca1.crt", "path/to/ca2.crt"]
optional = false
[entryPoints.http.redirect]
entryPoint = "https"
regex = "^http://localhost/(.*)"
replacement = "http://mydomain/$1"
permanent = true
[entryPoints.http.auth]
headerField = "X-WebAuth-User"
[entryPoints.http.auth.basic]
removeHeader = true
realm = "Your realm"
users = [
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
]
usersFile = "/path/to/.htpasswd"
[entryPoints.http.auth.digest]
removeHeader = true
users = [
"test:traefik:a2688e031edb4be6a3797f3882655c05",
"test2:traefik:518845800f9e2bfb1f1f740ec24f074e",
]
usersFile = "/path/to/.htdigest"
[entryPoints.http.auth.forward]
address = "https://authserver.com/auth"
trustForwardHeader = true
authResponseHeaders = ["X-Auth-User"]
[entryPoints.http.auth.forward.tls]
ca = "path/to/local.crt"
caOptional = true
cert = "path/to/foo.cert"
key = "path/to/foo.key"
insecureSkipVerify = true
[entryPoints.http.proxyProtocol]
insecure = true insecure = true
trustedIPs = ["10.10.10.1", "10.10.10.2"] trustedIPs = ["10.10.10.1", "10.10.10.2"]
[entryPoints.http.forwardedHeaders] [entrypoints.web.forwardedHeaders]
trustedIPs = ["10.10.10.1", "10.10.10.2"] trustedIPs = ["10.10.10.1", "10.10.10.2"]
insecure = false insecure = false
[entryPoints.https] [entrypoints.web-secure]
# ... # ...
``` ```
@ -94,38 +29,7 @@ defaultEntryPoints = ["http", "https"]
```ini ```ini
Name:foo Name:foo
Address::80 Address::80
TLS:/my/path/foo.cert,/my/path/foo.key;/my/path/goo.cert,/my/path/goo.key;/my/path/hoo.cert,/my/path/hoo.key
TLS
TLS.MinVersion:VersionTLS11
TLS.CipherSuites:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384
TLS.SniStrict:true
TLS.DefaultCertificate.Cert:path/to/foo.cert
TLS.DefaultCertificate.Key:path/to/foo.key
CA:car
CA.Optional:true
Redirect.EntryPoint:https
Redirect.Regex:http://localhost/(.*)
Redirect.Replacement:http://mydomain/$1
Redirect.Permanent:true
Compress:true
WhiteList.SourceRange:10.42.0.0/16,152.89.1.33/32,afed:be44::/16
WhiteList.IPStrategy.depth:3
WhiteList.IPStrategy.ExcludedIPs:10.0.0.3/24,20.0.0.3/24
ProxyProtocol.TrustedIPs:192.168.0.1 ProxyProtocol.TrustedIPs:192.168.0.1
ProxyProtocol.Insecure:true ProxyProtocol.Insecure:true
ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24 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.Basic.Realm:traefik
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
``` ```

View file

@ -6,75 +6,38 @@ Opening Connections for Incomming Requests
![EntryPoints](../assets/img/entrypoints.png) ![EntryPoints](../assets/img/entrypoints.png)
Entrypoints are the network entry points into Traefik. Entrypoints are the network entry points into Traefik.
They can be defined using: They define the port which will receive the requests (whether HTTP or TCP).
- a port (80, 443, ...)
- SSL (Certificates, Keys, authentication with a client certificate signed by a trusted CA, ...)
## Configuration Examples ## Configuration Examples
??? example "HTTP only" ??? example "Port 80 only"
```toml ```toml
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":80" address = ":80"
``` ```
We define an `entrypoint` called `http` that will listen on port `80`. We define an `entrypoint` called `web` that will listen on port `80`.
??? example "HTTP & HTTPS" ??? example "Port 80 & 443"
```toml ```toml
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":80" address = ":80"
[entryPoints.https] [entrypoints.web-secure]
address = ":443" address = ":443"
[entryPoints.https.tls] [entrypoints.web-secure.tls]
[[entryPoints.https.tls.certificates]] [[entrypoints.web-secure.tls.certificates]]
certFile = "tests/traefik.crt" certFile = "tests/traefik.crt"
keyFile = "tests/traefik.key" keyFile = "tests/traefik.key"
``` ```
- Two entrypoints are defined: one called `http`, and the other called `https`. - Two entrypoints are defined: one called `web`, and the other called `web-secure`.
- `http` listens on port `80`, and `https` on port `443`. - `web` listens on port `80`, and `web-secure` on port `443`.
- We enabled SSL on `https` by giving it a certificate and a key.
!!! note
In the example, `http` and `https` are the names for the entrypoints and have nothing to do with the underlying protocol.
We could have written `entryPoints.foo` and `entryPoints.bar` instead.
!!! tip "Automatic HTTPS with ACME"
If you don't have certificate files and wish to automatically enable HTTPS, you should have a look at one of Traefik's most praised feature: [ACME & Let's Encrypt integration](./acme.md)
??? example "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 enabled SSL on `https` by giving it a certificate and a key.
- Files containing Certificate Authorities (PEM format) were added.
!!! note "Multiple CAs"
It is possible to have multiple CA:s in the same file or keep them in separate files.
## Configuration ## Configuration
@ -115,130 +78,6 @@ Entrypoints are part of the [static configuration](../getting-started/configurat
command: --defaultentrypoints=powpow --entryPoints='Name:powpow Address::42 Compress:true' command: --defaultentrypoints=powpow --entryPoints='Name:powpow Address::42 Compress:true'
``` ```
## TLS
### Static Certificates
To add SNI support, define `certFile` and `keyFile`.
```toml
[entryPoints]
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "integration/fixtures/https/snitest.com.cert"
keyFile = "integration/fixtures/https/snitest.com.key"
```
!!! note
If you provide an empty TLS configuration, default self-signed certificates will be generated.
### Dynamic Certificates
To add / remove TLS certificates while Traefik is running, the [file provider](../providers/file.md) supports Dynamic TLS certificates in its `[[tls]]` section.
### Mutual Authentication
Traefik supports both optional and non optional (defaut value) mutual authentication.
- When `optional = false`, Traefik accepts connections only from client presenting a certificate signed by a CA listed in `ClientCA.files`.
- When `optional = true`, Traefik authorizes connections from client presenting a certificate signed by an unknown CA.
??? example "Non Optional Mutual Authentication"
In the following example, both `snitest.com` and `snitest.org` will require client certificates.
```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 = "integration/fixtures/https/snitest.com.cert"
keyFile = "integration/fixtures/https/snitest.com.key"
[[entryPoints.https.tls.certificates]]
certFile = "integration/fixtures/https/snitest.org.cert"
keyFile = "integration/fixtures/https/snitest.org.key"
```
!!! note "ClientCA.files"
You can use a file per `CA:s`, or a single file containing multiple `CA:s` (in `PEM` format).
`ClientCA.files` is not optional: every client will have to present a valid certificate. (This requirement will apply to every server certificate declared in the entrypoint.)
### Minimum TLS Version
??? example "Min TLS version & [cipherSuites](https://godoc.org/crypto/tls#pkg-constants)"
```toml
[entryPoints]
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
minVersion = "VersionTLS12"
cipherSuites = [
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_256_GCM_SHA384"
]
[[entryPoints.https.tls.certificates]]
certFile = "integration/fixtures/https/snitest.com.cert"
keyFile = "integration/fixtures/https/snitest.com.key"
[[entryPoints.https.tls.certificates]]
certFile = "integration/fixtures/https/snitest.org.cert"
keyFile = "integration/fixtures/https/snitest.org.key"
```
### Strict SNI Checking
With strict SNI checking, Traefik won't allow connections without a matching certificate.
??? example "Strict SNI"
```toml
[entryPoints]
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
sniStrict = true
[[entryPoints.https.tls.certificates]]
certFile = "integration/fixtures/https/snitest.com.cert"
keyFile = "integration/fixtures/https/snitest.com.key"
```
### Default Certificate
Traefik can use a default certificate for connections without an SNI, or without a matching domain.
If no default certificate is provided, Traefik generates a self-signed and use it instead.
??? example "Setting a Default Certificate"
```toml
[entryPoints]
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[entryPoints.https.tls.defaultCertificate]
certFile = "integration/fixtures/https/snitest.com.cert"
keyFile = "integration/fixtures/https/snitest.com.key"
```
!!! note "Only One Default Certificate"
There can only be one `defaultCertificate` per entrypoint.
## ProxyProtocol ## ProxyProtocol
Traefik supports [ProxyProtocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt). Traefik supports [ProxyProtocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt).
@ -246,11 +85,11 @@ Traefik supports [ProxyProtocol](https://www.haproxy.org/download/1.8/doc/proxy-
??? example "Enabling Proxy Protocol with Trusted IPs" ??? example "Enabling Proxy Protocol with Trusted IPs"
```toml ```toml
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":80" address = ":80"
[entryPoints.http.proxyProtocol] [entrypoints.web.proxyProtocol]
trustedIPs = ["127.0.0.1/32", "192.168.1.7"] trustedIPs = ["127.0.0.1/32", "192.168.1.7"]
``` ```
@ -261,11 +100,11 @@ Traefik supports [ProxyProtocol](https://www.haproxy.org/download/1.8/doc/proxy-
In a test environments, you can configure Traefik to trust every incomming connection. Doing so, every remote client address will be replaced (`trustedIPs` won't have any effect) In a test environments, you can configure Traefik to trust every incomming connection. Doing so, every remote client address will be replaced (`trustedIPs` won't have any effect)
```toml ```toml
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":80" address = ":80"
[entryPoints.http.proxyProtocol] [entrypoints.web.proxyProtocol]
insecure = true insecure = true
``` ```
@ -281,21 +120,21 @@ You can configure Traefik to trust the forwarded headers information (`X-Forward
??? example "Trusting Forwarded Headers from specific IPs" ??? example "Trusting Forwarded Headers from specific IPs"
```toml ```toml
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":80" address = ":80"
[entryPoints.http.forwardedHeaders] [entrypoints.web.forwardedHeaders]
trustedIPs = ["127.0.0.1/32", "192.168.1.7"] trustedIPs = ["127.0.0.1/32", "192.168.1.7"]
``` ```
??? example "Insecure Mode -- Always Trusting Forwarded Headers" ??? example "Insecure Mode -- Always Trusting Forwarded Headers"
```toml ```toml
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":80" address = ":80"
[entryPoints.http.forwardedHeaders] [entrypoints.web.forwardedHeaders]
insecure = true insecure = true
``` ```

View file

@ -5,18 +5,18 @@ What's Happening to the Requests?
Let's zoom on Traefik's architecture and talk about the components that enable the routes to be created. Let's zoom on Traefik's architecture and talk about the components that enable the routes to be created.
First, when you start Traefik, you define [entrypoints](./entrypoints.md) (in their most basic forms, they are port numbers). First, when you start Traefik, you define [entrypoints](../entrypoints) (in their most basic forms, they are port numbers).
Then, connected to these entrypoints, [routers](./routers.md) analyze the incoming requests to see if they match a set of [rules](../routers#rule). Then, connected to these entrypoints, [routers](../routers) analyze the incoming requests to see if they match a set of [rules](../routers#rule).
If they do, the router might transform the request using pieces of [middleware](../middlewares/overview.md) before forwarding them to your [services](./services.md). If they do, the router might transform the request using pieces of [middleware](../middlewares/overview.md) before forwarding them to your [services](./services/index.md).
![Architecture](../assets/img/architecture-overview.png) ![Architecture](../assets/img/architecture-overview.png)
## Clear Responsibilities ## Clear Responsibilities
- [_Providers_](../providers/overview.md) discover the services that live on your infrastructure (their IP, health, ...) - [_Providers_](../providers/overview.md) discover the services that live on your infrastructure (their IP, health, ...)
- [_Entrypoints_](./entrypoints.md) listen for incomming traffic (ports, SSL, ...) - [_Entrypoints_](./entrypoints.md) listen for incomming traffic (ports, ...)
- [_Routers_](./routers.md) analyse the requests (host, path, headers, ...) - [_Routers_](./routers/index.md) analyse the requests (host, path, headers, SSL, ...)
- [_Services_](./services.md) forward the request to your services (load balancing, ...) - [_Services_](./services/index.md) forward the request to your services (load balancing, ...)
- [_Middlewares_](../middlewares/overview.md) may update the request or make decisions based on the request (authentication, rate limiting, headers, ...) - [_Middlewares_](../middlewares/overview.md) may update the request or make decisions based on the request (authentication, rate limiting, headers, ...)
## Example with a File Provider ## Example with a File Provider
@ -25,27 +25,27 @@ Below is an example of a full configuration file for the [file provider](../prov
In the process, Traefik will make sure that the user is authenticated (using the [BasicAuth middleware](../middlewares/basicauth.md)). In the process, Traefik will make sure that the user is authenticated (using the [BasicAuth middleware](../middlewares/basicauth.md)).
```toml ```toml
[EntryPoints] [entrypoints]
[EntryPoints.http] [entrypoints.web]
address = ":8081" # Listen on port 8081 for incoming requests address = ":8081" # Listen on port 8081 for incoming requests
[Providers] [providers]
# Enable the file provider to define routers / middlewares / services in a file [providers.file] # Enable the file provider to define routers / middlewares / services in a file
[Providers.file]
[Routers] [http] # http routing section
[Routers.to-whoami] # Define a connection between requests and services [http.routers]
[http.routers.to-whoami] # Define a connection between requests and services
rule = "Host(domain) && PathPrefix(/whoami/)" rule = "Host(domain) && PathPrefix(/whoami/)"
middlewares = ["test-user"] # If the rule matches, applies the middleware middlewares = ["test-user"] # If the rule matches, applies the middleware
service = "whoami" # If the rule matches, forward to the whoami service (declared below) service = "whoami" # If the rule matches, forward to the whoami service (declared below)
[Middlewares] [http.middlewares]
[Middlewares.test-user.basicauth] # Define an authentication mechanism [http.middlewares.test-user.basicauth] # Define an authentication mechanism
users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"] users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"]
[Services] [http.services]
[Services.whoami.loadbalancer] # Define how to reach an existing service on our infrastructure [http.services.whoami.loadbalancer] # Define how to reach an existing service on our infrastructure
[[Services.whoami.loadbalancer.servers]] [[http.services.whoami.loadbalancer.servers]]
url = "http://private/whoami-service" url = "http://private/whoami-service"
``` ```
@ -53,3 +53,47 @@ In the process, Traefik will make sure that the user is authenticated (using the
In this example, we use the [file provider](../providers/file.md). In this example, we use the [file provider](../providers/file.md).
Even if it is one of the least magical way of configuring Traefik, it explicitly describes every available notion. Even if it is one of the least magical way of configuring Traefik, it explicitly describes every available notion.
!!! note "HTTP / TCP"
In this example, we've defined routing rules for http requests only.
Traefik also supports TCP requests. To add [TCP routers](./routers/index.md) and [TCP services](./services/index.md), declare them in a TCP section like in the following.
??? example "Adding a TCP route for TLS requests on whoami.traefik.io"
```toml
[entrypoints]
[entrypoints.web]
address = ":8081" # Listen on port 8081 for incoming requests
[providers]
[providers.file] # Enable the file provider to define routers / middlewares / services in a file
[http] # http routing section
[http.routers]
[http.routers.to-whoami] # Define a connection between requests and services
rule = "Host(`domain`) && PathPrefix(/whoami/)"
middlewares = ["test-user"] # If the rule matches, applies the middleware
service = "whoami" # If the rule matches, forward to the whoami service (declared below)
[http.middlewares]
[http.middlewares.test-user.basicauth] # Define an authentication mechanism
users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"]
[http.services]
[http.services.whoami.loadbalancer] # Define how to reach an existing service on our infrastructure
[[http.services.whoami.loadbalancer.servers]]
url = "http://private/whoami-service"
[tcp]
[tcp.routers]
[tcp.routers.to-whoami-tcp]
rule = "HostSNI(`whoami-tcp.traefik.io`)"
service = "whoami-tcp"
[tcp.routers.to-whoami-tcp.tls]
[tcp.services]
[tcp.services.whoami-tcp.loadbalancer]
[[tcp.services.whoami-tcp.loadbalancer.servers]]
address = "xx.xx.xx.xx:xx"
```

View file

@ -1,134 +0,0 @@
# Routers
Connecting Requests to Services
{: .subtitle }
![Routers](../assets/img/routers.png)
A router is in charge of connecting incoming requests to the services that can handle them.
In the process, routers may use pieces of [middleware](../middlewares/overview.md) to update the request, or act before forwarding the request to the service.
## Configuration Example
??? example "Requests /foo are Handled by service-foo -- Using the [File Provider](../providers/file.md)"
```toml
[Routers]
[Routers.my-router]
rule = "Path(/foo)"
service = "service-foo"
```
??? example "With a [Middleware](../middlewares/overview.md) -- using the [File Provider](../providers/file.md)"
```toml
[Routers]
[Routers.my-router]
rule = "Path(/foo)"
middlewares = ["authentication"] # declared elsewhere
service = "service-foo"
```
## Configuration
### EntryPoints
If not specified, routers will accept requests from all defined entrypoints.
If you want to limit the router scope to a set of entrypoint, set the entrypoints option.
??? example "Listens to Every EntryPoint"
```toml
[EntryPoints]
[EntryPoint.http]
# ...
[EntryPoint.https]
# ...
[EntryPoint.other]
# ...
[Routers]
[Routers.Router-1]
# By default, routers listen to every entrypoints
rule = "Host(traefik.io)"
service = "service-1"
```
??? example "Listens to Specific EntryPoints"
```toml
[EntryPoints]
[EntryPoint.http]
# ...
[EntryPoint.https]
# ...
[EntryPoint.other]
# ...
[Routers]
[Routers.Router-1]
entryPoints = ["https", "other"] # won't listen to entrypoint http
rule = "Host(traefik.io)"
service = "service-1"
```
### Rule
Rules are a set of matchers that determine if a particular request matches specific criteria.
If the rule is verified, then the router becomes active and calls middlewares, then forward the request to the service.
??? example "Host is traefik.io"
```
rule = "Host(`traefik.io`)"
```
??? example "Host is traefik.io OR Host is containo.us AND path is /traefik"
```
rule = "Host(`traefik.io`) || (Host(`containo.us`) && Path(`/traefik`))"
```
The table below lists all the available matchers:
| Rule | Description |
|--------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|
| ``Headers(`key`, `value`)`` | Check if there is a key `key`defined in the headers, with the value `value` |
| ``HeadersRegexp(`key`, `regexp`)`` | Check if there is a key `key`defined in the headers, with a value that matches the regular expression `regexp` |
| ``Host(`domain-1`, ...)`` | Check if the request domain targets one of the given `domains`. |
| ``HostRegexp(`traefik.io`, `{subdomain:[a-z]+}.traefik.io`, ...)`` | Check if the request domain matches the given `regexp`. |
| `Method(methods, ...)` | Check if the request method is one of the given `methods` (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`) |
| ``Path(`path`, `/articles/{category}/{id:[0-9]+}`, ...)`` | Match exact request path. 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. |
| ``Query(`foo=bar`, `bar=baz`)`` | Match` Query String parameters. It accepts a sequence of key=value pairs. |
!!! important "Regexp Syntax"
In order to use regular expressions with `Host` and `Path` expressions,
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]+}`).
!!! tip "Combining Matchers Using Operators and Parenthesis"
You can combine multiple matchers using the AND (`&&`) and OR (`||) operators. You can also use parenthesis.
!!! important "Rule, Middleware, and Services"
The rule is evaluated "before" any middleware has the opportunity to work, and "before" the request is forwarded to the service.
!!! tip "Path Vs PathPrefix"
Use `Path` if your service listens on the exact path only. For instance, `Path: /products` would match `/products` but not `/products/shoes`.
Use a `*Prefix*` matcher if your service 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 service is expected to listen on `/products`.
### Middlewares
You can attach a list of [middlewares](../middlewares/overview.md) to the routers.
The middlewares will take effect only if the rule matches, and before forwarding the request to the service.
### Service
You must attach a [service](./services.md) per router.
Services are the target for the router.

View file

@ -0,0 +1,4 @@
{
"extends": "../../../.markdownlint.json",
"MD024": false
}

View file

@ -0,0 +1,298 @@
# Routers
Connecting Requests to Services
{: .subtitle }
![routers](../../assets/img/routers.png)
A router is in charge of connecting incoming requests to the services that can handle them.
In the process, routers may use pieces of [middleware](../../middlewares/overview.md) to update the request, or act before forwarding the request to the service.
## Configuration Example
??? example "Requests /foo are Handled by service-foo -- Using the [File Provider](../../providers/file.md)"
```toml
[http.routers]
[http.routers.my-router]
rule = "Path(/foo)"
service = "service-foo"
```
??? example "With a [middleware](../../middlewares/overview.md) -- using the [File Provider](../../providers/file.md)"
```toml
[http.routers]
[http.routers.my-router]
rule = "Path(/foo)"
middlewares = ["authentication"] # declared elsewhere
service = "service-foo"
```
??? example "Forwarding all (non-tls) requests on port 3306 to a database service"
```toml
[entrypoints]
[entrypoints.mysql-default]
address = ":80"
[entrypoints.mysql-default]
address = ":3306"
[tcp]
[tcp.routers]
[tcp.routers.to-database]
entrypoints = ["mysql-default"]
rule = "HostSNI(`*`)" # Catch every request (only available rule for non-tls routers. See below.)
service = "database"
```
## Configuring HTTP Routers
### EntryPoints
If not specified, HTTP routers will accept requests from all defined entrypoints.
If you want to limit the router scope to a set of entrypoint, set the entrypoints option.
??? example "Listens to Every EntryPoint"
```toml
[entrypoints]
[entrypoints.web]
# ...
[entrypoints.web-secure]
# ...
[entrypoints.other]
# ...
[http.routers]
[http.routers.Router-1]
# By default, routers listen to every entrypoints
rule = "Host(traefik.io)"
service = "service-1"
```
??? example "Listens to Specific EntryPoints"
```toml
[entrypoints]
[entrypoints.web]
# ...
[entrypoint.web-secure]
# ...
[entrypoint.other]
# ...
[http.routers]
[http.routers.Router-1]
entryPoints = ["web-secure", "other"] # won't listen to entrypoint web
rule = "Host(traefik.io)"
service = "service-1"
```
### Rule
Rules are a set of matchers that determine if a particular request matches specific criteria.
If the rule is verified, then the router becomes active and calls middlewares, then forward the request to the service.
??? example "Host is traefik.io"
```toml
rule = "Host(`traefik.io`)"
```
??? example "Host is traefik.io OR Host is containo.us AND path is /traefik"
```toml
rule = "Host(`traefik.io`) || (Host(`containo.us`) && Path(`/traefik`))"
```
The table below lists all the available matchers:
| Rule | Description |
|--------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|
| ``Headers(`key`, `value`)`` | Check if there is a key `key`defined in the headers, with the value `value` |
| ``HeadersRegexp(`key`, `regexp`)`` | Check if there is a key `key`defined in the headers, with a value that matches the regular expression `regexp` |
| ``Host(`domain-1`, ...)`` | Check if the request domain targets one of the given `domains`. |
| ``HostRegexp(`traefik.io`, `{subdomain:[a-z]+}.traefik.io`, ...)`` | Check if the request domain matches the given `regexp`. |
| `Method(methods, ...)` | Check if the request method is one of the given `methods` (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`) |
| ``Path(`path`, `/articles/{category}/{id:[0-9]+}`, ...)`` | Match exact request path. 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. |
| ``Query(`foo=bar`, `bar=baz`)`` | Match` Query String parameters. It accepts a sequence of key=value pairs. |
!!! important "Regexp Syntax"
In order to use regular expressions with `Host` and `Path` expressions,
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]+}`).
!!! tip "Combining Matchers Using Operators and Parenthesis"
You can combine multiple matchers using the AND (`&&`) and OR (`||) operators. You can also use parenthesis.
!!! important "Rule, Middleware, and Services"
The rule is evaluated "before" any middleware has the opportunity to work, and "before" the request is forwarded to the service.
!!! tip "Path Vs PathPrefix"
Use `Path` if your service listens on the exact path only. For instance, `Path: /products` would match `/products` but not `/products/shoes`.
Use a `*Prefix*` matcher if your service 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 service is expected to listen on `/products`.
### Middlewares
You can attach a list of [middlewares](../../middlewares/overview.md) to each HTTP router.
The middlewares will take effect only if the rule matches, and before forwarding the request to the service.
### Service
You must attach a [service](../services/index.md) per router.
Services are the target for the router.
!!! note "HTTP Only"
HTTP routers can only target HTTP services (not TCP services).
### TLS
When specifying a TLS section, you tell Traefik that the current router is dedicated to HTTPS requests only (and that the router should ignore HTTP (non tls) requests).
Traefik will terminate the SSL connections (meaning that it will send decrypted data to the services).
??? example "Configuring the router to accept HTTPS requests only"
```toml
[http.routers]
[http.routers.Router-1]
rule = "Host(`foo-domain`) && Path(`/foo-path/`)"
service = "service-id"
[http.routers.Router-1.tls] # will terminate the TLS request
```
!!! note "HTTPS & ACME"
In the current version, with [ACME](../../https-tls/acme.md) enabled, automatic certificate generation will apply to every router declaring a TLS section.
In the near future, options will be available to enable fine-grain control of the TLS parameters.
!!! note "Passthrough"
On TCP routers, you can configure a passthrough option so that Traefik doesn't terminate the TLS connection.
!!! important "Routers for HTTP & HTTPS"
If you need to define the same route for both HTTP and HTTPS requests, you will need to define two different routers: one with the tls section, one without.
??? example "HTTP & HTTPS routes"
```toml
[http.routers]
[http.routers.Router-1-https]
rule = "Host(`foo-domain`) && Path(`/foo-path/`)"
service = "service-id"
[http.routers.Router-1.tls] # will terminate the TLS request
[http.routers.Router-1-http]
rule = "Host(`foo-domain`) && Path(`/foo-path/`)"
service = "service-id"
```
## Configuring TCP Routers
### General
If both HTTP routers and TCP routers listen to the same entrypoints, the TCP routers will apply *before* the HTTP routers.
If no matching route is found for the TCP routers, then the HTTP routers will take over.
### EntryPoints
If not specified, TCP routers will accept requests from all defined entrypoints.
If you want to limit the router scope to a set of entrypoints, set the entrypoints option.
??? example "Listens to Every EntryPoint"
```toml
[entrypoints]
[entrypoints.web]
# ...
[entrypoints.web-secure]
# ...
[entrypoints.other]
# ...
[tcp.routers]
[tcp.routers.Router-1]
# By default, routers listen to every entrypoints
rule = "Host(traefik.io)"
service = "service-1"
```
??? example "Listens to Specific EntryPoints"
```toml
[entrypoints]
[entrypoints.web]
# ...
[entrypoint.web-secure]
# ...
[entrypoint.other]
# ...
[tcp.routers]
[tcp.routers.Router-1]
entryPoints = ["web-secure", "other"] # won't listen to entrypoint web
rule = "Host(traefik.io)"
service = "service-1"
[tcp.routers.Router-1.tls] # will route TLS requests (and ignore non tls requests)
```
### Rule
| Rule | Description |
|--------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|
| ``HostSNI(`domain-1`, ...)`` | Check if the Server Name Indication corresponds to the given `domains`. |
!!! important "HostSNI & TLS"
It is important to note that the Server Name Indication is an extension of the TLS protocol.
Hence, only TLS routers will be able to specify a domain name with that rule.
However, non-TLS routers will have to explicitly use that rule with `*` (every domain) to state that every non-TLS request will be handled by the router.
### Services
You must attach a TCP [service](../services/index.md) per TCP router.
Services are the target for the router.
!!! note "TCP Only"
TCP routers can only target TCP services (not HTTP services).
### TLS
When specifying a TLS section, you tell Traefik that the current router is dedicated to TLS requests only (and that the router should ignore non-tls requests).
By default, Traefik will terminate the SSL connections (meaning that it will send decrypted data to the services), but you can tell Traefik that the request should pass through (keeping the encrypted data) and be forwarded to the service "as is".
??? example "Configuring TLS Termination"
```toml
[tcp.routers]
[tcp.routers.Router-1]
rule = "Host(`foo-domain`)"
service = "service-id"
[tcp.routers.Router-1.tls] # will terminate the TLS request by default
```
??? example "Configuring passthrough"
```toml
[tcp.routers]
[tcp.routers.Router-1]
rule = "Host(`foo-domain`)"
service = "service-id"
[tcp.routers.Router-1.tls]
passthrough=true
```
!!! note "TLS & ACME"
In the current version, with [ACME](../../https-tls/acme.md) enabled, automatic certificate generation will apply to every router declaring a TLS section.
In the near future, options will be available to enable fine-grain control of the TLS parameters.

View file

@ -0,0 +1,4 @@
{
"extends": "../../../.markdownlint.json",
"MD024": false
}

View file

@ -3,50 +3,61 @@
Configuring How to Reach the Services Configuring How to Reach the Services
{: .subtitle } {: .subtitle }
![Services](../assets/img/services.png) ![services](../../assets/img/services.png)
The `Services` are responsible for configuring how to reach the actual services that will eventually handle the incoming requests. The `Services` are responsible for configuring how to reach the actual services that will eventually handle the incoming requests.
## Configuration Example ## Configuration Example
??? example "Declaring a Service with Two Servers (with Load Balancing) -- Using the [File Provider](../providers/file.md)" ??? example "Declaring an HTTP Service with Two Servers -- Using the [File Provider](../../providers/file.md)"
```toml ```toml
[Services] [http.services]
[Services.my-service.LoadBalancer] [http.services.my-service.LoadBalancer]
method = "wrr" # Load Balancing based on weights method = "wrr" # Load Balancing based on weights
[[Services.my-service.LoadBalancer.servers]] [[http.services.my-service.LoadBalancer.servers]]
url = "http://private-ip-server-1/" url = "http://private-ip-server-1/"
weight = 30 # 30% of the requests will go to that instance weight = 30 # 30% of the requests will go to that instance
[[Services.my-service.LoadBalancer.servers]] [[http.services.my-service.LoadBalancer.servers]]
url = "http://private-ip-server-2/" url = "http://private-ip-server-2/"
weight = 70 # 70% of the requests will go to that instance weight = 70 # 70% of the requests will go to that instance
``` ```
## Configuration ??? example "Declaring a TCP Service with Two Servers -- Using the [File Provider](../../providers/file.md)"
```toml
[tcp.services]
[tcp.services.my-service.LoadBalancer]
[[tcp.services.my-service.LoadBalancer.servers]]
address = "xx.xx.xx.xx:xx"
[[tcp.services.my-service.LoadBalancer.servers]]
address = "xx.xx.xx.xx:xx"
```
## Configuring HTTP Services
### General ### General
Currently, the `LoadBalancer` service is the only supported kind of `Service` (see below). Currently, `LoadBalancer` is the only supported kind of HTTP `Service` (see below).
However, since Traefik is an ever evolving project, other kind of Services will be available in the future, However, since Traefik is an ever evolving project, other kind of HTTP Services will be available in the future,
reason why you have to specify what kind of service you declare. reason why you have to specify it.
### Load Balancer ### Load Balancer
The `LoadBalancer` service is able to load balance the requests between multiple instances of your programs. The load balancers are able to load balance the requests between multiple instances of your programs.
??? example "Declaring a Service with Two Servers (with Load Balancing) -- Using the [File Provider](../providers/file.md)" ??? example "Declaring a Service with Two Servers (with Load Balancing) -- Using the [File Provider](../../providers/file.md)"
```toml ```toml
[Services] [http.services]
[Services.my-service.LoadBalancer] [http.services.my-service.LoadBalancer]
method = "wrr" # Load Balancing based on weights method = "wrr" # Load Balancing based on weights
[[Services.my-service.LoadBalancer.servers]] [[http.services.my-service.LoadBalancer.servers]]
url = "http://private-ip-server-1/" url = "http://private-ip-server-1/"
weight = 50 # 50% of the requests will go to that instance weight = 50 # 50% of the requests will go to that instance
[[Services.my-service.LoadBalancer.servers]] [[http.services.my-service.LoadBalancer.servers]]
url = "http://private-ip-server-2/" url = "http://private-ip-server-2/"
weight = 50 # 50% of the requests will go to that instance weight = 50 # 50% of the requests will go to that instance
``` ```
@ -60,14 +71,14 @@ The `weight` option defines the weight of the server for the load balancing algo
!!! note !!! note
Paths in the servers' `url` have no effet. Paths in the servers' `url` have no effet.
If you want the requests to be sent to a specific path on your servers, If you want the requests to be sent to a specific path on your servers,
configure your [`routers`](./routers.md) to use a corresponding [Middleware](../middlewares/overview.md) (e.g. the [AddPrefix](../middlewares/addprefix.md) or [ReplacePath](../middlewares/replacepath.md)) middlewares. configure your [`routers`](../routers/index.md) to use a corresponding [middleware](../../middlewares/overview.md) (e.g. the [AddPrefix](../../middlewares/addprefix.md) or [ReplacePath](../../middlewares/replacepath.md)) middlewares.
??? example "A Service with One Server -- Using the [File Provider](../providers/file.md)" ??? example "A Service with One Server -- Using the [File Provider](../../providers/file.md)"
```toml ```toml
[Services] [http.services]
[Services.my-service.LoadBalancer] [http.services.my-service.LoadBalancer]
[[Services.my-service.LoadBalancer.servers]] [[http.services.my-service.LoadBalancer.servers]]
url = "http://private-ip-server-1/" url = "http://private-ip-server-1/"
``` ```
@ -78,15 +89,15 @@ Various methods of load balancing are supported:
- `wrr`: Weighted Round Robin. - `wrr`: Weighted Round Robin.
- `drr`: Dynamic Round Robin: increases weights on servers that perform better than others (rolls back to original weights when the server list is updated) - `drr`: Dynamic Round Robin: increases weights on servers that perform better than others (rolls back to original weights when the server list is updated)
??? example "Load Balancing Using DRR -- Using the [File Provider](../providers/file.md)" ??? example "Load Balancing Using DRR -- Using the [File Provider](../../providers/file.md)"
```toml ```toml
[Services] [http.services]
[Services.my-service.LoadBalancer] [http.services.my-service.LoadBalancer]
method = "drr" method = "drr"
[[Services.my-service.LoadBalancer.servers]] [[http.services.my-service.LoadBalancer.servers]]
url = "http://private-ip-server-1/" url = "http://private-ip-server-1/"
[[Services.my-service.LoadBalancer.servers]] [[http.services.my-service.LoadBalancer.servers]]
url = "http://private-ip-server-1/" url = "http://private-ip-server-1/"
``` ```
@ -106,17 +117,17 @@ On subsequent requests, the client is forwarded to the same server.
??? example "Adding Stickiness" ??? example "Adding Stickiness"
```toml ```toml
[Services] [http.services]
[Services.my-service] [http.services.my-service]
[Services.my-service.LoadBalancer.stickiness] [http.services.my-service.LoadBalancer.stickiness]
``` ```
??? example "Adding Stickiness with a Custom Cookie Name" ??? example "Adding Stickiness with a Custom Cookie Name"
```toml ```toml
[Services] [http.services]
[Services.my-service] [http.services.my-service]
[Services.my-service.LoadBalancer.stickiness] [http.services.my-service.LoadBalancer.stickiness]
cookieName = "my_stickiness_cookie_name" cookieName = "my_stickiness_cookie_name"
``` ```
@ -148,9 +159,9 @@ Below are the available options for the health check mechanism:
??? example "Custom Interval & Timeout -- Using the File Provider" ??? example "Custom Interval & Timeout -- Using the File Provider"
```toml ```toml
[Services] [http.services]
[Servicess.Service-1] [http.servicess.Service-1]
[Services.Service-1.healthcheck] [http.services.Service-1.healthcheck]
path = "/health" path = "/health"
interval = "10s" interval = "10s"
timeout = "3s" timeout = "3s"
@ -159,9 +170,9 @@ Below are the available options for the health check mechanism:
??? example "Custom Port -- Using the File Provider" ??? example "Custom Port -- Using the File Provider"
```toml ```toml
[Services] [http.services]
[Services.Service-1] [http.services.Service-1]
[Services.Service-1.healthcheck] [http.services.Service-1.healthcheck]
path = "/health" path = "/health"
port = 8080 port = 8080
``` ```
@ -169,9 +180,9 @@ Below are the available options for the health check mechanism:
??? example "Custom Scheme -- Using the File Provider" ??? example "Custom Scheme -- Using the File Provider"
```toml ```toml
[Services] [http.services]
[Services.Service-1] [http.services.Service-1]
[Services.Service-1.healthcheck] [http.services.Service-1.healthcheck]
path = "/health" path = "/health"
scheme = "http" scheme = "http"
``` ```
@ -179,12 +190,53 @@ Below are the available options for the health check mechanism:
??? example "Additional HTTP Headers -- Using the File Provider" ??? example "Additional HTTP Headers -- Using the File Provider"
```toml ```toml
[Services] [http.services]
[Services.Service-1] [http.services.Service-1]
[Servicess.Service-1.healthcheck] [http.servicess.Service-1.healthcheck]
path = "/health" path = "/health"
[Service.Service-1.healthcheck.headers] [Service.Service-1.healthcheck.headers]
My-Custom-Header = "foo" My-Custom-Header = "foo"
My-Header = "bar" My-Header = "bar"
``` ```
## Configuring TCP Services
### General
Currently, `LoadBalancer` is the only supported kind of TCP `Service`.
However, since Traefik is an ever evolving project, other kind of TCP Services will be available in the future,
reason why you have to specify it.
### Load Balancer
The load balancers are able to load balance the requests between multiple instances of your programs.
??? example "Declaring a Service with Two Servers -- Using the [File Provider](../../providers/file.md)"
```toml
[tcp.services]
[tcp.services.my-service.LoadBalancer]
[[tcp.services.my-service.LoadBalancer.servers]]
address = "xx.xx.xx.xx:xx"
[[tcp.services.my-service.LoadBalancer.servers]]
address = "xx.xx.xx.xx:xx"
```
#### Servers
Servers declare a single instance of your program.
The `address` option (IP:Port) point to a specific instance.
??? example "A Service with One Server -- Using the [File Provider](../../providers/file.md)"
```toml
[tcp.services]
[tcp.services.my-service.LoadBalancer]
[[tcp.services.my-service.LoadBalancer.servers]]
address = "xx.xx.xx.xx:xx"
```
!!! note "Weight"
The TCP LoadBalancer is currently a round robin only implementation and doesn't yet support weights.

View file

@ -79,9 +79,11 @@ nav:
- 'Routing & Load Balancing': - 'Routing & Load Balancing':
- 'Overview': 'routing/overview.md' - 'Overview': 'routing/overview.md'
- 'Entrypoints': 'routing/entrypoints.md' - 'Entrypoints': 'routing/entrypoints.md'
- 'Routers': 'routing/routers.md' - 'Routers': 'routing/routers/index.md'
- 'Services': 'routing/services.md' - 'Services': 'routing/services/index.md'
- 'ACME': 'routing/acme.md' - 'HTTPS & TLS':
- 'Overview': 'https-tls/overview.md'
- 'ACME': 'https-tls/acme.md'
- 'Middlewares': - 'Middlewares':
- 'Overview': 'middlewares/overview.md' - 'Overview': 'middlewares/overview.md'
- 'AddPrefix': 'middlewares/addprefix.md' - 'AddPrefix': 'middlewares/addprefix.md'

View file

@ -11,6 +11,19 @@ readonly BASE_DIR=/app
echo "== Linting Markdown" echo "== Linting Markdown"
# Uses the file ".markdownlint.json" for setup # Uses the file ".markdownlint.json" for setup
cd "${BASE_DIR}" || exit 1 cd "${BASE_DIR}" || exit 1
markdownlint --config ${BASE_DIR}/content/includes/.markdownlint.json "${BASE_DIR}/content/**/*.md" || EXIT_CODE=1
LINTER_EXCLUSIONS="$(find "${BASE_DIR}/content" -type f -name '.markdownlint.json')" \
GLOBAL_LINT_OPTIONS="--config ${BASE_DIR}/.markdownlint.json"
# Lint the specific folders (containing linter specific rulesets)
for LINTER_EXCLUSION in ${LINTER_EXCLUSIONS}
do
markdownlint --config "${LINTER_EXCLUSION}" "$(dirname "${LINTER_EXCLUSION}")" || EXIT_CODE=1
# Add folder to the ignore list for global lint
GLOBAL_LINT_OPTIONS="${GLOBAL_LINT_OPTIONS} --ignore=$(dirname "${LINTER_EXCLUSION}")"
done
# Lint all the content, excluding the previously done`
eval markdownlint "${GLOBAL_LINT_OPTIONS}" "${BASE_DIR}/content/**/*.md" || EXIT_CODE=1
exit "${EXIT_CODE}" exit "${EXIT_CODE}"

View file

@ -5,8 +5,8 @@ traefikLogsFile = "log/traefik.log"
accessLogsFile = "log/access.log" accessLogsFile = "log/access.log"
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.api] [entrypoints.api]
address = ":7888" address = ":7888"
################################################################ ################################################################

View file

@ -5,8 +5,8 @@ traefikLogsFile = "log/traefik.log"
accessLogsFile = "log/access.log" accessLogsFile = "log/access.log"
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.api] [entrypoints.api]
address = ":7888" address = ":7888"
################################################################ ################################################################

View file

@ -1,15 +1,13 @@
logLevel = "DEBUG" logLevel = "DEBUG"
defaultEntryPoints = ["http", "https"] [entrypoints]
[entrypoints.web]
[entryPoints]
[entryPoints.http]
address = ":80" address = ":80"
[entryPoints.http.redirect] [entrypoints.web.redirect]
entryPoint = "https" entryPoint = "https"
[entryPoints.https] [entrypoints.web-secure]
address = ":443" address = ":443"
[entryPoints.https.tls] [entrypoints.web-secure.tls]
[acme] [acme]
email = "test@traefik.io" email = "test@traefik.io"

View file

@ -1,13 +1,11 @@
logLevel = "DEBUG" logLevel = "DEBUG"
defaultEntryPoints = ["http", "https"] [entrypoints]
[entrypoints.web]
[entryPoints]
[entryPoints.http]
address = ":80" address = ":80"
[entryPoints.https] [entrypoints.web-secure]
address = ":443" address = ":443"
[entryPoints.https.tls] [entrypoints.web-secure.tls]
[acme] [acme]
email = "test@traefik.io" email = "test@traefik.io"

View file

@ -43,7 +43,7 @@ Edit your `docker-compose.yml` file and add the following at the end of your fil
whoami: whoami:
image: containous/whoami # A container that exposes an API to show its IP address image: containous/whoami # A container that exposes an API to show its IP address
labels: labels:
- "traefik.router.rule=Host:whoami.docker.localhost" - "traefik.http.routers.whoami.rule=Host:whoami.docker.localhost"
``` ```
The above defines `whoami`: a simple web service that outputs information about the machine it is deployed on (its IP address, host, and so on). The above defines `whoami`: a simple web service that outputs information about the machine it is deployed on (its IP address, host, and so on).

View file

@ -15,4 +15,4 @@ services:
whoami: whoami:
image: containous/whoami # A container that exposes an API to show its IP address image: containous/whoami # A container that exposes an API to show its IP address
labels: labels:
- "traefik.router.rule=Host:whoami.docker.localhost" - "traefik.http.routers.whoami.rule=Host:whoami.docker.localhost"

View file

@ -121,11 +121,12 @@ func (s *AcmeSuite) TearDownSuite(c *check.C) {
} }
func (s *AcmeSuite) TestHTTP01DomainsAtStart(c *check.C) { func (s *AcmeSuite) TestHTTP01DomainsAtStart(c *check.C) {
c.Skip("We need to fix DefaultCertificate at start")
testCase := acmeTestCase{ testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_base.toml", traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{ template: templateModel{
Acme: acme.Configuration{ Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"}, HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
Domains: types.Domains{types.Domain{ Domains: types.Domains{types.Domain{
Main: "traefik.acme.wtf", Main: "traefik.acme.wtf",
}}, }},
@ -139,11 +140,12 @@ func (s *AcmeSuite) TestHTTP01DomainsAtStart(c *check.C) {
} }
func (s *AcmeSuite) TestHTTP01DomainsInSANAtStart(c *check.C) { func (s *AcmeSuite) TestHTTP01DomainsInSANAtStart(c *check.C) {
c.Skip("We need to fix DefaultCertificate at start")
testCase := acmeTestCase{ testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_base.toml", traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{ template: templateModel{
Acme: acme.Configuration{ Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"}, HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
Domains: types.Domains{types.Domain{ Domains: types.Domains{types.Domain{
Main: "acme.wtf", Main: "acme.wtf",
SANs: []string{"traefik.acme.wtf"}, SANs: []string{"traefik.acme.wtf"},
@ -162,7 +164,7 @@ func (s *AcmeSuite) TestHTTP01OnHostRule(c *check.C) {
traefikConfFilePath: "fixtures/acme/acme_base.toml", traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{ template: templateModel{
Acme: acme.Configuration{ Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"}, HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
OnHostRule: true, OnHostRule: true,
}, },
}, },
@ -178,7 +180,7 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleECDSA(c *check.C) {
traefikConfFilePath: "fixtures/acme/acme_base.toml", traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{ template: templateModel{
Acme: acme.Configuration{ Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"}, HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
OnHostRule: true, OnHostRule: true,
KeyType: "EC384", KeyType: "EC384",
}, },
@ -195,7 +197,7 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleInvalidAlgo(c *check.C) {
traefikConfFilePath: "fixtures/acme/acme_base.toml", traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{ template: templateModel{
Acme: acme.Configuration{ Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"}, HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
OnHostRule: true, OnHostRule: true,
KeyType: "INVALID", KeyType: "INVALID",
}, },
@ -207,28 +209,12 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleInvalidAlgo(c *check.C) {
s.retrieveAcmeCertificate(c, testCase) s.retrieveAcmeCertificate(c, testCase)
} }
func (s *AcmeSuite) TestHTTP01OnHostRuleWithPath(c *check.C) {
testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_http01_web_path.toml",
template: templateModel{
Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"},
OnHostRule: true,
},
},
expectedCommonName: acmeDomain,
expectedAlgorithm: x509.RSA,
}
s.retrieveAcmeCertificate(c, testCase)
}
func (s *AcmeSuite) TestHTTP01OnHostRuleStaticCertificatesWithWildcard(c *check.C) { func (s *AcmeSuite) TestHTTP01OnHostRuleStaticCertificatesWithWildcard(c *check.C) {
testCase := acmeTestCase{ testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_tls.toml", traefikConfFilePath: "fixtures/acme/acme_tls.toml",
template: templateModel{ template: templateModel{
Acme: acme.Configuration{ Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"}, HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
OnHostRule: true, OnHostRule: true,
}, },
}, },
@ -244,7 +230,7 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleDynamicCertificatesWithWildcard(c *check
traefikConfFilePath: "fixtures/acme/acme_tls_dynamic.toml", traefikConfFilePath: "fixtures/acme/acme_tls_dynamic.toml",
template: templateModel{ template: templateModel{
Acme: acme.Configuration{ Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"}, HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
OnHostRule: true, OnHostRule: true,
}, },
}, },
@ -255,78 +241,6 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleDynamicCertificatesWithWildcard(c *check
s.retrieveAcmeCertificate(c, testCase) s.retrieveAcmeCertificate(c, testCase)
} }
func (s *AcmeSuite) TestHTTP01OnDemand(c *check.C) {
c.Skip("on demand")
testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{
Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"},
OnDemand: true,
},
},
expectedCommonName: acmeDomain,
expectedAlgorithm: x509.RSA,
}
s.retrieveAcmeCertificate(c, testCase)
}
func (s *AcmeSuite) TestHTTP01OnDemandStaticCertificatesWithWildcard(c *check.C) {
c.Skip("on demand")
testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_tls.toml",
template: templateModel{
Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"},
OnDemand: true,
},
},
expectedCommonName: wildcardDomain,
expectedAlgorithm: x509.RSA,
}
s.retrieveAcmeCertificate(c, testCase)
}
func (s *AcmeSuite) TestHTTP01OnDemandStaticCertificatesWithWildcardMultipleEntrypoints(c *check.C) {
c.Skip("on demand")
testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_tls_multiple_entrypoints.toml",
template: templateModel{
Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"},
OnDemand: true,
},
},
expectedCommonName: acmeDomain,
expectedAlgorithm: x509.RSA,
}
s.retrieveAcmeCertificate(c, testCase)
}
func (s *AcmeSuite) TestHTTP01OnDemandDynamicCertificatesWithWildcard(c *check.C) {
c.Skip("on demand")
testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_tls_dynamic.toml",
template: templateModel{
Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"},
OnDemand: true,
},
},
expectedCommonName: wildcardDomain,
expectedAlgorithm: x509.RSA,
}
s.retrieveAcmeCertificate(c, testCase)
}
func (s *AcmeSuite) TestTLSALPN01OnHostRule(c *check.C) { func (s *AcmeSuite) TestTLSALPN01OnHostRule(c *check.C) {
testCase := acmeTestCase{ testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_base.toml", traefikConfFilePath: "fixtures/acme/acme_base.toml",
@ -343,23 +257,8 @@ func (s *AcmeSuite) TestTLSALPN01OnHostRule(c *check.C) {
s.retrieveAcmeCertificate(c, testCase) s.retrieveAcmeCertificate(c, testCase)
} }
func (s *AcmeSuite) TestTLSALPN01OnDemand(c *check.C) {
testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{
Acme: acme.Configuration{
TLSChallenge: &acme.TLSChallenge{},
OnDemand: true,
},
},
expectedCommonName: acmeDomain,
expectedAlgorithm: x509.RSA,
}
s.retrieveAcmeCertificate(c, testCase)
}
func (s *AcmeSuite) TestTLSALPN01DomainsAtStart(c *check.C) { func (s *AcmeSuite) TestTLSALPN01DomainsAtStart(c *check.C) {
c.Skip("We need to fix DefaultCertificate at start")
testCase := acmeTestCase{ testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_base.toml", traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{ template: templateModel{
@ -378,6 +277,7 @@ func (s *AcmeSuite) TestTLSALPN01DomainsAtStart(c *check.C) {
} }
func (s *AcmeSuite) TestTLSALPN01DomainsInSANAtStart(c *check.C) { func (s *AcmeSuite) TestTLSALPN01DomainsInSANAtStart(c *check.C) {
c.Skip("We need to fix DefaultCertificate at start")
testCase := acmeTestCase{ testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_base.toml", traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{ template: templateModel{
@ -397,6 +297,7 @@ func (s *AcmeSuite) TestTLSALPN01DomainsInSANAtStart(c *check.C) {
} }
func (s *AcmeSuite) TestTLSALPN01DomainsWithProvidedWildcardDomainAtStart(c *check.C) { func (s *AcmeSuite) TestTLSALPN01DomainsWithProvidedWildcardDomainAtStart(c *check.C) {
c.Skip("We need to fix DefaultCertificate at start")
testCase := acmeTestCase{ testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_tls.toml", traefikConfFilePath: "fixtures/acme/acme_tls.toml",
template: templateModel{ template: templateModel{
@ -419,7 +320,7 @@ func (s *AcmeSuite) TestNoValidLetsEncryptServer(c *check.C) {
file := s.adaptFile(c, "fixtures/acme/acme_base.toml", templateModel{ file := s.adaptFile(c, "fixtures/acme/acme_base.toml", templateModel{
Acme: acme.Configuration{ Acme: acme.Configuration{
CAServer: "http://wrongurl:4001/directory", CAServer: "http://wrongurl:4001/directory",
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"}, HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
OnHostRule: true, OnHostRule: true,
}, },
}) })

View file

@ -14,8 +14,8 @@ import (
"github.com/abronan/valkeyrie/store" "github.com/abronan/valkeyrie/store"
"github.com/abronan/valkeyrie/store/consul" "github.com/abronan/valkeyrie/store/consul"
"github.com/containous/staert" "github.com/containous/staert"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/integration/try" "github.com/containous/traefik/integration/try"
"github.com/containous/traefik/old/cluster"
"github.com/go-check/check" "github.com/go-check/check"
checker "github.com/vdemeester/shakers" checker "github.com/vdemeester/shakers"
) )

View file

@ -158,13 +158,13 @@ func (s *DockerSuite) TestDockerContainersWithLabels(c *check.C) {
// Start a container with some labels // Start a container with some labels
labels := map[string]string{ labels := map[string]string{
"traefik.Routers.Super.Rule": "Host(`my.super.host`)", "traefik.http.Routers.Super.Rule": "Host(`my.super.host`)",
} }
s.startContainerWithLabels(c, "swarm:1.0.0", labels, "manage", "token://blabla") s.startContainerWithLabels(c, "swarm:1.0.0", labels, "manage", "token://blabla")
// Start another container by replacing a '.' by a '-' // Start another container by replacing a '.' by a '-'
labels = map[string]string{ labels = map[string]string{
"traefik.Routers.SuperHost.Rule": "Host(`my-super.host`)", "traefik.http.Routers.SuperHost.Rule": "Host(`my-super.host`)",
} }
s.startContainerWithLabels(c, "swarm:1.0.0", labels, "manage", "token://blablabla") s.startContainerWithLabels(c, "swarm:1.0.0", labels, "manage", "token://blablabla")
@ -250,8 +250,8 @@ func (s *DockerSuite) TestRestartDockerContainers(c *check.C) {
// Start a container with some labels // Start a container with some labels
labels := map[string]string{ labels := map[string]string{
"traefik.Routers.Super.Rule": "Host(`my.super.host`)", "traefik.http.Routers.Super.Rule": "Host(`my.super.host`)",
"traefik.Services.powpow.LoadBalancer.server.Port": "2375", "traefik.http.Services.powpow.LoadBalancer.server.Port": "2375",
} }
s.startContainerWithNameAndLabels(c, "powpow", "swarm:1.0.0", labels, "manage", "token://blabla") s.startContainerWithNameAndLabels(c, "powpow", "swarm:1.0.0", labels, "manage", "token://blabla")

View file

@ -8,16 +8,16 @@ checkNewVersion = false
[accessLog] [accessLog]
filePath = "access.log" filePath = "access.log"
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8000" address = ":8000"
[entryPoints.frontendRedirect] [entrypoints.frontendRedirect]
address = ":8005" address = ":8005"
[entryPoints.httpFrontendAuth] [entrypoints.httpFrontendAuth]
address = ":8006" address = ":8006"
[entryPoints.httpRateLimit] [entrypoints.httpRateLimit]
address = ":8007" address = ":8007"
[entryPoints.digestAuth] [entrypoints.digestAuth]
address = ":8008" address = ":8008"
[api] [api]

View file

@ -1,21 +1,17 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entrypoints]
[entrypoints.web]
[entryPoints]
[entryPoints.http]
address = "{{ .PortHTTP }}" address = "{{ .PortHTTP }}"
[entryPoints.https] [entrypoints.web-secure]
address = "{{ .PortHTTPS }}" address = "{{ .PortHTTPS }}"
[entryPoints.https.tls]
[acme] [acme]
email = "test@traefik.io" email = "test@traefik.io"
storage = "/tmp/acme.json" storage = "/tmp/acme.json"
entryPoint = "https" # entryPoint = "https"
acmeLogging = true acmeLogging = true
onDemand = {{ .Acme.OnDemand }}
onHostRule = {{ .Acme.OnHostRule }} onHostRule = {{ .Acme.OnHostRule }}
keyType = "{{ .Acme.KeyType }}" keyType = "{{ .Acme.KeyType }}"
caServer = "{{ .Acme.CAServer }}" caServer = "{{ .Acme.CAServer }}"
@ -42,14 +38,15 @@ logLevel = "DEBUG"
[providers] [providers]
[providers.file] [providers.file]
[services] [http.services]
[services.test.loadbalancer] [http.services.test.loadbalancer]
[[services.test.loadbalancer.servers]] [[http.services.test.loadbalancer.servers]]
url = "http://127.0.0.1:9010" url = "http://127.0.0.1:9010"
weight = 1 weight = 1
[routers] [http.routers]
[routers.test] [http.routers.test]
service = "test" entryPoints = ["web-secure"]
rule = "Host(`traefik.acme.wtf`)" rule = "Host(`traefik.acme.wtf`)"
entryPoints = ["https"] service = "test"
[http.routers.test.tls]

View file

@ -1,52 +0,0 @@
[log]
logLevel = "DEBUG"
[entryPoints]
[entryPoints.http]
address = "{{ .PortHTTP }}"
[entryPoints.https]
address = "{{ .PortHTTPS }}"
[entryPoints.https.tls]
[acme]
email = "test@traefik.io"
storage = "/tmp/acme.json"
entryPoint = "https"
acmeLogging = true
onDemand = {{ .Acme.OnDemand }}
onHostRule = {{ .Acme.OnHostRule }}
keyType = "{{ .Acme.KeyType }}"
caServer = "{{ .Acme.CAServer }}"
{{if .Acme.HTTPChallenge }}
[acme.httpChallenge]
entryPoint = "{{ .Acme.HTTPChallenge.EntryPoint }}"
{{end}}
{{range .Acme.Domains}}
[[acme.domains]]
main = "{{ .Main }}"
sans = [{{range .SANs }}
"{{.}}",
{{end}}]
{{end}}
[web]
path="/traefik"
[providers]
[providers.file]
[services]
[services.test.loadbalancer]
[[services.test.loadbalancer.servers]]
url = "http://127.0.0.1:9010"
weight = 1
[routers]
[routers.test]
service = "test"
rule = "Host(`traefik.acme.wtf`)"
entryPoints = ["https"]

View file

@ -1,22 +1,17 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = "{{ .PortHTTP }}" address = "{{ .PortHTTP }}"
[entryPoints.https] [entrypoints.web-secure]
address = "{{ .PortHTTPS }}" address = "{{ .PortHTTPS }}"
[entryPoints.https.tls]
[entryPoints.https.tls.DefaultCertificate]
certFile = "fixtures/acme/ssl/wildcard.crt"
keyFile = "fixtures/acme/ssl/wildcard.key"
[acme] [acme]
email = "test@traefik.io" email = "test@traefik.io"
storage = "/tmp/acme.json" storage = "/tmp/acme.json"
entryPoint = "https" # entryPoint = "https"
acmeLogging = true acmeLogging = true
onDemand = {{ .Acme.OnDemand }}
onHostRule = {{ .Acme.OnHostRule }} onHostRule = {{ .Acme.OnHostRule }}
keyType = "{{ .Acme.KeyType }}" keyType = "{{ .Acme.KeyType }}"
caServer = "{{ .Acme.CAServer }}" caServer = "{{ .Acme.CAServer }}"
@ -43,14 +38,19 @@ logLevel = "DEBUG"
[providers] [providers]
[providers.file] [providers.file]
[services] [http.services]
[services.test.loadbalancer] [http.services.test.loadbalancer]
[[services.test.loadbalancer.servers]] [[http.services.test.loadbalancer.servers]]
url = "http://127.0.0.1:9010" url = "http://127.0.0.1:9010"
weight = 1 weight = 1
[routers] [http.routers]
[routers.test] [http.routers.test]
service = "test" entryPoints = ["web-secure"]
rule = "Host(`traefik.acme.wtf`)" rule = "Host(`traefik.acme.wtf`)"
entryPoints = ["https"] service = "test"
[http.routers.test.tls]
[tlsStores.default.defaultCertificate]
certFile = "fixtures/acme/ssl/wildcard.crt"
keyFile = "fixtures/acme/ssl/wildcard.key"

View file

@ -1,20 +1,17 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entrypoints]
[entryPoints] [entrypoints.web]
[entryPoints.http]
address = "{{ .PortHTTP }}" address = "{{ .PortHTTP }}"
[entryPoints.https] [entrypoints.web-secure]
address = "{{ .PortHTTPS }}" address = "{{ .PortHTTPS }}"
[entryPoints.https.tls]
[acme] [acme]
email = "test@traefik.io" email = "test@traefik.io"
storage = "/tmp/acme.json" storage = "/tmp/acme.json"
entryPoint = "https" # entryPoint = "https"
acmeLogging = true acmeLogging = true
onDemand = {{ .Acme.OnDemand }}
onHostRule = {{ .Acme.OnHostRule }} onHostRule = {{ .Acme.OnHostRule }}
keyType = "{{ .Acme.KeyType }}" keyType = "{{ .Acme.KeyType }}"
caServer = "{{ .Acme.CAServer }}" caServer = "{{ .Acme.CAServer }}"

View file

@ -1,26 +1,26 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entrypoints]
[entryPoints] [entrypoints.web]
[entryPoints.http]
address = "{{ .PortHTTP }}" address = "{{ .PortHTTP }}"
[entryPoints.https]
[entrypoints.web-secure]
address = "{{ .PortHTTPS }}" address = "{{ .PortHTTPS }}"
[entryPoints.https.tls]
[entryPoints.traefik] [entrypoints.traefik]
address = ":9000" address = ":9000"
[entryPoints.traefik.tls] # FIXME
[entryPoints.traefik.tls.DefaultCertificate] # [entrypoints.traefik.tls]
certFile = "fixtures/acme/ssl/wildcard.crt" # [entrypoints.traefik.tls.DefaultCertificate]
keyFile = "fixtures/acme/ssl/wildcard.key" # certFile = "fixtures/acme/ssl/wildcard.crt"
# keyFile = "fixtures/acme/ssl/wildcard.key"
[acme] [acme]
email = "test@traefik.io" email = "test@traefik.io"
storage = "/tmp/acme.json" storage = "/tmp/acme.json"
entryPoint = "https" # entryPoint = "https"
acmeLogging = true acmeLogging = true
onDemand = {{ .Acme.OnDemand }}
onHostRule = {{ .Acme.OnHostRule }} onHostRule = {{ .Acme.OnHostRule }}
keyType = "{{ .Acme.KeyType }}" keyType = "{{ .Acme.KeyType }}"
caServer = "{{ .Acme.CAServer }}" caServer = "{{ .Acme.CAServer }}"

View file

@ -1,18 +1,18 @@
[services] [http.services]
[services.test.loadbalancer] [http.services.test.loadbalancer]
[[services.test.loadbalancer.servers]] [[http.services.test.loadbalancer.servers]]
url = "http://127.0.0.1:9010" url = "http://127.0.0.1:9010"
weight = 1 weight = 1
[routers] [http.routers]
[routers.test] [http.routers.test]
service = "test" entryPoints = ["web-secure"]
rule = "Host(`traefik.acme.wtf`)" rule = "Host(`traefik.acme.wtf`)"
entryPoints = ["https"] service = "test"
[http.routers.test.tls]
[[tls]] [[tls]]
entryPoints = ["https"] store = ["default"]
[tls.certificate] [tls.certificate]
certFile = "fixtures/acme/ssl/wildcard.crt" certFile = "fixtures/acme/ssl/wildcard.crt"
keyFile = "fixtures/acme/ssl/wildcard.key" keyFile = "fixtures/acme/ssl/wildcard.key"

View file

@ -1,10 +1,10 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8000" address = ":8000"
[entryPoints.api] [entrypoints.api]
address = ":8081" address = ":8081"

View file

@ -1,14 +1,14 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.api] [entrypoints.api]
address = ":8081" address = ":8081"
[entryPoints.http] [entrypoints.web]
address = ":8000" address = ":8000"
[entryPoints.https] [entrypoints.web-secure]
address = ":4443" address = ":4443"
[entryPoints.https.tls] [entrypoints.web-secure.tls]
[providers] [providers]
[providers.consul] [providers.consul]

View file

@ -3,8 +3,8 @@ logLevel = "DEBUG"
[api] [api]
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8000" address = ":8000"
[providers] [providers]

View file

@ -2,8 +2,8 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8000" address = ":8000"
[api] [api]

View file

@ -1,8 +1,8 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8000" address = ":8000"
[api] [api]

View file

@ -1,10 +1,10 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8080" address = ":8080"
[entryPoints.api] [entrypoints.api]
address = ":8081" address = ":8081"
[providers] [providers]

View file

@ -1,33 +1,33 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8080" address = ":8080"
[providers] [providers]
[providers.file] [providers.file]
[routers] [http.routers]
[routers.router1] [http.routers.router1]
Rule = "Host(`test.local`)" Rule = "Host(`test.local`)"
service = "service1" service = "service1"
middlewares = ["error"] middlewares = ["error"]
[middlewares] [http.middlewares]
[middlewares.error.errors] [http.middlewares.error.errors]
status = ["500-502", "503-599"] status = ["500-502", "503-599"]
service = "error" service = "error"
query = "/50x.html" query = "/50x.html"
[services] [http.services]
[services.service1.loadbalancer] [http.services.service1.loadbalancer]
passHostHeader = true passHostHeader = true
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "http://{{.Server1}}:8989474" url = "http://{{.Server1}}:8989474"
weight = 1 weight = 1
[services.error.loadbalancer] [http.services.error.loadbalancer]
[[services.error.loadbalancer.servers]] [[http.services.error.loadbalancer.servers]]
url = "http://{{.Server2}}:80" url = "http://{{.Server2}}:80"
weight = 1 weight = 1

View file

@ -1,33 +1,33 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8080" address = ":8080"
[providers] [providers]
[providers.file] [providers.file]
[routers] [http.routers]
[routers.router1] [http.routers.router1]
Rule = "Host(`test.local`)" Rule = "Host(`test.local`)"
service = "service1" service = "service1"
middlewares = ["error"] middlewares = ["error"]
[middlewares] [http.middlewares]
[middlewares.error.errors] [http.middlewares.error.errors]
status = ["500-502", "503-599"] status = ["500-502", "503-599"]
service = "error" service = "error"
query = "/50x.html" query = "/50x.html"
[services] [http.services]
[services.service1.loadbalancer] [http.services.service1.loadbalancer]
passHostHeader = true passHostHeader = true
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "http://{{.Server1}}:80" url = "http://{{.Server1}}:80"
weight = 1 weight = 1
[services.error.loadbalancer] [http.services.error.loadbalancer]
[[services.error.loadbalancer.servers]] [[http.services.error.loadbalancer.servers]]
url = "http://{{.Server2}}:80" url = "http://{{.Server2}}:80"
weight = 1 weight = 1

View file

@ -1,10 +1,10 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8000" address = ":8000"
[entryPoints.api] [entrypoints.api]
address = ":8081" address = ":8081"

View file

@ -1,14 +1,14 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.api] [entrypoints.api]
address = ":8081" address = ":8081"
[entryPoints.http] [entrypoints.web]
address = ":8000" address = ":8000"
[entryPoints.https] [entrypoints.web-secure]
address = ":4443" address = ":4443"
[entryPoints.https.tls] [entrypoints.web-secure.tls]

View file

@ -1,8 +1,8 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8000" address = ":8000"
[providers] [providers]

View file

@ -1,8 +1,10 @@
[entryPoints] [log]
[entryPoints.http] logLevel = "DEBUG"
[entrypoints]
[entrypoints.web]
address = ":8000" address = ":8000"
logLevel = "DEBUG"
[providers] [providers]
[providers.file] [providers.file]

View file

@ -1,10 +1,10 @@
[routers] [http.routers]
[routers.router1] [http.routers.router1]
rule = "Path(`/test1`)" rule = "Path(`/test1`)"
service = "service1" service = "service1"
[services] [http.services]
[services.service1.loadbalancer] [http.services.service1.loadbalancer]
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "http://172.17.0.2:80" url = "http://172.17.0.2:80"
weight = 1 weight = 1

View file

@ -1,10 +1,10 @@
[routers] [http.routers]
[routers.router2] [http.routers.router2]
rule = "Path(`/test2`)" rule = "Path(`/test2`)"
service = "service2" service = "service2"
[services] [http.services]
[services.service2.loadbalancer] [http.services.service2.loadbalancer]
[[services.service2.loadbalancer.servers]] [[http.services.service2.loadbalancer.servers]]
url = "http://172.17.0.123:80" url = "http://172.17.0.123:80"
weight = 1 weight = 1

View file

@ -1,8 +1,8 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8000" address = ":8000"
[providers] [providers]

View file

@ -1,6 +1,6 @@
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8000" address = ":8000"
[log] [log]
@ -9,35 +9,35 @@ logLevel = "DEBUG"
[providers] [providers]
[providers.file] [providers.file]
[routers] [http.routers]
[routers.router1] [http.routers.router1]
rule = "Host(`test.localhost`)" rule = "Host(`test.localhost`)"
service = "service2" service = "service2"
[routers.router2] [http.routers.router2]
rule = "Path(`/test`)" rule = "Path(`/test`)"
middlewares = ["circuitbreaker"] middlewares = ["circuitbreaker"]
service = "service1" service = "service1"
[middlewares] [http.middlewares]
[middlewares.circuitbreaker.circuitbreaker] [http.middlewares.circuitbreaker.circuitbreaker]
expression = "NetworkErrorRatio() > 0.5" expression = "NetworkErrorRatio() > 0.5"
[services] [http.services]
[services.service1.loadbalancer] [http.services.service1.loadbalancer]
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "http://172.17.0.2:80" url = "http://172.17.0.2:80"
weight = 10 weight = 10
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "http://172.17.0.3:80" url = "http://172.17.0.3:80"
weight = 1 weight = 1
[services.service2] [http.services.service2]
[services.service2.loadbalancer] [http.services.service2.loadbalancer]
method = "drr" method = "drr"
[[services.service2.loadbalancer.servers]] [[http.services.service2.loadbalancer.servers]]
url = "http://172.17.0.4:80" url = "http://172.17.0.4:80"
weight = 1 weight = 1
[[services.service2.loadbalancer.servers]] [[http.services.service2.loadbalancer.servers]]
url = "http://172.17.0.5:80" url = "http://172.17.0.5:80"
weight = 2 weight = 2

View file

@ -4,26 +4,27 @@ rootCAs = [ """{{ .CertContent }}""" ]
[global] [global]
debug = true debug = true
[entryPoints] [entrypoints]
[entryPoints.https] [entrypoints.web-secure]
address = ":4443" address = ":4443"
[entryPoints.https.tls]
[entryPoints.https.tls.DefaultCertificate]
certFile = """{{ .CertContent }}"""
keyFile = """{{ .KeyContent }}"""
[api] [api]
[providers] [providers]
[providers.file] [providers.file]
[routers] [http.routers]
[routers.router1] [http.routers.router1]
rule = "Host(`127.0.0.1`)" rule = "Host(`127.0.0.1`)"
service = "service1" service = "service1"
[http.routers.router1.tls]
[services] [http.services]
[services.service1.loadbalancer] [http.services.service1.loadbalancer]
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "https://127.0.0.1:{{ .GRPCServerPort }}" url = "https://127.0.0.1:{{ .GRPCServerPort }}"
weight = 1 weight = 1
[tlsStores.default.DefaultCertificate]
certFile = """{{ .CertContent }}"""
keyFile = """{{ .KeyContent }}"""

View file

@ -1,9 +1,8 @@
[global] [global]
debug = true debug = true
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8081" address = ":8081"
[api] [api]
@ -11,13 +10,13 @@ debug = true
[providers] [providers]
[providers.file] [providers.file]
[routers] [http.routers]
[routers.router1] [http.routers.router1]
rule = "Host(`127.0.0.1`)" rule = "Host(`127.0.0.1`)"
service = "service1" service = "service1"
[services] [http.services]
[services.service1.loadbalancer] [http.services.service1.loadbalancer]
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "h2c://127.0.0.1:{{ .GRPCServerPort }}" url = "h2c://127.0.0.1:{{ .GRPCServerPort }}"
weight = 1 weight = 1

View file

@ -1,27 +1,28 @@
[global] [global]
debug = true debug = true
[entryPoints] [entrypoints]
[entryPoints.https] [entrypoints.web-secure]
address = ":4443" address = ":4443"
[entryPoints.https.tls]
[entryPoints.https.tls.DefaultCertificate]
certFile = """{{ .CertContent }}"""
keyFile = """{{ .KeyContent }}"""
[api] [api]
[providers] [providers]
[providers.file] [providers.file]
[routers] [http.routers]
[routers.router1] [http.routers.router1]
rule = "Host(`127.0.0.1`)" rule = "Host(`127.0.0.1`)"
service = "service1" service = "service1"
[http.routers.router1.tls]
[services] [http.services]
[services.service1.loadbalancer] [http.services.service1.loadbalancer]
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "h2c://127.0.0.1:{{ .GRPCServerPort }}" url = "h2c://127.0.0.1:{{ .GRPCServerPort }}"
weight = 1 weight = 1
[tlsStores.default.DefaultCertificate]
certFile = """{{ .CertContent }}"""
keyFile = """{{ .KeyContent }}"""

View file

@ -5,28 +5,27 @@ insecureSkipVerify = true
[global] [global]
debug = true debug = true
[entryPoints] [entrypoints]
[entryPoints.https] [entrypoints.web-secure]
address = ":4443" address = ":4443"
[entryPoints.https.tls]
[entryPoints.https.tls.DefaultCertificate]
certFile = """{{ .CertContent }}"""
keyFile = """{{ .KeyContent }}"""
[api] [api]
[providers] [providers]
[providers.file] [providers.file]
[routers] [http.routers]
[routers.router1] [http.routers.router1]
rule = "Host(`127.0.0.1`)" rule = "Host(`127.0.0.1`)"
service = "service1" service = "service1"
[http.routers.router1.tls]
[http.services]
[services] [http.services.service1.loadbalancer]
[services.service1.loadbalancer] [[http.services.service1.loadbalancer.servers]]
[[services.service1.loadbalancer.servers]]
url = "https://127.0.0.1:{{ .GRPCServerPort }}" url = "https://127.0.0.1:{{ .GRPCServerPort }}"
weight = 1 weight = 1
[tlsStores.default.DefaultCertificate]
certFile = """{{ .CertContent }}"""
keyFile = """{{ .KeyContent }}"""

View file

@ -1,34 +1,34 @@
[serversTransport] [serversTransport]
rootCAs = [ """{{ .CertContent }}""" ] rootCAs = [ """{{ .CertContent }}""" ]
[entryPoints] [entrypoints]
[entryPoints.https] [entrypoints.web-secure]
address = ":4443" address = ":4443"
[entryPoints.https.tls]
[entryPoints.https.tls.DefaultCertificate]
certFile = """{{ .CertContent }}"""
keyFile = """{{ .KeyContent }}"""
[api] [api]
[providers] [providers]
[providers.file] [providers.file]
[routers] [http.routers]
[routers.router1] [http.routers.router1]
rule = "Host(`127.0.0.1`)" rule = "Host(`127.0.0.1`)"
service = "service1" service = "service1"
middlewares = ["retryer"] middlewares = ["retryer"]
[http.routers.router1.tls]
[middlewares] [http.middlewares]
[middlewares.retryer.retry] [http.middlewares.retryer.retry]
Attempts = 2 Attempts = 2
[services] [http.services]
[services.service1.loadbalancer] [http.services.service1.loadbalancer]
[services.service1.loadbalancer.responseForwarding] [http.services.service1.loadbalancer.responseForwarding]
flushInterval="1ms" flushInterval="1ms"
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "https://127.0.0.1:{{ .GRPCServerPort }}" url = "https://127.0.0.1:{{ .GRPCServerPort }}"
weight = 1 weight = 1
[tlsStores.default.DefaultCertificate]
certFile = """{{ .CertContent }}"""
keyFile = """{{ .KeyContent }}"""

View file

@ -2,29 +2,27 @@
[serversTransport] [serversTransport]
rootCAs = [ """{{ .CertContent }}""" ] rootCAs = [ """{{ .CertContent }}""" ]
[entryPoints] [entrypoints]
[entryPoints.https] [entrypoints.web-secure]
address = ":4443" address = ":4443"
[entryPoints.https.tls]
[entryPoints.https.tls.DefaultCertificate]
certFile = """{{ .CertContent }}"""
keyFile = """{{ .KeyContent }}"""
[api] [api]
[providers] [providers]
[providers.file] [providers.file]
[routers] [http.routers]
[routers.router1] [http.routers.router1]
rule = "Host(`127.0.0.1`)" rule = "Host(`127.0.0.1`)"
service = "service1" service = "service1"
[http.routers.router1.tls]
[services] [http.services]
[services.service1.loadbalancer] [http.services.service1.loadbalancer]
[services.service1.loadbalancer.responseForwarding] [[http.services.service1.loadbalancer.servers]]
flushInterval="1ms"
[[services.service1.loadbalancer.servers]]
url = "https://127.0.0.1:{{ .GRPCServerPort }}" url = "https://127.0.0.1:{{ .GRPCServerPort }}"
weight = 1 weight = 1
[tlsStores.default.DefaultCertificate]
certFile = """{{ .CertContent }}"""
keyFile = """{{ .KeyContent }}"""

View file

@ -1,10 +1,10 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.http1] [entrypoints.http1]
address = ":8000" address = ":8000"
[entryPoints.http2] [entrypoints.http2]
address = ":9000" address = ":9000"
[api] [api]
@ -12,21 +12,21 @@ logLevel = "DEBUG"
[providers] [providers]
[providers.file] [providers.file]
[routers] [http.routers]
[routers.router1] [http.routers.router1]
service = "service1" service = "service1"
Rule = "Host(`test.localhost`)" Rule = "Host(`test.localhost`)"
[services] [http.services]
[services.service1.loadbalancer] [http.services.service1.loadbalancer]
method = "drr" method = "drr"
[services.service1.loadbalancer.healthcheck] [http.services.service1.loadbalancer.healthcheck]
path = "/health" path = "/health"
interval = "1s" interval = "1s"
timeout = "0.9s" timeout = "0.9s"
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "http://{{.Server1}}:80" url = "http://{{.Server1}}:80"
weight = 1 weight = 1
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "http://{{.Server2}}:80" url = "http://{{.Server2}}:80"
weight = 1 weight = 1

View file

@ -1,10 +1,10 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.http1] [entrypoints.http1]
address = ":8000" address = ":8000"
[entryPoints.http2] [entrypoints.http2]
address = ":9000" address = ":9000"
[api] [api]
@ -12,21 +12,21 @@ logLevel = "DEBUG"
[providers] [providers]
[providers.file] [providers.file]
[routers] [http.routers]
[routers.router1] [http.routers.router1]
service = "service1" service = "service1"
Rule = "Host(`test.localhost`)" Rule = "Host(`test.localhost`)"
[services] [http.services]
[services.service1.loadbalancer] [http.services.service1.loadbalancer]
method = "wrr" method = "wrr"
[services.service1.loadbalancer.healthcheck] [http.services.service1.loadbalancer.healthcheck]
path = "/health" path = "/health"
interval = "1s" interval = "1s"
timeout = "0.9s" timeout = "0.9s"
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "http://{{.Server1}}:80" url = "http://{{.Server1}}:80"
weight = 1 weight = 1
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "http://{{.Server2}}:80" url = "http://{{.Server2}}:80"
weight = 1 weight = 1

View file

@ -1,8 +1,8 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8000" address = ":8000"
[api] [api]
@ -10,19 +10,19 @@ logLevel = "DEBUG"
[providers] [providers]
[providers.file] [providers.file]
[routers] [http.routers]
[routers.router1] [http.routers.router1]
service = "service1" service = "service1"
Rule = "Host(`test.localhost`)" Rule = "Host(`test.localhost`)"
[services] [http.services]
[services.service1.loadbalancer] [http.services.service1.loadbalancer]
method = "drr" method = "drr"
[services.service1.loadbalancer.healthcheck] [http.services.service1.loadbalancer.healthcheck]
path = "/health" path = "/health"
port = 80 port = 80
interval = "1s" interval = "1s"
timeout = "0.9s" timeout = "0.9s"
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "http://{{.Server1}}:81" url = "http://{{.Server1}}:81"
weight = 1 weight = 1

View file

@ -1,8 +1,8 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.http] [entrypoints.web]
address = ":8000" address = ":8000"
[api] [api]
@ -10,20 +10,20 @@ logLevel = "DEBUG"
[providers] [providers]
[providers.file] [providers.file]
[routers] [http.routers]
[routers.router1] [http.routers.router1]
service = "service1" service = "service1"
Rule = "Host(`test.localhost`)" Rule = "Host(`test.localhost`)"
[services] [http.services]
[services.service1.loadbalancer] [http.services.service1.loadbalancer]
[services.service1.loadbalancer.healthcheck] [http.services.service1.loadbalancer.healthcheck]
path = "/health" path = "/health"
interval = "1s" interval = "1s"
timeout = "0.9s" timeout = "0.9s"
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "http://{{.Server1}}:80" url = "http://{{.Server1}}:80"
weight = 1 weight = 1
[[services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "http://{{.Server2}}:80" url = "http://{{.Server2}}:80"
weight = 1 weight = 1

View file

@ -1,50 +1,49 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.https] [entrypoints.web-secure]
address = ":4443" address = ":4443"
[entryPoints.https.tls]
[entryPoints.https.tls.ClientCA]
files = ["fixtures/https/clientca/ca1.crt"]
optional = true
[api] [api]
[providers] [providers]
[providers.file] [providers.file]
[Routers] [http.routers]
[Routers.router1] [http.routers.router1]
Service = "service1" Service = "service1"
Rule = "Host(`snitest.com`)" Rule = "Host(`snitest.com`)"
[Routers.router2] [http.routers.router1.tls]
[http.routers.router2]
Service = "service2" Service = "service2"
Rule = "Host(`snitest.org`)" Rule = "Host(`snitest.org`)"
[http.routers.router2.tls]
[Services] [http.services]
[Services.service1] [http.services.service1]
[Services.service1.LoadBalancer] [http.services.service1.LoadBalancer]
[[http.services.service1.LoadBalancer.Servers]]
[[Services.service1.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9010" URL = "http://127.0.0.1:9010"
Weight = 1 Weight = 1
[Services.service2]
[Services.service2.LoadBalancer]
[[Services.service2.LoadBalancer.Servers]] [http.services.service2]
[http.services.service2.LoadBalancer]
[[http.services.service2.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9020" URL = "http://127.0.0.1:9020"
Weight = 1 Weight = 1
[[tls]] [[tls]]
entryPoints = ["https"]
[tls.certificate] [tls.certificate]
certFile = "fixtures/https/snitest.com.cert" certFile = "fixtures/https/snitest.com.cert"
keyFile = "fixtures/https/snitest.com.key" keyFile = "fixtures/https/snitest.com.key"
[[tls]] [[tls]]
entryPoints = ["https"]
[tls.certificate] [tls.certificate]
certFile = "fixtures/https/snitest.org.cert" certFile = "fixtures/https/snitest.org.cert"
keyFile = "fixtures/https/snitest.org.key" keyFile = "fixtures/https/snitest.org.key"
[tlsOptions.default.ClientCA]
files = ["fixtures/https/clientca/ca1.crt"]
optional = true

View file

@ -1,47 +1,47 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.https] [entrypoints.web-secure]
address = ":4443" address = ":4443"
[entryPoints.https.tls]
[entryPoints.https.tls.ClientCA]
files = ["fixtures/https/clientca/ca1and2.crt"]
[api] [api]
[providers] [providers]
[providers.file] [providers.file]
[Routers] [http.routers]
[Routers.router1] [http.routers.router1]
Service = "service1" Service = "service1"
Rule = "Host(`snitest.com`)" Rule = "Host(`snitest.com`)"
[Routers.router2] [http.routers.router1.tls]
[http.routers.router2]
Service = "service2" Service = "service2"
Rule = "Host(`snitest.org`)" Rule = "Host(`snitest.org`)"
[http.routers.router2.tls]
[Services] [http.services]
[Services.service1] [http.services.service1]
[Services.service1.LoadBalancer] [http.services.service1.LoadBalancer]
[[http.services.service1.LoadBalancer.Servers]]
[[Services.service1.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9010" URL = "http://127.0.0.1:9010"
Weight = 1 Weight = 1
[Services.service2]
[Services.service2.LoadBalancer]
[[Services.service2.LoadBalancer.Servers]] [http.services.service2]
[http.services.service2.LoadBalancer]
[[http.services.service2.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9020" URL = "http://127.0.0.1:9020"
Weight = 1 Weight = 1
[[tls]] [[tls]]
entryPoints = ["https"]
[tls.certificate] [tls.certificate]
certFile = "fixtures/https/snitest.com.cert" certFile = "fixtures/https/snitest.com.cert"
keyFile = "fixtures/https/snitest.com.key" keyFile = "fixtures/https/snitest.com.key"
[[tls]] [[tls]]
entryPoints = ["https"]
[tls.certificate] [tls.certificate]
certFile = "fixtures/https/snitest.org.cert" certFile = "fixtures/https/snitest.org.cert"
keyFile = "fixtures/https/snitest.org.key" keyFile = "fixtures/https/snitest.org.key"
[tlsOptions.default.ClientCA]
files = ["fixtures/https/clientca/ca1and2.crt"]

View file

@ -2,49 +2,48 @@
logLevel = "DEBUG" logLevel = "DEBUG"
[entryPoints] [entrypoints]
[entryPoints.https] [entrypoints.web-secure]
address = ":4443" address = ":4443"
[entryPoints.https.tls]
[entryPoints.https.tls.ClientCA]
files = ["fixtures/https/clientca/ca1.crt", "fixtures/https/clientca/ca2.crt"]
optional = false
[api] [api]
[providers] [providers]
[providers.file] [providers.file]
[Routers] [http.routers]
[Routers.router1] [http.routers.router1]
Service = "service1" Service = "service1"
Rule = "Host(`snitest.com`)" Rule = "Host(`snitest.com`)"
[Routers.router2] [http.routers.router1.tls]
[http.routers.router2]
Service = "service2" Service = "service2"
Rule = "Host(`snitest.org`)" Rule = "Host(`snitest.org`)"
[http.routers.router2.tls]
[Services] [http.services]
[Services.service1] [http.services.service1]
[Services.service1.LoadBalancer] [http.services.service1.LoadBalancer]
[[http.services.service1.LoadBalancer.Servers]]
[[Services.service1.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9010" URL = "http://127.0.0.1:9010"
Weight = 1 Weight = 1
[Services.service2]
[Services.service2.LoadBalancer]
[[Services.service2.LoadBalancer.Servers]] [http.services.service2]
[http.services.service2.LoadBalancer]
[[http.services.service2.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9020" URL = "http://127.0.0.1:9020"
Weight = 1 Weight = 1
[[tls]] [[tls]]
entryPoints = ["https"]
[tls.certificate] [tls.certificate]
certFile = "fixtures/https/snitest.com.cert" certFile = "fixtures/https/snitest.com.cert"
keyFile = "fixtures/https/snitest.com.key" keyFile = "fixtures/https/snitest.com.key"
[[tls]] [[tls]]
entryPoints = ["https"]
[tls.certificate] [tls.certificate]
certFile = "fixtures/https/snitest.org.cert" certFile = "fixtures/https/snitest.org.cert"
keyFile = "fixtures/https/snitest.org.key" keyFile = "fixtures/https/snitest.org.key"
[tlsOptions.default.ClientCA]
files = ["fixtures/https/clientca/ca1.crt", "fixtures/https/clientca/ca2.crt"]
optional = false

View file

@ -1,27 +1,28 @@
[Routers] [http.routers]
[Routers.router1] [http.routers.router1]
Service = "service1" service = "service1"
Rule = "Host(`snitest.com`)" rule = "Host(`snitest.com`)"
[Routers.router2] [http.routers.router1.tls]
Service = "service2"
Rule = "Host(`snitest.org`)"
[Services] [http.routers.router2]
[Services.service1] service = "service2"
[Services.service1.LoadBalancer] rule = "Host(`snitest.org`)"
[http.routers.router2.tls]
[[Services.service1.LoadBalancer.Servers]] [http.services]
URL = "http://127.0.0.1:9010" [http.services.service1]
Weight = 1 [http.services.service1.LoadBalancer]
[Services.service2] [[http.services.service1.LoadBalancer.Servers]]
[Services.service2.LoadBalancer] url = "http://127.0.0.1:9010"
weight = 1
[[Services.service2.LoadBalancer.Servers]] [http.services.service2]
URL = "http://127.0.0.1:9020" [http.services.service2.LoadBalancer]
Weight = 1 [[http.services.service2.LoadBalancer.Servers]]
url = "http://127.0.0.1:9020"
weight = 1
[[tls]] [[tls]]
entryPoints = ["https"]
# bad certificates to validate the loop on the certificate appending # bad certificates to validate the loop on the certificate appending
[tls.certificate] [tls.certificate]
# bad content # bad content
@ -36,7 +37,6 @@ w/X5M802XqzLjeec5zHoZDfknnAkgR9MsxZYmZPFaDyL6GOKUB8=
-----END RSA PRIVATE KEY-----""" -----END RSA PRIVATE KEY-----"""
[[tls]] [[tls]]
entryPoints = ["https"]
[tls.certificate] [tls.certificate]
certFile = """-----BEGIN CERTIFICATE----- certFile = """-----BEGIN CERTIFICATE-----
MIIC/zCCAeegAwIBAgIJALAYHG/vGqWEMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV MIIC/zCCAeegAwIBAgIJALAYHG/vGqWEMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV

View file

@ -1,15 +1,12 @@
[log] [log]
logLevel = "DEBUG" logLevel = "DEBUG"
[entrypoints]
[entryPoints] [entrypoints.web-secure]
[entryPoints.https]
address = ":4443" address = ":4443"
[entryPoints.https.tls]
[entryPoints.https02] [entrypoints.https02]
address = ":8443" address = ":8443"
[entryPoints.https02.tls]
[api] [api]

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