> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-parallel-read-in-order-multi-part.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> This page explains how ClickHouse server can be configured with configuration files in XML or YAML syntax.

# Configuration Files

<Note>
  XML-based settings profiles and configuration files are not supported for ClickHouse Cloud. Therefore, in ClickHouse Cloud, you won't find a config.xml file. Instead, you should use SQL commands to manage settings through settings profiles.

  For further details, see ["Configuring Settings"](/products/cloud/reference/settings)
</Note>

The ClickHouse server can be configured with configuration files in XML or YAML syntax.
In most installation types, the ClickHouse server runs with `/etc/clickhouse-server/config.xml` as the default configuration file, but it is also possible to specify the location of the configuration file manually at server startup using command line option `--config-file` or `-C`.
When neither of these options is given, the server looks for `config.xml`, `config.yaml` and `config.yml`, in this order, in the current working directory, and uses the first one that exists.
If none of them exists, the server starts with the configuration embedded into the binary.
A file requested with `--config-file` is used as is: if it does not exist, the server reports an error instead of looking for a file with a different extension.
`clickhouse-keeper` follows the same rules with `keeper_config.xml`, `keeper_config.yaml` and `keeper_config.yml`.
Additional configuration files may be placed into directory `config.d/` relative to the main configuration file, for example into directory `/etc/clickhouse-server/config.d/`.
Files in this directory and the main configuration are merged in a preprocessing step before the configuration is applied in ClickHouse server.
Configuration fragments are merged in lexicographical order by their full paths. For files in the standard `config.d/` directory, this is equivalent to ordering by file name. The legacy `conf.d/` directory is also merged; because `conf.d` sorts before `config.d`, all its fragments are processed first when both directories exist.
To simplify updates and improve modularization, it is a best practice to keep the default `config.xml` file unmodified and place additional customization into `config.d/`.
The ClickHouse keeper configuration lives in `/etc/clickhouse-keeper/keeper_config.xml`.
Similarly, additional configuration files for Keeper need to be placed in `/etc/clickhouse-keeper/keeper_config.d/`.

It is possible to mix XML and YAML configuration files, for example you could have a main configuration file `config.xml` and additional configuration files `config.d/network.xml`, `config.d/timezone.yaml` and `config.d/keeper.yaml`.
Mixing XML and YAML within a single configuration file is not supported.
XML configuration files should use `<clickhouse>...</clickhouse>` as the top-level tag.
In YAML configuration files, `clickhouse:` is optional, if absent the parser inserts it automatically.

<h2 id="merging">
  Merging configuration
</h2>

Two configuration files (usually the main configuration file and another configuration file from `config.d/`) are merged as follows:

* If a node (i.e. a path leading to an element) appears in both files and does not have attributes `replace` or `remove`, it is included in the merged configuration file and children from both nodes are included and merged recursively.
* If one of the two nodes contains the `replace` attribute, it is included in the merged configuration file but only children from the node with attribute `replace` are included.
* If one of the two nodes contains the `remove` attribute, the node is not included in the merged configuration file (if it exists already, it is deleted).

For example, given two configuration files:

```xml title="config.xml" theme={null}
<clickhouse>
    <config_a>
        <setting_1>1</setting_1>
    </config_a>
    <config_b>
        <setting_2>2</setting_2>
    </config_b>
    <config_c>
        <setting_3>3</setting_3>
    </config_c>
</clickhouse>
```

and

```xml title="config.d/other_config.xml" theme={null}
<clickhouse>
    <config_a>
        <setting_4>4</setting_4>
    </config_a>
    <config_b replace="replace">
        <setting_5>5</setting_5>
    </config_b>
    <config_c remove="remove">
        <setting_6>6</setting_6>
    </config_c>
</clickhouse>
```

The resulting merged configuration file will be:

```xml theme={null}
<clickhouse>
    <config_a>
        <setting_1>1</setting_1>
        <setting_4>4</setting_4>
    </config_a>
    <config_b>
        <setting_5>5</setting_5>
    </config_b>
</clickhouse>
```

<h3 id="from_env_zk">
  Substitution by environment variables and ZooKeeper nodes
</h3>

To specify that a value of an element should be replaced by the value of an environment variable, you can use the attribute `from_env`.

For example, with environment variable `$MAX_QUERY_SIZE = 150000`:

```xml theme={null}
<clickhouse>
    <profiles>
        <default>
            <max_query_size from_env="MAX_QUERY_SIZE"/>
        </default>
    </profiles>
</clickhouse>
```

Thw resulting configuration will be:

```xml theme={null}
<clickhouse>
    <profiles>
        <default>
            <max_query_size>150000</max_query_size>
        </default>
    </profiles>
</clickhouse>
```

The same is possible using `from_zk` (ZooKeeper node):

```xml theme={null}
<clickhouse>
    <postgresql_port from_zk="/zk_configs/postgresql_port"/>
</clickhouse>
```

```shell theme={null}
# clickhouse-keeper-client
/ :) touch /zk_configs
/ :) create /zk_configs/postgresql_port "9005"
/ :) get /zk_configs/postgresql_port
9005
```

Resulting in the following configuration:

```xml theme={null}
<clickhouse>
    <postgresql_port>9005</postgresql_port>
</clickhouse>
```

<h4 id="value-interpretation">
  How values are interpreted
</h4>

`from_env` and `from_zk` differ in how the substituted value is interpreted:

* A direct value substituted via `from_env` is taken as literal text. XML special characters such as `&`, `<` and `>` are escaped automatically, so an environment variable can contain any XML-representable value, for example `a&b<c>d`, without breaking the configuration (see the note on XML-illegal control characters below). A direct value is never interpreted as XML, even if it happens to look like an XML fragment: `<a>1</a>` substitutes the literal text `<a>1</a>`. This also applies when the direct attribute is placed on an ordinary container such as `<profiles from_env="…"/>`: an existing XML-subtree substitution must be migrated to `<profiles><include from_env="…"/></profiles>`. For backward compatibility, `<include from_env="…"/>` is different: it parses the environment variable as an XML fragment and splices its children into the parent element.
* A value substituted via `from_zk` depends on whether it begins with `<`. A value that begins with `<` is always parsed as an XML fragment: this is how a subtree is spliced into any element, both a structural `<include from_zk="…"/>` and an ordinary container such as `<profiles from_zk="…"/>`; it is kept for backward compatibility, because earlier versions always interpreted a `from_zk` value as XML. A non-`<` value is parsed as a YAML subtree only with the explicit form `<include from_zk="…" yaml="true"/>`; malformed YAML then rejects the configuration. The `yaml="true"` attribute enables YAML parsing wherever the generic `<include>` form is used, including inside a leaf element, so do not use it for a literal setting or secret. Without `yaml="true"`, a non-`<` value is literal text, including when it is used through the generic leaf-replacement form `<password><include from_zk="/secret"/></password>`. This preserves values that happen to contain YAML syntax or are malformed YAML, such as `abc # rotated` or `[1`. For that form, exact bytes are preserved only when the `<include>` is inline with no surrounding whitespace text nodes; for secrets and leaf settings where exact bytes matter, prefer the direct `<password from_zk="…"/>` form. On any other element — whether a leaf substitution such as `<some_setting from_zk="…"/>` or `<password from_zk="…"/>`, or an ordinary container such as `<profiles from_zk="…"/>` — a non-`<` value is also kept as literal text using its exact original bytes (XML special characters are escaped automatically, the same as for `from_env`), so a value such as `abc: def` stays the literal text `abc: def` instead of becoming an `<abc>def</abc>` sub-element. To splice a subtree into an ordinary element (rather than a structural `<include>`), provide it as an XML fragment (a value beginning with `<`).

<Note>
  **Literal values must be valid XML 1.0 text**

  A literal substitution (`from_env`, or a non-`<` leaf `from_zk` value) preserves the exact bytes of the value for every character that XML 1.0 can represent as text. Control characters that are illegal in XML 1.0 — `0x00`–`0x08`, `0x0B`, `0x0C` and `0x0E`–`0x1F` — cannot be carried through an XML configuration at all (the XML specification forbids them even as numeric character references such as `&#1;`), and a value containing one is rejected when the substitution is processed. Tab (`\t`), line feed (`\n`) and carriage return (`\r`) are legal and round-trip byte-for-byte.
</Note>

