TLS termination and certificates for Argo CD

Argo CD serves gRPC and HTTPS on one port, so where TLS ends decides your hostnames, ingress settings and CLI access. This page covers passthrough, termination and the grpc-web fallback.

On this page

Where TLS ends in front of Argo CD and why it matters

Where TLS ends is the first decision when you publish Argo CD through an ingress or load balancer, and it sets your hostname and certificate layout for the life of the installation. You can pass encrypted traffic through to the Argo CD API server unchanged, or you can terminate TLS at the ingress and forward plain traffic inside the cluster. The choice is not cosmetic. It determines whether the web UI and the argocd CLI can share one hostname, which certificates you must issue and renew, and what the API server must be configured to accept. Argo CD's own ingress guidance treats these as the two paths to plan for before any manifests are applied. The reason the choice matters is that argocd-server serves gRPC and HTTPS on the same port, 443, and detects the protocol of each incoming connection. Because the server sorts out the protocol itself, SSL passthrough can use a single hostname for both the browser and the CLI. Termination at the ingress is different. Most ingress controllers route on HTTP host and path rules after decrypting traffic, and they often cannot route gRPC and HTTPS from one hostname in the same way, so termination usually needs separate hostnames for the gRPC and HTTPS endpoints, each with its own certificate.

Before you commit, confirm three things about your controller: whether it supports passthrough on your version and how it is enabled, whether it can route gRPC for the CLI, and whether its TLS settings can be applied to both hostnames. Also confirm that your certificate tooling can issue and rotate certificates for every name you plan to publish. If you terminate TLS, the API server must run without its own TLS, which changes what traffic reaches the pod and is covered in the next section. Write down the hostnames, the certificate owner and the renewal process before you start, because changing this layout later means reissuing certificates and reconfiguring clients.

Passthrough or termination: which path fits your controller

When your ingress controller supports SSL passthrough, the simplest design is one hostname that carries both the web UI and CLI gRPC traffic. The edge forwards the encrypted stream to argocd-server without decrypting it, and argocd-server serves gRPC and HTTPS on port 443 and detects which protocol each connection uses. The certificate is therefore presented by Argo CD itself, so the platform team must issue and rotate a certificate that the API server loads, and the edge only needs to route on the hostname.

  • Certificate holder: argocd-server holds the certificate, so renewal is handled at the Argo CD layer rather than at the edge.
  • API server mode: the server keeps TLS enabled and does not run with server.insecure.
  • CLI behavior: argocd login connects to the single hostname over gRPC without needing the grpc-web fallback.
  • Edge features: the edge cannot inspect headers, apply path rules or add a web application firewall policy to the decrypted traffic.
  • Certificate trust: clients must trust the certificate that argocd-server presents, including any private CA used inside your network.

Confirm with your controller's documentation that passthrough is supported for the version you run and that it applies to the hostname and port you intend to publish.

TLS configuration options and when each fits

This table compares the four ways to expose Argo CD's API server for the UI and CLI, with the setting each one needs and the trade-off it carries. Read each row against your ingress controller's capabilities and your certificate process, then pick the option that keeps TLS where your security team expects it.

OptionWhen it fitsWhat it requiresMain trade-off
SSL passthrough, one hostnameYou want the API server to keep its own TLS and your ingress only routes traffic by hostnameIngress that supports passthrough; argocd-server serves gRPC and HTTPS on port 443 and detects the protocol, so one hostname can serve bothCertificates live in Argo CD, and the ingress cannot inspect or apply policy to decrypted traffic
Termination with separate gRPC and HTTPS hostnamesYour ingress terminates TLS centrally and you want certificate management and WAF rules at the edgeTwo hostnames, one for the UI and one for the CLI's gRPC traffic, each routed to the right backend protocol; the ingress usually needs this splitMore DNS records, certificates and routing rules to maintain and test
server.insecure set in argocd-cmd-params-cmThe ingress terminates TLS and the API server sits on a private network behind itserver.insecure set to "true" in argocd-cmd-params-cm (or the --insecure flag), so the API server accepts plain traffic from the ingressTraffic between the ingress and Argo CD is unencrypted unless you add encryption on that hop; confirm this against your segmentation rules
CLI --grpc-web flagThe path between the CLI and the ingress does not carry gRPC over HTTP/2 reliably, such as some proxies or load balancersThe CLI falls back from gRPC over HTTP/2 to HTTP/1.1 when you pass --grpc-web; the API server and ingress still need a route that reaches itFallback is a workaround, not a preferred path, and you should test each CLI workflow after enabling it
Choosing for audit evidenceYour assessors ask where encryption ends and who manages certificatesA written record of the chosen option, the certificate owner and the hop where traffic is decryptedAmbiguity about the termination point is a common finding; document each hop explicitly

