From 12a629c652474b88ba05a67a2cdde6bd9abdc2d0 Mon Sep 17 00:00:00 2001 From: Lukasz Raczylo Date: Fri, 10 Jul 2026 09:35:24 +0100 Subject: [PATCH] fixup! feat: comprehensive audit + Tier 3 wiring (security/correctness/features) --- examples/values-traefik.yaml | 129 ++++++++++++++++++ .../templates/ingressroute-traefik.yaml | 129 ++++++++++++++++++ helm/gohoarder/values.yaml | 10 ++ 3 files changed, 268 insertions(+) create mode 100644 examples/values-traefik.yaml create mode 100644 helm/gohoarder/templates/ingressroute-traefik.yaml diff --git a/examples/values-traefik.yaml b/examples/values-traefik.yaml new file mode 100644 index 0000000..d9d96ec --- /dev/null +++ b/examples/values-traefik.yaml @@ -0,0 +1,129 @@ +# Example GoHoarder values for Traefik IngressRoute +# +# This configuration uses Traefik IngressRoute instead of standard Kubernetes Ingress +# to better handle scoped npm packages with encoded slashes. +# +# IMPORTANT: You must also configure your Traefik deployment to allow encoded slashes. +# See docs/TRAEFIK_ENCODED_SLASHES.md for Traefik configuration steps. + +nameOverride: "gohoarder" +fullnameOverride: "" + +global: + domain: "i.raczylo.com" + imagePullSecrets: [] + +replicaCount: + server: 1 + frontend: 1 + scanner: 1 + +image: + server: + repository: ghcr.io/lukaszraczylo/gohoarder-server + pullPolicy: IfNotPresent + tag: "latest" + frontend: + repository: ghcr.io/lukaszraczylo/gohoarder-frontend + pullPolicy: IfNotPresent + tag: "latest" + scanner: + repository: ghcr.io/lukaszraczylo/gohoarder-scanner + pullPolicy: IfNotPresent + tag: "latest" + +# Ingress configuration for Traefik +ingress: + enabled: true + className: "traefik" # This triggers IngressRoute creation instead of Ingress + + # Your GoHoarder hostname + host: "hoarder.i.raczylo.com" + + # TLS configuration + tls: + enabled: true + secretName: "cert-i.raczylo.com" + + # Traefik-specific settings + # These are used by the IngressRoute template + traefik: + # Reference middlewares from the traefik namespace + # These will be applied to all routes + middlewares: + - default-chain # Your existing middleware chain from traefik namespace + + # ServersTransport configuration (optional) + transport: + serverName: "" + +# Storage configuration +storage: + backend: "filesystem" + filesystem: + storageClass: "longhorn" + size: "100Gi" + accessMode: "ReadWriteOnce" + +# Metadata storage +metadata: + backend: "sqlite" + sqlite: + persistence: + enabled: false # Using emptyDir for metadata + walMode: false + +# Cache configuration +cache: + defaultTTL: "168h" # 7 days + maxSizeBytes: 536870912000 # 500GB + +# Package handlers +handlers: + npm: + enabled: true + upstreamRegistry: "https://registry.npmjs.org" + pypi: + enabled: true + upstreamUrl: "https://pypi.org" + go: + enabled: true + upstreamProxy: "https://proxy.golang.org" + +# Authentication +auth: + enabled: true + adminApiKey: "" # Will be auto-generated if empty + +# Logging +logging: + level: "info" + format: "json" + +# Resource limits +server: + resources: + limits: + cpu: 2000m + memory: 2Gi + requests: + cpu: 500m + memory: 512Mi + +frontend: + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 100m + memory: 128Mi + +scanner: + resources: + limits: + cpu: 2000m + memory: 4Gi + requests: + cpu: 500m + memory: 1Gi diff --git a/helm/gohoarder/templates/ingressroute-traefik.yaml b/helm/gohoarder/templates/ingressroute-traefik.yaml new file mode 100644 index 0000000..586bab6 --- /dev/null +++ b/helm/gohoarder/templates/ingressroute-traefik.yaml @@ -0,0 +1,129 @@ +{{- if and .Values.ingress.enabled (eq .Values.ingress.className "traefik") -}} +--- +# Traefik IngressRoute for package registry paths +# This handles package downloads including scoped packages with encoded slashes +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: {{ include "gohoarder.fullname" . }}-packages + labels: + {{- include "gohoarder.labels" . | nindent 4 }} +spec: + entryPoints: + - websecure + routes: + # Package registry routes with high priority + # PathPrefix matching to avoid Go's encoded slash rejection in regex + - match: Host(`{{ .Values.ingress.host | default (printf "%s.%s" "gohoarder" .Values.global.domain) }}`) && PathPrefix(`/npm/`) + kind: Rule + priority: 100 + services: + - name: {{ include "gohoarder.fullname" . }}-frontend + port: {{ .Values.frontend.service.port }} + middlewares: + - name: {{ include "gohoarder.fullname" . }}-strip-encoded-slash + namespace: {{ .Release.Namespace }} + {{- if .Values.ingress.traefik }} + {{- if .Values.ingress.traefik.middlewares }} + {{- range .Values.ingress.traefik.middlewares }} + - name: {{ . }} + namespace: traefik + {{- end }} + {{- end }} + {{- end }} + + - match: Host(`{{ .Values.ingress.host | default (printf "%s.%s" "gohoarder" .Values.global.domain) }}`) && PathPrefix(`/pypi/`) + kind: Rule + priority: 100 + services: + - name: {{ include "gohoarder.fullname" . }}-frontend + port: {{ .Values.frontend.service.port }} + middlewares: + - name: {{ include "gohoarder.fullname" . }}-strip-encoded-slash + namespace: {{ .Release.Namespace }} + {{- if .Values.ingress.traefik }} + {{- if .Values.ingress.traefik.middlewares }} + {{- range .Values.ingress.traefik.middlewares }} + - name: {{ . }} + namespace: traefik + {{- end }} + {{- end }} + {{- end }} + + - match: Host(`{{ .Values.ingress.host | default (printf "%s.%s" "gohoarder" .Values.global.domain) }}`) && PathPrefix(`/go/`) + kind: Rule + priority: 100 + services: + - name: {{ include "gohoarder.fullname" . }}-frontend + port: {{ .Values.frontend.service.port }} + middlewares: + - name: {{ include "gohoarder.fullname" . }}-strip-encoded-slash + namespace: {{ .Release.Namespace }} + {{- if .Values.ingress.traefik }} + {{- if .Values.ingress.traefik.middlewares }} + {{- range .Values.ingress.traefik.middlewares }} + - name: {{ . }} + namespace: traefik + {{- end }} + {{- end }} + {{- end }} + + # All other routes (frontend, API, etc.) with lower priority + - match: Host(`{{ .Values.ingress.host | default (printf "%s.%s" "gohoarder" .Values.global.domain) }}`) + kind: Rule + priority: 50 + services: + - name: {{ include "gohoarder.fullname" . }}-frontend + port: {{ .Values.frontend.service.port }} + {{- if .Values.ingress.traefik }} + {{- if .Values.ingress.traefik.middlewares }} + middlewares: + {{- range .Values.ingress.traefik.middlewares }} + - name: {{ . }} + namespace: traefik + {{- end }} + {{- end }} + {{- end }} + + {{- if .Values.ingress.tls.enabled }} + tls: + secretName: {{ .Values.ingress.tls.secretName }} + {{- end }} + +--- +# Middleware to handle encoded slashes in package paths +# Note: This middleware attempts to work around Traefik's encoded slash limitation +# but may not fully resolve the issue due to Go stdlib constraints +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: {{ include "gohoarder.fullname" . }}-strip-encoded-slash + labels: + {{- include "gohoarder.labels" . | nindent 4 }} +spec: + # Use headers to pass original path information + # The backend can reconstruct the original URL from these headers + headers: + customRequestHeaders: + X-Original-URI: "{{ .Request.URL.Path }}" + X-Forwarded-Path: "{{ .Request.URL.Path }}" + +--- +# ServersTransport configuration for backend communication +# This ensures the backend connection doesn't have additional restrictions +apiVersion: traefik.io/v1alpha1 +kind: ServersTransport +metadata: + name: {{ include "gohoarder.fullname" . }}-transport + labels: + {{- include "gohoarder.labels" . | nindent 4 }} +spec: + insecureSkipVerify: false + {{- if .Values.ingress.traefik }} + {{- if .Values.ingress.traefik.transport }} + {{- with .Values.ingress.traefik.transport }} + serverName: {{ .serverName | default "" }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/gohoarder/values.yaml b/helm/gohoarder/values.yaml index ab73fb6..f539961 100644 --- a/helm/gohoarder/values.yaml +++ b/helm/gohoarder/values.yaml @@ -514,6 +514,16 @@ ingress: enabled: false secretName: "gohoarder-tls" + # Traefik-specific configuration (when className: "traefik") + # Used by IngressRoute template for advanced routing + traefik: + # Middleware references (from traefik namespace) + # Example: ["default-chain", "rate-limit"] + middlewares: [] + # ServersTransport configuration + transport: + serverName: "" + # Autoscaling configuration autoscaling: enabled: false