> ## Documentation Index
> Fetch the complete documentation index at: https://hoopdev-docs-improve-idp-sso-pages.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Kubernetes

This page provides instructions on how to configure the Helm chart to install Hoop in any cloud provider.

## Quick Start

<Tabs>
  <Tab title="Standard Installation">
    This is the standard installation to evaluate Hoop. We recommend it for Proof of Concepts or testing environments.

    <Warning>
      On this installation, clients establishes connections without TLS, which is subject to interception.
      Make sure to deploy it over a secure network and use it only with non production resources.
    </Warning>

    <Steps>
      <Step title="Deploy the Gateway">
        ```sh theme={null}
        VERSION=$(curl -s https://releases.hoop.dev/release/latest.txt)
        helm upgrade hoop --install oci://ghcr.io/hoophq/helm-charts/hoop-chart --version $VERSION \
          --namespace hoopdev --create-namespace \
          --set postgres.enabled=true \
          --set defaultAgent.enabled=true \
          --set dataMasking.enabled=true \
          --set config.POSTGRES_DB_URI=postgres://root:default-pwd@hoopgateway-pg/postgres?sslmode=disable \
          --set config.API_URL=http://localhost:8009
        ```
      </Step>

      <Step title="Access it">
        1. Forward the hoopgateway service ports to your local machine to access the WebApp

        ```sh theme={null}
        kubectl port-forward service/hoopgateway 8009:8009 8010:8010 -n hoopdev
        ```

        2. [Visit the Webapp at http://127.0.0.1:8009/login](http://127.0.0.1:8009/login)

        <Note>
          The default installation method install a Postgres database with Host mounted storage.
          In case the node is decommissioned, all data will be lost.

          For more durable setups, use a Persistent Volume by providing the option below:

          * `--set postgres.storageClassName=<your-storage-class>`
        </Note>
      </Step>
    </Steps>
  </Tab>

  <Tab title="Secure Installation (TLS)">
    This is production is recommended for production, it terminate the TLS directly on the gateway for all existent protocols.

    <Note>
      For the purpose of this quick start, we're going to generate certificate signed by a CA unstruted party with `openssl`. However,
      the process of installing and configuring should be the same when issuing certificates from trusted party organizations.

      Ensure you have all required certificate files from Step 1 if you've already issued them through your PKI provider.
    </Note>

    <Steps>
      <Step title="Obtain a certificate for your domain">
        1. Expose the domain name of the Hoop Gateway instance

        ```sh theme={null}
        export DOMAIN_HOSTNAME=<your-hoop-gateway-domain-name-goes-here>
        ```

        2. Generate and sign your certificates with `openssl`

        ```sh theme={null}
        mkdir ./tls && cd ./tls
        openssl genrsa -out ca.key 4096
        openssl req -x509 -new -nodes -key ca.key -sha256 -days 1826 -out ca.crt -subj '/CN=MyOrg CA/C=AT/ST=Vienna/L=Vienna/O=MyOrg'
        openssl req -new -nodes -out server.csr -newkey rsa:4096 -keyout server.key -subj '/CN=Gateway/C=AT/ST=Vienna/L=Vienna/O=MyOrg'
        # create a v3 ext file for SAN properties
        cat > server.v3.ext <<EOF
        authorityKeyIdentifier=keyid,issuer
        basicConstraints=CA:FALSE
        keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
        subjectAltName = @alt_names
        [alt_names]
        DNS.1 = $DOMAIN_HOSTNAME
        IP.1 = 127.0.0.1
        EOF

        openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 730 -sha256 -extfile server.v3.ext
        ```

        2. Join the Root Certificate Authority with your certificate

        ```sh theme={null}
        cat server.crt ca.crt > server-full.crt
        ```

        <Note>
          When issuing certificates from a trusted party, make sure to include the Root and Intermediate certificates if they are provided.
        </Note>

        3. (optional) Add the Root CA to your system keychain

        This process is needed only when creating certificates from an unstrusted third party (openssl).
        It will make your system to trust the certificated issued by the Root Certificate Authority.

        **Make sure to have the following files in your local filesystem before proceeding to the next step:**

        * `server.crt` - File containing the server certificate
        * `ca.crt` - File containing the Root with Intermediate CA's if it's available
        * `server.key` - File containing the private key of your certificate
      </Step>

      <Step title="Generate the values.yaml file">
        After having the certificates in your working directory, encode the following files in base64 to generate the `values.yaml` file.
        The certificates will be used to serve the ports exposed in the gateway securely with TLS

        <Note>
          Make sure that the DNS name of your domain match with the certificate.
          In this example we'll be exposing all ports with a load balancer from AWS.
          Make sure to adapt this recipe to deploy a network load balancer in your own infra-structure with the proper annontations.
        </Note>

        1. Export the domain hostname and the certificate files

        ```sh theme={null}
        export DOMAIN_HOSTNAME=<your-hoop-gateway-domain-name-goes-here>
        export TLS_KEY_ENC=$(cat server.key | base64)
        export TLS_CERT_ENC=$(cat server-full.crt | base64)
        ```

        2. Generate the `values.yaml` file

        ```sh theme={null}
        cat - > values.yaml <<EOF
        # gateway base configuration
        config:
          POSTGRES_DB_URI: 'postgres://root:default-pwd@hoopgateway-pg/postgres?sslmode=disable'
          API_URL: "https://$DOMAIN_HOSTNAME"
          TLS_KEY: "base64://$TLS_KEY_ENC"
          TLS_CERT: "base64://$TLS_CERT_ENC"

        # uses a local Postgres database with Host mounted stored
        # use a distinct storage class name for more durable setups 
        postgres:
          enabled: true
          storageClassName: null

        # enable data masking
        dataMasking:
          enabled: true
          mode: best-effort

        # an agent will be deployed along with the gateway
        defaultAgent:
          enabled: true
          grpcScheme: grpcs
          grpcHost: 127.0.0.1:8010
          grpcSkipVerify: true
          imageTag: latest

        # exposes a network load balancer for all services
        proxyService:
          enabled: true
          annotations:
            service.beta.kubernetes.io/aws-load-balancer-type: nlb
            service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
          ports:
          - name: api
            port: 443
            targetPort: 8009
          - name: grpcs
            port: 8443
            targetPort: 8010
          - name: pgproxy
            port: 15432
            targetPort: 15432
          - name: sshproxy
            port: 12222
            targetPort: 12222
          - name: rdpproxy
            port: 13389
            targetPort: 13389
        EOF
        ```
      </Step>

      <Step title="Deploy it">
        ```sh theme={null}
        VERSION=$(curl -s https://releases.hoop.dev/release/latest.txt)
        helm upgrade hoop \
          --install oci://ghcr.io/hoophq/helm-charts/hoop-chart --version $VERSION \
          --namespace hoopdev \
          --create-namespace \
          --values values.yaml
        ```
      </Step>

      <Step title="Access it">
        <Tabs>
          <Tab title="Via Public URL">
            1. Obtain the address of your load balancer by issuing the command below

            ```sh theme={null}
            kubectl get svc -n hoopdev hoopgateway-proxy \
              -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
            ```

            2. Create a CNAME record for your `$DOMAIN_HOSTNAME` in your DNS pointing to this address.
            3. Visit the Webapp at `https://$DOMAIN_NAME/login`
          </Tab>

          <Tab title="Via Port Forward">
            If you want to validate the installation without exposing the gateway to the public internet,
            use the `kubectl` to port forward the ports into your local machine.

            ```sh theme={null}
            kubectl port-forward service/hoopgateway 8009:8009 8010:8010 -n hoopdev
            ```

            Then [Visit the Webapp at http://127.0.0.1:8009/login](http://127.0.0.1:8009/login)

            <Note>
              To test the native protocols directly on the gateway, make sure to export the ports below:

              * `ssh/12222`
              * `postgres/15432`
              * `rdp/13389`
            </Note>
          </Tab>
        </Tabs>
      </Step>
    </Steps>
  </Tab>
</Tabs>

## Helm Install

To install the latest version in a new namespace (example: `hoopdev`). Issue the command below:

```bash theme={null}
VERSION=$(curl -s https://releases.hoop.dev/release/latest.txt)
helm upgrade --install hoop \
  oci://ghcr.io/hoophq/helm-charts/hoop-chart --version $VERSION \
  -f values.yaml \
  --namespace hoopdev
```

### Overwriting or passing new attributes

It is possible to add new attributes or overwrite an attribute from a base `values.yaml` file.
In the example below a default agent is deployed as a sidecar container and with a using a specific version of the gateway.

```bash theme={null}
helm upgrade --install hoop \
  oci://ghcr.io/hoophq/helm-charts/hoop-chart --version $VERSION \
  -f values.yaml \
  --set defaultAgent.enabled=true \
  --set image.gw.tag=1.45.0
```

## Database Configuration

Hoop uses Postgres as the backend storage of all data in the system.
It uses the schema `private` to create the tables of the system.
The command below creates a database and a user with privileges to access the database and the required schema.

```sql theme={null}
CREATE DATABASE hoopdb;
CREATE USER hoopuser WITH ENCRYPTED PASSWORD 'my-secure-password';
-- switch to the created database
\c hoopdb
CREATE SCHEMA IF NOT EXISTS private;
GRANT ALL PRIVILEGES ON DATABASE hoopdb TO hoopuser;
GRANT ALL PRIVILEGES ON SCHEMA public to hoopuser;
GRANT ALL PRIVILEGES ON SCHEMA private to hoopuser;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO hoopuser;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA private TO hoopuser;
```

<Note>
  In case of using a password with special characters, make sure to url encode it properly when setting the connection string.
</Note>

Use these values to assemble the configuration for POSTGRES\_DB\_URI:

* `POSTGRES_DB_URI=postgres://hoopuser:<passwd>@<db-host>:5432/hoopdb`

<Tip>
  Make sure to include `?sslmode=disable` option in the Postgres connection string in case your database setup doesn't support TLS.
</Tip>

## Agent Deployment

<AccordionGroup>
  <Accordion title="values.yaml (minimal)">
    ```yaml theme={null}
      config:
        HOOP_KEY: '<agent-key-dsn>'
    ```
  </Accordion>

  <Accordion title="values.yaml (full)">
    ```yaml theme={null}
    # base configuration
    config:
      HOOP_KEY: '<agent-key-dsn>'
      LOG_ENCODING: 'json' # json|console
      LOG_LEVEL: 'info' # debug|info|warn|error
      LOG_GRPC: '0' # 0|1|2

    # image default configuration
    image:
      repository: hoophq/hoopdev
      pullPolicy: Always
      tag: latest

    # define extra secret configuration to load as environment variables
    extraSecret: {}

    # -- Deployment strategy
    deploymentStrategy:
      type: Recreate

    # -- CPU/Memory resource requests/limits
    resources: {}
    #   limits:
    #     cpu: 1024m
    #     memory: 1Gi
    #   requests:
    #     cpu: 1024m
    #     memory: 1Gi

    # -- Node labels for pod assignment
    nodeSelector: {}

    # -- Toleration labels for pod assignment
    tolerations: []

    # -- Affinity settings for pod assignment
    affinity: {}

    ```
  </Accordion>
</AccordionGroup>

### Helm

Make sure you have helm installed in your machine. Check [Helm installation page](https://helm.sh/docs/intro/install/)

```bash theme={null}
VERSION=$(curl -s https://releases.hoop.dev/release/latest.txt)
helm upgrade --install hoopagent \
	oci://ghcr.io/hoophq/helm-charts/hoopagent-chart --version $VERSION \
	--set "config.HOOP_KEY=<AUTH-KEY>"
```

### Using Helm Manifests

```bash theme={null}
VERSION=$(curl -s https://releases.hoop.dev/release/latest.txt)
helm template hoopagent \
  oci://ghcr.io/hoophq/helm-charts/hoopagent-chart --version $VERSION \
  --set 'config.HOOP_KEY=<AUTH-KEY>' \
  --set 'image.tag=1.36.16' \
  --set 'extraSecret=AWS_REGION=us-east-1'
```

<Warning>
  Starting from version **1.21.9**, there is only one way to configure the agent key, which is by using the `config.HOOP_KEY` configuration. This requires creating a key in a DSN format in the API. To use legacy options, use the Helm chart version **1.21.4**.
</Warning>

### Standalone Deployment

<AccordionGroup>
  <Accordion title="deployment.yaml">
    ```yaml theme={null}
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hoopagent
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: hoopagent
      template:
        metadata:
          labels:
            app: hoopagent
        spec:
          containers:
          - name: hoopagent
            image: hoophq/hoopdev
            env:
            - name: HOOP_KEY
              value: '<AUTH-KEY>'
    ```
  </Accordion>
</AccordionGroup>

### Sidecar Container

<AccordionGroup>
  <Accordion title="deployment.yaml">
    ```yaml theme={null}
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: myapp
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: myapp
        template:
          metadata:
            labels:
              app: myapp
          spec:
            containers:
            - name: myapp
              image: myapp
              ports:
              - containerPort: 8000
                name: http
                protocol: TCP
            - name: hoopagent
              image: hoophq/hoopdev
              env:
              - name: HOOP_KEY
                value: '<AUTH-KEY>'
    ```
  </Accordion>
</AccordionGroup>

## Gateway Chart Configuration

Check the [environment variables section](/setup/configuration/env-vars) for more information about the configuration of the section `config`.
Example:

```yaml theme={null}
config:
  POSTGRES_DB_URI: 'postgres://user:pwd@host:port/db'
  (...)
```

### TLS Configuration

Starting with version **1.45+**,we are transitioning to expose native protocols directly on the Gateway, eliminating the need to forward ports locally through the Hoop Command Line.

This new approach requires the Gateway to terminate TLS connections, ensuring secure protocol negotiation and protecting data in transit.

* To deploy the gateway with a valid certificate, make to define the environment variables `TLS_KEY` and `TLS_CERT`.

<Note>
  The certificate file may contain the **Root** and **Intermediate CA's** as well.
  Make sure to include them in the proper order, the example below show how the certificates must be generated:

  ```
  <SERVER-CERT>
  <INTERMEDIATE-CA>
  <ROOT_CA>
  ```
</Note>

<Tabs>
  <Tab title="Base64 Encoded Configuration">
    ```yaml theme={null}
    config:
      TLS_KEY: 'base64://<pem-encoded-private-key>'
      TLS_CERT: 'base64://<pem-encoded-full-certificate>'
    ```

    Example of how to encode the files:

    <Note>
      Use the output of each value to configure the attributes above.
    </Note>

    ```sh theme={null}
    echo "base64://$(cat /tmp/tls/server.key |base64)
    echo "base64://$(cat /tmp/tls/server.crt |base64)
    ```
  </Tab>

  <Tab title="Path Based Configuration">
    ```yaml theme={null}
    config:
      TLS_KEY: 'file:///path/to/server.key'
      TLS_CERT: 'file:///path/to/server.crt'
    ```
  </Tab>
</Tabs>

### Authentication

<Tabs>
  <Tab title="Local Authentication">
    Local Authentication manages users and passwords locally and sign JWT access tokens to users.

    ```yaml theme={null}
    config:
      POSTGRES_DB_URI: 'postgres://<user>:<pwd>@<db-host>:<port>/<dbname>'
      API_URL: 'https://hoopdev.yourdomain.tld'
    ```
  </Tab>

  <Tab title="Oauth2/OIDC Authentication">
    The Oauth2/OIDC authentication integrates with any identity provider that support these protocols. The users are managed on the identity provider.

    ```yaml theme={null}
    config:
      POSTGRES_DB_URI: 'postgres://<user>:<pwd>@<db-host>:<port>/<dbname>'
      API_URL: 'https://hoopdev.yourdomain.tld'
      IDP_ISSUER: 'https://idp-issuer-url'
      IDP_CLIENT_ID: 'client-id'
      IDP_CLIENT_SECRET: 'client-secret'
      IDP_AUDIENCE: ''
      IDP_CUSTOM_SCOPES: ''
      IDP_GROUPS_CLAIM: ''
    ```

    <Warning>
      The authentication configuration is now handled via Webapp or defined via API directly,
      the environment variable with the prefix `IDP_` are deprecated and will be removed in upcoming releases.
    </Warning>
  </Tab>
</Tabs>

### Default Database

The chart allows deploying a Postgres database as part of the installation.

```yaml theme={null}
# -- Enable PostgreSQL
postgres:
  # it default to host mount when enabled
  enabled: false

  # set a storage class name to use a Persistent Volume Claim
  storageClassName: null

  # -- Size of PVC
  size: 10Gi
  # annotations: {}
```

<Tip>
  It creates a default Service resource named `hoopgateway-pg`.
  This service name could be used in the `POSTGRES_DB_URI` configuration.
</Tip>

### Persistence

We recommend using SSD for large deployments, it will help speed the I/O when handling many concurrent requests.
The following example shows how to enable a 50GB persistent volume when using AWS/EKS.

```yaml theme={null}
persistence:
  # -- Use persistent volume for write ahead log sessions
  enabled: true
  storageClassName: gp2

  # -- Size of persistent volume claim
  size: 50Gi
```

### Ingress Configuration

This section covers the ingress configuration. The gateway requires exposing the ports **HTTP/8009** and **HTTP2/8010.**
The ingress configuration establishes these two differing configurations based on the [ingress controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/) in use.

<Tabs>
  <Tab title="AWS ALB">
    AWS Load Balancer Controller is a controller to help manage Elastic Load Balancers for a Kubernetes cluster.

    <Steps>
      <Step title="Deploy the AWS Load Balancer Controller">
        * [https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/deploy/installation/](https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/deploy/installation/)
      </Step>

      <Step title="Ingress Configuration">
        ```yaml theme={null}
        # HTTP/8009 - API / WebApp
        ingressApi:
          enabled: true
          # the public DNS name
          host: 'hoopgateway.yourdomain.tld'
          # the ingress class, in this case alb
          ingressClassName: 'alb'
          annotations:
            # uses the ACM service to use a valid public certificate issued by AWS
            alb.ingress.kubernetes.io/certificate-arn: 'arn:aws:acm:...'
            # the group name allows resuing the same lb for both protocols (HTTP/gRPC)
            alb.ingress.kubernetes.io/group.name: 'hoopdev'
            alb.ingress.kubernetes.io/healthcheck-path: '/'
            alb.ingress.kubernetes.io/healthcheck-protocol: 'HTTP'
            alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS": 443}]'
            alb.ingress.kubernetes.io/scheme: 'internet-facing'
            alb.ingress.kubernetes.io/ssl-redirect: '443'
            alb.ingress.kubernetes.io/target-type: 'ip'

        # HTTP/8010 - gRPC Service
        ingressGrpc:
          enabled: true
          # the public DNS name
          host: 'hoopdev.yourdomain.tld'
          # the ingress class, in this case alb
          ingressClassName: 'alb'
          annotations:
            # configures the type of the protocol
            alb.ingress.kubernetes.io/backend-protocol-version: 'GRPC'
            # the certificate could be reused for the same protocol
            alb.ingress.kubernetes.io/certificate-arn: 'arn:aws:acm:...'
            # the group name allows resuing the same lb for both protocols (HTTP/gRPC)
            alb.ingress.kubernetes.io/group.name: 'hoopdev'
            alb.ingress.kubernetes.io/healthcheck-path: '/'
            alb.ingress.kubernetes.io/healthcheck-protocol: 'HTTP'
            alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS": 8443}]'
            alb.ingress.kubernetes.io/scheme: 'internet-facing'
            alb.ingress.kubernetes.io/target-type: 'ip'
        ```
      </Step>
    </Steps>
  </Tab>

  <Tab title="Nginx Ingress Controller">
    The Nginx Ingress Controller is an Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer.

    <Steps>
      <Step title="Deploy Nginx Ingress Controller">
        * [https://kubernetes.github.io/ingress-nginx/deploy/](https://kubernetes.github.io/ingress-nginx/deploy/)
      </Step>

      <Step title="Ingress Configuration">
        * TLS Termination on Nginx

        ```yaml theme={null}
        ingressApi:
          enabled: true
          host: hoopgateway.yourdomain.tld
          ingressClassName: 'nginx'
          tls:
          - hosts:
              - hoopgateway.yourdomain.tld
            secretName: hoopserver-tls

        ingressGrpc:
          enabled: true
          host: "hoop-grpc.yourdomain.tld"
          ingressClassName: 'nginx'
          annotations:
            nginx.ingress.kubernetes.io/backend-protocol: GRPC
            nginx.ingress.kubernetes.io/proxy-body-size: '0'
          tls:
          - hosts:
              - hoop-grpc.yourdomain.tld
            secretName: hoopserver-tls
        ```

        <Note>
          This setup requires deploying a network load balancer (Layer 4) in your cloud provider.
        </Note>
      </Step>
    </Steps>
  </Tab>

  <Tab title="GCP Classic ALB">
    The external Application Load Balancer is a proxy-based Layer 7 load balancer that enables you to run and scale your services behind a single external IP address.
    [See the Architecture Overview](https://cloud.google.com/load-balancing/docs/https).

    <Note>
      The Classic ALB doesn't support establishing HTTP/2 connections with the Hoop Gateway without TLS.
      To accommodate this requirement, TLS certificates must be configured both on the ALB and within the Hoop Gateway
      to establish secure communication between these components.
    </Note>

    <Steps>
      <Step title="Deploy GKE Cluster">
        * Deploy GKE Cluster by following the [GKE Quick Start guide](https://cloud.google.com/kubernetes-engine/docs/quickstarts/create-cluster)
        * Obtain access to [your cluster via kubectl](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl)
      </Step>

      <Step title="Export your domain name">
        ```sh theme={null}
        export DOMAIN_HOSTNAME=hoopgateway.yourdomain.tld
        ```
      </Step>

      <Step title="Setup Certificates">
        <AccordionGroup>
          <Accordion title="Generate self signed certificates">
            <Note>
              This step is not necessary if you already have certificates issued by a known entity.
            </Note>

            * Create the CA private key

            ```sh theme={null}
            mkdir -p /tmp/hoopdemo && cd /tmp/hoopdemo
            openssl genrsa -aes256 -out ca.key 2048
            ```

            * Create the Root Certificate Authority (CA)

            ```sh theme={null}
            openssl req -x509 -new -nodes -key ca.key -sha256 -days 1826 -out ca.crt -subj '/CN=Hoop Root CA'
            ```

            * Creating the Certificate Signing Request (CSR)

            ```sh theme={null}
            openssl req -new -nodes -out server.csr -newkey rsa:2048 -keyout server.key -subj '/CN=HoopGateway'
            ```

            * Sign the Certificate

            ```sh theme={null}
            # create a v3 ext file for SAN properties
            cat > server.v3.ext << EOF
            authorityKeyIdentifier=keyid,issuer
            basicConstraints=CA:FALSE
            keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
            subjectAltName = @alt_names
            [alt_names]
            DNS.1 = $DOMAIN_HOSTNAME
            DNS.2 = grpc-$DOMAIN_HOSTNAME
            IP.1 = 127.0.0.1
            EOF
            ```

            ```sh theme={null}
            openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
                -CAcreateserial -out server.crt -days 730 -sha256 -extfile server.v3.ext
            ```

            <Note>
              Make sure to install the Root Certificate Authority in your browser/system
              to be able to visit the Web App. The browser won't allow access due to HSTS policy.

              This step is not necessary when using certificates issued by a known entity.
            </Note>
          </Accordion>
        </AccordionGroup>

        * Export the certificates for setting up the helm chart

        ```sh theme={null}
        export TLS_CA="base64://$(cat ca.crt | base64)"
        export TLS_KEY="base64://$(cat server.key | base64)"
        export TLS_CERT="base64://$(cat server.crt | base64)"
        ```

        <Note>
          The format `base64://<inline-certificate-content>` allows configuring inline TLS to Hoop Gateway.
        </Note>

        * Upload them into GCP

        ```sh theme={null}
        gcloud compute ssl-certificates create hoopserver \
          --certificate=server.crt \
          --private-key=server.key
        ```

        <Tip>
          We recommend using a valid certificates for production workloads.
        </Tip>
      </Step>

      <Step title="Configure DNS and create static Global IP Addresses">
        * Create the ip addresses of the load balancer

        ```sh theme={null}
        gcloud compute addresses create hoopgateway-grpc --global
        gcloud compute addresses create hoopgateway-http --global
        ```

        * Associate the ip address to the proper domains in your DNS provider

        | Public DNS              | IP Address                      |
        | ----------------------- | ------------------------------- |
        | `$DOMAIN_HOSTNAME`      | `<hoopgateway-http-ip-address>` |
        | `grpc-$DOMAIN_HOSTNAME` | `<hoopgateway-grpc-ip-address>` |
      </Step>

      <Step title="Deploy the Hoop Gateway">
        * Create a namespace

        ```sh theme={null}
        kubectl create ns hoopdemo
        ```

        <AccordionGroup>
          <Accordion title="Deploy a Postgres Server">
            * Generate Specification

            ```sh theme={null}
            cat - > /tmp/hoopdemo/postgres-spec.yaml <<EOF
            apiVersion: apps/v1
            kind: Deployment
            metadata:
              name: postgres
            spec:
              replicas: 1
              selector:
                matchLabels:
                  app: postgres
              strategy:
                type: Recreate
              template:
                metadata:
                  labels:
                    app: postgres
                spec:
                  containers:
                  - env:
                    - name: POSTGRES_USER
                      value: root
                    - name: POSTGRES_PASSWORD
                      value: 1a2b3c4d
                    - name: POSTGRES_DB
                      value: hoopdb
                    image: postgres
                    name: postgres
                    ports:
                    - containerPort: 5432
                      name: pg
                      protocol: TCP
            ---
            apiVersion: v1
            kind: Service
            metadata:
              name: postgres
            spec:
              ports:
              - name: postgres
                port: 5432
                protocol: TCP
                targetPort: 5432
              selector:
                app: postgres
            EOF
            ```

            * Deploy it

            ```sh theme={null}
            kubectl apply -n hoopdemo -f /tmp/hoopdemo/postgres-spec.yaml
            ```
          </Accordion>
        </AccordionGroup>

        <AccordionGroup>
          <Accordion title="Deploy the Hoop Gateway">
            * Generate Helm values.yaml

            ```sh theme={null}
            cat - > /tmp/hoopdemo/values.yaml <<EOF
            config:
              POSTGRES_DB_URI: 'postgres://root:1a2b3c4d@postgres:5432/hoopdb?sslmode=disable'
              API_URL: "https://$DOMAIN_HOSTNAME"
              GRPC_URL: "grpcs://grpc-$DOMAIN_HOSTNAME:443"

            defaultAgent:
              enabled: true
              grpcHost: grpc-$DOMAIN_HOSTNAME:443

            mainService:
              annotations:
                beta.cloud.google.com/backend-config: '{"ports": {"http": "hoopgateway-http", "grpc": "hoopgateway-grpc"}}'
                cloud.google.com/app-protocols: '{"http":"HTTPS", "grpc":"HTTP2"}'
              httpBackendConfig:
                healthCheckType: HTTPS
              grpcBackendConfig:
                healthCheckType: HTTPS
                # it avoids clients being dropped for being idle
                timeoutSec: 259200

            ingressApi:
              enabled: true
              host: "$DOMAIN_HOSTNAME"
              annotations:
                kubernetes.io/ingress.class: 'gce'
                ingress.gcp.kubernetes.io/pre-shared-cert: 'hoopserver'
                kubernetes.io/ingress.global-static-ip-name: 'hoopgateway-http'

            ingressGrpc:
              enabled: true
              host: "grpc-$DOMAIN_HOSTNAME"
              annotations:
                kubernetes.io/ingress.class: 'gce'
                ingress.gcp.kubernetes.io/pre-shared-cert: 'hoopserver'
                kubernetes.io/ingress.global-static-ip-name: 'hoopgateway-grpc'
            EOF
            ```

            * Deploy it

            ```sh theme={null}
            helm upgrade --install hoop oci://ghcr.io/hoophq/helm-charts/hoop-chart -f values.yaml --namespace hoopdemo \
              --set config.TLS_CA=$TLS_CA \
              --set config.TLS_KEY=$TLS_KEY \
              --set config.TLS_CERT=$TLS_CERT
            ```
          </Accordion>
        </AccordionGroup>
      </Step>

      <Step title="Access It">
        * Wait for all resources to be provisioned, the command below will show any pending operations on GCP

        ```sh theme={null}
        gcloud compute operations list |grep -v DONE
        ```

        * Check if the ip addresses are displayed when listing the ingresses

        ```sh theme={null}
        kubectl get ing -n hoopdemo
        ```

        ```
        NAME               CLASS    HOSTS                   ADDRESS
        hoopgateway-grpc   <none>   grpc-$DOMAIN_HOSTNAME   XX.X.XX.XXX
        hoopgateway-web    <none>   $DOMAIN_HOSTNAME        XX.XXX.XXX.X
        ```

        * Navigate to the Web Application public URL at `https://$DOMAIN_HOSTNAME/login`
      </Step>
    </Steps>
  </Tab>
</Tabs>

### Service Configuration

The chart allows configuring the main service that exposes the service of the gateway.

```yaml theme={null}
mainService:
  annotations:
    beta.cloud.google.com/backend-config: '{"ports": {"http": "hoopgateway-http", "grpc": "hoopgateway-grpc"}}'
    cloud.google.com/app-protocols: '{"http":"HTTPS", "grpc":"HTTP2"}'
  httpBackendConfig:
    healthCheckType: HTTPS
  grpcBackendConfig:
    healthCheckType: HTTPS
    timeoutSec: 259200
```

* `mainService.annotations` attribute allows adding an annotation mapping. GCP for instance configure aspects of how to configure the load balancer based on this configuration
* `mainService.httpBackendConfig`: It creates the `hoopgateway-http` Backend Config resource when this attribute is set. It could be referenced using the annotation `beta.cloud.google.com/backend-config`
  * `healthCheckType`: The protocol used by probe systems for health checking. The BackendConfig only supports creating health checks using the HTTP, HTTPS, or HTTP2
  * `timeoutSec`: The amount of time in seconds that Google Cloud waits for a response to a probe.
* `mainService.grpcBackendConfig`: It creates the `hoopgateway-grpc` Backend Config resource when this attribute is set. It could be referenced using the annotation `beta.cloud.google.com/backend-config`
  * `healthCheckType`: The protocol used by probe systems for health checking. The BackendConfig only supports creating health checks using the HTTP, HTTPS, or HTTP2
  * `timeoutSec`: The amount of time in seconds that Google Cloud waits for a response to a probe.

For more information of how to configure these resources, refer to the [GCP Ingress Configuration Reference](https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-configuration#associating_backendconfig_with_your_ingress).

### Computing Resources

The helm-chart defaults to 1vCPU and 1GB, which is suitable for evaluation purposes only.
For production setups, we recommend allocating at least 8GB/4vCPU to the gateway process.

```yaml theme={null}
resources:
  gw:
    limits:
      cpu: 4096m
      memory: 8Gi
    requests:
      cpu: 4096m
      memory: 8Gi
```

### Image Configuration

By default, the latest version of all images is used. If you want to use a specific image or pin the versions, use the `image` attribute section.

```yaml theme={null}
image:
  gw:
    repository: hoophq/hoop
    pullPolicy: Always
    tag: latest
```

### Default Agent Sidecar

Adding this section will deploy a default agent as a sidecar container.

```yaml theme={null}
defaultAgent:
  enabled: true
  imageRepository: 'hoophq/hoopdev'
  imageTag: latest
  imagePullPolicy: Always
  grpcHost: 127.0.0.1:8009
```

<Note>
  The `grpcHost` allows configuring the host to connect when starting the agent.
  In case the gateway has TLS configured (`TLS_CA` env set), the host must match the certificate SAN.
</Note>

### Data Masking Configuration

To enable the Data Masking feature, you need to configure the `dataMasking` section in your `values.yaml` file.
It will deploy the [Microsoft Presidio](https://github.com/microsoft/presidio) on the same namespace as the Hoop Gateway.

```yaml theme={null}
dataMasking:
  enabled: true
  # https://github.com/microsoft/presidio/releases
  version: latest
  # best-effort | strict
  mode: best-effort

  analyzer:
    resources:
      limits:
        cpu: 512m
        memory: 1024Mi
      requests:
        cpu: 256m
        memory: 1024Mi

  anonymizer:
    resources:
      limits:
        cpu: 512m
        memory: 512Mi
      requests:
        cpu: 256m
        memory: 512Mi
```

<Note>
  When the `dataMasking` attribute is enabled, it takes control over the following configurations:

  * DLP\_MODE
  * DLP\_PROVIDER
  * MSPRESIDIO\_ANALYZER\_URL
  * MSPRESIDIO\_ANONYMIZER\_URL
  * GOOGLE\_APPLICATION\_CREDENTIALS\_JSON

  If you need more control over the deployment, we recommend using a standalone helm chart of Presidio.
  See more details above in the [Presidio Deployment](#presidio-deployment) section.
</Note>

<Tip>
  This attribute is available starting from version **1.37.16+** of the Helm chart.
</Tip>

### Node Selector

This configuration describes a pod that has a node selector, `disktype: ssd`. This means that the pod will get scheduled on a node that has a `disktype=ssd` label.

See [this documentation](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/) for more information.

```yaml theme={null}
# -- Node labels for pod assignment
nodeSelector:
  disktype: ssd
```

### Tolerations

See this article explaining how to configure [tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)

```yaml theme={null}
# -- Toleration labels for pod assignment
tolerations:
- effect: NoExecute
  key: spot
  value: "true"
- effect: NoSchedule
  key: spot
  value: "true"
```

### Node Affinity

See [this article](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) explaining how to configure affinity and anti-affinity rules

```yaml theme={null}
# -- Affinity settings for pod assignment
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: topology.kubernetes.io/zone
          operator: In
          values:
          - antarctica-east1
          - antarctica-west1
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 1
      preference:
        matchExpressions:
        - key: another-node-label-key
          operator: In
          values:
          - another-node-label-value
```

## Presidio Deployment

The Data Masking feature uses Microsoft Presidio.
We provide a Helm chart that gives more control over the deployment.

```bash theme={null}
helm upgrade --install presidio \
  oci://ghcr.io/hoophq/helm-charts/presidio-chart --version v0.0.3 \
  -f values.yaml
```

<AccordionGroup>
  <Accordion title="values.yaml">
    ```yaml theme={null}

    # analyzer service configuration
    analyzer:
      replicas: 1
      imageRepository: mcr.microsoft.com/presidio-analyzer
      imagePullPolicy: Always
      # versions: https://github.com/microsoft/presidio/releases
      imageTag: latest
      resources:
        limits:
          cpu: 512m
          memory: 1024Mi
        requests:
          cpu: 256m
          memory: 1024Mi

      # -- Node labels for pod assignment
      nodeSelector: {}

      # -- Toleration labels for pod assignment
      tolerations: []

      # -- Affinity settings for pod assignment
      affinity: {}

    # anonymizer service configuration
    anonymizer:
      replicas: 1
      imageRepository: mcr.microsoft.com/presidio-anonymizer
      imagePullPolicy: Always
      # versions: https://github.com/microsoft/presidio/releases
      imageTag: latest
      resources:
        limits:
          cpu: 512m
          memory: 512Mi
        requests:
          cpu: 256m
          memory: 512Mi

      # -- Node labels for pod assignment
      nodeSelector: {}

      # -- Toleration labels for pod assignment
      tolerations: []

      # -- Affinity settings for pod assignment
      affinity: {}
    ```
  </Accordion>
</AccordionGroup>

The chart will create two services that are used in the gateway to configure the data masking feature:

* `presidio-analyzer` -  The analyzer service that detects PII data in text.
* `presidio-anonymizer` -  The anonymizer service that masks PII data in text

These services must be respectively configured in the Gateway with the following environment variables:

```conf theme={null}
DLP_PROVIDER=mspresidio
MSPRESIDIO_ANALYZER_URL=http://presidio-analyzer:3000
MSPRESIDIO_ANONYMIZER_URL=http://presidio-anonymizer:3000
```

For more information about new releases, consult the [Presidio Helm Chart repository](https://github.com/hoophq/presidio-helm).

### Presidio With Flair

<Note>
  Available under the agent version **1.37.22+** and the Helm Presidio Chart version **v0.0.2+**.
</Note>

We have a custom build of Presidio that leverages the use of [Flair](https://flairnlp.github.io/flair/), it provides better accuracy in detecting PII data.
To use this custom build, you could use our custom build of the Presidio Analyzer.

```yaml theme={null}
analyzer:
  replicas: 1
  imageRepository: hoophq/presidio-analyzer-flair
  imageTag: 0.0.3
  imagePullPolicy: Always
  resources:
    limits:
      cpu: 8192m
      memory: 16384Mi
    requests:
      cpu: 8192m
      memory: 16384Mi

# anonymizer service configuration
anonymizer:
  replicas: 1
  imageRepository: mcr.microsoft.com/presidio-anonymizer
  imagePullPolicy: Always
  resources:
    limits:
      cpu: 512m
      memory: 512Mi
    requests:
      cpu: 256m
      memory: 512Mi
```

<Warning>
  The custom build of Presidio Analyzer with Flair requires more resources than the default official image.
  We recommend allocating at least 8vCPU and 16GB to the analyzer process.
</Warning>

### Node Selector

<Note>
  Available on Helm Chart version **v0.0.3+**.
</Note>

This configuration describes a pod that has a node selector, `disktype: ssd`. This means that the pod will get scheduled on a node that has a `disktype=ssd` label.

See [this documentation](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/) for more information.

```yaml theme={null}
# -- Node labels for pod assignment
nodeSelector:
  disktype: ssd
```

### Tolerations

<Note>
  Available on Helm Chart version **v0.0.3+**.
</Note>

See this article explaining how to configure [tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)

```yaml theme={null}
# -- Toleration labels for pod assignment
tolerations:
- effect: NoExecute
  key: spot
  value: "true"
- effect: NoSchedule
  key: spot
  value: "true"
```

### Node Affinity

<Note>
  Available on Helm Chart version **v0.0.3+**.
</Note>

See [this article](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) explaining how to configure affinity and anti-affinity rules

```yaml theme={null}
# -- Affinity settings for pod assignment
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: topology.kubernetes.io/zone
          operator: In
          values:
          - antarctica-east1
          - antarctica-west1
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 1
      preference:
        matchExpressions:
        - key: another-node-label-key
          operator: In
          values:
          - another-node-label-value
```

## Generating Manifests

If you prefer using manifests over Helm, we recommend this approach. It allows you to track any modifications to the chart whenever a new version appears. You can apply a diff to your versioned files to identify what has been altered.

```bash theme={null}
VERSION=$(curl -s https://releases.hoop.dev/release/latest.txt)
helm template hoop \
  oci://ghcr.io/hoophq/helm-charts/hoop-chart --version $VERSION \
  -f values.yaml
```