<Note>
  **Upgrade behaviour for entity-encoded leaf values**

  Earlier versions reparsed every direct `from_env` value as XML, so a raw `&`, `<` or `>` was rejected as not well-formed and the only way to embed one was to XML-entity-encode it: an environment variable set to `a&amp;b` decoded to `a&b`, `&lt;a&gt;1&lt;/a&gt;` decoded to `<a>1</a>`, and `&#13;` decoded to a carriage return. A direct `from_env` value is now literal text, so those same environment values resolve to the literal `a&amp;b`, `&lt;a&gt;1&lt;/a&gt;` and `&#13;`. This means only *plain-text* values keep their previous meaning unchanged: an environment value that was entity-encoded for the old XML path must be set raw instead (for example set `a&b`, which the old path rejected but the new one accepts as the literal text `a&b`).

  Earlier versions reparsed every leaf `from_zk` value as XML, so a raw `&`, `<` or `>` was rejected as not well-formed and the only way to embed one was to XML-entity-encode it: a value stored as `a&amp;b` decoded to `a&b`, `&lt;a&gt;1&lt;/a&gt;` decoded to `<a>1</a>`, and `&#13;` decoded to a carriage return. A non-`<` leaf value is now kept as its exact original bytes, so those same nodes now resolve to the literal `a&amp;b`, `&lt;a&gt;1&lt;/a&gt;` and `&#13;`. This means only *plain-text* scalars keep their previous meaning unchanged: a leaf value that was entity-encoded for the old XML path must be stored raw instead (for example store `a&b`, which the old path rejected but the new one accepts as the literal text `a&b`).

  The same change applies to a plain scalar substituted through an inline `<include from_zk="…"/>` under a leaf setting or a secret, for example `<password><include from_zk="/secret"/></password>`: a scalar is now kept as its exact original bytes there too, so `/secret = a&amp;b` (which used to decode to `a&b`) now resolves to the literal `a&amp;b` and must be stored raw as `a&b` instead. Do not use surrounding whitespace for this form, because that whitespace is part of the resulting setting value; prefer the direct `<password from_zk="…"/>` form when exact bytes matter. (A `from_zk` value that begins with `<`, or a YAML subtree referenced with `<include from_zk="…" yaml="true"/>`, is unaffected — only unmarked non-`<` values are kept literal.)
</Note>

<h4 id="default-values">
  Default values
</h4>

An element with the `from_env` or `from_zk` attributes may additionally have the attribute `replace="1"` (the latter must appear before `from_env`/`from_zk`).
In this case, the element may define a default value.
The element takes on the value of the environment variable or ZooKeeper node if set, otherwise it takes on the default value.

The previous example is repeated, but assuming `MAX_QUERY_SIZE` is not set:

```xml theme={null}
<clickhouse>
    <profiles>
        <default>
            <max_query_size replace="1" from_env="MAX_QUERY_SIZE">150000</max_query_size>
        </default>
    </profiles>
</clickhouse>
```

Resulting in configuration:

```xml theme={null}
<clickhouse>
    <profiles>
        <default>
            <max_query_size>150000</max_query_size>
        </default>
    </profiles>
</clickhouse>
```

<h2 id="substitution-with-file-content">
  Substitution with file content
</h2>

It is also possible to replace parts of the configuration by file contents. This can be done in two ways:

