Migrating from Ingress NGINX to Pomerium Ingress Controller

Published: (December 5, 2025 at 08:57 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

The Kubernetes community announced that Ingress NGINX will be retired in March 2026. After that date there will be no further updates, bug‑fixes, or security patches. Existing deployments will keep working, but running without security updates is risky and no new features will be added.

Many Kubernetes operators are now evaluating alternatives to the community Ingress NGINX controller. The Pomerium Ingress Controller offers a compelling migration path that provides the same reverse‑proxy functionality you’re used to, with optional zero‑trust capabilities that you can adopt incrementally without requiring an immediate overhaul of your existing setup.

Why Consider Pomerium?

While several good Ingress controller alternatives exist, Pomerium provides:

  • The same reverse‑proxy behavior as Ingress NGINX.
  • Built‑in zero‑trust features that can be enabled gradually.
  • Open‑source core and controller, avoiding vendor lock‑in.

Before You Start

This guide assumes you have:

  • Pomerium installed.
  • The Pomerium Ingress Controller installed.
  • TLS certificates configured (Pomerium requires HTTPS for all routes).
  • Basic familiarity with Kubernetes Ingress resources.

What’s Different?

Pomerium has two key requirements that differ from NGINX:

  1. HTTPS is mandatory – all routes must use TLS.
  2. Policies are required – you must specify an access policy (even if it’s permissive).

These defaults enforce security out of the box, but you can configure permissive policies that behave like a traditional reverse proxy.

A Simple Migration Example

Below is a typical Ingress NGINX configuration and its Pomerium equivalent.

# Ingress NGINX → Pomerium Ingress Controller
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
  annotations:
    ingress.pomerium.io/policy: |
      - allow:
          any: true
spec:
  ingressClassName: pomerium   # changed from nginx
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app-service
            port:
              number: 80
  tls:
  - hosts:
    - app.example.com
    secretName: app-tls-cert

The configuration is nearly identical—just change the ingressClassName from nginx to pomerium and add a basic policy. The any: true policy tells Pomerium to allow all requests through without applying access restrictions, effectively functioning as a traditional reverse proxy.

Policy Options for Basic Reverse‑Proxy Functionality

For a straightforward migration that matches Ingress NGINX’s default behavior, you have several policy options:

Option 1: Allow any request (most similar to Ingress NGINX default)

ingress.pomerium.io/policy: |
  - allow:
      any: true

Option 2: Truly public access (annotation shortcut)

ingress.pomerium.io/allow_public_unauthenticated_access: "true"

Option 3: Any authenticated user (basic auth)

ingress.pomerium.io/allow_any_authenticated_user: "true"

TLS Certificate Management

Since Pomerium requires HTTPS, consider using cert‑manager for automatic certificate provisioning. The Pomerium Ingress Controller integrates seamlessly with cert‑manager:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    ingress.pomerium.io/policy: |
      - allow:
          any: true
spec:
  ingressClassName: pomerium
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app-service
            port:
              number: 80
  tls:
  - hosts:
    - app.example.com
    secretName: app-tls-cert   # cert‑manager will create this

Start Simple, Add Zero Trust When Ready

You can begin with a permissive policy and later replace it with fine‑grained rules based on user identity, device status, request context, or other factors:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
  annotations:
    ingress.pomerium.io/policy: |
      - allow:
          and:
            - domain:
                is: example.com
spec:
  ingressClassName: pomerium
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app-service
            port:
              number: 80
  tls:
  - hosts:
    - app.example.com
    secretName: app-tls-cert

Getting Started

With the March 2026 retirement deadline, you have time to plan your migration carefully. The Pomerium Ingress Controller installation is straightforward and well‑documented. You can run both controllers side‑by‑side during migration, gradually moving services over as you validate functionality.

Whether you’re looking for a sustainable long‑term solution or preparing for a zero‑trust future, the Pomerium Ingress Controller offers a natural evolution from traditional reverse‑proxy patterns. Start with the familiar, add security when you’re ready.

Learn more: and see the deployment documentation for detailed instructions.

Back to Blog

Related posts

Read more »