Tutorials  /  Container & Cloud

Set Up Nginx Ingress Controller with SSL on Kubernetes

Ccentron Redaktion · October 2025 ·10 min read ·Container & Cloud, Tutorial

The Nginx Ingress Controller is one of the most widely used Ingress solutions for Kubernetes. It leverages Nginx as both a reverse proxy and load balancer to securely channel external requests to services inside your cluster. Acting as a central gateway, it provides SSL/TLS termination, load balancing, session persistence, and path-based routing for various applications running in Kubernetes.

In this tutorial, you will configure an Nginx Ingress Controller with SSL certificates inside a Kubernetes Engine cluster. You’ll deploy two sample applications and secure them using Let’s Encrypt certificates managed by Cert Manager. The guide also demonstrates how to integrate commercial SSL certificates for TLS encryption.

Prerequisites

Before proceeding, ensure you have the following ready:

  • A running Kubernetes cluster with at least two nodes.
  • Kubectl installed for managing your cluster.
  • The Helm package manager set up on your local system.
  • A valid domain name, for instance example.com.
K8

Matching infrastructure at centron

From container to cluster: managed Kubernetes with cStack starts at €29.99 per month – control plane, autoscaler and traffic included. Explore managed Kubernetes →

Install the Nginx Ingress Controller

First, add the Nginx Ingress Helm repository.

Console
$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

Update Helm repositories to fetch the latest charts.

Console
$ helm repo update

Install the Nginx Ingress Controller into your Kubernetes environment.

Console
$ helm install ingress-nginx ingress-nginx/ingress-nginx

After installation, a LoadBalancer service is automatically provisioned for the controller.

Console
$ kubectl get services ingress-nginx-controller

Output example:

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

ingress-nginx-controller LoadBalancer 10.101.22.249 <pending> 80:31915/TCP,443:30217/TCP 106s

It may take several minutes for the service to obtain an EXTERNAL-IP, depending on your cloud provider.

Install Cert Manager

Deploy the latest release of Cert Manager using the command below.

Console
$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.2/cert-manager.yaml

You can always check the official Cert Manager release page for newer versions.

Verify Cert Manager resources within the cert-manager namespace.

Console
$ kubectl get all -n cert-manager

You should see several pods, services, replicasets, and deployments related to Cert Manager.

Deploy Backend Applications

Next, you’ll deploy two simple applications—app1 and app2—for testing the Ingress configuration. Both will use the hashicorp/http-echo image that serves a text response on an HTML page.

Create the Deployment for App1

Console
$ nano app1-deploy.yaml

Add the following configuration:

YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app1
  template:
    metadata:
      labels:
        app: app1
    spec:
      containers:
      - name: app1
        image: hashicorp/http-echo
        args: ["-text=Hello from App1"]
        ports:
        - containerPort: 5678

Create the Deployment for App2

Console
$ nano app2-deploy.yaml

Insert this configuration:

YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app2
  template:
    metadata:
      labels:
        app: app2
    spec:
      containers:
      - name: app2
        image: hashicorp/http-echo
        args: ["-text=Hello from App2"]
        ports:
        - containerPort: 5678

Apply both deployment manifests:

Console
$ kubectl apply -f app1-deploy.yaml
$ kubectl apply -f app2-deploy.yaml

Confirm that the deployments are active:

Console
$ kubectl get deployments

Create Service Manifests

Service for App1

Console
$ nano app1-svc.yaml

Insert the following YAML:

YAML
apiVersion: v1
kind: Service
metadata:
  name: app1-svc
spec:
  ports:
    - name: http
      port: 80
      targetPort: 8080
  selector:
    app: app1

Service for App2

Console
$ nano app2-svc.yaml

Add this configuration:

YAML
apiVersion: v1
kind: Service
metadata:
  name: app2-svc
spec:
  ports:
    - name: http
      port: 80
      targetPort: 8080
  selector:
    app: app2

Deploy both services:

Console
$ kubectl apply -f app1-svc.yaml
$ kubectl apply -f app2-svc.yaml

Check that all services are running:

Console
$ kubectl get services

Configure DNS Records

