feat: add deployment hardening from production experience
Some checks failed
Build and Push Docker Images / Сборка сервера (multi-arch) (push) Has been cancelled
Build and Push Docker Images / Сборка клиента (multi-arch) (push) Has been cancelled

- Add IP forwarding setup (sysctl) to install.sh — container can't
  write /proc/sys, must be done on host
- Add host-level WireGuard detection and auto-stop in install.sh
- Update key exchange instructions: 2-step process (server first,
  then client, then restart server with client key)
- Add deployment nuances section to README (ip_forward, wg0 cleanup,
  compose version warning, key exchange, network_mode, iptables order)
- Add production deployment notes to .env.example
- Remove obsolete compose version warnings noted during deployment
This commit is contained in:
Deploy Bot
2026-07-30 01:05:13 +01:00
parent dcebf21e03
commit 1c4a40f0c1
3 changed files with 145 additions and 6 deletions

View File

@@ -44,3 +44,17 @@ CLIENT_WG_IP=10.0.0.2
# Интервал Keepalive в секундах (оптимизировано для Starlink, по умолчанию 21)
PERSISTENT_KEEPALIVE=21
# ── Важные замечания по развёртыванию ──────────────────────────────────────
# 1. На VPS: включите IP-форвардинг на хосте (контейнер не может /proc/sys):
# echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf && sysctl -p
# 2. Ключи генерируются автоматически при первом запуске.
# Сервер: /etc/wireguard/server_private.key, server_public.key
# Клиент: /etc/wireguard/client_private.key, client_public.key
# 3. После первого запуска сервера скопируйте SERVER_PUBLIC_KEY в .env клиента.
# 4. После первого запуска клиента скопируйте CLIENT_PUBLIC_KEY в .env сервера.
# 5. Перезапустите контейнеры после обновления ключей:
# docker compose -f docker-compose.server.yml restart (на VPS)
# docker compose -f docker-compose.client.yml restart (на RPi)
# 6. Контейнер использует network_mode: host — порты пробрасываются
# через iptables DNAT, а не через Docker port mapping.

View File

