From 71e98912470b0b8d39858825e053919a2edbd705 Mon Sep 17 00:00:00 2001 From: embeddevio Date: Wed, 21 Oct 2026 23:31:04 +0300 Subject: [PATCH] =?UTF-8?q?feat(#18):=20=D1=81=D1=83=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B2=D0=B8=D0=B7=D0=BE=D1=80=20entrypoint.sh=20=D0=B8=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80=20.conf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/awg0.conf.example | 32 +++++++++++++++++ deploy/entrypoint.sh | 75 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 deploy/awg0.conf.example create mode 100644 deploy/entrypoint.sh diff --git a/deploy/awg0.conf.example b/deploy/awg0.conf.example new file mode 100644 index 0000000..5538ee0 --- /dev/null +++ b/deploy/awg0.conf.example @@ -0,0 +1,32 @@ +# Пример клиентского конфига AmneziaWG для awg-dash. +# +# Скопируйте в том /config как awg0.conf (имя файла = имя интерфейса) или +# загрузите через Web UI (задача #38). Значения ниже — заглушки, замените своими. +# Файл в репозитории не является рабочим конфигом и не содержит реальных ключей. + +[Interface] +# Адрес внутри туннеля (из панели провайдера AmneziaWG) +Address = 10.8.1.2/32 + +# DNS: адрес должен указывать на этот шлюз, иначе не сработает DNS-split (ADR-005) +DNS = 10.8.1.1 + +PrivateKey = + +# Обфускация AmneziaWG (Amnezia VPN: экспорт -> AmneziaWG) +Jc = 4 +Jmin = 40 +Jmax = 70 +S1 = 0 +S2 = 0 +H1 = 1 +H2 = 2 +H3 = 3 +H4 = 4 + +[Peer] +PublicKey = +PresharedKey = +AllowedIPs = 0.0.0.0/0, ::/0 +Endpoint = : +PersistentKeepalive = 25 diff --git a/deploy/entrypoint.sh b/deploy/entrypoint.sh new file mode 100644 index 0000000..5fd7dbb --- /dev/null +++ b/deploy/entrypoint.sh @@ -0,0 +1,75 @@ +#!/bin/sh +# Супервизор контейнера awg-dash (задача #18, ADR-002). +# Последовательность: preflight -> подготовка -> запуск awg-api под awg. +# Привилегированный агент awg-agent стартует отсюда же после реализации (#22). +# +# Роль процесса: все сетевые операции выполняет агент под root; здесь только +# проверяем, что нужные возможности и устройства проброшены, и падаем явной +# ошибкой, если контейнер запущен без них (а не тихо деградируем). +set -eu + +CONFIG_DIR="${AWG_CONFIG_DIR:-/config}" +DATA_DIR="${AWG_DATA_DIR:-/data}" +RUN_DIR="${AWG_RUN_DIR:-/run/awg}" +API_HOST="${AWG_API_HOST:-0.0.0.0}" +API_PORT="${AWG_API_PORT:-8080}" +ROUTING_TABLE_ID=100 +ROUTING_TABLE_NAME=awg-vpn + +log() { printf '[entrypoint] %s\n' "$*"; } +fail() { printf '[entrypoint] FATAL: %s\n' "$*" >&2; exit 1; } + +log 'preflight' +[ -e /dev/net/tun ] || fail '/dev/net/tun не проброшен: добавьте --device=/dev/net/tun:/dev/net/tun' +iptables -t mangle -L -n >/dev/null 2>&1 || fail 'iptables недоступен: нужен --cap-add=NET_ADMIN (и/или --privileged)' +command -v awg >/dev/null 2>&1 || fail 'бинарь awg не найден в образе' +command -v amneziawg-go >/dev/null 2>&1 || log 'WARN: amneziawg-go не найден — остаётся только kernel-модуль' +command -v ipset >/dev/null 2>&1 || fail 'ipset не найден в образе' + +log 'подготовка каталогов состояния' +mkdir -p "$CONFIG_DIR" "$DATA_DIR" "$RUN_DIR" +chown -R awg:awg "$CONFIG_DIR" "$DATA_DIR" "$RUN_DIR" 2>/dev/null || true +chmod 700 "$CONFIG_DIR" "$DATA_DIR" 2>/dev/null || true + +if ! grep -q "^${ROUTING_TABLE_ID} ${ROUTING_TABLE_NAME}" /etc/iproute2/rt_tables 2>/dev/null; then + printf '%s %s\n' "$ROUTING_TABLE_ID" "$ROUTING_TABLE_NAME" >> /etc/iproute2/rt_tables \ + || log 'WARN: не удалось записать таблицу маршрутизации в /etc/iproute2/rt_tables' +fi + +sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1 \ + || log 'WARN: не удалось включить net.ipv4.ip_forward (нужен SYS_MODULE или --privileged)' + +log "awg: $(awg --version 2>/dev/null | head -n 1 || echo 'version unknown')" + +api_pid='' +if [ -f /app/backend/awg_api/app.py ]; then + log "запуск awg-api на ${API_HOST}:${API_PORT}" + su-exec awg /opt/venv/bin/uvicorn awg_api.app:app --host "$API_HOST" --port "$API_PORT" & + api_pid=$! +else + log 'WARN: awg_api/app.py ещё не реализован (задача #31) — API не запущен, контейнер работает только как агент' +fi + +stop() { + if [ -n "$api_pid" ] && kill -0 "$api_pid" 2>/dev/null; then + log 'остановка awg-api' + kill -TERM "$api_pid" 2>/dev/null || true + fi +} +trap stop INT TERM + +if [ -n "$api_pid" ]; then + # ждём завершения API и прокидываем его код возврата в Docker + set +e + wait "$api_pid" + rc=$? + set -e + log "awg-api завершился с кодом $rc" + exit "$rc" +fi + +log 'активных процессов нет (agent #22 и api #31 ещё не реализованы) — ожидание сигнала' +while :; do + sleep 3600 & + wait $! +done