#!/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 mkdir -p /etc/iproute2 touch /etc/iproute2/rt_tables 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 не включён — задайте --sysctl net.ipv4.ip_forward=1 или --privileged (см. runbook #45)' 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