HestiaCP

Как настроить HestiaCP с двумя отдельными DNS-серверами: master + slave DNS

В этой статье разберём схему установки HestiaCP на три сервера:

host.domain.ru  — основной сервер HestiaCP, хостинг, сайты, базы, панель управления
ns1.domain.ru   — первый DNS-only сервер
ns2.domain.ru   — второй DNS-only сервер

Идея простая: все сайты, пользователи и DNS-зоны создаются на основном сервере host.domain.ru, а два отдельных сервера ns1.domain.ru и ns2.domain.ru автоматически получают DNS-зоны с master-сервера и отвечают за домены клиентов в интернете.

Такой вариант удобен для хостинга: клиенту достаточно указать у регистратора домена только:

ns1.domain.ru
ns2.domain.ru

А управление зонами остаётся в HestiaCP на основном сервере.


1. Общая схема

Будем использовать такие условные данные:

Домен:       domain.ru

Master:      host.domain.ru
IP master:   IP_HOST

Slave DNS 1: ns1.domain.ru
IP ns1:      IP_NS1

Slave DNS 2: ns2.domain.ru
IP ns2:      IP_NS2

В реальной установке замените:

domain.ru → ваш домен
IP_HOST   → IP основного сервера
IP_NS1    → IP первого DNS-сервера
IP_NS2    → IP второго DNS-сервера

2. Что нужно подготовить заранее

Нужно три чистых VPS/VDS-сервера. Желательно использовать поддерживаемую версию Debian или Ubuntu. Для продакшена лучше брать стабильную и официально поддерживаемую версию ОС. Если вы хотите ставить на Debian 13, сначала проверьте, поддерживает ли его текущая версия HestiaCP. Если нет — безопаснее использовать Debian 12.

На всех трёх серверах нужен root-доступ.

Перед установкой желательно сразу назначить hostname:

host.domain.ru
ns1.domain.ru
ns2.domain.ru

3. Настройка у регистратора домена

У регистратора домена domain.ru нужно сделать две вещи.

Первая — создать child nameservers, они же glue records:

ns1.domain.ru → IP_NS1
ns2.domain.ru → IP_NS2

Например:

ns1.domain.ru → 111.111.111.111
ns2.domain.ru → 222.222.222.222

Вторая — делегировать сам домен domain.ru на эти DNS-серверы:

domain.ru NS ns1.domain.ru
domain.ru NS ns2.domain.ru

Это важный момент. Glue records только связывают имена ns1.domain.ru и ns2.domain.ru с IP-адресами. Но сам домен ещё должен быть делегирован на эти NS.


4. Подготовка серверов

На каждом сервере обновляем систему.

На master-сервере:

hostnamectl set-hostname host.domain.ru

apt update
apt upgrade -y
apt install -y curl wget ca-certificates gnupg lsb-release nano dnsutils
reboot

На первом DNS-сервере:

hostnamectl set-hostname ns1.domain.ru

apt update
apt upgrade -y
apt install -y curl wget ca-certificates gnupg lsb-release nano dnsutils
reboot

На втором DNS-сервере:

hostnamectl set-hostname ns2.domain.ru

apt update
apt upgrade -y
apt install -y curl wget ca-certificates gnupg lsb-release nano dnsutils
reboot

5. Установка HestiaCP на master-сервер

На сервере host.domain.ru ставим полноценную HestiaCP-панель.

Если почта на сервере не нужна, можно ставить без Exim и Dovecot:

cd /root

wget https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh

bash hst-install.sh \
  --interactive no \
  --hostname host.domain.ru \
  --email admin@domain.ru \
  --password 'СЛОЖНЫЙ_ПАРОЛЬ' \
  --lang ru \
  --apache yes \
  --phpfpm yes \
  --multiphp yes \
  --vsftpd yes \
  --named yes \
  --mysql yes \
  --postgresql no \
  --exim no \
  --dovecot no \
  --sieve no \
  --clamav no \
  --spamassassin no \
  --iptables yes \
  --fail2ban yes \
  --quota yes \
  --api yes \
  --port 8083

Если нужна почта, тогда вместо блока:

--exim no
--dovecot no
--sieve no

используйте:

--exim yes \
--dovecot yes \
--sieve yes \
--spamassassin yes \

После установки панель будет доступна по адресу:

