Dateien nach "scripts" hochladen
This commit is contained in:
@@ -190,15 +190,6 @@ create_lxc() {
|
|||||||
|
|
||||||
success "LXC erstellt"
|
success "LXC erstellt"
|
||||||
|
|
||||||
# TUN-Device für NordVPN/Gluetun vorbereiten
|
|
||||||
# (muss VOR dem Start in die Config, danach braucht install-vpn.sh keinen manuellen Eingriff)
|
|
||||||
cat >> "/etc/pve/lxc/${CT_ID}.conf" << 'TUNCFG'
|
|
||||||
# TUN-Device fuer NordVPN/Gluetun (eingetragen von freqtrade-lxc-install.sh)
|
|
||||||
lxc.cgroup2.devices.allow: c 10:200 rwm
|
|
||||||
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
|
|
||||||
TUNCFG
|
|
||||||
success "TUN-Device in LXC-Config eingetragen"
|
|
||||||
|
|
||||||
# Container mit Tag "freqtrade" versehen (für proxmox-vpn-install.sh nutzbar)
|
# Container mit Tag "freqtrade" versehen (für proxmox-vpn-install.sh nutzbar)
|
||||||
pct set "$CT_ID" --tags "freqtrade" 2>/dev/null || true
|
pct set "$CT_ID" --tags "freqtrade" 2>/dev/null || true
|
||||||
|
|
||||||
@@ -515,11 +506,11 @@ show_result() {
|
|||||||
echo -e " ${YELLOW}1. Binance API-Keys in config.json eintragen${NC}"
|
echo -e " ${YELLOW}1. Binance API-Keys in config.json eintragen${NC}"
|
||||||
echo -e " ${YELLOW}2. dry_run: false setzen wenn bereit${NC}"
|
echo -e " ${YELLOW}2. dry_run: false setzen wenn bereit${NC}"
|
||||||
echo -e " ${YELLOW}3. Strategie anpassen${NC}"
|
echo -e " ${YELLOW}3. Strategie anpassen${NC}"
|
||||||
echo -e " ${YELLOW}4. NordVPN optional: install-vpn.sh im LXC ausführen${NC}"
|
echo -e " ${YELLOW}4. NordVPN optional: proxmox-vpn-install.sh auf dem Proxmox Host ausführen${NC}"
|
||||||
echo
|
echo
|
||||||
echo -e " ${BOLD}LXC-Konsole öffnen:${NC} ${CYAN}pct enter ${CT_ID}${NC}"
|
echo -e " ${BOLD}LXC-Konsole öffnen:${NC} ${CYAN}pct enter ${CT_ID}${NC}"
|
||||||
echo -e " ${BOLD}NordVPN Addon:${NC}"
|
echo -e " ${BOLD}NordVPN Addon:${NC}"
|
||||||
echo -e " ${CYAN}bash -c \"\$(curl -fsSL https://git.obraasch.de/olli1986/freqtrade-proxmox-deploy/raw/branch/main/scripts/install-vpn.sh)\"${NC}"
|
echo -e " ${CYAN}bash -c \"\$(curl -fsSL https://git.obraasch.de/olli1986/freqtrade-proxmox-deploy/raw/branch/main/scripts/proxmox-vpn-install.sh)\"${NC}"
|
||||||
echo
|
echo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+344
-109
@@ -1,10 +1,13 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Freqtrade NordVPN Addon – Proxmox Host Installer
|
# Freqtrade NordVPN Addon – Proxmox Host Installer
|
||||||
# Erkennt Freqtrade-Container automatisch per Tag, richtet TUN-Device ein
|
# Läuft komplett auf dem PROXMOX HOST.
|
||||||
# und startet install-vpn.sh im Container.
|
# - Zeigt Freqtrade-Container zur Auswahl (gefiltert nach Tag/Hostname)
|
||||||
|
# - Richtet TUN-Device ein (Container-Neustart)
|
||||||
|
# - Fragt NordVPN-Credentials ab
|
||||||
|
# - Schreibt .env + docker-compose.yml mit Gluetun im Container
|
||||||
|
# - Startet Stack und prüft VPN-IP
|
||||||
#
|
#
|
||||||
# Läuft auf dem PROXMOX HOST.
|
|
||||||
# Quelle: https://git.obraasch.de/olli1986/freqtrade-proxmox-deploy
|
# Quelle: https://git.obraasch.de/olli1986/freqtrade-proxmox-deploy
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
@@ -18,7 +21,23 @@ warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
|||||||
error() { echo -e "${RED}[FAIL]${NC} $*"; exit 1; }
|
error() { echo -e "${RED}[FAIL]${NC} $*"; exit 1; }
|
||||||
step() { echo -e "\n${BOLD}${BLUE}▶ $*${NC}"; }
|
step() { echo -e "\n${BOLD}${BLUE}▶ $*${NC}"; }
|
||||||
|
|
||||||
VPN_SCRIPT_URL="https://git.obraasch.de/olli1986/freqtrade-proxmox-deploy/raw/branch/main/scripts/install-vpn.sh"
|
ask() {
|
||||||
|
local prompt="$1" default="${2:-}"
|
||||||
|
[[ -n "$default" ]] \
|
||||||
|
&& echo -ne "${YELLOW} ➜ ${NC}${prompt} [${CYAN}${default}${NC}]: " \
|
||||||
|
|| echo -ne "${YELLOW} ➜ ${NC}${prompt}: "
|
||||||
|
read -r REPLY; REPLY="${REPLY:-$default}"
|
||||||
|
}
|
||||||
|
|
||||||
|
ask_secret() {
|
||||||
|
echo -ne "${YELLOW} ➜ ${NC}${1}: "
|
||||||
|
read -rs REPLY; echo
|
||||||
|
}
|
||||||
|
|
||||||
|
confirm() {
|
||||||
|
echo -ne "${YELLOW} ➜ ${NC}${1} [${CYAN}j${NC}/N]: "
|
||||||
|
read -r ans; [[ "$ans" =~ ^[jJyY]$ ]]
|
||||||
|
}
|
||||||
|
|
||||||
# ── Banner ─────────────────────────────────────────────────────────────────────
|
# ── Banner ─────────────────────────────────────────────────────────────────────
|
||||||
print_banner() {
|
print_banner() {
|
||||||
@@ -32,160 +51,373 @@ print_banner() {
|
|||||||
NordVPN Addon – Proxmox Host Installer
|
NordVPN Addon – Proxmox Host Installer
|
||||||
BANNER
|
BANNER
|
||||||
echo -e "${NC}"
|
echo -e "${NC}"
|
||||||
echo -e " ${CYAN}Richtet TUN-Device ein und startet NordVPN-Setup im LXC${NC}\n"
|
echo -e " ${CYAN}Richtet TUN + Gluetun/NordVPN vollautomatisch ein${NC}"
|
||||||
|
echo -e " ${CYAN}Quelle: git.obraasch.de/olli1986/freqtrade-proxmox-deploy${NC}\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Proxmox-Check ──────────────────────────────────────────────────────────────
|
# ── Proxmox-Check ──────────────────────────────────────────────────────────────
|
||||||
check_host() {
|
check_host() {
|
||||||
|
step "Proxmox Host prüfen"
|
||||||
[[ $EUID -ne 0 ]] && error "Bitte als root ausführen!"
|
[[ $EUID -ne 0 ]] && error "Bitte als root ausführen!"
|
||||||
command -v pct &>/dev/null || error "pct nicht gefunden – läuft das auf Proxmox?"
|
command -v pct &>/dev/null || error "pct nicht gefunden – läuft das auf Proxmox?"
|
||||||
|
command -v pvesh &>/dev/null || error "pvesh nicht gefunden."
|
||||||
success "Proxmox Host erkannt"
|
success "Proxmox Host erkannt"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Container-Auswahl ─────────────────────────────────────────────────────────
|
# ── Container-Auswahl ─────────────────────────────────────────────────────────
|
||||||
select_container() {
|
select_container() {
|
||||||
step "Freqtrade Container suchen"
|
step "Freqtrade Container auswählen"
|
||||||
|
|
||||||
# Alle laufenden Container mit Tag "freqtrade" finden
|
# Alle Container auflisten mit Tag-Info
|
||||||
mapfile -t TAGGED_IDS < <(
|
local -a ct_list=()
|
||||||
pct list 2>/dev/null | awk 'NR>1{print $1}' | while read -r id; do
|
while IFS= read -r line; do
|
||||||
tags=$(pct config "$id" 2>/dev/null | grep '^tags:' | sed 's/tags: *//' || true)
|
local ct_id status
|
||||||
if echo "$tags" | grep -qi "freqtrade"; then
|
ct_id=$(echo "$line" | awk '{print $1}')
|
||||||
name=$(pct config "$id" 2>/dev/null | grep '^hostname:' | awk '{print $2}' || echo "?")
|
status=$(echo "$line" | awk '{print $2}')
|
||||||
status=$(pct list 2>/dev/null | awk -v id="$id" '$1==id{print $2}')
|
[[ "$ct_id" =~ ^[0-9]+$ ]] || continue
|
||||||
echo "${id}|${name}|${status}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
)
|
|
||||||
|
|
||||||
# Auch ungetaggte Container mit Hostname "freqtrade" als Fallback
|
local hostname tags marker=""
|
||||||
mapfile -t HOSTNAME_IDS < <(
|
hostname=$(pct config "$ct_id" 2>/dev/null | awk '/^hostname:/{print $2}' || echo "?")
|
||||||
pct list 2>/dev/null | awk 'NR>1{print $1}' | while read -r id; do
|
tags=$(pct config "$ct_id" 2>/dev/null | awk '/^tags:/{print $2}' || echo "")
|
||||||
hostname=$(pct config "$id" 2>/dev/null | grep '^hostname:' | awk '{print $2}' || true)
|
|
||||||
tags=$(pct config "$id" 2>/dev/null | grep '^tags:' | sed 's/tags: *//' || true)
|
|
||||||
if echo "$hostname" | grep -qi "freqtrade" && ! echo "$tags" | grep -qi "freqtrade"; then
|
|
||||||
status=$(pct list 2>/dev/null | awk -v id="$id" '$1==id{print $2}')
|
|
||||||
echo "${id}|${hostname}|${status} (kein Tag)"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
)
|
|
||||||
|
|
||||||
ALL_IDS=("${TAGGED_IDS[@]}" "${HOSTNAME_IDS[@]}")
|
# Freqtrade-Container markieren
|
||||||
|
if echo "$tags" | grep -qi "freqtrade"; then
|
||||||
if [[ ${#ALL_IDS[@]} -eq 0 ]]; then
|
marker="${GREEN}★${NC}"
|
||||||
warn "Keine Freqtrade-Container gefunden (Tag 'freqtrade' oder Hostname 'freqtrade*')"
|
|
||||||
echo
|
|
||||||
echo -e " Alle verfügbaren Container:"
|
|
||||||
pct list 2>/dev/null | awk 'NR==1{printf " %-8s %-12s %s\n",$1,$2,$3} NR>1{printf " %-8s %-12s %s\n",$1,$2,$3}'
|
|
||||||
echo
|
|
||||||
echo -ne "${YELLOW} ➜ ${NC}Container-ID manuell eingeben: "
|
|
||||||
read -r SEL_ID
|
|
||||||
SEL_NAME=$(pct config "$SEL_ID" 2>/dev/null | grep '^hostname:' | awk '{print $2}' || echo "unbekannt")
|
|
||||||
SEL_STATUS=$(pct list 2>/dev/null | awk -v id="$SEL_ID" '$1==id{print $2}')
|
|
||||||
elif [[ ${#ALL_IDS[@]} -eq 1 ]]; then
|
|
||||||
# Genau einer gefunden → direkt nehmen
|
|
||||||
IFS='|' read -r SEL_ID SEL_NAME SEL_STATUS <<< "${ALL_IDS[0]}"
|
|
||||||
echo -e " ${GREEN}Gefunden:${NC} CT ${CYAN}${SEL_ID}${NC} | ${CYAN}${SEL_NAME}${NC} | ${SEL_STATUS}"
|
|
||||||
else
|
|
||||||
# Mehrere → Auswahl anzeigen
|
|
||||||
echo -e " ${CYAN}Gefundene Freqtrade-Container:${NC}\n"
|
|
||||||
echo -e " ${BOLD}Nr ID Hostname Status${NC}"
|
|
||||||
echo -e " ${BLUE}────────────────────────────────────${NC}"
|
|
||||||
local i=1
|
|
||||||
for entry in "${ALL_IDS[@]}"; do
|
|
||||||
IFS='|' read -r cid cname cstatus <<< "$entry"
|
|
||||||
printf " ${CYAN}%-4s${NC} %-8s %-16s %s\n" "$i" "$cid" "$cname" "$cstatus"
|
|
||||||
((i++))
|
|
||||||
done
|
|
||||||
echo
|
|
||||||
echo -ne "${YELLOW} ➜ ${NC}Nummer auswählen [1]: "
|
|
||||||
read -r sel_nr
|
|
||||||
sel_nr="${sel_nr:-1}"
|
|
||||||
IFS='|' read -r SEL_ID SEL_NAME SEL_STATUS <<< "${ALL_IDS[$((sel_nr-1))]}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
[[ -z "${SEL_ID:-}" ]] && error "Keine Container-ID gewählt!"
|
|
||||||
|
|
||||||
# Status-Check
|
|
||||||
local cur_status
|
|
||||||
cur_status=$(pct list 2>/dev/null | awk -v id="$SEL_ID" '$1==id{print $2}' || echo "unknown")
|
|
||||||
if [[ "$cur_status" != "running" ]]; then
|
|
||||||
warn "Container $SEL_ID ist nicht running (Status: $cur_status)"
|
|
||||||
echo -ne "${YELLOW} ➜ ${NC}Container starten? [j/N]: "
|
|
||||||
read -r ans
|
|
||||||
if [[ "$ans" =~ ^[jJyY]$ ]]; then
|
|
||||||
pct start "$SEL_ID"
|
|
||||||
sleep 5
|
|
||||||
success "Container gestartet"
|
|
||||||
else
|
else
|
||||||
error "Container muss laufen für die Installation!"
|
marker=" "
|
||||||
fi
|
fi
|
||||||
|
ct_list+=("${ct_id}|${hostname}|${status}|${marker}")
|
||||||
|
done < <(pct list 2>/dev/null | tail -n +2)
|
||||||
|
|
||||||
|
if [[ ${#ct_list[@]} -eq 0 ]]; then
|
||||||
|
error "Keine Container gefunden!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
success "Gewählt: CT ${SEL_ID} | ${SEL_NAME}"
|
# Nur Container mit Tag "freqtrade" anzeigen
|
||||||
|
local -a display_list=()
|
||||||
|
for entry in "${ct_list[@]}"; do
|
||||||
|
if echo "$entry" | grep -q "★"; then
|
||||||
|
display_list+=("$entry")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ${#display_list[@]} -eq 0 ]]; then
|
||||||
|
error "Keine Container mit Tag 'freqtrade' gefunden!\n Bitte zuerst freqtrade-lxc-install.sh ausführen oder manuell setzen:\n pct set <ID> --tags freqtrade"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e " ${BOLD}Nr ID Hostname Status ${GREEN}★${NC}${BOLD} = Freqtrade${NC}"
|
||||||
|
echo -e " ${BLUE}─────────────────────────────────────────${NC}"
|
||||||
|
local i=1
|
||||||
|
for entry in "${display_list[@]}"; do
|
||||||
|
IFS='|' read -r cid cname cstatus cmark <<< "$entry"
|
||||||
|
printf " ${CYAN}%-4s${NC} %-8s %-18s %-10s %b\n" "$i" "$cid" "$cname" "$cstatus" "$cmark"
|
||||||
|
((i++))
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
|
||||||
|
local sel_nr=1
|
||||||
|
if [[ ${#display_list[@]} -gt 1 ]]; then
|
||||||
|
ask "Container Nummer wählen" "1"
|
||||||
|
sel_nr="$REPLY"
|
||||||
|
else
|
||||||
|
info "Nur ein Container vorhanden – wird automatisch gewählt."
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS='|' read -r SEL_ID SEL_NAME SEL_STATUS _ <<< "${display_list[$((sel_nr-1))]}"
|
||||||
|
[[ -z "${SEL_ID:-}" ]] && error "Ungültige Auswahl!"
|
||||||
|
|
||||||
|
success "Gewählt: CT ${SEL_ID} | ${SEL_NAME} | ${SEL_STATUS}"
|
||||||
|
|
||||||
|
# Starten falls nötig
|
||||||
|
if [[ "$SEL_STATUS" != "running" ]]; then
|
||||||
|
warn "Container ist nicht running. Starte..."
|
||||||
|
pct start "$SEL_ID"
|
||||||
|
sleep 5
|
||||||
|
success "Container gestartet"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── TUN-Device einrichten ──────────────────────────────────────────────────────
|
# ── TUN-Device einrichten ──────────────────────────────────────────────────────
|
||||||
setup_tun() {
|
setup_tun() {
|
||||||
step "TUN-Device für CT ${SEL_ID} prüfen"
|
step "TUN-Device für CT ${SEL_ID} prüfen"
|
||||||
|
|
||||||
local conf="/etc/pve/lxc/${SEL_ID}.conf"
|
local conf="/etc/pve/lxc/${SEL_ID}.conf"
|
||||||
[[ ! -f "$conf" ]] && error "LXC-Config nicht gefunden: $conf"
|
[[ ! -f "$conf" ]] && error "LXC-Config nicht gefunden: $conf"
|
||||||
|
|
||||||
local tun_ok=true
|
if grep -q "lxc.cgroup2.devices.allow: c 10:200 rwm" "$conf" && \
|
||||||
grep -q "lxc.cgroup2.devices.allow: c 10:200 rwm" "$conf" || tun_ok=false
|
grep -q "lxc.mount.entry: /dev/net/tun" "$conf"; then
|
||||||
grep -q "lxc.mount.entry: /dev/net/tun" "$conf" || tun_ok=false
|
|
||||||
|
|
||||||
if [[ "$tun_ok" == "true" ]]; then
|
|
||||||
success "TUN-Device bereits konfiguriert"
|
success "TUN-Device bereits konfiguriert"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
info "TUN-Device Zeilen fehlen – trage ein..."
|
info "Trage TUN-Device in Config ein und starte Container neu..."
|
||||||
cat >> "$conf" << 'TUNCFG'
|
cat >> "$conf" << 'TUNCFG'
|
||||||
# TUN-Device fuer NordVPN/Gluetun (eingetragen von proxmox-vpn-install.sh)
|
# TUN-Device fuer NordVPN/Gluetun (eingetragen von proxmox-vpn-install.sh)
|
||||||
lxc.cgroup2.devices.allow: c 10:200 rwm
|
lxc.cgroup2.devices.allow: c 10:200 rwm
|
||||||
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
|
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
|
||||||
TUNCFG
|
TUNCFG
|
||||||
success "TUN-Device in $conf eingetragen"
|
|
||||||
|
|
||||||
# Container neu starten damit die Config greift
|
pct stop "$SEL_ID"
|
||||||
info "Container neu starten damit TUN-Device aktiv wird..."
|
|
||||||
pct stop "$SEL_ID"
|
|
||||||
sleep 3
|
sleep 3
|
||||||
pct start "$SEL_ID"
|
pct start "$SEL_ID"
|
||||||
sleep 5
|
|
||||||
|
|
||||||
# Warten auf Netzwerk
|
|
||||||
local tries=0
|
local tries=0
|
||||||
|
info "Warte auf Netzwerk..."
|
||||||
until pct exec "$SEL_ID" -- bash -c "ip route | grep -q default" 2>/dev/null; do
|
until pct exec "$SEL_ID" -- bash -c "ip route | grep -q default" 2>/dev/null; do
|
||||||
sleep 3; tries=$((tries+1)); echo -n "."
|
sleep 3; tries=$((tries+1)); echo -n "."
|
||||||
[[ $tries -ge 15 ]] && error "Netzwerk nach Neustart nicht erreichbar!"
|
[[ $tries -ge 15 ]] && error "Netzwerk nach Neustart nicht erreichbar!"
|
||||||
done
|
done
|
||||||
echo
|
echo
|
||||||
success "Container läuft wieder mit TUN-Device"
|
success "Container neu gestartet mit TUN-Device"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── install-vpn.sh im Container ausführen ─────────────────────────────────────
|
# ── NordVPN Konfiguration abfragen ─────────────────────────────────────────────
|
||||||
run_vpn_install() {
|
collect_vpn_config() {
|
||||||
step "NordVPN-Setup im Container starten"
|
step "NordVPN Konfiguration"
|
||||||
echo -e "\n ${YELLOW}Das install-vpn.sh Script läuft jetzt interaktiv im Container.${NC}"
|
echo -e "\n ${BOLD}Service-Credentials${NC} findest du unter:"
|
||||||
echo -e " ${YELLOW}Du wirst nach deinen NordVPN Service-Credentials gefragt.${NC}\n"
|
echo -e " ${CYAN}https://my.nordaccount.com → NordVPN → 'Set up NordVPN manually'${NC}"
|
||||||
echo -e " Service-Credentials: ${CYAN}https://my.nordaccount.com${NC}"
|
echo -e " ${RED} Nicht deine E-Mail/Passwort – die Service-Credentials!${NC}\n"
|
||||||
echo -e " ${CYAN}→ NordVPN → 'Set up NordVPN manually'${NC}\n"
|
|
||||||
|
|
||||||
echo -ne "${YELLOW} ➜ ${NC}Jetzt starten? [j/N]: "
|
ask "NordVPN Service-Username"
|
||||||
read -r ans
|
NORD_USER="$REPLY"
|
||||||
[[ ! "$ans" =~ ^[jJyY]$ ]] && { info "Abgebrochen. Manuell starten mit:\n pct enter ${SEL_ID} dann: bash -c \"\$(curl -fsSL ${VPN_SCRIPT_URL})\""; exit 0; }
|
[[ -z "$NORD_USER" ]] && error "Username darf nicht leer sein!"
|
||||||
|
|
||||||
|
ask_secret "NordVPN Service-Passwort"
|
||||||
|
NORD_PASS="$REPLY"
|
||||||
|
[[ -z "$NORD_PASS" ]] && error "Passwort darf nicht leer sein!"
|
||||||
|
|
||||||
# Script in Container laden und interaktiv ausführen
|
|
||||||
info "Lade install-vpn.sh in Container..."
|
|
||||||
pct exec "$SEL_ID" -- bash -c "curl -fsSL '${VPN_SCRIPT_URL}' -o /root/install-vpn.sh && chmod +x /root/install-vpn.sh"
|
|
||||||
success "Script geladen – starte interaktive Session im Container..."
|
|
||||||
echo
|
echo
|
||||||
echo -e "${BOLD}${BLUE}──── Container ${SEL_ID} – NordVPN Setup ────${NC}"
|
echo -e " ${BOLD}VPN-Server Modus:${NC}"
|
||||||
# pct enter öffnet eine echte interaktive Shell → Script direkt übergeben
|
echo -e " ${CYAN}1)${NC} Serverland – normaler Server (IP kann wechseln)"
|
||||||
pct exec "$SEL_ID" -- bash /root/install-vpn.sh
|
echo -e " ${CYAN}2)${NC} Hostname – Dedicated-IP oder spez. Server pinnen"
|
||||||
|
ask "Auswahl [1/2]" "1"
|
||||||
|
VPN_MODE="$REPLY"
|
||||||
|
|
||||||
|
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}"
|
||||||
|
ask "Hostname (z.B. de507.nordvpn.com)"
|
||||||
|
VPN_HOSTNAME="$REPLY"; VPN_COUNTRY=""
|
||||||
|
else
|
||||||
|
ask "Serverland" "Germany"
|
||||||
|
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"
|
||||||
|
|
||||||
|
echo -e "\n${BOLD}${BLUE}══════════ Zusammenfassung ══════════${NC}"
|
||||||
|
echo -e " Container: ${CYAN}CT ${SEL_ID} | ${SEL_NAME}${NC}"
|
||||||
|
echo -e " NordVPN User: ${CYAN}${NORD_USER}${NC}"
|
||||||
|
[[ -n "$VPN_HOSTNAME" ]] \
|
||||||
|
&& echo -e " VPN Server: ${CYAN}${VPN_HOSTNAME}${NC}" \
|
||||||
|
|| echo -e " VPN Land: ${CYAN}${VPN_COUNTRY}${NC}"
|
||||||
|
echo -e " FreqUI Port: ${CYAN}${FT_PORT}${NC}"
|
||||||
|
echo -e "${BOLD}${BLUE}=====================================\n${NC}"
|
||||||
|
confirm "Einrichten?" || { info "Abgebrochen."; exit 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Konfiguration in Container schreiben ──────────────────────────────────────
|
||||||
|
write_vpn_config() {
|
||||||
|
step "VPN-Konfiguration in Container schreiben"
|
||||||
|
|
||||||
|
local FT_DIR="/opt/docker-projekte/freqtrade"
|
||||||
|
local NORD_USER_B64 NORD_PASS_B64
|
||||||
|
NORD_USER_B64=$(printf '%s' "$NORD_USER" | base64 -w0)
|
||||||
|
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}"
|
||||||
|
|
||||||
|
# Backup
|
||||||
|
pct exec "$SEL_ID" -- bash -c \
|
||||||
|
"cp ${FT_DIR}/docker-compose.yml ${FT_DIR}/docker-compose.yml.bak-\$(date +%Y%m%d_%H%M%S) 2>/dev/null || true"
|
||||||
|
success "Backup erstellt"
|
||||||
|
|
||||||
|
# Stack stoppen
|
||||||
|
pct exec "$SEL_ID" -- bash -c \
|
||||||
|
"cd ${FT_DIR} && docker compose down 2>/dev/null || true"
|
||||||
|
success "Stack gestoppt"
|
||||||
|
|
||||||
|
# .env schreiben
|
||||||
|
pct exec "$SEL_ID" -- bash -c "
|
||||||
|
echo \"OPENVPN_USER=\$(echo ${NORD_USER_B64} | base64 -d)\" > ${FT_DIR}/.env
|
||||||
|
echo \"OPENVPN_PASSWORD=\$(echo ${NORD_PASS_B64} | base64 -d)\" >> ${FT_DIR}/.env
|
||||||
|
chmod 600 ${FT_DIR}/.env
|
||||||
|
"
|
||||||
|
success ".env geschrieben (chmod 600)"
|
||||||
|
|
||||||
|
# docker-compose.yml schreiben
|
||||||
|
pct exec "$SEL_ID" -- bash -c "cat > ${FT_DIR}/docker-compose.yml << 'COMPOSEEOF'
|
||||||
|
# Freqtrade + NordVPN/Gluetun | generiert von proxmox-vpn-install.sh
|
||||||
|
# Netzwerk: [Freqtrade] -> [Gluetun] -> NordVPN -> Internet
|
||||||
|
# WebUI: http://LXC-IP:${FT_PORT}
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
gluetun:
|
||||||
|
image: qmcgaw/gluetun:latest
|
||||||
|
container_name: gluetun
|
||||||
|
restart: unless-stopped
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
devices:
|
||||||
|
- /dev/net/tun:/dev/net/tun
|
||||||
|
environment:
|
||||||
|
- VPN_SERVICE_PROVIDER=nordvpn
|
||||||
|
- VPN_TYPE=openvpn
|
||||||
|
- OPENVPN_USER=\${OPENVPN_USER}
|
||||||
|
- OPENVPN_PASSWORD=\${OPENVPN_PASSWORD}
|
||||||
|
${VPN_SERVER_LINE}
|
||||||
|
ports:
|
||||||
|
- \"0.0.0.0:${FT_PORT}:8080\"
|
||||||
|
volumes:
|
||||||
|
- gluetun_data:/gluetun
|
||||||
|
healthcheck:
|
||||||
|
test: [\"CMD-SHELL\", \"wget -qO- https://ipinfo.io/ip || exit 1\"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 15s
|
||||||
|
retries: 5
|
||||||
|
start_period: 45s
|
||||||
|
|
||||||
|
freqtrade:
|
||||||
|
image: freqtradeorg/freqtrade:stable
|
||||||
|
restart: unless-stopped
|
||||||
|
container_name: freqtrade
|
||||||
|
network_mode: \"container:gluetun\"
|
||||||
|
depends_on:
|
||||||
|
gluetun:
|
||||||
|
condition: service_healthy
|
||||||
|
volumes:
|
||||||
|
- \"./user_data:/freqtrade/user_data\"
|
||||||
|
command: >
|
||||||
|
trade
|
||||||
|
--logfile /freqtrade/user_data/logs/freqtrade.log
|
||||||
|
--db-url sqlite:////freqtrade/user_data/tradesv3.sqlite
|
||||||
|
--config /freqtrade/user_data/config.json
|
||||||
|
--strategy SampleStrategy
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
gluetun_data:
|
||||||
|
COMPOSEEOF"
|
||||||
|
success "docker-compose.yml geschrieben"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Stack starten mit Fehlerbehandlung ─────────────────────────────────────────
|
||||||
|
start_and_verify() {
|
||||||
|
step "VPN-Stack starten"
|
||||||
|
|
||||||
|
local FT_DIR="/opt/docker-projekte/freqtrade"
|
||||||
|
local MAX_ATTEMPTS=3
|
||||||
|
local attempt=1
|
||||||
|
|
||||||
|
while [[ $attempt -le $MAX_ATTEMPTS ]]; do
|
||||||
|
echo -e "\n ${CYAN}Versuch ${attempt}/${MAX_ATTEMPTS}...${NC}"
|
||||||
|
|
||||||
|
# Stack starten
|
||||||
|
pct exec "$SEL_ID" -- bash -c "cd ${FT_DIR} && docker compose up -d 2>&1" || true
|
||||||
|
|
||||||
|
# Auf Gluetun warten (bis zu 60s)
|
||||||
|
info "Warte auf VPN-Verbindung (bis zu 60s)..."
|
||||||
|
local tries=0
|
||||||
|
local vpn_ok=false
|
||||||
|
while [[ $tries -lt 12 ]]; do
|
||||||
|
sleep 5; echo -n "."; tries=$((tries+1))
|
||||||
|
if pct exec "$SEL_ID" -- bash -c \
|
||||||
|
"docker exec gluetun wget -qO- https://ipinfo.io/ip 2>/dev/null" &>/dev/null; then
|
||||||
|
vpn_ok=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [[ "$vpn_ok" == "true" ]]; then
|
||||||
|
VPN_IP=$(pct exec "$SEL_ID" -- bash -c \
|
||||||
|
"docker exec gluetun wget -qO- https://ipinfo.io/ip 2>/dev/null" || echo "unbekannt")
|
||||||
|
success "VPN verbunden! Ausgehende IP: ${BOLD}${GREEN}${VPN_IP}${NC}"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fehleranalyse
|
||||||
|
echo
|
||||||
|
warn "VPN-Verbindung fehlgeschlagen. Gluetun-Log:"
|
||||||
|
echo -e "${YELLOW}─────────────────────────────────────────${NC}"
|
||||||
|
pct exec "$SEL_ID" -- bash -c \
|
||||||
|
"docker logs gluetun 2>&1 | grep -E 'ERROR|WARN|hostname|credentials|password|Invalid' | tail -20" \
|
||||||
|
2>/dev/null || true
|
||||||
|
echo -e "${YELLOW}─────────────────────────────────────────${NC}"
|
||||||
|
|
||||||
|
# Häufige Fehler erkennen und erklären
|
||||||
|
local gluetun_errors
|
||||||
|
gluetun_errors=$(pct exec "$SEL_ID" -- bash -c \
|
||||||
|
"docker logs gluetun 2>&1 | tail -30" 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
if echo "$gluetun_errors" | grep -qi "hostname.*not valid\|not one of the possible choices"; then
|
||||||
|
echo -e "\n ${RED}FEHLER: Ungültiger Hostname!${NC}"
|
||||||
|
echo -e " ${YELLOW}Gültige deutsche Server haben das Format: de507.nordvpn.com${NC}"
|
||||||
|
echo -e " ${YELLOW}Sieh die Fehlermeldung für eine Liste gültiger Hostnamen.${NC}"
|
||||||
|
elif echo "$gluetun_errors" | grep -qi "auth\|credential\|password\|unauthorized\|401"; then
|
||||||
|
echo -e "\n ${RED}FEHLER: Ungültige Credentials!${NC}"
|
||||||
|
echo -e " ${YELLOW}Bitte Service-Credentials prüfen unter:${NC}"
|
||||||
|
echo -e " ${CYAN}https://my.nordaccount.com → NordVPN → Set up NordVPN manually${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
pct exec "$SEL_ID" -- bash -c "cd ${FT_DIR} && docker compose down 2>/dev/null || true"
|
||||||
|
|
||||||
|
if [[ $attempt -lt $MAX_ATTEMPTS ]]; then
|
||||||
|
echo
|
||||||
|
if confirm "Andere Konfiguration versuchen?"; then
|
||||||
|
collect_vpn_config
|
||||||
|
write_vpn_config
|
||||||
|
else
|
||||||
|
error "Abgebrochen. Stack wurde gestoppt."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
attempt=$((attempt+1))
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ "$vpn_ok" != "true" ]] && error "VPN konnte nach ${MAX_ATTEMPTS} Versuchen nicht verbunden werden."
|
||||||
|
|
||||||
|
# Freqtrade prüfen
|
||||||
|
sleep 6
|
||||||
|
if pct exec "$SEL_ID" -- bash -c \
|
||||||
|
"docker ps --filter name=freqtrade --filter status=running | grep -q freqtrade" 2>/dev/null; then
|
||||||
|
success "Freqtrade läuft"
|
||||||
|
else
|
||||||
|
warn "Freqtrade prüfen: pct exec ${SEL_ID} -- docker logs freqtrade"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Ergebnis anzeigen ──────────────────────────────────────────────────────────
|
||||||
|
show_result() {
|
||||||
|
local LXC_IP
|
||||||
|
LXC_IP=$(pct exec "$SEL_ID" -- hostname -I 2>/dev/null | awk '{print $1}' || echo "unbekannt")
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "${BOLD}${GREEN}╔══════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${BOLD}${GREEN}║ ✅ NordVPN erfolgreich eingerichtet! ║${NC}"
|
||||||
|
echo -e "${BOLD}${GREEN}╚══════════════════════════════════════════╝${NC}"
|
||||||
|
echo
|
||||||
|
echo -e " ${BOLD}FreqUI:${NC} ${CYAN}http://${LXC_IP}:${FT_PORT}${NC}"
|
||||||
|
echo -e " ${BOLD}NordVPN IP:${NC} ${BOLD}${GREEN}${VPN_IP}${NC}"
|
||||||
|
echo
|
||||||
|
echo -e " ${BOLD}${YELLOW}⚠ Binance API-Key anpassen:${NC}"
|
||||||
|
echo -e " ${YELLOW}Binance → API Management → IP-Beschränkung${NC}"
|
||||||
|
echo -e " ${YELLOW}Die NordVPN-IP eintragen: ${BOLD}${VPN_IP}${NC}"
|
||||||
|
echo
|
||||||
|
echo -e " ${BOLD}Nützliche Befehle (im LXC: pct enter ${SEL_ID}):${NC}"
|
||||||
|
echo -e " ${CYAN}docker exec gluetun wget -qO- https://ipinfo.io/ip${NC} # VPN-IP prüfen"
|
||||||
|
echo -e " ${CYAN}docker logs gluetun${NC} # VPN-Logs"
|
||||||
|
echo -e " ${CYAN}docker logs freqtrade${NC} # Freqtrade-Logs"
|
||||||
|
echo -e " ${CYAN}cd /opt/docker-projekte/freqtrade && docker compose restart${NC}"
|
||||||
|
echo
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Hauptprogramm ──────────────────────────────────────────────────────────────
|
# ── Hauptprogramm ──────────────────────────────────────────────────────────────
|
||||||
@@ -194,7 +426,10 @@ main() {
|
|||||||
check_host
|
check_host
|
||||||
select_container
|
select_container
|
||||||
setup_tun
|
setup_tun
|
||||||
run_vpn_install
|
collect_vpn_config
|
||||||
|
write_vpn_config
|
||||||
|
start_and_verify
|
||||||
|
show_result
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|||||||
Reference in New Issue
Block a user