Skip to main content

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. The nginx.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 from RELEASE_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:
To install using another method, follow the instructions for your preferred tool:

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 at 80: the generated nginx.conf listens on 80 and the health probes check port 80, 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 raising maxScale scales it horizontally.
  • autoscaling.maxConcurrency — the maximum number of concurrent requests per replica.
The scaling metric is fixed in the chart: CPU, with a 50 percent target.

Example Backend

When 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

Each entry becomes one Nginx 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 in nginxConf. 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, whatever locations 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:
Then check the built-in health route:
A response of {"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

The nginx.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:
The values file must use the chart’s nesting, exactly as the blocks in Configuration show. A flat dotted key is accepted without error and silently changes nothing. A routing change rolls the proxy onto the new configuration by itself after the upgrade. With one replica, requests may fail for a few seconds during the swap. Confirm a route you changed answers on the public endpoint. Edit routing through Helm values only, and keep your routing in your values file.

Upgrading From 1.1.1 or Earlier

Versions 1.1.1 and earlier defaulted proxyWorkload.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

Version 1.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

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.
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:
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: false before routing to your own services; the default example backend answers every request none of your locations match, 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.local itself.
  • 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.port at 80; 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 :latest and 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