From f2c907585819031e8dad6cc095dd8235739bc9f0 Mon Sep 17 00:00:00 2001 From: "Arthur K." Date: Mon, 12 May 2025 14:25:51 +0300 Subject: [PATCH] custom config and stuff --- .env | 2 + .gitignore | 6 +- Dockerfile | 4 +- cmd/traefik/traefik.go | 6 ++ compose.yml | 20 ++++++ .../reference/static-configuration/cli-ref.md | 3 + .../reference/static-configuration/env-ref.md | 3 + .../reference/static-configuration/file.toml | 1 + .../reference/static-configuration/file.yaml | 3 + pkg/config/static/static_config.go | 1 + pkg/updater/provider.go | 49 +++++++++++++++ traefik.yml | 63 +++++++++++++++++++ 12 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 .env create mode 100644 compose.yml create mode 100644 pkg/updater/provider.go create mode 100644 traefik.yml diff --git a/.env b/.env new file mode 100644 index 000000000..479e48100 --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +CF_API_EMAIL=wzrayyy@gmail.com +CF_DNS_API_TOKEN=mLo8IB_Q5Bg9gUu9cdXwASS3hSl6NQ1lP9OJnTsw diff --git a/.gitignore b/.gitignore index 1754b1c70..b1ce4c383 100644 --- a/.gitignore +++ b/.gitignore @@ -8,9 +8,9 @@ /site/ /docs/site/ /autogen/ -/traefik -/traefik.toml -/traefik.yml +# /traefik +# /traefik.toml +# /traefik.yml *.log *.exe cover.out diff --git a/Dockerfile b/Dockerfile index fcf9c49b9..ec1012635 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,8 +3,8 @@ FROM alpine:3.21 RUN apk add --no-cache --no-progress ca-certificates tzdata -ARG TARGETPLATFORM -COPY ./dist/$TARGETPLATFORM/traefik / +COPY ./dist/linux/amd64/traefik / +COPY ./traefik.yml /etc/traefik/traefik.yml EXPOSE 80 VOLUME ["/tmp"] diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 61f8e8217..1aeccf08e 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -49,6 +49,7 @@ import ( "github.com/traefik/traefik/v3/pkg/tracing" "github.com/traefik/traefik/v3/pkg/types" "github.com/traefik/traefik/v3/pkg/version" + "github.com/traefik/traefik/v3/pkg/updater" ) func main() { @@ -197,6 +198,8 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err tsProviders := initTailscaleProviders(staticConfiguration, providerAggregator) + updaterProvider := updater.New(staticConfiguration); + // Observability metricRegistries := registerMetricClients(staticConfiguration.Metrics) @@ -383,6 +386,9 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err } }) + // Updater + watcher.AddListener(updaterProvider.HandleConfigUpdate) + return server.NewServer(routinesPool, serverEntryPointsTCP, serverEntryPointsUDP, watcher, observabilityMgr), nil } diff --git a/compose.yml b/compose.yml new file mode 100644 index 000000000..87862e486 --- /dev/null +++ b/compose.yml @@ -0,0 +1,20 @@ +services: + traefik: + build: . + network_mode: host + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - certs:/etc/certs/ + - /tmp:/tmp + environment: + - CF_API_EMAIL=${CF_API_EMAIL} + - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN} + labels: + traefik.host: _ + traefik.http.services.dashboard.loadbalancer.server.port: 0 + traefik.http.routers.api.rule: Host(`traefik.wzray.com`) + traefik.http.routers.api.service: api@internal + restart: unless-stopped + +volumes: + certs: diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index b35cbc982..2eaa9861b 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -369,6 +369,9 @@ Periodically check if a new version has been released. (Default: ```true```) `--global.sendanonymoususage`: Periodically send anonymous usage statistics. If the option is not specified, it will be disabled by default. (Default: ```false```) +`--global.updatercallbacks`: +Callback urls for updater script (example: https://localhost:8080/callback) + `--hostresolver`: Enable CNAME Flattening. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 8f6e25c05..474fdc9ef 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -369,6 +369,9 @@ Periodically check if a new version has been released. (Default: ```true```) `TRAEFIK_GLOBAL_SENDANONYMOUSUSAGE`: Periodically send anonymous usage statistics. If the option is not specified, it will be disabled by default. (Default: ```false```) +`TRAEFIK_GLOBAL_UPDATERCALLBACKS`: +Callback urls for updater script (example: https://localhost:8080/callback) + `TRAEFIK_HOSTRESOLVER`: Enable CNAME Flattening. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index e548ee76d..8e96fd52e 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -3,6 +3,7 @@ [global] checkNewVersion = true sendAnonymousUsage = true + updaterCallbacks = ["foobar", "foobar"] [serversTransport] insecureSkipVerify = true diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 760802591..3c79d9089 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -3,6 +3,9 @@ global: checkNewVersion: true sendAnonymousUsage: true + updaterCallbacks: + - foobar + - foobar serversTransport: insecureSkipVerify: true rootCAs: diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index af60efbb8..73f740472 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -108,6 +108,7 @@ type CertificateResolver struct { type Global struct { CheckNewVersion bool `description:"Periodically check if a new version has been released." json:"checkNewVersion,omitempty" toml:"checkNewVersion,omitempty" yaml:"checkNewVersion,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` SendAnonymousUsage bool `description:"Periodically send anonymous usage statistics. If the option is not specified, it will be disabled by default." json:"sendAnonymousUsage,omitempty" toml:"sendAnonymousUsage,omitempty" yaml:"sendAnonymousUsage,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` + UpdaterCallbacks []string `description:"Callback urls for updater script (example: https://localhost:8080/callback)" json:"updaterCallbacks,omitempty" toml:"updaterCallbacks,omitempty" yaml:"updaterCallbacks,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` } // ServersTransport options to configure communication between Traefik and the servers. diff --git a/pkg/updater/provider.go b/pkg/updater/provider.go new file mode 100644 index 000000000..26d1fc469 --- /dev/null +++ b/pkg/updater/provider.go @@ -0,0 +1,49 @@ +package updater + +import ( + "bytes" + "encoding/json" + "net/http" + + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/safe" +) + +type Updater struct { + callbackUrls []string +} + +func New(config *static.Configuration) *Updater { + updater := &Updater{ + callbackUrls: config.Global.UpdaterCallbacks, + } + + return updater +} + +func (u *Updater) HandleConfigUpdate(cfg dynamic.Configuration) { + body, err := json.Marshal(cfg) + + if err != nil { + // should never happen? + log.Error().Err(err).Msg("Error while marshalling dynamic configuration data to json") + return + } + + requestBody := bytes.NewBuffer(body) + + for _, url := range u.callbackUrls { + safe.Go(func() { + resp, err := http.Post(url, "application/json", requestBody) + + if err != nil { + log.Error().Err(err).Str("url", url).Msg("Error while sending configuration data to callback") + } else { + log.Debug().Str("url", url).Msg("Configuration data sent") + resp.Body.Close() + } + }) + } +} diff --git a/traefik.yml b/traefik.yml new file mode 100644 index 000000000..7cd3d857b --- /dev/null +++ b/traefik.yml @@ -0,0 +1,63 @@ +# log: +# level: DEBUG + +api: + dashboard: true + +global: + updaterCallbacks: + - 'http://10.161.8.2:8000/callback' + +providers: + docker: + constraints: '!Label(`traefik.host`, ``)' + defaultRule: Host(`{{ index .Labels "traefik.host" }}.wzray.com`) + exposedByDefault: true + allowEmptyServices: true + +certificatesResolvers: + cloudflare: + acme: + email: security@wzray.com + storage: /etc/certs/acme.json + caServer: https://acme-v02.api.letsencrypt.org/directory + dnsChallenge: + provider: cloudflare + +entryPoints: + https: + address: ':443' + asDefault: true + http: + middlewares: + - pretty-errors + tls: + certResolver: cloudflare + domains: + - main: wzray.com + sans: ['*.wzray.com'] + + ehttps: + address: ':8443' + proxyProtocol: + trustedIPs: + - 0.0.0.0/0 + http: + middlewares: + - pretty-errors + tls: + certResolver: cloudflare + domains: + - main: wzray.com + sans: ['*.wzray.com'] + + http: + address: ':80' + http: + redirections: + entryPoint: + to: https + scheme: https + +# yaml-language-server: $schema=https://json.schemastore.org/traefik-v3.json +# defualt schema doesn't permit asDefault property on entrypoints