mirror of https://github.com/wg-easy/wg-easy
Browse Source
Implement entrypoint script for wg-easy-ip-tls with TLS and HTTP modes, including background certificate renewal and graceful shutdown handling.pull/2552/head
committed by
GitHub
1 changed files with 130 additions and 0 deletions
@ -0,0 +1,130 @@ |
|||||
|
#!/bin/sh |
||||
|
#=== |
||||
|
# wg-easy-ip-tls entrypoint |
||||
|
# Architecture: |
||||
|
# - dumb-init is PID 1 and spawns this script for proper |
||||
|
# signal forwarding and zombie reaping |
||||
|
# - Nitro (wg-easy) runs on HTTP internally on NITRO_PORT |
||||
|
# - If LEGO_ENABLED=true and INSECURE!=true: a Node.js TLS |
||||
|
# reverse proxy wraps Nitro on PORT (HTTPS termination) |
||||
|
# - If INSECURE=true: Nitro listens directly on PORT (HTTP) |
||||
|
# - A background renewal loop re-runs lego-renew.sh every |
||||
|
# LEGO_RENEW_INTERVAL seconds (default: 5 days) |
||||
|
#=== |
||||
|
set -e |
||||
|
|
||||
|
CERT_FILE="/root/cert/ip/fullchain.pem" |
||||
|
KEY_FILE="/root/cert/ip/privkey.pem" |
||||
|
PORT="${PORT:-51821}" |
||||
|
NITRO_PORT="${NITRO_PORT:-51822}" |
||||
|
LEGO_ENABLED="${LEGO_ENABLED:-false}" |
||||
|
INSECURE="${INSECURE:-true}" |
||||
|
# Renewal interval in seconds (default 5 days = 432000s) |
||||
|
LEGO_RENEW_INTERVAL="${LEGO_RENEW_INTERVAL:-432000}" |
||||
|
|
||||
|
SERVER_PID_FILE="/tmp/wg-easy.pid" |
||||
|
PROXY_PID_FILE="/tmp/tls-proxy.pid" |
||||
|
RENEWAL_PID_FILE="/tmp/lego-renewal.pid" |
||||
|
|
||||
|
# Graceful shutdown handler |
||||
|
cleanup() { |
||||
|
echo "[entrypoint] Shutting down..." |
||||
|
if [ -f "$RENEWAL_PID_FILE" ]; then |
||||
|
PID=$(cat "$RENEWAL_PID_FILE" 2>/dev/null) |
||||
|
[ -n "$PID" ] && kill "$PID" 2>/dev/null || true |
||||
|
fi |
||||
|
if [ -f "$PROXY_PID_FILE" ]; then |
||||
|
PID=$(cat "$PROXY_PID_FILE" 2>/dev/null) |
||||
|
[ -n "$PID" ] && kill "$PID" 2>/dev/null || true |
||||
|
fi |
||||
|
if [ -f "$SERVER_PID_FILE" ]; then |
||||
|
PID=$(cat "$SERVER_PID_FILE" 2>/dev/null) |
||||
|
[ -n "$PID" ] && kill "$PID" 2>/dev/null || true |
||||
|
fi |
||||
|
exit 0 |
||||
|
} |
||||
|
trap cleanup TERM INT |
||||
|
|
||||
|
if [ "$LEGO_ENABLED" = "true" ] && [ "$INSECURE" != "true" ]; then |
||||
|
# ── TLS mode ─── |
||||
|
/usr/local/bin/lego-renew.sh |
||||
|
|
||||
|
# Start background cert renewal loop |
||||
|
( |
||||
|
while true; do |
||||
|
sleep "$LEGO_RENEW_INTERVAL" |
||||
|
echo "[entrypoint] Running scheduled cert renewal..." |
||||
|
/usr/local/bin/lego-renew.sh && echo "[entrypoint] Cert renewal complete" || \ |
||||
|
echo "[entrypoint] WARNING: cert renewal failed, will retry next cycle" |
||||
|
done |
||||
|
) & |
||||
|
echo $! > "$RENEWAL_PID_FILE" |
||||
|
|
||||
|
echo "[entrypoint] Starting wg-easy (internal HTTP on port $NITRO_PORT)..." |
||||
|
PORT="$NITRO_PORT" HOST="127.0.0.1" node /app/server/index.mjs & |
||||
|
echo $! > "$SERVER_PID_FILE" |
||||
|
|
||||
|
# Wait for Nitro to be ready before starting the proxy |
||||
|
echo "[entrypoint] Waiting for internal server..." |
||||
|
i=0 |
||||
|
while ! nc -z 127.0.0.1 "$NITRO_PORT" 2>/dev/null; do |
||||
|
sleep 0.5 |
||||
|
i=$((i + 1)) |
||||
|
if [ $i -ge 60 ]; then |
||||
|
echo "[entrypoint] ERROR: internal server did not start in 30 seconds" |
||||
|
exit 1 |
||||
|
fi |
||||
|
done |
||||
|
|
||||
|
echo "[entrypoint] Starting TLS proxy on port $PORT..." |
||||
|
node -e " |
||||
|
const https = require('https'); |
||||
|
const http = require('http'); |
||||
|
const net = require('net'); |
||||
|
const fs = require('fs'); |
||||
|
const cert = fs.readFileSync('$CERT_FILE'); |
||||
|
const key = fs.readFileSync('$KEY_FILE'); |
||||
|
const server = https.createServer({ cert, key }, (req, res) => { |
||||
|
const proxy = http.request({ |
||||
|
hostname: '127.0.0.1', |
||||
|
port: $NITRO_PORT, |
||||
|
path: req.url, |
||||
|
method: req.method, |
||||
|
headers: req.headers, |
||||
|
}, (proxyRes) => { |
||||
|
res.writeHead(proxyRes.statusCode, proxyRes.headers); |
||||
|
proxyRes.pipe(res); |
||||
|
}); |
||||
|
proxy.on('error', (e) => { |
||||
|
console.error('[tls-proxy] error:', e.message); |
||||
|
if (!res.headersSent) { res.writeHead(502); } |
||||
|
res.end('Bad Gateway'); |
||||
|
}); |
||||
|
req.pipe(proxy); |
||||
|
}); |
||||
|
server.on('upgrade', (req, socket, head) => { |
||||
|
const conn = net.connect($NITRO_PORT, '127.0.0.1', () => { |
||||
|
conn.write('GET ' + req.url + ' HTTP/1.1\\r\\n' + |
||||
|
Object.entries(req.headers).map(([k,v]) => k + ': ' + v).join('\\r\\n') + |
||||
|
'\\r\\n\\r\\n'); |
||||
|
if (head && head.length) conn.write(head); |
||||
|
socket.pipe(conn); |
||||
|
conn.pipe(socket); |
||||
|
}); |
||||
|
conn.on('error', (e) => { |
||||
|
console.error('[tls-proxy] ws error:', e.message); |
||||
|
socket.destroy(); |
||||
|
}); |
||||
|
}); |
||||
|
server.listen($PORT, '0.0.0.0', () => { |
||||
|
console.log('[tls-proxy] HTTPS listening on 0.0.0.0:$PORT -> http://127.0.0.1:$NITRO_PORT'); |
||||
|
}); |
||||
|
" & |
||||
|
echo $! > "$PROXY_PID_FILE" |
||||
|
else |
||||
|
# ── HTTP mode (INSECURE=true or LEGO_ENABLED=false) ─── |
||||
|
echo "[entrypoint] Starting wg-easy in HTTP mode on port $PORT..." |
||||
|
PORT="$PORT" HOST="0.0.0.0" node /app/server/index.mjs & |
||||
|
echo $! > "$SERVER_PID_FILE" |
||||
|
fi |
||||
|
wait |
||||
Loading…
Reference in new issue