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
- Provides HTTPS to your microservices by leveraging [Let's Encrypt](https://letsencrypt.org) (wildcard certificates support)
- Circuit breakers, retry
- High Availability with cluster mode (beta)
- See the magic through its clean web UI
- Websocket, HTTP/2, GRPC ready
- Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB)

View file

@ -1,15 +1,14 @@
package anonymize
import (
"crypto/tls"
"os"
"testing"
"time"
"github.com/containous/flaeg/parse"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/config/static"
"github.com/containous/traefik/provider"
"github.com/containous/traefik/provider/acme"
acmeprovider "github.com/containous/traefik/provider/acme"
"github.com/containous/traefik/provider/file"
traefiktls "github.com/containous/traefik/tls"
@ -45,14 +44,6 @@ func TestDo_globalConfiguration(t *testing.T) {
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{
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),
},
},
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{
TrustedIPs: []string{"127.0.0.1/32", "192.168.0.1"},
},
},
}
config.ACME = &acme.ACME{
config.ACME = &acme.Configuration{
Email: "acme Email",
Domains: []types.Domain{
{
@ -88,16 +71,11 @@ func TestDo_globalConfiguration(t *testing.T) {
},
},
Storage: "Storage",
OnDemand: true,
OnHostRule: true,
CAServer: "CAServer",
EntryPoint: "EntryPoint",
DNSChallenge: &acmeprovider.DNSChallenge{Provider: "DNSProvider"},
ACMELogging: true,
TLSConfig: &tls.Config{
InsecureSkipVerify: true,
// ...
},
}
config.Providers = &static.Providers{
ProvidersThrottleDuration: parse.Duration(111 * time.Second),

View file

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

View file

@ -65,19 +65,20 @@ type jsonRenderer interface {
}
// Append add api routes on a router
func (p Handler) Append(router *mux.Router) {
if p.Debug {
func (h Handler) Append(router *mux.Router) {
if h.Debug {
DebugHandler{}.Append(router)
}
router.Methods(http.MethodGet).Path("/api/providers").HandlerFunc(p.getProvidersHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}").HandlerFunc(p.getProviderHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/routers").HandlerFunc(p.getRoutersHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/routers/{router}").HandlerFunc(p.getRouterHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/middlewares").HandlerFunc(p.getMiddlewaresHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/middlewares/{middleware}").HandlerFunc(p.getMiddlewareHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/services").HandlerFunc(p.getServicesHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/services/{service}").HandlerFunc(p.getServiceHandler)
router.Methods(http.MethodGet).Path("/api/rawdata").HandlerFunc(h.getRawData)
router.Methods(http.MethodGet).Path("/api/providers").HandlerFunc(h.getProvidersHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}").HandlerFunc(h.getProviderHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/routers").HandlerFunc(h.getRoutersHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/routers/{router}").HandlerFunc(h.getRouterHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/middlewares").HandlerFunc(h.getMiddlewaresHandler)
router.Methods(http.MethodGet).Path("/api/providers/{provider}/middlewares/{middleware}").HandlerFunc(h.getMiddlewareHandler)
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
// health route
@ -85,15 +86,30 @@ func (p Handler) Append(router *mux.Router) {
version.Handler{}.Append(router)
if p.Dashboard {
DashboardHandler{Assets: p.DashboardAssets}.Append(router)
if h.Dashboard {
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
if p.CurrentConfigurations != nil {
currentConfigurations, ok := p.CurrentConfigurations.Get().(config.Configurations)
if h.CurrentConfigurations != nil {
currentConfigurations, ok := h.CurrentConfigurations.Get().(config.Configurations)
if !ok {
rw.WriteHeader(http.StatusOK)
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"]
currentConfigurations := p.CurrentConfigurations.Get().(config.Configurations)
currentConfigurations := h.CurrentConfigurations.Get().(config.Configurations)
provider, ok := currentConfigurations[providerID]
if !ok {
@ -126,8 +142,13 @@ func (p Handler) getProviderHandler(rw http.ResponseWriter, request *http.Reques
return
}
if provider.HTTP == nil {
http.NotFound(rw, request)
return
}
var routers []ResourceIdentifier
for name := range provider.Routers {
for name := range provider.HTTP.Routers {
routers = append(routers, ResourceIdentifier{
ID: name,
Path: "/api/providers/" + providerID + "/routers",
@ -135,7 +156,7 @@ func (p Handler) getProviderHandler(rw http.ResponseWriter, request *http.Reques
}
var services []ResourceIdentifier
for name := range provider.Services {
for name := range provider.HTTP.Services {
services = append(services, ResourceIdentifier{
ID: name,
Path: "/api/providers/" + providerID + "/services",
@ -143,7 +164,7 @@ func (p Handler) getProviderHandler(rw http.ResponseWriter, request *http.Reques
}
var middlewares []ResourceIdentifier
for name := range provider.Middlewares {
for name := range provider.HTTP.Middlewares {
middlewares = append(middlewares, ResourceIdentifier{
ID: name,
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"]
currentConfigurations := p.CurrentConfigurations.Get().(config.Configurations)
currentConfigurations := h.CurrentConfigurations.Get().(config.Configurations)
provider, ok := currentConfigurations[providerID]
if !ok {
@ -170,8 +191,13 @@ func (p Handler) getRoutersHandler(rw http.ResponseWriter, request *http.Request
return
}
if provider.HTTP == nil {
http.NotFound(rw, request)
return
}
var routers []RouterRepresentation
for name, router := range provider.Routers {
for name, router := range provider.HTTP.Routers {
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"]
routerID := mux.Vars(request)["router"]
currentConfigurations := p.CurrentConfigurations.Get().(config.Configurations)
currentConfigurations := h.CurrentConfigurations.Get().(config.Configurations)
provider, ok := currentConfigurations[providerID]
if !ok {
@ -194,7 +220,12 @@ func (p Handler) getRouterHandler(rw http.ResponseWriter, request *http.Request)
return
}
router, ok := provider.Routers[routerID]
if provider.HTTP == nil {
http.NotFound(rw, request)
return
}
router, ok := provider.HTTP.Routers[routerID]
if !ok {
http.NotFound(rw, request)
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"]
currentConfigurations := p.CurrentConfigurations.Get().(config.Configurations)
currentConfigurations := h.CurrentConfigurations.Get().(config.Configurations)
provider, ok := currentConfigurations[providerID]
if !ok {
@ -218,8 +249,13 @@ func (p Handler) getMiddlewaresHandler(rw http.ResponseWriter, request *http.Req
return
}
if provider.HTTP == nil {
http.NotFound(rw, request)
return
}
var middlewares []MiddlewareRepresentation
for name, middleware := range provider.Middlewares {
for name, middleware := range provider.HTTP.Middlewares {
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"]
middlewareID := mux.Vars(request)["middleware"]
currentConfigurations := p.CurrentConfigurations.Get().(config.Configurations)
currentConfigurations := h.CurrentConfigurations.Get().(config.Configurations)
provider, ok := currentConfigurations[providerID]
if !ok {
@ -242,7 +278,12 @@ func (p Handler) getMiddlewareHandler(rw http.ResponseWriter, request *http.Requ
return
}
middleware, ok := provider.Middlewares[middlewareID]
if provider.HTTP == nil {
http.NotFound(rw, request)
return
}
middleware, ok := provider.HTTP.Middlewares[middlewareID]
if !ok {
http.NotFound(rw, request)
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"]
currentConfigurations := p.CurrentConfigurations.Get().(config.Configurations)
currentConfigurations := h.CurrentConfigurations.Get().(config.Configurations)
provider, ok := currentConfigurations[providerID]
if !ok {
@ -266,8 +307,13 @@ func (p Handler) getServicesHandler(rw http.ResponseWriter, request *http.Reques
return
}
if provider.HTTP == nil {
http.NotFound(rw, request)
return
}
var services []ServiceRepresentation
for name, service := range provider.Services {
for name, service := range provider.HTTP.Services {
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"]
serviceID := mux.Vars(request)["service"]
currentConfigurations := p.CurrentConfigurations.Get().(config.Configurations)
currentConfigurations := h.CurrentConfigurations.Get().(config.Configurations)
provider, ok := currentConfigurations[providerID]
if !ok {
@ -290,7 +336,12 @@ func (p Handler) getServiceHandler(rw http.ResponseWriter, request *http.Request
return
}
service, ok := provider.Services[serviceID]
if provider.HTTP == nil {
http.NotFound(rw, request)
return
}
service, ok := provider.HTTP.Services[serviceID]
if !ok {
http.NotFound(rw, request)
return

View file

@ -30,8 +30,10 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers",
configuration: config.Configurations{
"foo": {
Routers: map[string]*config.Router{
"bar": {EntryPoints: []string{"foo", "bar"}},
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{
"bar": {EntryPoints: []string{"foo", "bar"}},
},
},
},
},
@ -42,18 +44,20 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers/foo",
configuration: config.Configurations{
"foo": {
Routers: map[string]*config.Router{
"bar": {EntryPoints: []string{"foo", "bar"}},
},
Middlewares: map[string]*config.Middleware{
"bar": {
AddPrefix: &config.AddPrefix{Prefix: "bar"},
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{
"bar": {EntryPoints: []string{"foo", "bar"}},
},
},
Services: map[string]*config.Service{
"foo": {
LoadBalancer: &config.LoadBalancerService{
Method: "wrr",
Middlewares: map[string]*config.Middleware{
"bar": {
AddPrefix: &config.AddPrefix{Prefix: "bar"},
},
},
Services: map[string]*config.Service{
"foo": {
LoadBalancer: &config.LoadBalancerService{
Method: "wrr",
},
},
},
},
@ -72,8 +76,10 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers/foo/routers",
configuration: config.Configurations{
"foo": {
Routers: map[string]*config.Router{
"bar": {EntryPoints: []string{"foo", "bar"}},
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{
"bar": {EntryPoints: []string{"foo", "bar"}},
},
},
},
},
@ -84,8 +90,10 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers/foo/routers/bar",
configuration: config.Configurations{
"foo": {
Routers: map[string]*config.Router{
"bar": {EntryPoints: []string{"foo", "bar"}},
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{
"bar": {EntryPoints: []string{"foo", "bar"}},
},
},
},
},
@ -104,10 +112,12 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers/foo/services",
configuration: config.Configurations{
"foo": {
Services: map[string]*config.Service{
"foo": {
LoadBalancer: &config.LoadBalancerService{
Method: "wrr",
HTTP: &config.HTTPConfiguration{
Services: map[string]*config.Service{
"foo": {
LoadBalancer: &config.LoadBalancerService{
Method: "wrr",
},
},
},
},
@ -120,10 +130,12 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers/foo/services/foo",
configuration: config.Configurations{
"foo": {
Services: map[string]*config.Service{
"foo": {
LoadBalancer: &config.LoadBalancerService{
Method: "wrr",
HTTP: &config.HTTPConfiguration{
Services: map[string]*config.Service{
"foo": {
LoadBalancer: &config.LoadBalancerService{
Method: "wrr",
},
},
},
},
@ -144,9 +156,11 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers/foo/middlewares",
configuration: config.Configurations{
"foo": {
Middlewares: map[string]*config.Middleware{
"bar": {
AddPrefix: &config.AddPrefix{Prefix: "bar"},
HTTP: &config.HTTPConfiguration{
Middlewares: map[string]*config.Middleware{
"bar": {
AddPrefix: &config.AddPrefix{Prefix: "bar"},
},
},
},
},
@ -158,9 +172,11 @@ func TestHandler_Configuration(t *testing.T) {
path: "/api/providers/foo/middlewares/bar",
configuration: config.Configurations{
"foo": {
Middlewares: map[string]*config.Middleware{
"bar": {
AddPrefix: &config.AddPrefix{Prefix: "bar"},
HTTP: &config.HTTPConfiguration{
Middlewares: map[string]*config.Middleware{
"bar": {
AddPrefix: &config.AddPrefix{Prefix: "bar"},
},
},
},
},

View file

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

View file

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

View file

@ -8,8 +8,6 @@ import (
"github.com/abronan/valkeyrie/store"
"github.com/containous/flaeg"
"github.com/containous/staert"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/cmd"
)
@ -17,7 +15,7 @@ import (
func NewCmd(traefikConfiguration *cmd.TraefikConfiguration, traefikPointersConfiguration *cmd.TraefikConfiguration) *flaeg.Command {
return &flaeg.Command{
Name: "storeconfig",
Description: `Store the static traefik configuration into a Key-value stores. Traefik will not start.`,
Description: `Stores the static traefik configuration into a Key-value stores. Traefik will not start.`,
Config: traefikConfiguration,
DefaultPointersConfig: traefikPointersConfiguration,
Metadata: map[string]string{
@ -71,48 +69,48 @@ func Run(kv *staert.KvSource, traefikConfiguration *cmd.TraefikConfiguration) fu
}
}
if traefikConfiguration.Configuration.ACME != nil {
account := &acme.Account{}
accountInitialized, err := keyExists(kv, traefikConfiguration.Configuration.ACME.Storage)
if err != nil && err != store.ErrKeyNotFound {
return err
}
// Check to see if ACME account object is already in kv store
if traefikConfiguration.Configuration.ACME.OverrideCertificates || !accountInitialized {
// Store the ACME Account into the KV Store
// Certificates in KV Store will be overridden
meta := cluster.NewMetadata(account)
err = meta.Marshall()
if err != nil {
return err
}
source := staert.KvSource{
Store: kv,
Prefix: traefikConfiguration.Configuration.ACME.Storage,
}
err = source.StoreConfig(meta)
if err != nil {
return err
}
}
}
// if traefikConfiguration.Configuration.ACME != nil {
// account := &acme.Account{}
//
// accountInitialized, err := keyExists(kv, traefikConfiguration.Configuration.ACME.Storage)
// if err != nil && err != store.ErrKeyNotFound {
// return err
// }
//
// // Check to see if ACME account object is already in kv store
// if traefikConfiguration.Configuration.ACME.OverrideCertificates || !accountInitialized {
//
// // Stores the ACME Account into the KV Store
// // Certificates in KV Stores will be overridden
// meta := cluster.NewMetadata(account)
// err = meta.Marshall()
// if err != nil {
// return err
// }
//
// source := staert.KvSource{
// Store: kv,
// Prefix: traefikConfiguration.Configuration.ACME.Storage,
// }
//
// err = source.StoreConfig(meta)
// if err != nil {
// return err
// }
// }
// }
return nil
}
}
func keyExists(source *staert.KvSource, key string) (bool, error) {
list, err := source.List(key, nil)
if err != nil {
return false, err
}
return len(list) > 0, nil
}
// func keyExists(source *staert.KvSource, key string) (bool, error) {
// list, err := source.List(key, nil)
// if err != nil {
// return false, err
// }
//
// return len(list) > 0, nil
// }
// CreateKvSource creates KvSource
// 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 {
ctx := log.With(context.Background(), log.Str(log.EntryPointName, entryPointName))
logger := log.FromContext(ctx)
serverEntryPoint, err := server.NewEntryPoint(ctx, config)
serverEntryPointsTCP[entryPointName], err = server.NewTCPEntryPoint(ctx, config)
if err != nil {
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
if acmeProvider.TLSChallenge != nil && acmeProvider.HTTPChallenge == nil && acmeProvider.DNSChallenge == nil {
serverEntryPoint.TLSALPNGetter = acmeProvider.GetTLSALPNCertificate
}
}
serverEntryPoints[entryPointName] = serverEntryPoint
}
svr := server.NewServer(*staticConfiguration, providerAggregator, serverEntryPoints)
tlsManager := traefiktls.NewManager()
if acmeProvider != nil {
acmeProvider.SetTLSManager(tlsManager)
if acmeProvider.TLSChallenge != nil &&
acmeProvider.HTTPChallenge == nil &&
acmeProvider.DNSChallenge == nil {
tlsManager.TLSAlpnGetter = acmeProvider.GetTLSALPNCertificate
}
}
svr := server.NewServer(*staticConfiguration, providerAggregator, serverEntryPointsTCP, tlsManager)
if acmeProvider != nil && acmeProvider.OnHostRule {
acmeProvider.SetConfigListenerChan(make(chan config.Configuration))

View file

@ -13,11 +13,28 @@ import (
// Router holds the router configuration.
type Router struct {
EntryPoints []string `json:"entryPoints"`
Middlewares []string `json:"middlewares,omitempty" toml:",omitempty"`
Service string `json:"service,omitempty" toml:",omitempty"`
Rule string `json:"rule,omitempty" toml:",omitempty"`
Priority int `json:"priority,omitempty" toml:"priority,omitzero"`
EntryPoints []string `json:"entryPoints"`
Middlewares []string `json:"middlewares,omitempty" toml:",omitempty"`
Service string `json:"service,omitempty" toml:",omitempty"`
Rule string `json:"rule,omitempty" toml:",omitempty"`
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.
@ -30,6 +47,12 @@ type LoadBalancerService struct {
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.
func (l *LoadBalancerService) Mergeable(loadBalancer *LoadBalancerService) bool {
savedServers := l.Servers
@ -71,6 +94,12 @@ type Server struct {
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.
func (s *Server) SetDefaults() {
s.Weight = 1
@ -175,18 +204,37 @@ type Message struct {
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.
type Configurations map[string]*Configuration
// Configuration FIXME better name?
type Configuration struct {
Routers map[string]*Router `json:"routers,omitempty" toml:",omitempty"`
Middlewares map[string]*Middleware `json:"middlewares,omitempty" toml:",omitempty"`
Services map[string]*Service `json:"services,omitempty" toml:",omitempty"`
TLS []*traefiktls.Configuration `json:"-" label:"-"`
// HTTPConfiguration FIXME better name?
type HTTPConfiguration struct {
Routers map[string]*Router `json:"routers,omitempty" toml:",omitempty"`
Middlewares map[string]*Middleware `json:"middlewares,omitempty" toml:",omitempty"`
Services map[string]*Service `json:"services,omitempty" toml:",omitempty"`
}
// 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).
type Service struct {
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"
"github.com/containous/traefik/log"
"github.com/containous/traefik/tls"
)
// EntryPoint holds the entry point configuration.
type EntryPoint struct {
Address string
Transport *EntryPointsTransport
TLS *tls.TLS
ProxyProtocol *ProxyProtocol
ForwardedHeaders *ForwardedHeaders
}
@ -65,14 +63,8 @@ func (ep *EntryPoints) Type() string {
func (ep *EntryPoints) Set(value string) error {
result := parseEntryPointsConfiguration(value)
configTLS, err := makeEntryPointTLS(result)
if err != nil {
return err
}
(*ep)[result["name"]] = &EntryPoint{
Address: result["address"],
TLS: configTLS,
ProxyProtocol: makeEntryPointProxyProtocol(result),
ForwardedHeaders: makeEntryPointForwardedHeaders(result),
}
@ -100,55 +92,6 @@ func makeEntryPointProxyProtocol(result map[string]string) *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 {
sections := strings.Fields(raw)

View file

@ -3,7 +3,6 @@ package static
import (
"testing"
"github.com/containous/traefik/tls"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -18,10 +17,6 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
name: "all parameters",
value: "Name:foo " +
"Address::8000 " +
"TLS:goo,gii " +
"TLS " +
"TLS.MinVersion:VersionTLS11 " +
"TLS.CipherSuites:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA " +
"CA:car " +
"CA.Optional:true " +
"Redirect.EntryPoint:https " +
@ -76,10 +71,6 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
"redirect_permanent": "true",
"redirect_regex": "http://localhost/(.*)",
"redirect_replacement": "http://mydomain/$1",
"tls": "goo,gii",
"tls_acme": "TLS",
"tls_ciphersuites": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"tls_minversion": "VersionTLS11",
"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",
@ -95,15 +86,6 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
"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 {
@ -185,23 +167,12 @@ func TestEntryPoints_Set(t *testing.T) {
name: "all parameters camelcase",
expression: "Name:foo " +
"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.Optional:true " +
"ProxyProtocol.TrustedIPs:192.168.0.1 ",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
Address: ":8000",
TLS: &tls.TLS{
MinVersion: "VersionTLS11",
CipherSuites: []string{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"},
ClientCA: tls.ClientCA{
Files: tls.FilesOrContents{"car"},
Optional: true,
},
},
ProxyProtocol: &ProxyProtocol{
Insecure: false,
TrustedIPs: []string{"192.168.0.1"},
@ -223,14 +194,6 @@ func TestEntryPoints_Set(t *testing.T) {
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
Address: ":8000",
TLS: &tls.TLS{
MinVersion: "VersionTLS11",
CipherSuites: []string{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"},
ClientCA: tls.ClientCA{
Files: tls.FilesOrContents{"car"},
Optional: true,
},
},
ProxyProtocol: &ProxyProtocol{
Insecure: false,
TrustedIPs: []string{"192.168.0.1"},

View file

@ -6,7 +6,6 @@ import (
"time"
"github.com/containous/flaeg/parse"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/log"
"github.com/containous/traefik/old/provider/boltdb"
"github.com/containous/traefik/old/provider/consul"
@ -70,7 +69,7 @@ type Configuration struct {
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.
@ -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.")
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) {
if c.ACME != nil {
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")
}
provider := &acmeprovider.Provider{}
provider.Configuration = convertACMEChallenge(c.ACME)
store := acmeprovider.NewLocalStore(provider.Storage)
provider.Store = store
acme.ConvertToNewFormat(provider.Storage)
c.ACME = nil
return provider, nil
return &acmeprovider.Provider{
Configuration: c.ACME,
}, nil
}
return nil, nil
}
@ -368,12 +356,26 @@ func (c *Configuration) InitACMEProvider() (*acmeprovider.Provider, error) {
// ValidateConfiguration validate that configuration is coherent
func (c *Configuration) ValidateConfiguration() {
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)
for _, domain := range c.ACME.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)
}
}
}
}
// 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 {
@ -395,47 +397,3 @@ func getSafeACMECAServer(caServerSrc string) string {
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"
```toml
[entryPoints]
[entryPoints.http]
[entrypoints]
[entrypoints.web]
address = ":80"
[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"
```toml
[entryPoints]
[entryPoints.http]
[entrypoints]
[entrypoints.web]
address = ":80"
[api]

View file

@ -24,11 +24,11 @@ You no longer need to create and synchronize configuration files cluttered with
!!! 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"
In the [middleware](../middlewares/overview.md) section, you can learn about how to update the requests before forwarding them to the services.
In the [middleware](../middlewares/overview.md) section, you can learn about how to update the requests before forwarding them to the services.
!!! question "How does Traefik discover the services?"

View file

@ -3,56 +3,52 @@
Automatic HTTPS
{: .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"
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
??? example "Configuring ACME on the Https EntryPoint"
??? example "Enabling ACME"
```toml
[entryPoints]
[entryPoints.web]
[entrypoints]
[entrypoints.web]
address = ":80"
[entryPoints.http-tls]
[entrypoints.http-tls]
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"
storage = "acme.json"
entryPoint = "http-tls" # acme is enabled on http-tls
onHostRule = true # dynamic generation based on the Host() matcher
onHostRule = true # dynamic generation based on the Host() & HostSNI() matchers
[acme.httpChallenge]
entryPoint = "web" # used during the challenge
entryPoint = "web" # used during the challenge
```
??? example "Configuring Wildcard Certificates"
```toml
[entryPoints]
[entryPoints.web]
address = ":80"
[entrypoints]
[entrypoints.web]
address = ":80"
[entrypoints.http-tls]
address = ":443"
[entryPoints.http-tls]
address = ":443"
[entryPoints.https.tls] # enabling TLS
[acme]
email = "your-email@your-domain.org"
storage = "acme.json"
entryPoint = "http-tls" # acme is enabled on http-tls
[acme.dnsChallenge]
provider = "xxx"
[[acme.domains]]
main = "*.mydomain.com"
sans = ["mydomain.com"]
```
email = "your-email@your-domain.org"
storage = "acme.json"
[acme.dnsChallenge]
provider = "xxx"
[[acme.domains]]
main = "*.mydomain.com"
sans = ["mydomain.com"]
```
!!! note "Configuration Reference"
There are many available options for ACME. For a quick glance at what's possible, browse the [configuration reference](../reference/acme.md).
@ -65,37 +61,34 @@ 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.
??? example "Using an EntryPoint Called https for the `tlsChallenge`"
??? example "Configuring the `tlsChallenge`"
```toml
[acme]
# ...
entryPoint = "https"
[acme.tlsChallenge]
[acme.tlsChallenge]
```
!!! 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`
Use the `HTTP-01` challenge to generate and renew ACME certificates by provisioning an HTTP resource under a well-known URI.
??? example "Using an EntryPoint Called http for the `httpChallenge`"
??? example "Using an EntryPoint Called http for the `httpChallenge`"
```toml
[acme]
# ...
entryPoint = "https"
[acme.httpChallenge]
entryPoint = "http"
# ...
[acme.httpChallenge]
entryPoint = "http"
```
!!! 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 `HTTP-01` challenge, `acme.httpChallenge.entryPoint` must be reachable by Let's Encrypt through port 80.
!!! note
Redirection is fully compatible with the `HTTP-01` challenge.
!!! note
Redirection is fully compatible with the `HTTP-01` challenge.
#### `dnsChallenge`
@ -105,20 +98,20 @@ Use the `DNS-01` challenge to generate and renew ACME certificates by provisioni
```toml
[acme]
# ...
[acme.dnsChallenge]
provider = "digitalocean"
delayBeforeCheck = 0
# ...
[acme.dnsChallenge]
provider = "digitalocean"
delayBeforeCheck = 0
# ...
```
!!! important
A `provider` is mandatory.
??? list "Supported Providers"
Here is a list of supported `providers`, that can automate the DNS verification, along with the required environment variables and their [wildcard & root domain support](#wildcard-domains).
Do not hesitate to complete it.
Do not hesitate to complete it.
| Provider Name | Provider Code | Environment Variables | Wildcard & Root Domain Support |
|-------------------------------------------------------------|----------------|-------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------|
@ -161,19 +154,19 @@ Use the `DNS-01` challenge to generate and renew ACME certificates by provisioni
| [Ns1](https://ns1.com/) | `ns1` | `NS1_API_KEY` | Not tested yet |
| [Open Telekom Cloud](https://cloud.telekom.de) | `otc` | `OTC_DOMAIN_NAME`, `OTC_USER_NAME`, `OTC_PASSWORD`, `OTC_PROJECT_NAME`, `OTC_IDENTITY_ENDPOINT` | Not tested yet |
| [OVH](https://www.ovh.com) | `ovh` | `OVH_ENDPOINT`, `OVH_APPLICATION_KEY`, `OVH_APPLICATION_SECRET`, `OVH_CONSUMER_KEY` | YES |
| [Openstack Designate](https://docs.openstack.org/designate) | `designate` | `OS_AUTH_URL`, `OS_USERNAME`, `OS_PASSWORD`, `OS_TENANT_NAME`, `OS_REGION_NAME` | YES |
| [PowerDNS](https://www.powerdns.com) | `pdns` | `PDNS_API_KEY`, `PDNS_API_URL` | Not tested yet |
| [Rackspace](https://www.rackspace.com/cloud/dns) | `rackspace` | `RACKSPACE_USER`, `RACKSPACE_API_KEY` | Not tested yet |
| [RFC2136](https://tools.ietf.org/html/rfc2136) | `rfc2136` | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER` | Not tested yet |
| [Route 53](https://aws.amazon.com/route53/) | `route53` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile. | YES |
| [Sakura Cloud](https://cloud.sakura.ad.jp/) | `sakuracloud` | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET` | Not tested yet |
| [Selectel](https://selectel.ru/en/) | `selectel` | `SELECTEL_API_TOKEN` | YES |
| [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | Not tested yet |
| [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | YES |
| [VegaDNS](https://github.com/shupp/VegaDNS-API) | `vegadns` | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL` | Not tested yet |
| [Vscale](https://vscale.io/) | `vscale` | `VSCALE_API_TOKEN` | YES |
| [VULTR](https://www.vultr.com) | `vultr` | `VULTR_API_KEY` | Not tested yet |
| [Zone.ee](https://www.zone.ee) | `zoneee` | `ZONEEE_API_USER`, `ZONEEE_API_KEY` | YES |
| [Openstack Designate](https://docs.openstack.org/designate) | `designate` | `OS_AUTH_URL`, `OS_USERNAME`, `OS_PASSWORD`, `OS_TENANT_NAME`, `OS_REGION_NAME` |YES |
| [PowerDNS](https://www.powerdns.com) | `pdns` | `PDNS_API_KEY`, `PDNS_API_URL` | Not tested yet |
| [Rackspace](https://www.rackspace.com/cloud/dns) | `rackspace` | `RACKSPACE_USER`, `RACKSPACE_API_KEY` | Not tested yet |
| [RFC2136](https://tools.ietf.org/html/rfc2136) | `rfc2136` | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER` | Not tested yet |
| [Route 53](https://aws.amazon.com/route53/) | `route53` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile. | YES |
| [Sakura Cloud](https://cloud.sakura.ad.jp/) | `sakuracloud` | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET` | Not tested yet |
| [Selectel](https://selectel.ru/en/) | `selectel` | `SELECTEL_API_TOKEN` | YES |
| [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | Not tested yet |
| [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | YES |
| [VegaDNS](https://github.com/shupp/VegaDNS-API) | `vegadns` | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL` | Not tested yet |
| [Vscale](https://vscale.io/) | `vscale` | `VSCALE_API_TOKEN` | YES |
| [VULTR](https://www.vultr.com) | `vultr` | `VULTR_API_KEY` | Not tested yet |
| [Zone.ee](https://www.zone.ee) | `zoneee` | `ZONEEE_API_USER`, `ZONEEE_API_KEY` | YES |
- (1): more information about the HTTP message format can be found [here](https://go-acme.github.io/lego/dns/httpreq/)
- (2): https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application
@ -187,13 +180,13 @@ Use the `DNS-01` challenge to generate and renew ACME certificates by provisioni
!!! note "`resolvers`"
Use custom DNS servers to resolve the FQDN authority.
```toml
[acme]
# ...
[acme.dnsChallenge]
# ...
resolvers = ["1.1.1.1:53", "8.8.8.8:53"]
# ...
[acme.dnsChallenge]
# ...
resolvers = ["1.1.1.1:53", "8.8.8.8:53"]
```
### Known Domains, SANs, and Wildcards
@ -204,15 +197,15 @@ Each domain & SAN will lead to a certificate request.
```toml
[acme]
# ...
[[acme.domains]]
main = "local1.com"
sans = ["test1.local1.com", "test2.local1.com"]
[[acme.domains]]
main = "local2.com"
[[acme.domains]]
main = "*.local3.com"
sans = ["local3.com", "test1.test1.local3.com"]
# ...
[[acme.domains]]
main = "local1.com"
sans = ["test1.local1.com", "test2.local1.com"]
[[acme.domains]]
main = "local2.com"
[[acme.domains]]
main = "*.local3.com"
sans = ["local3.com", "test1.test1.local3.com"]
# ...
```
@ -229,10 +222,11 @@ As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/stagi
```toml
[acme]
# ...
[[acme.domains]]
main = "*.local1.com"
sans = ["local1.com"]
# ...
[[acme.domains]]
main = "*.local1.com"
sans = ["local1.com"]
# ...
```
@ -241,7 +235,7 @@ As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/stagi
!!! note "Double Wildcard Certificates"
It is not possible to request a double wildcard certificate for a domain (for example `*.*.local.com`).
Due to an ACME limitation it is not possible to define wildcards in SANs (alternative domains).
Thus, the wildcard domain has to be defined as a main domain.
Most likely the root domain should receive a certificate too, so it needs to be specified as SAN and 2 `DNS-01` challenges are executed.
@ -256,22 +250,22 @@ The [Supported `provider` table](#dnschallenge) indicates if they allow generati
```toml
[acme]
# ...
caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"
# ...
# ...
caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"
# ...
```
### 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.
```toml
[acme]
# ...
onHostRule = true
# ...
# ...
onHostRule = true
# ...
```
!!! note "Multiple Hosts in a Rule"
@ -286,9 +280,9 @@ The `storage` option sets the location where your ACME certificates are saved to
```toml
[acme]
# ...
storage = "acme.json"
# ...
# ...
storage = "acme.json"
# ...
```
The value can refer to two kinds of storage:
@ -315,7 +309,7 @@ docker run -v "/my/host/acme:/etc/traefik/acme" traefik
#### In a a Key Value Store Entry
ACME certificates can be stored in a key-value store entry.
ACME certificates can be stored in a key-value store entry.
```toml
storage = "traefik/acme/account"

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"
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"
```toml
[Middlewares]
[Middlewares.add-foo.AddPrefix]
[http.middlewares]
[http.middlewares.add-foo.AddPrefix]
prefix = "/foo"
```
@ -23,7 +23,7 @@ The AddPrefix middleware updates the URL Path of the request before forwarding i
a-container:
image: a-container-image
labels:
- "traefik.middlewares.add-bar.addprefix.prefix=/bar"
- "traefik.http.middlewares.add-bar.addprefix.prefix=/bar"
```
## 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"
```toml
[Middlewares]
[Middlewares.test-auth.basicauth]
[http.middlewares]
[http.middlewares.test-auth.basicauth]
users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"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:
image: a-container-image
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
@ -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"
```toml
[Middlewares.my-auth.basicauth]
[http.middlewares.my-auth.basicauth]
usersFile = "path-to-file.ext"
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"
```toml
[Middlewares]
[Middlewares.2Mb-limit.buffering]
[http.middlewares]
[http.middlewares.2Mb-limit.buffering]
maxRequestBodyBytes = 250000
```
@ -27,7 +27,7 @@ This can help services deal with large data (multipart/form-data for example), a
a-container:
image: a-container-image
labels:
- "traefik.middlewares.1Mb-memory.buffering.memRequestBodyBytes=125000",
- "traefik.http.middlewares.1Mb-memory.buffering.memRequestBodyBytes=125000",
```
## Configuration Options

View file

@ -14,27 +14,27 @@ It makes reusing the same groups easier.
```toml
# ...
[Routers]
[Routers.router1]
[http.routers]
[http.routers.router1]
service = "service1"
middlewares = ["secured"]
rule = "Host: mydomain"
[Middlewares]
[Middlewares.secured.Chain]
[http.middlewares]
[http.middlewares.secured.Chain]
middlewares = ["https-only", "known-ips", "auth-users"]
[Middlewares.auth-users.BasicAuth]
[http.middlewares.auth-users.BasicAuth]
users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"]
[Middlewares.https-only.SchemeRedirect]
[http.middlewares.https-only.SchemeRedirect]
scheme = "https"
[Middlewares.known-ips.ipWhiteList]
[http.middlewares.known-ips.ipWhiteList]
sourceRange = ["192.168.1.7", "x.x.x.x", "x.x.x.x"]
[Services]
[Services.service1]
[Services.service1.LoadBalancer]
[[Services.service1.LoadBalancer.Servers]]
[http.services]
[http.services.service1]
[http.services.service1.LoadBalancer]
[[http.services.service1.LoadBalancer.Servers]]
URL = "http://127.0.0.1:80"
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"
```toml
[middlewares]
[middlewares.latency-check.circuitbreaker]
[http.middlewares]
[http.middlewares.latency-check.circuitbreaker]
expression = "LatencyAtQuantileMS(50.0) > 100"
```
@ -38,7 +38,7 @@ To assess if your system is healthy, the circuit breaker constantly monitors the
container-definition:
image: image-name
labels:
- "traefik.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100"
- "traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100"
```
## Possible States

View file

@ -12,8 +12,8 @@ The Compress middleware enables the gzip compression.
??? example "File -- enable gzip compression"
```toml
[Middlewares]
[Middlewares.test-compress.Compress]
[http.middlewares]
[http.middlewares.test-compress.Compress]
```
??? example "Docker -- enable gzip compression"
@ -22,7 +22,7 @@ The Compress middleware enables the gzip compression.
a-container:
image: a-container-image
labels:
- "traefik.middlewares.test-compress.compress=true",
- "traefik.http.middlewares.test-compress.compress=true",
```
## 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"
```toml
[Middlewares]
[Middlewares.test-auth.digestauth]
[http.middlewares]
[http.middlewares.test-auth.digestauth]
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:
image: a-container-image
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
@ -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"
```toml
[Middlewares.my-auth.digestauth]
[http.middlewares.my-auth.digestauth]
usersFile = "path-to-file.ext"
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"
```toml
[Routers]
[Routers.router1]
[http.routers]
[http.routers.router1]
Service = "my-service"
Rule = Host(`my-domain`)
[Middlewares]
[Middlewares.5XX-errors.Errors]
[http.middlewares]
[http.middlewares.5XX-errors.Errors]
status = ["500-599"]
service = "error-handler-service"
query = "/error.html"
[Services]
[http.services]
# ... 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:
image: a-container-image
labels:
- "traefik.middlewares.test-errorpage.errors.status=500-599",
- "traefik.middlewares.test-errorpage.errors.service=serviceError",
- "traefik.middlewares.test-errorpage.errors.query=/{status}.html",
- "traefik.http.middlewares.test-errorpage.errors.status=500-599",
- "traefik.http.middlewares.test-errorpage.errors.service=serviceError",
- "traefik.http.middlewares.test-errorpage.errors.query=/{status}.html",
```

View file

@ -14,13 +14,13 @@ Otherwise, the response from the authentication server is returned.
??? example "File -- Forward authentication to authserver.com"
```toml
[Middlewares]
[Middlewares.test-auth.forwardauth]
[http.middlewares]
[http.middlewares.test-auth.forwardauth]
address = "https://authserver.com/auth"
trustForwardHeader = true
authResponseHeaders = ["X-Auth-User", "X-Secret"]
[Middlewares.test-auth.forwardauth.tls]
[http.middlewares.test-auth.forwardauth.tls]
ca = "path/to/local.crt"
caOptional = true
cert = "path/to/foo.cert"
@ -33,14 +33,14 @@ Otherwise, the response from the authentication server is returned.
a-container:
image: a-container-image
labels:
- "traefik.Middlewares.test-auth.ForwardAuth.Address=https://authserver.com/auth"
- "traefik.Middlewares.test-auth.ForwardAuth.AuthResponseHeaders=X-Auth-User, X-Secret"
- "traefik.Middlewares.test-auth.ForwardAuth.TLS.CA=path/to/local.crt"
- "traefik.Middlewares.test-auth.ForwardAuth.TLS.CAOptional=true"
- "traefik.Middlewares.test-auth.ForwardAuth.TLS.Cert=path/to/foo.cert"
- "traefik.Middlewares.test-auth.ForwardAuth.TLS.InsecureSkipVerify=true"
- "traefik.Middlewares.test-auth.ForwardAuth.TLS.Key=path/to/foo.key"
- "traefik.Middlewares.test-auth.ForwardAuth.TrustForwardHeader=true"
- "traefik.http.middlewares.test-auth.ForwardAuth.Address=https://authserver.com/auth"
- "traefik.http.middlewares.test-auth.ForwardAuth.AuthResponseHeaders=X-Auth-User, X-Secret"
- "traefik.http.middlewares.test-auth.ForwardAuth.TLS.CA=path/to/local.crt"
- "traefik.http.middlewares.test-auth.ForwardAuth.TLS.CAOptional=true"
- "traefik.http.middlewares.test-auth.ForwardAuth.TLS.Cert=path/to/foo.cert"
- "traefik.http.middlewares.test-auth.ForwardAuth.TLS.InsecureSkipVerify=true"
- "traefik.http.middlewares.test-auth.ForwardAuth.TLS.Key=path/to/foo.key"
- "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"
```toml
[Middlewares]
[Middlewares.testHeader.headers]
[Middlewares.testHeader.headers.CustomRequestHeaders]
[http.middlewares]
[http.middlewares.testHeader.headers]
[http.middlewares.testHeader.headers.CustomRequestHeaders]
X-Script-Name = "test"
[Middlewares.testHeader.headers.CustomResponseHeaders]
[http.middlewares.testHeader.headers.CustomResponseHeaders]
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:
image: a-container-image
labels:
- "traefik.Middlewares.testHeader.Headers.CustomRequestHeaders.X-Script-Name=test",
- "traefik.Middlewares.testHeader.Headers.CustomResponseHeaders.X-Custom-Response-Header=True",
- "traefik.http.middlewares.testHeader.Headers.CustomRequestHeaders.X-Script-Name=test",
- "traefik.http.middlewares.testHeader.Headers.CustomResponseHeaders.X-Custom-Response-Header=True",
```
### 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"
```toml
[Middlewares]
[Middlewares.testHeader.headers]
[Middlewares.testHeader.headers.CustomRequestHeaders]
[http.middlewares]
[http.middlewares.testHeader.headers]
[http.middlewares.testHeader.headers.CustomRequestHeaders]
X-Script-Name = "test"
[Middlewares.testHeader.headers.CustomResponseHeaders]
[http.middlewares.testHeader.headers.CustomResponseHeaders]
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:
image: a-container-image
labels:
- "traefik.Middlewares.testHeader.Headers.CustomRequestHeaders.X-Script-Name=test",
- "traefik.Middlewares.testHeader.Headers.CustomResponseHeaders.X-Custom-Response-Header=True",
- "traefik.http.middlewares.testHeader.Headers.CustomRequestHeaders.X-Script-Name=test",
- "traefik.http.middlewares.testHeader.Headers.CustomResponseHeaders.X-Custom-Response-Header=True",
```
### Using Security Headers
@ -67,8 +67,8 @@ This functionality allows for some easy security features to quickly be set.
??? example "File"
```toml
[Middlewares]
[Middlewares.testHeader.headers]
[http.middlewares]
[http.middlewares.testHeader.headers]
FrameDeny = true
SSLRedirect = true
```
@ -79,8 +79,8 @@ This functionality allows for some easy security features to quickly be set.
a-container:
image: a-container-image
labels:
- "traefik.Middlewares.testHeader.Headers.FrameDeny=true",
- "traefik.Middlewares.testHeader.Headers.SSLRedirect=true",
- "traefik.http.middlewares.testHeader.Headers.FrameDeny=true",
- "traefik.http.middlewares.testHeader.Headers.SSLRedirect=true",
```
## Configuration Options

View file

@ -12,8 +12,8 @@ IPWhitelist accepts / refuses requests based on the client IP.
??? example "File -- Accepts request from defined IP"
```toml
[Middlewares]
[Middlewares.test-ipwhitelist.ipWhiteList]
[http.middlewares]
[http.middlewares.test-ipwhitelist.ipWhiteList]
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:
image: a-container-image
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
@ -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`"
```toml
[Middlewares]
[Middlewares.test-ipwhitelist.ipWhiteList]
[http.middlewares]
[http.middlewares.test-ipwhitelist.ipWhiteList]
sourceRange = ["127.0.0.1/32", "192.168.1.7"]
[Middlewares.test-ipwhitelist.ipWhiteList.ipStrategy]
[http.middlewares.test-ipwhitelist.ipWhiteList.ipStrategy]
depth = 2
```
@ -68,8 +68,8 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take th
a-container:
image: a-container-image
labels:
- "traefik.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.SourceRange=127.0.0.1/32, 192.168.1.7"
- "traefik.http.middlewares.testIPwhitelist.ipwhitelist.ipstrategy.depth=2"
```
!!! 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`"
```toml
[Middlewares]
[Middlewares.test-ipwhitelist.ipWhiteList]
[Middlewares.test-ipwhitelist.ipWhiteList.ipStrategy]
[http.middlewares]
[http.middlewares.test-ipwhitelist.ipWhiteList]
[http.middlewares.test-ipwhitelist.ipWhiteList.ipStrategy]
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:
image: a-container-image
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"
```toml
[Middlewares]
[Middlewares.test-maxconn.maxconn]
[http.middlewares]
[http.middlewares.test-maxconn.maxconn]
amount = 10
```
@ -23,7 +23,7 @@ To proactively prevent services from being overwhelmed with high load, a maximum
a-container:
image: a-container-image
labels:
- "traefik.middlewares.test-maxconn.maxconn.amount=10"
- "traefik.http.middlewares.test-maxconn.maxconn.amount=10"
```
## Configuration Options

View file

@ -5,35 +5,35 @@ Tweaking the Request
![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.
Pieces of middleware can be combined in chains to fit every scenario.
## Configuration Example
Pieces of middleware can be combined in chains to fit every scenario.
## Configuration Example
??? example "As Toml Configuration File"
```toml
[providers]
[providers.file]
[Routers]
[Routers.router1]
[http.routers]
[http.routers.router1]
Service = "myService"
Middlewares = ["foo-add-prefix"]
Rule = "Host: example.com"
[Middlewares]
[Middlewares.foo-add-prefix.AddPrefix]
[http.middlewares]
[http.middlewares.foo-add-prefix.AddPrefix]
prefix = "/foo"
[Services]
[Services.service1]
[Services.service1.LoadBalancer]
[[Services.service1.LoadBalancer.Servers]]
[http.services]
[http.services.service1]
[http.services.service1.LoadBalancer]
[[http.services.service1.LoadBalancer.Servers]]
URL = "http://127.0.0.1:80"
Weight = 1
```
@ -45,7 +45,7 @@ Pieces of middleware can be combined in chains to fit every scenario.
whoami:
image: containous/whoami # A container that exposes an API to show its IP address
labels:
- "traefik.middlewares.foo-add-prefix.addprefix.prefix=/foo",
- "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo",
```
## Advanced Configuration
@ -58,25 +58,25 @@ If you use multiple `providers` and wish to reference a middleware declared in a
??? abstract "Referencing a Middleware from Another Provider"
Declaring the add-foo-prefix in the file provider.
```toml
[providers]
[providers.file]
[middlewares]
[middlewares.add-foo-prefix.AddPrefix]
[http.middlewares]
[http.middlewares.add-foo-prefix.AddPrefix]
prefix = "/foo"
```
Using the add-foo-prefix middleware from docker.
```yaml
your-container: #
image: your-docker-image
image: your-docker-image
labels:
# 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

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"
```toml
[Middlewares]
[Middlewares.test-passtlsclientcert.passtlsclientcert]
[http.middlewares]
[http.middlewares.test-passtlsclientcert.passtlsclientcert]
pem = true
```
@ -23,19 +23,19 @@ PassTLSClientCert adds in header the selected data from the passed client tls ce
a-container:
image: a-container-image
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"
```toml
[Middlewares]
[Middlewares.test-passtlsclientcert.passtlsclientcert]
[Middlewares.test-passtlsclientcert.passtlsclientcert.info]
[http.middlewares]
[http.middlewares.test-passtlsclientcert.passtlsclientcert]
[http.middlewares.test-passtlsclientcert.passtlsclientcert.info]
notAfter = true
notBefore = true
sans = true
[Middlewares.test-passtlsclientcert.passtlsclientcert.info.subject]
[http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject]
country = true
province = true
locality = true
@ -43,7 +43,7 @@ PassTLSClientCert adds in header the selected data from the passed client tls ce
commonName = true
serialNumber = true
domainComponent = true
[Middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer]
[http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer]
country = true
province = true
locality = true
@ -59,23 +59,23 @@ PassTLSClientCert adds in header the selected data from the passed client tls ce
a-container:
image: a-container-image
labels:
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.country=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.domaincomponent=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.locality=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.organization=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.province=true"
- "traefik.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.country=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.domaincomponent=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.locality=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.organization=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.province=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber=true"
```
## 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)"
```toml
[middlewares]
[middlewares.fair-ratelimit.ratelimit]
[http.middlewares]
[http.middlewares.fair-ratelimit.ratelimit]
extractorfunc = "client.ip"
[middlewares.fair-ratelimit.ratelimit.rateset1]
[http.middlewares.fair-ratelimit.ratelimit.rateset1]
period = "10s"
average = 100
burst = 200
@ -25,16 +25,16 @@ The RateLimit middleware ensures that services will receive a _fair_ number of r
??? example "Combine multiple limits"
```toml
[middlewares]
[middlewares.fair-ratelimit.ratelimit]
[http.middlewares]
[http.middlewares.fair-ratelimit.ratelimit]
extractorfunc = "client.ip"
[middlewares.fair-ratelimit.ratelimit.rateset1]
[http.middlewares.fair-ratelimit.ratelimit.rateset1]
period = "10s"
average = 100
burst = 200
[middlewares.fair-ratelimit.ratelimit.rateset2]
[http.middlewares.fair-ratelimit.ratelimit.rateset2]
period = "3s"
average = 5
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"
```toml
[Middlewares]
[Middlewares.test-redirectregex.redirectregex]
[http.middlewares]
[http.middlewares.test-redirectregex.redirectregex]
regex = "^http://localhost/(.*)"
replacement = "http://mydomain/$1"
```
@ -24,8 +24,8 @@ RegexRedirect redirect a request from an url to another with regex matching and
a-container:
image: a-container-image
labels:
- "traefik.Middlewares.test-redirectregex.redirectregex.regex=^http://localhost/(.*)"
- "traefik.Middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$1"
- "traefik.http.middlewares.test-redirectregex.redirectregex.regex=^http://localhost/(.*)"
- "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$1"
```
## Configuration Options

View file

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

View file

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

View file

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

View file

@ -1,7 +1,7 @@
# Traefik & Docker
A Story of Labels & Containers
{: .subtitle }
{: .subtitle }
![Docker](../assets/img/providers/docker.png)
@ -15,27 +15,27 @@ Attach labels to your containers and let Traefik do the rest!
??? example "Configuring Docker & Deploying / Exposing Services"
Enabling the docker provider
```toml
[docker]
endpoint = "unix:///var/run/docker.sock"
```
Attaching labels to containers (in your docker compose file)
```yaml
version: "3"
services:
my-container:
# ...
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"
Enabling the docker provider (Swarm Mode)
```toml
[docker]
# swarm classic (1.12-)
@ -44,18 +44,18 @@ Attach labels to your containers and let Traefik do the rest!
endpoint = "tcp://127.0.0.1:2377"
swarmMode = true
```
Attaching labels to containers (in your docker compose file)
```yaml
version: "3"
services:
my-container:
deploy:
labels:
- traefik.services.my-container.rule=Host(my-domain)
- traefik.http.services.my-container.rule=Host(my-domain)
```
!!! important "Labels in Docker Swarm Mode"
If you use a compose file with the Swarm mode, labels should be defined in the `deploy` part of your service.
This behavior is only enabled for docker-compose version 3+ ([Compose file reference](https://docs.docker.com/compose/compose-file/#labels-1)).
@ -76,13 +76,13 @@ Traefik requires access to the docker socket to get its dynamic configuration.
As explained in the Docker documentation: ([Docker Daemon Attack Surface page](https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface)):
`[...] only **trusted** users should be allowed to control your Docker daemon [...]`
!!! note "Improved Security"
[TraefikEE](https://containo.us/traefikee) solves this problem by separating the control plane (connected to Docker) and the data plane (handling the requests).
??? tip "Resources about Docker's Security"
- [KubeCon EU 2018 Keynote, Running with Scissors, from Liz Rice](https://www.youtube.com/watch?v=ltrV-Qmh3oY)
- [Don't expose the Docker socket (not even to a container)](https://www.lvh.io/posts/dont-expose-the-docker-socket-not-even-to-a-container.html)
- [A thread on Stack Overflow about sharing the `/var/run/docker.sock` file](https://news.ycombinator.com/item?id=17983623)
@ -92,20 +92,20 @@ Traefik requires access to the docker socket to get its dynamic configuration.
Expose the Docker socket over TCP, instead of the default Unix socket file.
It allows different implementation levels of the [AAA (Authentication, Authorization, Accounting) concepts](https://en.wikipedia.org/wiki/AAA_(computer_security)), depending on your security assessment:
- Authentication with Client Certificates as described in ["Protect the Docker daemon socket."](https://docs.docker.com/engine/security/https/)
- Authorization with the [Docker Authorization Plugin Mechanism](https://docs.docker.com/engine/extend/plugins_authorization/)
- Accounting at networking level, by exposing the socket only inside a Docker private network, only available for Traefik.
- Accounting at container level, by exposing the socket on a another container than Traefik's.
With Swarm mode, it allows scheduling of Traefik on worker nodes, with only the "socket exposer" container on the manager nodes.
- Accounting at kernel level, by enforcing kernel calls with mechanisms like [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux), to only allows an identified set of actions for Traefik's process (or the "socket exposer" process).
??? tip "Additional Resources"
- [Traefik issue GH-4174 about security with Docker socket](https://github.com/containous/traefik/issues/4174)
- [Inspecting Docker Activity with Socat](https://developers.redhat.com/blog/2015/02/25/inspecting-docker-activity-with-socat/)
- [Letting Traefik run on Worker Nodes](https://blog.mikesir87.io/2018/07/letting-traefik-run-on-worker-nodes/)
@ -113,34 +113,34 @@ Traefik requires access to the docker socket to get its dynamic configuration.
!!! note "Traefik & Swarm Mode"
To let Traefik access the Docker Socket of the Swarm manager, it is mandatory to schedule Traefik on the Swarm manager nodes.
??? example "Using the docker.sock"
The docker-compose file shares the docker sock with the Traefik container
```yaml
version: '3'
services:
traefik:
image: traefik
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
```
```
We specify the docker.sock in traefik's configuration file.
```toml
# ...
[providers]
[providers.docker]
endpoint = "unix:///var/run/docker.sock"
```
### usebindportip (_Optional_, _Default=false_)
### usebindportip (_Optional_, _Default=false_)
Traefik routes requests to the IP/Port of the matching container.
When setting `usebindportip=true`, you tell Traefik to use the IP/Port attached to the container's _binding_ instead of its inner network IP/Port.
@ -159,11 +159,11 @@ If it can't find such a binding, Traefik falls back on the internal network IP o
| LblPort | ExtIp:ExtPort:LblPort | ExtIp:ExtPort |
| LblPort | ExtIp:ExtPort:OtherPort | IntIp:LblPort |
| LblPort | ExtIp1:ExtPort1:IntPort1 & ExtIp2:LblPort:IntPort2 | ExtIp2:LblPort |
!!! note
In the above table, ExtIp stands for "external IP found in the binding", IntIp stands for "internal network container's IP", ExtPort stands for "external Port found in the binding", and IntPort stands for "internal network container's port."
### exposedByDefault (_Optional_, _Default=true_)
### exposedByDefault (_Optional_, _Default=true_)
Expose containers by default through Traefik.
If set to false, containers that don't have a `traefik.enable=true` label will be ignored from the resulting routing configuration.
@ -193,25 +193,25 @@ Defines the polling interval (in seconds) in Swarm Mode.
### 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.
### 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
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
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"
@ -220,8 +220,8 @@ You can declare pieces of middleware using labels starting with `traefik.middlew
my-container:
# ...
labels:
- traefik.middlewares.my-redirect.schemeredirect.scheme=https
- traefik.routers.middlewares=my-redirect
- traefik.http.middlewares.my-redirect.schemeredirect.scheme=https
- traefik.http.routers.middlewares=my-redirect
```
!!! warning "Conflicts in Declaration"
@ -240,11 +240,11 @@ This option overrides the value of `exposedByDefault`.
Sets the tags for [constraints filtering](./overview.md#constraints-configuration).
#### traefik.docker.network
#### traefik.docker.network
Overrides the default docker network to use for connections to the container.
If a container is linked to several networks, be sure to set the proper network name (you can check this with `docker inspect <container_id>`), otherwise it will randomly pick one (depending on how docker is returning them).
If a container is linked to several networks, be sure to set the proper network name (you can check this with `docker inspect <container_id>`), otherwise it will randomly pick one (depending on how docker is returning them).
!!! warning
!!! warning
When deploying a stack from a compose file `stack`, the networks defined are prefixed with `stack`.

View file

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

View file

@ -6,86 +6,21 @@ Every Options for EntryPoints
## TOML
```toml
defaultEntryPoints = ["http", "https"]
# ...
# ...
[entryPoints]
[entryPoints.http]
[entrypoints]
[entrypoints.web]
address = ":80"
[entryPoints.http.compress]
[entryPoints.http.clientIPStrategy]
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]
[entrypoints.web.proxyProtocol]
insecure = true
trustedIPs = ["10.10.10.1", "10.10.10.2"]
[entryPoints.http.forwardedHeaders]
[entrypoints.web.forwardedHeaders]
trustedIPs = ["10.10.10.1", "10.10.10.2"]
insecure = false
[entryPoints.https]
[entrypoints.web-secure]
# ...
```
@ -94,38 +29,7 @@ defaultEntryPoints = ["http", "https"]
```ini
Name:foo
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.Insecure:true
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,76 +6,39 @@ Opening Connections for Incomming Requests
![EntryPoints](../assets/img/entrypoints.png)
Entrypoints are the network entry points into Traefik.
They can be defined using:
- a port (80, 443, ...)
- SSL (Certificates, Keys, authentication with a client certificate signed by a trusted CA, ...)
They define the port which will receive the requests (whether HTTP or TCP).
## Configuration Examples
??? example "HTTP only"
??? example "Port 80 only"
```toml
[entryPoints]
[entryPoints.http]
address = ":80"
[entrypoints]
[entrypoints.web]
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
[entryPoints]
[entryPoints.http]
[entrypoints]
[entrypoints.web]
address = ":80"
[entryPoints.https]
[entrypoints.web-secure]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
[entrypoints.web-secure.tls]
[[entrypoints.web-secure.tls.certificates]]
certFile = "tests/traefik.crt"
keyFile = "tests/traefik.key"
```
- Two entrypoints are defined: one called `http`, and the other called `https`.
- `http` listens on port `80`, and `https` on port `443`.
- We enabled SSL on `https` by giving it a certificate and a key.
!!! note
- Two entrypoints are defined: one called `web`, and the other called `web-secure`.
- `web` listens on port `80`, and `web-secure` on port `443`.
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
### General
@ -115,130 +78,6 @@ Entrypoints are part of the [static configuration](../getting-started/configurat
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
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"
```toml
[entryPoints]
[entryPoints.http]
[entrypoints]
[entrypoints.web]
address = ":80"
[entryPoints.http.proxyProtocol]
[entrypoints.web.proxyProtocol]
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)
```toml
[entryPoints]
[entryPoints.http]
[entrypoints]
[entrypoints.web]
address = ":80"
[entryPoints.http.proxyProtocol]
[entrypoints.web.proxyProtocol]
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"
```toml
[entryPoints]
[entryPoints.http]
[entrypoints]
[entrypoints.web]
address = ":80"
[entryPoints.http.forwardedHeaders]
[entrypoints.web.forwardedHeaders]
trustedIPs = ["127.0.0.1/32", "192.168.1.7"]
```
??? example "Insecure Mode -- Always Trusting Forwarded Headers"
```toml
[entryPoints]
[entryPoints.http]
[entrypoints]
[entrypoints.web]
address = ":80"
[entryPoints.http.forwardedHeaders]
[entrypoints.web.forwardedHeaders]
insecure = true
```

View file

@ -5,51 +5,95 @@ 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.
First, when you start Traefik, you define [entrypoints](./entrypoints.md) (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).
If they do, the router might transform the request using pieces of [middleware](../middlewares/overview.md) before forwarding them to your [services](./services.md).
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) 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/index.md).
![Architecture](../assets/img/architecture-overview.png)
## Clear Responsibilities
- [_Providers_](../providers/overview.md) discover the services that live on your infrastructure (their IP, health, ...)
- [_Entrypoints_](./entrypoints.md) listen for incomming traffic (ports, SSL, ...)
- [_Routers_](./routers.md) analyse the requests (host, path, headers, ...)
- [_Services_](./services.md) forward the request to your services (load balancing, ...)
- [_Providers_](../providers/overview.md) discover the services that live on your infrastructure (their IP, health, ...)
- [_Entrypoints_](./entrypoints.md) listen for incomming traffic (ports, ...)
- [_Routers_](./routers/index.md) analyse the requests (host, path, headers, SSL, ...)
- [_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, ...)
## Example with a File Provider
Below is an example of a full configuration file for the [file provider](../providers/file.md) that forwards `http://domain/whoami/` requests to a service reachable on `http://private/whoami-service/`.
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
[EntryPoints]
[EntryPoints.http]
[entrypoints]
[entrypoints.web]
address = ":8081" # Listen on port 8081 for incoming requests
[Providers]
# Enable the file provider to define routers / middlewares / services in a file
[Providers.file]
[providers]
[providers.file] # Enable the file provider to define routers / middlewares / services in a file
[Routers]
[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)
[Middlewares]
[Middlewares.test-user.basicauth] # Define an authentication mechanism
users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"]
[Services]
[Services.whoami.loadbalancer] # Define how to reach an existing service on our infrastructure
[[Services.whoami.loadbalancer.servers]]
url = "http://private/whoami-service"
[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"
```
!!! note "The File Provider"
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.
!!! 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
{: .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.
## 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
[Services]
[Services.my-service.LoadBalancer]
[http.services]
[http.services.my-service.LoadBalancer]
method = "wrr" # Load Balancing based on weights
[[Services.my-service.LoadBalancer.servers]]
[[http.services.my-service.LoadBalancer.servers]]
url = "http://private-ip-server-1/"
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/"
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
Currently, the `LoadBalancer` service is the only supported kind of `Service` (see below).
However, since Traefik is an ever evolving project, other kind of Services will be available in the future,
reason why you have to specify what kind of service you declare.
Currently, `LoadBalancer` is the only supported kind of HTTP `Service` (see below).
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 it.
### 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
[Services]
[Services.my-service.LoadBalancer]
[http.services]
[http.services.my-service.LoadBalancer]
method = "wrr" # Load Balancing based on weights
[[Services.my-service.LoadBalancer.servers]]
[[http.services.my-service.LoadBalancer.servers]]
url = "http://private-ip-server-1/"
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/"
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
Paths in the servers' `url` have no effet.
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.
??? example "A Service with One Server -- Using the [File Provider](../providers/file.md)"
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)"
```toml
[Services]
[Services.my-service.LoadBalancer]
[[Services.my-service.LoadBalancer.servers]]
[http.services]
[http.services.my-service.LoadBalancer]
[[http.services.my-service.LoadBalancer.servers]]
url = "http://private-ip-server-1/"
```
@ -77,16 +88,16 @@ Various methods of load balancing are supported:
- `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)
??? 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
[Services]
[Services.my-service.LoadBalancer]
[http.services]
[http.services.my-service.LoadBalancer]
method = "drr"
[[Services.my-service.LoadBalancer.servers]]
[[http.services.my-service.LoadBalancer.servers]]
url = "http://private-ip-server-1/"
[[Services.my-service.LoadBalancer.servers]]
[[http.services.my-service.LoadBalancer.servers]]
url = "http://private-ip-server-1/"
```
@ -106,17 +117,17 @@ On subsequent requests, the client is forwarded to the same server.
??? example "Adding Stickiness"
```toml
[Services]
[Services.my-service]
[Services.my-service.LoadBalancer.stickiness]
[http.services]
[http.services.my-service]
[http.services.my-service.LoadBalancer.stickiness]
```
??? example "Adding Stickiness with a Custom Cookie Name"
```toml
[Services]
[Services.my-service]
[Services.my-service.LoadBalancer.stickiness]
[http.services]
[http.services.my-service]
[http.services.my-service.LoadBalancer.stickiness]
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"
```toml
[Services]
[Servicess.Service-1]
[Services.Service-1.healthcheck]
[http.services]
[http.servicess.Service-1]
[http.services.Service-1.healthcheck]
path = "/health"
interval = "10s"
timeout = "3s"
@ -159,9 +170,9 @@ Below are the available options for the health check mechanism:
??? example "Custom Port -- Using the File Provider"
```toml
[Services]
[Services.Service-1]
[Services.Service-1.healthcheck]
[http.services]
[http.services.Service-1]
[http.services.Service-1.healthcheck]
path = "/health"
port = 8080
```
@ -169,9 +180,9 @@ Below are the available options for the health check mechanism:
??? example "Custom Scheme -- Using the File Provider"
```toml
[Services]
[Services.Service-1]
[Services.Service-1.healthcheck]
[http.services]
[http.services.Service-1]
[http.services.Service-1.healthcheck]
path = "/health"
scheme = "http"
```
@ -179,12 +190,53 @@ Below are the available options for the health check mechanism:
??? example "Additional HTTP Headers -- Using the File Provider"
```toml
[Services]
[Services.Service-1]
[Servicess.Service-1.healthcheck]
[http.services]
[http.services.Service-1]
[http.servicess.Service-1.healthcheck]
path = "/health"
[Service.Service-1.healthcheck.headers]
My-Custom-Header = "foo"
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':
- 'Overview': 'routing/overview.md'
- 'Entrypoints': 'routing/entrypoints.md'
- 'Routers': 'routing/routers.md'
- 'Services': 'routing/services.md'
- 'ACME': 'routing/acme.md'
- 'Routers': 'routing/routers/index.md'
- 'Services': 'routing/services/index.md'
- 'HTTPS & TLS':
- 'Overview': 'https-tls/overview.md'
- 'ACME': 'https-tls/acme.md'
- 'Middlewares':
- 'Overview': 'middlewares/overview.md'
- 'AddPrefix': 'middlewares/addprefix.md'

View file

@ -11,6 +11,19 @@ readonly BASE_DIR=/app
echo "== Linting Markdown"
# Uses the file ".markdownlint.json" for setup
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}"

View file

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

View file

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

View file

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

View file

@ -1,13 +1,11 @@
logLevel = "DEBUG"
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.http]
[entrypoints]
[entrypoints.web]
address = ":80"
[entryPoints.https]
[entrypoints.web-secure]
address = ":443"
[entryPoints.https.tls]
[entrypoints.web-secure.tls]
[acme]
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:
image: containous/whoami # A container that exposes an API to show its IP address
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).

View file

@ -15,4 +15,4 @@ services:
whoami:
image: containous/whoami # A container that exposes an API to show its IP address
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) {
c.Skip("We need to fix DefaultCertificate at start")
testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{
Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"},
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
Domains: types.Domains{types.Domain{
Main: "traefik.acme.wtf",
}},
@ -139,11 +140,12 @@ func (s *AcmeSuite) TestHTTP01DomainsAtStart(c *check.C) {
}
func (s *AcmeSuite) TestHTTP01DomainsInSANAtStart(c *check.C) {
c.Skip("We need to fix DefaultCertificate at start")
testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{
Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"},
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
Domains: types.Domains{types.Domain{
Main: "acme.wtf",
SANs: []string{"traefik.acme.wtf"},
@ -162,7 +164,7 @@ func (s *AcmeSuite) TestHTTP01OnHostRule(c *check.C) {
traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{
Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"},
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
OnHostRule: true,
},
},
@ -178,7 +180,7 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleECDSA(c *check.C) {
traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{
Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"},
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
OnHostRule: true,
KeyType: "EC384",
},
@ -195,7 +197,7 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleInvalidAlgo(c *check.C) {
traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{
Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"},
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
OnHostRule: true,
KeyType: "INVALID",
},
@ -207,28 +209,12 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleInvalidAlgo(c *check.C) {
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) {
testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_tls.toml",
template: templateModel{
Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"},
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
OnHostRule: true,
},
},
@ -244,7 +230,7 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleDynamicCertificatesWithWildcard(c *check
traefikConfFilePath: "fixtures/acme/acme_tls_dynamic.toml",
template: templateModel{
Acme: acme.Configuration{
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"},
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
OnHostRule: true,
},
},
@ -255,78 +241,6 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleDynamicCertificatesWithWildcard(c *check
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) {
testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_base.toml",
@ -343,23 +257,8 @@ func (s *AcmeSuite) TestTLSALPN01OnHostRule(c *check.C) {
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) {
c.Skip("We need to fix DefaultCertificate at start")
testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{
@ -378,6 +277,7 @@ func (s *AcmeSuite) TestTLSALPN01DomainsAtStart(c *check.C) {
}
func (s *AcmeSuite) TestTLSALPN01DomainsInSANAtStart(c *check.C) {
c.Skip("We need to fix DefaultCertificate at start")
testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_base.toml",
template: templateModel{
@ -397,6 +297,7 @@ func (s *AcmeSuite) TestTLSALPN01DomainsInSANAtStart(c *check.C) {
}
func (s *AcmeSuite) TestTLSALPN01DomainsWithProvidedWildcardDomainAtStart(c *check.C) {
c.Skip("We need to fix DefaultCertificate at start")
testCase := acmeTestCase{
traefikConfFilePath: "fixtures/acme/acme_tls.toml",
template: templateModel{
@ -419,7 +320,7 @@ func (s *AcmeSuite) TestNoValidLetsEncryptServer(c *check.C) {
file := s.adaptFile(c, "fixtures/acme/acme_base.toml", templateModel{
Acme: acme.Configuration{
CAServer: "http://wrongurl:4001/directory",
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "http"},
HTTPChallenge: &acme.HTTPChallenge{EntryPoint: "web"},
OnHostRule: true,
},
})

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,49 +2,48 @@
logLevel = "DEBUG"
[entryPoints]
[entryPoints.https]
[entrypoints]
[entrypoints.web-secure]
address = ":4443"
[entryPoints.https.tls]
[entryPoints.https.tls.ClientCA]
files = ["fixtures/https/clientca/ca1.crt", "fixtures/https/clientca/ca2.crt"]
optional = false
[api]
[providers]
[providers.file]
[Routers]
[Routers.router1]
[http.routers]
[http.routers.router1]
Service = "service1"
Rule = "Host(`snitest.com`)"
[Routers.router2]
[http.routers.router1.tls]
[http.routers.router2]
Service = "service2"
Rule = "Host(`snitest.org`)"
[http.routers.router2.tls]
[Services]
[Services.service1]
[Services.service1.LoadBalancer]
[[Services.service1.LoadBalancer.Servers]]
[http.services]
[http.services.service1]
[http.services.service1.LoadBalancer]
[[http.services.service1.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9010"
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"
Weight = 1
[[tls]]
entryPoints = ["https"]
[tls.certificate]
certFile = "fixtures/https/snitest.com.cert"
keyFile = "fixtures/https/snitest.com.key"
[[tls]]
entryPoints = ["https"]
[tls.certificate]
certFile = "fixtures/https/snitest.org.cert"
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]
[Routers.router1]
Service = "service1"
Rule = "Host(`snitest.com`)"
[Routers.router2]
Service = "service2"
Rule = "Host(`snitest.org`)"
[http.routers]
[http.routers.router1]
service = "service1"
rule = "Host(`snitest.com`)"
[http.routers.router1.tls]
[Services]
[Services.service1]
[Services.service1.LoadBalancer]
[http.routers.router2]
service = "service2"
rule = "Host(`snitest.org`)"
[http.routers.router2.tls]
[[Services.service1.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9010"
Weight = 1
[Services.service2]
[Services.service2.LoadBalancer]
[http.services]
[http.services.service1]
[http.services.service1.LoadBalancer]
[[http.services.service1.LoadBalancer.Servers]]
url = "http://127.0.0.1:9010"
weight = 1
[[Services.service2.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9020"
Weight = 1
[http.services.service2]
[http.services.service2.LoadBalancer]
[[http.services.service2.LoadBalancer.Servers]]
url = "http://127.0.0.1:9020"
weight = 1
[[tls]]
entryPoints = ["https"]
# bad certificates to validate the loop on the certificate appending
[tls.certificate]
# bad content
@ -36,7 +37,6 @@ w/X5M802XqzLjeec5zHoZDfknnAkgR9MsxZYmZPFaDyL6GOKUB8=
-----END RSA PRIVATE KEY-----"""
[[tls]]
entryPoints = ["https"]
[tls.certificate]
certFile = """-----BEGIN CERTIFICATE-----
MIIC/zCCAeegAwIBAgIJALAYHG/vGqWEMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV

View file

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

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