ClickHouse обычно ставят, когда нужна очень быстрая аналитика по миллионам и миллиардам строк: логи, события, метрики, BI-выгрузки, отчёты, антифрод, продуктовая аналитика. В этом гайде вы поднимете ClickHouse на Debian 12, Ubuntu 22.04/24.04 или AlmaLinux 9, настроите безопасный доступ, создадите отдельного пользователя, проверите порты и выполните первые SQL-запросы так, чтобы сервер сразу был готов к продакшну. Если задача “быстро в прод и без сюрпризов”, проще заказать VPS под ClickHouse с честными vCPU/NVMe и нужной локацией (NL/DE/UK/USA/RU/SG) и попросить преднастройку под ваш стек, чем потом отлавливать ошибки в сетевых и лимитах.
Что важно решить до установки
ClickHouse чувствителен к диску. NVMe даёт резкий выигрыш по вставкам и запросам. По памяти можно стартовать и на 2–4 GB, но с маленькой RAM чаще ловят memory limit и начинают “лечить” не то. Если вы планируете серьёзную нагрузку, разумный старт это 4 vCPU и 16 GB RAM, а дальше масштабирование уже по факту запросов и объёма.
Ещё момент: ClickHouse по умолчанию имеет HTTP интерфейс (8123) и нативный TCP (9000). Делать их доступными всему интернету нельзя. Нормальная схема такая:
-
ClickHouse слушает локально (127.0.0.1), если приложение на том же сервере
-
либо слушает на всех интерфейсах, но firewall пускает только ваши IP (офис, VPN, подсеть приложений)
-
отдельный пользователь под приложение, отдельный под админку, default пользователь не используем для продакшна
Дальше я дам один bash-скрипт, который всё делает сам: ставит ClickHouse, отвечает на парольные вопросы в apt (чтобы установка не зависла), включает сервис, настраивает конфиги через config.d и users.d, ставит лимиты systemd, настраивает firewall и выводит проверки.
Установка и базовая настройка одним скриптом (Debian/Ubuntu/AlmaLinux)
Запускайте от root на чистой системе. Скрипт сам определит тип ОС (apt или dnf/yum), спросит пароль для default пользователя (нужно для Debian/Ubuntu, чтобы установщик не ждал ввода), создаст пользователя app с ограничением по IP, и по желанию включит удалённый доступ (с firewall allowlist).
cat > /root/install-clickhouse-hstq.sh <<'BASH'
#!/usr/bin/env bash
set -euo pipefail
log(){ printf "\n[%s] %s\n" "$(date '+%H:%M:%S')" "$*"; }
die(){ echo "ERROR: $*" >&2; exit 1; }
need_root(){
[[ "$(id -u)" -eq 0 ]] || die "run as root"
}
detect_os(){
if command -v apt-get >/dev/null 2>&1; then
OS_FAMILY="apt"
elif command -v dnf >/dev/null 2>&1; then
OS_FAMILY="rpm"
PKG_MGR="dnf"
elif command -v yum >/dev/null 2>&1; then
OS_FAMILY="rpm"
PKG_MGR="yum"
else
die "unsupported OS: no apt/dnf/yum"
fi
}
ask(){
echo "Remote access options:"
echo "1) Local only (recommended if app is on same server)"
echo "2) Allow remote from specific CIDR/IP (recommended for separate app server)"
read -r -p "Choose [1-2]: " ACCESS_MODE
[[ "${ACCESS_MODE}" == "1" || "${ACCESS_MODE}" == "2" ]] || die "invalid choice"
if [[ "${ACCESS_MODE}" == "2" ]]; then
read -r -p "Allowed CIDR/IP (example 203.0.113.10/32 or 10.10.0.0/24): " ALLOW_CIDR
[[ -n "${ALLOW_CIDR}" ]] || die "empty ALLOW_CIDR"
else
ALLOW_CIDR=""
fi
read -r -s -p "Password for ClickHouse default user (Debian/Ubuntu installer prompt): " CH_DEFAULT_PASS; echo
[[ -n "${CH_DEFAULT_PASS}" ]] || die "empty password is not allowed for this script"
read -r -p "App user name [app]: " CH_APP_USER
CH_APP_USER="${CH_APP_USER:-app}"
read -r -s -p "App user password: " CH_APP_PASS; echo
[[ -n "${CH_APP_PASS}" ]] || die "empty app password is not allowed"
}
install_clickhouse_apt(){
log "APT: system update and prerequisites"
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get upgrade -y
apt-get install -y apt-transport-https ca-certificates curl gnupg expect ufw
log "APT: add ClickHouse repo (keyring)"
curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' | gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg
ARCH="$(dpkg --print-architecture)"
echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg arch=${ARCH}] https://packages.clickhouse.com/deb stable main" > /etc/apt/sources.list.d/clickhouse.list
apt-get update -y
log "APT: install clickhouse-server and clickhouse-client (auto-answer password prompts)"
expect <<EXP
set timeout 1200
log_user 1
spawn apt-get install -y clickhouse-server clickhouse-client
expect {
-re {Enter password for the default user:} { send -- "$env(CH_DEFAULT_PASS)\r"; exp_continue }
-re {Repeat password for the default user:} { send -- "$env(CH_DEFAULT_PASS)\r"; exp_continue }
-re {Password:} { send -- "$env(CH_DEFAULT_PASS)\r"; exp_continue }
eof
}
catch wait result
set exit_status [lindex \$result 3]
exit \$exit_status
EXP
}
install_clickhouse_rpm(){
log "RPM: system update and prerequisites"
"${PKG_MGR}" -y update
"${PKG_MGR}" -y install yum-utils curl ca-certificates || true
log "RPM: add ClickHouse repo"
yum-config-manager --add-repo https://packages.clickhouse.com/rpm/clickhouse.repo
log "RPM: install clickhouse-server and clickhouse-client"
"${PKG_MGR}" -y install clickhouse-server clickhouse-client
}
configure_clickhouse(){
log "Enable and start ClickHouse"
systemctl enable --now clickhouse-server
log "Configure network bind and ports using config.d"
mkdir -p /etc/clickhouse-server/config.d /etc/clickhouse-server/users.d
if [[ "${ACCESS_MODE}" == "1" ]]; then
cat > /etc/clickhouse-server/config.d/90-network.xml <<'XML'
<clickhouse>
<listen_host>127.0.0.1</listen_host>
<listen_host>::1</listen_host>
<http_port>8123</http_port>
<tcp_port>9000</tcp_port>
</clickhouse>
XML
else
cat > /etc/clickhouse-server/config.d/90-network.xml <<'XML'
<clickhouse>
<listen_host>0.0.0.0</listen_host>
<listen_host>::</listen_host>
<http_port>8123</http_port>
<tcp_port>9000</tcp_port>
</clickhouse>
XML
fi
log "Configure systemd limits (NOFILE) via override"
mkdir -p /etc/systemd/system/clickhouse-server.service.d
cat > /etc/systemd/system/clickhouse-server.service.d/limits.conf <<'CONF'
[Service]
LimitNOFILE=1048576
LimitNPROC=1048576
TasksMax=infinity
CONF
log "Create app user in users.d with sha256 password and network allowlist"
CH_APP_PASS_SHA256="$(printf '%s' "${CH_APP_PASS}" | sha256sum | awk '{print $1}')"
if [[ "${ACCESS_MODE}" == "1" ]]; then
cat > /etc/clickhouse-server/users.d/90-app-user.xml <<XML
<clickhouse>
<users>
<${CH_APP_USER}>
<password_sha256_hex>${CH_APP_PASS_SHA256}</password_sha256_hex>
<profile>default</profile>
<quota>default</quota>
<access_management>1</access_management>
<networks>
<ip>127.0.0.1</ip>
<ip>::1</ip>
</networks>
</${CH_APP_USER}>
</users>
</clickhouse>
XML
else
cat > /etc/clickhouse-server/users.d/90-app-user.xml <<XML
<clickhouse>
<users>
<${CH_APP_USER}>
<password_sha256_hex>${CH_APP_PASS_SHA256}</password_sha256_hex>
<profile>default</profile>
<quota>default</quota>
<access_management>1</access_management>
<networks>
<ip>127.0.0.1</ip>
<ip>::1</ip>
<ip>${ALLOW_CIDR}</ip>
</networks>
</${CH_APP_USER}>
</users>
</clickhouse>
XML
fi
log "Restart ClickHouse to apply configs"
systemctl daemon-reload
systemctl restart clickhouse-server
}
configure_firewall(){
log "Firewall: allow only what is needed"
if command -v ufw >/dev/null 2>&1; then
ufw --force reset
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
if [[ "${ACCESS_MODE}" == "2" ]]; then
ufw allow from "${ALLOW_CIDR}" to any port 8123 proto tcp
ufw allow from "${ALLOW_CIDR}" to any port 9000 proto tcp
fi
ufw --force enable
ufw status verbose
elif command -v firewall-cmd >/dev/null 2>&1; then
systemctl enable --now firewalld
firewall-cmd --permanent --add-service=ssh
if [[ "${ACCESS_MODE}" == "2" ]]; then
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='${ALLOW_CIDR}' port port='8123' protocol='tcp' accept"
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='${ALLOW_CIDR}' port port='9000' protocol='tcp' accept"
fi
firewall-cmd --reload
firewall-cmd --list-all
else
log "No ufw/firewalld found, skipping firewall. This is risky for remote mode."
fi
}
checks(){
log "Checks: service and ports"
systemctl status clickhouse-server --no-pager || true
ss -lntp | egrep ':8123|:9000' || true
log "Checks: ping HTTP and version query"
curl -fsS http://127.0.0.1:8123/ping || true
clickhouse-client --user "${CH_APP_USER}" --password "${CH_APP_PASS}" --query "SELECT version(), now()" || true
log "Done"
echo "App user: ${CH_APP_USER}"
echo "Access mode: ${ACCESS_MODE}"
if [[ "${ACCESS_MODE}" == "2" ]]; then
echo "Allowed CIDR/IP: ${ALLOW_CIDR}"
echo "Connect example:"
echo "clickhouse-client --host YOUR_SERVER_IP --port 9000 --user ${CH_APP_USER} --password"
else
echo "Connect example (local):"
echo "clickhouse-client --user ${CH_APP_USER} --password"
fi
}
need_root
detect_os
ask
export CH_DEFAULT_PASS
if [[ "${OS_FAMILY}" == "apt" ]]; then
install_clickhouse_apt
else
install_clickhouse_rpm
fi
configure_clickhouse
configure_firewall
checks
BASH
chmod +x /root/install-clickhouse-hstq.sh
/root/install-clickhouse-hstq.sh
Смысл скрипта простой: установка не должна зависать на паролях, ClickHouse не должен торчать наружу без ограничений, а проверка должна быть сразу после деплоя, чтобы вы видели реальный результат.
Как подключаться и “использовать” ClickHouse: первые запросы
После установки у вас есть два интерфейса.
-
HTTP: 8123, удобен для простых проверок и интеграций
-
Native TCP: 9000, основной для клиентов и приложений
Быстрая проверка “жив ли сервер”:
curl -sS http://127.0.0.1:8123/ping
Подключение клиентом локально:
clickhouse-client --user app --password
Пример минимального рабочего сценария: база, таблица, вставка, выборка.
CREATE DATABASE IF NOT EXISTS analytics;
CREATE TABLE IF NOT EXISTS analytics.events
(
ts DateTime,
user_id UInt64,
event LowCardinality(String),
props String
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(ts)
ORDER BY (event, ts, user_id);
INSERT INTO analytics.events (ts, user_id, event, props) VALUES
(now(), 1001, 'signup', '{"src":"ads"}'),
(now(), 1001, 'login', '{"device":"mobile"}'),
(now(), 1002, 'signup', '{"src":"seo"}');
SELECT event, count() AS c
FROM analytics.events
WHERE ts >= now() - INTERVAL 1 DAY
GROUP BY event
ORDER BY c DESC;
Если вы из мира PostgreSQL, важно быстро привыкнуть к двум вещам: правильный ORDER BY в MergeTree и аккуратный выбор типов, иначе вы сами себе убьёте скорость.
Где лежат конфиги и логи
ClickHouse правильно настраивать не через правку “главных” XML, а через директории:
-
/etc/clickhouse-server/config.d/ для настроек сервера
-
/etc/clickhouse-server/users.d/ для пользователей, профилей, лимитов
Логи обычно здесь:
-
/var/log/clickhouse-server/clickhouse-server.log
-
/var/log/clickhouse-server/clickhouse-server.err.log
Полезные команды диагностики:
systemctl status clickhouse-server --no-pager
journalctl -u clickhouse-server -n 200 --no-pager
tail -n 200 /var/log/clickhouse-server/clickhouse-server.log
ss -lntp | egrep ':8123|:9000'
Быстрый тюнинг для маленькой RAM, чтобы не ловить “memory limit exceeded”
Если сервер 2–4 GB, стандартный профиль может упираться в память на тяжёлых запросах. Это не “ClickHouse плохой”, это вы не зафиксировали лимиты.
Самый прямой вариант: создать профиль с ограничением и назначить его пользователю приложения. Добавьте файл:
cat > /etc/clickhouse-server/users.d/95-lowram-profile.xml <<'XML'
<clickhouse>
<profiles>
<lowram>
<max_memory_usage>2000000000</max_memory_usage>
<max_bytes_before_external_group_by>500000000</max_bytes_before_external_group_by>
<max_bytes_before_external_sort>500000000</max_bytes_before_external_sort>
<max_threads>4</max_threads>
</lowram>
</profiles>
</clickhouse>
XML
systemctl restart clickhouse-server
И поменяйте профиль у пользователя в users.d/90-app-user.xml с default на lowram. Это реальный способ сделать поведение предсказуемым и не терять ночь на разбор “почему упало”.
Типовые ошибки и мгновенная починка
Ошибка 1: после включения listen_host на 0.0.0.0 вы “потеряли” локальное подключение. Такое бывает, если вы случайно оставили только один listen_host и сломали IPv6 или перепутали конфиг. Проверка: что реально слушает сервер.
ss -lntp | egrep ':8123|:9000'
Если портов нет, смотрите логи и валидность XML. Самая частая причина это битый XML. В ClickHouse один лишний символ ломает старт.
Ошибка 2: “Authentication failed” и не заходит default или ваш пользователь. На Debian/Ubuntu пароль default мог быть задан установщиком. Если вы забыли, ищите файл пароля:
ls -l /etc/clickhouse-server/users.d/ | grep -i default || true
Если вам нужно сбросить именно default, чаще всего помогает удаление файла пароля default и рестарт. Но в продакшне лучше вообще не опираться на default, а работать вашим отдельным пользователем и ограничить сети.
Ошибка 3: “Connection refused” снаружи, хотя ClickHouse работает. Это почти всегда firewall. Либо вы не разрешили 8123/9000 для вашего CIDR, либо ClickHouse слушает только 127.0.0.1. Проверяйте оба уровня, а не один.
Безопасность, которую реально делают в продакшне
Если вы хотите “как у взрослых”, оставьте себе простую дисциплину.
-
Не открывайте 8123 и 9000 всему миру
-
Делайте доступ по allowlist IP или через VPN
-
Разделяйте пользователей: app и admin
-
Настройки держите в config.d/users.d, чтобы обновления пакетов не перетирали вашу ручную правку
-
Следите за диском и логами, ClickHouse быстро показывает, когда IOPS не хватает
Если вам нужна внешняя доступность, но вы не хотите возиться, часто проще взять отдельный IPv4 под доступ к базе и фильтровать на сетевом уровне. Для проектов, где требуется много IP, подсети /24 и дальше, PTR/WHOIS и более сложная сеть, это уже инфраструктура, а не “поставил базу”. В HSTQ такие запросы закрываются как нормальная услуга, включая аренду IPv4 и помощь с LIR/ASN, плюс администрирование 24/7.
Масштабирование: от single-node к репликации и HA
На одном сервере ClickHouse закрывает большую часть задач. Но есть точки, где логично расти.
Стадия 1: single-node на VPS. Вы держите данные, запросы, бэкапы и мониторинг на одном узле. Подходит для старта и умеренной нагрузки.
Стадия 2: два узла ClickHouse и отдельный ClickHouse Keeper. Когда вам нужна репликация и устойчивость, вы делаете 2 реплики данных и выносите Keeper на отдельный VPS. В продакшне Keeper лучше держать не на тех же узлах, что и база.
Стадия 3: шардирование плюс репликация. Это когда один узел уже не помещается по диску или запросам. Тут появляются распределённые таблицы, балансировка и более строгая дисциплина по схемам и партициям.
Когда пора переходить на выделенный сервер: когда вы упираетесь в диск и стабильную производительность. Аналитические базы плохо переносят “плавающие” ресурсы. Dedicated на NVMe часто даёт меньше сюрпризов и в итоге дешевле по времени инженера, чем бесконечные микротюнинги на маленьком VPS.
Мини-FAQ
Что выбрать для ClickHouse: Debian 12 или Ubuntu 24.04?
Если важна консервативность, берите Debian 12. Если хотите более свежую базу и пакеты, Ubuntu 24.04 обычно удобнее.
Какие порты нужно открыть для удалённого доступа?
Минимально 8123 (HTTP) и 9000 (native TCP), но открывать их надо только на конкретные IP или через VPN.
Можно ли поставить ClickHouse на Windows Server?
Сервер ClickHouse обычно держат на Linux. На Windows используйте клиентские инструменты или WSL, а сам продакшн сервер держите на Linux VPS или выделенном сервере.
Почему ClickHouse “медленный” на маленьком VPS?
Чаще всего причина в диске и нехватке RAM. NVMe и нормальная память решают больше, чем попытки “покрутить один параметр”.
Как быстро проверить, что установка нормальная?
curl http://127.0.0.1:8123/ping, затем clickhouse-client и SELECT version() от вашего пользователя. Если это работает, дальше вопросы уже к схемам и нагрузке, а не к установке.
Если хочешь, я сделаю вторую часть для базы знаний: “ClickHouse для логов и метрик”, где покажу готовую схему таблиц, партиционирование, TTL на холодные данные, materialized view для агрегатов и пример загрузки батчами, чтобы уже на старте не убить диск и не получить взрыв по кардинальности.