# Installation Этот документ описывает production-порядок установки AWG2 Harness. Подробный runtime-план с SSH hardening и Amnezia preflight находится в корневом [`README.md`](../README.md). ## Deployment contract - Целевой production-хост: Debian 13 amd64. - Amnezia ставится до AWG2 Harness официальным self-hosted способом через приложение AmneziaVPN. - Проект рассчитан на AmneziaWG/AWG 2.0 и compatible legacy-сценарий AmneziaWG/AWG 1.5. - SSH должен быть заранее настроен. Production-пример: порт `2323`, вход по ключу, password login disabled. - Production-хост получает готовый Debian-пакет; Rust/cargo/source tree на нём не требуются. - `/etc/awg2-harness/config.toml` создаётся вручную. `config.example.toml` не копируется автоматически как боевой config. - Пакет не устанавливает Docker/Amnezia и не включает services автоматически. ## A. Build machine ### A1. Подготовить build environment ```bash cd awg2_harness chmod +x tools/build.sh ./tools/build.sh --prepare-build-env --bootstrap-rust --yes ``` ### A2. Проверить код ```bash cargo fmt --manifest-path Cargo.toml --all --check cargo clippy --locked --workspace --all-targets --manifest-path Cargo.toml -- -D warnings cargo test --locked --workspace --release --manifest-path Cargo.toml ``` То же самое выполняет build helper: ```bash ./tools/build.sh --build ``` ### A3. Собрать Debian-пакет ```bash ./tools/build.sh --package --version 0.1.6 (cd dist && sha256sum -c SHA256SUMS) dpkg-deb -I dist/awg2-harness_0.1.6_amd64.deb dpkg-deb -c dist/awg2-harness_0.1.6_amd64.deb | sort ``` `--version` можно опустить, если версия в `traffic_core/Cargo.toml` уже равна release version. Version override влияет только на metadata `.deb`. ## B. Подготовить production-хост ### B1. SSH Сначала сгенерируйте отдельную пару ключей для Amnezia на Windows (RSA PEM): ```cmd ssh-keygen -t rsa -b 4096 -m PEM -f %USERPROFILE%\.ssh\amnezia_key ``` Дальше разделяйте ключи строго: - на сервер в `/root/.ssh/authorized_keys` кладётся содержимое `%USERPROFILE%\.ssh\amnezia_key.pub`; - в AmneziaVPN в поле `Password or SSH private key` вставляется содержимое `%USERPROFILE%\.ssh\amnezia_key` (без `.pub`). `.pub` нельзя вставлять в поле private key в AmneziaVPN. Установка `.pub` на сервер: ```bash install -d -m 0700 /root/.ssh nano /root/.ssh/authorized_keys chmod 0600 /root/.ssh/authorized_keys ``` Production-пример: ```bash install -d -m 0755 /etc/ssh/sshd_config.d cat >/etc/ssh/sshd_config.d/99-awg2-production.conf <<'EOF' Port 2323 PermitRootLogin prohibit-password PasswordAuthentication no KbdInteractiveAuthentication no PubkeyAuthentication yes EOF sshd -t systemctl reload ssh 2>/dev/null || systemctl reload sshd ss -ltnp | grep ':2323' ``` Обязательно проверьте вход с нового терминала: ```cmd ssh -i %USERPROFILE%\.ssh\amnezia_key -p 2323 root@ ``` Проверить содержимое ключей в Windows: ```cmd type %USERPROFILE%\.ssh\amnezia_key.pub type %USERPROFILE%\.ssh\amnezia_key ``` ### B2. Amnezia Установите AmneziaWG/AWG через официальное приложение AmneziaVPN в режиме self-hosted server. Заполнение полей в интерфейсе AmneziaVPN: ```text Configure your server: Server IP address [:port]: :2323 SSH Username: root Password or SSH private key: полное содержимое приватного ключа %USERPROFILE%\.ssh\amnezia_key ``` Важно: в это поле не вставляется `.pub`. Файл `.pub` нужен только для `/root/.ssh/authorized_keys` на сервере. Проверка после установки: ```bash docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' C="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg)$' | head -n1)" echo "container=$C" docker port "$C" docker exec "$C" wg show ``` Если контейнер называется иначе или интерфейс не `awg0`, отразите это в `/etc/awg2-harness/config.toml`. ### B3. Установить AmneziaDNS Установите AmneziaDNS из desktop-приложения AmneziaVPN: ```text Servers → → Services → AmneziaDNS → Install ``` Затем включите его для подключения: ```text Settings → Connection → DNS servers → Use AmneziaDNS ``` Ожидаемое состояние Docker: ```bash docker ps -a --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}' ``` Ожидаемая строка для DNS-контейнера: ```text amnezia-dns amnezia-dns Up ... (healthy) 53/tcp, 53/udp ``` Проверка публикации портов: ```bash docker inspect -f 'ports={{json .NetworkSettings.Ports}}' amnezia-dns docker inspect -f 'networks={{range $n,$v := .NetworkSettings.Networks}}{{printf "%s=%s " $n $v.IPAddress}}{{end}}' amnezia-dns docker inspect -f 'networks={{range $n,$v := .NetworkSettings.Networks}}{{printf "%s=%s " $n $v.IPAddress}}{{end}}' amnezia-awg2 ``` Ожидаемый результат по портам: ```text ports={"53/tcp":null,"53/udp":null} ``` Это означает, что DNS не опубликован на публичном host-интерфейсе и остаётся доступным только через VPN/Docker path. Negative-check публичного DNS: ```bash nslookup example.com ``` Ожидаемое поведение: публичный DNS-запрос **не должен успешно резолвиться**. Типичные безопасные варианты ответа: `connection refused`, `timeout` или `no servers could be reached`. Optional deep-check DNS path (если нужна углублённая проверка): ```bash apt install -y dnsutils DNS_PID="$(docker inspect -f '{{.State.Pid}}' amnezia-dns)" AWG_PID="$(docker inspect -f '{{.State.Pid}}' amnezia-awg2)" nsenter -t "$DNS_PID" -n ss -lntup nsenter -t "$AWG_PID" -n ip route nsenter -t "$AWG_PID" -n dig @172.29.172.254 example.com A +short ``` ## C. Transfer artifacts Ниже два production-сценария установки. ### C1. Вариант A: config передаётся вместе с `.deb` ```bash scp -P 2323 dist/awg2-harness_*_amd64.deb root@:/root/ scp -P 2323 dist/SHA256SUMS root@:/root/ scp -P 2323 config.example.toml root@:/root/awg2-harness.config.toml ``` Перед установкой отредактируйте `/root/awg2-harness.config.toml`. Минимально проверьте: - `[host_firewall].ssh_port` совпадает с реальным SSH-портом (`2323` в production-примере); - `[host_firewall].amnezia_port` совпадает с published UDP port Amnezia; - `[amnezia].peer_ipv4_cidr` совпадает с подсетью clients; - `[anti_torrent].peer_ipv4_cidr` обычно равен `[amnezia].peer_ipv4_cidr`; - `peer_limit` и `root_rate` отражают нужную traffic policy. ### C2. Вариант B (основной): config создаётся на production после установки ```bash scp -P 2323 dist/awg2-harness_*_amd64.deb root@:/root/ scp -P 2323 dist/SHA256SUMS root@:/root/ ``` ## D. Production install ### D1. Вариант A ```bash cd /root sha256sum -c SHA256SUMS apt install ./awg2-harness_*_amd64.deb install -d -m 0755 /etc/awg2-harness install -m 0644 /root/awg2-harness.config.toml /etc/awg2-harness/config.toml systemctl daemon-reload ``` ### D2. Вариант B (основной) ```bash cd /root sha256sum -c SHA256SUMS apt install ./awg2-harness_*_amd64.deb install -d -m 0755 /etc/awg2-harness cp /usr/share/doc/awg2-harness/repo/config.example.toml /etc/awg2-harness/config.toml nano /etc/awg2-harness/config.toml systemctl daemon-reload ``` Перед первым `apply-firewall` обязательно перепроверьте: - `[host_firewall].ssh_port` совпадает с реально слушающим `sshd` портом; - `[host_firewall].amnezia_port` совпадает с published Docker UDP port; - `[amnezia].peer_ipv4_cidr` совпадает с peer-подсетью; - `[anti_torrent].peer_ipv4_cidr` обычно тот же CIDR. ## E. Preflight before enable ```bash awg2-harness --config /etc/awg2-harness/config.toml validate-config awg2-harness --config /etc/awg2-harness/config.toml validate-runtime awg2-harness --config /etc/awg2-harness/config.toml ensure-swap awg2-harness --config /etc/awg2-harness/config.toml apply-firewall awg2-harness --config /etc/awg2-harness/config.toml apply-limits awg2-harness --config /etc/awg2-harness/config.toml status ``` Expected healthy result: ```text Traffic actual: drift: no Host firewall: drift: no Anti-torrent: drift: no Swap: drift: no ``` If there are no peers yet, `apply-limits` may print `no peers found, skip tc apply`. That is healthy for an empty server. When `swap.enabled=true`, AWG2 Harness intentionally makes swap exclusive: one managed swapfile, one fstab swap entry, configured swappiness. ## F. Enable services ```bash systemctl enable --now awg2-harness.service systemctl enable --now awg2-reboot-scheduler.service systemctl status awg2-harness.service --no-pager -l systemctl status awg2-reboot-scheduler.service --no-pager -l journalctl -u awg2-harness.service --since '5 minutes ago' --no-pager journalctl -u awg2-reboot-scheduler.service --since '5 minutes ago' --no-pager ``` After 30–60 seconds: ```bash awg2-harness --config /etc/awg2-harness/config.toml status ``` ## G. Reboot validation ```bash reboot ``` After reconnect: ```bash systemctl status docker --no-pager -l systemctl status awg2-harness.service --no-pager -l systemctl status awg2-reboot-scheduler.service --no-pager -l awg2-harness --config /etc/awg2-harness/config.toml status ``` ## H. Manual source-tree install `./tools/build.sh --install` and `./tools/build.sh --enable` exist for staging/debug. They are not the recommended production path. Use `.deb` on production.