user-guide

TAK-OS Ingress user guide

Use this guide to expose an application through a controller that your cluster administrator has already installed. You need kubectl access to your application namespace and permission to manage Services, Ingresses, and Secrets. Ask your administrator for the ingress class and the address clients should use.

Publish an application

Your application must already run behind a Service. The following example creates a Service for Pods labeled app: my-app in an existing apps namespace. The application listens on port 8080; the Ingress references the Service port 80. Save this as my-app.yaml and adjust the selector and ports for your workload.

apiVersion: v1
kind: Service
metadata:
  name: my-app
  namespace: apps
spec:
  selector:
    app: my-app
  ports:
    - name: http
      port: 80
      targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
  namespace: apps
spec:
  ingressClassName: tak-os
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-app
                port:
                  number: 80
kubectl apply -f my-app.yaml
kubectl -n apps get ingress my-app
kubectl -n apps get service my-app
kubectl -n apps get endpointslices -l kubernetes.io/service-name=my-app

Point the DNS record for app.example.com at the address supplied by your administrator. Before DNS is ready, test against that address while preserving the hostname:

curl --resolve app.example.com:80:192.0.2.10 http://app.example.com/

Replace 192.0.2.10 with the ingress address. A response from your application confirms that the host, route, and backend are reachable. An empty Ingress ADDRESS column does not establish a failure: this controller does not populate Ingress load-balancer status.

Match hosts and paths

Set spec.ingressClassName to the class configured by your administrator. The legacy kubernetes.io/ingress.class annotation is used only when that field is absent. Ingresses with neither are ignored unless the administrator enables --process-without-class.

Use Exact for a single path or Prefix for a path subtree. For example, Prefix /api matches /api and /api/users, but not /apix. The request path is forwarded to the application; these annotations do not provide URL rewriting. Use explicit rules[].http.paths: spec.defaultBackend and resource backends are not implemented. Service backends must be in the Ingress namespace. Both numeric Service ports and named Service ports are supported.

Changes to routes, annotations, referenced Secrets, and Service ports are reconciled live. Avoid giving multiple Ingresses or HTTPRoutes ownership of the same hostname and path. See Gateway route overlap when migrating between APIs.

Enable HTTPS

Use an existing certificate

Create a TLS Secret in the Ingress namespace using your certificate chain and matching private key:

kubectl -n apps create secret tls app-tls \
  --cert=fullchain.pem --key=privkey.pem

Add this TLS block alongside rules in the example Ingress:

spec:
  ingressClassName: tak-os
  tls:
    - hosts:
        - app.example.com
      secretName: app-tls
  # Retain the rules from my-app.yaml.

Reapply the complete manifest. The TLS host must match the rule host. HTTP requests to that TLS-enabled host redirect to HTTPS with status 308 by default. Set ingress.tak-os.org/ssl-redirect: "false" to serve HTTP without that redirect. Certificate Secret updates are loaded without a controller restart.

curl --resolve app.example.com:443:192.0.2.10 https://app.example.com/

Use --cacert your-ca.pem for a certificate issued by your own CA. A missing or invalid Ingress TLS Secret causes the proxy to serve its self-signed fallback certificate, so clients will report certificate validation failures.

Request a certificate through cert-manager

Your administrator must install cert-manager and configure an Issuer or ClusterIssuer. Add the issuer annotation and omit secretName from the TLS block to let TAK-OS create a Certificate:

metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts:
        - app.example.com
  # Retain ingressClassName and rules from my-app.yaml.

For Ingress my-app, the first TLS block creates Certificate and Secret my-app-tls-0; subsequent blocks use my-app-tls-1, and so on. An explicitly named Secret is treated as an existing certificate; TAK-OS does not create its Certificate through this path. With no issuer annotation, the default is ClusterIssuer letsencrypt-staging, whose ACME certificates are not publicly trusted.

kubectl -n apps get certificates
kubectl -n apps describe certificate my-app-tls-0
kubectl -n apps wait --for=condition=Ready certificate/my-app-tls-0 --timeout=180s

Configure backend connections

Annotations go on Ingress metadata.annotations and affect its routes. This example enables HTTPS to the Service and shortens the backend timeouts:

metadata:
  annotations:
    ingress.tak-os.org/backend-protocol: "https"
    ingress.tak-os.org/proxy-connect-timeout: "5"
    ingress.tak-os.org/proxy-read-timeout: "60"
    ingress.tak-os.org/proxy-send-timeout: "60"

Keep the backend Service port set to the port that actually serves HTTPS. Backend certificate verification is enabled by default. The proxy-ssl-verify: "false" annotation disables it for that route.

