$linuxjunkies
>

Install ClickHouse on Linux

Install ClickHouse on Linux from the official repo, configure users and storage, design an efficient MergeTree schema, ingest data, and tune for query performance.

IntermediateUbuntuDebianFedoraArch10 min readUpdated June 7, 2026

Before you start

  • Root or sudo access on the target server
  • At least 4 GB RAM and 20 GB free disk space on a dedicated partition
  • Outbound HTTPS access to packages.clickhouse.com for repo setup

ClickHouse is a column-oriented OLAP database designed for high-throughput analytical queries on large datasets. Installing it correctly — with proper repo pinning, a hardened user model, and sensible storage settings — saves significant pain later. This guide walks through installation from the official APT and RPM repos, initial configuration, user management, schema design basics, ingesting test data, and a handful of performance-critical settings.

Add the Official ClickHouse Repository

ClickHouse publishes signed packages through its own repo. Avoid distribution-packaged versions; they lag significantly behind upstream.

Debian / Ubuntu

sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' \
  | gpg --dearmor \
  | sudo tee /usr/share/keyrings/clickhouse-keyring.gpg > /dev/null

echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg arch=$(dpkg --print-architecture)] \
https://packages.clickhouse.com/deb stable main" \
  | sudo tee /etc/apt/sources.list.d/clickhouse.list

sudo apt-get update

Fedora / RHEL / Rocky

sudo tee /etc/yum.repos.d/clickhouse.repo <<'EOF'
[clickhouse-stable]
name=ClickHouse Stable
baseurl=https://packages.clickhouse.com/rpm/stable/
gpgcheck=1
gpgkey=https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key
enabled=1
EOF

Arch Linux

ClickHouse is available in the AUR. Use your preferred AUR helper:

paru -S clickhouse

Install the Packages

Debian / Ubuntu

sudo apt-get install -y clickhouse-server clickhouse-client

The installer prompts for a default user password. Set something strong — you cannot recover it without editing config files later.

Fedora / RHEL / Rocky

sudo dnf install -y clickhouse-server clickhouse-client

Start and Enable the Service

sudo systemctl enable --now clickhouse-server
systemctl status clickhouse-server

The server listens on TCP 9000 (native protocol) and HTTP 8123 by default. Both bind to 127.0.0.1 only until you explicitly change that.

Core Configuration

Main config lives at /etc/clickhouse-server/config.xml. Do not edit that file directly — place overrides in /etc/clickhouse-server/config.d/ so package upgrades do not overwrite your changes.

Example: set a custom data path and listen address

sudo tee /etc/clickhouse-server/config.d/custom.xml <<'EOF'


    
    /data/clickhouse/
    /data/clickhouse/tmp/

    
    

    
    0.8

EOF
sudo mkdir -p /data/clickhouse/tmp
sudo chown -R clickhouse:clickhouse /data/clickhouse
sudo systemctl restart clickhouse-server

If you expose port 8123 or 9000 to any network, add a firewall rule first:

# firewalld (Fedora/RHEL)
sudo firewall-cmd --add-port=8123/tcp --permanent
sudo firewall-cmd --reload

# ufw (Ubuntu)
sudo ufw allow from 10.0.0.0/8 to any port 8123 proto tcp

User Management

ClickHouse's user config lives in /etc/clickhouse-server/users.xml or, preferably, in override files under /etc/clickhouse-server/users.d/. Since ClickHouse 22.4 you can also manage users with SQL — the recommended approach for runtime changes.

Create an application user via SQL

clickhouse-client --password
# Inside the client
CREATE USER appuser IDENTIFIED WITH sha256_password BY 'StrongPassword123!';
GRANT SELECT, INSERT, CREATE TABLE ON appdb.* TO appuser;
CREATE DATABASE appdb;

SQL-managed users persist in ZooKeeper or local disk storage depending on your setup. For single-node installs they are stored in /var/lib/clickhouse/access/.

Restrict the default user

The default user has broad rights. Tighten it in a config override:

sudo tee /etc/clickhouse-server/users.d/restrict_default.xml <<'EOF'


    
        
            
                127.0.0.1
                ::1
            
        
    

EOF
sudo systemctl reload clickhouse-server

Create a Schema

ClickHouse's workhorse engine is MergeTree and its variants. Choose your ORDER BY key carefully — it determines on-disk sort order and query performance for all time.

