# Deploy Immuta without Elasticsearch

{% hint style="warning" %}
**Feature availability**

If you deploy Immuta without Elasticsearch, several core services and features will be unavailable. See the [Deployment requirements page](/2024.2/self-managed-deployment/deployment-requirements.md) for details.
{% endhint %}

The guides below outline how to deploy Immuta without Elasticsearch.

{% tabs %}
{% tab title="Managed Public Cloud" %}
This is a guide on how to deploy Immuta on Kubernetes in the following managed public cloud providers:

* Amazon Web Services (AWS)
* Microsoft Azure
* Google Cloud Platform (GCP)

**Prerequisites**

The following cloud-managed services must be provisioned before proceeding:

* Amazon Web Services (AWS): [Amazon RDS for PostgreSQL](https://docs.aws.amazon.com/rds/)
* Microsoft Azure: [Azure Database for PostgreSQL](https://learn.microsoft.com/en-us/azure/postgresql/)
* Google Cloud Platform (GCP): [Google Cloud SQL for PostgreSQL](https://cloud.google.com/sql/docs/postgres)

**Validation**

1. The PostgreSQL instance's hostname/FQDN is [resolvable from within the Kubernetes cluster](/2024.2/self-managed-deployment/troubleshooting.md).
2. The PostgreSQL instance is [accepting connections](/2024.2/self-managed-deployment/troubleshooting.md#postgresql).

**Authenticate with OCI registry**

{% hint style="warning" %}
**Helm chart availability**

The deprecated Immuta Helm chart (IHC) is not available from ocir.immuta.com.
{% endhint %}

Copy the snippet below and replace the placeholder text with the credentials provided to you by your customer success manager:

```shell
echo <token> | helm registry login --password-stdin --username <username> ocir.immuta.com
```

**Setup**

1. Create a Kubernetes namespace named `immuta` for Immuta.

   ```shell
   kubectl create namespace immuta
   ```
2. Switch to namespace `immuta`.

   ```shell
   kubectl config set-context --current --namespace=immuta
   ```
3. Create a container registry pull secret. Your credentials to authenticate with ocir.immuta.com can be viewed in your user profile at [support.immuta.com](https://support.immuta.com).

   ```shell
   kubectl create secret docker-registry immuta-oci-registry \
       --docker-server=https://ocir.immuta.com \
       --docker-username="<username>" \
       --docker-password="<token>" \
       --docker-email=support@immuta.com
   ```

**PostgreSQL**

{% hint style="info" %}
**Connecting to the database**

There are numerous ways to connect to a PostgreSQL database. This step demonstrates how to connect by creating an ephemeral Kubernetes pod.
{% endhint %}

1. Connect to the database as superuser (postgres) by creating an ephemeral container inside the Kubernetes cluster. A shell prompt will not be displayed after executing the `kubectl run` command outlined below. Wait 5 seconds, and then proceed by entering a password.

   ```shell
   kubectl run pgclient \
       --stdin \
       --tty \
       --rm \
       --image docker.io/bitnami/postgresql -- \
       psql --host <postgres-fqdn> --username postgres --port 5432 --password
   ```
2. Create an `immuta` role and database.

   ```sql
   CREATE ROLE immuta with login encrypted password '<postgres-password>';

   GRANT immuta TO CURRENT_USER;

   CREATE DATABASE immuta OWNER immuta;

   GRANT all ON DATABASE immuta TO immuta;
   ALTER ROLE immuta SET search_path TO bometadata,public;
   ```
3. Revoke privileges from `CURRENT_USER` as they're no longer required.

   ```sql
   REVOKE immuta FROM CURRENT_USER;
   ```
4. Enable the `pgcrypto` extension.

   ```sql
   \c immuta
   CREATE EXTENSION pgcrypto;
   ```
5. Type `\q`, and then press `Enter` to exit.

**Install Immuta**

This section demonstrates how to deploy Immuta using the Immuta Enterprise Helm chart once the prerequisite cloud-managed services are configured.

1. Create a Helm values file named `immuta-values.yaml` with the following content:

   ```yaml
   global:
     imageRegistry: ocir.immuta.com
     imagePullSecrets:
       - name: immuta-oci-registry
     imageRepositoryMap:
       immuta/immuta-service: stable/immuta-service
       immuta/immuta-db: stable/immuta-db
       immuta/immuta-fingerprint: stable/immuta-fingerprint
       immuta/audit-service: stable/audit-service
       immuta/audit-export-cronjob: stable/audit-export-cronjob
       immuta/classify-service: stable/classify-service
       immuta/cache: stable/cache

   audit:
     enabled: false

   secure:
     ingress:
       enabled: false
       tls: false
     extraEnvVars:
       - name: FeatureFlag_AuditService
         value: "false"
       - name: FeatureFlag_detect
         value: "false"
       - name: FeatureFlag_auditLegacyViewHide
         value: "false"

     postgresql:
       host: <postgres-fqdn>
       port: 5432
       database: immuta
       username: immuta
       password: <postgres-password>
       ssl: true
   ```
2. Update all [placeholder values](/2024.2/self-managed-deployment/conventions.md) in the `immuta-values.yaml` file.

{% hint style="warning" %}
**Avoid these special characters in generated passwords**

whitespace, `$`, `&`, `:`, `\`, `/`, `'`
{% endhint %}

3. Deploy Immuta.

   ```shell
   helm install immuta immuta/immuta-enterprise \
       --values immuta-values.yaml
   ```

**Validation**

1. Wait for all pods in the namespace to become ready.

   ```shell
   kubectl wait --for=condition=Ready pods --all
   ```
2. Determine the name of the Secure service.

   ```shell
   kubectl get service --selector "app.kubernetes.io/component=secure" --output template='{{ .metadata.name }}'
   ```
3. Listen on local port `8080`, forwarding TCP traffic to the Secure service's port named `http`.

   ```shell
   kubectl port-forward service/<name> 8080:http
   ```

**Next steps**

* Amazon Web Services (AWS)
  * [Configure Ingress](/2024.2/self-managed-deployment/configure/ingress-configuration.md#aws-load-balancer-controller) to complete your installation and access your Immuta application.
  * [Configure TLS](/2024.2/self-managed-deployment/configure/tls-configuration.md#aws-load-balancer-controller) to secure your Ingress by specifying a Secret that contains a TLS private key and certificate.
  * [Learn more about the best practices for Immuta in production](/2024.2/self-managed-deployment/configure/immuta-in-production.md).
* Microsoft Azure
  * [Configure Ingress](/2024.2/self-managed-deployment/configure/ingress-configuration.md#aks-application-gateway-ingress-controller) to complete your installation and access your Immuta application.
  * [Configure TLS](/2024.2/self-managed-deployment/configure/tls-configuration.md#aks-application-gateway-ingress-controller) to secure your Ingress by specifying a Secret that contains a TLS private key and certificate.
  * [Learn more about the best practices for Immuta in production](/2024.2/self-managed-deployment/configure/immuta-in-production.md).
* Google Cloud Platform (GCP)
  * [Configure Ingress](/2024.2/self-managed-deployment/configure/ingress-configuration.md#gke-ingress-controller) to complete your installation and access your Immuta application.
  * [Configure TLS](/2024.2/self-managed-deployment/configure/tls-configuration.md#gke-ingress-controller) to secure your Ingress by specifying a Secret that contains a TLS private key and certificate.
  * [Learn more about the best practices for Immuta in production](/2024.2/self-managed-deployment/configure/immuta-in-production.md).
    {% endtab %}

{% tab title="Red Hat OpenShift" %}
This is an OpenShift-specific guide on how to deploy Immuta with the following managed services:

* Cloud-managed PostgreSQL
* Cloud-managed Redis

**Prerequisites**

Review the following criteria before proceeding with deploying Immuta.

**PostgreSQL**

1. The PostgreSQL instance has been provisioned and is actively running.
2. The PostgreSQL instance's hostname/FQDN is [resolvable from within the Kubernetes cluster](/2024.2/self-managed-deployment/troubleshooting.md).
3. The PostgreSQL instance is [accepting connections](/2024.2/self-managed-deployment/troubleshooting.md#postgresql).

**Redis**

1. The Redis instance has been provisioned and is actively running.
2. The Redis instance's hostname/FQDN is [resolvable from within the Kubernetes cluster](/2024.2/self-managed-deployment/troubleshooting.md).
3. The Redis instance is [accepting connections](/2024.2/self-managed-deployment/troubleshooting.md#redis).

**Authenticate with OCI registry**

{% hint style="warning" %}
**Helm chart availability**

The deprecated Immuta Helm chart (IHC) is not available from ocir.immuta.com.
{% endhint %}

Copy the snippet below and replace the placeholder text with the credentials provided to you by your customer success manager:

```shell
echo <token> | helm registry login --password-stdin --username <username> ocir.immuta.com
```

**Setup**

1. Create a new OpenShift project named `immuta` for Immuta.

   ```shell
   oc new-project immuta
   ```
2. Get the UID range allocated to the project. Each running container's UID must fall within this range. This value will be referenced later on.

   ```shell
   oc get project immuta --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
   ```
3. Get the GID range allocated to the project. Each running container's GID must fall within this range. This value will be referenced later on.

   ```shell
   oc get project immuta --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
   ```
4. Switch to project `immuta`.

   ```shell
   oc project immuta
   ```
5. Create a container registry pull secret. Your credentials to authenticate with ocir.immuta.com can be viewed in your user profile at [support.immuta.com](https://support.immuta.com).

   ```shell
   oc create secret docker-registry immuta-oci-registry \
       --docker-server=https://ocir.immuta.com \
       --docker-username="<username>" \
       --docker-password="<token>" \
       --docker-email=support@immuta.com
   ```

**Cloud-managed PostgreSQL**

{% hint style="info" %}
**Connecting to the database**

There are numerous ways to connect to a PostgreSQL database. This step demonstrates how to connect by creating an ephemeral Kubernetes pod.
{% endhint %}

1. Connect to the database as superuser (postgres) by creating an ephemeral container inside the Kubernetes cluster. A shell prompt will not be displayed after executing the `oc run` command outlined below. Wait 5 seconds, and then proceed by entering a password.

   ```shell
   oc run pgclient \
       --stdin \
       --tty \
       --rm \
       --image docker.io/bitnami/postgresql -- \
       psql --host <postgres-fqdn> --username postgres --port 5432 --password
   ```
2. Create an `immuta` role and database.

   ```sql
   CREATE ROLE immuta with login encrypted password '<postgres-password>';

   GRANT immuta TO CURRENT_USER;

   CREATE DATABASE immuta OWNER immuta;

   GRANT all ON DATABASE immuta TO immuta;
   ALTER ROLE immuta SET search_path TO bometadata,public;
   ```
3. Revoke privileges from `CURRENT_USER` as they're no longer required.

   ```sql
   REVOKE immuta FROM CURRENT_USER;
   ```
4. Enable the `pgcrypto` extension.

   ```sql
   \c immuta
   CREATE EXTENSION pgcrypto;
   ```
5. Type `\q`, and then press `Enter` to exit.

**Install Immuta**

This section demonstrates how to deploy Immuta using the Immuta Enterprise Helm chart once the prerequisite cloud-managed services are configured.

1. Create a Helm values file named `immuta-values.yaml` with the content below. Because the Ingress resource will be managed by an OpenShift route you will create when [configuring Ingress](/2024.2/self-managed-deployment/configure/ingress-configuration.md#openshift-ingress-operator) and not the Immuta Enterprise Helm chart, `ingress` is set to `false` below. TLS comes pre-configured with OpenShift, so `tls` is also set to `false`.

   ```yaml
   global:
     imageRegistry: ocir.immuta.com
     imagePullSecrets:
       - name: immuta-oci-registry
     imageRepositoryMap:
       immuta/immuta-service: stable/immuta-service
       immuta/immuta-db: stable/immuta-db
       immuta/immuta-fingerprint: stable/immuta-fingerprint
       immuta/audit-service: stable/audit-service
       immuta/audit-export-cronjob: stable/audit-export-cronjob
       immuta/classify-service: stable/classify-service
       immuta/cache: stable/cache

   audit:
     enabled: false

     deployment:
       podSecurityContext:
         # A number that is within the project range:
         #   oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
         runAsUser: <user-id>
         # A number that is within the project range:
         #   oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
         runAsGroup: <group-id>
         seccompProfile:
           type: RuntimeDefault

       containerSecurityContext:
         allowPrivilegeEscalation: false
         capabilities:
           drop:
             - ALL

   discover:
     deployment:
       podSecurityContext:
         # A number that is within the project range:
         #   oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
         runAsUser: <user-id>
         # A number that is within the project range:
         #   oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
         runAsGroup: <group-id>
         seccompProfile:
           type: RuntimeDefault

       containerSecurityContext:
         allowPrivilegeEscalation: false
         capabilities:
           drop:
             - ALL

   secure:
     extraEnvVars:
       - name: FeatureFlag_AuditService
         value: "false"
       - name: FeatureFlag_detect
         value: "false"
       - name: FeatureFlag_auditLegacyViewHide
         value: "false"

     ingress:
       enabled: false
       tls: false

     postgresql:
       host: <postgres-fqdn>
       port: 5432
       database: immuta
       username: immuta
       password: <postgres-password>
       ssl: true

     web:
       podSecurityContext:
         # A number that is within the project range:
         #   oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
         runAsUser: <user-id>
         # A number that is within the project range:
         #   oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
         runAsGroup: <group-id>
         seccompProfile:
           type: RuntimeDefault

       containerSecurityContext:
         allowPrivilegeEscalation: false
         capabilities:
           drop:
             - ALL

     backgroundWorker:
       podSecurityContext:
         # A number that is within the project range:
         #   oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.uid-range"}}{{"\n"}}'
         runAsUser: <user-id>
         # A number that is within the project range:
         #   oc get project <project-name> --output template='{{index .metadata.annotations "openshift.io/sa.scc.supplemental-groups"}}{{"\n"}}'
         runAsGroup: <group-id>
         seccompProfile:
           type: RuntimeDefault

       containerSecurityContext:
         allowPrivilegeEscalation: false
         capabilities:
           drop:
             - ALL
   ```
2. Update all [placeholder values](/2024.2/self-managed-deployment/conventions.md) in the `immuta-values.yaml` file.

{% hint style="warning" %}
**Avoid these special characters in generated passwords**

whitespace, `$`, `&`, `:`, `\`, `/`, `'`
{% endhint %}

3. Deploy Immuta.

   ```shell
   helm install immuta immuta/immuta-enterprise \
       --values immuta-values.yaml
   ```

**Validation**

1. Wait for all pods in the namespace to become ready.

   ```shell
   oc wait --for=condition=Ready pods --all
   ```
2. Determine the name of the Secure service.

   ```shell
   oc get service --selector "app.kubernetes.io/component=secure" --output template='{{ .metadata.name }}'
   ```
3. Listen on local port `8080`, forwarding TCP traffic to the Secure service's port named `http`.

   ```shell
   oc port-forward service/<name> 8080:http
   ```

**Next steps**

* [Configure Ingress](/2024.2/self-managed-deployment/configure/ingress-configuration.md#openshift-ingress-operator) to complete your installation and access your Immuta application.
* [Learn more about best practices for Immuta in Production](/2024.2/self-managed-deployment/configure/immuta-in-production.md).
  {% endtab %}

{% tab title="Generic" %}
This is a generic guide that demonstrates how to deploy Immuta into any Kubernetes cluster without dependencies on any particular cloud provider.

**Considerations**

For the purposes of this guide, the [PostgreSQL](https://artifacthub.io/packages/helm/bitnami/postgresql) state stores are deployed in Kubernetes using third-party Helm charts maintained by [Bitnami](https://bitnami.com/).

{% hint style="warning" %}
Running production-grade stateful workloads (e.g, databases) in Kubernetes is difficult and heavily discouraged due to the following reasons.
{% endhint %}

* **Operational overhead**: Managing PostgreSQL on Kubernetes requires expertise in deploying, maintaining, and scaling these databases and search engines effectively. This involves tasks like setting up monitoring, configuring backups, managing updates, and ensuring high availability. Cloud-managed services abstract much of this operational burden away, allowing teams to focus on application development rather than infrastructure management.
* **Resource allocation and scaling**: Kubernetes requires careful resource allocation and scaling decisions to ensure that PostgreSQL has sufficient CPU, memory, and storage. Properly sizing these resources can be challenging and may require continuous adjustments as workload patterns change. Managed services typically handle this scaling transparently and can automatically adjust based on demand.
* **Data integrity and high availability**: PostgreSQL deployments need robust strategies for data integrity and high availability. Kubernetes can facilitate high availability through pod replicas and distributed deployments, but ensuring data consistency and durability across database instances and search indexes requires careful consideration and often additional tooling.
* **Performance**: Kubernetes networking and storage configurations can introduce performance overhead compared to native cloud services. For latency-sensitive applications or high-throughput workloads, these factors become critical in maintaining optimal performance.
* **Observability**: Troubleshooting issues in a Kubernetes environment, especially related to database and search engine performance, can be complex. Managed services typically come with built-in monitoring, logging, and alerting capabilities tailored to the specific service, making it easier to identify and resolve issues.
* **Security and compliance**: Kubernetes environments require careful attention to security best practices, including network policies, access controls, and encryption. Managed services often come pre-configured with security features and compliance certifications, reducing the burden on teams to implement and maintain these measures.

**Authenticate with OCI registry**

{% hint style="warning" %}
**Helm chart availability**

The deprecated Immuta Helm chart (IHC) is not available from ocir.immuta.com.
{% endhint %}

Copy the snippet below and replace the placeholder text with the credentials provided to you by your customer success manager:

```shell
echo <token> | helm registry login --password-stdin --username <username> ocir.immuta.com
```

**Setup**

1. Create a Kubernetes namespace named `immuta` for Immuta and its third-party dependencies.

   ```shell
   kubectl create namespace immuta
   ```
2. Switch to namespace `immuta`.

   ```shell
   kubectl config set-context --current --namespace=immuta
   ```
3. Create a container registry pull secret. Your credentials to authenticate with ocir.immuta.com can be viewed in your user profile at [support.immuta.com](https://support.immuta.com).

   ```shell
   oc create secret docker-registry immuta-oci-registry \
       --docker-server=https://ocir.immuta.com \
       --docker-username="<username>" \
       --docker-password="<token>" \
       --docker-email=support@immuta.com
   ```

**PostgreSQL**

1. Create a Helm values file named `pg-values.yaml` with the following content:

   ```yaml
   auth:
       database: immuta
       username: immuta
       password: <postgres-password>
   ```
2. Update all [placeholder values](/2024.2/self-managed-deployment/conventions.md) in the `pg-values.yaml` file.

{% hint style="warning" %}
**Avoid these special characters in generated passwords**

whitespace, `$`, `&`, `:`, `\`, `/`, `'`
{% endhint %}

3. Deploy PostgreSQL.

   ```shell
   helm install pg-db oci://registry-1.docker.io/bitnamicharts/postgresql \
       --values pg-values.yaml
   ```
4. Wait for all pods in the namespace to become ready.

   ```shell
   kubectl wait --for=condition=Ready pods --all
   ```
5. Determine the name of the PostgreSQL database pod. This will be referenced in a subsequent step.

   ```shell
   kubectl get pod --selector "app.kubernetes.io/name=postgresql" --output template='{{ .metadata.name }}'
   ```
6. Exec into the PostgreSQL database pod using the `psql` command and `immuta` user to configure the PostgreSQL user used by Immuta.

   ```shell
   kubectl exec --stdin --tty pod/<database-pod-name> -- psql -U immuta
   ```
7. Alter the `search_path` for the `immuta` user.

   ```sql
   ALTER ROLE immuta SET search_path TO bometadata,public;
   ```
8. Enable the `pgcrypto` extension.

   ```sql
   CREATE EXTENSION pgcrypto;
   ```
9. Type `\q` then press `Enter` to exit.

**Install Immuta**

This section demonstrates how to deploy Immuta using the Immuta Enterprise Helm chart once the prerequisite local services are configured.

1. Create a Helm values file named `immuta-values.yaml` with the following content:

   ```yaml
   global:
     imageRegistry: ocir.immuta.com
     imagePullSecrets:
       - name: immuta-oci-registry
     imageRepositoryMap:
       immuta/immuta-service: stable/immuta-service
       immuta/immuta-db: stable/immuta-db
       immuta/immuta-fingerprint: stable/immuta-fingerprint
       immuta/audit-service: stable/audit-service
       immuta/audit-export-cronjob: stable/audit-export-cronjob
       immuta/classify-service: stable/classify-service
       immuta/cache: stable/cache

   audit:
     enabled: false

   secure:
     ingress:
       enabled: false
     extraEnvVars:
       - name: FeatureFlag_AuditService
         value: "false"
       - name: FeatureFlag_detect
         value: "false"
       - name: FeatureFlag_auditLegacyViewHide
         value: "false"

     postgresql:
       # Each Kubernetes Service has a DNS record associated with it. See: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
       # The anatomy of a domain name is as follows:
       #   <service>.<namespace>.svc.<cluster-domain>
       #
       # Where the default cluster domain is: cluster.local
       host: pg-db-postgresql.immuta.svc.cluster.local
       port: 5432
       database: immuta
       username: immuta
       password: <postgres-password>
       ssl: true
   ```
2. Update all [placeholder values](/2024.2/self-managed-deployment/conventions.md) in the `immuta-values.yaml` file.

{% hint style="warning" %}
**Avoid these special characters in generated passwords**

whitespace, `$`, `&`, `:`, `\`, `/`, `'`
{% endhint %}

3. Deploy Immuta.

   ```shell
   helm install immuta immuta/immuta-enterprise \
       --values immuta-values.yaml
   ```

**Validation**

1. Wait for all pods in the namespace to become ready.

   ```shell
   kubectl wait --for=condition=Ready pods --all
   ```
2. Determine the name of the Secure service.

   ```shell
   kubectl get service --selector "app.kubernetes.io/component=secure" --output template='{{ .metadata.name }}'
   ```
3. Listen on local port `8080`, forwarding TCP traffic to the Secure service's port named `http`.

   ```shell
   kubectl port-forward service/<name> 8080:http
   ```
4. Navigate to `http://localhost:8080` in a web browser.

**Next steps**

* [Configure Ingress](/2024.2/self-managed-deployment/configure/ingress-configuration.md) to complete your installation and access your Immuta application.
* [Configure TLS](/2024.2/self-managed-deployment/configure/tls-configuration.md) to secure your Ingress by specifying a Secret that contains a TLS private key and certificate.
* [Learn more about best practices for Immuta in Production](/2024.2/self-managed-deployment/configure/immuta-in-production.md).
  {% endtab %}
  {% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://documentation.immuta.com/2024.2/self-managed-deployment/install/no-es-os.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
