> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/argoproj/argo-cd/llms.txt
> Use this file to discover all available pages before exploring further.

# TLS Configuration

> Configure TLS certificates and encryption for all Argo CD components

Argo CD provides three inbound TLS endpoints that should be configured with proper certificates. By default, these endpoints use automatically generated, self-signed certificates.

## Quick Reference

### Certificate Configuration

| Component            | Secret Name              | Hot Reload         | Default Cert | Required SAN Entries                                          |
| -------------------- | ------------------------ | ------------------ | ------------ | ------------------------------------------------------------- |
| `argocd-server`      | `argocd-server-tls`      | ✅ Yes              | Self-signed  | External hostname (e.g., `argocd.example.com`)                |
| `argocd-repo-server` | `argocd-repo-server-tls` | ❌ Restart required | Self-signed  | `DNS:argocd-repo-server`, `DNS:argocd-repo-server.argocd.svc` |
| `argocd-dex-server`  | `argocd-dex-server-tls`  | ❌ Restart required | Self-signed  | `DNS:argocd-dex-server`, `DNS:argocd-dex-server.argocd.svc`   |

### Inter-Component TLS

| Connection                                                | Strict TLS Parameter              | Plain Text Parameter             | Default Behavior   |
| --------------------------------------------------------- | --------------------------------- | -------------------------------- | ------------------ |
| `argocd-server` → `argocd-repo-server`                    | `--repo-server-strict-tls`        | `--repo-server-plaintext`        | Non-validating TLS |
| `argocd-server` → `argocd-dex-server`                     | `--dex-server-strict-tls`         | `--dex-server-plaintext`         | Non-validating TLS |
| `argocd-application-controller` → `argocd-repo-server`    | `--repo-server-strict-tls`        | `--repo-server-plaintext`        | Non-validating TLS |
| `argocd-applicationset-controller` → `argocd-repo-server` | `--repo-server-strict-tls`        | `--repo-server-plaintext`        | Non-validating TLS |
| `argocd-notifications-controller` → `argocd-repo-server`  | `--argocd-repo-server-strict-tls` | `--argocd-repo-server-plaintext` | Non-validating TLS |

## Configuring argocd-server TLS

### Inbound TLS Options

Configure TLS parameters for the API server:

| Parameter         | Default                                                                 | Description                            |
| ----------------- | ----------------------------------------------------------------------- | -------------------------------------- |
| `--insecure`      | `false`                                                                 | Disables TLS completely                |
| `--tlsminversion` | `1.2`                                                                   | Minimum TLS version offered to clients |
| `--tlsmaxversion` | `1.3`                                                                   | Maximum TLS version offered to clients |
| `--tlsciphers`    | `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_RSA_WITH_AES_256_GCM_SHA384` | Colon-separated list of cipher suites  |

<CodeGroup>
  ```yaml Deployment Patch theme={null}
  apiVersion: apps/v1
  kind: Deployment
  metadata:
    name: argocd-server
    namespace: argocd
  spec:
    template:
      spec:
        containers:
        - name: argocd-server
          command:
          - argocd-server
          - --tlsminversion=1.2
          - --tlsmaxversion=1.3
  ```

  ```bash Helm Values theme={null}
  server:
    extraArgs:
    - --tlsminversion=1.2
    - --tlsmaxversion=1.3
  ```
</CodeGroup>

### Certificate Priority

Argo CD determines which certificate to use in this order:

<Steps>
  <Step title="argocd-server-tls Secret">
    **Recommended**: Dedicated TLS secret for argocd-server

    ```bash theme={null}
    kubectl create -n argocd secret tls argocd-server-tls \
      --cert=/path/to/cert.pem \
      --key=/path/to/key.pem
    ```

    <Info>This secret is safe to manage via third-party tools like cert-manager or Sealed Secrets.</Info>
  </Step>

  <Step title="argocd-secret Secret">
    **Deprecated**: Legacy location for TLS certificate

    Only used if `argocd-server-tls` doesn't exist. Not recommended for new deployments.
  </Step>

  <Step title="Auto-generated Certificate">
    If neither secret contains a certificate, Argo CD generates and persists a self-signed certificate in `argocd-secret`.
  </Step>
</Steps>

<Tip>
  Argo CD automatically detects changes to `argocd-server-tls` without requiring a restart.
</Tip>

### Using cert-manager

