Files
freqtrade-proxmox-deploy/scripts/proxmox-vpn-install.sh
T

201 lines
8.5 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# =============================================================================
# Freqtrade NordVPN Addon Proxmox Host Installer
# Erkennt Freqtrade-Container automatisch per Tag, richtet TUN-Device ein
# und startet install-vpn.sh im Container.
#
# Läuft auf dem PROXMOX HOST.
# Quelle: https://git.obraasch.de/olli1986/freqtrade-proxmox-deploy
# =============================================================================
set -euo pipefail
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
BLUE='\033[0;34m'; CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
info() { echo -e "${CYAN}[INFO]${NC} $*"; }
success() { echo -e "${GREEN}[ OK ]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[FAIL]${NC} $*"; exit 1; }
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"
# ── Banner ─────────────────────────────────────────────────────────────────────
print_banner() {
clear
echo -e "${BOLD}${BLUE}"
cat << 'BANNER'
_ _ _ _ ___ _ _
| \| |___ _ _ __| \ \ / / | \| |
| .` / _ \ '_/ _` \ V /| | .` |
|_|\_\___/_| \__,_|\_/ |_|_|\_|
NordVPN Addon Proxmox Host Installer
BANNER
echo -e "${NC}"
echo -e " ${CYAN}Richtet TUN-Device ein und startet NordVPN-Setup im LXC${NC}\n"
}
# ── Proxmox-Check ──────────────────────────────────────────────────────────────
check_host() {
[[ $EUID -ne 0 ]] && error "Bitte als root ausführen!"
command -v pct &>/dev/null || error "pct nicht gefunden läuft das auf Proxmox?"
success "Proxmox Host erkannt"
}
# ── Container-Auswahl ─────────────────────────────────────────────────────────
select_container() {
step "Freqtrade Container suchen"
# Alle laufenden Container mit Tag "freqtrade" finden
mapfile -t TAGGED_IDS < <(
pct list 2>/dev/null | awk 'NR>1{print $1}' | while read -r id; do
tags=$(pct config "$id" 2>/dev/null | grep '^tags:' | sed 's/tags: *//' || true)
if echo "$tags" | grep -qi "freqtrade"; then
name=$(pct config "$id" 2>/dev/null | grep '^hostname:' | awk '{print $2}' || echo "?")
status=$(pct list 2>/dev/null | awk -v id="$id" '$1==id{print $2}')
echo "${id}|${name}|${status}"
fi
done
)
# Auch ungetaggte Container mit Hostname "freqtrade" als Fallback
mapfile -t HOSTNAME_IDS < <(
pct list 2>/dev/null | awk 'NR>1{print $1}' | while read -r id; do
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[@]}")
if [[ ${#ALL_IDS[@]} -eq 0 ]]; then
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
error "Container muss laufen für die Installation!"
fi
fi
success "Gewählt: CT ${SEL_ID} | ${SEL_NAME}"
}
# ── TUN-Device einrichten ──────────────────────────────────────────────────────
setup_tun() {
step "TUN-Device für CT ${SEL_ID} prüfen"
local conf="/etc/pve/lxc/${SEL_ID}.conf"
[[ ! -f "$conf" ]] && error "LXC-Config nicht gefunden: $conf"
local tun_ok=true
grep -q "lxc.cgroup2.devices.allow: c 10:200 rwm" "$conf" || tun_ok=false
grep -q "lxc.mount.entry: /dev/net/tun" "$conf" || tun_ok=false
if [[ "$tun_ok" == "true" ]]; then
success "TUN-Device bereits konfiguriert"
return
fi
info "TUN-Device Zeilen fehlen trage ein..."
cat >> "$conf" << 'TUNCFG'
# TUN-Device fuer NordVPN/Gluetun (eingetragen von proxmox-vpn-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 $conf eingetragen"
# Container neu starten damit die Config greift
info "Container neu starten damit TUN-Device aktiv wird..."
pct stop "$SEL_ID"
sleep 3
pct start "$SEL_ID"
sleep 5
# Warten auf Netzwerk
local tries=0
until pct exec "$SEL_ID" -- bash -c "ip route | grep -q default" 2>/dev/null; do
sleep 3; tries=$((tries+1)); echo -n "."
[[ $tries -ge 15 ]] && error "Netzwerk nach Neustart nicht erreichbar!"
done
echo
success "Container läuft wieder mit TUN-Device"
}
# ── install-vpn.sh im Container ausführen ─────────────────────────────────────
run_vpn_install() {
step "NordVPN-Setup im Container starten"
echo -e "\n ${YELLOW}Das install-vpn.sh Script läuft jetzt interaktiv im Container.${NC}"
echo -e " ${YELLOW}Du wirst nach deinen NordVPN Service-Credentials gefragt.${NC}\n"
echo -e " Service-Credentials: ${CYAN}https://my.nordaccount.com${NC}"
echo -e " ${CYAN}→ NordVPN → 'Set up NordVPN manually'${NC}\n"
echo -ne "${YELLOW}${NC}Jetzt starten? [j/N]: "
read -r ans
[[ ! "$ans" =~ ^[jJyY]$ ]] && { info "Abgebrochen. Manuell starten mit:\n pct enter ${SEL_ID} dann: bash -c \"\$(curl -fsSL ${VPN_SCRIPT_URL})\""; exit 0; }
# 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 -e "${BOLD}${BLUE}──── Container ${SEL_ID} NordVPN Setup ────${NC}"
# pct enter öffnet eine echte interaktive Shell → Script direkt übergeben
pct exec "$SEL_ID" -- bash /root/install-vpn.sh
}
# ── Hauptprogramm ──────────────────────────────────────────────────────────────
main() {
print_banner
check_host
select_container
setup_tun
run_vpn_install
}
main "$@"