Kubernetes (Helm)

The ingress controller sees every whistleblower's IP address. The chart (charts/openwhistle/) sets nginx.ingress.kubernetes.io/enable-access-log: "false" on its Ingress. It also sets the bundled nginx's rate limit: limit-rps: "10", limit-burst-multiplier: "3", a burst of 30. It raises proxy-body-size to 55m, like the bundled nginx; ingress-nginx otherwise refuses any upload over 1 MB.

The chart bundles no PostgreSQL and no Redis: set secrets.databaseUrl and secrets.redisUrl to your own. A helm upgrade that changes a value restarts the pods; with autoscaling.enabled the HPA alone sets the replica count.

  • Your own ingress.annotations are merged with it; do not set it to null.
  • Required: error-log-level: crit in the controller ConfigMap. Below crit, ingress-nginx logs every rate-limited request and upstream error with the client's IP address.
  • A rate-limited request gets 503, not 429, unless the controller ConfigMap sets limit-req-status-code: "429" (controller-wide).
  • The limit is per peer address. Behind a load balancer the controller must see the real client, or every reporter shares one budget:
    • L4 (TCP, SNAT): proxy protocol (use-proxy-protocol: "true" in the controller ConfigMap, and on the load balancer), or externalTrafficPolicy: Local on the controller Service.
    • L7 (HTTP): use-forwarded-headers: "true" together with proxy-real-ip-cidr set to the load balancer's range. Without that range, any client sends its own X-Forwarded-For and escapes the limit.
  • ingress-nginx always forwards X-Forwarded-For and X-Real-IP. OpenWhistle drops them, and the peer address, in its first middleware. The admin dashboard still warns that the proxy knows the addresses.
  • Other controllers (Traefik: access log off unless enabled): check their logging.

With several replicas, only the pod that wins the race to create the setup token logs it: kubectl logs -l app.kubernetes.io/name=openwhistle | grep "Setup token" finds it. Setting secrets.setupToken (chart) / SETUP_TOKEN avoids the hunt: every replica uses that value.

A setting from the configuration table without a values.yaml key goes into extraEnv as NAME: value (for example SECURE_COOKIES: "false"). Secrets belong in secrets.

Edit this page on GitHub