Dateien nach "scripts" hochladen

This commit is contained in:
2026-04-20 23:34:43 +02:00
parent 22a291d6cf
commit fe26ce4cbb
+147 -29
View File
@@ -182,7 +182,8 @@ collect_vpn_config() {
NORD_USER="$REPLY"
[[ -z "$NORD_USER" ]] && error "Username darf nicht leer sein!"
ask_secret "NordVPN Service-Passwort"
stty echo 2>/dev/null || true
ask "NordVPN Service-Passwort"
NORD_PASS="$REPLY"
[[ -z "$NORD_PASS" ]] && error "Passwort darf nicht leer sein!"
@@ -196,8 +197,10 @@ collect_vpn_config() {
VPN_PROTO="udp" # Start mit UDP, automatischer Fallback auf TCP bei TLS-Fehler
if [[ "$VPN_MODE" == "2" ]]; then
echo -e "\n ${YELLOW}Gültige Hostnamen haben das Format: de507.nordvpn.com, de654.nordvpn.com etc.${NC}"
echo -e " ${YELLOW}Beispiele für Deutschland: de507, de654, de675 ... de1118${NC}"
echo -e "\n ${YELLOW}Hostnamen Format: de507.nordvpn.com, de654.nordvpn.com etc.${NC}"
echo -e " ${YELLOW}Wichtig: NordVPN zeigt oft neue Server die Gluetun noch nicht kennt.${NC}"
echo -e " ${YELLOW}Falls 'Ungültiger Hostname' erscheint → die angezeigten gültigen Server nutzen.${NC}"
echo -e " ${CYAN}Tipp: Modus 1 (Serverland) ist einfacher Gluetun wählt selbst.${NC}"
ask "Hostname (z.B. de507.nordvpn.com)"
VPN_HOSTNAME="$REPLY"; VPN_COUNTRY=""
else
@@ -205,13 +208,9 @@ collect_vpn_config() {
VPN_COUNTRY="$REPLY"; VPN_HOSTNAME=""
fi
# FreqUI Port aus bestehender config ermitteln
local current_port
current_port=$(pct exec "$SEL_ID" -- bash -c \
"grep -oP '0\.0\.0\.0:\K[0-9]+(?=:[0-9]+)' /opt/docker-projekte/freqtrade/docker-compose.yml 2>/dev/null | head -1 || echo 8080" \
2>/dev/null || echo "8080")
ask "FreqUI Port" "$current_port"
FT_PORT="$REPLY"
# FreqUI Port aus bestehender docker-compose.yml lesen (ändert sich nicht)
FT_PORT=$(pct exec "$SEL_ID" -- bash -c "grep -oP '0\.0\.0\.0:\K[0-9]+(?=:[0-9]+)' /opt/docker-projekte/freqtrade/docker-compose.yml 2>/dev/null | head -1 || echo 8080" 2>/dev/null || echo "8080")
info "FreqUI Port: ${FT_PORT} (aus bestehender Konfiguration)"
echo -e "\n${BOLD}${BLUE}══════════ Zusammenfassung ══════════${NC}"
echo -e " Container: ${CYAN}CT ${SEL_ID} | ${SEL_NAME}${NC}"
@@ -227,6 +226,8 @@ collect_vpn_config() {
# ── Konfiguration in Container schreiben ──────────────────────────────────────
write_vpn_config() {
step "VPN-Konfiguration in Container schreiben"
# Image: custom build bei Dedicated-IP, sonst offizielles Image
GLUETUN_IMAGE="${GLUETUN_IMAGE:-qmcgaw/gluetun:latest}"
local FT_DIR="/opt/docker-projekte/freqtrade"
local NORD_USER_B64 NORD_PASS_B64
@@ -234,9 +235,15 @@ write_vpn_config() {
NORD_PASS_B64=$(printf '%s' "$NORD_PASS" | base64 -w0)
local VPN_SERVER_LINE=""
[[ -n "$VPN_HOSTNAME" ]] \
&& VPN_SERVER_LINE=" - SERVER_HOSTNAMES=${VPN_HOSTNAME}" \
|| VPN_SERVER_LINE=" - SERVER_COUNTRIES=${VPN_COUNTRY}"
local VPN_CUSTOM_LINE=""
if [[ -n "$VPN_HOSTNAME" ]]; then
# Dedicated-IP: Custom Config direkt mit IP bypasses Gluetun Hostname-Validierung
VPN_SERVER_LINE=" - VPN_SERVICE_PROVIDER=custom"
VPN_CUSTOM_LINE=" - OPENVPN_CUSTOM_CONFIG=/gluetun/nordvpn-custom.conf"
else
VPN_SERVER_LINE=" - VPN_SERVICE_PROVIDER=nordvpn"
VPN_CUSTOM_LINE=" - SERVER_COUNTRIES=${VPN_COUNTRY}"
fi
# Backup
pct exec "$SEL_ID" -- bash -c \
@@ -275,7 +282,7 @@ services:
# Gluetun läuft als HTTP-Proxy auf Port 8888.
# Freqtrade schickt nur den Exchange-Traffic darüber.
gluetun:
image: qmcgaw/gluetun:latest
image: ${GLUETUN_IMAGE:-qmcgaw/gluetun:latest}
container_name: gluetun
restart: unless-stopped
cap_add:
@@ -283,11 +290,11 @@ services:
devices:
- /dev/net/tun:/dev/net/tun
environment:
- VPN_SERVICE_PROVIDER=nordvpn
${VPN_SERVER_LINE}
- VPN_TYPE=openvpn
- OPENVPN_USER=\${OPENVPN_USER}
- OPENVPN_PASSWORD=\${OPENVPN_PASSWORD}
${VPN_SERVER_LINE}
${VPN_CUSTOM_LINE}
# HTTP-Proxy aktivieren darüber leitet Freqtrade den Binance-Traffic
- HTTPPROXY=on
- HTTPPROXY_LOG=off
@@ -345,6 +352,90 @@ start_and_verify() {
local vpn_ok=false
VPN_IP=""
# Bei Hostname-Modus: Gluetun aus GitHub klonen, Server eintragen, neu kompilieren
# → Löst das Problem dauerhaft: de1370 wird in die Binary eingebaut
if [[ -n "${VPN_HOSTNAME:-}" ]]; then
step "Gluetun Custom Build für ${VPN_HOSTNAME}"
# IP per DNS auflösen
local server_ip=""
server_ip=$(pct exec "$SEL_ID" -- bash -c "getent hosts ${VPN_HOSTNAME} 2>/dev/null | awk '{print \$1}' | head -1" 2>/dev/null || echo "")
[[ -z "$server_ip" ]] && server_ip=$(pct exec "$SEL_ID" -- bash -c "nslookup ${VPN_HOSTNAME} 2>/dev/null | awk '/Address:/ && !/#/{print \$2}' | head -1" 2>/dev/null || echo "")
[[ -z "$server_ip" ]] && error "IP für ${VPN_HOSTNAME} nicht auflösbar!"
info "DNS: ${VPN_HOSTNAME}${server_ip}"
# Prüfen ob Image bereits existiert (kein Rebuild nötig)
local img_exists
img_exists=$(pct exec "$SEL_ID" -- bash -c "docker image inspect gluetun-custom:latest 2>/dev/null | grep -c 'Id' || echo 0" 2>/dev/null || echo "0")
if [[ "$img_exists" -gt 0 ]]; then
# Prüfen ob der Hostname schon drin ist
local host_in_img
host_in_img=$(pct exec "$SEL_ID" -- bash -c "docker run --rm --entrypoint sh gluetun-custom:latest -c 'cat /gluetun/servers.json 2>/dev/null | grep -c ${VPN_HOSTNAME} || echo 0'" 2>/dev/null || echo "0")
if [[ "$host_in_img" -gt 0 ]]; then
success "gluetun-custom:latest bereits vorhanden und enthält ${VPN_HOSTNAME}"
GLUETUN_IMAGE="gluetun-custom:latest"
return 0 2>/dev/null || true
fi
info "Image vorhanden, aber ${VPN_HOSTNAME} fehlt baue neu..."
fi
# git installieren falls nötig
pct exec "$SEL_ID" -- bash -c "command -v git &>/dev/null || apt-get install -y -qq git" 2>/dev/null
info "Klone Gluetun von GitHub (einmalig, ~3-5 Min zum Kompilieren)..."
pct exec "$SEL_ID" -- bash -c "rm -rf /tmp/gluetun-build && git clone --depth 1 https://github.com/qdm12/gluetun.git /tmp/gluetun-build 2>&1 | tail -3"
info "Füge ${VPN_HOSTNAME} (${server_ip}) in servers.json ein..."
pct exec "$SEL_ID" -- bash -c "python3 << PYEOF
import json, copy, sys
path = '/tmp/gluetun-build/internal/storage/servers.json'
hostname = '${VPN_HOSTNAME}'
ip = '${server_ip}'
with open(path) as f:
db = json.load(f)
servers = db.get('nordvpn', {}).get('servers', [])
if any(s.get('hostname') == hostname for s in servers):
print(f'Bereits vorhanden: {hostname}')
sys.exit(0)
# Deutschen OpenVPN-Eintrag als Template klonen
template = next(
(s for s in servers if s.get('country','').lower() == 'germany' and s.get('vpn') == 'openvpn'),
servers[0]
)
entry = copy.deepcopy(template)
entry['hostname'] = hostname
entry['ips'] = [ip]
servers.append(entry)
db['nordvpn']['servers'] = servers
with open(path, 'w') as f:
json.dump(db, f, indent=2)
print(f'Eingetragen: {hostname} ({ip}) Gesamt NordVPN-Server: {len(servers)}')
PYEOF"
info "Kompiliere Gluetun Docker Image (dauert ~3-5 Minuten)..."
echo -e " ${YELLOW}Bitte warten Go Multi-Stage Build...${NC}"
pct exec "$SEL_ID" -- bash -c "cd /tmp/gluetun-build && docker build -t gluetun-custom:latest . 2>&1 | grep -E '^Step|Successfully|error|Error|=>|RUN|COPY' | tail -30" && success "gluetun-custom:latest erfolgreich gebaut!" || error "Docker Build fehlgeschlagen. Prüfe: pct exec ${SEL_ID} -- docker build /tmp/gluetun-build"
GLUETUN_IMAGE="gluetun-custom:latest"
info "Aufräumen..."
pct exec "$SEL_ID" -- bash -c "rm -rf /tmp/gluetun-build" 2>/dev/null || true
else
GLUETUN_IMAGE="qmcgaw/gluetun:latest"
fi
# docker-compose.yml mit korrektem Image aktualisieren
info "Setze Image in docker-compose.yml: ${GLUETUN_IMAGE}"
pct exec "$SEL_ID" -- bash -c "sed -i 's|image: .*gluetun.*|image: ${GLUETUN_IMAGE}|' ${FT_DIR}/docker-compose.yml"
# Protokoll-Reihenfolge: UDP zuerst, dann automatisch TCP
for proto in udp tcp; do
[[ "$proto" == "tcp" ]] && info "UDP fehlgeschlagen versuche TCP automatisch..."
@@ -367,7 +458,7 @@ start_and_verify() {
${CYAN}[INFO]${NC} ${proto^^} ${elapsed}s..."
local log_snippet
log_snippet=$(pct exec "$SEL_ID" -- bash -c "docker logs --since 30s gluetun 2>&1" 2>/dev/null || echo "")
log_snippet=$(pct exec "$SEL_ID" -- bash -c "docker logs gluetun 2>&1 | tail -60" 2>/dev/null || echo "")
# Auth-Fehler → sofort abbrechen, kein Retry
if echo "$log_snippet" | grep -qi "AUTH_FAILED\|auth.*fail\|wrong.*password\|incorrect.*password"; then
@@ -388,22 +479,49 @@ start_and_verify() {
fi
fi
# Hostname ungültig → sofort abbrechen
# Hostname ungültig → gültige Server aus Log parsen und zur Auswahl anbieten
if echo "$log_snippet" | grep -qi "hostname.*not valid\|not one of the possible choices"; then
echo
echo -e "
${RED}✗ Ungültiger Hostname!${NC}"
echo -e " ${YELLOW}Gültige Server: de507.nordvpn.com, de654.nordvpn.com, de675.nordvpn.com ...${NC}"
pct exec "$SEL_ID" -- bash -c "cd ${FT_DIR} && docker compose down 2>/dev/null || true"
echo -e " ${RED}✗ Ungültiger Hostname: ${VPN_HOSTNAME}${NC}"
echo -e " ${YELLOW}Nicht in Gluetuns Server-Datenbank. Bitte einen der folgenden wählen:${NC}
"
if confirm "Anderen Hostname eingeben?"; then
collect_vpn_config
write_vpn_config
start_and_verify
return
else
error "Abgebrochen."
# Mehr Log holen die Server-Liste ist sehr lang
local full_log valid_servers
full_log=$(pct exec "$SEL_ID" -- bash -c "docker logs gluetun 2>&1" 2>/dev/null || echo "")
# Nur deutsche Server aus der Liste filtern (de*)
valid_servers=$(echo "$full_log" | grep -oP 'de[0-9]+\.nordvpn\.com' | sort -uV | head -20)
# Falls keine deutschen → alle zeigen
[[ -z "$valid_servers" ]] && valid_servers=$(echo "$full_log" | grep -oP '[a-z]{2}[0-9]+\.nordvpn\.com' | sort -u | head -20)
if [[ -n "$valid_servers" ]]; then
local i=1
while IFS= read -r srv; do
printf " ${CYAN}%2s)${NC} %s
" "$i" "$srv"
i=$((i+1))
done <<< "$valid_servers"
echo
echo -ne "${YELLOW}${NC}Nummer wählen oder Hostname direkt eingeben: "
read -r sel
if [[ "$sel" =~ ^[0-9]+$ ]]; then
VPN_HOSTNAME=$(echo "$valid_servers" | sed -n "${sel}p")
elif [[ -n "$sel" ]]; then
VPN_HOSTNAME="$sel"
fi
if [[ -n "$VPN_HOSTNAME" ]]; then
info "Neuer Hostname: $VPN_HOSTNAME schreibe Config neu..."
pct exec "$SEL_ID" -- bash -c "cd ${FT_DIR} && docker compose down 2>/dev/null || true"
write_vpn_config
tries=0; tls_error=false
pct exec "$SEL_ID" -- bash -c "cd ${FT_DIR} && docker compose up -d 2>&1" || true
continue
fi
else
echo -e " ${YELLOW}Keine Server im Log gefunden. Modus 1 (Serverland) empfohlen.${NC}"
fi
pct exec "$SEL_ID" -- bash -c "cd ${FT_DIR} && docker compose down 2>/dev/null || true"
error "Abgebrochen."
fi
# TLS-Fehler → nächstes Protokoll versuchen