Setting up TLS termination for Argo CD step by step

This sequence takes you from choosing where TLS ends to a verified CLI login, so the UI and the gRPC-based CLI both reach argocd-server through the ingress path you chose.

  1. Choose passthrough or termination

    The platform or security owner decides whether TLS ends at argocd-server (passthrough) or at the ingress (termination). Passthrough lets one hostname serve both the web UI and gRPC traffic, because argocd-server detects the protocol on port 443. Termination usually needs separate hostnames for gRPC and HTTPS, and it moves the certificate handling to the ingress layer. Record the decision and the hostnames in your design notes. Done when the team has agreed the path and each hostname that will be published.

  2. Source a certificate for each hostname

    The team that owns DNS and certificate issuance obtains a certificate for every hostname the ingress will serve, from your internal CA, a public CA or an in-cluster issuer such as cert-manager, depending on your policy. Confirm the certificate covers the exact gRPC and HTTPS names, that the chain is complete, and that renewal is owned by someone. Store the key material in the secret store your organization uses, not in the Argo CD repository. Done when each hostname resolves and presents a valid chain from a client outside the cluster.

  3. Set server.insecure for termination

    If the ingress terminates TLS, the API server must stop serving TLS itself. Set server.insecure to "true" in the argocd-cmd-params-cm ConfigMap, or start argocd-server with the --insecure flag, then restart the argocd-server deployment so the change takes effect. Skip this step for passthrough, because the API server still needs its TLS listener there. Done when the argocd-server logs show it listening without TLS and a direct request to the pod port over HTTPS no longer completes a TLS handshake.

  4. Configure the ingress for gRPC and HTTPS

    The platform engineer creates the ingress resources in the ingress controller you run, using the hostname plan from the first step. For termination, route the HTTPS hostname to the argocd-server service for the web UI and API, and route the gRPC hostname to the same service with the backend protocol your controller needs for HTTP/2 to the server. For passthrough, configure SSL passthrough on the single hostname. Syntax differs between controllers, so confirm the exact annotations or resource types with your controller's documentation and the Argo CD ingress guide. Done when both hostnames return the Argo CD login page or a gRPC error from the correct backend, rather than a routing error from the controller.

  5. Verify the CLI login over gRPC

    From a workstation outside the cluster, the operator runs argocd login against the gRPC hostname, using the standard CLI flags for your ingress setup. A successful login returns the authenticated user and writes a context to the local CLI configuration. If the login fails with a protocol or handshake error, the ingress is probably not passing HTTP/2 through to argocd-server. Note the certificate chain the CLI trusts, because a missing internal CA certificate is a common cause of failure. Done when argocd version and argocd account get-user-info both return results through the gRPC hostname.

  6. Test the grpc-web fallback

    Where the ingress or a load balancer cannot carry HTTP/2 for gRPC, the operator retries the login with the --grpc-web flag, which lets the CLI fall back from gRPC over HTTP/2 to HTTP/1.1. Use this path as a documented workaround rather than as the default, and confirm with your network team which path your infrastructure supports. Record which mode you rely on in the runbook, because teams often change load balancers later and break the CLI without noticing. Done when the same login command succeeds with --grpc-web and the team has written down when it should be used.

  7. Confirm internal traffic and certificate expiry

    The security or operations owner checks the end-to-end path once more after the first successful logins. Confirm that the UI and CLI reach argocd-server only through the ingress, that no unexpected TLS listener is exposed inside the cluster, and that the certificates have monitored expiry dates with an owner for renewal. Record the configuration in Git so that a later upgrade does not silently reset server.insecure. Done when a checklist signed off by the owner shows each hostname, certificate expiry, the chosen path and the login results from the previous step.

Certificate ownership, trust and rotation

Decide who owns each certificate before you choose a termination point, because the answer changes with the path. With SSL passthrough, the Argo CD API server presents its own certificate to clients, so the team that operates Argo CD issues, installs and renews it, usually through a secret the server reads. With TLS termination at the ingress, the certificate that browsers and the CLI see belongs to the ingress layer, so the team that operates the ingress or load balancer owns it. In that model, the gRPC and HTTPS hostnames may each need a certificate, and each one needs an owner, a renewal process and an alert before expiry. Confirm these owners in writing, including who approves a renewal that fails outside business hours.

