Skip to main content

Configure TLS

When running on Kubernetes, TLS should be terminated at the Ingress layer—not inside Appsmith. This page covers the common approaches to adding TLS to your Appsmith ingress.

caution

Avoid setting APPSMITH_CUSTOM_DOMAIN in your Helm values. This enables Appsmith's built-in Caddy proxy to handle TLS, which is designed for Docker and single-instance deployments. On Kubernetes it can cause redirect loops if proxy protocol or X-Forwarded-Proto headers are not correctly configured between your cloud load balancer, Ingress controller, and Appsmith.

Wildcard or pre-existing certificate

If your cluster already has TLS coverage for your domain—for example, a wildcard certificate managed by your Ingress controller or a cloud load balancer—no additional TLS configuration is needed in the Appsmith chart. Your ingress configuration from the install guide is sufficient:

ingress:
enabled: true
className: traefik
hosts:
- host: appsmith.example.com

The Ingress controller matches the hostname against the existing certificate and terminates TLS automatically.

cert-manager

cert-manager automates certificate issuance and renewal. This is the most common approach when you don't already have wildcard coverage. The examples below show how to wire cert-manager into the Appsmith Helm chart—for help installing or troubleshooting cert-manager itself, refer to the cert-manager documentation.

Prerequisites

  • cert-manager installed in your cluster (installation guide)
  • A ClusterIssuer or Issuer configured (for example, Let's Encrypt)

Values

Add the following to your values.yaml:

ingress:
enabled: true
className: "" # your ingress controller
tls: true
certManager: true
certManagerTls:
- hosts:
- appsmith.example.com
secretName: appsmith-tls
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: appsmith.example.com

Setting certManager: true automatically adds the kubernetes.io/tls-acme: "true" annotation. The cert-manager.io/cluster-issuer annotation tells cert-manager which issuer to use—adjust this to match your ClusterIssuer name.

Apply with:

helm upgrade appsmith-ee appsmith-ee/appsmith \
-n appsmith-ee -f values.yaml

Verify

Check that cert-manager issued a certificate:

kubectl get certificate -n appsmith-ee

The certificate should show Ready: True. If it stays False, check the certificate and order events:

kubectl describe certificate appsmith-tls -n appsmith-ee

Bring your own certificate

If you manage certificates outside of Kubernetes (purchased certs, internal CA, etc.), create a TLS Secret and reference it in your values.

Create the Secret

kubectl create secret tls appsmith-tls \
-n appsmith-ee \
--cert=path/to/tls.crt \
--key=path/to/tls.key

Values

ingress:
enabled: true
className: "" # your ingress controller
tls: true
secrets:
- hosts:
- appsmith.example.com
secretName: appsmith-tls
hosts:
- host: appsmith.example.com

Apply with:

helm upgrade appsmith-ee appsmith-ee/appsmith \
-n appsmith-ee -f values.yaml

Controller-managed TLS

Some Ingress controllers handle certificate provisioning themselves—for example, Tailscale or cloud load balancer controllers that provision certificates via AWS ACM or Google-managed certs. In these cases, set tls: true but leave secretName empty:

ingress:
enabled: true
className: tailscale
tls: true
secrets:
- hosts:
- appsmith
secretName: ~

The controller provisions and manages the certificate. No cert-manager or manual Secret required.

Troubleshooting

Redirect loop after enabling TLS

Cause: APPSMITH_CUSTOM_DOMAIN is set in your Helm values. This tells Appsmith's built-in Caddy proxy to handle TLS internally, which conflicts with Ingress TLS termination.

Fix: Remove APPSMITH_CUSTOM_DOMAIN from your applicationConfig and restart the pods:

helm upgrade appsmith-ee appsmith-ee/appsmith \
-n appsmith-ee -f values.yaml

Certificate not issued by cert-manager

Check the cert-manager logs and the Certificate resource events:

kubectl logs -n cert-manager -l app=cert-manager --tail=50
kubectl describe certificate -n appsmith-ee

Common causes: the ClusterIssuer name doesn't match, DNS isn't pointing to the Ingress yet, or the ACME challenge can't be reached.

See also