WebSocket upgrades work without an additional enable annotation. Backend read and send timeouts also apply to WebSocket tunnels. Their defaults are 300 seconds of inactivity; continuous traffic keeps a stream alive. Set an individual timeout to "0" to disable it. For applications that close persistent backend connections unreliably, set ingress.tak-os.org/backend-keepalive: "false" to open a fresh connection for each ordinary request.

Protect an application

Choose one authentication mechanism per route. When several are configured, built-in OAuth takes precedence, followed by external authentication, then Basic authentication. They are not applied as successive authentication steps.

Basic authentication

Create an htpasswd file with a password prompt, then store it under Secret key auth. These commands require the htpasswd utility:

htpasswd -cB auth alice
kubectl -n apps create secret generic app-basic-auth --from-file=auth
rm auth

Add the annotations to your HTTPS Ingress:

metadata:
  annotations:
    ingress.tak-os.org/auth-type: basic
    ingress.tak-os.org/auth-secret: app-basic-auth
    ingress.tak-os.org/auth-realm: "Application access"

The Secret must be in the Ingress namespace. A missing or invalid referenced Secret returns 501 Authentication required but not configured. On successful authentication, the proxy supplies the authenticated identity to the backend and removes the Basic Authorization header. Test with curl -u alice over HTTPS to prompt for the password.

External authentication

To delegate authentication to a service such as oauth2-proxy, configure:

metadata:
  annotations:
    ingress.tak-os.org/auth-url: "https://auth.example.com/oauth2/auth"
    ingress.tak-os.org/auth-signin: "https://auth.example.com/oauth2/start"

The proxy calls auth-url for each request. A 2xx response allows access and forwards returned X-Auth-Request-* and Authorization headers to the application. A 401 or 403 redirects to auth-signin with status 302 when configured; otherwise the denial status is returned. Provider connection failures return 502.

Built-in OAuth2 and OIDC

Register https://app.example.com/_tak/oauth2/callback as an allowed redirect URI at your identity provider. Create an OAuth configuration Secret in apps using the Secret reference, then add:

metadata:
  annotations:
    k8s.tak-os.com/oauth2-secret: app-oidc

Browsers without a valid session are redirected to the provider. The callback requires the state cookie from the browser that started login. The controller also supports bearer-token authentication; configure the expected audience and an introspection endpoint when using opaque tokens. The local logout endpoint is /_tak/oauth2/logout.

TLS must reach this controller for it to generate HTTPS callback URLs and Secure cookies. It determines the scheme from its own connection and ignores supplied forwarding headers. Sharing a signing key alone does not share browser cookies across hosts; cross-host SSO also requires compatible cookie names, domain, and provider settings.

Configure CORS and rate limits

For a browser frontend on a different origin, set the allowed origin explicitly when using credentials:

metadata:
  annotations:
    ingress.tak-os.org/enable-cors: "true"
    ingress.tak-os.org/cors-allow-origin: "https://frontend.example.com"
    ingress.tak-os.org/cors-allow-credentials: "true"
    ingress.tak-os.org/limit-rps: "10"
    ingress.tak-os.org/limit-burst-multiplier: "5"

The limiter uses a token bucket per route and client IP, with a burst of 50 in this example. It returns 429 when no tokens remain. State is local to each controller process, so the limit is not a cluster-wide quota. It uses the TCP peer address; upstream NAT can combine many users into one client key. CORS preflight requests are answered before authentication and rate limiting. See the annotation reference for all supported settings.

Troubleshoot application access

Symptom Check
Connection refused or timed out Confirm DNS, ingress address, Service exposure, and firewall rules with the administrator
404 from the controller Check host, path, ingress class, and whether the route is supported
502 Check Service ports, ready EndpointSlices, network access from ingress Pods, backend protocol, and authentication provider reachability
Certificate warning Check TLS host, Secret namespace and contents, certificate expiry, and cert-manager issuance status
Redirect loop or incorrect callback scheme Confirm TLS terminates at this controller and the provider redirect URI matches the application URL
401 or 403 Check credentials, provider policy, and external authentication response
501 authentication configuration error Check the referenced Secret name, required keys, and the 32-byte OAuth signing key
429 Honor Retry-After; check route limits, repeated failed authentication, and shared peer IPs
413 on upload Ask the administrator about the global request body limit, which defaults to 50 MiB
WebSocket disconnect after inactivity Check the read and send timeout annotations and application heartbeat settings

Include the namespace, Ingress name, hostname, timestamp, and HTTP status when asking an administrator for help. Do not include passwords, session cookies, or Secret contents.

Remove application exposure

kubectl -n apps delete ingress my-app

Deleting the Ingress removes its routes. Delete application-owned authentication and TLS Secrets only after checking whether other resources share them. A Certificate generated by TAK-OS has an Ingress owner reference and is subject to Kubernetes garbage collection; retention of its Secret depends on cert-manager configuration.