Trust is the part most often missed. Every client must trust the CA that issued the certificate it sees: browsers for the web UI, and the argocd CLI on engineers' workstations and in CI runners for gRPC. If the CA is internal, plan how it reaches those machines, and test the CLI against each hostname separately, since a trusted browser session does not prove the CLI trusts the gRPC endpoint. Also remember that TLS does not stop at the ingress. Argo CD uses TLS for traffic between its own components, so termination at the edge does not remove the need for internal certificates, and you should confirm with the project's security documentation how those internal certificates are generated and rotated in your version. Argo CD's own documentation on security is the starting point for that check.

Plan rotation for both hostnames as separate events, even when they share a CA. A renewal that replaces only the HTTPS certificate leaves the gRPC hostname serving an expired certificate, and CLI users see failures while the web UI looks healthy. Write a rotation runbook that lists each hostname, its secret or load balancer object, the reload step, and a post-change test with both argocd login and a browser session. Argo CD itself is largely stateless, so a renewal normally means updating ingress or server configuration and checking the rollout, but confirm how your chosen controller picks up new certificates without a restart. Test the runbook on a non-production cluster before the first real expiry date arrives.

Security risks of moving TLS termination to the ingress

Terminating TLS at the ingress moves part of the trust boundary out of Argo CD and into the network path in front of it. The cards below cover the controls that change with that choice and the checks to run before you publish the API server.

Plaintext API server behind the ingress

With server.insecure set to true in argocd-cmd-params-cm, the API server accepts unencrypted connections on its port. Anything that reaches that port without passing through the ingress can read tokens and manifests in transit. Confirm that network policies allow only the ingress controller to reach argocd-server, and that no NodePort or LoadBalancer service exposes the plaintext port directly.

Trust boundary between ingress and cluster

Once TLS ends at the ingress, traffic between the ingress and argocd-server crosses the cluster network unencrypted. The Argo CD security documentation says TLS protects traffic between its own components, so this hop is a deliberate exception you must accept or cover. Decide whether the ingress and Argo CD share a trusted network segment, and document who can run pods or capture traffic there.

JWT-only API authentication

Argo CD authenticates API requests only with JSON Web Tokens, so a stolen or long-lived token gives the same access as the session that issued it. Terminating TLS at the ingress does not change this, but it does mean token interception on the plaintext hop is a live risk. Review token lifetimes, rotate tokens used by automation, and limit which accounts can generate them.

Credential redaction in responses and logs

Argo CD redacts cluster, Git and OAuth2 credentials from API responses and logs. That protection covers what Argo CD emits, not what your ingress logs. Many ingress controllers record request paths, headers and sometimes bodies, so check their access log format and retention before you enable verbose logging on the ingress or forward those logs to a shared store.

Disable the built-in admin user

The user management documentation recommends using the built-in admin user only for initial setup. Once SSO or local users are configured, set admin.enabled to false. Without this step, a password-based account remains reachable through the same published hostname, which widens the attack surface the ingress exposes.

Certificate and hostname ownership

The certificate presented at the ingress is the one clients trust, so its private key becomes a high-value asset. Assign an owner for issuance and renewal, restrict who can read the TLS secret in the Argo CD namespace, and confirm that the CLI and the UI use the same hostnames as the certificate subject names. Mismatched names tend to lead teams to disable verification rather than fix it.

Common questions about Argo CD TLS and certificates

Should I use TLS passthrough or TLS termination for Argo CD?

Use passthrough when you want the Argo CD API server to hold its own certificate and keep TLS end to end, and termination when your ingress or load balancer must own certificates, inspect traffic or follow a central certificate process. Passthrough lets one hostname serve both the web UI and the gRPC CLI, because argocd-server detects the protocol on port 443. Termination is common in organizations that already manage certificates at the edge, but it adds configuration: the API server must run without TLS, and the gRPC and HTTPS paths usually need separate hostnames. Decide this before building the ingress, since switching later changes DNS, certificates and CLI login instructions.

Is running Argo CD with server.insecure safe?