clickhouse-client --user appuser --password --database appdb
CREATE TABLE events
(
    event_date   Date,
    event_time   DateTime,
    user_id      UInt64,
    action       LowCardinality(String),
    value        Float64,
    tags         Array(String)
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(event_date)
ORDER BY (user_id, event_time)
SETTINGS index_granularity = 8192;
  • PARTITION BY — monthly partitions work well for time-series; avoid over-partitioning (thousands of partitions slow merges).
  • ORDER BY — put your most-filtered columns first. This doubles as the sparse primary index.
  • LowCardinality — wrap low-distinct-count strings (status, country, action) for 3–5× compression and faster GROUP BY.

Ingest Data

Bulk insert from CSV

clickhouse-client \
  --user appuser --password \
  --database appdb \
  --query "INSERT INTO events FORMAT CSVWithNames" \
  < /tmp/events.csv

HTTP interface (useful for scripting and Kafka-style pipelines)

curl -X POST \
  'http://localhost:8123/?database=appdb&query=INSERT+INTO+events+FORMAT+JSONEachRow' \
  --user appuser:StrongPassword123! \
  --data-binary @/tmp/events.ndjson

Generate quick test data

clickhouse-client --database appdb --query "
INSERT INTO events
SELECT
    today() - randNormal(180, 60),
    now() - randNormal(15552000, 5000000),
    rand() % 100000,
    ['click','view','buy'][rand() % 3 + 1],
    randNormal(50, 20),
    []
FROM numbers(5000000);
"

This inserts five million synthetic rows in a few seconds and gives you a realistic dataset to query against.

Performance Basics

A few settings make an outsized difference on production workloads.

Compression

ClickHouse uses LZ4 by default. Switch to ZSTD for better compression ratios on analytical data (minimal CPU cost):

sudo tee /etc/clickhouse-server/config.d/compression.xml <<'EOF'


    
        
            zstd
            3
        
    

EOF

Thread and memory tuning

sudo tee /etc/clickhouse-server/users.d/query_limits.xml <<'EOF'


    
        
            auto
            10000000000  
            5000000000
        
    

EOF

Disk I/O

Put /var/lib/clickhouse (or your custom path) on a fast local NVMe disk. ClickHouse is heavily I/O-bound for large scans. Network-attached storage (NFS, EBS gp2) degrades performance dramatically.

Verify the Installation

clickhouse-client --query "SELECT version()"
clickhouse-client --database appdb --query "
SELECT action, count() AS cnt, round(avg(value), 2) AS avg_val
FROM events
GROUP BY action
ORDER BY cnt DESC;
"

Expected output (values will vary): three rows for click/view/buy with counts near 1.67 million each and avg_value near 50.

# Check server logs for errors
sudo journalctl -u clickhouse-server -n 50 --no-pager

Troubleshooting

  • Server won't start after config change — run sudo clickhouse-server --config /etc/clickhouse-server/config.xml --check-config to validate XML before restarting.
  • Authentication failure — SQL-created users and XML-defined users coexist but don't merge. If you set a password in both places, the XML file wins at startup. Check /var/lib/clickhouse/access/ for SQL-managed users.
  • Disk full on /var/lib/clickhouse/tmp — large GROUP BY or ORDER BY operations spill to disk. Increase the tmp partition size or raise max_bytes_before_external_group_by cautiously.
  • Too many parts exception — you are inserting too frequently in small batches. ClickHouse expects batch inserts of at least 10,000–100,000 rows. Use a buffer table or batch at the application layer.
  • Port 9000 already in use — another ClickHouse instance or a conflicting service is running. Check with sudo ss -tlnp | grep 9000.
tested on:Ubuntu 24.04Debian 12Fedora 40Rocky 9

Frequently asked questions

What is the difference between ClickHouse TCP port 9000 and HTTP port 8123?
Port 9000 uses ClickHouse's native binary protocol and is used by clickhouse-client and native drivers — it is faster for bulk operations. Port 8123 is an HTTP interface that accepts SQL queries as request bodies and is easier to use from scripts, curl, and generic HTTP-speaking tools.
How often should I insert data into ClickHouse?
ClickHouse performs best with infrequent large batch inserts — ideally one insert per second per table or fewer, with each batch containing at least 10,000–100,000 rows. Frequent small inserts create excessive parts on disk and trigger the 'too many parts' error. Use a buffer table or batch at the application layer.
Can I change the ORDER BY key after a table is created?
Not directly. The ORDER BY key is fixed at table creation and defines physical storage order. To change it you must create a new table with the desired key and copy data using INSERT INTO new_table SELECT * FROM old_table, or use the RENAME TABLE approach.
Is ClickHouse suitable for transactional (OLTP) workloads?
No. ClickHouse is designed for analytical read-heavy workloads over large datasets. It does not support row-level UPDATE or DELETE efficiently, has no true transactions, and performs poorly when queries return or modify individual rows.
How do I safely upgrade ClickHouse to a newer version?
Run apt-get update && apt-get install clickhouse-server clickhouse-client (or dnf upgrade) — the packages are designed for in-place upgrades. Always snapshot your data directory or take a backup first, and check the ClickHouse changelog for backward-incompatible changes before upgrading major versions.

Related guides