docs: unify language contract to Russian and reconcile the spec with the code

The docs folder had drifted into a mixed-language contract: IMPLEMENTATION_SPEC.md was
entirely in English while the rest was Russian with English headings. Prose is now
Russian throughout; English is kept only where it is technically load-bearing (commands,
tool output, config keys, file/module/table names, tc handles) and for terms with no
settled Russian equivalent in this context (drift, reconcile, peer, namespace, handshake).
docs/README.md now states that contract explicitly.

Rewriting the spec surfaced several places where it described intent rather than the
code. Corrected against traffic_core/src:

- module layout: the spec showed traffic/ and firewall/ as directories with
  model/inspect/apply submodules. They are single files, and sysctl_tuning.rs was
  missing from the tree entirely.
- data model: Peer was documented as carrying public key, handshake and counters. It
  carries only ipv4; runtime state lives in a separate PeerRuntime, and there is no
  desired-state struct at all - it is derived inline from config plus sorted peers.
  RuntimeTarget.netns_path is a String, not a PathBuf.
- interface detection: the spec listed a third step taking the first non-loopback
  interface with an IPv4 address. No such fallback exists; detection bails with an
  explicit error, which is safer and is now documented as deliberate.
- reconcile: the pseudo-flow folded firewall into reconcile_traffic. They are two
  independent reconciles with separate locks.
- locking: only traffic.lock was documented. There are three locks, and
  sysctl_tuning.lock has a 30s timeout rather than 10s. Stale-lock recovery via
  /proc/<pid> was undocumented.
- sysctl_tuning: the module also manages /etc/modules-load.d/90-awg2-harness-bbr.conf
  when BBR is active, and refuses to touch either managed file without its marker.
  Both docs and the acceptance checklist claimed only the sysctl.d file was written.
- status contract: the documented output was outdated. All 15 printed sections are now
  listed in the order status.rs emits them, including the degraded path when no container
  is found, and the fact that the Network tuning block is printed between the System
  service line and the container lines.
- swap: size was documented as a constant 2048 MB instead of swap.size_mb, and the
  /etc/fstab.awg2-harness.bak backup was undocumented.
- apply/verify: the tolerated-error lists are now the actual closed sets from the code.

Acceptance checklist gained checks for the daemon startup failure policy (sysctl/swap
fatal, traffic/firewall not), lock contention and stale-lock recovery, degraded status,
the modules-load file, and the marker guard. The stale host wg requirement was dropped
from its host-tools item.

Every path, table, counter and log string quoted in the docs was verified to exist in
the source. cargo test --workspace: 110 + 4 passed.
This commit is contained in:
2026-08-06 16:45:00 +05:00
parent 16214f3c66
commit d98ade42ce
7 changed files with 419 additions and 366 deletions
+18 -18
View File
@@ -1,8 +1,8 @@
# 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.
@@ -13,9 +13,9 @@
- Пакет не устанавливает Docker/Amnezia и не включает services автоматически.
- `sysctl_tuning` не применяется в `postinst`; применение только на старте daemon или вручную через CLI.
## A. Build machine
## A. Сборочная машина
### A1. Подготовить build environment
### A1. Подготовить сборочное окружение
```bash
cd awg2_harness
@@ -207,11 +207,11 @@ nsenter -t "$AWG_PID" -n ip route
nsenter -t "$AWG_PID" -n dig @"$DNS_IP" example.com A +short
```
## C. Transfer artifacts
## C. Передача артефактов
Ниже два production-сценария установки.
### C1. Вариант A: config передаётся вместе с `.deb`
### C1. Вариант A: конфиг передаётся вместе с `.deb`
```bash
scp -P 2323 dist/awg2-harness_*_amd64.deb root@<server-ip>:/root/
@@ -227,14 +227,14 @@ scp -P 2323 config.example.toml root@<server-ip>:/root/awg2-harness.config.toml
- `[anti_torrent].peer_ipv4_cidr` обычно равен `[amnezia].peer_ipv4_cidr`;
- `peer_limit` и `root_rate` отражают нужную traffic policy.
### C2. Вариант B (основной): config создаётся на production после установки
### C2. Вариант B (основной): конфиг создаётся на production после установки
```bash
scp -P 2323 dist/awg2-harness_*_amd64.deb root@<server-ip>:/root/
scp -P 2323 dist/SHA256SUMS root@<server-ip>:/root/
```
## D. Production install
## D. Установка на production
### D1. Вариант A
@@ -266,7 +266,7 @@ systemctl daemon-reload
- `[amnezia].peer_ipv4_cidr` совпадает с peer-подсетью;
- `[anti_torrent].peer_ipv4_cidr` обычно тот же CIDR.
## E. Preflight before enable
## E. Preflight до включения сервисов
```bash
awg2-harness --config /etc/awg2-harness/config.toml validate-config
@@ -277,7 +277,7 @@ 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:
@@ -290,11 +290,11 @@ 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.
Если peers ещё нет, `apply-limits` напечатает `no peers found, skip tc apply`. Для пустого сервера это здоровое состояние.
When `swap.enabled=true`, AWG2 Harness intentionally makes swap exclusive: one managed swapfile, one fstab swap entry, configured swappiness.
При `swap.enabled = true` AWG2 Harness намеренно делает swap эксклюзивным: один управляемый swapfile, одна swap-запись в `/etc/fstab`, заданный `swappiness`.
## F. Enable services
## F. Включение сервисов
```bash
systemctl enable --now awg2-harness.service
@@ -306,19 +306,19 @@ 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:
Через 30–60 секунд:
```bash
awg2-harness --config /etc/awg2-harness/config.toml status
```
## G. Reboot validation
## G. Проверка перезагрузкой
```bash
reboot
```
After reconnect:
После восстановления подключения:
```bash
systemctl status docker --no-pager -l
@@ -327,6 +327,6 @@ systemctl status awg2-reboot-scheduler.service --no-pager -l
awg2-harness --config /etc/awg2-harness/config.toml status
```
## H. Manual source-tree install
## H. Ручная установка из дерева исходников
`./tools/build.sh --install` and `./tools/build.sh --enable` exist for staging/debug. They are not the recommended production path. Use `.deb` on production.
`./tools/build.sh --install` и `./tools/build.sh --enable` существуют для staging и отладки. Это не рекомендуемый production-путь: на production используйте `.deb`.