@@ -414,6 +414,76 @@ wireguard-vps-tunnel/
└── README.md # Документация
```
## Нюансы развёртывания (выявлены на практике)
### 1. IP-форвардинг на хосте (обязательно)
Контейнер не может записать в `/proc/sys/net/ipv4/ip_forward` (read-only в Docker). Включите на хосте:
```bash
# Временно
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
# Постоянно
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' >> /etc/sysctl.conf
sysctl -p
```
Без этого DNAT-трафик не будет перенаправляться.
### 2. Обмен ключами: двухэтапный запуск
Ключи генерируются **внутри контейнера** при первом запуске. Поэтому:
1. Запустите сервер → он сгенерирует ключи и выведет `SERVER_PUBLIC_KEY=...`
2. Впишите `SERVER_PUBLIC_KEY` в `.env` на клиенте
3. Запустите клиент → он выведет `CLIENT_PUBLIC_KEY=...`
4. Впишите `CLIENT_PUBLIC_KEY` в `.env` на сервере
5. Перезапустите сервер: `docker compose -f docker-compose.server.yml restart`
Конфигурация `wg0.conf` пересоздаётся при каждом перезапуске, поэтому обновление ключей не требует ручного редактирования.
### 3. Удаление старого интерфейса wg0
При перезапуске контейнера интерфейс `wg0` может остаться от предыдущего запуска. Entrypoint автоматически удаляет его перед запуском `wg-quick up`. Если на хосте остался host-level WireGuard — остановите его:
```bash
systemctl stop wg-quick@wg0
systemctl disable wg-quick@wg0
ip link del wg0 2>/dev/null
rm -f /etc/wireguard/wg0.conf
```
### 4. Docker Compose `version` устарел
Поле `version: "3.8"` в docker-compose вызывает предупреждение:
`the attribute 'version' is obsolete`. Оно удалено из файлов проекта.
Если вы видите это предупреждение — просто удалите строку `version:` из compose-файла.
### 5. Multi-arch сборка требует Buildx
Стандартный `docker build` не поддерживает `platforms: linux/amd64,linux/arm64`.
Для multi-arch сборки через CI/CD используется Docker Buildx с QEMU.
Для локальной сборки на текущей архитектуре достаточно убрать `platforms:` из compose-файла.
### 6. network_mode: host и порты
Контейнеры используют `network_mode: host`. Секция `ports:` в compose-файле игнорируется (Docker выведет предупреждение). Все порты доступны напрямую через iptables DNAT.
### 7. Конфликт с Docker iptables
Правила DNAT вставляются через `iptables -I FORWARD 1`**перед** цепочкой DOCKER-USER.
Это гарантирует, что WireGuard-трафик не блокируется Docker. Не меняйте приоритет
без необходимости.
### 8. Парольная аутентификация SSH
Скрипт **НЕ отключает** `PasswordAuthentication` в sshd. Если вы хотите отключить,
сделайте это вручную и обязательно добавьте SSH-ключ в `authorized_keys` **до**
отключения пароля, иначе потеряете доступ.
## Поддерживаемые ОС
- Любой Linux с Docker 20.10+

View File

@@ -91,6 +91,50 @@ install_docker() {
fi
}
# ── Включение IP-форвардинга (обязательно для VPS) ──────────────────────────
enable_ip_forwarding() {
header "Настройка IP-форвардинга"
# Включить временно
echo 1 > /proc/sys/net/ipv4/ip_forward 2>/dev/null || true
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding 2>/dev/null || true
# Включить постоянно
if ! grep -q "net.ipv4.ip_forward" /etc/sysctl.conf 2>/dev/null; then
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
else
sed -i 's/.*net.ipv4.ip_forward.*/net.ipv4.ip_forward = 1/' /etc/sysctl.conf
fi
if ! grep -q "net.ipv6.conf.all.forwarding" /etc/sysctl.conf 2>/dev/null; then
echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf
else
sed -i 's/.*net.ipv6.conf.all.forwarding.*/net.ipv6.conf.all.forwarding = 1/' /etc/sysctl.conf
fi
sysctl -p 2>/dev/null || true
success "IP-форвардинг включён"
}
# ── Остановка host-level WireGuard ────────────────────────────────────────
stop_host_wireguard() {
if systemctl is-active --quiet wg-quick@wg0 2>/dev/null; then
warn "Обнаружен host-level WireGuard (wg-quick@wg0). Останавливаем..."
systemctl stop wg-quick@wg0 2>/dev/null || true
systemctl disable wg-quick@wg0 2>/dev/null || true
ip link del wg0 2>/dev/null || true
success "Host-level WireGuard остановлен и отключён"
fi
# Остановить watchdog если есть
if systemctl is-active --quiet wg-watchdog 2>/dev/null; then
systemctl stop wg-watchdog 2>/dev/null || true
systemctl disable wg-watchdog 2>/dev/null || true
success "wg-watchdog остановлен"
fi
}
# ── Генерация ключей WireGuard ─────────────────────────────────────────────
generate_keys() {
header "Генерация ключей WireGuard"
@@ -335,6 +379,8 @@ print_summary() {
if [[ "$MODE" == "vps" ]]; then
echo -e "${BOLD}Проброс портов:${NC} ${PORTS}${CLIENT_WG_IP}"
echo ""
echo -e "${GREEN}${BOLD}✅ IP-форвардинг включён (net.ipv4.ip_forward=1)${NC}"
fi
echo ""
@@ -355,11 +401,14 @@ print_summary() {
if [[ "$MODE" == "vps" ]]; then
echo ""
echo -e "${YELLOW}${BOLD}⚠️ ВАЖНО:${NC} ${YELLOW}Скопируйте публичный ключ сервера на клиент:${NC}"
echo -e " ${BOLD}cat ${CONFIG_DIR}/server_public.key${NC}"
echo ""
echo -e "${YELLOW}Затем на клиенте (RPi):${NC}"
echo -e " ${BOLD}sudo ./install.sh --client --vps-ip ${VPS_PUBLIC_IP}${NC}"
echo -e "${YELLOW}${BOLD}⚠️ ВАЖНО:${NC} ${YELLOW}Двухэтапный обмен ключами:${NC}"
echo -e " 1. Запишите публичный ключ сервера:"
echo -e " ${BOLD}cat ${CONFIG_DIR}/server_public.key${NC}"
echo -e " 2. Передайте его на клиент (в .env как SERVER_PUBLIC_KEY)"
echo -e " 3. После запуска клиента, получите CLIENT_PUBLIC_KEY:"
echo -e " ${BOLD}cat ${CONFIG_DIR}/client_public.key${NC} (на клиенте)"
echo -e " 4. Впишите CLIENT_PUBLIC_KEY в .env на VPS и перезапустите:"
echo -e " ${BOLD}docker compose -f docker-compose.server.yml restart${NC}"
else
echo ""
echo -e "${YELLOW}${BOLD}⚠️ ВАЖНО:${NC} ${YELLOW}Скопируйте публичный ключ клиента на VPS:${NC}"
@@ -367,6 +416,8 @@ print_summary() {
echo ""
echo -e "${YELLOW}И добавьте в .env на VPS:${NC}"
echo -e " ${BOLD}CLIENT_PUBLIC_KEY=<ключ>${NC}"
echo -e "${YELLOW}Затем перезапустите сервер:${NC}"
echo -e " ${BOLD}docker compose -f docker-compose.server.yml restart${NC}"
fi
echo ""
@@ -403,8 +454,12 @@ main() {
fi
install_docker
stop_host_wireguard
generate_keys
create_env_file
if [[ "$MODE" == "vps" ]]; then
enable_ip_forwarding
fi
start_docker
print_summary
}