Experimental: Update traefik Host() rules for v3

This commit is contained in:
Tom Wiesing 2023-04-12 19:21:11 +02:00
parent 34db2e1923
commit 285aaff77d
No known key found for this signature in database
10 changed files with 60 additions and 13 deletions

View file

@ -5,7 +5,7 @@ import (
"net/url"
"strings"
"github.com/tkw1536/pkglib/collection"
"golang.org/x/net/idna"
)
type HTTPConfig struct {
@ -80,10 +80,7 @@ func (hcfg HTTPConfig) Domains(sub string) []string {
// HostRule returns a HostRule for the provided subdomain.
// See Domains() for usage of sub.
func (hcfg HTTPConfig) HostRule(sub string) string {
quoted := collection.MapSlice(hcfg.Domains(sub), func(name string) string {
return "`" + name + "`"
})
return fmt.Sprintf("Host(%s)", strings.Join(quoted, ","))
return MakeHostRule(hcfg.Domains(sub)...)
}
// HTTPSEnabledEnv returns "true" if https is enabled, and "false" otherwise.
@ -141,3 +138,36 @@ func TrimSuffixFold(s string, suffix string) string {
func (cfg HTTPConfig) DefaultHostRule() string {
return cfg.HostRule("")
}
// MakeHostRule builds a new Host() rule string to be used by traefik.
func MakeHostRule(hosts ...string) string {
var builder strings.Builder
first := true
for _, host := range hosts {
// HACK HACK HACK: Very minimal domain validation to prevent validation.
// Just skip everything that isn't a domain.
if strings.Contains(host, "`") {
continue
}
if first {
builder.WriteString("||Host(`")
} else {
builder.WriteString("Host(`")
}
// domain should be punycode!
domain, err := idna.ToASCII(host)
if err != nil {
domain = host
}
builder.WriteString(domain)
builder.WriteString("`)")
first = false
}
return builder.String()
}

View file

@ -2,7 +2,8 @@ DATA_PATH=${DATA_PATH}
RUNTIME_DIR=${RUNTIME_DIR}
SLUG=${SLUG}
VIRTUAL_HOST=${VIRTUAL_HOST}
HOSTNAME=${HOSTNAME}
HOST_RULE=${HOST_RULE}
DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
HTTPS_ENABLED=${HTTPS_ENABLED}

View file

@ -4,14 +4,14 @@ services:
barrel:
build: .
restart: always
hostname: ${VIRTUAL_HOST}.wisski
hostname: ${HOSTNAME}
# label it with the current slug
labels:
- "traefik.enable=True"
- "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
- "traefik.http.routers.wisski_${SLUG}.rule=Host(`${VIRTUAL_HOST}`)"
- "traefik.http.routers.wisski_${SLUG}.rule=${HOST_RULE}"
- "traefik.http.routers.wisski_${SLUG}.tls=${HTTPS_ENABLED}"
- "traefik.http.routers.wisski_${SLUG}.tls.certresolver=distillery"
- "traefik.http.services.wisski_${SLUG}.loadbalancer.server.port=8080"

View file

@ -25,7 +25,8 @@ func (barrel *Barrel) Stack() component.StackWithResources {
"DOCKER_NETWORK_NAME": barrel.Malt.Config.Docker.Network(),
"SLUG": barrel.Slug,
"VIRTUAL_HOST": barrel.Domain(),
"HOST_RULE": barrel.HostRule(),
"HOSTNAME": barrel.Hostname(),
"HTTPS_ENABLED": barrel.Malt.Config.HTTP.HTTPSEnabledEnv(),
"DATA_PATH": filepath.Join(barrel.FilesystemBase, "data"),

View file

@ -1,5 +1,5 @@
SLUG=${SLUG}
VIRTUAL_HOST=${VIRTUAL_HOST}
HOST_RULE=${HOST_RULE}
DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
HTTPS_ENABLED=${HTTPS_ENABLED}

View file

@ -32,7 +32,8 @@ func (reserve *Reserve) Stack() component.StackWithResources {
"DOCKER_NETWORK_NAME": reserve.Malt.Config.Docker.Network(),
"SLUG": reserve.Slug,
"VIRTUAL_HOST": reserve.Domain(),
"HOST_RULE": reserve.HostRule(),
"HOSTNAME": reserve.Hostname(),
"HTTPS_ENABLED": reserve.Malt.Config.HTTP.HTTPSEnabledEnv(),
},
}

View file

@ -11,7 +11,7 @@ services:
- "traefik.enable=True"
- "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
- "traefik.http.routers.reserve_${SLUG}.rule=Host(`${VIRTUAL_HOST}`)"
- "traefik.http.routers.reserve_${SLUG}.rule=${HOST_RULE}"
- "traefik.http.routers.reserve_${SLUG}.tls=${HTTPS_ENABLED}"
- "traefik.http.routers.reserve_${SLUG}.tls.certresolver=distillery"
- "traefik.http.services.reserve_${SLUG}.loadbalancer.server.port=8043"

View file

@ -2,6 +2,8 @@ package liquid
import (
"net/url"
"github.com/FAU-CDI/wisski-distillery/internal/config"
)
// Domain returns the full domain name of this WissKI
@ -9,6 +11,15 @@ func (liquid *Liquid) Domain() string {
return liquid.Config.HTTP.HostFromSlug(liquid.Slug)
}
func (liquid *Liquid) Hostname() string {
return liquid.Domain() + ".wisski"
}
// HostRule returns a host rule for this wisski
func (liquid *Liquid) HostRule() string {
return config.MakeHostRule(liquid.Domain())
}
// URL returns the public URL of this instance
func (liquid *Liquid) URL() *url.URL {
// setup domain and path