Automate certificate management with [cert-manager](https://cert-manager.io/):

<Tabs>
  <Tab title="Let's Encrypt">
    ```yaml theme={null}
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: argocd-server-tls
      namespace: argocd
    spec:
      secretName: argocd-server-tls
      issuerRef:
        name: letsencrypt-prod
        kind: ClusterIssuer
      dnsNames:
      - argocd.example.com
      duration: 2160h # 90 days
      renewBefore: 360h # 15 days
    ```
  </Tab>

  <Tab title="Internal CA">
    ```yaml theme={null}
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: argocd-server-tls
      namespace: argocd
    spec:
      secretName: argocd-server-tls
      issuerRef:
        name: internal-ca
        kind: ClusterIssuer
      commonName: argocd.example.internal
      dnsNames:
      - argocd.example.internal
      - argocd.argocd.svc
      - argocd.argocd.svc.cluster.local
      duration: 8760h # 1 year
      renewBefore: 720h # 30 days
    ```
  </Tab>
</Tabs>

## Configuring argocd-repo-server TLS

### Inbound TLS Options

| Parameter         | Default                                                                 | Description             |
| ----------------- | ----------------------------------------------------------------------- | ----------------------- |
| `--disable-tls`   | `false`                                                                 | Disables TLS completely |
| `--tlsminversion` | `1.2`                                                                   | Minimum TLS version     |
| `--tlsmaxversion` | `1.3`                                                                   | Maximum TLS version     |
| `--tlsciphers`    | `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_RSA_WITH_AES_256_GCM_SHA384` | Cipher suites           |

### Certificate Configuration

Create the `argocd-repo-server-tls` secret:

```bash theme={null}
kubectl create -n argocd secret tls argocd-repo-server-tls \
  --cert=/path/to/cert.pem \
  --key=/path/to/key.pem
```

<Warning>
  **Important**: The certificate must include the correct SAN entries:

  * `DNS:argocd-repo-server`
  * `DNS:argocd-repo-server.argocd.svc`
  * `DNS:argocd-repo-server.argocd.svc.cluster.local`
</Warning>

#### Self-Signed Certificates

If using a self-signed certificate, add the CA certificate:

<CodeGroup>
  ```bash Generate Self-Signed Cert theme={null}
  # Generate CA
  openssl genrsa -out ca.key 4096
  openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
    -subj "/CN=ArgoCD CA"

  # Generate server certificate
  openssl genrsa -out tls.key 2048
  openssl req -new -key tls.key -out tls.csr \
    -subj "/CN=argocd-repo-server" \
    -addext "subjectAltName=DNS:argocd-repo-server,DNS:argocd-repo-server.argocd.svc"

  openssl x509 -req -in tls.csr -CA ca.crt -CAkey ca.key \
    -CAcreateserial -out tls.crt -days 365 \
    -extfile <(printf "subjectAltName=DNS:argocd-repo-server,DNS:argocd-repo-server.argocd.svc")
  ```

  ```bash Create Secret with CA theme={null}
  kubectl create secret generic argocd-repo-server-tls \
    --from-file=tls.crt=tls.crt \
    --from-file=tls.key=tls.key \
    --from-file=ca.crt=ca.crt \
    -n argocd
  ```
</CodeGroup>

<Note>
  Unlike argocd-server, argocd-repo-server requires a pod restart to pick up certificate changes.
</Note>

### Enable Strict TLS Validation

By default, components use non-validating TLS connections to argocd-repo-server. To enable strict validation:

<Steps>
  <Step title="Create Persistent Certificate">
    Create the `argocd-repo-server-tls` secret as shown above.
  </Step>

  <Step title="Restart repo-server">
    ```bash theme={null}
    kubectl rollout restart deployment argocd-repo-server -n argocd
    ```
  </Step>

  <Step title="Enable Strict TLS">
    Add `--repo-server-strict-tls` parameter to connecting components:

    ```yaml theme={null}
    # For argocd-server
    spec:
      containers:
      - name: argocd-server
        command:
        - argocd-server
        - --repo-server-strict-tls

    # For argocd-application-controller
    spec:
      containers:
      - name: argocd-application-controller
        command:
        - argocd-application-controller
        - --repo-server-strict-tls

    # For argocd-applicationset-controller
    spec:
      containers:
      - name: argocd-applicationset-controller
        command:
        - argocd-applicationset-controller
        - --repo-server-strict-tls

    # For argocd-notifications-controller
    spec:
      containers:
      - name: argocd-notifications-controller
        command:
        - argocd-notifications-controller
        - --argocd-repo-server-strict-tls
    ```
  </Step>
</Steps>

<Warning>
  **Certificate Expiry**: Ensure certificates have adequate lifetime. When replacing certificates, all workloads must be restarted.
</Warning>

## Configuring argocd-dex-server TLS

### Inbound TLS Options

| Parameter       | Default | Description             |
| --------------- | ------- | ----------------------- |
| `--disable-tls` | `false` | Disables TLS completely |

### Certificate Configuration

Create the `argocd-dex-server-tls` secret:

```bash theme={null}
kubectl create -n argocd secret tls argocd-dex-server-tls \
  --cert=/path/to/cert.pem \
  --key=/path/to/key.pem
```

<Info>
  Similar to repo-server, include correct SAN entries:

  * `DNS:argocd-dex-server`
  * `DNS:argocd-dex-server.argocd.svc`
</Info>

### Enable Strict TLS Validation

<Steps>
  <Step title="Create Certificate">
    Create the `argocd-dex-server-tls` secret.
  </Step>

  <Step title="Restart dex-server">
    ```bash theme={null}
    kubectl rollout restart deployment argocd-dex-server -n argocd
    ```
  </Step>

  <Step title="Enable Strict TLS in argocd-server">
    ```yaml theme={null}
    spec:
      containers:
      - name: argocd-server
        command:
        - argocd-server
        - --dex-server-strict-tls
    ```
  </Step>
</Steps>

## Service Mesh / mTLS Configuration

In service mesh environments with sidecar proxies (e.g., Istio, Linkerd), you may want to disable TLS between Argo CD components and let the mesh handle encryption.

### Disable TLS to repo-server

<Steps>
  <Step title="Configure repo-server">
    Disable TLS and restrict to loopback:

    ```yaml theme={null}
    spec:
      containers:
      - name: argocd-repo-server
        command:
        - argocd-repo-server
        - --disable-tls
        - --listen=127.0.0.1
    ```

    <Info>Listening on localhost prevents direct network access while allowing sidecar communication.</Info>
  </Step>

  <Step title="Configure Clients">
    Set plaintext mode on all clients:

    ```yaml theme={null}
    # argocd-server, argocd-application-controller, argocd-applicationset-controller
    - --repo-server-plaintext

    # argocd-notifications-controller
    - --argocd-repo-server-plaintext
    ```
  </Step>

  <Step title="Configure Service Address">
    Point to sidecar proxy instead of direct service:

    ```yaml theme={null}
    - --repo-server=localhost:8081
    ```
  </Step>
</Steps>

### Disable TLS to dex-server

<Steps>
  <Step title="Configure dex-server">
    ```yaml theme={null}
    spec:
      containers:
      - name: argocd-dex-server
        command:
        - argocd-dex
        - rundex
        - --disable-tls
    ```
  </Step>

  <Step title="Configure argocd-server">
    ```yaml theme={null}
    spec:
      containers:
      - name: argocd-server
        command:
        - argocd-server
        - --dex-server-plaintext
        - --dex-server=localhost:5556
    ```
  </Step>
</Steps>

## Complete Configuration Examples

### Production Setup with cert-manager

<CodeGroup>
  ```yaml ClusterIssuer theme={null}
  apiVersion: cert-manager.io/v1
  kind: ClusterIssuer
  metadata:
    name: letsencrypt-prod
  spec:
    acme:
      server: https://acme-v02.api.letsencrypt.org/directory
      email: admin@example.com
      privateKeySecretRef:
        name: letsencrypt-prod
      solvers:
      - http01:
          ingress:
            class: nginx
  ```

  ```yaml Certificates theme={null}
  ---
  apiVersion: cert-manager.io/v1
  kind: Certificate
  metadata:
    name: argocd-server-tls
    namespace: argocd
  spec:
    secretName: argocd-server-tls
    issuerRef:
      name: letsencrypt-prod
      kind: ClusterIssuer
    dnsNames:
    - argocd.example.com
    duration: 2160h
    renewBefore: 360h
  ---
  apiVersion: cert-manager.io/v1
  kind: Certificate
  metadata:
    name: argocd-repo-server-tls
    namespace: argocd
  spec:
    secretName: argocd-repo-server-tls
    issuerRef:
      name: internal-ca
      kind: ClusterIssuer
    dnsNames:
    - argocd-repo-server
    - argocd-repo-server.argocd.svc
    - argocd-repo-server.argocd.svc.cluster.local
    duration: 8760h
    renewBefore: 720h
  ```

  ```yaml Deployment Patches theme={null}
  # Patch argocd-server
  kubectl patch deployment argocd-server -n argocd --type=json -p='[
    {
      "op": "add",
      "path": "/spec/template/spec/containers/0/command/-",
      "value": "--repo-server-strict-tls"
    },
    {
      "op": "add",
      "path": "/spec/template/spec/containers/0/command/-",
      "value": "--tlsminversion=1.2"
    }
  ]'

  # Patch argocd-application-controller
  kubectl patch statefulset argocd-application-controller -n argocd --type=json -p='[
    {
      "op": "add",
      "path": "/spec/template/spec/containers/0/command/-",
      "value": "--repo-server-strict-tls"
    }
  ]'
  ```
</CodeGroup>

### Internal PKI Setup

<Accordion title="Step-by-Step Internal PKI Configuration">
  1. **Create internal CA**
     ```bash theme={null}
     # Generate root CA
     openssl genrsa -out rootCA.key 4096
     openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 \
       -out rootCA.crt -subj "/CN=ArgoCD Internal CA"
     ```

  2. **Install CA as cluster resource**
     ```bash theme={null}
     kubectl create secret generic argocd-ca \
       --from-file=ca.crt=rootCA.crt \
       -n argocd
     ```

  3. **Configure cert-manager with internal CA**
     ```yaml theme={null}
     apiVersion: cert-manager.io/v1
     kind: ClusterIssuer
     metadata:
       name: internal-ca
     spec:
       ca:
         secretName: argocd-ca
     ```

  4. **Request certificates**
     Use the Certificate resources shown in previous examples.
</Accordion>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Certificate not picked up">
    **Symptom**: New certificate not being used

    **Solution**:

    * For `argocd-server`: Wait up to 60 seconds (hot reload)
    * For `argocd-repo-server` and `argocd-dex-server`: Restart pods
      ```bash theme={null}
      kubectl rollout restart deployment argocd-repo-server -n argocd
      kubectl rollout restart deployment argocd-dex-server -n argocd
      ```
  </Accordion>

  <Accordion title="TLS handshake errors">
    **Symptom**: `x509: certificate is valid for X, not Y`

    **Solution**: Ensure SAN entries match the DNS names used by clients:

    ```bash theme={null}
    # Check certificate SANs
    kubectl get secret argocd-repo-server-tls -n argocd -o json | \
      jq -r '.data["tls.crt"]' | base64 -d | \
      openssl x509 -noout -text | grep -A1 "Subject Alternative Name"
    ```
  </Accordion>

  <Accordion title="Self-signed certificate errors">
    **Symptom**: `x509: certificate signed by unknown authority`

    **Solutions**:

    1. Add `ca.crt` to the TLS secret
    2. Enable strict TLS validation with proper CA trust
    3. Or use `--repo-server-plaintext` if in service mesh
  </Accordion>

  <Accordion title="cert-manager not issuing">
    **Check certificate status**:

    ```bash theme={null}
    kubectl describe certificate argocd-server-tls -n argocd
    kubectl get certificaterequest -n argocd
    ```

    **Common issues**:

    * DNS not resolving for ACME challenges
    * Rate limiting from Let's Encrypt
    * Incorrect issuer configuration
  </Accordion>
</AccordionGroup>

## Best Practices

<CardGroup cols={2}>
  <Card title="Use cert-manager" icon="robot">
    Automate certificate lifecycle management and rotation
  </Card>

  <Card title="Enable Strict TLS" icon="shield-check">
    Validate certificates for inter-component communication
  </Card>

  <Card title="Monitor Expiry" icon="calendar-clock">
    Set up alerts for certificates expiring within 30 days
  </Card>

  <Card title="Use Strong Ciphers" icon="key">
    Configure TLS 1.2+ and modern cipher suites only
  </Card>
</CardGroup>

<Warning>
  Never commit private keys to Git. Use secret management solutions like Sealed Secrets or External Secrets Operator.
</Warning>

## Related Resources

<CardGroup cols={2}>
  <Card title="Security Overview" icon="shield" href="/security/overview">
    Comprehensive security architecture and threat model
  </Card>

  <Card title="Secrets Management" icon="key" href="/security/secrets-management">
    Best practices for managing secrets
  </Card>

  <Card title="Signed Releases" icon="file-signature" href="/security/signed-releases">
    Verify Argo CD artifacts and images
  </Card>

  <Card title="cert-manager" icon="certificate" href="https://cert-manager.io/">
    Kubernetes certificate management
  </Card>
</CardGroup>