* *Substituting Values*: If an element has the attribute `incl`, its value will be replaced by the content of the referenced file. The path to the file with substitutions is set by the [`include_from`](/reference/settings/server-settings/settings/other#include_from) element in the server config; there is no default path, so substitutions are only read when it is specified. The substitution values are specified in `/clickhouse/substitution_name` elements in this file. If a substitution specified in `incl` does not exist, it is recorded in the log. To prevent ClickHouse from logging missing substitutions, specify attribute `optional="true"` (for example, settings for [macros](/reference/settings/server-settings/settings/other#macros)).
* *Substituting elements*: If you want to replace the entire element with a substitution, use `include` as the element name. The element name `include` can be combined with the attribute `from_zk = "/path/to/node"`. In this case, the element value is replaced by the contents of the ZooKeeper node at `/path/to/node`. This also works with you store an entire XML subtree as a Zookeeper node, it will be fully inserted into the source element.

<Note>
  Changed in version 26.8: before that version, the file `/etc/metrika.xml` was used implicitly whenever it existed, even when `include_from` was not specified. If you rely on that file, specify its path in `include_from` explicitly. Note that `include_from` is read from each configuration file individually: files that are loaded separately from the main server configuration — the users' configuration (e.g. `users.xml` when it is not included in the main file) and XML dictionary configurations — each need their own `include_from` element; specifying it only in the main server configuration does not apply to them.
</Note>

An example of this is shown below:

```xml theme={null}
<clickhouse>
    <!-- Appends XML subtree found at `/profiles-in-zookeeper` ZK path to `<profiles>` element. -->
    <profiles from_zk="/profiles-in-zookeeper" />

    <users>
        <!-- Replaces `include` element with the subtree found at `/users-in-zookeeper` ZK path. -->
        <include from_zk="/users-in-zookeeper" />
        <include from_zk="/other-users-in-zookeeper" />
    </users>
</clickhouse>
```

If you want to merge the substituting content with the existing configuration instead of appending, you can use the attribute `merge="true"`. For example: `<include from_zk="/some_path" merge="true">`. In this case, the existing configuration will be merged with the content from the substitution and the existing configuration settings will be replaced with values from the substitution.

<h2 id="encryption">
  Encrypting and hiding configuration
</h2>

You can use symmetric encryption to encrypt a configuration element, for example, a plaintext password or private key.
To do so, first configure the [encryption codec](/reference/statements/create/table/codec#encryption-codecs), then add the attribute `encrypted_by` with the name of the encryption codec as the value to the element to encrypt.

Unlike attributes `from_zk`, `from_env` and `incl`, or element `include`, no substitution (i.e. decryption of the encrypted value) is performed in the preprocessed file.
Decryption happens only at runtime in the server process.

For example:

```xml theme={null}
<clickhouse>

    <encryption_codecs>
        <aes_128_gcm_siv>
            <key_hex>00112233445566778899aabbccddeeff</key_hex>
        </aes_128_gcm_siv>
    </encryption_codecs>

    <interserver_http_credentials>
        <user>admin</user>
        <password encrypted_by="AES_128_GCM_SIV">961F000000040000000000EEDDEF4F453CFE6457C4234BD7C09258BD651D85</password>
    </interserver_http_credentials>

</clickhouse>
```

The attributes [`from_env`](#from_env_zk) and [`from_zk`](#from_env_zk) can also be applied to `encryption_codecs`:

```xml theme={null}
<clickhouse>

    <encryption_codecs>
        <aes_128_gcm_siv>
            <key_hex from_env="CLICKHOUSE_KEY_HEX"/>
        </aes_128_gcm_siv>
    </encryption_codecs>

    <interserver_http_credentials>
        <user>admin</user>
        <password encrypted_by="AES_128_GCM_SIV">961F000000040000000000EEDDEF4F453CFE6457C4234BD7C09258BD651D85</password>
    </interserver_http_credentials>

</clickhouse>
```

```xml theme={null}
<clickhouse>

    <encryption_codecs>
        <aes_128_gcm_siv>
            <key_hex from_zk="/clickhouse/aes128_key_hex"/>
        </aes_128_gcm_siv>
    </encryption_codecs>

    <interserver_http_credentials>
        <user>admin</user>
        <password encrypted_by="AES_128_GCM_SIV">961F000000040000000000EEDDEF4F453CFE6457C4234BD7C09258BD651D85</password>
    </interserver_http_credentials>

</clickhouse>
```

Encryption keys and encrypted values can be defined in either config file.

An example `config.xml` is given as:

```xml theme={null}
<clickhouse>

    <encryption_codecs>
        <aes_128_gcm_siv>
            <key_hex from_zk="/clickhouse/aes128_key_hex"/>
        </aes_128_gcm_siv>
    </encryption_codecs>

</clickhouse>
```

An example `users.xml` is given as:

```xml theme={null}
<clickhouse>

    <users>
        <test_user>
            <password encrypted_by="AES_128_GCM_SIV">96280000000D000000000030D4632962295D46C6FA4ABF007CCEC9C1D0E19DA5AF719C1D9A46C446</password>
            <profile>default</profile>
        </test_user>
    </users>

</clickhouse>
```

To encrypt a value, you can use the (example) program `encrypt_decrypt`:

```bash theme={null}
./encrypt_decrypt /etc/clickhouse-server/config.xml -e AES_128_GCM_SIV abcd
```

```text theme={null}
961F000000040000000000EEDDEF4F453CFE6457C4234BD7C09258BD651D85
```

Even with encrypted configuration elements, encrypted elements still appear in the preprocessed configuration file.
If this is a problem for your ClickHouse deployment, there are two alternatives: Either set file permissions of the preprocessed file to 600 or use the attribute `hide_in_preprocessed`.

For example:

```xml theme={null}
<clickhouse>

    <interserver_http_credentials hide_in_preprocessed="true">
        <user>admin</user>
        <password>secret</password>
    </interserver_http_credentials>

</clickhouse>
```

<h2 id="user-settings">
  User settings
</h2>

The `config.xml` file can specify a separate config with user settings, profiles, and quotas. The relative path to this config is set in the `users_config` element. By default, it is `users.xml`. If `users_config` is omitted, the user settings, profiles, and quotas are specified directly in `config.xml`.

User configuration can be split into separate files similar to `config.xml` and `config.d/`.
The directory name is defined as `users_config` setting without `.xml` postfix concatenated with `.d`.
The directory `users.d` is used by default, as `users_config` defaults to `users.xml`.
User configuration fragments are merged in lexicographical order by their full paths. For files in the standard `users.d/` directory, this is equivalent to ordering by file name. The legacy `conf.d/` directory is also merged; because `conf.d` sorts before `users.d`, all its fragments are processed first when both directories exist.

Note that configuration files are first [merged](#merging) taking into account settings, and includes are processed after that.

<h2 id="example">
  XML example
</h2>

For example, you can have a separate config file for each user like this:

```bash theme={null}
$ cat /etc/clickhouse-server/users.d/alice.xml
```

```xml theme={null}
<clickhouse>
    <users>
      <alice>
          <profile>analytics</profile>
            <networks>
                  <ip>::/0</ip>
            </networks>
          <password_sha256_hex>...</password_sha256_hex>
          <quota>analytics</quota>
      </alice>
    </users>
</clickhouse>
```

<h2 id="example-1">
  YAML examples
</h2>

Here you can see the default config written in YAML: [`config.yaml.example`](https://github.com/ClickHouse/ClickHouse/blob/master/programs/server/config.yaml.example).

There are some differences between YAML and XML formats in terms of ClickHouse configurations.
Tips for writing configuration in YAML format are presented below.

An XML tag with a text value is represented by a YAML key-value pair

```yaml theme={null}
key: value
```

Corresponding XML:

```xml theme={null}
<key>value</key>
```

A nested XML node is represented by a YAML map:

```yaml theme={null}
map_key:
  key1: val1
  key2: val2
  key3: val3
```

Corresponding XML:

```xml theme={null}
<map_key>
    <key1>val1</key1>
    <key2>val2</key2>
    <key3>val3</key3>
</map_key>
```

To create the same XML tag multiple times, use a YAML sequence:

```yaml theme={null}
seq_key:
  - val1
  - val2
  - key1: val3
  - map:
      key2: val4
      key3: val5
```

Corresponding XML:

```xml theme={null}
<seq_key>val1</seq_key>
<seq_key>val2</seq_key>
<seq_key>
    <key1>val3</key1>
</seq_key>
<seq_key>
    <map>
        <key2>val4</key2>
        <key3>val5</key3>
    </map>
</seq_key>
```

To provide an XML attribute, you can use an attribute key with a `@` prefix. Note that `@` is reserved by YAML standard, so must be wrapped in double quotes:

```yaml theme={null}
map:
  "@attr1": value1
  "@attr2": value2
  key: 123
```

Corresponding XML:

```xml theme={null}
<map attr1="value1" attr2="value2">
    <key>123</key>
</map>
```

It is also possible to use attributes in YAML sequence:

```yaml theme={null}
seq:
  - "@attr1": value1
  - "@attr2": value2
  - 123
  - abc
```

Corresponding XML:

```xml theme={null}
<seq attr1="value1" attr2="value2">123</seq>
<seq attr1="value1" attr2="value2">abc</seq>
```

The aforementioned syntax does not allow to express XML text nodes with XML attributes as YAML. This special case can be achieved using an
`#text` attribute key:

```yaml theme={null}
map_key:
  "@attr1": value1
  "#text": value2
```

Corresponding XML:

```xml theme={null}
<map_key attr1="value1">value2</map_key>
```

<h2 id="implementation-details">
  Implementation details
</h2>

For each config file, the server also generates `file-preprocessed.xml` files when starting. These files contain all the completed substitutions and overrides, and they are intended for informational use. If ZooKeeper substitutions were used in the config files but ZooKeeper is not available on the server start, the server loads the configuration from the preprocessed file.

The server tracks changes in config files, as well as files and ZooKeeper nodes that were used when performing substitutions and overrides, and reloads the settings for users and clusters on the fly. This means that you can modify the cluster, users, and their settings without restarting the server.
