Gateway API
Inbound HTTP traffic goes through the Gateway API, not Ingress. You create an HTTPRoute in your namespace and attach it to the shared gateway.
Which gateway to attach to
There is exactly one gateway: default in the namespace nginx-gateway. Every HTTPRoute references it through parentRefs.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: myapp
annotations:
cert-manager.io/cluster-issuer: "auto"
spec:
parentRefs:
- name: default
namespace: nginx-gateway
sectionName: https-myapp-your-namespace-itsh-dev
hostnames:
- myapp.<your-namespace>.itsh.dev
rules:
- backendRefs:
- name: myapp
port: 8080Which hostnames you may use
Your namespace has its own subdomain, and any name under it is yours to use without asking:
| Plan | Hostnames you may use |
|---|---|
| Paid and pay-as-you-go | *.<your-namespace>.itsh.dev |
| Free tier | *.<your-namespace>.itsh-apps.dev |
So a namespace called tenant-7 can serve myapp.tenant-7.itsh.dev, api.tenant-7.itsh.dev and anything else at that level, immediately.
Anything else is refused when you apply the route:
Hostname is not allowed in namespace 'tenant-7'. Tenant namespaces may only use
*.tenant-7.itsh.dev (paid) or *.tenant-7.itsh-apps.dev (free) subdomains or
hostnames listed in the itsh.dev/allowed-hostnames namespace annotation.A route must also declare at least one hostname. One with none is refused too, because it would attach as a catch-all on the shared gateway.
Using your own domain
To serve a domain you own, add it in the portal first. You prove the domain is yours with a TXT record, and once it is verified it is added to the list your namespace is allowed to use. From then on you can name it in an HTTPRoute like any other hostname.
A domain registered with us needs no verification
If the domain is already registered through ITSH, adding it verifies immediately. We can see it belongs to your account, so there is no TXT record to create and nothing to wait for.
Custom domains are not available on the free tier
A free namespace can only serve names under its itsh-apps.dev subdomain. Bringing your own domain needs a paid or pay-as-you-go plan.
HTTPS listeners are created for you
You do not configure anything on the gateway. If your HTTPRoute carries the annotation cert-manager.io/cluster-issuer, the matching HTTPS listener and its certificate are created automatically.
The annotation value does not select an issuer
Only the presence of the annotation matters. Which issuer is used is fixed by the platform, so putting a different value in your HTTPRoute changes nothing.
Listener naming
The listener is named https-<hostname with dots replaced by dashes>:
| Hostname | sectionName |
|---|---|
myapp.tenant-7.itsh.dev | https-myapp-tenant-7-itsh-dev |
shop.example.com | https-shop-example-com |
*.example.com | https-wildcard-example-com |
sectionName is optional, but you should set it
The listener is created with or without sectionName. Leave it out, however, and your route also binds the port 80 listener http, which means your application is served in plaintext. Always point sectionName at the HTTPS listener.
HTTP to HTTPS redirect
The redirect is a separate route that attaches to the port 80 listener with sectionName: http:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: myapp-redirect
spec:
parentRefs:
- name: default
namespace: nginx-gateway
sectionName: http
hostnames:
- myapp.<your-namespace>.itsh.dev
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301DNS
For a hostname under your namespace subdomain there is nothing to do. The whole subdomain already points at the gateway, so myapp.<your-namespace>.itsh.dev resolves the moment your route exists.
DNS only becomes your job when you bring your own domain.
Auto-DNS keeps the records for you
If the domain's DNS is managed here, switch on Auto-DNS next to it in the portal. The records are then created from your HTTPRoutes and kept up to date as you add or remove hostnames, so the table below is only for domains you host somewhere else.
Auto-DNS can be switched on once the domain is verified.
For a domain hosted elsewhere, point it at these addresses yourself:
| Type | Value |
|---|---|
A | 91.98.6.3 |
AAAA | 2a01:4f8:1c1f:7bfa::1 |
gRPC
gRPC backends use GRPCRoute instead of HTTPRoute. Everything else is the same: the same gateway, the same hostname rules, the same listener naming.
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: myapp-grpc
annotations:
cert-manager.io/cluster-issuer: "auto"
spec:
parentRefs:
- name: default
namespace: nginx-gateway
sectionName: https-grpc-your-namespace-itsh-dev
hostnames:
- grpc.<your-namespace>.itsh.dev
rules:
- backendRefs:
- name: myapp-grpc
port: 9000Set sectionName here too. Leaving it out binds the plaintext listener, and gRPC over plaintext is rarely what you want.
gRPC cannot be combined with scale-to-zero; run those services always-on.
Client IP and forwarded headers
The gateway sets X-Forwarded-For and X-Real-IP. Your application should accept those headers only when the connection comes from the gateway, that is from a private in-cluster address, never from arbitrary senders. If it trusts them from anyone, any client can claim any IP and defeat your logging, rate limiting and IP-based access rules.
What's next
- Scale-to-zero to let an idle service sleep
- Your app is not reachable if traffic does not arrive