Overview
Nginx is a high-performance web server and reverse proxy. This template deploys Nginx as a stateless reverse proxy that routes incoming requests by path to other workloads in the same GVC, so several internal services can share one public endpoint. Thenginx.conf is generated from your locations values (or supplied whole through nginxConf) and mounted into the container from a secret.
A default install also deploys a small example backend and routes every request to it, so you can confirm the proxy works before pointing it at your own services.
This template does not create a GVC. It deploys into an existing GVC that you already have, and every workload it proxies to must already exist in that same GVC.
What Gets Created
Prerequisites
None for a default install. To proxy to your own services, each target workload must already exist in the same GVC, and its internal firewall must allow traffic fromRELEASE_NAME-nginx (for example same-gvc, or a workload list that includes the proxy).
Installation
Install the template into an existing GVC. No--set values are required:
UI
Browse, install, and manage templates visually
CLI
Manage templates from your terminal
Terraform
Declare templates in your Terraform configurations
Pulumi
Declare templates in your Pulumi programs
Configuration
Proxy Workload
proxyWorkload.image— the Nginx container image.proxyWorkload.port— the container port exposed by the workload. Leave it at80: the generatednginx.conflistens on80and the health probes check port80, neither of which follows this value.proxyWorkload.timeoutSeconds— the workload request timeout in seconds.
Resources
resources.cpu/resources.memory— the CPU and memory limit for each Nginx replica.
Autoscaling
autoscaling.minScale/autoscaling.maxScale— the minimum and maximum replica count. The proxy is stateless, so raisingmaxScalescales it horizontally.autoscaling.maxConcurrency— the maximum number of concurrent requests per replica.
Example Backend
true, the chart deploys RELEASE_NAME-example, a demo backend that answers every request none of your locations match. Set it to false to route / to your own service; a / location while it is on stops the proxy from starting.
Locations
location block that forwards matching requests to a workload in the same GVC:
Enter only the workload name in
workload. The chart builds the fully qualified internal hostname itself, WORKLOAD_NAME.GVC_NAME.cpln.local, and uses it for both the upstream address and the Host header sent to the target.
Example routing two paths to two services:
Custom nginx.conf
To run your own configuration instead of the generated one, put the whole file innginxConf. Helm template syntax in it is rendered, so it can still use .Values.locations and .Values.global.cpln.gvc. Keep listen 80 and a location /health that returns 200, because the health probes check them:
Built-in Routes
Two routes are always present, whateverlocations contains:
A
500, 502, 503 or 504 from an upstream workload is answered with the /fail body; the status code is kept.
Connecting
Read the canonical endpoint:
{"success":true,"message":"OK"} means Nginx is serving. With the example backend enabled, a request to https://CANONICAL_ENDPOINT/ returns the example greeting page.
Operations
Changing the Routing
Thenginx.conf lives in the RELEASE_NAME-nginx-config secret and is rebuilt from your values on every Helm upgrade. Edit locations (and enableExample) in your values file, then upgrade:
Upgrading From 1.1.1 or Earlier
Versions 1.1.1 and earlier defaultedproxyWorkload.image to nginx:latest. Version 1.1.2 pins it to nginx:1.31.4, so an upgrade that does not set the image restarts the proxy on the pinned version. The proxy holds no data, so nothing needs to be migrated. To keep a specific image, set proxyWorkload.image explicitly.
Upgrading From 1.1.2
Version1.1.3 moves the proxy to nginx 1.31.7, adds nginxConf, and removes proxyWorkload.capacityAI, which never had any effect (CapacityAI is always off for this template). Delete the key from your values file if you set it; the proxy holds no data, so nothing needs to be migrated.
Scaling and Availability
The proxy is stateless, so it scales horizontally. The shipped default runs exactly one replica (minScale: 1, maxScale: 1), which means a restart or redeployment briefly interrupts traffic. Set autoscaling.minScale to 2 or more for an endpoint other systems depend on, and raise autoscaling.maxScale to let it scale out under load.
Troubleshooting
Every request returns the example page
Every request returns the example page
Symptom: You added
locations, but requests to / still return the example greeting page.Cause: enableExample is still true, so the example backend answers every request your locations do not match, including /.Fix: Set enableExample: false and run a Helm upgrade as described in Changing the Routing.A route returns the JSON error body
A route returns the JSON error body
Symptom: Requests to one of your paths return
500 with {"success":false,"message":"Error"}.Cause: The upstream returned a 5xx or could not be reached. The usual reasons are a workload value that does not match the target name exactly, a wrong port, or a target whose internal firewall does not allow RELEASE_NAME-nginx.Fix: Check that the target exists in the same GVC and listens on the configured port, put only the bare workload name in workload, and allow the proxy in the target’s internal firewall. Read the proxy logs to see the upstream error:The proxy never becomes ready after a routing change
The proxy never becomes ready after a routing change
Symptom: After an upgrade the proxy restarts repeatedly, while
cpln helm upgrade itself reported success.Cause: locations is written into nginx.conf as-is, so a malformed entry is only caught when Nginx starts. Two entries with the same path, or a / entry while enableExample is true, produce a duplicate location that Nginx refuses to load.Fix: Read the startup error in the logs, correct the entry in your values, and upgrade again:Important Notes
- Set
enableExample: falsebefore routing to your own services; the default example backend answers every request none of yourlocationsmatch, and a/location while it is on stops the proxy from starting. - Put only the bare workload name in
locations[].workload; the chart appends.GVC_NAME.cpln.localitself. - Each target workload’s internal firewall must allow
RELEASE_NAME-nginx, or its route returns the JSON error body. - The proxy is always open to the internet; there is no value to make it private.
- Leave
proxyWorkload.portat80; Nginx and its health probes are fixed to that port. - A routing change rolls the proxy onto the new config after
helm upgrade; with one replica, requests may fail for a few seconds during the swap. - The example backend image,
gcr.io/knative-samples/helloworld-go, publishes only:latestand cannot be pinned; it does not affect the proxy.
External References
Nginx Documentation
Official Nginx documentation
Nginx Location Directive
How location paths and regex modifiers are matched
Nginx Reverse Proxy Guide
Proxying requests to upstream servers
Nginx Template
View the source files, default values, and chart definition