Log in to your DNS provider and open your domain management console. Create an A record for app1 pointing to your LoadBalancer’s external IP address. Repeat the process for app2, using the same IP.

Expose Applications via Nginx Ingress Controller

Now create Ingress resources to expose your backend applications publicly.

Ingress for App1

Console
$ nano app1-ingress.yaml

Insert this content:

YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-app1
  annotations:
    cert-manager.io/issuer: letsencrypt-nginx
spec:
  ingressClassName: nginx
  rules:
  - host: app1.example.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: app1-svc
            port:
              number: 80

Ingress for App2

Console
$ nano app2-ingress.yaml

Use this YAML content:

YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-app2
  annotations:
    cert-manager.io/issuer: letsencrypt-nginx
spec:
  ingressClassName: nginx
  rules:
  - host: app2.example.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: app2-svc
            port:
              number: 80

Apply both Ingress manifests:

Console
$ kubectl apply -f app1-ingress.yaml
$ kubectl apply -f app2-ingress.yaml

Confirm the Ingress resources:

Console
$ kubectl get ingress

You should see both ingress-app1 and ingress-app2 entries. Wait until the ADDRESS column shows your LoadBalancer IP.

Enable SSL Certificates for Nginx Ingress

To enable HTTPS, you can configure Cert Manager to automatically manage SSL certificates for your cluster. Cert Manager extends Kubernetes with custom resources for certificate issuance and lifecycle management from trusted Certificate Authorities like Let’s Encrypt.

  • Issuer: Defines configuration for a certificate issuer, such as the type (ACME) and challenge method (DNS01 or HTTP01) within a namespace.
  • ClusterIssuer: Similar to Issuer but can issue certificates cluster-wide, suitable for multi-namespace configurations.
  • Certificate: Specifies certificate properties including domain names, secret storage, and the chosen issuer.

List available CRDs for Cert Manager using the following command:

Console
$ kubectl get crd -l app.kubernetes.io/name=cert-manager

The output should include resources like issuers.cert-manager.io, certificates.cert-manager.io, and clusterissuers.cert-manager.io, confirming Cert Manager’s CRDs are available.

Set Up Let’s Encrypt Certificates

Create a new Issuer manifest named cert-issuer.yaml to configure Let’s Encrypt certificate management.

Console
$ nano cert-issuer.yaml

Add the following YAML configuration:

YAML
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-nginx
spec:
  acme:
    email: hello@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-nginx-prod
    solvers:
    - http01:
        ingress:
          class: nginx

This configuration defines an ACME Issuer with the following parameters:

  • email: The contact email associated with the ACME account. Avoid using @example.com as it will prevent the issuer from becoming active.
  • server: The API endpoint for the Let’s Encrypt ACME service.
  • privateKeySecretRef: Specifies the Kubernetes Secret where the ACME account’s private key is stored.
  • solvers: Defines how Let’s Encrypt validates domain ownership. Typically, the http01 method is used unless wildcard certificates are required.

Replace the placeholder email address with your valid one, then save and close the file.

Apply the Issuer resource to your cluster:

Console
$ kubectl apply -f cert-issuer.yaml

Check if the Issuer resource is properly created and initialized:

Console
$ kubectl get issuer

Sample output:

NAME READY AGE

letsencrypt-nginx False 4s

The READY column will initially show False. After a short time, it should change to True.

Configure Ingress Resources for TLS

Next, link your Ingress resources with the Let’s Encrypt certificates.

Check the current state of Ingress resources:

Console
$ kubectl get ingress

Edit the app1-ingress.yaml file to include a TLS section:

Console
$ nano app1-ingress.yaml

Add this snippet under the spec section:

YAML
tls:
  - hosts:
    - app1.example.com
    secretName: letsencrypt-nginx-app1

The full manifest now appears as follows:

YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-app1
  annotations:
    cert-manager.io/issuer: letsencrypt-nginx
spec:
  ingressClassName: nginx
  rules:
  - host: app1.example.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: app1-svc
            port:
              number: 80
  tls:
  - hosts:
    - app1.example.com
    secretName: letsencrypt-nginx-app1

Apply the same TLS section to the app2-ingress.yaml manifest:

YAML
tls:
  - hosts:
    - app2.example.com
    secretName: letsencrypt-nginx-app2

Apply the updated manifests to enable TLS on both hosts:

Console
$ kubectl apply -f app1-ingress.yaml
$ kubectl apply -f app2-ingress.yaml

Verify that your Ingress resources have port 443 activated:

Console
$ kubectl get ingress

Example output:

NAME CLASS HOSTS ADDRESS PORTS AGE

app1-ingress nginx app1.example.com 192.0.2.1 80,443 10m

app2-ingress nginx app2.example.com 192.0.2.1 80,443 10m

Check Certificate Resources

Confirm that the SSL certificates were generated successfully:

Console
$ kubectl get certificates

Example output:

NAME READY SECRET AGE

letsencrypt-app1 True letsencrypt-nginx-app1 5m

letsencrypt-app2 True letsencrypt-nginx-app2 5m

If the READY column reads True, your certificates are correctly issued. If False, double-check your Ingress configuration and reapply the manifests to renew certificates.

Test the SSL Configuration

Once certificates are active, verify HTTPS access through a browser:

If accessed via HTTP, the Ingress Controller automatically redirects traffic to HTTPS.

Import Commercial SSL Certificates

If you purchased an SSL certificate from a commercial Certificate Authority, you can manually import it. First, convert both the certificate and private key files into base64 format.

Console
$ base64 -w 0 /path/ssl-certificate.pem
$ base64 -w 0 /path/cert-private-key.pem

Replace /path with the actual directory containing your SSL files.

Next, create a Kubernetes Secret manifest:

Console
$ nano ssl-secret.yaml

Insert the following YAML configuration:

YAML
apiVersion: v1
kind: Secret
metadata:
  name: prod-ssl-secret
type: kubernetes.io/tls
data:
  tls.crt: 
  tls.key: 

Ensure that:

  • tls.crt holds the base64-encoded SSL certificate.
  • tls.key contains the base64-encoded private key.

Save the file and apply it. Then, reference this Secret under spec.tls.secretName in your Ingress manifest to activate the commercial SSL certificate.

Troubleshooting

  • Nginx 502 Gateway Error: Verify the Ingress rules and ensure all backend services are reachable.
  • Let’s Encrypt Certificates not generating (READY = False): Confirm your Issuer and Certificate configurations, use a valid email address, and review the Issuer logs for errors.

Conclusion

In this guide, you successfully installed and configured the Nginx Ingress Controller with SSL on a Kubernetes Engine cluster. Your setup now routes external traffic securely over HTTPS, using either Let’s Encrypt or commercial SSL certificates for encrypted access to your Kubernetes services.

Jetzt 200 € Guthaben sichern

Testen Sie Ihr Setup auf ccloud³

Registrieren Sie sich in der ccloud³ und erhalten Sie 200 € Startguthaben für Ihr Projekt – z. B. für eine PostgreSQL-VM mit automatischen Backups.

centron Redaktion Technische Redaktion

Das Redaktionsteam von centron schreibt Anleitungen aus dem Betriebsalltag: getestet auf unserer eigenen Plattform, betrieben im Rechenzentrum in Hallstadt bei Bamberg.

Kategorie Container & Cloud
Teilen
Noch offene Fragen?

Unser Team hilft Ihnen bei Ihrem konkreten Setup weiter – von Menschen, die die Plattform selbst betreiben.

War dieses Tutorial hilfreich?

Ihre Antwort wird anonym gespeichert und hilft uns, die Tutorials zu verbessern.

Kommentare

Noch keine Kommentare – stellen Sie die erste Frage zu diesem Tutorial.

Zum Kommentieren anmelden

Kommentare stehen centron-Kunden offen. Melden Sie sich in Ihrem Konto an, um eine Frage zu diesem Tutorial zu stellen.

Weiterlesen

Das könnte Sie auch interessieren

Jetzt kostenlos anfangen

Melden Sie sich an und erhalten Sie in den ersten 60 Tagen ein Guthaben von 200 € bei centron.

Dieses Werbeangebot gilt nur für neue Konten. Angebot ausschließlich für Gewerbetreibende.

Jetzt loslegen Sales kontaktieren