fix(docker): add missing Python deps, fix VPN routing and healthcheck
- Add missing packages to requirements.txt: requests, beautifulsoup4, fake-useragent, yt-dlp, urllib3 - Fix entrypoint.sh: replace grep -oP (GNU) with awk (BusyBox compat) - Fix entrypoint.sh: add policy routing so LAN clients get responses via eth0 instead of through the WireGuard tunnel - Change healthcheck from ping to curl (VPN provider blocks ICMP) - Add start_period and increase retries for healthcheck - Change external port mapping to 2000:8000 - Add podman-compose.prod.yml and push.sh to version control
This commit is contained in:
@@ -18,7 +18,7 @@ COPY entrypoint.sh /entrypoint.sh
|
|||||||
RUN chmod +x /entrypoint.sh
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
# Health check: can we reach the internet through the VPN?
|
# Health check: can we reach the internet through the VPN?
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --retries=5 \
|
||||||
CMD ping -c 1 -W 5 1.1.1.1 || exit 1
|
CMD curl -sf --max-time 5 http://1.1.1.1 || exit 1
|
||||||
|
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
|
|||||||
@@ -101,7 +101,9 @@ setup_killswitch() {
|
|||||||
# ──────────────────────────────────────────────
|
# ──────────────────────────────────────────────
|
||||||
enable_forwarding() {
|
enable_forwarding() {
|
||||||
echo "[init] Enabling IP forwarding..."
|
echo "[init] Enabling IP forwarding..."
|
||||||
if echo 1 > /proc/sys/net/ipv4/ip_forward 2>/dev/null; then
|
if cat /proc/sys/net/ipv4/ip_forward 2>/dev/null | grep -q 1; then
|
||||||
|
echo "[init] IP forwarding already enabled."
|
||||||
|
elif echo 1 > /proc/sys/net/ipv4/ip_forward 2>/dev/null; then
|
||||||
echo "[init] IP forwarding enabled via /proc."
|
echo "[init] IP forwarding enabled via /proc."
|
||||||
else
|
else
|
||||||
echo "[init] /proc read-only — relying on --sysctl net.ipv4.ip_forward=1"
|
echo "[init] /proc read-only — relying on --sysctl net.ipv4.ip_forward=1"
|
||||||
@@ -139,6 +141,20 @@ start_vpn() {
|
|||||||
ip route add 0.0.0.0/1 dev "$INTERFACE"
|
ip route add 0.0.0.0/1 dev "$INTERFACE"
|
||||||
ip route add 128.0.0.0/1 dev "$INTERFACE"
|
ip route add 128.0.0.0/1 dev "$INTERFACE"
|
||||||
|
|
||||||
|
# ── Policy routing: ensure responses to incoming LAN traffic go back via eth0 ──
|
||||||
|
if [ -n "$DEFAULT_GW" ] && [ -n "$DEFAULT_IF" ]; then
|
||||||
|
# Get the container's eth0 IP address (BusyBox-compatible, no grep -P)
|
||||||
|
ETH0_IP=$(ip -4 addr show "$DEFAULT_IF" | awk '/inet / {split($2, a, "/"); print a[1]}' | head -1)
|
||||||
|
ETH0_SUBNET=$(ip -4 route show dev "$DEFAULT_IF" | grep -v default | head -1 | awk '{print $1}')
|
||||||
|
if [ -n "$ETH0_IP" ] && [ -n "$ETH0_SUBNET" ]; then
|
||||||
|
echo "[vpn] Setting up policy routing for incoming traffic (${ETH0_IP} on ${DEFAULT_IF})"
|
||||||
|
ip route add default via "$DEFAULT_GW" dev "$DEFAULT_IF" table 100 2>/dev/null || true
|
||||||
|
ip route add "$ETH0_SUBNET" dev "$DEFAULT_IF" table 100 2>/dev/null || true
|
||||||
|
ip rule add from "$ETH0_IP" table 100 priority 100 2>/dev/null || true
|
||||||
|
echo "[vpn] Policy routing active — incoming connections will be routed back via ${DEFAULT_IF}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Set up DNS
|
# Set up DNS
|
||||||
VPN_DNS=$(grep -i '^DNS' "$CONFIG_FILE" | head -1 | sed 's/.*= *//;s/ //g')
|
VPN_DNS=$(grep -i '^DNS' "$CONFIG_FILE" | head -1 | sed 's/.*= *//;s/ //g')
|
||||||
if [ -n "$VPN_DNS" ]; then
|
if [ -n "$VPN_DNS" ]; then
|
||||||
@@ -169,7 +185,7 @@ health_loop() {
|
|||||||
while true; do
|
while true; do
|
||||||
sleep "$CHECK_INTERVAL"
|
sleep "$CHECK_INTERVAL"
|
||||||
|
|
||||||
if ping -c 1 -W 5 "$CHECK_HOST" > /dev/null 2>&1; then
|
if curl -sf --max-time 5 "http://$CHECK_HOST" > /dev/null 2>&1; then
|
||||||
if [ "$failures" -gt 0 ]; then
|
if [ "$failures" -gt 0 ]; then
|
||||||
echo "[health] VPN recovered."
|
echo "[health] VPN recovered."
|
||||||
failures=0
|
failures=0
|
||||||
|
|||||||
54
Docker/podman-compose.prod.yml
Normal file
54
Docker/podman-compose.prod.yml
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# Production compose — pulls pre-built images from Gitea registry.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# podman login git.lpl-mind.de
|
||||||
|
# podman-compose -f podman-compose.prod.yml pull
|
||||||
|
# podman-compose -f podman-compose.prod.yml up -d
|
||||||
|
#
|
||||||
|
# Required files:
|
||||||
|
# - wg0.conf (WireGuard configuration in the same directory)
|
||||||
|
|
||||||
|
services:
|
||||||
|
vpn:
|
||||||
|
image: git.lpl-mind.de/lukas.pupkalipinski/aniworld/vpn:latest
|
||||||
|
container_name: vpn-wireguard
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
- SYS_MODULE
|
||||||
|
sysctls:
|
||||||
|
- net.ipv4.ip_forward=1
|
||||||
|
- net.ipv4.conf.all.src_valid_mark=1
|
||||||
|
volumes:
|
||||||
|
- /server/server_aniworld/wg0.conf:/etc/wireguard/wg0.conf:ro
|
||||||
|
- /lib/modules:/lib/modules:ro
|
||||||
|
ports:
|
||||||
|
- "2000:8000"
|
||||||
|
environment:
|
||||||
|
- HEALTH_CHECK_INTERVAL=10
|
||||||
|
- HEALTH_CHECK_HOST=1.1.1.1
|
||||||
|
- LOCAL_PORTS=8000
|
||||||
|
- PUID=1013
|
||||||
|
- PGID=1001
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-sf", "--max-time", "5", "http://1.1.1.1"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
start_period: 60s
|
||||||
|
|
||||||
|
app:
|
||||||
|
image: git.lpl-mind.de/lukas.pupkalipinski/aniworld/app:latest
|
||||||
|
container_name: aniworld-app
|
||||||
|
network_mode: "service:vpn"
|
||||||
|
depends_on:
|
||||||
|
vpn:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
- PYTHONUNBUFFERED=1
|
||||||
|
- PUID=1013
|
||||||
|
- PGID=1001
|
||||||
|
volumes:
|
||||||
|
- /server/server_aniworld/data:/app/data
|
||||||
|
- /server/server_aniworld/logs:/app/logs
|
||||||
|
restart: unless-stopped
|
||||||
97
Docker/push.sh
Normal file
97
Docker/push.sh
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# filepath: /home/lukas/Volume/repo/Aniworld/Docker/push.sh
|
||||||
|
#
|
||||||
|
# Build and push Aniworld container images to the Gitea registry.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./push.sh # builds & pushes with tag "latest"
|
||||||
|
# ./push.sh v1.2.3 # builds & pushes with tag "v1.2.3"
|
||||||
|
# ./push.sh v1.2.3 --no-build # pushes existing images only
|
||||||
|
#
|
||||||
|
# Prerequisites:
|
||||||
|
# podman login git.lpl-mind.de
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Configuration
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
REGISTRY="git.lpl-mind.de"
|
||||||
|
NAMESPACE="lukas.pupkalipinski"
|
||||||
|
PROJECT="aniworld"
|
||||||
|
|
||||||
|
APP_IMAGE="${REGISTRY}/${NAMESPACE}/${PROJECT}/app"
|
||||||
|
VPN_IMAGE="${REGISTRY}/${NAMESPACE}/${PROJECT}/vpn"
|
||||||
|
|
||||||
|
TAG="${1:-latest}"
|
||||||
|
SKIP_BUILD=false
|
||||||
|
if [[ "${2:-}" == "--no-build" ]]; then
|
||||||
|
SKIP_BUILD=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Helpers
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
log() { echo -e "\n>>> $*"; }
|
||||||
|
err() { echo -e "\n❌ ERROR: $*" >&2; exit 1; }
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Pre-flight checks
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "============================================"
|
||||||
|
echo " Aniworld — Build & Push"
|
||||||
|
echo " Registry : ${REGISTRY}"
|
||||||
|
echo " Tag : ${TAG}"
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
command -v podman &>/dev/null || err "podman is not installed."
|
||||||
|
|
||||||
|
if ! podman login --get-login "${REGISTRY}" &>/dev/null; then
|
||||||
|
err "Not logged in. Run:\n podman login ${REGISTRY}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Build
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
if [[ "${SKIP_BUILD}" == false ]]; then
|
||||||
|
log "Building app image → ${APP_IMAGE}:${TAG}"
|
||||||
|
podman build \
|
||||||
|
-t "${APP_IMAGE}:${TAG}" \
|
||||||
|
-f "${SCRIPT_DIR}/Dockerfile.app" \
|
||||||
|
"${PROJECT_ROOT}"
|
||||||
|
|
||||||
|
log "Building VPN image → ${VPN_IMAGE}:${TAG}"
|
||||||
|
podman build \
|
||||||
|
-t "${VPN_IMAGE}:${TAG}" \
|
||||||
|
-f "${SCRIPT_DIR}/Containerfile" \
|
||||||
|
"${SCRIPT_DIR}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Push
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
log "Pushing ${APP_IMAGE}:${TAG}"
|
||||||
|
podman push "${APP_IMAGE}:${TAG}"
|
||||||
|
|
||||||
|
log "Pushing ${VPN_IMAGE}:${TAG}"
|
||||||
|
podman push "${VPN_IMAGE}:${TAG}"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Summary
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo " ✅ Push complete!"
|
||||||
|
echo ""
|
||||||
|
echo " Images:"
|
||||||
|
echo " ${APP_IMAGE}:${TAG}"
|
||||||
|
echo " ${VPN_IMAGE}:${TAG}"
|
||||||
|
echo ""
|
||||||
|
echo " Deploy on server:"
|
||||||
|
echo " podman login ${REGISTRY}"
|
||||||
|
echo " podman-compose -f podman-compose.prod.yml pull"
|
||||||
|
echo " podman-compose -f podman-compose.prod.yml up -d"
|
||||||
|
echo "============================================"
|
||||||
@@ -18,4 +18,10 @@ aiosqlite>=0.19.0
|
|||||||
aiohttp>=3.9.0
|
aiohttp>=3.9.0
|
||||||
lxml>=5.0.0
|
lxml>=5.0.0
|
||||||
pillow>=10.0.0
|
pillow>=10.0.0
|
||||||
APScheduler>=3.10.4
|
APScheduler>=3.10.4
|
||||||
|
Events>=0.5
|
||||||
|
requests>=2.31.0
|
||||||
|
beautifulsoup4>=4.12.0
|
||||||
|
fake-useragent>=1.4.0
|
||||||
|
yt-dlp>=2024.1.0
|
||||||
|
urllib3>=2.0.0
|
||||||
Reference in New Issue
Block a user