github.com/argoproj/argo-cd/v2@v2.10.9/docs/operator-manual/ingress.md (about)

     1  # Ingress Configuration
     2  
     3  Argo CD API server runs both a gRPC server (used by the CLI), as well as a HTTP/HTTPS server (used by the UI).
     4  Both protocols are exposed by the argocd-server service object on the following ports:
     5  
     6  * 443 - gRPC/HTTPS
     7  * 80 - HTTP (redirects to HTTPS)
     8  
     9  There are several ways how Ingress can be configured.
    10  
    11  ## [Ambassador](https://www.getambassador.io/)
    12  
    13  The Ambassador Edge Stack can be used as a Kubernetes ingress controller with [automatic TLS termination](https://www.getambassador.io/docs/latest/topics/running/tls/#host) and routing capabilities for both the CLI and the UI.
    14  
    15  The API server should be run with TLS disabled. Edit the `argocd-server` deployment to add the `--insecure` flag to the argocd-server command, or simply set `server.insecure: "true"` in the `argocd-cmd-params-cm` ConfigMap [as described here](server-commands/additional-configuration-method.md). Given the `argocd` CLI includes the port number in the request `host` header, 2 Mappings are required.
    16  
    17  ### Option 1: Mapping CRD for Host-based Routing
    18  ```yaml
    19  apiVersion: getambassador.io/v2
    20  kind: Mapping
    21  metadata:
    22    name: argocd-server-ui
    23    namespace: argocd
    24  spec:
    25    host: argocd.example.com
    26    prefix: /
    27    service: argocd-server:443
    28  ---
    29  apiVersion: getambassador.io/v2
    30  kind: Mapping
    31  metadata:
    32    name: argocd-server-cli
    33    namespace: argocd
    34  spec:
    35    # NOTE: the port must be ignored if you have strip_matching_host_port enabled on envoy
    36    host: argocd.example.com:443
    37    prefix: /
    38    service: argocd-server:80
    39    regex_headers:
    40      Content-Type: "^application/grpc.*$"
    41    grpc: true
    42  ```
    43  
    44  Login with the `argocd` CLI:
    45  
    46  ```shell
    47  argocd login <host>
    48  ```
    49  
    50  ### Option 2: Mapping CRD for Path-based Routing
    51  
    52  The API server must be configured to be available under a non-root path (e.g. `/argo-cd`). Edit the `argocd-server` deployment to add the `--rootpath=/argo-cd` flag to the argocd-server command.
    53  
    54  ```yaml
    55  apiVersion: getambassador.io/v2
    56  kind: Mapping
    57  metadata:
    58    name: argocd-server
    59    namespace: argocd
    60  spec:
    61    prefix: /argo-cd
    62    rewrite: /argo-cd
    63    service: argocd-server:443
    64  ```
    65  
    66  Login with the `argocd` CLI using the extra `--grpc-web-root-path` flag for non-root paths.
    67  
    68  ```shell
    69  argocd login <host>:<port> --grpc-web-root-path /argo-cd
    70  ```
    71  
    72  ## [Contour](https://projectcontour.io/)
    73  The Contour ingress controller can terminate TLS ingress traffic at the edge.
    74  
    75  The Argo CD API server should be run with TLS disabled. Edit the `argocd-server` Deployment to add the `--insecure` flag to the argocd-server container command, or simply set `server.insecure: "true"` in the `argocd-cmd-params-cm` ConfigMap [as described here](server-commands/additional-configuration-method.md).
    76  
    77  It is also possible to provide an internal-only ingress path and an external-only ingress path by deploying two instances of Contour: one behind a private-subnet LoadBalancer service and one behind a public-subnet LoadBalancer service. The private Contour deployment will pick up Ingresses annotated with `kubernetes.io/ingress.class: contour-internal` and the public Contour deployment will pick up Ingresses annotated with `kubernetes.io/ingress.class: contour-external`.
    78  
    79  This provides the opportunity to deploy the Argo CD UI privately but still allow for SSO callbacks to succeed.
    80  
    81  ### Private Argo CD UI with  Multiple Ingress Objects and BYO Certificate
    82  Since Contour Ingress supports only a single protocol per Ingress object, define three Ingress objects. One for private HTTP/HTTPS, one for private gRPC, and one for public HTTPS SSO callbacks.
    83  
    84  Internal HTTP/HTTPS Ingress:
    85  ```yaml
    86  apiVersion: networking.k8s.io/v1
    87  kind: Ingress
    88  metadata:
    89    name: argocd-server-http
    90    annotations:
    91      kubernetes.io/ingress.class: contour-internal
    92      ingress.kubernetes.io/force-ssl-redirect: "true"
    93  spec:
    94    rules:
    95    - host: internal.path.to.argocd.io
    96      http:
    97        paths:
    98        - path: /
    99          pathType: Prefix
   100          backend:
   101            service:
   102              name: argocd-server
   103              port:
   104                name: http
   105    tls:
   106    - hosts:
   107      - internal.path.to.argocd.io
   108      secretName: your-certificate-name
   109  ```
   110  
   111  Internal gRPC Ingress:
   112  ```yaml
   113  apiVersion: networking.k8s.io/v1
   114  kind: Ingress
   115  metadata:
   116    name: argocd-server-grpc
   117    annotations:
   118      kubernetes.io/ingress.class: contour-internal
   119  spec:
   120    rules:
   121    - host: grpc-internal.path.to.argocd.io
   122      http:
   123        paths:
   124        - path: /
   125          pathType: Prefix
   126          backend:
   127            service:
   128              name: argocd-server
   129              port:
   130                name: https
   131    tls:
   132    - hosts:
   133      - grpc-internal.path.to.argocd.io
   134      secretName: your-certificate-name
   135  ```
   136  
   137  External HTTPS SSO Callback Ingress:
   138  ```yaml
   139  apiVersion: networking.k8s.io/v1
   140  kind: Ingress
   141  metadata:
   142    name: argocd-server-external-callback-http
   143    annotations:
   144      kubernetes.io/ingress.class: contour-external
   145      ingress.kubernetes.io/force-ssl-redirect: "true"
   146  spec:
   147    rules:
   148    - host: external.path.to.argocd.io
   149      http:
   150        paths:
   151        - path: /api/dex/callback
   152          pathType: Prefix
   153          backend:
   154            service:
   155              name: argocd-server
   156              port:
   157                name: http
   158    tls:
   159    - hosts:
   160      - external.path.to.argocd.io
   161      secretName: your-certificate-name
   162  ```
   163  
   164  The argocd-server Service needs to be annotated with `projectcontour.io/upstream-protocol.h2c: "https,443"` to wire up the gRPC protocol proxying.
   165  
   166  The API server should then be run with TLS disabled. Edit the `argocd-server` deployment to add the
   167  `--insecure` flag to the argocd-server command, or simply set `server.insecure: "true"` in the `argocd-cmd-params-cm` ConfigMap [as described here](server-commands/additional-configuration-method.md).
   168  
   169  ## [kubernetes/ingress-nginx](https://github.com/kubernetes/ingress-nginx)
   170  
   171  ### Option 1: SSL-Passthrough
   172  
   173  Argo CD serves multiple protocols (gRPC/HTTPS) on the same port (443), this provides a
   174  challenge when attempting to define a single nginx ingress object and rule for the argocd-service,
   175  since the `nginx.ingress.kubernetes.io/backend-protocol` [annotation](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#backend-protocol)
   176  accepts only a single value for the backend protocol (e.g. HTTP, HTTPS, GRPC, GRPCS).
   177  
   178  In order to expose the Argo CD API server with a single ingress rule and hostname, the
   179  `nginx.ingress.kubernetes.io/ssl-passthrough` [annotation](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#ssl-passthrough)
   180  must be used to passthrough TLS connections and terminate TLS at the Argo CD API server.
   181  
   182  ```yaml
   183  apiVersion: networking.k8s.io/v1
   184  kind: Ingress
   185  metadata:
   186    name: argocd-server-ingress
   187    namespace: argocd
   188    annotations:
   189      nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
   190      nginx.ingress.kubernetes.io/ssl-passthrough: "true"
   191  spec:
   192    ingressClassName: nginx
   193    rules:
   194    - host: argocd.example.com
   195      http:
   196        paths:
   197        - path: /
   198          pathType: Prefix
   199          backend:
   200            service:
   201              name: argocd-server
   202              port:
   203                name: https
   204  ```
   205  
   206  The above rule terminates TLS at the Argo CD API server, which detects the protocol being used,
   207  and responds appropriately. Note that the `nginx.ingress.kubernetes.io/ssl-passthrough` annotation
   208  requires that the `--enable-ssl-passthrough` flag be added to the command line arguments to
   209  `nginx-ingress-controller`.
   210  
   211  #### SSL-Passthrough with cert-manager and Let's Encrypt
   212  
   213  ```yaml
   214  apiVersion: networking.k8s.io/v1
   215  kind: Ingress
   216  metadata:
   217    name: argocd-server-ingress
   218    namespace: argocd
   219    annotations:
   220      cert-manager.io/cluster-issuer: letsencrypt-prod
   221      nginx.ingress.kubernetes.io/ssl-passthrough: "true"
   222      # If you encounter a redirect loop or are getting a 307 response code
   223      # then you need to force the nginx ingress to connect to the backend using HTTPS.
   224      #
   225      nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
   226  spec:
   227    ingressClassName: nginx
   228    rules:
   229    - host: argocd.example.com
   230      http:
   231        paths:
   232        - path: /
   233          pathType: Prefix
   234          backend:
   235            service:
   236              name: argocd-server
   237              port:
   238                name: https
   239    tls:
   240    - hosts:
   241      - argocd.example.com
   242      secretName: argocd-server-tls # as expected by argocd-server
   243  ```
   244  
   245  ### Option 2: SSL Termination at Ingress Controller
   246  
   247  An alternative approach is to perform the SSL termination at the Ingress. Since an `ingress-nginx` Ingress supports only a single protocol per Ingress object, two Ingress objects need to be defined using the `nginx.ingress.kubernetes.io/backend-protocol` annotation, one for HTTP/HTTPS and the other for gRPC.
   248  
   249  Each ingress will be for a different domain (`argocd.example.com` and `grpc.argocd.example.com`). This requires that the Ingress resources use different TLS `secretName`s to avoid unexpected behavior.
   250  
   251  HTTP/HTTPS Ingress:
   252  ```yaml
   253  apiVersion: networking.k8s.io/v1
   254  kind: Ingress
   255  metadata:
   256    name: argocd-server-http-ingress
   257    namespace: argocd
   258    annotations:
   259      nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
   260      nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
   261  spec:
   262    ingressClassName: nginx
   263    rules:
   264    - http:
   265        paths:
   266        - path: /
   267          pathType: Prefix
   268          backend:
   269            service:
   270              name: argocd-server
   271              port:
   272                name: http
   273      host: argocd.example.com
   274    tls:
   275    - hosts:
   276      - argocd.example.com
   277      secretName: argocd-ingress-http
   278  ```
   279  
   280  gRPC Ingress:
   281  ```yaml
   282  apiVersion: networking.k8s.io/v1
   283  kind: Ingress
   284  metadata:
   285    name: argocd-server-grpc-ingress
   286    namespace: argocd
   287    annotations:
   288      nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
   289  spec:
   290    ingressClassName: nginx
   291    rules:
   292    - http:
   293        paths:
   294        - path: /
   295          pathType: Prefix
   296          backend:
   297            service:
   298              name: argocd-server
   299              port:
   300                name: https
   301      host: grpc.argocd.example.com
   302    tls:
   303    - hosts:
   304      - grpc.argocd.example.com
   305      secretName: argocd-ingress-grpc
   306  ```
   307  
   308  The API server should then be run with TLS disabled. Edit the `argocd-server` deployment to add the
   309  `--insecure` flag to the argocd-server command, or simply set `server.insecure: "true"` in the `argocd-cmd-params-cm` ConfigMap [as described here](server-commands/additional-configuration-method.md).
   310  
   311  The obvious disadvantage to this approach is that this technique requires two separate hostnames for
   312  the API server -- one for gRPC and the other for HTTP/HTTPS. However it allows TLS termination to
   313  happen at the ingress controller.
   314  
   315  
   316  ## [Traefik (v2.2)](https://docs.traefik.io/)
   317  
   318  Traefik can be used as an edge router and provide [TLS](https://docs.traefik.io/user-guides/grpc/) termination within the same deployment.
   319  
   320  It currently has an advantage over NGINX in that it can terminate both TCP and HTTP connections _on the same port_ meaning you do not require multiple hosts or paths.
   321  
   322  The API server should be run with TLS disabled. Edit the `argocd-server` deployment to add the `--insecure` flag to the argocd-server command or set `server.insecure: "true"` in the `argocd-cmd-params-cm` ConfigMap [as described here](server-commands/additional-configuration-method.md).
   323  
   324  ### IngressRoute CRD
   325  ```yaml
   326  apiVersion: traefik.containo.us/v1alpha1
   327  kind: IngressRoute
   328  metadata:
   329    name: argocd-server
   330    namespace: argocd
   331  spec:
   332    entryPoints:
   333      - websecure
   334    routes:
   335      - kind: Rule
   336        match: Host(`argocd.example.com`)
   337        priority: 10
   338        services:
   339          - name: argocd-server
   340            port: 80
   341      - kind: Rule
   342        match: Host(`argocd.example.com`) && Headers(`Content-Type`, `application/grpc`)
   343        priority: 11
   344        services:
   345          - name: argocd-server
   346            port: 80
   347            scheme: h2c
   348    tls:
   349      certResolver: default
   350  ```
   351  
   352  ## AWS Application Load Balancers (ALBs) And Classic ELB (HTTP Mode)
   353  AWS ALBs can be used as an L7 Load Balancer for both UI and gRPC traffic, whereas Classic ELBs and NLBs can be used as L4 Load Balancers for both.
   354  
   355  When using an ALB, you'll want to create a second service for argocd-server. This is necessary because we need to tell the ALB to send the GRPC traffic to a different target group then the UI traffic, since the backend protocol is HTTP2 instead of HTTP1.
   356  
   357  ```yaml
   358  apiVersion: v1
   359  kind: Service
   360  metadata:
   361    annotations:
   362      alb.ingress.kubernetes.io/backend-protocol-version: HTTP2 #This tells AWS to send traffic from the ALB using HTTP2. Can use GRPC as well if you want to leverage GRPC specific features
   363    labels:
   364      app: argogrpc
   365    name: argogrpc
   366    namespace: argocd
   367  spec:
   368    ports:
   369    - name: "443"
   370      port: 443
   371      protocol: TCP
   372      targetPort: 8080
   373    selector:
   374      app.kubernetes.io/name: argocd-server
   375    sessionAffinity: None
   376    type: NodePort
   377  ```
   378  
   379  Once we create this service, we can configure the Ingress to conditionally route all `application/grpc` traffic to the new HTTP2 backend, using the `alb.ingress.kubernetes.io/conditions` annotation, as seen below. Note: The value after the . in the condition annotation _must_ be the same name as the service that you want traffic to route to - and will be applied on any path with a matching serviceName.
   380  
   381  ```yaml
   382    apiVersion: networking.k8s.io/v1
   383    kind: Ingress
   384    metadata:
   385      annotations:
   386        alb.ingress.kubernetes.io/backend-protocol: HTTPS
   387        # Use this annotation (which must match a service name) to route traffic to HTTP2 backends.
   388        alb.ingress.kubernetes.io/conditions.argogrpc: |
   389          [{"field":"http-header","httpHeaderConfig":{"httpHeaderName": "Content-Type", "values":["application/grpc"]}}]
   390        alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
   391      name: argocd
   392      namespace: argocd
   393    spec:
   394      rules:
   395      - host: argocd.argoproj.io
   396        http:
   397          paths:
   398          - path: /
   399            backend:
   400              service:
   401                name: argogrpc
   402                port:
   403                  number: 443
   404            pathType: Prefix
   405          - path: /
   406            backend:
   407              service:
   408                name: argocd-server
   409                port:
   410                  number: 443
   411            pathType: Prefix
   412      tls:
   413      - hosts:
   414        - argocd.argoproj.io
   415  ```
   416  
   417  ## [Istio](https://www.istio.io)
   418  You can put Argo CD behind Istio using following configurations. Here we will achive both serving Argo CD behind istio and using subpath on Istio
   419  
   420  First we need to make sure that we can run Argo CD with subpath (ie /argocd). For this we have used install.yaml from argocd project as is
   421  
   422  ```bash
   423  curl -kLs -o install.yaml https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
   424  ```
   425  
   426  save following file as kustomization.yml
   427  
   428  ```yaml
   429  apiVersion: kustomize.config.k8s.io/v1beta1
   430  kind: Kustomization
   431  resources:
   432  - ./install.yaml
   433  
   434  patches:
   435  - path: ./patch.yml
   436  ``` 
   437  
   438  And following lines as patch.yml
   439  
   440  ```yaml
   441  # Use --insecure so Ingress can send traffic with HTTP
   442  # --bashref /argocd is the subpath like https://IP/argocd
   443  # env was added because of https://github.com/argoproj/argo-cd/issues/3572 error
   444  ---
   445  apiVersion: apps/v1
   446  kind: Deployment
   447  metadata:
   448   name: argocd-server
   449  spec:
   450   template:
   451     spec:
   452       containers:
   453       - args:
   454         - /usr/local/bin/argocd-server
   455         - --staticassets
   456         - /shared/app
   457         - --redis
   458         - argocd-redis-ha-haproxy:6379
   459         - --insecure
   460         - --basehref
   461         - /argocd
   462         - --rootpath
   463         - /argocd
   464         name: argocd-server
   465         env:
   466         - name: ARGOCD_MAX_CONCURRENT_LOGIN_REQUESTS_COUNT
   467           value: "0"
   468  ```
   469  
   470  After that install Argo CD  (there should be only 3 yml file defined above in current directory )
   471  
   472  ```bash
   473  kubectl apply -k ./ -n argocd --wait=true
   474  ```
   475  
   476  Be sure you create secret for Isito ( in our case secretname is argocd-server-tls on argocd Namespace). After that we create Istio Resources
   477  
   478  ```yaml
   479  apiVersion: networking.istio.io/v1alpha3
   480  kind: Gateway
   481  metadata:
   482    name: argocd-gateway
   483    namespace: argocd
   484  spec:
   485    selector:
   486      istio: ingressgateway
   487    servers:
   488    - port:
   489        number: 80
   490        name: http
   491        protocol: HTTP
   492      hosts:
   493      - "*"
   494      tls:
   495       httpsRedirect: true
   496    - port:
   497        number: 443
   498        name: https
   499        protocol: HTTPS
   500      hosts:
   501      - "*"
   502      tls:
   503        credentialName: argocd-server-tls
   504        maxProtocolVersion: TLSV1_3
   505        minProtocolVersion: TLSV1_2
   506        mode: SIMPLE
   507        cipherSuites:
   508          - ECDHE-ECDSA-AES128-GCM-SHA256
   509          - ECDHE-RSA-AES128-GCM-SHA256
   510          - ECDHE-ECDSA-AES128-SHA
   511          - AES128-GCM-SHA256
   512          - AES128-SHA
   513          - ECDHE-ECDSA-AES256-GCM-SHA384
   514          - ECDHE-RSA-AES256-GCM-SHA384
   515          - ECDHE-ECDSA-AES256-SHA
   516          - AES256-GCM-SHA384
   517          - AES256-SHA
   518  ---
   519  apiVersion: networking.istio.io/v1alpha3
   520  kind: VirtualService
   521  metadata:
   522    name: argocd-virtualservice
   523    namespace: argocd
   524  spec:
   525    hosts:
   526    - "*"
   527    gateways:
   528    - argocd-gateway
   529    http:
   530    - match:
   531      - uri:
   532          prefix: /argocd
   533      route:
   534      - destination:
   535          host: argocd-server
   536          port:
   537            number: 80
   538  ```
   539  
   540  And now we can browse http://{{ IP }}/argocd (it will be rewritten to https://{{ IP }}/argocd
   541  
   542  
   543  ## Google Cloud load balancers with Kubernetes Ingress
   544  
   545  You can make use of the integration of GKE with Google Cloud to deploy Load Balancers using just Kubernetes objects.
   546  
   547  For this we will need these five objects:
   548  - A Service
   549  - A BackendConfig
   550  - A FrontendConfig
   551  - A secret with your SSL certificate
   552  - An Ingress for GKE
   553  
   554  If you need detail for all the options available for these Google integrations, you can check the [Google docs on configuring Ingress features](https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features)
   555  
   556  ### Disable internal TLS
   557  
   558  First, to avoid internal redirection loops from HTTP to HTTPS, the API server should be run with TLS disabled.
   559  
   560  Edit the `--insecure` flag in the `argocd-server` command of the argocd-server deployment, or simply set `server.insecure: "true"` in the `argocd-cmd-params-cm` ConfigMap [as described here](server-commands/additional-configuration-method.md).
   561  
   562  ### Creating a service
   563  
   564  Now you need an externally accessible service. This is practically the same as the internal service Argo CD has, but with Google Cloud annotations. Note that this service is annotated to use a [Network Endpoint Group](https://cloud.google.com/load-balancing/docs/negs) (NEG) to allow your load balancer to send traffic directly to your pods without using kube-proxy, so remove the `neg` annotation it that's not what you want.
   565  
   566  The service:
   567  
   568  ```yaml
   569  apiVersion: v1
   570  kind: Service
   571  metadata:
   572    name: argocd-server
   573    namespace: argocd
   574    annotations:
   575      cloud.google.com/neg: '{"ingress": true}'
   576      cloud.google.com/backend-config: '{"ports": {"http":"argocd-backend-config"}}'
   577  spec:
   578    type: ClusterIP
   579    ports:
   580    - name: http
   581      port: 80
   582      protocol: TCP
   583      targetPort: 8080
   584    selector:
   585      app.kubernetes.io/name: argocd-server
   586  ```
   587  
   588  ### Creating a BackendConfig
   589  
   590  See that previous service referencing a backend config called `argocd-backend-config`? So lets deploy it using this yaml:
   591  
   592  ```yaml
   593  apiVersion: cloud.google.com/v1
   594  kind: BackendConfig
   595  metadata:
   596    name: argocd-backend-config
   597    namespace: argocd
   598  spec:
   599    healthCheck:
   600      checkIntervalSec: 30
   601      timeoutSec: 5
   602      healthyThreshold: 1
   603      unhealthyThreshold: 2
   604      type: HTTP
   605      requestPath: /healthz
   606      port: 8080
   607  ```
   608  
   609  It uses the same health check as the pods.
   610  
   611  ### Creating a FrontendConfig
   612  
   613  Now we can deploy a frontend config with an HTTP to HTTPS redirect:
   614  
   615  ```yaml
   616  apiVersion: networking.gke.io/v1beta1
   617  kind: FrontendConfig
   618  metadata:
   619    name: argocd-frontend-config
   620    namespace: argocd
   621  spec:
   622    redirectToHttps:
   623      enabled: true
   624  ```
   625  
   626  ---
   627  !!! note
   628  
   629      The next two steps (the certificate secret and the Ingress) are described supposing that you manage the certificate yourself, and you have the certificate and key files for it. In the case that your certificate is Google-managed, fix the next two steps using the [guide to use a Google-managed SSL certificate](https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs#creating_an_ingress_with_a_google-managed_certificate).
   630  
   631  ---
   632  
   633  ### Creating a certificate secret
   634  
   635  We need now to create a secret with the SSL certificate we want in our load balancer. It's as easy as executing this command on the path you have your certificate keys stored:
   636  
   637  ```
   638  kubectl -n argocd create secret tls secret-yourdomain-com \
   639    --cert cert-file.crt --key key-file.key
   640  ```
   641  
   642  ### Creating an Ingress
   643  
   644  And finally, to top it all, our Ingress. Note the reference to our frontend config, the service, and to the certificate secret.
   645  
   646  ---
   647  !!! note
   648  
   649     GKE clusters running versions earlier than `1.21.3-gke.1600`, [the only supported value for the pathType field](https://cloud.google.com/kubernetes-engine/docs/how-to/load-balance-ingress#creating_an_ingress) is `ImplementationSpecific`. So you must check your GKE cluster's version. You need to use different YAML depending on the version.
   650  
   651  ---
   652  
   653  If you use the version earlier than `1.21.3-gke.1600`, you should use the following Ingress resource:
   654  ```yaml
   655  apiVersion: networking.k8s.io/v1
   656  kind: Ingress
   657  metadata:
   658    name: argocd
   659    namespace: argocd
   660    annotations:
   661      networking.gke.io/v1beta1.FrontendConfig: argocd-frontend-config
   662  spec:
   663    tls:
   664      - secretName: secret-example-com
   665    rules:
   666      - host: argocd.example.com
   667        http:
   668          paths:
   669          - pathType: ImplementationSpecific
   670            path: "/*"   # "*" is needed. Without this, the UI Javascript and CSS will not load properly
   671            backend:
   672              service:
   673                name: argocd-server
   674                port:
   675                  number: 80
   676  ```
   677  
   678  If you use the version `1.21.3-gke.1600` or later, you should use the following Ingress resource:
   679  ```yaml
   680  apiVersion: networking.k8s.io/v1
   681  kind: Ingress
   682  metadata:
   683    name: argocd
   684    namespace: argocd
   685    annotations:
   686      networking.gke.io/v1beta1.FrontendConfig: argocd-frontend-config
   687  spec:
   688    tls:
   689      - secretName: secret-example-com
   690    rules:
   691      - host: argocd.example.com
   692        http:
   693          paths:
   694          - pathType: Prefix
   695            path: "/"
   696            backend:
   697              service:
   698                name: argocd-server
   699                port:
   700                  number: 80
   701  ```
   702  
   703  As you may know already, it can take some minutes to deploy the load balancer and become ready to accept connections. Once it's ready, get the public IP address for your Load Balancer, go to your DNS server (Google or third party) and point your domain or subdomain (i.e. argocd.example.com) to that IP address.
   704  
   705  You can get that IP address describing the Ingress object like this:
   706  
   707  ```
   708  kubectl -n argocd describe ingresses argocd | grep Address
   709  ```
   710  
   711  Once the DNS change is propagated, you're ready to use Argo with your Google Cloud Load Balancer
   712  
   713  ## Authenticating through multiple layers of authenticating reverse proxies
   714  
   715  Argo CD endpoints may be protected by one or more reverse proxies layers, in that case, you can provide additional headers through the `argocd` CLI `--header` parameter to authenticate through those layers.
   716  
   717  ```shell
   718  $ argocd login <host>:<port> --header 'x-token1:foo' --header 'x-token2:bar' # can be repeated multiple times
   719  $ argocd login <host>:<port> --header 'x-token1:foo,x-token2:bar' # headers can also be comma separated
   720  ```
   721  ## ArgoCD Server and UI Root Path (v1.5.3)
   722  
   723  Argo CD server and UI can be configured to be available under a non-root path (e.g. `/argo-cd`).
   724  To do this, add the `--rootpath` flag into the `argocd-server` deployment command:
   725  
   726  ```yaml
   727  spec:
   728    template:
   729      spec:
   730        name: argocd-server
   731        containers:
   732        - command:
   733          - /argocd-server
   734          - --repo-server
   735          - argocd-repo-server:8081
   736          - --rootpath
   737          - /argo-cd
   738  ```
   739  NOTE: The flag `--rootpath` changes both API Server and UI base URL.
   740  Example nginx.conf:
   741  
   742  ```
   743  worker_processes 1;
   744  
   745  events { worker_connections 1024; }
   746  
   747  http {
   748  
   749      sendfile on;
   750  
   751      server {
   752          listen 443;
   753  
   754          location /argo-cd/ {
   755              proxy_pass         https://localhost:8080/argo-cd/;
   756              proxy_redirect     off;
   757              proxy_set_header   Host $host;
   758              proxy_set_header   X-Real-IP $remote_addr;
   759              proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
   760              proxy_set_header   X-Forwarded-Host $server_name;
   761              # buffering should be disabled for api/v1/stream/applications to support chunked response
   762              proxy_buffering off;
   763          }
   764      }
   765  }
   766  ```
   767  Flag ```--grpc-web-root-path ``` is used to provide a non-root path (e.g. /argo-cd)
   768  
   769  ```shell
   770  $ argocd login <host>:<port> --grpc-web-root-path /argo-cd
   771  ```
   772  
   773  ## UI Base Path
   774  
   775  If the Argo CD UI is available under a non-root path (e.g. `/argo-cd` instead of `/`) then the UI path should be configured in the API server.
   776  To configure the UI path add the `--basehref` flag into the `argocd-server` deployment command:
   777  
   778  ```yaml
   779  spec:
   780    template:
   781      spec:
   782        name: argocd-server
   783        containers:
   784        - command:
   785          - /argocd-server
   786          - --repo-server
   787          - argocd-repo-server:8081
   788          - --basehref
   789          - /argo-cd
   790  ```
   791  
   792  NOTE: The flag `--basehref` only changes the UI base URL. The API server will keep using the `/` path so you need to add a URL rewrite rule to the proxy config.
   793  Example nginx.conf with URL rewrite:
   794  
   795  ```
   796  worker_processes 1;
   797  
   798  events { worker_connections 1024; }
   799  
   800  http {
   801  
   802      sendfile on;
   803  
   804      server {
   805          listen 443;
   806  
   807          location /argo-cd {
   808              rewrite /argo-cd/(.*) /$1  break;
   809              proxy_pass         https://localhost:8080;
   810              proxy_redirect     off;
   811              proxy_set_header   Host $host;
   812              proxy_set_header   X-Real-IP $remote_addr;
   813              proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
   814              proxy_set_header   X-Forwarded-Host $server_name;
   815              # buffering should be disabled for api/v1/stream/applications to support chunked response
   816              proxy_buffering off;
   817          }
   818      }
   819  }
   820  ```