https://host.domain.ru:8083

6. Установка HestiaCP на DNS-only серверы

На ns1.domain.ru и ns2.domain.ru не нужны Apache, PHP, MySQL, почта и FTP. Эти серверы будут использоваться только для DNS.

На ns1.domain.ru:

cd /root

wget https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh

bash hst-install.sh \
  --interactive no \
  --hostname ns1.domain.ru \
  --email admin@domain.ru \
  --password 'СЛОЖНЫЙ_ПАРОЛЬ' \
  --lang ru \
  --apache no \
  --phpfpm no \
  --multiphp no \
  --vsftpd no \
  --proftpd no \
  --named yes \
  --mysql no \
  --postgresql no \
  --exim no \
  --dovecot no \
  --sieve no \
  --clamav no \
  --spamassassin no \
  --iptables yes \
  --fail2ban yes \
  --quota no \
  --api yes \
  --port 8083

На ns2.domain.ru команда аналогичная:

cd /root

wget https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh

bash hst-install.sh \
  --interactive no \
  --hostname ns2.domain.ru \
  --email admin@domain.ru \
  --password 'СЛОЖНЫЙ_ПАРОЛЬ' \
  --lang ru \
  --apache no \
  --phpfpm no \
  --multiphp no \
  --vsftpd no \
  --proftpd no \
  --named yes \
  --mysql no \
  --postgresql no \
  --exim no \
  --dovecot no \
  --sieve no \
  --clamav no \
  --spamassassin no \
  --iptables yes \
  --fail2ban yes \
  --quota no \
  --api yes \
  --port 8083

7. Включение API на DNS-серверах

Master-сервер должен подключаться к ns1 и ns2 по API HestiaCP. Поэтому на обоих DNS-серверах нужно включить API и разрешить IP master-сервера.

На ns1.domain.ru:

IP_HOST="IP_HOST"

/usr/local/hestia/bin/v-change-sys-api enable api
/usr/local/hestia/bin/v-add-sys-api-ip "$IP_HOST"

systemctl restart hestia

На ns2.domain.ru:

IP_HOST="IP_HOST"

/usr/local/hestia/bin/v-change-sys-api enable api
/usr/local/hestia/bin/v-add-sys-api-ip "$IP_HOST"

systemctl restart hestia

Также желательно открыть порт 8083 только для IP master-сервера и для вашего рабочего IP.

Пример для Hestia firewall:

/usr/local/hestia/bin/v-add-firewall-rule ACCEPT IP_HOST 8083 TCP "Allow Hestia API from master"

8. Включение режима hestia-zone

Для схемы master/slave в HestiaCP нужно использовать режим:

DNS_CLUSTER_SYSTEM='hestia-zone'

На всех трёх серверах выполните:

sed -i "s/^DNS_CLUSTER_SYSTEM=.*/DNS_CLUSTER_SYSTEM='hestia-zone'/" /usr/local/hestia/conf/hestia.conf

grep -q "^DNS_CLUSTER_SYSTEM=" /usr/local/hestia/conf/hestia.conf || \
echo "DNS_CLUSTER_SYSTEM='hestia-zone'" >> /usr/local/hestia/conf/hestia.conf

systemctl restart hestia

9. Настройка BIND на master-сервере

На master-сервере host.domain.ru нужно разрешить передачу DNS-зон на slave-серверы.

Откройте файл:

nano /etc/bind/named.conf.options

Внутри блока options { ... } добавьте или измените параметры:

allow-transfer { IP_NS1; IP_NS2; };
also-notify { IP_NS1; IP_NS2; };

Пример:

options {
    directory "/var/cache/bind";

    dnssec-validation auto;
    auth-nxdomain no;

    allow-transfer { IP_NS1; IP_NS2; };
    also-notify { IP_NS1; IP_NS2; };

    hostname none;
    server-id none;
    version none;
};

Проверяем конфигурацию и перезапускаем BIND:

named-checkconf
systemctl restart named || systemctl restart bind9

10. Настройка BIND на DNS-slave серверах

На ns1.domain.ru и ns2.domain.ru нужно разрешить уведомления от master-сервера.

Откройте файл:

nano /etc/bind/named.conf.options

Пример конфига для DNS-only slave:

options {
    directory "/var/cache/bind";

    dnssec-validation auto;
    auth-nxdomain no;

    listen-on port 53 { any; };
    listen-on-v6 { none; };

    allow-query { any; };

    recursion no;
    allow-recursion { none; };

    allow-notify { IP_HOST; };
    allow-transfer { "none"; };

    hostname none;
    server-id none;
    version none;
};

После изменения:

named-checkconf
named-checkconf -z
systemctl restart named || systemctl restart bind9

Важно: для публичного авторитетного DNS-сервера рекурсию лучше отключать:

recursion no;
allow-recursion { none; };

Иначе сервер может стать открытым рекурсивным DNS-резолвером, что плохо с точки зрения безопасности.


11. Создание DNS-пользователей на slave-серверах

На ns1.domain.ru создаём отдельного пользователя, под которым будут храниться DNS-зоны:

DNS_PASS_NS1='СЛОЖНЫЙ_ПАРОЛЬ'

/usr/local/hestia/bin/v-add-user dns-ns1 "$DNS_PASS_NS1" dns-ns1@domain.ru
/usr/local/hestia/bin/v-change-user-config-value dns-ns1 ROLE dns-cluster

На ns2.domain.ru:

DNS_PASS_NS2='СЛОЖНЫЙ_ПАРОЛЬ'

/usr/local/hestia/bin/v-add-user dns-ns2 "$DNS_PASS_NS2" dns-ns2@domain.ru
/usr/local/hestia/bin/v-change-user-config-value dns-ns2 ROLE dns-cluster

Если команда изменения роли не подходит для вашей версии HestiaCP, можно сделать это через панель: открыть пользователя и назначить роль dns-cluster.


12. Создание API-ключей на DNS-серверах

На ns1.domain.ru и ns2.domain.ru нужно создать access key для подключения master-сервера.

Рекомендуемый способ — через панель HestiaCP:

https://ns1.domain.ru:8083
https://ns2.domain.ru:8083

В панели:

Admin → Access Keys → Add Access Key

Для ключа желательно выдать минимальные права, необходимые для синхронизации DNS-кластера. После создания вы получите пару:

ACCESS_KEY:SECRET_KEY

Сохраните отдельно ключ для ns1 и отдельно ключ для ns2.

Например:

NS1_ACCESS="ACCESS_KEY_NS1:SECRET_KEY_NS1"
NS2_ACCESS="ACCESS_KEY_NS2:SECRET_KEY_NS2"

13. Подключение slave DNS-серверов к master

На master-сервере host.domain.ru добавляем удалённые DNS-хосты:

NS1_ACCESS='ACCESS_KEY_NS1:SECRET_KEY_NS1'
NS2_ACCESS='ACCESS_KEY_NS2:SECRET_KEY_NS2'

/usr/local/hestia/bin/v-add-remote-dns-host ns1.domain.ru 8083 "$NS1_ACCESS" '' 'api' 'dns-ns1'
/usr/local/hestia/bin/v-add-remote-dns-host ns2.domain.ru 8083 "$NS2_ACCESS" '' 'api' 'dns-ns2'

Проверить список подключённых DNS-хостов:

/usr/local/hestia/bin/v-list-remote-dns-hosts

Если при синхронизации появляется ошибка:

Error: ns1.domain.ru connection failed

нужно проверить:

getent hosts ns1.domain.ru
nc -vz ns1.domain.ru 8083
curl -kI https://ns1.domain.ru:8083/

Частые причины:

1. hostname ns1.domain.ru не резолвится с master-сервера;
2. закрыт порт 8083;
3. API на slave-сервере выключен;
4. IP master-сервера не добавлен в API allowlist;
5. неправильно создан access key.

14. Создание DNS-зоны domain.ru

На master-сервере в HestiaCP создайте DNS-зону:

DNS → Add DNS Zone → domain.ru

В зоне должны быть записи:

@     NS    ns1.domain.ru.
@     NS    ns2.domain.ru.

ns1   A     IP_NS1
ns2   A     IP_NS2
host  A     IP_HOST

Также можно добавить запись для панели:

panel A IP_HOST

Если панель будет открываться по host.domain.ru, достаточно записи:

host A IP_HOST

15. Синхронизация DNS-зон

На master-сервере запускаем синхронизацию:

