---
title: OS users and groups
---

<!-- TODO: Update for San Luis release - DH_MONIT_USER and DH_MONIT_GROUP are no longer relevant/used -->

This page describes the operating system users and groups that Deephaven Enterprise uses to run its services. These accounts enforce separation of privileges between administrative, data-writing, and data-reading processes.

All user and group names are configurable via [cluster.cnf](./cluster-config-guide.md) during installation. The installer creates any missing accounts automatically.

## Overview

Deephaven uses a layered approach to OS-level security:

- **Three primary service accounts** run different classes of Deephaven processes, each with distinct filesystem permissions.
- **Two shared groups** enable controlled file sharing between service accounts and, optionally, end users.
- **Three private groups** provide per-account isolation when needed.
- **Infrastructure accounts** run supporting services like Monit and Etcd.
- **An installer service account** handles installation and maintenance via SSH.

## Primary service accounts

These three accounts run all [Deephaven services](../admin-glossary.md#deephaven-services). Each is designed with specific access levels to enforce the principle of least privilege.

### `DH_ADMIN_USER`

| Setting                                                    | Default value |
| ---------------------------------------------------------- | ------------- |
| [`DH_ADMIN_USER`](./cluster-config-guide.md#dh_admin_user) | `irisadmin`   |

The administrative service account runs privileged services that manage the Deephaven cluster:

- [Configuration Server](../core-components/configserver.md)
- [Authentication Server](../core-components/authentication.md)
- [Persistent Query Controller](../core-components/controller.md)
- [ACL Write Server](../runbooks/runbook-acl-write-server.md)
- [Web API Service](../runbooks/runbook-web-api-server.md)
- [Status Dashboard](../status-dashboard.md)

**Security considerations:**

- This account has access to cluster secrets, including TLS private keys and authentication configuration.
- Restrict access to this account to trusted system administrators only.
- Never allow user code execution as `DH_ADMIN_USER`.

**Sudoers requirements:**

Both [`DH_SSH_USER`](#dh_ssh_user) and [`DH_MONIT_USER`](#dh_monit_user-and-dh_monit_group) must be able to run commands as `DH_ADMIN_USER:DH_ADMIN_GROUP`.

### `DH_MERGE_USER`

| Setting                                                    | Default value |
| ---------------------------------------------------------- | ------------- |
| [`DH_MERGE_USER`](./cluster-config-guide.md#dh_merge_user) | `dbmerge`     |

The merge service account runs processes with **write access** to [historical table data](../table-storage/table-storage-filesystem.md):

- [Merge dispatchers](../pq-controller/dispatcher.md) (read-write Remote Query Dispatchers)
- Batch import processes (CSV, JDBC, Parquet importers)
- Any Persistent Query or worker that must write to `/db/Systems/` or `/db/Namespace/` locations

**Security considerations:**

- This account can modify or delete historical data.
- Restrict [Deephaven user](../admin-glossary.md#deephaven-user) access to trusted users who are members of [iris-data* ACL special groups](../permissions/web-acl-editor.md#special-groups).
- Never set `DH_MERGE_USER` equal to `DH_ADMIN_USER` or `DH_MONIT_USER` — doing so would grant administrative privileges to any user allowed to run code on the merge server.

**Sudoers requirements:**

Both `DH_SSH_USER` and `DH_MONIT_USER` must be able to run commands as `DH_MERGE_USER:DH_MERGE_GROUP`.

### `DH_QUERY_USER`

| Setting                                                    | Default value |
| ---------------------------------------------------------- | ------------- |
| [`DH_QUERY_USER`](./cluster-config-guide.md#dh_query_user) | `dbquery`     |

The query service account runs processes with **read-only access** to table data:

- [Query dispatchers](../pq-controller/dispatcher.md) (read-only Remote Query Dispatchers)
- Interactive console workers
- Most Persistent Queries that do not require write access to historical data

**Security considerations:**

- This account cannot modify historical data, but can access all data readable by `DH_SHARED_GROUP`.
- Users may optionally have write access to [user tables](../../deephaven-database/user-tables.md) via [Deephaven ACLs](../permissions/table-acls.md).
- Never set `DH_QUERY_USER` equal to `DH_ADMIN_USER` or `DH_MONIT_USER`.

**Sudoers requirements:**

Both `DH_SSH_USER` and `DH_MONIT_USER` must be able to run commands as `DH_QUERY_USER:DH_QUERY_GROUP`.

## Shared groups

Shared groups enable controlled file sharing between service accounts.

### `DH_SHARED_GROUP`

| Setting                                                        | Default value |
| -------------------------------------------------------------- | ------------- |
| [`DH_SHARED_GROUP`](./cluster-config-guide.md#dh_shared_group) | `dbmergegrp`  |

The primary shared group for all Deephaven service accounts. All three primary service accounts (`DH_ADMIN_USER`, `DH_MERGE_USER`, and `DH_QUERY_USER`) have this as their **primary group**.

**Purpose:**

- Files created by any Deephaven service are group-owned by `DH_SHARED_GROUP`, making them accessible to all Deephaven processes.
- Directories under `/db/` (historical data, intraday data, system tables) typically have group ownership of `DH_SHARED_GROUP`.
- Enables merge processes to write data that query processes can read.

**Group membership:**

| User            | Primary group     | Notes                 |
| --------------- | ----------------- | --------------------- |
| `DH_ADMIN_USER` | `DH_SHARED_GROUP` | Administrative access |
| `DH_MERGE_USER` | `DH_SHARED_GROUP` | Write access          |
| `DH_QUERY_USER` | `DH_SHARED_GROUP` | Read access           |

### `DH_SHARED_QUERY_GROUP`

| Setting                                                                    | Default value |
| -------------------------------------------------------------------------- | ------------- |
| [`DH_SHARED_QUERY_GROUP`](./cluster-config-guide.md#dh_shared_query_group) | `dbquerygrp`  |

A secondary shared group for broader access to Deephaven resources. This group allows non-service-account OS users to run Deephaven workers and access shared resources.

**Purpose:**

- Enables [per-user workers](../configuration/per-user-workers.md) — OS users outside the three primary service accounts can start Deephaven sessions.
- Files that should be accessible to all Deephaven users (including end users running their own workers) can be group-owned by `DH_SHARED_QUERY_GROUP`.

**Group membership:**

All three primary service accounts have **secondary membership** in `DH_SHARED_QUERY_GROUP`. You may add additional OS users to this group to grant them the ability to run Deephaven workers.

## Private groups

Each primary service account has a private group for files that should only be accessible to that specific account.

### `DH_ADMIN_GROUP`

| Setting                                                      | Default value |
| ------------------------------------------------------------ | ------------- |
| [`DH_ADMIN_GROUP`](./cluster-config-guide.md#dh_admin_group) | `irisadmin`   |

The private group for `DH_ADMIN_USER`. Used for files that only administrative processes should access, such as:

- TLS private keys
- Authentication secrets
- Etcd client credentials

> [!IMPORTANT]
> Despite its name, `DH_ADMIN_GROUP` is NOT the primary group for `DH_ADMIN_USER`. The primary group is `DH_SHARED_GROUP` (`dbmergegrp`). The `DH_ADMIN_GROUP` is a secondary/private group.

### `DH_MERGE_GROUP`

| Setting                                                      | Default value |
| ------------------------------------------------------------ | ------------- |
| [`DH_MERGE_GROUP`](./cluster-config-guide.md#dh_merge_group) | `dbmerge`     |

The private group for `DH_MERGE_USER`. Processes run with `DH_SHARED_GROUP` as the effective group, so files created by merge processes are accessible to other Deephaven services.

### `DH_QUERY_GROUP`

| Setting                                                      | Default value |
| ------------------------------------------------------------ | ------------- |
| [`DH_QUERY_GROUP`](./cluster-config-guide.md#dh_query_group) | `dbquery`     |

The private group for `DH_QUERY_USER`. Similar to `DH_MERGE_GROUP`, this exists primarily for account isolation rather than file ownership.

## Infrastructure accounts

### `DH_MONIT_USER` and `DH_MONIT_GROUP`

| Setting                                                      | Default value |
| ------------------------------------------------------------ | ------------- |
| [`DH_MONIT_USER`](./cluster-config-guide.md#dh_monit_user)   | `irisadmin`   |
| [`DH_MONIT_GROUP`](./cluster-config-guide.md#dh_monit_group) | `irisadmin`   |

> [!NOTE]
> For native installations, the Monit process manager starts and monitors all Deephaven services.

The Monit account runs the [Monit](../ops-guide/startup-shutdown.md) process manager, which is responsible for:

- Starting Deephaven services at system boot
- Monitoring service health
- Restarting failed services automatically

**Sudoers requirements:**

`DH_MONIT_USER` must be able to sudo as all three primary service accounts:

- `DH_ADMIN_USER:DH_ADMIN_GROUP`
- `DH_MERGE_USER:DH_MERGE_GROUP`
- `DH_QUERY_USER:DH_QUERY_GROUP`

By default, `DH_MONIT_USER` is the same as `DH_ADMIN_USER` (`irisadmin`). This simplifies sudoers configuration while maintaining security — Monit itself does not execute user code.

**Related settings:**

| Setting            | Default value              | Description                          |
| ------------------ | -------------------------- | ------------------------------------ |
| `DH_MONIT_RC`      | OS-dependent               | Path to the monit configuration file |
| `DH_MONIT_ROOT`    | `false`                    | Whether monit runs as the root user  |
| `DH_MONIT_LOG_DIR` | `/var/log/deephaven/monit` | Directory for monit log files        |

### `DH_ETCD_USER`

| Setting                                                  | Default value |
| -------------------------------------------------------- | ------------- |
| [`DH_ETCD_USER`](./cluster-config-guide.md#dh_etcd_user) | `etcd`        |

The account that runs the [Etcd](../core-components/etcd.md) service on native installations. Etcd stores all cluster configuration, ACLs, and runtime state.

**File ownership:**

- Etcd server secrets: `/etc/etcd/dh` and `/var/lib/etcd` are owned by `DH_ETCD_USER`
- Etcd client secrets: owned by `DH_ADMIN_USER`, with group access via `DH_ADMIN_GROUP`

> [!TIP]
> Setting `DH_ETCD_USER` to the same username as `DH_ADMIN_USER` simplifies file permissions and sudoers rules, but increases risk if `DH_ADMIN_USER` is compromised.

## Installer service account

### `DH_SSH_USER`

| Setting                                                | Default value                        |
| ------------------------------------------------------ | ------------------------------------ |
| [`DH_SSH_USER`](./cluster-config-guide.md#dh_ssh_user) | (current user running the installer) |

The service account used by the installer for SSH access to Deephaven servers during installation and maintenance. This account:

- Copies installation files to remote machines
- Runs installation scripts via SSH
- Must have sudoers permission to act as all primary service accounts

**Security considerations:**

- `DH_SSH_USER` is not used after installation completes — it only performs installation and upgrade tasks.
- Consider using a dedicated service account rather than a personal user account.
- SSH keys for this account should be carefully protected.

**Sudoers requirements:**

`DH_SSH_USER` must be able to sudo as:

- `DH_ADMIN_USER:DH_ADMIN_GROUP`
- `DH_MERGE_USER:DH_MERGE_GROUP`
- `DH_QUERY_USER:DH_QUERY_GROUP`
- `DH_MONIT_USER:DH_MONIT_GROUP` (if different from `DH_ADMIN_USER`)

**Related settings:**

| Setting      | Description                                        |
| ------------ | -------------------------------------------------- |
| `DH_SSH_KEY` | Path to the SSH private key for installation       |
| `DH_LAX_SSH` | Bypass SSH host key verification (not recommended) |

## Group membership summary

The following table summarizes group membership for all service accounts:

| Account         | Primary group     | Secondary groups                                        |
| --------------- | ----------------- | ------------------------------------------------------- |
| `DH_ADMIN_USER` | `DH_SHARED_GROUP` | `DH_ADMIN_GROUP`, `DH_SHARED_QUERY_GROUP`               |
| `DH_MERGE_USER` | `DH_SHARED_GROUP` | `DH_MERGE_GROUP`, `DH_SHARED_QUERY_GROUP`               |
| `DH_QUERY_USER` | `DH_SHARED_GROUP` | `DH_QUERY_GROUP`, `DH_SHARED_QUERY_GROUP`               |
| `DH_MONIT_USER` | `DH_MONIT_GROUP`  | (requires sudo access to all three primary accounts)    |
| `DH_ETCD_USER`  | `DH_ADMIN_GROUP`  | (Etcd-specific, shares some files with `DH_ADMIN_USER`) |

To verify group membership for any account, run:

```shell
id "${DH_ADMIN_USER:-irisadmin}"
# Expected output format:
# uid=9002(irisadmin) gid=9003(dbmergegrp) groups=9003(dbmergegrp),9004(dbquerygrp),9002(irisadmin)
# The gid= shows the primary group; groups= shows all group memberships
```

## Customizing user and group names

All user and group names can be customized in your `cluster.cnf` file before installation. See [Custom user accounts](./cluster-config-guide.md#custom-user-accounts) for the complete list of configurable variables.

Example custom configuration:

```properties
# Custom admin account
DH_ADMIN_USER=dh_admin
DH_ADMIN_GROUP=dh_admin

# Custom merge account
DH_MERGE_USER=dh_merge
DH_MERGE_GROUP=dh_merge

# Custom query account
DH_QUERY_USER=dh_query
DH_QUERY_GROUP=dh_query

# Custom shared groups
DH_SHARED_GROUP=dh_shared
DH_SHARED_QUERY_GROUP=dh_query_shared

# Installer service account
DH_SSH_USER=dh_installer
```

> [!CAUTION]
> Changing user or group names after installation is an advanced operation that requires careful migration of file ownership and permissions. Contact Deephaven support for guidance.

## Related documentation

- [Custom user accounts](./cluster-config-guide.md#custom-user-accounts)
- [Deephaven service accounts](../admin-glossary.md#deephaven-service-accounts)
- [Basic installation](./basic-install.md)
- [Sudoers configuration](./basic-install.md#appendix-d-sudoers)
- [Per-user workers](../configuration/per-user-workers.md)
- [Hardening Technical Controls](../security/hardening-technical-controls.md)
