Migrate from ingress-nginx to NGINX Gateway Fabric and the akash-gateway chart.
You already use cert-manager and a ClusterIssuer for Let’s Encrypt. For the wildcard, you mainly recreate the same Certificate request with three changes: metadata.namespace: akash-gateway, metadata.name: wildcard-ingress, and spec.secretName: wildcard-ingress-tls (chart defaults for https-wildcard). Keep your DNS names and issuerRef the same as before. Install the Gateway stack in the steps below, then apply that Certificate in Re-bind TLS.
If cert-manager is not on the cluster yet, use the without cert-manager path and prep STEP 9 first. Back to overview.
Time: 30–45 minutes of work, plus time for certificates to become Ready.
What you’ll install
- Gateway API CRDs (standard + experimental, includes
TCPRoute) - NGINX Gateway Fabric with host ports 80, 443, 8443, 8444, 5002
- The
akash-gatewayHelm release (Gateway,TCPRoutes, HTTPS for deployers) - TLS for the Gateway in the
akash-gatewaynamespace (secret names and listeners are set in the re-bind section)
Before you begin
- Provider on v0.11.2 before upgrading to v0.12.0
kubectland Helm 3ingress-nginxon TCP 8443 and 8444 today- Host ports 80, 443, 8443, 8444, and 5002 available on your nodes
- cert-manager and a
ClusterIssuer; plan to finish TLS inakash-gateway(not only iningress-nginx)
STEP 1: Install Gateway API CRDs
Install the standard Gateway API CRDs. These are required before deploying NGINX Gateway Fabric.
# Install NGINX Gateway Fabric CRDs (standard channel)kubectl kustomize "https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/standard?ref=v2.4.2" | kubectl apply -f -Then install the full experimental Gateway API bundle, which includes TCPRoute support:
# Install experimental Gateway API resources (includes TCPRoute)kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/experimental-install.yamlVerify the CRDs are installed:
kubectl get crd | grep gateway.networking.k8s.ioExpected output:
gatewayclasses.gateway.networking.k8s.iogateways.gateway.networking.k8s.iohttproutes.gateway.networking.k8s.iotcproutes.gateway.networking.k8s.io...STEP 2: Install NGINX Gateway Fabric
On your control plane node, save the following as /root/provider/values-nginx-gateway-fabric.yaml:
nginxGateway: gatewayClassName: nginx
gwAPIExperimentalFeatures: enable: true
leaderElection: enable: true
config: logging: level: info
resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 256Mi
nginx: kind: daemonSet
service: type: ClusterIP
container: hostPorts: - port: 80 containerPort: 80 - port: 443 containerPort: 443 - port: 8443 containerPort: 8443 - port: 8444 containerPort: 8444 - port: 5002 containerPort: 5002
resources: requests: cpu: 100m memory: 128Mi limits: cpu: 1000m memory: 512MiNote: gwAPIExperimentalFeatures.enable: true is required for TCPRoute support. nginx.kind: daemonSet with ClusterIP service type means NGINX binds directly to host ports on each node rather than using a LoadBalancer. Include port 443 so deployers can reach HTTPS on the Gateway without a second NGF upgrade.
Firewall: allow 443/tcp in addition to your existing provider ports.
Install NGINX Gateway Fabric via Helm:
cd /root/provider
helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \ --create-namespace \ -n nginx-gateway \ -f values-nginx-gateway-fabric.yamlVerify the installation:
kubectl -n nginx-gateway get podsExpected output:
NAME READY STATUS RESTARTS AGEngf-nginx-gateway-fabric-xxxxxxxxxx-xxxxx 2/2 Running 0 60sSTEP 3: Install the Akash Gateway (Gateway + TCPRoutes)
The akash-gateway Helm chart creates the Gateway resource, TCPRoutes, and HTTPS listeners named https-wildcard and https-custom. It expects TLS Secrets wildcard-ingress-tls and akash-default-tls (defaults).
New clusters: the recommended order is to finish cert-manager, ClusterIssuer, and both Secrets in Provider installation (prep) – STEP 9 before helm install akash-gateway (then continue with Provider installation (install)).
In-place migration (this guide): you will install the chart below, then follow re-bind TLS to akash-gateway to attach the same (or a new) Let’s Encrypt certificate to the new listeners. If you do not have cert-manager yet, stop and use Gateway API migration (without cert-manager) instead.
Pass the same domain you use for the provider (for example with -f /root/provider/provider.yaml) so the wildcard host *.ingress.<domain> matches your DNS; only keys this chart uses are read from the file.
helm repo add akash https://akash-network.github.io/helm-chartshelm repo update akash
helm install akash-gateway akash/akash-gateway \ -n akash-gateway \ --create-namespace \ -f /root/provider/provider.yamlIf you are not ready to use your full values file, set the domain explicitly:
helm install akash-gateway akash/akash-gateway -n akash-gateway --create-namespace --set "domain=yourdomain.com"The chart enables TLS listeners by default, but the cluster must still have the Secrets in place, or clients will not get valid HTTPS. After this helm install, complete re-bind TLS to akash-gateway.
Verify
kubectl -n akash-gateway get gateway akash-gatewaykubectl -n akash-services get tcproutesExpected output:
# GatewayNAME CLASS ADDRESS PROGRAMMED AGEakash-gateway nginx True 30s
# TCPRoutesNAME AGEakash-provider-8443 15sakash-provider-8444 15sRe-bind TLS to akash-gateway
If STEP 2 already opens port 443 on NGF, you do not need another NGF upgrade. Keep 443/tcp open on the firewall.
Wildcard cert (https-wildcard)
Point the wildcard Certificate at the Gateway by setting:
| Field | Value |
|---|---|
metadata.namespace | akash-gateway |
metadata.name | wildcard-ingress |
spec.secretName | wildcard-ingress-tls |
Copy spec.dnsNames (and spec.commonName if you use it) and spec.issuerRef from your existing ingress-nginx Certificate; only the namespace, resource name, and secret name change. Then apply:
apiVersion: cert-manager.io/v1kind: Certificatemetadata: name: wildcard-ingress namespace: akash-gatewayspec: secretName: wildcard-ingress-tls issuerRef: name: letsencrypt-prod kind: ClusterIssuer commonName: "*.yourdomain.com" dnsNames: - "*.yourdomain.com" - "*.ingress.yourdomain.com"kubectl apply -f /root/provider/wildcard-ingress-tls.yamlNote: After cutover, delete the old Certificate in ingress-nginx if you no longer need it, so you are not renewing the same hostnames twice.
Default listener secret (https-custom)
If you do not have a real cert for the custom listener yet, a self-signed placeholder is enough until you replace it:
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \ -keyout /tmp/default.key -out /tmp/default.crt -subj "/CN=default"
kubectl create secret tls akash-default-tls \ --cert=/tmp/default.crt --key=/tmp/default.key -n akash-gatewayWait for the Certificate
Usually one to two minutes until Ready:
kubectl -n akash-gateway get certificatekubectl -n akash-gateway describe certificate wildcard-ingressHelm: same domain as the provider
cd /root/providerhelm upgrade --install akash-gateway akash/akash-gateway -n akash-gateway -f provider.yamlCheck listeners and HTTPS
kubectl -n akash-gateway get gateway akash-gateway -o yaml \ | grep -E "name: (https-wildcard|https-custom)" -A 20# Replace host with a tenant name under your domainecho "" | openssl s_client -connect test.ingress.yourdomain.com:443 -showcerts 2>&1 \ | openssl x509 -issuer -subject -dates -noout -text \ | grep -E "(Issuer:|Subject:|Not Before:|Not After :|DNS:)"If NGF does not pick up the new cert, restart its data plane:
kubectl -n nginx-gateway rollout restart deployment \ -l app.kubernetes.io/name=nginx-gateway-fabricFor another pass on verification, use the end-to-end HTTPS test in prep. DNS-01 and issuer setup details: STEP 9 (TLS) in prep and the cert-manager DNS-01 docs.
STEP 4: Upgrade Provider to v0.12.0
With the Gateway resources in place, upgrade the Akash provider Helm charts to v0.12.0.
Update Helm Repo
helm repo update akashVerify the expected chart versions are available:
helm search repo akashExpected output:
NAME CHART VERSION APP VERSIONakash/akash-hostname-operator 16.0.0 0.12.0akash/akash-inventory-operator 16.0.0 0.12.0akash/akash-ip-operator 16.0.0 0.12.0akash/akash-node 17.1.1 2.0.1akash/provider 16.0.0 0.12.0Backup Current Chart Values
cd /root/providerfor i in $(helm list -n akash-services -q | grep -vw akash-node); do helm -n akash-services get values $i > ${i}.pre-v0.12.0.values; doneUpgrade Operators
helm -n akash-services upgrade akash-hostname-operator akash/akash-hostname-operatorhelm -n akash-services upgrade inventory-operator akash/akash-inventory-operatorWith persistent storage (adjust storage class to match your setup):
helm -n akash-services upgrade inventory-operator akash/akash-inventory-operator \ --set inventoryConfig.cluster_storage[0]=default \ --set inventoryConfig.cluster_storage[1]=beta3 \ --set inventoryConfig.cluster_storage[2]=ramWith IP leasing (MetalLB):
helm -n akash-services upgrade akash-ip-operator akash/akash-ip-operatorUpgrade Provider
cd /root/provider
helm upgrade akash-provider akash/provider \ -n akash-services \ -f provider.yaml \ --set bidpricescript="$(cat price_script_generic.sh | openssl base64 -A)"Verify Pod Versions
Allow a minute or two for Kubernetes to apply the changes, then confirm all pods are running v0.12.0:
kubectl -n akash-services get pods -o custom-columns='NAME:.metadata.name,IMAGE:.spec.containers[*].image'All provider, hostname-operator, and inventory-operator images should reference 0.12.0.
STEP 5: Uninstall ingress-nginx
With the provider upgraded and NGINX Gateway Fabric handling all traffic on ports 80, 443, 8443, 8444, and 5002, ingress-nginx is no longer needed and can be removed.
helm uninstall ingress-nginx -n ingress-nginxVerify all ingress-nginx resources are removed:
kubectl -n ingress-nginx get podsExpected output:
No resources found in ingress-nginx namespace.Verification
Check Provider Endpoints
Verify that the provider endpoints are accessible through the new gateway:
# Replace provider.example.com with your provider domaincurl -k https://provider.example.com:8443/statusVerify TCPRoute Status
kubectl -n akash-services describe tcproute akash-provider-8443kubectl -n akash-services describe tcproute akash-provider-8444Look for ResolvedRefs and Accepted conditions showing True in the output.
Check NGINX Gateway Fabric Logs
kubectl -n nginx-gateway logs -l app.kubernetes.io/name=nginx-gateway-fabric -c nginx-gatewayVerify No Port Conflicts
Confirm no two processes are bound to the same host ports:
# Run on each node in your clusterss -tlnp | grep -E ':(80|443|8443|8444|5002)\s'Each port should appear only once, owned by the NGINX Gateway Fabric process.
Troubleshooting
Issue: Gateway Shows Programmed: False
Symptoms:
kubectl get gateway akash-gatewayshowsPROGRAMMED: False- TCPRoutes remain unresolved
Diagnosis:
kubectl -n akash-gateway describe gateway akash-gatewaySolution:
Verify NGINX Gateway Fabric pods are running and the GatewayClass was registered:
kubectl -n nginx-gateway get podskubectl get gatewayclass nginxIf the GatewayClass is missing, the Helm install may have failed. Re-run the Helm install from Step 2.
Issue: TCPRoute ResolvedRefs is False
Symptoms:
kubectl describe tcproute akash-provider-8443shows backend not found
Diagnosis:
kubectl -n akash-services get service akash-providerSolution:
Confirm the akash-provider service exists in the akash-services namespace and exposes the expected ports:
kubectl -n akash-services get service akash-provider -o yaml | grep -A 20 portsThe service must have ports 8443 and 8444 defined.
Issue: Port Conflict on Node
Symptoms:
- NGINX Gateway Fabric pods fail to start or crash-loop
- Error in pod logs:
bind: address already in use
Solution:
Check which process holds the port on the affected node:
ss -tlnp | grep -E ':(80|443|8443|8444|5002)\s'If ingress-nginx still holds the ports, ensure it was fully uninstalled in Step 5:
helm list -n ingress-nginxIf the release still exists, uninstall it:
helm uninstall ingress-nginx -n ingress-nginxRelated Resources
- Gateway API migration overview — pick with vs without cert-manager
- Gateway API migration (without cert-manager) — if you need to install cert-manager first
- Provider installation (prep) —
provider.yaml, DNS, NGF, and STEP 9 (Let’s Encrypt, Secrets) - Provider installation (install) —
helm installforakash-gateway, operators, andakash/provider - Provider installation (prep) – STEP 9 (TLS) — cert-manager,
wildcard-ingress-tls/akash-default-tls, troubleshooting - Updates & Maintenance
- Provider Verification
- NGINX Gateway Fabric
- Kubernetes Gateway API