/usr/local/hestia/bin/v-sync-dns-cluster ns1.domain.ru
/usr/local/hestia/bin/v-sync-dns-cluster ns2.domain.ru

На ns1.domain.ru проверяем:

/usr/local/hestia/bin/v-list-dns-domains dns-ns1

На ns2.domain.ru:

/usr/local/hestia/bin/v-list-dns-domains dns-ns2

Если всё хорошо, в списке должна быть зона:

domain.ru

16. Проверка BIND на DNS-серверах

На каждом DNS-сервере проверяем, что BIND запущен:

systemctl status named --no-pager

или:

systemctl status bind9 --no-pager

Проверяем, слушает ли сервер порт 53:

ss -lntup | grep ':53'

Нужно увидеть, что named слушает внешний IP-адрес сервера:

IP_NS1:53
IP_NS2:53

Проверяем локальный ответ на ns1:

dig @127.0.0.1 domain.ru SOA +short
dig @IP_NS1 domain.ru SOA +short

Проверяем локальный ответ на ns2:

dig @127.0.0.1 domain.ru SOA +short
dig @IP_NS2 domain.ru SOA +short

Если ответ есть, BIND работает локально.


17. Проверка DNS с внешнего компьютера

С рабочего компьютера или любого стороннего сервера:

dig @IP_NS1 domain.ru SOA +short
dig @IP_NS2 domain.ru SOA +short

Оба сервера должны вернуть SOA-запись.

Например:

ns1.domain.ru. root.domain.ru. 2026052004 7200 3600 1209600 180

Проверяем NS-записи:

dig @IP_NS1 domain.ru NS +short
dig @IP_NS2 domain.ru NS +short

Ожидаемый результат:

ns1.domain.ru.
ns2.domain.ru.

Проверяем публичное делегирование:

dig domain.ru NS +short

Ожидаемый результат:

ns1.domain.ru.
ns2.domain.ru.

Проверяем записи DNS-серверов:

dig ns1.domain.ru A +short
dig ns2.domain.ru A +short
dig host.domain.ru A +short

Ожидаемо:

IP_NS1
IP_NS2
IP_HOST

18. Возможная проблема: BIND отдаёт SERVFAIL на одном slave

Иногда зона в HestiaCP есть, команда v-list-dns-domains её показывает, named-checkconf -z говорит, что зона загружается, но при запросе:

dig @127.0.0.1 domain.ru SOA

получаем:

status: SERVFAIL

Проверяем статус зоны:

rndc zonestatus domain.ru

Если ответ:

zone not loaded

смотрим журнал BIND:

journalctl -u named -n 80 --no-pager

или:

journalctl -u bind9 -n 80 --no-pager

Если там есть ошибка вида:

loading from master file /home/dns-ns1/conf/dns/domain.ru.db failed: permission denied
zone domain.ru/IN: not loaded due to errors

то проблема может быть не в правах файла, а в AppArmor.

Проверяем AppArmor:

journalctl -k -g 'apparmor.*named|DENIED.*named' -n 50 --no-pager

Если видим:

apparmor="DENIED" operation="open" profile="named" name="/home/dns-ns1/conf/dns/domain.ru.db"

разрешаем BIND читать зоны HestiaCP.

Для ns1, если DNS-пользователь называется dns-ns1:

printf '\n# Hestia DNS zones\n/home/dns-ns1/conf/dns/** r,\n' >> /etc/apparmor.d/local/usr.sbin.named

apparmor_parser -r /etc/apparmor.d/usr.sbin.named
systemctl restart named

Для ns2, если DNS-пользователь называется dns-ns2:

printf '\n# Hestia DNS zones\n/home/dns-ns2/conf/dns/** r,\n' >> /etc/apparmor.d/local/usr.sbin.named

apparmor_parser -r /etc/apparmor.d/usr.sbin.named
systemctl restart named

После этого снова проверяем:

dig @127.0.0.1 domain.ru SOA +short

Если SOA-запись появилась, проблема устранена.


19. Возможная проблема: DNS работает локально, но не отвечает снаружи

Бывает ситуация, когда на самом DNS-сервере команда работает:

dig @IP_NS2 domain.ru SOA +short

а с внешнего компьютера:

dig @IP_NS2 domain.ru SOA +short

возвращает timeout.

Проверяем TCP:

dig +tcp @IP_NS2 domain.ru SOA +short

Если UDP timeout, а TCP connection reset или тоже не работает, нужно проверить firewall.

Смотрим правила Hestia:

/usr/local/hestia/bin/v-list-firewall

Должны быть открыты:

53 TCP
53 UDP

Но иногда на сервере дополнительно работает UFW, и правила Hestia не попадают в ufw-user-input.

Проверяем:

iptables -L INPUT -n -v --line-numbers
iptables -L ufw-user-input -n -v --line-numbers

Если в ufw-user-input нет правил для 53 порта, добавляем:

ufw allow 53
ufw reload

После этого снова проверяем с внешнего компьютера:

dig @IP_NS1 domain.ru SOA +short
dig @IP_NS2 domain.ru SOA +short

Если оба сервера отвечают — DNS работает правильно.

Также проверьте firewall в панели провайдера VPS. Некоторые провайдеры имеют отдельный сетевой firewall вне сервера. Там тоже должны быть открыты:

53 UDP
53 TCP

20. Настройка SSL для панелей HestiaCP

Когда DNS уже работает и записи указывают на правильные IP, можно выпустить Let’s Encrypt сертификаты для всех трёх панелей.

На master-сервере:

/usr/local/hestia/bin/v-add-letsencrypt-host

Панель будет доступна по:

https://host.domain.ru:8083

На ns1.domain.ru:

/usr/local/hestia/bin/v-add-letsencrypt-host

Панель:

https://ns1.domain.ru:8083

На ns2.domain.ru:

/usr/local/hestia/bin/v-add-letsencrypt-host

Панель:

https://ns2.domain.ru:8083

Перед выпуском сертификатов проверьте:

dig host.domain.ru A +short
dig ns1.domain.ru A +short
dig ns2.domain.ru A +short

Ожидаемо:

IP_HOST
IP_NS1
IP_NS2

Также порт 80/tcp должен быть доступен извне, иначе проверка Let’s Encrypt может не пройти.


21. Финальная проверка всей схемы

С внешнего компьютера:

dig domain.ru NS +short

Должно быть:

ns1.domain.ru.
ns2.domain.ru.

Проверяем glue/A-записи:

dig ns1.domain.ru A +short
dig ns2.domain.ru A +short
dig host.domain.ru A +short

Должно быть:

IP_NS1
IP_NS2
IP_HOST

Проверяем ответы обоих DNS-серверов:

dig @IP_NS1 domain.ru SOA +short
dig @IP_NS2 domain.ru SOA +short

Оба должны вернуть SOA-запись.

Проверяем NS с каждого сервера:

dig @IP_NS1 domain.ru NS +short
dig @IP_NS2 domain.ru NS +short

Ожидаемо:

ns1.domain.ru.
ns2.domain.ru.

Проверяем запись панели:

dig host.domain.ru A +short

Ожидаемо:

IP_HOST

22. Итог

В результате получается такая схема:

Пользователь создаёт домен в HestiaCP на host.domain.ru
        ↓
HestiaCP создаёт DNS-зону на master-сервере
        ↓
Master синхронизирует зону на ns1.domain.ru и ns2.domain.ru
        ↓
В интернете за домены отвечают ns1.domain.ru и ns2.domain.ru

Для клиентов указываются только NS:

ns1.domain.ru
ns2.domain.ru

А управление DNS-зонами остаётся в одной панели HestiaCP на master-сервере.

Главные моменты, которые нужно проверить после установки:

1. У регистратора созданы glue records для ns1 и ns2.
2. Домен domain.ru делегирован на ns1.domain.ru и ns2.domain.ru.
3. На master включён BIND и разрешён transfer на IP slave-серверов.
4. На slave-серверах включён BIND и разрешён notify от master.
5. В HestiaCP включён режим hestia-zone.
6. API на slave-серверах включён и разрешает IP master-сервера.
7. Порт 8083 доступен с master до slave-серверов.
8. Порты 53 TCP и 53 UDP открыты наружу на ns1 и ns2.
9. AppArmor не блокирует чтение DNS-зон из /home/dns-user/conf/dns/.
10. Оба DNS-сервера отвечают на dig-запросы извне.

Если все проверки проходят, HestiaCP DNS-кластер master/slave настроен корректно.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *