diff --git a/.forgejo/workflows/deploy.yaml b/.forgejo/workflows/deploy.yaml
index 50c8cfc..f7857d5 100644
--- a/.forgejo/workflows/deploy.yaml
+++ b/.forgejo/workflows/deploy.yaml
@@ -3,10 +3,31 @@ name: Deploy DNS Configuration
on:
push:
branches: [ main ]
+ paths: [ 'domains.txt' ]
jobs:
deploy:
runs-on: self-hosted # Используем self-hosted runner на шлюзе
+ env:
+ # ==== Конфигурация проекта ====
+ INPUT_FILE: domains.txt
+
+ # Временные конфиги (куда пишутся generate-configs.sh)
+ IPSET_CONF: /tmp/91-ipset-bbrkn.conf
+ RESOLVE_CONF: /tmp/92-resolve-bbrkn.conf
+
+ # DNS-сервер для резолвинга
+ DNS_SERVER: 8.8.8.8
+
+ # Адрес сервиса Chromium
+ API_URL: http://10.100.1.2:3000/domains?domain=
+
+ # Директория конфигов на шлюзе
+ TARGET_DIR: /opt/appdata/pihole/etc/dnsmasq.d
+
+ # Имя контейнера Pi-hole
+ DOCKER_CONTAINER: pihole
+
steps:
- name: Checkout repository
uses: actions/checkout@v3
@@ -30,10 +51,9 @@ jobs:
chmod +x scripts/generate-configs.sh
chmod +x scripts/deploy-to-gateway.sh
- - name: Run workflow (clean → check → all)
+ - name: Run workflow (clean → all)
run: |
make clean
- make check
make all
- name: Upload configs as artifacts
@@ -41,5 +61,5 @@ jobs:
with:
name: dnsmasq-configs
path: |
- /tmp/91-ipset-bbrkn.conf
- /tmp/92-resolve-bbrkn.conf
+ ${{ env.IPSET_CONF }}
+ ${{ env.RESOLVE_CONF }}
diff --git a/README.md b/README.md
index f393eb5..d44265b 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,202 @@
-# bbrkn
+# BBRKN DNS Configurator
+## Описание
+
+**BBRKN** — это инструмент для автоматического формирования и деплоя конфигураций
+для `dnsmasq` (через Pi-hole), необходимых для корректной работы целевых сайтов и сервисов.
+
+Проект решает задачу: у нас есть список базовых доменов (`domains.txt`), но для работы
+сайтов часто требуется множество дополнительных ресурсов — CDN, API-эндпоинты,
+трекеры и т.д. Ручное отслеживание этих зависимостей неудобно.
+
+Для этого используется сервис на базе Chromium, который автоматически анализирует
+страницу и возвращает список всех связанных доменов. Проект берёт этот список,
+нормализует его и формирует два конфигурационных файла для `dnsmasq`:
+
+- `91-ipset-bbrkn.conf` — добавляет все домены в ipset `bbrkn`
+- `92-resolve-bbrkn.conf` — указывает резолвить все эти домены через DNS-сервер `8.8.8.8`
+
+Эти файлы затем автоматически деплоятся в Pi-hole и активируются перезапуском контейнера.
+
+---
+
+## Архитектура
+
+```mermaid
+flowchart TD
+ A[domains.txt] --> B[generate-configs.sh]
+ B -->|HTTP API| C[Chromium service
API_URL]
+ B --> D[91-ipset-bbrkn.conf
92-resolve-bbrkn.conf]
+ D --> E[deploy-to-gateway.sh]
+ E --> F[Pi-hole
(dnsmasq)]
+```
+
+---
+
+## Переменные окружения
+
+Все важные параметры конфигурируются через **переменные окружения**.
+Если переменная не задана, используется дефолтное значение.
+
+| Переменная | По умолчанию | Назначение |
+| ------------------ | ---------------------------------------- | ------------------------------------------- |
+| `INPUT_FILE` | `domains.txt` | Входной список доменов |
+| `IPSET_CONF` | `/tmp/91-ipset-bbrkn.conf` | Временный файл конфигурации для ipset |
+| `RESOLVE_CONF` | `/tmp/92-resolve-bbrkn.conf` | Временный файл конфигурации для серверов |
+| `API_URL` | `http://10.100.1.2:3000/domains?domain=` | Адрес API сервиса Chromium |
+| `DNS_SERVER` | `8.8.8.8` | DNS-сервер, через который резолвятся домены |
+| `TARGET_DIR` | `/opt/appdata/pihole/etc/dnsmasq.d` | Директория для установки конфигов в Pi-hole |
+| `DOCKER_CONTAINER` | `pihole` | Имя контейнера Pi-hole |
+
+👉 В Forgejo workflow все эти переменные задаются в секции `env:`.
+
+---
+
+## Пример работы
+
+Пример запроса к Chromium-сервису:
+
+```bash
+curl "http://10.100.1.2:3000/domains?domain=pornhub.com"
+```
+
+Ответ:
+
+```json
+{
+ "domains": [
+ "a.adtng.com",
+ "cdn1-smallimg.phncdn.com",
+ "ei.phncdn.com",
+ "ht-cdn2.adtng.com",
+ "media.trafficjunky.net",
+ "pix-cdn77.phncdn.com",
+ "pornhub.com",
+ "www.pornhub.com"
+ ]
+}
+```
+
+В итоговые конфиги будут добавлены все эти домены.
+
+Если сайт недоступен (например, сервисный домен):
+
+```bash
+curl "http://10.100.1.2:3000/domains?domain=bt1.t-ru.org"
+```
+
+Ответ:
+
+```json
+{
+ "error": "page.goto: net::ERR_NAME_NOT_RESOLVED at https://bt1.t-ru.org/"
+}
+```
+
+Такой домен будет классифицирован как `service` и попадёт в конфиг без связанных.
+
+---
+
+## Установка и запуск
+
+### Требования
+
+* Linux-система или self-hosted runner Forgejo
+* [dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html) через [Pi-hole](https://pi-hole.net/)
+* [jq](https://stedolan.github.io/jq/) для парсинга JSON
+* make
+* docker (для управления Pi-hole контейнером)
+* доступ к сервису Chromium (по умолчанию: `http://10.100.1.2:3000/domains`)
+
+### Ручной запуск
+
+```bash
+make clean # очистка временных файлов
+make check # только отчёт по доменам
+make test # генерация + превью файлов
+make deploy # генерация + деплой на шлюз
+```
+
+### Автоматический запуск (Forgejo CI/CD)
+
+Workflow (`.forgejo/workflows/deploy.yml`) автоматически срабатывает при изменении `domains.txt`.
+CI делает:
+
+1. Валидацию синтаксиса `domains.txt`
+2. `make clean`
+3. `make check`
+4. `make all` (генерация + деплой)
+5. Сохранение артефактов (`91-ipset-bbrkn.conf` и `92-resolve-bbrkn.conf`)
+
+---
+
+## Пример отладочного отчёта
+
+```
+===== DEBUG REPORT =====
+Original domains file: 50 entries
+Final unique domains: 135
+ - Base domains: 50
+ - Related domains: 85
+
+auth.openai.com - site
+cdn.oaistatic.com - site
+oaistatic.com - site
+ab.chatgpt.com - site
+realtime.chatgpt.com - site
+ws.chatgpt.com - site
+chatgpt.com - site
+byspotify.com - site
+pscdn.co - service
+...
+========================
+```
+
+---
+
+## Траблшутинг
+
+### 1. Chromium-сервис недоступен
+
+* Проверь, что сервис слушает на `${API_URL}`.
+* Убедись, что firewall не блокирует доступ с runner-а.
+* Можно протестировать напрямую:
+
+ ```bash
+ curl "${API_URL}example.com"
+ ```
+
+ Если ответа нет или ошибка — перезапусти сервис.
+
+### 2. В отчёте все домены помечены как `service`
+
+Это значит, что сервис не смог открыть страницы. Возможные причины:
+
+* Сайты блокируются провайдером → нужен обход (VPN/проксирование).
+* Chromium-сервис работает без доступа к интернету.
+
+### 3. Конфиги пустые или слишком маленькие
+
+* Проверь содержимое `domains.txt` (убери комментарии, пустые строки).
+* Убедись, что `jq` установлен (иначе парсинг JSON не сработает).
+* В debug-отчёте будет видно, какие домены обработаны.
+
+### 4. Pi-hole не поднимается после деплоя
+
+* Запусти `docker logs ${DOCKER_CONTAINER}`, проверь ошибки.
+* Откати конфиги из бэкапа (они создаются с суффиксом `.backup.YYYYMMDD-HHMMSS`).
+* Убедись, что новые конфиги не содержат невалидных строк.
+
+### 5. Forgejo CI падает
+
+* Проверь, что runner имеет доступ к `/tmp` (для генерации файлов).
+* Проверь, что установлены зависимости: `make`, `jq`, `docker`.
+* Логи CI подскажут, на каком шаге сломалось (`check`, `generate`, `deploy`).
+
+---
+
+## Зачем это нужно?
+
+* Автоматически отслеживать **скрытые зависимости сайтов** (CDN, API-сервера и т.п.).
+* Поддерживать актуальные списки для маршрутизации/блокировки/разделения трафика.
+* Исключить ручную рутину: всё обновление конфигов делается одной командой или автоматически через CI/CD.
\ No newline at end of file
diff --git a/scripts/deploy-to-gateway.sh b/scripts/deploy-to-gateway.sh
index c5e67db..293d9a6 100644
--- a/scripts/deploy-to-gateway.sh
+++ b/scripts/deploy-to-gateway.sh
@@ -1,40 +1,39 @@
#!/bin/bash
-set -e
+set -euo pipefail
-# Пути к конфигурационным файлам
-TARGET_DIR="/opt/appdata/pihole/etc/dnsmasq.d"
-IPSET_CONF="91-ipset-bbrkn.conf"
-RESOLVE_CONF="92-resolve-bbrkn.conf"
+# ==============================
+# Конфигурация через переменные
+# ==============================
+TARGET_DIR="${TARGET_DIR:-/opt/appdata/pihole/etc/dnsmasq.d}"
+IPSET_CONF="${IPSET_CONF:-91-ipset-bbrkn.conf}"
+RESOLVE_CONF="${RESOLVE_CONF:-92-resolve-bbrkn.conf}"
+
+DOCKER_CONTAINER="${DOCKER_CONTAINER:-pihole}"
echo "Deploying configuration files to $TARGET_DIR"
-# Создаем резервные копии существующих файлов
+# Бэкап существующих файлов
if [ -f "$TARGET_DIR/$IPSET_CONF" ]; then
cp "$TARGET_DIR/$IPSET_CONF" "$TARGET_DIR/$IPSET_CONF.backup.$(date +%Y%m%d-%H%M%S)"
fi
-
if [ -f "$TARGET_DIR/$RESOLVE_CONF" ]; then
cp "$TARGET_DIR/$RESOLVE_CONF" "$TARGET_DIR/$RESOLVE_CONF.backup.$(date +%Y%m%d-%H%M%S)"
fi
-# Копируем новые файлы
+# Копирование новых файлов
cp "/tmp/$IPSET_CONF" "$TARGET_DIR/$IPSET_CONF"
cp "/tmp/$RESOLVE_CONF" "$TARGET_DIR/$RESOLVE_CONF"
+# Перезапуск контейнера
+echo "Restarting $DOCKER_CONTAINER container..."
+docker restart "$DOCKER_CONTAINER"
-# Перезапускаем dnsmasq через Pi-hole контейнер
-echo "Restarting Pi-hole container..."
-docker restart pihole
-
-# Проверяем успешность перезапуска
sleep 5
-if ! docker ps | grep -q pihole; then
- echo "Error: Pi-hole container failed to start"
+if ! docker ps | grep -q "$DOCKER_CONTAINER"; then
+ echo "Error: $DOCKER_CONTAINER container failed to start"
exit 1
fi
echo "Deployment completed successfully"
-
-# Уведомляем о количестве обработанных доменов
DOMAIN_COUNT=$(grep -c '^ipset=' "$TARGET_DIR/$IPSET_CONF" || echo "0")
echo "Applied configuration for $DOMAIN_COUNT domains"
diff --git a/scripts/generate-configs.sh b/scripts/generate-configs.sh
index 56c1a4f..41e7d9c 100644
--- a/scripts/generate-configs.sh
+++ b/scripts/generate-configs.sh
@@ -1,24 +1,31 @@
#!/bin/bash
set -euo pipefail
-INPUT_FILE="domains.txt"
-IPSET_CONF="/tmp/91-ipset-bbrkn.conf"
-RESOLVE_CONF="/tmp/92-resolve-bbrkn.conf"
-API_URL="http://10.100.1.2:3000/domains?domain="
+# ==============================
+# Конфигурация через переменные
+# ==============================
+INPUT_FILE="${INPUT_FILE:-domains.txt}"
+
+IPSET_CONF="${IPSET_CONF:-/tmp/91-ipset-bbrkn.conf}"
+RESOLVE_CONF="${RESOLVE_CONF:-/tmp/92-resolve-bbrkn.conf}"
+
+API_URL="${API_URL:-http://10.100.1.2:3000/domains?domain=}"
+DNS_SERVER="${DNS_SERVER:-8.8.8.8}"
DRY_RUN=false
if [[ "${1:-}" == "--dry-run" ]]; then
DRY_RUN=true
fi
+# Очистка файлов только если не dry-run
if ! $DRY_RUN; then
: > "$IPSET_CONF"
: > "$RESOLVE_CONF"
fi
-declare -A DOM_ROLE # роли для исходных доменов: site/service
-declare -A EXPANDED # все уникальные домены (ключи = домены)
-declare -A SOURCES # источник: base или related
+declare -A DOM_ROLE
+declare -A EXPANDED
+declare -A SOURCES
normalize_domain() {
local raw="$1"
@@ -34,7 +41,7 @@ normalize_domain() {
fi
}
-# Обработка доменов из входного списка
+# Обработка доменов
while IFS= read -r line || [ -n "$line" ]; do
dom="$(normalize_domain "$line" || true)"
[ -z "$dom" ] && continue
@@ -60,25 +67,23 @@ while IFS= read -r line || [ -n "$line" ]; do
fi
done < "$INPUT_FILE"
-# Сортировка доменов
+# Сортировка
mapfile -t ALL_DOMAINS < <(printf "%s\n" "${!EXPANDED[@]}" | sort -u)
# Генерация конфигов
if ! $DRY_RUN; then
for d in "${ALL_DOMAINS[@]}"; do
echo "ipset=/$d/bbrkn" >> "$IPSET_CONF"
- echo "server=/$d/8.8.8.8" >> "$RESOLVE_CONF"
+ echo "server=/$d/$DNS_SERVER" >> "$RESOLVE_CONF"
done
fi
# Подсчёты
count_in=$(wc -l < "$INPUT_FILE")
count_total=${#ALL_DOMAINS[@]}
-count_base=$(printf "%s\n" "${!SOURCES[@]}" | grep -c '.*' || true)
-count_related=$(printf "%s\n" "${!SOURCES[@]}" | grep -c '.*' || true)
count_related=$(( count_total - count_in ))
-# Отладочный вывод
+# Отладочный отчёт
echo
echo "===== DEBUG REPORT ====="
echo "Original domains file: $count_in entries"