It is safe only when the hop between your ingress and argocd-server stays on a network path you control and the public edge still uses TLS. With termination, setting server.insecure to "true" in argocd-cmd-params-cm turns off TLS on the API server, so plaintext traffic reaches the pod. Keep that internal hop inside the cluster network, restrict who can reach the service directly with network policies, and confirm that your ingress re-encrypts traffic if policy requires it. Argo CD's security documentation says it uses TLS for traffic between its own components, so an unencrypted internal hop is a deliberate exception that your security team should approve and record.

Why do I usually need separate gRPC and HTTPS hostnames?

Most ingress controllers route HTTP/2 gRPC and HTTPS web traffic differently, so a terminating ingress often needs one hostname and rule set for the web UI and another for the CLI's gRPC traffic. Passthrough avoids this because the TLS connection reaches argocd-server unchanged and the server sorts out the protocol itself. With termination, the ingress must handle HTTP/2 for gRPC, and many controllers and load balancers need a separate backend protocol setting or service for it. Check your controller's documentation for gRPC support and HTTP/2 backends before you choose a single hostname, and test argocd login from a real workstation.

When does the Argo CD CLI need grpc-web?

Use the --grpc-web option when the CLI cannot reach the server over gRPC on HTTP/2, which is common when an ingress, proxy or load balancer in front of Argo CD does not pass HTTP/2 through to the backend. The CLI then falls back from gRPC over HTTP/2 to HTTP/1.1. It is a workaround for the path between the CLI and the server, not a replacement for a correct gRPC route. Prefer fixing the ingress so gRPC works natively, and treat grpc-web as an interim option for specific CI runners or users behind restrictive proxies. Document the flag in your runbooks so that teams know why it is there.

What drives the effort and cost of setting up Argo CD TLS?

The main drivers are the ingress controller or load balancer you already run, the number of hostnames and routes you need, how certificates are issued and renewed, and how many people and pipelines use the CLI. A single passthrough hostname with an existing certificate process is the smallest case. Termination with separate gRPC and HTTPS hostnames, internal certificate authorities, SSO callbacks on the same host, and a change-controlled certificate process adds configuration and testing. Your effort also grows with the number of clusters that expose their own Argo CD instances. Ask any quote to list each hostname, certificate source, renewal method, controller version and test plan.

Can my team do this work alone, or do we need outside help?

A team with working Kubernetes, ingress and certificate experience can usually configure a single passthrough or termination setup from the official ingress guide, provided it tests gRPC login, the web UI and certificate renewal before go-live. Outside help is most useful when the environment is complex: several controllers, segmented networks, internal certificate authorities, air-gapped clusters, or strict audit evidence requirements. DeployOpen implements, hardens and documents self-hosted platforms in infrastructure you control, under written, fixed scope. It does not issue audit reports or certifications, so certificate evidence still goes to your auditor. Confirm the exact steps with your ingress vendor and your own environment before you commit.

How DeployOpen works on this

DeployOpen plans, implements, hardens, documents and supports self-hosted open-source platforms inside your own infrastructure, including the TLS path in front of Argo CD. We agree the termination model, hostnames, certificate sources and verification steps in writing before any change reaches your clusters.

How we scope

  • Record which ingress controller, load balancer or Gateway API implementation sits in front of Argo CD and who operates it.
  • Agree whether TLS ends at passthrough or termination, and list the hostnames for the UI and the gRPC CLI.
  • Document the certificate authority, issuance method, renewal owner and trust chain your CLI and automation clients must accept.

How we build

  • Configure argocd-server for the chosen model, including server.insecure in argocd-cmd-params-cm only where ingress terminates TLS.
  • Set up certificate issuance and renewal in your cluster or PKI, and test expiry alerts before go-live.
  • Verify CLI login over gRPC and the grpc-web fallback, then test the UI, SSO redirects and webhook callbacks through the final path.

How we hand over

  • Deliver the ingress manifests, certificate resources, values changes and a written runbook kept under your version control.
  • Include a test script that checks each hostname, protocol path, certificate chain and renewal date after any change.
  • Walk your platform and security teams through the decisions, trade-offs and known limits of the chosen TLS design.

How we support

  • Ongoing support, upgrades and continuous testing are available as a retainer, so TLS settings are rechecked with each Argo CD release.
  • Re-verify the ingress path after Argo CD upgrades, controller changes and certificate rotations that your team asks us to handle.
  • Confirm with your vendors and standards bodies which certificate and ingress capabilities your versions support before relying on them.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.