ClickHouse splits its configuration into two main files, config.xml for server settings and users.xml for user-level profiles and access control, plus a system of override directories that merge on top. Treating these correctly is the difference between a server that survives package upgrades and one that breaks every time apt upgrade runs. This guide covers the layout, the merge order, what reloads automatically versus what needs a restart, and how to verify your changes actually took effect.
The default layout
On a package install, /etc/clickhouse-server/ contains:
config.xml # main server config (do not edit directly)
users.xml # main users / profiles / quotas (do not edit directly)
config.d/ # server config overrides
users.d/ # user config overrides
conf.d/ # overrides that can target either
The vendor files (config.xml, users.xml) belong to the package. If you edit them, your next package upgrade either reverts your changes or leaves a .dpkg-dist file you have to merge by hand. Put everything custom under the .d/ directories instead.
How merging works
At startup, and at every config reload, ClickHouse processes files in this order:
config.xml- Every file in
config.d/, alphabetical order. - Every file in
conf.d/, alphabetical order.
The same pattern applies to user config:
users.xmlusers.d/conf.d/
Alphabetical ordering matters because later files override earlier ones. A common convention is to prefix files with numbers: 10-listen.xml, 20-logging.xml, 99-custom.xml. This makes the precedence explicit.
When the root config file has a custom name, the override directory follows the same stem. ClickHouse Keeper uses keeper_config.xml and keeper_config.d/.
Override syntax: replace, remove, merge
By default, repeated tags merge: child elements from the override are added to or overwrite siblings in the base. Two attributes change this behavior.
Remove a section
<?xml version="1.0"?>
<clickhouse>
<http_port remove="1"/>
<tcp_port remove="1"/>
</clickhouse>
Useful for disabling default ports on hardened deployments.
Replace a section entirely
<?xml version="1.0" ?>
<clickhouse>
<remote_servers replace="1">
<mycluster>
<shard>
<replica>
<host>node1</host>
<port>9000</port>
</replica>
</shard>
</mycluster>
</remote_servers>
</clickhouse>
Without replace="1", the override's shards merge with whatever the base config defined. With it, the override wins outright.
What needs a restart and what does not
Most config.xml changes require restarting clickhouse-server. The notable exceptions reload live:
<max_server_memory_usage>and related memory caps<macros><remote_servers><dictionaries_config><logger>(live reload since 21.11)<storage_configuration>additions (new disks and policies)
users.xml and users.d/ changes generally apply without restart, but they take effect at the next connection, not for sessions already open. A few exceptions exist around thread pool sizing (background_buffer_flush_schedule_pool_size and friends), which are read once at startup.
To force a reload without restart:
SYSTEM RELOAD CONFIG;
This re-reads everything in config.d/, users.d/, and conf.d/. Settings that cannot live-reload are flagged in the log.
The incl attribute and shared config
For shared values across many nodes (cluster topology, credentials), use the include mechanism. By default ClickHouse looks at /etc/metrika.xml; override with:
<include_from>/etc/clickhouse-server/dict_sources.xml</include_from>
Then reference sections by name:
<remote_servers incl="clickhouse_remote_servers"/>
The named section is pulled from the include file. This is the classic way to keep cluster topology in a single file managed by configuration management (Ansible, Puppet, Chef) and distributed to every node.
Verifying what the server actually loaded
After any non-trivial change, do not trust that the file you edited is what the server is using. ClickHouse writes the assembled config to:
/var/lib/clickhouse/preprocessed_configs/
You will find merged config.xml and users.xml reflecting everything from the base files plus every override. Diff this against your expectations. If a setting is missing, your override file was not picked up (wrong directory, wrong filename, XML parse error in an earlier file aborting the merge).
clickhouse-extract-from-config also reads the merged result, which is handy for scripted checks:
sudo clickhouse-extract-from-config \
--config=/etc/clickhouse-server/config.xml \
--key=listen_host
Running multiple instances on one host
Each instance needs its own config tree and data path. Pass --config-file per instance and ensure these are distinct:
<path>/var/lib/clickhouse-2/</path>
<tmp_path>/var/lib/clickhouse-2/tmp/</tmp_path>
<user_files_path>/var/lib/clickhouse-2/user_files/</user_files_path>
<format_schema_path>/var/lib/clickhouse-2/format_schemas/</format_schema_path>
<tcp_port>9001</tcp_port>
<http_port>8124</http_port>
<interserver_http_port>9010</interserver_http_port>
Use distinct <logger><log> paths as well, otherwise the two instances will fight over the same log file.
Common Pitfalls
- Editing
config.xmlorusers.xmldirectly, then losing changes on package upgrade. - Forgetting that
.d/files merge alphabetically. Numerical prefixes make precedence obvious. - Assuming a config change took effect because the server did not crash. Check
preprocessed_configs/and the server log. - An XML parse error in one
config.d/file silently breaks the entire load. The server logs the error but stays on the previous config. - Mixing
<clickhouse>and<yandex>root tags between files. Both still work, but pick one for consistency. - Forgetting that user setting changes apply only to new sessions, not currently open ones.
Frequently Asked Questions
Q: Where are ClickHouse config files located?
A: /etc/clickhouse-server/ on a standard package install. The main files are config.xml and users.xml, with overrides in config.d/, users.d/, and conf.d/.
Q: Should I edit config.xml directly?
A: No. Put overrides in config.d/. The vendor file is owned by the package and gets replaced on upgrade.
Q: How do I see the final merged configuration?
A: Look in /var/lib/clickhouse/preprocessed_configs/. ClickHouse writes the merged result there after every config reload.
Q: Do all config changes require a restart?
A: No. remote_servers, macros, dictionaries, logger, and memory caps reload live. Most other server-level changes need a restart. User profile changes apply to new connections only.
Q: What happens if one override file has an XML syntax error? A: ClickHouse logs the parse error and continues running on the previously loaded config. Reload attempts will keep failing until the file is fixed. Always check the log after editing.
Q: Can I use environment variables in the config?
A: Yes, ClickHouse supports from_env attributes on XML elements. Example: <password from_env="CH_PASSWORD"/> pulls the value from the environment at startup.