# Privileges and Permissions for Self-Deployment

> Which Linux privileges each Sisense self-deployment method needs and on which machine, the Kubernetes RBAC the installing identity needs, what the Sisense Helm chart creates, and how Sisense works with Pod Security Standards.

*Source: https://docs.sisense.com/main/SisenseLinux/self-deployment-privileges-and-permissions.htm*

---

Last updated: October 21, 2026

|  |  |
| --- | --- |
| [Tier](https://www.sisense.com/pricing/#pricing) | [Deployment](https://docs.sisense.com/main/SisenseLinux/introduction-to-sisense-cloud-managed-services.md#ComparisonofManagedCloudandSelfHosted) |
| Enterprise | On-Prem |

This page describes which privileges each Sisense self-deployment method needs, and on which machine. It covers Linux privileges on the machine that runs the installation and on the Kubernetes nodes, the Kubernetes RBAC that the installing identity needs, the RBAC objects that the Sisense Helm chart creates, and how Sisense works with Pod Security Standards.

To compare the installation methods, see [Choosing an Installation Method](https://docs.sisense.com/main/SisenseLinux/choosing-an-installation-method.md).

## Host Privileges by Installation Method

The *install machine* is the computer where you run the installation command. The *Kubernetes nodes* are the servers that run the Sisense pods.

| Installation Method | Install Machine | Kubernetes Nodes | SSH to Nodes | Kubernetes Identity |
| --- | --- | --- | --- | --- |
| Helm | Any computer with `kubectl` and `helm`. No Linux user, SSH key, or `sudo`. | No privileges | No | `cluster-admin`, or the namespace-scoped permissions described [below](#RBAC) |
| Provisioner | Any computer with `kubectl` and `helm`. No Linux user, SSH key, or `sudo`. | No privileges. The installer runs in a pod. | No | `cluster-admin`. The installation Job's ServiceAccount is bound to `cluster-admin`. |
| *sisense.sh* on EKS, AKS, or GKE (*cloud\_config.yaml*) or OpenShift (*openshift\_config.yaml*) | Linux. A regular (non-root) user that can run `sudo` without a password (NOPASSWD) for the duration of the installation. You can remove the NOPASSWD rule afterwards. | No privileges. The installer does not connect to or run anything on the nodes. | No | `cluster-admin` through the user's kubeconfig (or `oc login` on OpenShift) |
| *sisense.sh* on multiple Linux servers (*cluster\_config.yaml*) | Linux. A regular (non-root) user with passwordless `sudo`. | The same user with passwordless `sudo` on every server. The installer prepares the operating system and installs RKE2 on each server. | Yes, as the configured Linux user | Created by the installer |
| *sisense.sh* on a single Linux server (*single\_config.yaml*) | Linux. A regular (non-root) user with passwordless `sudo`. The install machine is also the Kubernetes node. | Same machine | Yes, to the same machine | Created by the installer |

In summary:

- On a cloud-managed cluster (EKS, AKS, GKE) or OpenShift, no installation method needs privileges on the Kubernetes nodes.
- The Helm and Provisioner methods need no Linux user or `sudo` anywhere. They need a Kubernetes identity, not a Linux one.
- The only `sudo` that *sisense.sh* needs on a cloud-managed cluster or OpenShift is on the install machine.

## Why *sisense.sh* Needs sudo on the Install Machine

With every configuration file, *sisense.sh* runs these steps on the install machine as the configured Linux user:

- Installs the operating-system packages the installer uses, such as `python3`, `jq`, `pssh`, and `sshpass`.
- Creates the */opt/sisense* directory and sets its owner.
- Copies `kubectl`, `helm`, and `helmfile` to */usr/local/bin*.

At startup, the installer checks `sudo` with a short timeout, so `sudo` must not prompt for a password. If the check fails, the installer stops with this message:

[Copy](javascript:void(0);)

```
User <linux_user> has insufficient sudo permissions  
sudo configuration should include NOPASSWD for the installation and can be removed at the end of the installation.
```

To fix it, add a NOPASSWD rule for the installation user (for example, with `sudo visudo`), run the installation, and remove the rule when the installation is complete.

**Example:**

```
<linux_user> ALL=(ALL) NOPASSWD: ALL
```

## Kubernetes RBAC for the Installing Identity

The installing identity is the Kubernetes user or ServiceAccount whose credentials run `helm` or *sisense.sh*.

| Method | Permissions at Installation and Upgrade | Why |
| --- | --- | --- |
| Helm (default, `global.clusterVisibility: true`) | `cluster-admin` | The chart creates ClusterRoles and ClusterRoleBindings (see [What the Sisense Helm Chart Creates](#Creates)) and reads cluster-scoped objects while it renders. |
| Helm, namespace-scoped (`global.clusterVisibility: false`) | - Full administrative rights in the target namespace. - `list` on `nodes` (cluster-wide). - `get` on `namespaces` (cluster-wide). - If a namespace named `monitoring` exists: rights to create a Role and a RoleBinding in it. | The chart creates Roles and RoleBindings in the namespace. Kubernetes lets an identity grant only permissions it already holds.  While rendering, the chart lists the cluster's nodes and checks whether a `monitoring` namespace exists. If it exists, the chart creates a Role and RoleBinding there for the validator Job. |
| Provisioner | `cluster-admin` | The Provisioner chart binds the installation Job's ServiceAccount to the `cluster-admin` ClusterRole. |
| *sisense.sh* on EKS, AKS, GKE, or OpenShift | `cluster-admin` | The installer labels nodes, creates namespaces and StorageClasses, installs storage drivers and other Helm releases, and installs the Sisense chart. |
| *sisense.sh* on your own Linux servers | None in advance | The installer creates the RKE2 cluster and uses its administrator kubeconfig. |

**Tip:** To check whether an identity has enough permissions before you install, run the installation command with `--dry-run=server` (Helm 3.13 or later). A dry run needs the same permissions as a real installation and creates nothing. If permissions are missing, it fails with a `forbidden` error.

## What the Sisense Helm Chart Creates

Every installation method installs the Sisense Helm chart, so these objects exist with every method unless you change the values described below.

### ClusterRoles Controlled by global.clusterVisibility

When `global.clusterVisibility` is `true` (the default), the chart creates these ClusterRoles, each with a ClusterRoleBinding to the service's own ServiceAccount. When it is `false`, none of them is created.

| ClusterRole | Used By | Resources and Verbs |
| --- | --- | --- |
| `<release>-build-visibility-clusterrole` | build | `nodes`: get, list, watch, patch |
| `<release>-bsm-executors-visibility-clusterrole` | bsm-executors (disabled by default) | `nodes`: get, list, watch, patch |
| `<release>-management-visibility-clusterrole` | management | `nodes`, `jobs`, `cronjobs`: get, list, watch, patch, create, update, delete, deletecollection |
| `<release>-oxygen-monitoring-clusterrole` | oxygen | `configmaps`: get, list, watch, patch; `pods`: list, delete, deletecollection; `secrets` named `fluentd-kinesis` and `kinesis-credentials` only: get, watch, list, patch |
| `validator-<namespace>` | validator Job | `nodes`: get, list; `services`, `pods`: get, list, delete; `persistentvolumes`: get, list, watch, patch, delete; Gateway API `gateways`: get, list |

### Cluster-Scoped Objects Not Controlled by global.clusterVisibility

- **Grafana:** Grafana is deployed by default. Unless `grafana.rbac.namespaced` is `true` (the default is `false`), the Grafana subchart creates the ClusterRole `<release>-grafana-clusterrole` and a ClusterRoleBinding, which let its dashboard and data source sidecars read `configmaps` and `secrets` in all namespaces (get, watch, list). With `grafana.rbac.namespaced: true`, Grafana uses a Role in the release namespace instead. To skip Grafana entirely, set `grafana.enabled: false`.
- **PersistentVolumes:** In single-node mode (`global.clusterMode.enabled: false`), the chart creates hostPath PersistentVolumes. With `global.storageType: fsx`, the chart creates a PersistentVolume for the FSx file system. PersistentVolumes are cluster-scoped.

### Namespaced Roles

Each Sisense service has its own ServiceAccount, Role, and RoleBinding in the release namespace. Several services (for example, ae, build, management, and query) can manage pods, jobs, deployments, statefulsets, services, secrets, and PersistentVolumeClaims in that namespace. Sisense ServiceAccounts do not request permissions on StorageClasses or CustomResourceDefinitions.

## Namespace-Scoped Installation

When you install with Helm and cannot grant Sisense cluster-wide RBAC, add these values:

[Copy](javascript:void(0);)

```
global:  
  clusterVisibility: false   # no ClusterRoles for build, bsm-executors, management, oxygen, validator  
grafana:  
  rbac:  
    namespaced: true         # Grafana uses a Role instead of a ClusterRole (or set grafana.enabled: false)
```

Also keep these settings at their defaults:

- `mongodb.metrics.enabled`, `rabbitmq.metrics.enabled`, and `zookeeper.metrics.enabled`: `false`. When enabled, they create ServiceMonitors, which require the Prometheus Operator CRDs.
- `global.monitoring.internal`: `false`.

With `global.clusterVisibility: false`, the management, build, bsm-executors, and validator services also receive `CLUSTER_VISIBILITY=false` and do not access cluster nodes. For what this changes in Sisense, see [Installing Sisense without ClusterVisibility](https://docs.sisense.com/main/SisenseLinux/install-clustervisibility-false.md).

The installing identity still needs the cluster-wide read access described in [Kubernetes RBAC for the Installing Identity](#RBAC).

With *sisense.sh*, set `cluster_visibility: false` in the configuration file. The installer then sets `grafana.rbac.namespaced: true`, and it does not label nodes, install storage drivers, check node pod capacity, or install the monitoring and logging stacks.

## Pod Security Standards

This section helps you choose a Pod Security Admission level for the Sisense namespace.

- **Cluster mode** (`global.clusterMode.enabled: true`): Sisense workloads do not use privileged containers, host namespaces (`hostNetwork`, `hostPID`, `hostIPC`), host ports, or hostPath volumes. Use the `baseline` level.
- **Single-node mode** (`global.clusterMode.enabled: false`): Sisense stores its data in hostPath volumes under */opt/sisense* on the node. The `baseline` level does not allow hostPath volumes, so the namespace needs the `privileged` level.

### Differences from the Restricted Level

With default values, the Sisense chart does not meet the `restricted` level, for these reasons:

| Difference | Workloads | When |
| --- | --- | --- |
| No container-level `securityContext` is set by default, so the settings that `restricted` requires (`allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`, `seccompProfile.type: RuntimeDefault`) are missing. | Sisense service containers and their init containers | By default. See `global.containerSecurityContext` below. |
| The `init-chown-data` init container runs as root (UID 0) to set the owner of the data directory. | Dgraph (single node), and Dgraph alpha and zero (cluster mode) | When `initChownData.enabled` is `true` (the default) |
| The `init-chown-data` init container runs as root and adds the `CHOWN`, `DAC_OVERRIDE`, and `FOWNER` capabilities. | Grafana | When Grafana persistence is enabled (the Sisense default) and `grafana.initChownData.enabled` is `true` (the default) |
| The volume-permissions init container runs as root. | MongoDB | When `mongodb.volumePermissions.enabled` is `true` (the Sisense default) |

All Sisense pods also set an SELinux level (`s0:c123,c456`) in `global.securityContext`. Both `baseline` and `restricted` allow this setting.

`global.containerSecurityContext` is not set by default. When you set it, the chart applies it as the container-level `securityContext` of most Sisense service containers and their init containers. It does not change the root init containers listed in the table above.

### Components Added by the Installer and the Provisioner

- **NGINX Gateway Fabric on your own Linux servers:** *sisense.sh* runs the NGINX data plane as a privileged DaemonSet that binds host ports (80 or 443, and 9113). On EKS, AKS, and GKE it runs as a Deployment behind a LoadBalancer Service.
- **Provisioner Job:** Mounts the hostPath */opt/sisense* when `persistence.enabled` is `false`, and mounts the hostPath */etc/passwd* when `securityContext.runAsUser` is not 1000.
- **Storage drivers:** Drivers that the installer installs for you (for example, the AWS EBS, FSx, and NFS CSI drivers, and Rook-Ceph) are third-party components with their own security requirements. They run in their own namespaces.

### Recommended Namespace Labels

| Mode | Labels |
| --- | --- |
| Cluster mode (Helm with `global.clusterMode.enabled: true`, Provisioner with `persistence.enabled: true`, *sisense.sh* with a `storage_type` or `rwx_sc_name`) | `pod-security.kubernetes.io/enforce=baseline`  Optionally, add `pod-security.kubernetes.io/warn=restricted` and `pod-security.kubernetes.io/audit=restricted` to see the differences listed above without blocking pods. |
| Single-node mode (hostPath) | `pod-security.kubernetes.io/enforce=privileged` |

For example, to label the namespace for cluster mode:

[Copy](javascript:void(0);)

```
kubectl label namespace <namespace> \  
  pod-security.kubernetes.io/enforce=baseline \  
  pod-security.kubernetes.io/warn=restricted \  
  pod-security.kubernetes.io/audit=restricted --overwrite
```

If you use a policy engine (for example, Gatekeeper, Kyverno, or Azure Policy), allow `runAsUser: 0` for the init containers listed above. In cluster mode, the Sisense chart does not need hostPath volumes.
