Files
ingress/LLM.md
zooqueen 1d875dd71c rebrand: strip "traefik" branding from the ingress controller
Removes all "traefik" branding/paths/env/comments from the shipping
surface while keeping load-bearing config schema and external deps intact.

Paths / binary:
- cmd/traefik/ -> cmd/ingress/ (traefik.go->ingress.go, etc.); merged out
  the empty cmd/ingress/generate.go stub. Build refs updated in Dockerfile,
  Makefile, .goreleaser.yml.tmpl, script/crossbinary-default.sh, README.
- contrib/systemd/traefik.service -> ingress.service (Hanzo Ingress unit,
  /etc/ingress paths, hanzo-ingress binary).
- contrib/grafana/traefik*.json -> ingress*.json; metric queries
  traefik_* -> ingress_* (now match the engine's ingress_ prefix) + titles.
- script/gcg/traefik-*.toml -> ingress-*.toml; Owner/Repo -> hanzoai/ingress.

Code/config branding (comments + non-schema strings):
- doc.go, mount.go, client/router.go, zap_backend.go, forward_backend.go,
  register.go: "Traefik" -> "the ingress"/"Hanzo Ingress"; corrected the
  annotation example to ingress.kubernetes.io/.
- ingress.sample.{toml,yml}: header + log + entryPoint example.
- pkg/config/dynamic/fixtures/sample.toml comment.
- pkg/redactor/testdata example+expected: /etc/traefik/traefik.toml ->
  /etc/ingress/ingress.toml, TraefikLogsFile -> IngressLogsFile (both files
  kept identical so the redactor golden test stays green).
- .golangci.yml importas aliases traefik* -> ingress* and the stale
  crd/traefikio path -> crd/hanzoai; unused-var exclude ingressVersion.
- .dockerignore / .gitignore: drop stale /traefik artifacts.
- script/code-gen.sh: PROJECT_MODULE -> github.com/hanzoai/ingress,
  v1alpha1 path -> crd/hanzoai, CRD output -> hanzo.ai_*.yaml /
  01-ingress-crd.yml.
- script/deploy.sh: drop the upstream traefik-library-image push.
- Removed dead, disabled upstream docs-publish workflow
  (.github/workflows/documentation.yaml, pushed to traefik/doc).
- LLM.md: rewrote rebrand notes; documented load-bearing "traefik" that
  stays (external imports, hash-bound realm, upstream issue URL, license
  attribution) and vendored upstream docs/webui/changelog as out of scope.

Load-bearing "traefik" intentionally KEPT (not branding):
- external Go modules github.com/traefik/{oxy,yaegi,grpc-web};
- digest_auth_test.go htdigest realm "traefik" (invalidates the hashes);
- consul_test.go upstream issue URL #8092 (provenance citation);
- LICENSE.md + boilerplate.go.tmpl Containous/Traefik Labs copyright
  (MIT attribution; Hanzo AI appended);
- integration/ test fixtures (traefik/whoami images, rawdata-*.json
  golden entrypoint names, nomad traefik.* tags) — test-only, semantics-
  sensitive; out of scope for this pass.

Verify: `go build $(go list ./... | grep -v /webui)` passes; redactor /
config/dynamic / nomad / server/service tests pass. The webui go:embed
failure and the kubernetes/crd test (ingress.k8s.io group mismatch) are
pre-existing on main, not caused by this rebrand.
2026-06-21 15:55:45 -07:00

4.9 KiB

Hanzo Ingress

Overview

Go module: github.com/hanzoai/ingress/v3

Tech Stack

  • Language: Go

Build & Run

go build ./...
go test ./...

Structure

ingress/
  CHANGELOG.md
  CODE_OF_CONDUCT.md
  CONTRIBUTING.md
  Dockerfile
  Dockerfile.bin
  LICENSE.md
  LLM.md
  Makefile
  README.md
  SECURITY.md
  cmd/
  contrib/
  docs/
  generate.go
  go.mod

Key Files

  • README.md -- Project documentation
  • go.mod -- Go module definition
  • Makefile -- Build automation
  • Dockerfile -- Container build

Rebrand Notes

The engine is fully de-traefik'd: the parser dependency was forked to github.com/hanzoai/ingress-parser (DefaultRootName = "ingress", DefaultNamePrefix = "INGRESS_"), the config base paths are /etc/ingress/ingress, the Prometheus metric prefix is ingress_, and the CRD apiGroup is hanzo.ai. The standalone binary is built from cmd/ingress (was cmd/traefik) and ships as hanzo-ingress.

Load-bearing "traefik" that intentionally STAYS

These are the only remaining traefik strings outside the vendored upstream docs/changelog. They are NOT branding and must not be renamed:

  • External Go imports — github.com/traefik/yaegi, github.com/traefik/grpc-web, github.com/traefik/oxy are real third-party modules (in go.mod/go.sum and the import lines that use them). Renaming breaks the build.
  • Hash-bound test data — pkg/middlewares/auth/digest_auth_test.go htdigest hashes are md5(user:realm:password) with realm "traefik". Changing the realm invalidates the precomputed hashes (~10 refs).
  • Upstream issue citation — integration/consul_test.go links https://github.com/traefik/traefik/issues/8092 as the provenance of a regression test. The issue only exists at that URL.

Vendored upstream content (out of scope by nature)

docs/content/**, CHANGELOG.md, webui/** (the dashboard SPA), and the traefik.io_*.yaml CRD reference dumps under docs/ are imported upstream Traefik material kept for reference. They carry the bulk of the remaining traefik occurrences and do not ship in the runtime binary or image. Rebrand them only as part of a dedicated docs pass.

Wire protocol changes (intentional)

  • X-Traefik-Fast-Proxy header renamed to X-Ingress-Fast-Proxy
  • X-Traefik-Router header renamed to X-Ingress-Router
  • Prometheus/InfluxDB metric prefix: traefik.* renamed to ingress.* (the bundled Grafana dashboards in contrib/grafana/ingress*.json query the ingress_* metric names accordingly)

Pre-existing build/test issues (not caused by rebrand)

  • webui/embed.go //go:embed static fails until the dashboard assets are built (make generate-webui); go build ./... therefore needs the webui built first, or build the subset go build $(go list ./... | grep -v /webui).
  • pkg/muxer/http/Test_addRoute/Host_IPv6: Go 1.26 broke IPv6 URL parsing
  • pkg/middlewares/ratelimiter: Timing-sensitive tests, flaky

Header Passthrough Behavior (2026-04-13)

The ingress controller correctly passes through ALL backend response headers. Both the httputil.ReverseProxy path and the fast proxy path copy response headers verbatim via VisitAll / Header().Add().

The security-headers Middleware CRD (k8s/hanzo/middlewares.yaml) uses unrolled/secure to ADD secure headers (HSTS, X-Frame-Options, etc.) via ModifyResponseHeaders. It uses res.Header.Set(), which overwrites same-named backend headers. This is intentional -- ingress-level security headers override backend headers.

The contenttype.DisableAutoDetection wrapper on the entrypoint sets Content-Type to nil in the header map before handler execution. This prevents Go's default content-type sniffing but does not strip any other headers.

No code in the ingress adds Content-Disposition. If you see Content-Disposition: inline; filename="index.html" in responses, it comes from the backend (Go's http.ServeContent or http.ServeFile).

Annotation prefix

The K8s Ingress provider uses annotation prefix ingress.kubernetes.io/, NOT traefik.ingress.kubernetes.io/. Annotations with the old Traefik prefix are silently ignored.

ZAP-HTTP Backend Transport

pkg/server/service/zap_backend.go wraps every backend RoundTripper returned by TransportManager.createRoundTripper. When the request's upstream host:port (i.e. req.URL.Host at transport time) matches the allowlist from env INGRESS_ZAP_BACKENDS (comma-separated), the request is dialed via github.com/zap-proto/http instead of net/http. All other backends fall through unchanged. Empty / unset env keeps the wrapped transport untouched (no allocation, no overhead).

zaphttp.NewTransport pins to one peer (it ignores req.URL.Host internally), so we keep one *zaphttp.Transport per backend address in a sync.Map.

External (client-facing) TLS termination is untouched. CRD schema is untouched. Reference doc: docs/content/reference/dynamic-configuration/zap-backend.md.