Hub docs: the two servers are mdns.shnt.top and ndns.shnt.top, the hub is on dnss.shnt.top
CI / check (push) Successful in 2m39s
Hub / check (push) Successful in 41s
CI / image (push) Successful in 2m11s
Hub / image (push) Successful in 1m48s

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
DenozordecandClaude Opus 5.5 committed 2026-10-30 21:53:53 +07:00
1 parent 607d46f872
commit 042cb116ea
3 files changed
+36 -36

No files matched your search

+5 -5
View File
@@ -9,7 +9,7 @@ version: "3.8"
# 2. Administration > Users: пользователь hub-reader в этой группе. # 2. Administration > Users: пользователь hub-reader в этой группе.
# 3. Войти под ним и создать токен: Administration > Sessions > Create API Token. # 3. Войти под ним и создать токен: Administration > Sessions > Create API Token.
# Токены кладутся в .env рядом с этим файлом (не в git): # Токены кладутся в .env рядом с этим файлом (не в git):
# DNS_TOKEN=... # MDNS_TOKEN=...
# NDNS_TOKEN=... # NDNS_TOKEN=...
# HUB_USER=... # логин в сам хаб # HUB_USER=... # логин в сам хаб
# HUB_PASSWORD=... # длинный пароль: у хаба нет ограничения числа попыток входа # HUB_PASSWORD=... # длинный пароль: у хаба нет ограничения числа попыток входа
@@ -25,18 +25,18 @@ services:
- dns-net - dns-net
environment: environment:
# id=адрес, по порядку; токен каждого берётся из <ID>_TOKEN # id=адрес, по порядку; токен каждого берётся из <ID>_TOKEN
- HUB_SERVERS=dns=https://dns.shnt.top,ndns=https://ndns.shnt.top - HUB_SERVERS=mdns=https://mdns.shnt.top,ndns=https://ndns.shnt.top
- DNS_TOKEN=${DNS_TOKEN} - MDNS_TOKEN=${MDNS_TOKEN}
- NDNS_TOKEN=${NDNS_TOKEN} - NDNS_TOKEN=${NDNS_TOKEN}
- HUB_USER=${HUB_USER} - HUB_USER=${HUB_USER}
- HUB_PASSWORD=${HUB_PASSWORD} - HUB_PASSWORD=${HUB_PASSWORD}
- HUB_DOMAIN=hub.shnt.top - HUB_DOMAIN=dnss.shnt.top
- TZ=Asia/Novosibirsk - TZ=Asia/Novosibirsk
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
- "traefik.docker.network=dns-net" - "traefik.docker.network=dns-net"
- "traefik.http.routers.hub.rule=Host(`hub.shnt.top`)" - "traefik.http.routers.hub.rule=Host(`dnss.shnt.top`)"
- "traefik.http.routers.hub.entrypoints=websecure" - "traefik.http.routers.hub.entrypoints=websecure"
- "traefik.http.routers.hub.tls.certresolver=myresolver" - "traefik.http.routers.hub.tls.certresolver=myresolver"
- "traefik.http.routers.hub.service=hub-svc" - "traefik.http.routers.hub.service=hub-svc"
+4 -4
View File
@@ -173,7 +173,7 @@ services:
# Хаб: одна консоль со статистикой обоих серверов на https://dnss.shnt.top # Хаб: одна консоль со статистикой обоих серверов на https://dnss.shnt.top
# (docs/hub-deploy.md). Только чтение. Токены и вход хаба берутся из .env: # (docs/hub-deploy.md). Только чтение. Токены и вход хаба берутся из .env:
# DNS_TOKEN, NDNS_TOKEN (пользователь hub-reader на каждом сервере), HUB_USER, HUB_PASSWORD. # MDNS_TOKEN, NDNS_TOKEN (пользователь hub-reader на каждом сервере), HUB_USER, HUB_PASSWORD.
# Обновление: docker compose pull technitium-hub && docker compose up -d technitium-hub # Обновление: docker compose pull technitium-hub && docker compose up -d technitium-hub
technitium-hub: technitium-hub:
image: git.shx.one/denozord/technitium-hub:latest image: git.shx.one/denozord/technitium-hub:latest
@@ -183,9 +183,9 @@ services:
- dns-net - dns-net
environment: environment:
# id=адрес по порядку; токен каждого из <ID>_TOKEN. Сервер на ЭТОМ же хосте можно # id=адрес по порядку; токен каждого из <ID>_TOKEN. Сервер на ЭТОМ же хосте можно
# указать изнутри сети, мимо Traefik: dns=http://technitium-smart:5380 # указать изнутри сети, мимо Traefik: ndns=http://technitium-smart:5380
- HUB_SERVERS=dns=https://dns.shnt.top,ndns=https://ndns.shnt.top - HUB_SERVERS=mdns=https://mdns.shnt.top,ndns=https://ndns.shnt.top
- DNS_TOKEN=${DNS_TOKEN} - MDNS_TOKEN=${MDNS_TOKEN}
- NDNS_TOKEN=${NDNS_TOKEN} - NDNS_TOKEN=${NDNS_TOKEN}
- HUB_USER=${HUB_USER} - HUB_USER=${HUB_USER}
- HUB_PASSWORD=${HUB_PASSWORD} - HUB_PASSWORD=${HUB_PASSWORD}
+27 -27
View File
@@ -1,16 +1,16 @@
# Хаб: запуск по шагам # Хаб: запуск по шагам
Хаб показывает статистику двух серверов Technitium DNS (`dns.shnt.top` и `ndns.shnt.top`) в одной консоли. Это один маленький контейнер. Он отдаёт ту же консоль и сам ходит в API обоих серверов по их токенам: Хаб показывает статистику двух серверов Technitium DNS (`mdns.shnt.top` и `ndns.shnt.top`) в одной консоли. Это один маленький контейнер. Он отдаёт ту же консоль и сам ходит в API обоих серверов по их токенам:
- запрос «All servers» хаб отправляет на оба сервера и складывает ответы; - запрос «All servers» хаб отправляет на оба сервера и складывает ответы;
- запрос к одному серверу хаб пересылает только ему; - запрос к одному серверу хаб пересылает только ему;
- запись хаб не выполняет никогда. - запись хаб не выполняет никогда.
Серверы Technitium не меняются, кластер не нужен. В инструкции хаб ставится на хост, где уже работают Traefik и `technitium-smart` (`docs/compose.shnt.example.yaml`). Адрес хаба: `https://hub.shnt.top`. Серверы Technitium не меняются, кластер не нужен. В инструкции хаб ставится на хост, где уже работают Traefik и `technitium-smart` (`docs/compose.shnt.example.yaml`). Адрес хаба: `https://dnss.shnt.top`.
``` ```
браузер ─► Traefik (hub.shnt.top, TLS) ─► technitium-hub:8080 браузер ─► Traefik (dnss.shnt.top, TLS) ─► technitium-hub:8080
├─► https://dns.shnt.top/api/... (DNS_TOKEN) ├─► https://mdns.shnt.top/api/... (MDNS_TOKEN)
└─► https://ndns.shnt.top/api/... (NDNS_TOKEN) └─► https://ndns.shnt.top/api/... (NDNS_TOKEN)
``` ```
@@ -43,7 +43,7 @@ git tag hub-v1.0.0 && git push origin hub-v1.0.0
## Шаг 1. Пользователь только для чтения на каждом сервере ## Шаг 1. Пользователь только для чтения на каждом сервере
Сделайте это **на обоих серверах**: `https://dns.shnt.top` и `https://ndns.shnt.top`. Войдите в консоль сервера как администратор. Сделайте это **на обоих серверах**: `https://mdns.shnt.top` и `https://ndns.shnt.top`. Войдите в консоль сервера как администратор.
1. **Группа.** Administration › Groups › **Add Group**: имя `hub-readers`, описание любое. 1. **Группа.** Administration › Groups › **Add Group**: имя `hub-readers`, описание любое.
2. **Права группы.** Administration › Permissions: у группы `hub-readers` отметьте только **View** в четырёх разделах: 2. **Права группы.** Administration › Permissions: у группы `hub-readers` отметьте только **View** в четырёх разделах:
@@ -65,18 +65,18 @@ git tag hub-v1.0.0 && git push origin hub-v1.0.0
Можно и под администратором: Administration › Sessions › **Create Token**, пользователь `hub-reader`. Можно и под администратором: Administration › Sessions › **Create Token**, пользователь `hub-reader`.
5. Проверьте токен с любой машины. В ответе должно быть `"status":"ok"`: 5. Проверьте токен с любой машины. В ответе должно быть `"status":"ok"`:
```bash ```bash
curl -s "https://dns.shnt.top/api/dashboard/stats/get?type=LastHour&token=ТОКЕН" | head -c 200 curl -s "https://mdns.shnt.top/api/dashboard/stats/get?type=LastHour&token=ТОКЕН" | head -c 200
``` ```
- `"status":"invalid-token"` значит, что скопирован не тот токен; - `"status":"invalid-token"` значит, что скопирован не тот токен;
- `"status":"error"` с сообщением об отказе в доступе значит, что у группы не хватает права View. - `"status":"error"` с сообщением об отказе в доступе значит, что у группы не хватает права View.
Результат шага: два токена, `DNS_TOKEN` (с `dns.shnt.top`) и `NDNS_TOKEN` (с `ndns.shnt.top`). Результат шага: два токена, `MDNS_TOKEN` (с `mdns.shnt.top`) и `NDNS_TOKEN` (с `ndns.shnt.top`).
--- ---
## Шаг 2. DNS-запись для hub.shnt.top ## Шаг 2. DNS-запись для dnss.shnt.top
В Cloudflare (зона `shnt.top`) создайте запись `hub` той же формы, что `dns`: `A` на IP хоста или `CNAME` на `dns.shnt.top`. В Cloudflare (зона `shnt.top`) создайте запись `dnss` типа `A` на IP хоста, где работает хаб.
Сертификат Traefik получит сам. В compose уже настроен `certresolver=myresolver` с DNS-challenge через Cloudflare (`CF_DNS_API_TOKEN`), отдельно открывать порт 80 для проверки не нужно. Сертификат Traefik получит сам. В compose уже настроен `certresolver=myresolver` с DNS-challenge через Cloudflare (`CF_DNS_API_TOKEN`), отдельно открывать порт 80 для проверки не нужно.
@@ -88,7 +88,7 @@ git tag hub-v1.0.0 && git push origin hub-v1.0.0
```dotenv ```dotenv
# Хаб: токены пользователей hub-reader с шага 1 # Хаб: токены пользователей hub-reader с шага 1
DNS_TOKEN=вставьте_токен_dns MDNS_TOKEN=вставьте_токен_mdns
NDNS_TOKEN=вставьте_токен_ndns NDNS_TOKEN=вставьте_токен_ndns
# Вход в сам хаб (это НЕ логин Technitium) # Вход в сам хаб (это НЕ логин Technitium)
@@ -121,17 +121,17 @@ chmod 600 .env
- dns-net - dns-net
environment: environment:
# id=адрес, по порядку; токен каждого берётся из <ID>_TOKEN # id=адрес, по порядку; токен каждого берётся из <ID>_TOKEN
- HUB_SERVERS=dns=https://dns.shnt.top,ndns=https://ndns.shnt.top - HUB_SERVERS=mdns=https://mdns.shnt.top,ndns=https://ndns.shnt.top
- DNS_TOKEN=${DNS_TOKEN} - MDNS_TOKEN=${MDNS_TOKEN}
- NDNS_TOKEN=${NDNS_TOKEN} - NDNS_TOKEN=${NDNS_TOKEN}
- HUB_USER=${HUB_USER} - HUB_USER=${HUB_USER}
- HUB_PASSWORD=${HUB_PASSWORD} - HUB_PASSWORD=${HUB_PASSWORD}
- HUB_DOMAIN=hub.shnt.top - HUB_DOMAIN=dnss.shnt.top
- TZ=Asia/Novosibirsk - TZ=Asia/Novosibirsk
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
- "traefik.docker.network=dns-net" - "traefik.docker.network=dns-net"
- "traefik.http.routers.hub.rule=Host(`hub.shnt.top`)" - "traefik.http.routers.hub.rule=Host(`dnss.shnt.top`)"
- "traefik.http.routers.hub.entrypoints=websecure" - "traefik.http.routers.hub.entrypoints=websecure"
- "traefik.http.routers.hub.tls.certresolver=myresolver" - "traefik.http.routers.hub.tls.certresolver=myresolver"
- "traefik.http.routers.hub.service=hub-svc" - "traefik.http.routers.hub.service=hub-svc"
@@ -142,10 +142,10 @@ chmod 600 .env
Про имена в `HUB_SERVERS`: Про имена в `HUB_SERVERS`:
- имя слева от `=` видно в консоли в селекторе «Server»; - имя слева от `=` видно в консоли в селекторе «Server»;
- из имени получается переменная токена: `dns` даёт `DNS_TOKEN`, `ndns` даёт `NDNS_TOKEN`, `my-dns` дал бы `MY_DNS_TOKEN`; - из имени получается переменная токена: `mdns` даёт `MDNS_TOKEN`, `ndns` даёт `NDNS_TOKEN`, `my-dns` дал бы `MY_DNS_TOKEN`;
- первый в списке сервер считается основным. - первый в списке сервер считается основным.
Адреса серверов указываются публичные (`https://dns.shnt.top`). API Technitium доступно по тому же адресу, что и консоль (роутер `panel-old` в Traefik), отдельный порт не нужен. Адреса серверов указываются публичные (`https://mdns.shnt.top`). API Technitium доступно по тому же адресу, что и консоль (роутер `panel-old` в Traefik), отдельный порт не нужен.
--- ---
@@ -174,19 +174,19 @@ docker compose logs -f technitium-hub
## Шаг 6. Проверка ## Шаг 6. Проверка
1. Откройте `https://hub.shnt.top` и войдите с `HUB_USER` / `HUB_PASSWORD` из `.env`. 1. Откройте `https://dnss.shnt.top` и войдите с `HUB_USER` / `HUB_PASSWORD` из `.env`.
2. На Dashboard над заголовком должен быть селектор **Server: All servers**. 2. На Dashboard над заголовком должен быть селектор **Server: All servers**.
3. Сверьте цифры. Total Queries в «All servers» должна равняться сумме значений в консолях `dns.shnt.top` и `ndns.shnt.top` за тот же период. Расхождение в пределах минуты нормально: хаб кеширует ответы на 15 секунд, а Last Hour обновляется на ходу. 3. Сверьте цифры. Total Queries в «All servers» должна равняться сумме значений в консолях `mdns.shnt.top` и `ndns.shnt.top` за тот же период. Расхождение в пределах минуты нормально: хаб кеширует ответы на 15 секунд, а Last Hour обновляется на ходу.
4. Выберите в селекторе `dns`, затем `ndns`: цифры каждого сервера должны совпасть с его собственной консолью. 4. Выберите в селекторе `mdns`, затем `ndns`: цифры каждого сервера должны совпасть с его собственной консолью.
5. Откройте Logs › Query Logs, нажмите **Query**. Записи обоих серверов идут вместе, в колонке **Server** видно, чья запись. 5. Откройте Logs › Query Logs, нажмите **Query**. Записи обоих серверов идут вместе, в колонке **Server** видно, чья запись.
6. Кнопка статуса справа в шапке показывает `hub.shnt.top`. Если какой-то сервер не ответил, там будет «1 server not answering», а по нажатию появится причина. 6. Кнопка статуса справа в шапке показывает `dnss.shnt.top`. Если какой-то сервер не ответил, там будет «1 server not answering», а по нажатию появится причина.
Проверка без браузера (подставьте пароль хаба): Проверка без браузера (подставьте пароль хаба):
```bash ```bash
T=$(curl -s -X POST https://hub.shnt.top/api/user/login \ T=$(curl -s -X POST https://dnss.shnt.top/api/user/login \
--data-urlencode "user=admin" --data-urlencode "pass=ПАРОЛЬ_ХАБА" | sed -E 's/.*"token":"([^"]+)".*/\1/') --data-urlencode "user=admin" --data-urlencode "pass=ПАРОЛЬ_ХАБА" | sed -E 's/.*"token":"([^"]+)".*/\1/')
curl -s -H "Authorization: Bearer $T" "https://hub.shnt.top/api/dashboard/stats/get?type=LastHour" | head -c 300 curl -s -H "Authorization: Bearer $T" "https://dnss.shnt.top/api/dashboard/stats/get?type=LastHour" | head -c 300
curl -s -H "Authorization: Bearer $T" "https://hub.shnt.top/api/dashboard/stats/get?type=LastHour&node=ndns" | head -c 300 curl -s -H "Authorization: Bearer $T" "https://dnss.shnt.top/api/dashboard/stats/get?type=LastHour&node=ndns" | head -c 300
``` ```
--- ---
@@ -217,7 +217,7 @@ docker compose rm -f technitium-hub # удалить контейнер
| Переменная | По умолчанию | Что задаёт | | Переменная | По умолчанию | Что задаёт |
|---|---|---| |---|---|---|
| `HUB_SERVERS` | обязательна | Серверы по порядку: `id=https://адрес,...` | | `HUB_SERVERS` | обязательна | Серверы по порядку: `id=https://адрес,...` |
| `<ID>_TOKEN` | обязательна для каждого | API-токен сервера (`DNS_TOKEN`, `NDNS_TOKEN`, ...) | | `<ID>_TOKEN` | обязательна для каждого | API-токен сервера (`MDNS_TOKEN`, `NDNS_TOKEN`, ...) |
| `HUB_USER`, `HUB_PASSWORD` | обязательны | Вход в хаб | | `HUB_USER`, `HUB_PASSWORD` | обязательны | Вход в хаб |
| `HUB_DOMAIN` | `hub` | Имя, которое консоль показывает как имя сервера | | `HUB_DOMAIN` | `hub` | Имя, которое консоль показывает как имя сервера |
| `HUB_CACHE_SECONDS` | `15` | Сколько секунд хранить ответы серверов (0 выключает кеш) | | `HUB_CACHE_SECONDS` | `15` | Сколько секунд хранить ответы серверов (0 выключает кеш) |
@@ -226,7 +226,7 @@ docker compose rm -f technitium-hub # удалить контейнер
Третий сервер добавляется строкой в `HUB_SERVERS` и его токеном: Третий сервер добавляется строкой в `HUB_SERVERS` и его токеном:
```yaml ```yaml
- HUB_SERVERS=dns=https://dns.shnt.top,ndns=https://ndns.shnt.top,lab=https://lab.shnt.top - HUB_SERVERS=mdns=https://mdns.shnt.top,ndns=https://ndns.shnt.top,lab=https://lab.shnt.top
- LAB_TOKEN=${LAB_TOKEN} - LAB_TOKEN=${LAB_TOKEN}
``` ```
@@ -237,8 +237,8 @@ docker compose rm -f technitium-hub # удалить контейнер
| Признак | Причина и что делать | | Признак | Причина и что делать |
|---|---| |---|---|
| Контейнер сразу завершается | В `docker compose logs technitium-hub` будет названа недостающая переменная. Проверьте `.env` и что compose его видит (`docker compose config \| grep TOKEN`). | | Контейнер сразу завершается | В `docker compose logs technitium-hub` будет названа недостающая переменная. Проверьте `.env` и что compose его видит (`docker compose config \| grep TOKEN`). |
| `https://hub.shnt.top` не открывается, ошибка сертификата | Нет DNS-записи `hub` (шаг 2) или Traefik ещё получает сертификат: смотрите `docker logs traefik`. | | `https://dnss.shnt.top` не открывается, ошибка сертификата | Нет DNS-записи `dnss` (шаг 2) или Traefik ещё получает сертификат: смотрите `docker logs traefik`. |
| 404 от Traefik | Контейнер не в сети `dns-net` или опечатка в `Host(\`hub.shnt.top\`)`. | | 404 от Traefik | Контейнер не в сети `dns-net` или опечатка в `Host(\`dnss.shnt.top\`)`. |
| Вход в хаб: «Invalid username or password» | Неверные `HUB_USER`/`HUB_PASSWORD` в `.env`. После правки `.env` нужен `docker compose up -d technitium-hub`. | | Вход в хаб: «Invalid username or password» | Неверные `HUB_USER`/`HUB_PASSWORD` в `.env`. После правки `.env` нужен `docker compose up -d technitium-hub`. |
| В шапке «1 server not answering», в подсказке `ndns: its API token was refused` | Токен `NDNS_TOKEN` отозван или скопирован с ошибкой. Создайте новый (шаг 1.4) и перезапустите хаб. | | В шапке «1 server not answering», в подсказке `ndns: its API token was refused` | Токен `NDNS_TOKEN` отозван или скопирован с ошибкой. Создайте новый (шаг 1.4) и перезапустите хаб. |
| В подсказке `... did not answer: ...` или `ECONNREFUSED` / `timeout` | Хаб не достучался до сервера. Проверьте с хоста хаба: `docker exec technitium-hub node -e "fetch('https://ndns.shnt.top/api/status').then(r=>console.log(r.status))"`. | | В подсказке `... did not answer: ...` или `ECONNREFUSED` / `timeout` | Хаб не достучался до сервера. Проверьте с хоста хаба: `docker exec technitium-hub node -e "fetch('https://ndns.shnt.top/api/status').then(r=>console.log(r.status))"`. |