---
title: Cluster configuration files
---

`cluster.cnf` files are used to configure basic Deephaven installations. These settings define the Deephaven cluster topology.

> [!WARNING]
> You should treat the cluster configuration file as critical source code and protect it under source control.

## File structure

### Format

Cluster configuration files consist of two main sections: basic configuration and node definition. The format of the `cluster.cnf` file is very strict. Variables must be defined in uppercase letters, with no spaces between the declaration and the assignment. Values can be either single token values or enclosed in double quotes. Note that Unicode "smart" quotes are not permitted, and the use of the `export` command is also not allowed.

> [!NOTE]
> The first time you run the [installation generator](./basic-install.md#generate-the-installation-scripts), the cluster configuration file is updated with the default values for unspecified options.

```properties
# Comments are allowed in Java properties and bash
DH_SOME_KEY=good
DH_OTHER_KEY="also good"

# Now, some bad examples:
// illegal comment
DH_BAD_KEY = badSpace
DH_ALSO_BAD=also bad space
DH_SMART_QUOTES=”bad: no ‘smart’ quotes”
DH_SINGLE_QUOTE='bad: must use double quote'
export SOMETHING="bad: java properties cannot export"
```

### Basic configuration

The basic configuration section defines the parameters of the installation:

- Deephaven system version
- Java JDK version
- Service User definition
- OS
- Python configuration
- Envoy configuration
- The fully qualified domain name suffix
- Installation directories

Below is an example of a minimum set of configurations for an example cluster.

```properties
# The name of the cluster
DH_CLUSTER_NAME="dh-example-cluster"

# The local directory containing the installation files
DH_LOCAL_DIR="/tmp/dh/install"

# The directory on each host to upload and run the installation from
DH_REMOTE_DIR="/tmp/dh/install"

# The Deephaven version being installed
DH_VERSION="1.20240517.245"

# The root of the domain of the hosts
DH_DOMAIN_ROOT="mydomain.com"

# The Java version being used
DH_JAVA_VERSION="jdk17"

# Set to true to allow the installer to automatically update the sudoers file with the proper rules.
DH_MODIFY_ETC_SUDOERS="true"

# Allows adding sudoers rules to enable the dh-etcd service with systemd. This grants root-equivalent privileges to your DH_SSH_USER service account
# To avoid this, you must create and enable the dh-etcd.service systemd unit yourself
DH_ALLOW_SYSTEMCTL_ENABLE="true"

# Replace this user with the installation service account username (the user that runs installer scripts on Deephaven server machines)
DH_SSH_USER=dh_service

# The operating system used on server machines
DH_OS="rocky9"

# Set to true to install Deephaven Python integration, including venv update and setup.
DH_PYTHON="true"

# Set this to the version of Python you have installed. See the support matrix for supported versions.
DH_PYTHON_VERSION="3.10"

# Set to true to configure Envoy automatically.
# Note that you must install Envoy separately. See the documentation for more information
DH_CONFIGURE_ENVOY="false"

# Comment out this line to allow the installer to download and install missing requirements.
#  For example, if the requested Python version is not detected, the installer will download,
#  build, and install the correct version of Python on each node.
DH_OFFLINE=true
```

### Node configuration

> [!NOTE]
> For a more complete definition of the different classes of Deephaven nodes, see the [planning guide](./installation-planning.md)

The node configuration section defines the cluster topology. Include a section defining each cluster node, their names, and roles. Each node is assigned a numbered prefix, for example, `DH_NODE_1_`, which is then used to define the configuration of that node. You must define at least one node that acts as an Infrastructure node. For example, a simple single-node cluster is:

```properties
# Infrastructure node
DH_NODE_1_NAME="dh-example-cluster-infra"
DH_NODE_1_ROLE_INFRA="true"
DH_NODE_1_ROLE_QUERY="true"
DH_NODE_1_ROLE_ETCD="true"
```

The `INFRA` role is a special role that configures several separate services required for a Deephaven Infrastructure node, see [`DH_NODE_N_ROLE_INFRA`](#dh_node_n_role_infra). For the full set of possible roles, see [`DH_NODE_N_ROLE_$SERVICE`](#dh_node_n_role_service).

You can add as many nodes as you want to your cluster by adding another set of `DH_NODE_N` values. For example, you could add two more nodes that run query servers and ETCD instances to the cluster defined above with the following:

```properties
# Query 1 Node
DH_NODE_2_NAME="dh-example-cluster-query-1"
DH_NODE_2_ROLE_QUERY="true"
DH_NODE_2_ROLE_ETCD="true"

# Query 2 Node
DH_NODE_3_NAME="dh-example-cluster-query-2"
DH_NODE_3_ROLE_QUERY="true"
DH_NODE_3_ROLE_ETCD="true"
```

## Service redundancy

Several Deephaven services such as the Authentication Server, Persistent Query Controller, and Data Import Server, support redundancy and failover. You can add these roles to additional nodes in the system to automatically configure these services for redundancy. For more details about redundant services, see [resilience planning](../architecture/resilience-planning/resilience-planning-overview.md).

## Required variables

### `DH_LOCAL_DIR`

```properties
DH_LOCAL_DIR=/tmp/deploy
```

The location on the Installation Host where installation media is placed and all generated scripts are written to and run from. You run the [installation generator](./basic-install.md#generate-the-installation-scripts) from this directory. If this property is not defined, the value for [`DH_REMOTE_DIR`](#dh_remote_dir) is used instead. If neither is specified, an error is thrown, and no files are generated.

> [!NOTE]
> This directory must be owned and writable by the [`DH_SSH_USER`](#dh_ssh_user).

### `DH_REMOTE_DIR`

```properties
DH_REMOTE_DIR=/tmp/deploy
```

The location on each Remote Host where the installer copies installation media and writes log files. If this directory is missing, the install script creates it. If `DH_REMOTE_DIR` is not specified, the value of [`DH_LOCAL_DIR`](#dh_local_dir) is used instead. If both are missing, an error is thrown, and no files are generated.

> [!TIP]
> To avoid uploading large files from your installer host to each target machine, you can place the installation media into `/var/lib/deephaven`, ensuring the files are readable by [`DH_SSH_USER`](#dh_ssh_user) and [`DH_ADMIN_USER`](#dh_admin_user)

All scripts that run during installation write their log files to `$DH_REMOTE_DIR/logs`.

### `DH_VERSION`

```properties
DH_VERSION=VAR::COREPLUS_DHE_VERSION
```

The version of Deephaven to install. This must match the name of the Deephaven `tar.gz` file placed in [`DH_LOCAL_DIR`](#dh_local_dir). The installer searches for the installation media in the following filesystem locations, in order:

1. `/var/lib/deephaven/deephaven-enterprise-${DH_JAVA_VERSION}-VAR::COREPLUS_DHE_VERSION.tar.gz` (owned by `irisadmin`)
2. `$DH_REMOTE_DIR/lib/deephaven-enterprise-${DH_JAVA_VERSION}-VAR::COREPLUS_DHE_VERSION.tar.gz` (readable by Service Account AND `irisadmin`)
3. `$DH_LOCAL_DIR/deephaven-enterprise-${DH_JAVA_VERSION}-VAR::COREPLUS_DHE_VERSION.tar.gz` (readable by service account)

If the `tar.gz` is not found in any of these places, the installation fails.

### `DH_CLUSTER_NAME`

```properties
DH_CLUSTER_NAME="Some Name"
```

An identifying name for the cluster. While this is required, it is only used for logging.

### `DH_OS`

```properties
DH_OS=rocky9
```

The operating system that the installer targets. Valid options are:

- ubuntu20
- ubuntu22
- rocky8
- rocky9
- rhel8
- rhel9

The [version support matrix](../../reference/supported-versions.md#linux-versions) details when each Operating System is supported by a specific version of Deephaven. To install on an OS, both the install generator and product archive must have matching versions listed on the support matrix.

> [!CAUTION]
> It is strongly recommended that all hosts within the Deephaven cluster use the same OS flavor and version. If you have specific requirements that prevent this, please contact Deephaven support for further help configuring your system.

### `DH_NODE_N_NAME`

```properties
DH_NODE_N_NAME="some-name"
```

`DH_NODE_N_` variables define each Remote Host in the cluster that the installer configures (domain name, hostname, and running processes). At least one node must be specified, and `N` should be replaced with an integer starting at 1.

> [!TIP]
> You should set this to match the node's short hostname (not the fully qualified domain name), similar to the output of `hostname -s`.

## Optional variables

**SSH and service account**

### `DH_SSH_USER`

```properties
DH_SSH_USER=dh_service
```

The service account user on Deephaven servers used to copy files and run scripts via SSH.

If left unspecified, this defaults to the user running the installer from the [`DH_LOCAL_DIR`](#dh_local_dir) on the Installer Host.

> [!CAUTION]
> It is strongly recommended that you set the [`DH_SSH_USER`](#dh_ssh_user) variable when generating scripts so the installer can validate the proper ownership of all files.

### `DH_SSH_KEY`

```properties
DH_SSH_KEY=/path/to/some/id_rsa
```

The path to the SSH key on the installation host to use during the installation process. It is good practice to combine this with [`DH_SSH_USER`](#dh_ssh_user). If left unspecified, the installer performs normal SSH key lookup using the SSH keys in `$HOME/.ssh`.

### `DH_LAX_SSH`

```properties
DH_LAX_SSH="false"
```

Setting this to `true` bypasses SSH Remote Host verification. The default value is `false`, and requires that the `known_hosts` file for the [`DH_SSH_USER`](#dh_ssh_user) on the installation host is already set up to communicate with all target Remote Hosts.

### `DH_SSH_CONFIG`

```properties
DH_SSH_CONFIG="/path/to/ssh/config"
```

Path to an SSH config file to use during installation. This allows customization of SSH behavior when connecting to remote hosts.

### `DH_SYSADMIN_USER`

```properties
DH_SYSADMIN_USER=dh_service
```

The sysadmin-level user for operations that require elevated OS privileges during installation. Defaults to [`DH_SSH_USER`](#dh_ssh_user) if set, otherwise falls back to the user running the installation scripts.

**General installer**

### `DH_WORLD_READABLE_LOGS`

```properties
DH_WORLD_READABLE_LOGS="false"
```

Setting this to `true` makes log files world-readable. The default value is `false`.

> [!CAUTION]
> Set this to `true` only if access to the [`DH_SSH_USER`](#dh_ssh_user) is highly restricted, and other users need to debug logs without logging in as the service account. Enabling this option may risk exposing sensitive information through the log files.

### `DH_CLEANUP`

```properties
DH_CLEANUP="true"
```

Setting this to `true` directs the installer to scrub all temporary files AND logs on all remote machines after installation completes. Logs are copied from Remote Host to Installer Host before they are deleted. The default value is `false` unless [`DH_LOCAL_DIR`](#dh_local_dir) is not the same as [`DH_REMOTE_DIR`](#dh_remote_dir).

For more information about host types see the [installation guide](./basic-install.md#prerequisites)

**Node networking**

### `DH_DOMAIN_ROOT`

```properties
DH_DOMAIN_ROOT=my.company.com
```

When `DH_DOMAIN_ROOT` is set, per-node domain names are computed by concatenating [`DH_NODE_N_HOST`](#dh_node_n_host) with `DH_DOMAIN_ROOT` (see below).

### `DH_NODE_N_HOST`

The hostname of node N. If this is not specified, the installer uses the [`DH_NODE_N_NAME`](#dh_node_n_name) instead.

### `DH_NODE_N_DOMAIN`

The [fully qualified domain name](../admin-glossary.md#fqdn) of node N.

If `DH_NODE_N_DOMAIN` is NOT set, and [`DH_DOMAIN_ROOT`](#dh_domain_root) is set, the installer assumes the [fully qualified domain name](../admin-glossary.md#fqdn) for node N is [`DH_NODE_N_HOST`](#dh_node_n_host).[`DH_DOMAIN_ROOT`](#dh_domain_root). When `DH_DOMAIN_ROOT` is not set, the default for `DH_NODE_N_DOMAIN` is `DH_NODE_N_HOST`.

> [!CAUTION]
> Note that all Deephaven processes connect to each other using the configured `DH_NODE_N_DOMAIN`, using TLS which requires that your certificate's [Subject Alternative Name](../admin-glossary.md#san) matches the configured FQDN. If a [Deephaven client](../admin-glossary.md#deephaven-client) cannot resolve or reach your cluster's internal domain names, then you MUST use the [Envoy](../envoy/envoy.md) load balancer and expose the [`DH_ENVOY_FQDN`](#dh_envoy_fqdn) and [`DH_ENVOY_PORT`](#dh_envoy_port) to client machines.

> [!TIP]
> When using [Envoy](../envoy/envoy.md), the installer, by default, [generates secure certificates for all other machines](../security/tls-certificates.md#required-tls-certificates).
>
> When customers [provide per-node TLS certificates](../security/tls-certificates.md#one-certificate-per-machine), each node must have a certificate whose SAN entries include the value of `DH_NODE_N_DOMAIN` for that node.

### `DH_NODE_N_INSTALLER_ROUTE`

The [fully qualified domain name](../admin-glossary.md#fqdn) that the Installer Host must use to reach machine N.

By default, `DH_NODE_N_INSTALLER_ROUTE`=[`DH_NODE_N_DOMAIN`](#dh_node_n_domain).

You only need to consider this variable if your Installer Host machine does not have network access to the standard FQDNs used to access Deephaven servers.

The installer route hostname does not need to be included in any certificate or trust material.

### `DH_NODE_N_ETCD_IP`

For systems with complex networking, you may need your [Deephaven server processes](../admin-glossary.md#deephaven-services) to reach your Etcd cluster on an IP address that your Installer Host may not be able to connect to.

By default, the installer computes the IP addresses for your Etcd servers by resolving the [`DH_NODE_N_DOMAIN`](#dh_node_n_domain) from the Installer Host. By setting an explicit `ETCD_IP` per node, no DNS resolution occurs from the Installer Host, and whatever IP addresses you pass in are supplied verbatim to Etcd client and server configuration files.

### `DH_NODE_N_ROLE\_$SERVICE`

```properties
DH_NODE_N_ROLE_$SERVICE=true|false
```

When set to `true`, this directs the installer to enable the specified service on the specified node. The [`DH_NODE_N_ROLE_INFRA`](#dh_node_n_role_infra) role is a special role that enables common services needed on an Infrastructure node.

The full list of services is:

| Service Suffix | Description                                                                                                                                                                                                                           |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `_QUERY`       | Enable a query-class (read-only) RemoteQueryDispatcher `[db_query]`.                                                                                                                                                                  |
| `_MERGE`       | Enable a merge-class (read-write) RemoteQueryDispatcher `[db_merge]`.                                                                                                                                                                 |
| `_CONFIG`      | Enable a ConfigurationServer. This requires etcd binaries and client keys on disk [`configuration_server`](../configuration/configuration-server-overview.md).                                                                        |
| `_AUTH`        | Enable an AuthenticationServer `[authentication_server]`.                                                                                                                                                                             |
| `_DIS`         | Enable a Data Import Server `[db_dis]`.                                                                                                                                                                                               |
| `_WEB`         | Enable a WebServer (web IDE) and a Client Update Service `[web_api_server]`.                                                                                                                                                          |
| `_CONTROLLER`  | Enable a Persistent Query Controller `[iris_controller]`.                                                                                                                                                                             |
| `_ETCD`        | Enable an etcd server on this node. An etcd node need not run any other services. There must be an odd number of etcd nodes. When not specified, the first node or (if available) three nodes are marked as etcd servers.             |
| `_SCHEMA`      | Specify the node (which must run a merge server) to be used to run the Schema Editor for Swing clients. If this value is not specified, the first merge server in the service list is used.                                           |
| `_LAS`         | Enable a Log Aggregator Service. By default, all nodes run a LAS `[log_aggregator_service]`                                                                                                                                           |
| `_TDCP`        | Enable a Table Data Cache Proxy `[db_tdcp]`. By default, all nodes run a Table Data Cache Proxy.                                                                                                                                      |
| `_TAILER`      | Enable a Log Tailer `[tailer1]`. By default, all nodes run a log tailer.                                                                                                                                                              |
| `_LTDS`        | Enable a Local Table Data Service `[db_ltds]`.                                                                                                                                                                                        |
| `_DASHBOARD`   | Enable the Status Dashboard process `[status_dashboard]`. This service requires both `_AUTH` and `_CONFIG` to be enabled on the same node.                                                                                            |
| `_ENVOY`       | Enable Envoy reverse proxy. Note that Envoy configuration also requires that [`DH_CONFIGURE_ENVOY`](#dh_configure_envoy) be set to `true`. When Envoy is enabled, but no node is designated, this defaults to the first Web API node. |

For example, the snippet below enables a merge server on node 4 and disables the query server on node 1:

```properties
# Tell installer that node 4 should run a merge server

DH_NODE_4_ROLE_MERGE=true

# Tell installer that node 1 should NOT run a query server

DH_NODE_1_ROLE_QUERY=false
```

### `DH_NODE_N_ROLE_INFRA`

```properties
DH_NODE_N_ROLE_INFRA="true"
```

The `DH_NODE_N_ROLE_INFRA` flag is a shortcut for enabling the following services: `CONFIG`, `AUTH`, `DIS`, `WEB`, `SCHEMA`, `CONTROLLER`, `DASHBOARD`, and `MERGE`. To remove any of these, set the service to be removed to `false` after setting the `INFRA` flag.

> [!NOTE]
> If you configure infrastructure services individually without using the `INFRA` role, you must explicitly set `DH_NODE_<N>_ROLE_DASHBOARD=true` on a node that also has both `AUTH` and `CONFIG` roles enabled.

**Installer skip flags**

### `DH_SKIP_MONIT_CHECK`

```properties
DH_SKIP_MONIT_CHECK="false"
```

The default value is `false`. When set to `true`, bypass built-in monit health checks. This flag instructs installer scripts to skip all checks and modifications and assume that monit has been configured correctly.

### `DH_SKIP_ALL_MONIT`

```properties
DH_SKIP_ALL_MONIT="false"
```

The default value is `false`. When set to `true`, skip all monit-related operations during installation.

> [!CAUTION]
> Only use this if you know what you are doing. Monit is responsible for monitoring and restarting Deephaven services.

### `DH_SKIP_DB_OWNERSHIP`

```properties
DH_SKIP_DB_OWNERSHIP="false"
```

The default value is `false`. When set to `true`, skip ownership checks for files under `/db/`.

> [!CAUTION]
> Only use this if you have verified that file ownership under `/db/` is correct. This flag is intended for environments with non-standard filesystem ownership constraints.

### `DH_SKIP_ACL_INIT`

```properties
DH_SKIP_ACL_INIT="false"
```

The default value is `false`. When set to `true`, bypass built-in ACL setup checks. The installer assumes that ACLs have been set up correctly.

**etcd**

### `DH_ACLS_USE_ETCD`

```properties
DH_ACLS_USE_ETCD="true"
```

The default value is `true`, which stores Access Control List (ACL) data in etcd.

When set to `false`, ACLs are stored in a MySQL/MariaDB database instead. This requires a SQL database to be available and configured.

> [!NOTE]
> When upgrading from a system that used SQL-based ACLs, you must either set `DH_ACLS_USE_ETCD=false` to continue using SQL, or migrate your ACL data after the upgrade. See [Migrating ACLs to etcd](./basic-install.md#appendix-g-migrating-acls-to-etcd) for details.

### `DH_SKIP_ETCD_IMPORT`

```properties
DH_SKIP_ETCD_IMPORT="false"
```

The default value is `false`. When set to `true`, skip the etcd data import step during installation. This is useful when adding nodes to an existing cluster where etcd data is already populated.

### `DH_ALLOW_ETCD_OFFLINE`

```properties
DH_ALLOW_ETCD_OFFLINE="false"
```

The default value is `false`. When set to `true`, allow the installation to proceed even if etcd is not reachable. This should only be used in special circumstances where etcd will be configured separately.

### `DH_ETCD_TOKEN`

```properties
DH_ETCD_TOKEN=""
```

This property specifies the etcd initial cluster token to use. The token is a unique identifier that prevents different etcd clusters from accidentally merging. Some installations install and configure etcd before installation and pass in the etcd token they used via `DH_ETCD_TOKEN`.

See [etcd tokens](./basic-install.md#etcd-tokens) for details on generating and using etcd tokens.

### `DH_DIR_ETCD_BIN`

```properties
DH_DIR_ETCD_BIN="/usr/bin"
```

This property sets the directory where `etcd` and `etcdctl` binaries are installed. The default value is `/usr/bin`.

The specified directory must exist before performing an installation. If the required etcd binaries are not found in this directory, the installer downloads them from https://github.com/etcd-io/etcd/releases unless [`DH_OFFLINE`](#dh_offline)=true.

### `DH_ETCD_ROOT`

```properties
DH_ETCD_ROOT="false"
```

When set to `true`, this indicates that the root etcd keys are owned by the OS `root` user rather than the etcd service user. Set this flag if your etcd installation was configured with root ownership. The default value is the value of `DH_ROOT` (`false` unless otherwise set).

### `DH_ETCD_IMPORT_NODE`

```properties
DH_ETCD_IMPORT_NODE="node-name"
```

The hostname of the single node responsible for importing Deephaven system files into etcd. By default, this is a single node: the first configured config-server node.

This is useful when adding nodes to an existing cluster where etcd data is already populated, and you want to restrict which node performs the import.

**MySQL**

### `DH_MYSQL_VERSION`

```properties
DH_MYSQL_VERSION="8.0.28"
```

The version of MySQL/MariaDB to use when [`DH_ACLS_USE_ETCD`](#dh_acls_use_etcd) is set to `false`. The default value is `8.0.28`.

### `DH_WEB_FQDN`

Defaults to the [installer-configured domain name](#dh_node_n_domain), of the first Web API node.

When Envoy is not used, this value is written to the `/etc/deephaven/FRONTEND_HOST` file on every Deephaven server, while the default web port, `8123` is written to `/etc/deephaven/FRONTEND_PORT`. When Envoy is used, [`DH_ENVOY_FQDN`](#dh_envoy_fqdn) is written instead.

The `FRONTEND_HOST` and `FRONTEND_PORT` files can be used by [Deephaven client](../admin-glossary.md#deephaven-client) processes running on the remote server to easily find a `FQDN:port` to connect to. For example, the [Core+ Python client](../../clients/python/coreplus-python-client.md) `SessionManager` class uses the `FRONTEND_HOST` and `FRONTEND_PORT` files if you do not specify your own URL to connect to.

**Installer setup**

### `DH_MODIFY_ETC_SUDOERS`

```properties
DH_MODIFY_ETC_SUDOERS="false"
```

The default value is `false`, and the installer fails if sudoers permissions are incorrect.

When set to `true`, the installation scripts detect when sudoers permissions are incorrect and automatically modify `/etc/sudoers` with the correct sudoers permissions.

### `DH_ALLOW_SYSTEMCTL_ENABLE`

```properties
DH_ALLOW_SYSTEMCTL_ENABLE="false"
```

The default value is `false`; when this flag and `DH_MODIFY_ETC_SUDOERS` are both set to `true`, the installer expects that the [`DH_SSH_USER`](#dh_ssh_user) has permission to execute `sudo /usr/bin/systemctl enable /etc/etcd/dh/DH_ETCD_TOKEN/dh-etcd.service`, and will add sudoers rules if necessary.

> [!CAUTION]
> Using this option grants root-equivalent privileges to the `DH_SSH_USER` service account.
> This permission is not necessary if you [set up the dh-etcd.service unit](basic-install.md#appendix-e-dh-etcd-service-unit-file) before running the installer.

Allowing a service account to enable systemd units grants that account privileges to run anything they wish as root.
`DH_ALLOW_SYSTEMCTL_ENABLE` should only be set to true when `DH_SSH_USER` already has full root privileges, or when running installations on low-impact, non-privileged machines.

### `DH_PARALLEL`

```properties
DH_PARALLEL="true"
```

The default value is `true`.

When set to `true`, installation scripts use as much parallelism as possible. This can greatly improve installation speed, especially on large clusters.

> [!CAUTION]
> This setting can cause log messages to interleave and become harder to read. When debugging an installation, you should set `DH_PARALLEL=false` to trade speed for clarity.

### `DH_STRICT`

```properties
DH_STRICT="true"
```

The default value is `true`, which means all `cluster.cnf` entries are validated before performing the installation.

> [!NOTE]
> A value of false should only be used in rare cases when upgrading to a new version of the installer and it is needed to ignore deprecated or removed properties.

**Java**

### `DH_JAVA`

```properties
DH_JAVA="/path/to/java_executable_to_use/bin/java"
```

This variable specifies where the `java` executables are, regardless of the system `PATH`.

`DH_JAVA` works correctly whether you point to a Java executable or a Java installation directory (like "JAVA_HOME").
Both `DH_JAVA=/path/to/java_to_use` and `DH_JAVA=/path/to/java_to_use/bin/java` behave the same.

### `DH_JAVA_VERSION`

```properties
DH_JAVA_VERSION="jdk17"
```

This determines which version of Java to use. Valid values are `jdk11` and `jdk17`. The default value is `jdk17`.

### `DH_JAVA_FORCE_INSTALL`

```properties
DH_JAVA_FORCE_INSTALL="false"
```

The default value is `false`. When set to `true`, force Java installation even if a compatible version is already present on the system.

### `DH_JAVA_PACKAGE`

```properties
DH_JAVA_PACKAGE="temurin-17-jdk"
```

When the [requested version](#dh_java_version) of Java is not installed, this specifies the exact Java package name to use with apt/dnf install. This is normally computed from [`DH_JAVA_VERSION`](#dh_java_version) and is only needed if an installed JDK version was not provided, e.g., if a suitable Java JDK was not already installed on the target nodes for the cluster.

### `DH_JAVA_REPO`

```properties
DH_JAVA_REPO="https://packages.adoptium.net"
```

When the [requested version](#dh_java_version) of Java is not installed, Deephaven adds a repository definition to your remote machine's package manager to install [`DH_JAVA_PACKAGE`](#dh_java_package) using apt/dnf.

When using the default value for `DH_JAVA_REPO`, Deephaven saves the Temurin OpenJDK repositories from adoptium.net into `/etc/apt/sources.list.d/adoptium.list` on Debian distributions and `/etc/yum.repos.d/adoptopenjdk.repo` on RPM-based distributions.

When using a non-default value of `DH_JAVA_REPO`, the repository definition is saved to `/etc/apt/sources.list.d/deephaven-java.list` and `/etc/yum.repos.d/deephaven-java.repo`.

If you do not wish to modify any of these files, pre-install Java on all remote machines.

### `DH_JAVA_GPG_KEY`

```properties
DH_JAVA_GPG_KEY="https://packages.adoptium.net/artifactory/api/gpg/key/public"
```

When the [requested version](#dh_java_version) of Java is not installed, Deephaven adds the Temurin OpenJDK repositories at adoptium.net to your remote machine's package manager so we can install [`DH_JAVA_PACKAGE`](#dh_java_package) using apt/dnf.

The `DH_JAVA_GPG_KEY` variable defines a URL where the installer can download the GPG key used to verify packages in [`DH_JAVA_REPO`](#dh_java_repo).

If you do not wish to download any GPG keys, pre-install Java on all remote machines.

**Python**

### `DH_PYTHON`

```properties
DH_PYTHON="true"
```

The default value is `true`, which means Python is installed on the target node(s).

If the Python version specified by [`DH_PYTHON_VERSION`](#dh_python_version) is not available, the installer downloads and builds it from source. The corresponding `Python-<version>.tgz` file (for example, `Python-3.10.12.tgz`) can be downloaded or locally provided. See [`DH_PYTHON_VERSION`](#dh_python_version) and [`DH_PYTHON_PATCH_VERSION`](#dh_python_patch_version) for options to install other versions of Python. If a different `DH_PYTHON_VERSION` major.minor version is specified, and `DH_PYTHON=true`, the specified version is checked for and installed if not already present.

### `DH_COREPLUS_PYTHON`

```properties
DH_COREPLUS_PYTHON="3.12"
```

Set to the executable or short version of Python to use for creating the default Core+ virtual environment. If set to `false`, then no Core+ virtual environment is created. If [`DH_PYTHON`](#dh_python) is `false`, then `DH_COREPLUS_PYTHON` defaults to `false`; otherwise, it defaults to `3.12`.

The Python installation must already exist on all query and merge servers.

### `DH_PYTHON_VERSION`

```properties
DH_PYTHON_VERSION="3.10"
```

The version of Python to install when [`DH_PYTHON`](#dh_python) is set to `true`. See the [version support matrix](../../reference/supported-versions.md) for valid versions. The default value is `3.10`.

### `DH_PYTHON_PATCH_VERSION`

```properties
DH_PYTHON_PATCH_VERSION="12"
```

> [!NOTE]
> Python versions are of the format `Major.Minor.Patch`. Using the default values for [`DH_PYTHON_VERSION`](#dh_python_version) and `DH_PYTHON_PATCH_VERSION` you would install Python `3.10.12`

This determines which patch version of Python to install when [`DH_PYTHON`](#dh_python) is set to `true`.

Valid values are 0 or higher integers. The corresponding file can be downloaded from `https://www.python.org/ftp/python` or provided to the installer as part of the [installation media](./basic-install.md#collect-installation-media).

The default Python version is `3.10.12`.

**TLS certificates and offline installation**

### `DH_OFFLINE`

```properties
DH_OFFLINE="false"
```

The default value is `false`. When set to `true`, the installer fails if the etcd binary tarball or MySQL connector JAR is not already present — it will not attempt to download them.

> [!NOTE]
> `DH_OFFLINE=true` does not prevent Java or Python from being fetched. Java is installed via the system package manager (apt, dnf, or yum) and Python is downloaded from `https://www.python.org` and built from source if the specified version is not already present. Pre-install Java and Python on all remote machines before running the installer to prevent all network access.

When `DH_OFFLINE` is `false` (the default), the installer automatically downloads the following dependencies if they are not already present:

| Dependency          | Gated by `DH_OFFLINE` | Download source                                          | Pre-place location                                                                          |
| ------------------- | --------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| etcd binary tarball | Yes                   | `https://storage.googleapis.com/etcd`                    | `$DH_LOCAL_DIR/` on the installer host (auto-copied), or `$DH_REMOTE_DIR/lib/` on each node |
| MySQL connector JAR | Yes                   | Deephaven repository                                     | `$DH_LOCAL_DIR/` on the installer host (auto-copied), or `$DH_REMOTE_DIR/lib/` on each node |
| Java JDK            | No                    | System package manager (apt, dnf, or yum)                | Pre-install on remote hosts                                                                 |
| Python              | No                    | `https://www.python.org` (downloaded, built from source) | Pre-install on remote hosts                                                                 |

> [!NOTE]
> The installer does not download resources that are already present on the running system.

> [!TIP]
> For environments with restricted internet access, place `etcd-vVAR::ETCD_VERSION-linux-amd64.tar.gz` in `$DH_LOCAL_DIR/` on the installer host before running the installer — the master install script automatically copies it to `$DH_REMOTE_DIR/lib/` on each remote node. Alternatively, place it directly in `$DH_REMOTE_DIR/lib/` or `/var/lib/deephaven/` on each node.

### `DH_FORCE_NEW_CERTS`

```properties
DH_FORCE_NEW_CERTS="false"
```

The default value is `false`. When set to `true`, it forcibly overwrites all TLS certificates.

> [!CAUTION]
> This should only be set to `true` when you need to rotate keys or certificates are expiring and the Deephaven cluster is not enrolled in a certificate management infrastructure.

### `DH_SKIP_CERT_VALIDATION`

```properties
DH_SKIP_CERT_VALIDATION="false"
```

This defaults to `false`. When set to `true`, additional truststore / certificate validation performed at the end of an installation is bypassed. This flag should only be used if you have verified that your truststore and certificates are correctly formatted or if you plan to repair your certificates after the installation has completed.

### `DH_LOCAL_CERT_DIR`

```properties
DH_LOCAL_CERT_DIR="${DH_LOCAL_DIR}/certs"
```

Directory on the Installation Host containing the per-machine certificate inputs for native installs without Envoy.

For each machine, place:

- `DH_LOCAL_CERT_DIR/<node>.pem`
- `DH_LOCAL_CERT_DIR/<node>.key`

`<node>` matches `DH_NODE_N_HOST` for that machine.

### `DH_CA_CERTIFICATE`

```properties
DH_CA_CERTIFICATE="/path/to/ca-bundle.pem"
```

Optional path on the Installation Host to a PEM-encoded [root CA X.509 certificate bundle](../admin-glossary.md#root-ca-certificate) used to generate [Deephaven-managed TLS truststores](../security/tls-certificates.md#optional-truststore).

Set this flag to specify the CA certificates used to complete the [chain of TLS trust](../admin-glossary.md#tls-chain-of-trust) for the [signing certificates](../admin-glossary.md#signing-certificate) used to sign TLS HTTPS requests. Leave `DH_CA_CERTIFICATE` unset when [TLS clients](../admin-glossary.md#tls-client) should instead rely on [system trust](../admin-glossary.md#system-trust-vs-a-custom-truststore).

When [Envoy is enabled](#dh_configure_envoy) and [`DH_GENERATE_CERTIFICATES=true`](#dh_generate_certificates), then the CA certificate bundle specified by `DH_CA_CERTIFICATE` is only used to verify [Deephaven client](../admin-glossary.md#deephaven-client) TLS connections to the Envoy frontend proxy, and only needs to complete the chain of TLS trust for the [`DH_ENVOY_LOCAL_CERT` signing certificate](#dh_envoy_local_cert). In this scenario, server-to-server TLS connections are instead verified using a Deephaven-generated [internal TLS truststore](../security/tls-certificates.md#internal-tls-trust).

**Package repositories**

### `DH_REPO_URL`

```properties
DH_REPO_URL="https://illumon.jfrog.io/illumon/libs-customer"
```

When installation media for [`DH_VERSION`](#dh_version) is not found on each Remote Host or in [`DH_LOCAL_DIR`](#dh_local_dir) on the Installer Host, the installer downloads the media from Deephaven's jfrog repository, as specified by [`DH_REPO_URL`](#dh_repo_url).

> [!CAUTION]
> To avoid network-related failures, it is recommended that you supply all installation media before running the installation. See [installation media](./basic-install.md#collect-installation-media)

### `DH_REPO_SEGMENT`

```properties
DH_REPO_SEGMENT="iris/illumon-db/VAR::COREPLUS_DHE_VERSION"
```

The repo name segment to use in conjunction with [`DH_REPO_URL`](#dh_repo_url) to calculate download URLs. The default value is `iris/illumon-db/<DH_VERSION>`. This value is not needed when [installation media](./basic-install.md#collect-installation-media) has been provided.

### `DH_REPO_KEY_FILE`

```properties
DH_REPO_KEY_FILE="/path/to/file/containing/repo/password"
```

When using [`DH_REPO_URL`](#dh_repo_url) to download archives, the `DH_REPO_KEY_FILE` specifies a file containing the secret password used to authenticate with Deephaven's jfrog repository. The file is copied to the Remote Host, which downloads the files and erases the key file once complete. This is not needed when [installation media](./basic-install.md#collect-installation-media) has been provided.

### `DH_DND_VERSIONS`

> [!WARNING]
> Deprecated: Instead, use the replacement property, `DH_COREPLUS_VERSIONS`.

### `DH_COREPLUS_VERSIONS`

```properties
DH_COREPLUS_VERSIONS=auto
```

or

```properties
DH_COREPLUS_VERSIONS=VAR::COREPLUS_DHC_VERSION
```

> [!NOTE]
> The recommended setting for this value is `auto`. Do not set this to anything else unless directed by Deephaven support.

A comma-separated list of Core+ versions to install. You must have provided the Core+ installation file (e.g., `deephaven-coreplus-VAR::COREPLUS_DHC_VERSION-VAR::COREPLUS_DHE_VERSION.tgz`) that corresponds to the [DH_VERSION](#dh_version) and Core+ version that you are requesting.

The installer expects the installation file to be located in `$DH_LOCAL_DIR/` along with the other installation media. The Installer searches the same paths as documented in [DH_VERSION](#dh_version)

The installer sets the `/usr/illumon/coreplus/latest` link to the first specified version. If you install multiple versions, you must edit your `iris-environment.prop` file to include appropriate [WorkerKind definitions](./customize-basic-install.md) for those versions.

You may also set `DH_COREPLUS_VERSIONS` to the special properties `none` or `auto`. When selecting `auto`, the installer selects the same version of Deephaven Community that was built and tested with your selected version of Deephaven Enterprise. When selecting `none`, Core+ is not installed or upgraded.

### `DH_USE_EPEL`

```properties
DH_USE_EPEL="true"
```

Set to `false` to tell Fedora-based operating systems (Red Hat, Rocky) to exclude the automatically added epel-release upstream source.
This is useful when you have your own RPM repositories to supply operating system dependencies and do not wish to include the epel repository.

## Envoy properties

When configuring Envoy automatically, the installer sets the necessary properties in `iris-endpoints.prop`, adjusts `getdown.global`, generates `envoy3.yaml`, and writes the configured Envoy certificate path into that YAML. The [Envoy configuration doc](../envoy/configuring-envoy.md#native-installer-envoy-properties) gives a high-level overview of how these properties affect your installation.

### `DH_CONFIGURE_ENVOY`

```properties
DH_CONFIGURE_ENVOY="false"
```

The default value is `false`.

When set to `true`, the installer configures Deephaven to route client traffic through Envoy.

If `DH_CONFIGURE_ENVOY=true`, the installer:

- Updates [Deephaven properties](../admin-glossary.md#deephaven-property) to configure [Deephaven clients](../admin-glossary.md#deephaven-client) to connect to the Deephaven cluster through Envoy.
- Generates [`envoy3.yaml`](../envoy/configuring-envoy.md#envoy-yaml-file) matching your cluster's network topology.
- Optionally, installs and selectively restarts Envoy depending on the [`DH_ENVOY_INSTALL_MODE`](#dh_envoy_install_mode).

### `DH_NODE_N_ROLE_ENVOY`

Set to `true` to specify the machine where Envoy runs.

If [`DH_CONFIGURE_ENVOY=true`](#dh_configure_envoy), and `DH_NODE_N_ROLE_ENVOY` is not specified, the first `DH_NODE_N_ROLE_WEB=true` node is selected to run Envoy.

### `DH_ENVOY_INSTALL_MODE`

Controls whether Deephaven installs and manages Envoy on the Envoy node.

- `NONE` - Envoy remains manually managed (default).
  - You must [install](../envoy/installing-envoy.md#manual-envoy-installation), [upgrade](../envoy/installing-envoy.md#manual-envoy-upgrade) and restart Envoy whenever upgrading Deephaven.
- `PODMAN` - the installer manages an Envoy container under `systemd`.
  - Recommended for Rocky and RedHat-based Operating Systems.
  - Sets up a Podman quadlet for smooth systemd integration.
  - Container lifecycle is managed by `systemctl <operation> deephaven_envoy`.
- `DOCKER` - the installer manages an Envoy container under `systemd`.
  - Recommended for all Ubuntu and Debian-based Operating Systems.
  - Sets up a root systemd service that uses `docker run --rm` to stay directly attached to the container, for graceful restarts.
  - Container lifecycle is managed by `systemctl <operation> deephaven_envoy`.
- `NATIVE` - the installer manages a native Envoy service.
  - Downloads an Envoy binary from Envoy's GitHub releases page.
  - Creates a systemd user service to run Envoy as `DH_ADMIN_USER`.
  - Container lifecycle is managed by the `DH_ADMIN_USER`:
    ```
    export XDG_RUNTIME_DIR=/run/user/$(id -u)
    systemctl --user <operation> deephaven_envoy
    ```

> [!WARNING]
> If you are upgrading a pre-existing Envoy-enabled cluster,
> before you set `DH_ENVOY_INSTALL_MODE` to any value other than `NONE`,
> make sure you [Uninstall any manually-managed Envoy processes](../envoy/installing-envoy.md#uninstall-envoy).

### `DH_GENERATE_CERTIFICATES`

```properties
DH_GENERATE_CERTIFICATES="true"
```

Only used when `DH_CONFIGURE_ENVOY=true`.

This flag defaults to true when Envoy is enabled. When `DH_GENERATE_CERTIFICATES=true`, Deephaven generates per-node TLS certificates for every machine, so you only need to provide one certificate via `DH_ENVOY_LOCAL_CERT` regardless of the size of your cluster.

When `DH_GENERATE_CERTIFICATES=false`, you must provide one certificate/key pair per machine, and each machine's certificate must cover the value of `DH_NODE_N_DOMAIN` for that node.

### `DH_ENVOY_LOCAL_CERT`

```properties
DH_ENVOY_LOCAL_CERT="${DH_LOCAL_DIR}/certs/envoy.pem"
```

Path on the Installation Host to the Envoy certificate input.

This file must be a single concatenated PEM bundle containing:

1. the certificate chain Envoy presents to clients, followed by
2. the private key for that certificate.

The [Envoy configuration guide](../envoy/configuring-envoy.md#tls-certificates) gives high-level details about the TLS certificate requirements and PEM bundle format.

### `DH_ENVOY_REMOTE_CERT`

```properties
DH_ENVOY_REMOTE_CERT="/etc/deephaven/certs/envoy.pem"
```

Path on the Envoy node where the installer copies the Envoy PEM bundle.

### `DH_ENVOY_PEM_PATH`

Runtime path that Envoy reads, and the value written into the generated `envoy3.yaml`.

Default runtime paths:

- `NATIVE`: `/etc/deephaven/certs/envoy.pem`
- `DOCKER` / `PODMAN` / `NONE`: `/envoy.pem`

The FQDN settings below are used when configuring properties, generated YAML, and client-facing URLs so Envoy and Deephaven services can find each other.

> [!WARNING]
> When using Deephaven managed Envoy installation with `PODMAN` or `DOCKER` installation methods, the `DH_ENVOY_PEM_PATH` is mounted as a volume in your container, but only when Envoy is first installed. If you change this location, you will need to `systemctl edit deephaven_envoy` to alter this volume mount as well.

### `DH_ENVOY_FQDN`

`DH_ENVOY_FQDN` determines the hostname that all Deephaven clients use to connect to your cluster.

Defaults to the [`DH_NODE_N_DOMAIN`](#dh_node_n_domain) of the [`DH_NODE_N_ROLE_ENVOY`](#dh_node_n_role_envoy) node. The default Envoy node is the first Web API node, if `DH_NODE_N_ROLE_ENVOY` is not specified.

The `DH_ENVOY_FQDN` is used to configure the `envoy.front.proxy.url` Deephaven property, which is what the product uses to determine whether Deephaven clients are allowed to connect directly to Deephaven servers or not.

Additionally, `DH_ENVOY_FQDN` is written to `/etc/deephaven/FRONTEND_HOST` on every Deephaven server, while the `DH_ENVOY_PORT` (default `8000`) is written to `/etc/deephaven/FRONTEND_PORT`. When Envoy is not used, `DH_WEB_FQDN` is written instead.

The `FRONTEND_HOST` and `FRONTEND_PORT` files can be used by Deephaven client processes running on the remote server to easily find a `FQDN:port` to connect to. For example, the Core+ Python client `SessionManager` class uses the `FRONTEND_HOST` and `FRONTEND_PORT` files if you do not specify your own URL to connect to.

### `DH_ENVOY_PORT`

```properties
DH_ENVOY_PORT=8000
```

The port where the Envoy server receives Deephaven client traffic.

If set to `443`, worker URLs omit the port, but you require administrative privileges to use this port.

This value is also used, in conjunction with `DH_ENVOY_FQDN` to define the default host and port used by Deephaven client processes that are running on a Deephaven server.

### `DH_ENVOY_ENABLE_ADMIN`

Whether to enable the Envoy administration page.

```properties
DH_ENVOY_ENABLE_ADMIN=false
```

> [!CAUTION]
> Opening the Envoy admin port exposes your cluster's information, stability, and integrity to your network.
> While it is a valuable debugging tool, be sure to enable it with minimum scope, and to disable it when you are done.

The admin interface must be enabled in Envoy YAML, Envoy must be restarted, and the relevant ports exposed before you can interact with the Envoy administration page.

### `DH_ENVOY_ADMIN_PORT`

```properties
DH_ENVOY_ADMIN_PORT=8001
```

If `DH_ENVOY_ENABLE_ADMIN=true`, choose which port to host the Envoy administration server.

The installer writes this value into `envoy.yaml`, and if `DH_ENVOY_INSTALL_MODE` is used to install Envoy with Podman or Docker, the admin port is opened through the container. If you later change the admin port, you may need to use `systemctl edit deephaven_envoy` to update the container with your desired port mapping. Make sure to `systemctl daemon-reload` when you are done editing.

### `DH_ENVOY_CLUSTER_TYPE="STRICT_DNS"`

Determines how Envoy uses DNS. Options are:

- `STATIC` - Use only IP addresses for endpoints. When `STATIC` is used, the installer sets IP addresses instead of hostnames in the Envoy config YAML.
- `STRICT_DNS` - Make a DNS call each time an address needs to be resolved.
- `LOGICAL_DNS` - Make a DNS call once for an address and cache the results.

### `DH_ENVOY_COPY_YAML`

```properties
DH_ENVOY_COPY_YAML=true
```

Whether the installer should try to copy the generated `envoy3.yaml` Envoy configuration file to the host where Envoy is running. The default and most common configuration is for Envoy to run on the Web API node. If this setting is enabled, the installer copies the file to `/etc/sysconfig/illumon.d/resources` on the configured node.

> [!TIP]
> If Envoy is running on a separate system, the file copy step can be disabled by setting `DH_ENVOY_COPY_YAML=false` in the `cluster.cnf` file. An alternate location for Envoy can be specified by setting the `DH_ENVOY_FQDN` property in `cluster.cnf`.

## Custom user accounts

If you are unable to use the default [Deephaven service account](../admin-glossary.md#deephaven-service-accounts) usernames, you may change them using the following settings. For a complete overview of how these accounts work together, see [OS users and groups](./os-users-and-groups.md).

### `DH_MONIT_USER`

```properties
DH_MONIT_USER=irisadmin
```

The OS user account to run Monit. The default value is `irisadmin`. If the user does not exist, the installer creates one.

> [!NOTE]
> This can be the same user as your [`DH_SSH_USER`](#dh_ssh_user) service account

The user must have sudoer privileges to run as the [`DH_ADMIN_USER`](#dh_admin_user), [`DH_MERGE_USER`](#dh_merge_user), and [`DH_QUERY_USER`](#dh_query_user). See [Sudoers](./basic-install.md#appendix-d-sudoers) for more details.

### `DH_MONIT_GROUP`

```properties
DH_MONIT_GROUP=irisadmin
```

The OS group to use to run monit. The default value is the same name as [`DH_MONIT_USER`](#dh_monit_user) and is created if missing.

### `DH_MONIT_RC`

```properties
DH_MONIT_RC="/etc/monitrc"
```

The path to the monit configuration file. Inferred from [`DH_OS`](#dh_os) using system defaults:

- RHEL/Rocky: `/etc/monitrc`
- Ubuntu: `/etc/monit/monitrc`

> [!NOTE]
> This is inferred from [`DH_OS`](#dh_os). Only set this explicitly if your system uses a non-standard monit configuration file location — for example, if the OS detection logic does not correctly identify your installed configuration.

### `DH_MONIT_ROOT`

```properties
DH_MONIT_ROOT="false"
```

The default value is `false`. When set to `true`, monit is run and owned by the OS `root` user rather than [`DH_MONIT_USER`](#dh_monit_user).

> [!NOTE]
> `DH_MONIT_ROOT=false` is the only value currently supported.

### `DH_MONIT_LOG_DIR`

```properties
DH_MONIT_LOG_DIR="/var/log/deephaven/monit"
```

The directory where monit writes its log files. The default value is `/var/log/deephaven/monit`. When [`DH_MONIT_USER`](#dh_monit_user) is `root`, the default is `/var/log`.

### `DH_SHARED_GROUP`

```properties
DH_SHARED_GROUP=dbmergegrp
```

The OS group to use for ownership of files that must be shared between [`DH_ADMIN_USER`](#dh_admin_user), [`DH_MERGE_USER`](#dh_merge_user), and [`DH_QUERY_USER`](#dh_query_user). This defaults to `dbmergegrp`.

This group must be the primary group for these three Deephaven system accounts, and any files which must be readable by all three OS users should have group ownership of `DH_SHARED_GROUP` (or `DH_SHARED_QUERY_GROUP`, described below, if you wish to share data beyond Deephaven system accounts).

If the `DH_SHARED_GROUP` group does not exist, it is created and set as the OS primary (default) group for the [`DH_ADMIN_USER`](#dh_admin_user), [`DH_MERGE_USER`](#dh_merge_user), and [`DH_QUERY_USER`](#dh_query_user) accounts.

### `DH_ADMIN_USER`

```properties
DH_ADMIN_USER=irisadmin
```

The OS user to run administrative services such as the query controller, authentication and configuration servers. The default value is `irisadmin`. This user account is created if it does not exist. Both the [`DH_SSH_USER`](#dh_ssh_user) and [`DH_MONIT_USER`](#dh_monit_user) must be able to sudo as `DH_ADMIN_USER : DH_ADMIN_GROUP`.

> [!CAUTION]
> Restrict access to this user account as much as possible.

### `DH_ADMIN_GROUP`

```properties
DH_ADMIN_GROUP=irisadmin
```

The OS group used primarily for file permissions. This defaults to the same name as [`DH_ADMIN_USER`](#dh_admin_user). If the group does not exist, it is created.

The primary group for [`DH_ADMIN_USER`](#dh_admin_user) must be [`DH_SHARED_GROUP`](#dh_shared_group) (typically `dbmergegrp`), _NOT_ `DH_ADMIN_GROUP` (typically `irisadmin`).

To check your primary group, run:

```shell
id "${DH_ADMIN_USER:-irisadmin}"
# expect output similar to: uid=9002(irisadmin) gid=9003(dbmergegrp) groups=9003(dbmergegrp),9004(dbquerygrp),9002(irisadmin)
# the gid= represents the primary group, groups= are the complete group membership list
```

### `DH_MERGE_USER`

```properties
DH_MERGE_USER=dbmerge
```

The OS user to use when running merge processes (allowed to write historical data). This defaults to `dbmerge`. It is created if it does not exist.

> [!CAUTION]
> It is strongly discouraged to set `DH_MERGE_USER == DH_ADMIN_USER` or `DH_MONIT_USER` because it grants administrative privileges to any user allowed to run queries on the merge server. The `DH_MONIT_USER` and `DH_SSH_USER` must be able to use sudo as `DH_MERGE_USER : DH_MERGE_GROUP`.

### `DH_MERGE_GROUP`

```properties
DH_MERGE_GROUP=dbmerge
```

The OS group to use for files that are only readable by `DH_MERGE_USER`. This defaults to the same name as [`DH_MERGE_USER`](#dh_merge_user). It is created if it does not exist.

> [!NOTE]
> Processes are run using [`DH_SHARED_GROUP`](#dh_shared_group), so files created by merge processes are visible to other OS user accounts.

The primary group for [`DH_MERGE_USER`](#dh_merge_user) must be [`DH_SHARED_GROUP`](#dh_shared_group) (typically `dbmergegrp`), _NOT_ `DH_MERGE_GROUP` (typically `dbmerge`).

### `DH_QUERY_USER`

```properties
DH_QUERY_USER=dbquery
```

The OS user to use when running query processes. This defaults to `dbquery`. It is created if it does not exist.
The primary group for `DH_QUERY_USER` must be [`DH_SHARED_GROUP`](#dh_shared_group) (typically `dbmergegrp`), _NOT_ [`DH_QUERY_GROUP`](#dh_query_group) (typically `dbquery`).

> [!CAUTION]
> It is strongly discouraged to set `DH_QUERY_USER == DH_ADMIN_USER` or `DH_MONIT_USER` because this grants administrative privileges to any user allowed to run code on the query server. The `DH_MONIT_USER` and `DH_SSH_USER` must be able to use sudo as `DH_QUERY_USER : DH_QUERY_GROUP`.

### `DH_QUERY_GROUP`

```properties
DH_QUERY_GROUP=dbquery
```

The OS group to use for files that are only readable by `DH_QUERY_USER`. This defaults to the same name as [`DH_QUERY_USER`](#dh_query_user) (`dbquery`). It is created if it does not exist.

> [!NOTE]
> Processes are run using [`DH_SHARED_GROUP`](#dh_shared_group), so files created by query processes are visible to other OS user accounts.

### `DH_SHARED_QUERY_GROUP`

```properties
DH_SHARED_QUERY_GROUP=dbquerygrp
```

The OS group to use for ownership of files that must be shared between any operating system user that you want to be able to run a Deephaven worker / query / console. The default value is `dbquerygrp`.

All three system users, [`DH_ADMIN_USER`](#dh_admin_user), [`DH_MERGE_USER`](#dh_merge_user), and [`DH_QUERY_USER`](#dh_query_user) must have secondary group membership in the `DH_SHARED_QUERY_GROUP`, but you may also allow any operating system user to start Deephaven sessions by granting them membership to `DH_SHARED_QUERY_GROUP`. See the [Configuration guide](../configuration/per-user-workers.md) for more information.

### `DH_ETCD_USER`

```properties
DH_ETCD_USER=etcd
```

The OS user that runs the `dh-etcd` process on Etcd server machines.

All sensitive Etcd server secrets are owned by `DH_ETCD_USER`, while Etcd client secrets are owned by `DH_ADMIN_USER`. Some Etcd installation methods create and use the username `etcd`, so the default `DH_ETCD_USER` is also `etcd`.

> [!TIP]
> Setting `DH_ETCD_USER` to the same username as `DH_ADMIN_USER` can simplify file permissions / sudoers rules, in exchange for increased risk if your `DH_ADMIN_USER` account is compromised.
> The Etcd server directories, `/etc/etcd/dh` and `/var/lib/etcd`, require `DH_ETCD_USER:DH_ADMIN_GROUP` ownership to share some files with `DH_ADMIN_USER`.
> Deephaven replaces the default `etcd` systemd service with a `dh-etcd` service, so it is safe to change the username.

> [!WARNING]
> Changing `DH_ETCD_USER` after setting up an Etcd machine is an advanced operation which is not recommended.
> You will need to run the following commands on all Etcd server machines:
>
> - `chown -R ${DH_ETCD_USER:?} /etc/etcd/dh /var/lib/etcd/dh`
> - `systemctl edit dh-etcd.service`
>   In your text editor, add the `[Service]` header if missing, and under that, set `User=<your-username>`.
> - `systemctl --daemon-reload`
> - `systemctl restart dh-etcd.service`

### `DH_USER_HOME`

```properties
DH_USER_HOME=/db/TempFiles
```

The expected location for the user `HOME` directory of all Deephaven system users. This property is _only_ used when any of the three system users do not already exist and the installation process must create the service account user.

If you pre-create your own administrative users before running the Deephaven installer,
you must update this directory to the correct `HOME` directories of `DH_ADMIN_USER`, `DH_MERGE_USER` and `DH_QUERY_USER`.

> [!WARNING]
> Beware that `/db/TempFiles/<usernames>` paths will still be created and used for all users that run Deephaven queries or workers of any kind, regardless of where the user's `HOME` directory resides.

### Home directories

Default `HOME` directories for [Deephaven system users](../admin-glossary.md#deephaven-service-accounts) are under `/db/TempFiles`.

If you pre-create the Deephaven service accounts with a different `HOME` directory, set [`DH_USER_HOME`](#dh_user_home) in `cluster.cnf` to match your chosen `HOME` directory.

Regardless of where your system user's `HOME` directories are located, `/db/TempFiles/<username>` directories will store some account-specific configuration values, and also serve as a scratchpad space for caching dynamically compiled Java classes for workers.

## Configuration directory links

These variables allow you to manage certain Deephaven configuration directories with an external tool such as a configuration manager (Puppet, Ansible, or Chef). When set, Deephaven replaces the target directory with a symlink to the specified path and will not back up or modify files in it.

> [!CAUTION]
> The linked path must exist and be readable by [`DH_ADMIN_USER`](#dh_admin_user) before the installer runs. Because Deephaven will not back up the linked directories, ensure the contents are correct before installation — there is no automatic recovery path if the linked path is missing or incorrect.

### `DH_LINK_RESOURCES`

```properties
DH_LINK_RESOURCES="/path/to/resources"
```

If set, the `/etc/sysconfig/illumon.d/resources` directory is replaced with a symlink to the specified path. Deephaven will not back up or alter any files in the resources directory.

### `DH_LINK_HOSTCONFIG`

```properties
DH_LINK_HOSTCONFIG="/path/to/hostconfig"
```

If set, the `/etc/sysconfig/illumon` hostconfig symlink (or the versioned `illumon.iris.hostconfig` link target) is replaced to point to the specified hostconfig file. Deephaven will not back up or alter the linked host configuration file.

### `DH_LINK_OVERRIDE`

```properties
DH_LINK_OVERRIDE="/path/to/override"
```

If set, the `/etc/sysconfig/illumon.d/override` directory is replaced with a symlink to the specified path. Deephaven will not back up or alter any override files.

### `DH_LINK_HOTFIXES`

```properties
DH_LINK_HOTFIXES="/path/to/hotfixes"
```

If set, the `/etc/sysconfig/illumon.d/hotfixes` directory is replaced with a symlink to the specified path. Deephaven will not back up or alter any hotfix files.

## Related documentation

- [Basic installation](./basic-install.md)
- [Installation planning](./installation-planning.md)
- [Resilience planning](../architecture/resilience-planning/resilience-planning-overview.md)
- [Envoy configuration](../envoy/envoy.md)
