Set up ClickHouse OLAP database with clustering support for real-time analytics workloads. Configure distributed tables, security, SSL encryption, and monitoring for production environments.
Prerequisites
- Root or sudo access
- Minimum 4GB RAM
- Multiple servers for clustering
- Network connectivity between cluster nodes
What this solves
ClickHouse is a columnar OLAP database designed for real-time analytics on large datasets. This tutorial helps you install and configure a production-ready ClickHouse cluster with distributed tables, SSL encryption, user security, performance optimization, and backup procedures for high-performance analytics workloads.
Step-by-step installation
Update system packages and install dependencies
Start by updating your package manager and installing required dependencies for ClickHouse.
sudo apt update && sudo apt upgrade -y
sudo apt install -y apt-transport-https ca-certificates dirmngr curl gnupg2Add ClickHouse repository
Add the official ClickHouse repository to install the latest stable version.
curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' | sudo gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg] https://packages.clickhouse.com/deb stable main" | sudo tee /etc/apt/sources.list.d/clickhouse.list
sudo apt updateInstall ClickHouse server and client
Install ClickHouse server and client packages. The installer will prompt for a default user password.
sudo apt install -y clickhouse-server clickhouse-clientCreate ClickHouse system user and directories
Ensure proper ownership and permissions for ClickHouse data directories.
sudo mkdir -p /var/lib/clickhouse /var/log/clickhouse-server /etc/clickhouse-server/conf.d
sudo chown clickhouse:clickhouse /var/lib/clickhouse /var/log/clickhouse-server
sudo chmod 755 /var/lib/clickhouse /var/log/clickhouse-server
sudo chmod 750 /etc/clickhouse-serverConfigure main server settings
Create the main configuration file with clustering and security settings.
information
/var/log/clickhouse-server/clickhouse-server.log
/var/log/clickhouse-server/clickhouse-server.err.log
100M
10
8123
9000
9004
9005
::
4096
3
100
8589934592
5368709120
/var/lib/clickhouse/
/var/lib/clickhouse/tmp/
/var/lib/clickhouse/user_files/
/var/lib/clickhouse/format_schemas/
users.xml
default
default
UTC
022
false
3600
3600
60
Configure users and security
Set up user accounts with proper access controls and password authentication.
10000000000
0
random
268435456
500000
500000
0
1
5000000000
0
random
YOUR_SHA256_PASSWORD_HASH
::1
127.0.0.1
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
default
default
YOUR_ANALYTICS_PASSWORD_HASH
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
default
default
YOUR_READONLY_PASSWORD_HASH
0.0.0.0/0
readonly
default
3600
0
0
0
0
0
Generate password hashes for users
Create secure password hashes for your ClickHouse users and update the configuration.
# Generate password hash for default user
echo -n 'your_secure_password' | sha256sum
Generate password hash for analytics user
echo -n 'analytics_password' | sha256sum
Generate password hash for readonly user
echo -n 'readonly_password' | sha256sumReplace the YOUR_*_PASSWORD_HASH placeholders in users.xml with the generated hashes.
Configure clustering settings
Set up clustering configuration for distributed tables and high availability.
203.0.113.10
9000
default
your_secure_password
203.0.113.11
9000
default
your_secure_password
203.0.113.12
9000
default
your_secure_password
203.0.113.10
9000
203.0.113.11
9000
203.0.113.12
9000
203.0.113.13
9000
cluster_3shards_1replicas
01
replica_1
Configure SSL/TLS encryption
Enable HTTPS and secure TCP connections with SSL certificates.
# Generate self-signed certificates for testing (use proper CA certificates in production)
sudo mkdir -p /etc/clickhouse-server/certs
sudo openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
-subj "/C=US/ST=State/L=City/O=Organization/CN=example.com" \
-keyout /etc/clickhouse-server/certs/server.key \
-out /etc/clickhouse-server/certs/server.crt
sudo chown -R clickhouse:clickhouse /etc/clickhouse-server/certs
sudo chmod 600 /etc/clickhouse-server/certs/server.key
sudo chmod 644 /etc/clickhouse-server/certs/server.crtEnable SSL in ClickHouse configuration
Configure HTTPS and secure TCP ports with SSL certificates.
8443
9440
/etc/clickhouse-server/certs/server.crt
/etc/clickhouse-server/certs/server.key
/etc/clickhouse-server/certs/dhparam.pem
none
true
true
sslv2,sslv3
true
true
true
sslv2,sslv3
true
none
RejectCertificateHandler
Generate DH parameters for SSL
Create Diffie-Hellman parameters for enhanced SSL security.
sudo openssl dhparam -out /etc/clickhouse-server/certs/dhparam.pem 2048
sudo chown clickhouse:clickhouse /etc/clickhouse-server/certs/dhparam.pem
sudo chmod 644 /etc/clickhouse-server/certs/dhparam.pemConfigure firewall rules
Open necessary ports for ClickHouse cluster communication and client access.
sudo ufw allow 8123/tcp comment 'ClickHouse HTTP'
sudo ufw allow 8443/tcp comment 'ClickHouse HTTPS'
sudo ufw allow 9000/tcp comment 'ClickHouse Native TCP'
sudo ufw allow 9440/tcp comment 'ClickHouse Secure TCP'
sudo ufw allow from 203.0.113.0/24 to any port 9009 comment 'ClickHouse Interserver HTTP'Start and enable ClickHouse service
Start the ClickHouse service and enable it to start automatically on boot.
sudo systemctl enable clickhouse-server
sudo systemctl start clickhouse-server
sudo systemctl status clickhouse-serverCreate distributed tables
Set up distributed tables that span across your ClickHouse cluster for analytics workloads.
# Connect to ClickHouse client
clickhouse-client --user default --password
Create local table on each shard
CREATE TABLE events_local (
event_id UInt64,
user_id UInt32,
event_time DateTime,
event_type String,
properties Map(String, String)
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(event_time)
ORDER BY (user_id, event_time)
SETTINGS index_granularity = 8192;
Create distributed table
CREATE TABLE events_distributed AS events_local
ENGINE = Distributed(cluster_3shards_1replicas, default, events_local, rand());
Create materialized view for real-time aggregations
CREATE MATERIALIZED VIEW events_hourly_mv
TO events_hourly
AS SELECT
toStartOfHour(event_time) as hour,
event_type,
count() as event_count,
uniq(user_id) as unique_users
FROM events_local
GROUP BY hour, event_type;Performance optimization
Configure memory and cache settings
Optimize ClickHouse performance with proper memory allocation and cache configuration.
0.8
20000000000
8589934592
5368709120
134217728
0
100
16
2
lz4
Set up monitoring integration
Configure ClickHouse metrics exposure for monitoring systems like Prometheus.
/metrics
9363
true
true
true
true
system
query_log
toYYYYMM(event_date)
7500
You can integrate this with existing monitoring solutions like Grafana and Prometheus.
Backup and maintenance
Configure automated backups
Set up ClickHouse backup configuration for data protection and disaster recovery.
local
/var/lib/clickhouse/backups/
s3
https://s3.amazonaws.com
YOUR_ACCESS_KEY
YOUR_SECRET_KEY
clickhouse-backups
cluster-backups/
Create backup script
Create an automated backup script for regular data protection.
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/var/lib/clickhouse/backups"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="backup_${DATE}"
RETENTION_DAYS=7
Create backup directory
mkdir -p "${BACKUP_DIR}/${BACKUP_NAME}"
Backup ClickHouse data
echo "Starting ClickHouse backup at $(date)"
clickhouse-client --query "BACKUP DATABASE default TO Disk('disk', '${BACKUP_NAME}');"
Backup configuration
tar -czf "${BACKUP_DIR}/${BACKUP_NAME}/config.tar.gz" -C /etc clickhouse-server
Clean old backups
find "${BACKUP_DIR}" -type d -name "backup_*" -mtime +${RETENTION_DAYS} -exec rm -rf {} +
echo "Backup completed: ${BACKUP_NAME}"
Optional: Upload to S3 or remote storage
aws s3 sync "${BACKUP_DIR}/${BACKUP_NAME}" s3://your-backup-bucket/clickhouse/${BACKUP_NAME}/
Set backup permissions and schedule
Configure proper permissions for the backup script and schedule regular backups.
sudo chmod +x /usr/local/bin/clickhouse-backup.sh
sudo mkdir -p /var/lib/clickhouse/backups
sudo chown clickhouse:clickhouse /var/lib/clickhouse/backups
sudo chmod 755 /var/lib/clickhouse/backups
Add to crontab for daily backups at 2 AM
echo "0 2 * /usr/local/bin/clickhouse-backup.sh >> /var/log/clickhouse-backup.log 2>&1" | sudo crontab -u clickhouse -Verify your setup
# Check ClickHouse service status
sudo systemctl status clickhouse-server
Test client connection
clickhouse-client --query "SELECT version()"
Test HTTPS endpoint
curl -k https://localhost:8443/
Check cluster configuration
clickhouse-client --query "SELECT * FROM system.clusters"
Verify distributed tables
clickhouse-client --query "SHOW TABLES"
Test insert and query on distributed table
clickhouse-client --query "INSERT INTO events_distributed VALUES (1, 100, now(), 'click', {'page': '/home', 'referrer': 'google'})"
clickhouse-client --query "SELECT * FROM events_distributed LIMIT 5"
Check system metrics
clickhouse-client --query "SELECT * FROM system.metrics WHERE metric LIKE '%Connection%' LIMIT 10"Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Service fails to start | Configuration syntax error | sudo clickhouse-server --config-file=/etc/clickhouse-server/config.xml --daemon=false to check config |
| Connection refused on port 8123 | Firewall blocking connections | Check firewall rules and ensure port 8123 is open |
| Permission denied accessing data directory | Incorrect ownership or permissions | sudo chown -R clickhouse:clickhouse /var/lib/clickhouse && sudo chmod 755 /var/lib/clickhouse |
| SSL certificate errors | Invalid or expired certificates | Regenerate certificates or check certificate paths in SSL configuration |
| Cluster nodes cannot connect | Network configuration or authentication | Verify network connectivity and user credentials in cluster configuration |
| High memory usage | Inadequate memory limits | Adjust max_memory_usage and max_server_memory_usage_to_ram_ratio in configuration |
| Slow query performance | Missing indexes or poor table design | Add appropriate ORDER BY clauses and partition keys, check with EXPLAIN |
Next steps
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# ClickHouse Production Installation Script
# Supports Ubuntu, Debian, AlmaLinux, Rocky Linux, CentOS, RHEL, Fedora
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Configuration
CLICKHOUSE_PASSWORD=""
CLUSTER_NODES=""
usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -p PASSWORD Set default user password (required)"
echo " -c NODES Comma-separated cluster nodes (optional)"
echo " -h Show this help"
echo ""
echo "Example: $0 -p MySecurePass123 -c \"10.0.1.10,10.0.1.11,10.0.1.12\""
exit 1
}
log() {
echo -e "${GREEN}[$(date +'%H:%M:%S')] $1${NC}"
}
warn() {
echo -e "${YELLOW}[WARNING] $1${NC}"
}
error() {
echo -e "${RED}[ERROR] $1${NC}"
exit 1
}
cleanup() {
if [ $? -ne 0 ]; then
warn "Installation failed. Cleaning up..."
systemctl stop clickhouse-server 2>/dev/null || true
systemctl disable clickhouse-server 2>/dev/null || true
fi
}
trap cleanup ERR
check_prerequisites() {
log "[1/12] Checking prerequisites..."
if [[ $EUID -ne 0 ]]; then
error "This script must be run as root or with sudo"
fi
if [ -z "$CLICKHOUSE_PASSWORD" ]; then
error "Password is required. Use -p option."
fi
if [ ${#CLICKHOUSE_PASSWORD} -lt 8 ]; then
error "Password must be at least 8 characters long"
fi
}
detect_distro() {
log "[2/12] Detecting operating system..."
if [ ! -f /etc/os-release ]; then
error "Cannot detect OS. /etc/os-release not found."
fi
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update && apt upgrade -y"
FIREWALL_CMD="ufw"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
FIREWALL_CMD="firewall-cmd"
if ! command -v dnf &> /dev/null; then
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
fi
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
FIREWALL_CMD="firewall-cmd"
;;
*)
error "Unsupported distribution: $ID"
;;
esac
log "Detected: $PRETTY_NAME using $PKG_MGR"
}
update_system() {
log "[3/12] Updating system packages..."
$PKG_UPDATE
case "$PKG_MGR" in
apt)
$PKG_INSTALL apt-transport-https ca-certificates dirmngr curl gnupg2
;;
dnf|yum)
$PKG_INSTALL curl gnupg2 ca-certificates
;;
esac
}
add_repository() {
log "[4/12] Adding ClickHouse repository..."
case "$PKG_MGR" in
apt)
curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' | gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg] https://packages.clickhouse.com/deb stable main" > /etc/apt/sources.list.d/clickhouse.list
chmod 644 /etc/apt/sources.list.d/clickhouse.list
apt update
;;
dnf|yum)
cat > /etc/yum.repos.d/clickhouse.repo << 'EOF'
[clickhouse-stable]
name=ClickHouse - Stable Repository
baseurl=https://packages.clickhouse.com/rpm/stable/
gpgcheck=1
enabled=1
gpgkey=https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key
EOF
chmod 644 /etc/yum.repos.d/clickhouse.repo
;;
esac
}
install_clickhouse() {
log "[5/12] Installing ClickHouse..."
export CLICKHOUSE_PASSWORD_SHA256_HEX=$(echo -n "$CLICKHOUSE_PASSWORD" | sha256sum | cut -d' ' -f1)
$PKG_INSTALL clickhouse-server clickhouse-client
}
configure_clickhouse() {
log "[6/12] Configuring ClickHouse..."
# Backup original config
cp /etc/clickhouse-server/config.xml /etc/clickhouse-server/config.xml.backup
# Create users configuration
mkdir -p /etc/clickhouse-server/users.d
cat > /etc/clickhouse-server/users.d/default.xml << EOF
<yandex>
<users>
<default>
<password_sha256_hex>$(echo -n "$CLICKHOUSE_PASSWORD" | sha256sum | cut -d' ' -f1)</password_sha256_hex>
<networks>
<ip>::/0</ip>
</networks>
<profile>default</profile>
<quota>default</quota>
</default>
</users>
</yandex>
EOF
# Set proper permissions
chown -R clickhouse:clickhouse /etc/clickhouse-server/users.d
chmod 640 /etc/clickhouse-server/users.d/default.xml
# Configure main settings
mkdir -p /etc/clickhouse-server/config.d
cat > /etc/clickhouse-server/config.d/custom.xml << 'EOF'
<yandex>
<listen_host>0.0.0.0</listen_host>
<http_port>8123</http_port>
<tcp_port>9000</tcp_port>
<interserver_http_port>9009</interserver_http_port>
<max_connections>2048</max_connections>
<keep_alive_timeout>3</keep_alive_timeout>
<max_concurrent_queries>200</max_concurrent_queries>
<uncompressed_cache_size>8589934592</uncompressed_cache_size>
<mark_cache_size>5368709120</mark_cache_size>
<path>/var/lib/clickhouse/</path>
<tmp_path>/var/lib/clickhouse/tmp/</tmp_path>
<user_files_path>/var/lib/clickhouse/user_files/</user_files_path>
<users_config>/etc/clickhouse-server/users.xml</users_config>
<logger>
<level>information</level>
<log>/var/log/clickhouse-server/clickhouse-server.log</log>
<errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
<size>1000M</size>
<count>3</count>
</logger>
</yandex>
EOF
chown clickhouse:clickhouse /etc/clickhouse-server/config.d/custom.xml
chmod 640 /etc/clickhouse-server/config.d/custom.xml
}
configure_cluster() {
if [ -n "$CLUSTER_NODES" ]; then
log "[7/12] Configuring cluster..."
cat > /etc/clickhouse-server/config.d/cluster.xml << EOF
<yandex>
<remote_servers>
<analytics_cluster>
$(
IFS=','
shard=1
for node in $CLUSTER_NODES; do
echo " <shard>"
echo " <replica>"
echo " <host>$node</host>"
echo " <port>9000</port>"
echo " </replica>"
echo " </shard>"
((shard++))
done
)
</analytics_cluster>
</remote_servers>
<zookeeper incl="zookeeper-servers" optional="true" />
<macros>
<cluster>analytics_cluster</cluster>
<shard>01</shard>
<replica>$(hostname)</replica>
</macros>
</yandex>
EOF
chown clickhouse:clickhouse /etc/clickhouse-server/config.d/cluster.xml
chmod 640 /etc/clickhouse-server/config.d/cluster.xml
else
log "[7/12] Skipping cluster configuration (no nodes specified)"
fi
}
configure_firewall() {
log "[8/12] Configuring firewall..."
case "$FIREWALL_CMD" in
ufw)
if command -v ufw &> /dev/null; then
ufw --force enable
ufw allow 8123/tcp comment "ClickHouse HTTP"
ufw allow 9000/tcp comment "ClickHouse TCP"
ufw allow 9009/tcp comment "ClickHouse Interserver"
ufw reload
fi
;;
firewall-cmd)
if command -v firewall-cmd &> /dev/null && systemctl is-active --quiet firewalld; then
firewall-cmd --permanent --add-port=8123/tcp --add-port=9000/tcp --add-port=9009/tcp
firewall-cmd --reload
fi
;;
esac
}
configure_selinux() {
log "[9/12] Configuring SELinux..."
if command -v setsebool &> /dev/null && [ -f /sys/fs/selinux/enforce ]; then
setsebool -P httpd_can_network_connect 1 2>/dev/null || true
semanage port -a -t http_port_t -p tcp 8123 2>/dev/null || true
semanage port -a -t mysqld_port_t -p tcp 9000 2>/dev/null || true
semanage port -a -t http_port_t -p tcp 9009 2>/dev/null || true
fi
}
start_services() {
log "[10/12] Starting ClickHouse service..."
systemctl enable clickhouse-server
systemctl start clickhouse-server
# Wait for service to be ready
for i in {1..30}; do
if systemctl is-active --quiet clickhouse-server; then
break
fi
sleep 2
done
}
verify_installation() {
log "[11/12] Verifying installation..."
# Check service status
if ! systemctl is-active --quiet clickhouse-server; then
error "ClickHouse service is not running"
fi
# Test connection
sleep 5
if ! echo "SELECT version()" | clickhouse-client --password="$CLICKHOUSE_PASSWORD" &>/dev/null; then
error "Cannot connect to ClickHouse server"
fi
# Test HTTP interface
if ! curl -s "http://localhost:8123/?query=SELECT%201" &>/dev/null; then
error "HTTP interface is not responding"
fi
log "ClickHouse is running and accessible"
}
show_summary() {
log "[12/12] Installation completed successfully!"
echo ""
echo -e "${GREEN}ClickHouse Installation Summary:${NC}"
echo "================================"
echo "HTTP Port: 8123"
echo "TCP Port: 9000"
echo "Interserver Port: 9009"
echo ""
echo "Connection examples:"
echo " clickhouse-client --password='$CLICKHOUSE_PASSWORD'"
echo " curl 'http://localhost:8123/?query=SELECT%20version()'"
echo ""
echo "Configuration files:"
echo " Main config: /etc/clickhouse-server/config.xml"
echo " Custom config: /etc/clickhouse-server/config.d/"
echo " Users config: /etc/clickhouse-server/users.d/"
echo ""
echo "Log files:"
echo " Server log: /var/log/clickhouse-server/clickhouse-server.log"
echo " Error log: /var/log/clickhouse-server/clickhouse-server.err.log"
if [ -n "$CLUSTER_NODES" ]; then
echo ""
echo -e "${YELLOW}Cluster Configuration:${NC}"
echo "Cluster nodes: $CLUSTER_NODES"
echo "Configure ZooKeeper for replication if needed"
fi
}
# Parse arguments
while getopts "p:c:h" opt; do
case $opt in
p) CLICKHOUSE_PASSWORD="$OPTARG" ;;
c) CLUSTER_NODES="$OPTARG" ;;
h) usage ;;
*) usage ;;
esac
done
# Main execution
check_prerequisites
detect_distro
update_system
add_repository
install_clickhouse
configure_clickhouse
configure_cluster
configure_firewall
configure_selinux
start_services
verify_installation
show_summary
Review the script before running. Execute with: bash install.sh