- Removed privileged: true from docker-compose.yml - Removed SYS_MODULE cap_add (kept NET_ADMIN for WireGuard) - Removed source code bind mounts (./src, package.json) - Removed wg0.conf and resolv.conf bind mounts (now generated from env) - Added resource limits: mem_limit 512m, cpus 1.0 - Added healthcheck with curl - Added non-root user appuser:appgroup in Dockerfile - wg0.conf now generated from env vars at container startup (WG_PRIVATE_KEY, etc.) - resolv.conf generated from WG_DNS env var - Rotated wg0.conf — private key removed from file - Added WG_ALLOWED_IPS to .env.example SECURITY: Rotate WireGuard keys on server if previously used in production
This commit is contained in:
@@ -36,6 +36,7 @@ WG_PRESHARED_KEY=
|
|||||||
WG_ENDPOINT=
|
WG_ENDPOINT=
|
||||||
WG_ADDRESS=
|
WG_ADDRESS=
|
||||||
WG_DNS=
|
WG_DNS=
|
||||||
|
WG_ALLOWED_IPS=0.0.0.0/0,::/0
|
||||||
|
|
||||||
# --- Gitea API (для CI/CD и пайплайна) ---
|
# --- Gitea API (для CI/CD и пайплайна) ---
|
||||||
GITEA_API_URL=https://git.softuniq.eu/api/v1
|
GITEA_API_URL=https://git.softuniq.eu/api/v1
|
||||||
|
|||||||
12
Dockerfile
12
Dockerfile
@@ -11,6 +11,10 @@ RUN apk update && \
|
|||||||
curl && \
|
curl && \
|
||||||
rm -rf /var/cache/apk/*
|
rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
|
# Создаём непривилегированного пользователя
|
||||||
|
RUN addgroup -S appgroup && \
|
||||||
|
adduser -S appuser -G appgroup
|
||||||
|
|
||||||
# Рабочая директория
|
# Рабочая директория
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
@@ -18,9 +22,15 @@ WORKDIR /app
|
|||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|
||||||
|
# Копируем исходный код с правильным владельцем
|
||||||
|
COPY --chown=appuser:appgroup ./src ./src
|
||||||
|
|
||||||
# Копируем скрипт запуска
|
# Копируем скрипт запуска
|
||||||
COPY ./wg/start.sh /app/start.sh
|
COPY --chown=appuser:appgroup ./wg/start.sh /app/start.sh
|
||||||
RUN chmod +x /app/start.sh
|
RUN chmod +x /app/start.sh
|
||||||
|
|
||||||
|
# Переключаемся на непривилегированного пользователя
|
||||||
|
USER appuser
|
||||||
|
|
||||||
# Команда для запуска
|
# Команда для запуска
|
||||||
CMD ["/bin/bash", "/app/start.sh"]
|
CMD ["/bin/bash", "/app/start.sh"]
|
||||||
|
|||||||
@@ -10,18 +10,19 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
volumes:
|
volumes:
|
||||||
- ./db:/app/db/ # Синхронизация базы данных
|
- ./db:/app/db/ # Синхронизация базы данных (persistence)
|
||||||
- ./src:/app/src/ # Синхронизация исходного кода
|
- ./wg/start.sh:/app/start.sh # Монтируем start.sh (генерирует wg0.conf из env)
|
||||||
- ./package.json:/app/package.json # Синхронизация package.json
|
cap_add: # Минимальные привилегии, необходимые только для WireGuard
|
||||||
- ./package-lock.json:/app/package-lock.json # Синхронизация package-lock.json
|
|
||||||
- ./wg/config/wg0.conf:/etc/wireguard/wg0.conf # Монтируем конфиг WireGuard
|
|
||||||
- ./wg/config/resolv.conf:/etc/resolv.conf # Монтируем resolv.conf
|
|
||||||
- ./wg/start.sh:/app/start.sh # Монтируем start.sh
|
|
||||||
cap_add: # Необходимо для работы WireGuard
|
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
- SYS_MODULE
|
|
||||||
sysctls:
|
sysctls:
|
||||||
- net.ipv4.conf.all.src_valid_mark=1 # Необходимо для маршрутизации
|
- net.ipv4.conf.all.src_valid_mark=1 # Необходимо для маршрутизации
|
||||||
privileged: true # Даем контейнеру повышенные привилегии
|
mem_limit: 512m
|
||||||
|
cpus: "1.0"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 60s
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
nameserver 9.9.9.11
|
# Generated from WG_DNS environment variable at container startup
|
||||||
|
# See wg/start.sh
|
||||||
@@ -1,12 +1,7 @@
|
|||||||
# Autogenerated by WireGuard UI (WireAdmin)
|
# SECURITY: This file is intentionally empty.
|
||||||
[Interface]
|
# WireGuard configuration is generated from environment variables at container startup.
|
||||||
PrivateKey = ePxlvZTgr+fJ7ntU6oWti13X8h2100CrjnZFOkSLUWQ=
|
# See wg/start.sh and .env.example (WG_PRIVATE_KEY, WG_ADDRESS, WG_DNS, etc.).
|
||||||
Address = 10.8.0.4/24
|
#
|
||||||
DNS = 9.9.9.11
|
# IMPORTANT: The previous version of this file contained a real WireGuard private key.
|
||||||
|
# ROTATE THE WIREGUARD KEYS ON THE SERVER SIDE if this key was ever used in production.
|
||||||
[Peer]
|
# Generate new keys with: wg genkey | tee /dev/stderr | wg pubkey
|
||||||
PublicKey = PYJSZlU38l9OzZnb7iANVk3LotbTg5MdyB2nInxhdA0=
|
|
||||||
PresharedKey = gK0SjJAvE0oFT6q9yDOQpBP6CyUOclX5yMqAm3hNa1Q=
|
|
||||||
AllowedIPs = 0.0.0.0/0, ::/0
|
|
||||||
PersistentKeepalive = 0
|
|
||||||
Endpoint = 194.87.105.23:51820
|
|
||||||
162
wg/start.sh
162
wg/start.sh
@@ -44,7 +44,9 @@ print_result() {
|
|||||||
print_separator
|
print_separator
|
||||||
}
|
}
|
||||||
|
|
||||||
# Проверка включения WireGuard
|
# ============================================================
|
||||||
|
# WireGuard: полное отключение
|
||||||
|
# ============================================================
|
||||||
if [ "$WG_ENABLED" = "false" ]; then
|
if [ "$WG_ENABLED" = "false" ]; then
|
||||||
print_stage "WireGuard is disabled"
|
print_stage "WireGuard is disabled"
|
||||||
print_result "Skipping WireGuard setup"
|
print_result "Skipping WireGuard setup"
|
||||||
@@ -54,37 +56,60 @@ if [ "$WG_ENABLED" = "false" ]; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Проверка наличия /etc/resolv.conf
|
# ============================================================
|
||||||
print_stage "Checking /etc/resolv.conf"
|
# WireGuard: включён, но нет приватного ключа — warn и skip
|
||||||
if [ ! -f /etc/resolv.conf ]; then
|
# ============================================================
|
||||||
echo "║ /etc/resolv.conf not found. Creating it..."
|
if [ -z "$WG_PRIVATE_KEY" ]; then
|
||||||
|
print_stage "WireGuard misconfiguration"
|
||||||
|
echo "║ ⚠️ WG_ENABLED=true but WG_PRIVATE_KEY is empty"
|
||||||
|
echo "║ ⚠️ Skipping WireGuard setup. Set WG_PRIVATE_KEY or set WG_ENABLED=false"
|
||||||
|
print_result "WireGuard skipped (missing private key)"
|
||||||
|
print_stage "Starting application"
|
||||||
|
echo "║ Application is starting without VPN..."
|
||||||
|
exec node src/index.js
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Генерация /etc/resolv.conf из WG_DNS
|
||||||
|
# ============================================================
|
||||||
|
print_stage "Configuring /etc/resolv.conf"
|
||||||
|
if [ -n "$WG_DNS" ]; then
|
||||||
|
echo "║ Using DNS from env WG_DNS: $WG_DNS"
|
||||||
|
echo "nameserver $WG_DNS" > /etc/resolv.conf
|
||||||
|
else
|
||||||
|
echo "║ WG_DNS empty — using fallback DNS: 1.1.1.1, 8.8.8.8"
|
||||||
echo "nameserver 1.1.1.1" > /etc/resolv.conf
|
echo "nameserver 1.1.1.1" > /etc/resolv.conf
|
||||||
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
|
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
print_result "/etc/resolv.conf created successfully." "created"
|
|
||||||
else
|
|
||||||
print_result "Failed to create /etc/resolv.conf"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
print_result "/etc/resolv.conf already exists." "exists"
|
|
||||||
fi
|
fi
|
||||||
|
print_result "/etc/resolv.conf configured." "created"
|
||||||
|
|
||||||
# Проверка наличия конфига WireGuard
|
# ============================================================
|
||||||
print_stage "Checking WireGuard config"
|
# Генерация /etc/wireguard/wg0.conf из env vars
|
||||||
if [ ! -f /etc/wireguard/wg0.conf ]; then
|
# ============================================================
|
||||||
echo "║ Error: WireGuard config not found!"
|
print_stage "Generating /etc/wireguard/wg0.conf from environment"
|
||||||
exit 1
|
cat > /etc/wireguard/wg0.conf <<EOF
|
||||||
else
|
# Generated from environment variables at container start.
|
||||||
if [ -r /etc/wireguard/wg0.conf ]; then
|
# DO NOT commit real keys to the repository.
|
||||||
print_result "WireGuard config found and readable." "exists"
|
[Interface]
|
||||||
else
|
PrivateKey = ${WG_PRIVATE_KEY}
|
||||||
print_result "WireGuard config found but not readable!"
|
Address = ${WG_ADDRESS}
|
||||||
exit 1
|
DNS = ${WG_DNS}
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = ${WG_PUBLIC_KEY}
|
||||||
|
PresharedKey = ${WG_PRESHARED_KEY}
|
||||||
|
AllowedIPs = ${WG_ALLOWED_IPS:-0.0.0.0/0,::/0}
|
||||||
|
PersistentKeepalive = 0
|
||||||
|
Endpoint = ${WG_ENDPOINT}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 600 /etc/wireguard/wg0.conf
|
||||||
|
print_result "wg0.conf generated with mode 0600." "created"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
# Проверка сети ДО включения WireGuard
|
# Проверка сети ДО включения WireGuard
|
||||||
|
# ============================================================
|
||||||
print_stage "Testing connectivity BEFORE WireGuard"
|
print_stage "Testing connectivity BEFORE WireGuard"
|
||||||
echo "║ Pinging 1.1.1.1..."
|
echo "║ Pinging 1.1.1.1..."
|
||||||
ping -c 4 1.1.1.1 > /tmp/ping.log 2>&1
|
ping -c 4 1.1.1.1 > /tmp/ping.log 2>&1
|
||||||
@@ -96,71 +121,38 @@ else
|
|||||||
fi
|
fi
|
||||||
print_separator
|
print_separator
|
||||||
|
|
||||||
# Извлекаем DNS из конфига WireGuard
|
# ============================================================
|
||||||
WG_DNS=$(awk -F= '/DNS/ {print $2}' /etc/wireguard/wg0.conf | xargs)
|
# Запуск WireGuard
|
||||||
|
# ============================================================
|
||||||
# Настройка DNS
|
print_stage "Starting WireGuard"
|
||||||
print_stage "Configuring DNS"
|
wg-quick up wg0 2>&1 | tee /tmp/wg.log
|
||||||
if [ -n "$WG_DNS" ]; then
|
wg_status=$?
|
||||||
echo "║ Using DNS from WireGuard config: $WG_DNS"
|
if [ $wg_status -eq 0 ]; then
|
||||||
echo "nameserver $WG_DNS" > /etc/resolv.conf
|
echo "║ WireGuard started successfully."
|
||||||
if [ $? -eq 0 ]; then
|
print_result "WireGuard interface activated successfully."
|
||||||
print_result "DNS configured using WireGuard settings." "created"
|
|
||||||
else
|
|
||||||
print_result "Failed to configure DNS!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
echo "║ Using fallback DNS: 1.1.1.1, 8.8.8.8"
|
echo "║ WireGuard failed to start. Logs:"
|
||||||
echo "nameserver 1.1.1.1" > /etc/resolv.conf
|
cat /tmp/wg.log | sed 's/^/║ /'
|
||||||
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
|
print_result "Failed to start WireGuard interface!"
|
||||||
if [ $? -eq 0 ]; then
|
exit 1
|
||||||
print_result "DNS configured using fallback settings." "created"
|
|
||||||
else
|
|
||||||
print_result "Failed to configure DNS!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Проверка включения WireGuard
|
# Проверка маршрутизации после запуска WireGuard
|
||||||
print_stage "Checking WireGuard status"
|
print_stage "Routing table AFTER WireGuard"
|
||||||
if [ "$WG_ENABLED" = "true" ]; then
|
ip route | sed 's/^/║ /'
|
||||||
echo "║ WireGuard is enabled. Starting..."
|
print_separator
|
||||||
|
|
||||||
# Запуск WireGuard
|
# Проверка сети ПОСЛЕ включения WireGuard
|
||||||
wg-quick up wg0 2>&1 | tee /tmp/wg.log
|
print_stage "Testing connectivity AFTER WireGuard"
|
||||||
wg_status=$?
|
echo "║ Pinging 1.1.1.1..."
|
||||||
if [ $wg_status -eq 0 ]; then
|
ping -c 4 1.1.1.1 > /tmp/ping.log 2>&1
|
||||||
echo "║ WireGuard started successfully."
|
if [ $? -eq 0 ]; then
|
||||||
print_result "WireGuard interface activated successfully."
|
echo "║ Ping successful."
|
||||||
else
|
cat /tmp/ping.log | sed 's/^/║ /'
|
||||||
echo "║ WireGuard failed to start. Logs:"
|
|
||||||
cat /tmp/wg.log | sed 's/^/║ /'
|
|
||||||
print_result "Failed to start WireGuard interface!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Проверка маршрутизации после запуска WireGuard
|
|
||||||
print_stage "Routing table AFTER WireGuard"
|
|
||||||
ip route | sed 's/^/║ /'
|
|
||||||
print_separator
|
|
||||||
|
|
||||||
# Проверка сети ПОСЛЕ включения WireGuard
|
|
||||||
print_stage "Testing connectivity AFTER WireGuard"
|
|
||||||
echo "║ Pinging 1.1.1.1..."
|
|
||||||
ping -c 4 1.1.1.1 > /tmp/ping.log 2>&1
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo "║ Ping successful."
|
|
||||||
cat /tmp/ping.log | sed 's/^/║ /'
|
|
||||||
else
|
|
||||||
echo "║ Ping failed."
|
|
||||||
fi
|
|
||||||
print_separator
|
|
||||||
else
|
else
|
||||||
echo "║ WireGuard is disabled. Skipping..."
|
echo "║ Ping failed."
|
||||||
print_result "WireGuard is disabled in configuration."
|
|
||||||
fi
|
fi
|
||||||
|
print_separator
|
||||||
|
|
||||||
# Проверка DNS
|
# Проверка DNS
|
||||||
print_stage "Testing DNS"
|
print_stage "Testing DNS"
|
||||||
|
|||||||
Reference in New Issue
Block a user