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.
