Dateien nach "scripts" hochladen

This commit is contained in:
2026-04-22 13:03:16 +02:00
parent e518420194
commit d51a612764
+56 -137
View File
@@ -1,13 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# ============================================================================= # =============================================================================
# Freqtrade NordVPN Addon Proxmox Host Installer (Custom Config Edition) # Freqtrade NordVPN Addon Proxmox Host Installer (Custom Config Edition)
# Läuft komplett auf dem PROXMOX HOST. # Ablauf: System -> Ordner -> Filebrowser -> User-Input -> VPN-Start
# - Richtet TUN-Device ein
# - Erstellt VPN-Ordner & Berechtigungen
# - Fragt NordVPN-Credentials ab & pausiert für custom.conf
# - Ermittelt automatisch das lokale Subnetz
# - Schreibt docker-compose.yml & startet den Stack
# - NEU: Integriert den VPN-Ordner automatisch in den Filebrowser
# ============================================================================= # =============================================================================
set -euo pipefail set -euo pipefail
@@ -33,22 +27,11 @@ confirm() {
read -r ans; [[ "$ans" =~ ^[jJyY]$ ]] read -r ans; [[ "$ans" =~ ^[jJyY]$ ]]
} }
# ── Banner ─────────────────────────────────────────────────────────────────────
print_banner() { print_banner() {
clear clear
echo -e "${BOLD}${BLUE}" echo -e "${BOLD}${BLUE} NordVPN Custom Config Installer (Filebrowser-First)${NC}\n"
cat << 'BANNER'
_ _ _ _ ___ _ _
| \| |___ _ _ __| \ \ / / | \| |
| .` / _ \ '_/ _` \ V /| | .` |
|_|\_\___/_| \__,_|\_/ |_|_|\_|
NordVPN Custom Config Installer
BANNER
echo -e "${NC}"
echo -e " ${CYAN}Automatisiertes Setup für feste IPs via custom.conf${NC}\n"
} }
# ── Proxmox-Check ──────────────────────────────────────────────────────────────
check_host() { check_host() {
step "Proxmox Host prüfen" step "Proxmox Host prüfen"
[[ $EUID -ne 0 ]] && error "Bitte als root ausführen!" [[ $EUID -ne 0 ]] && error "Bitte als root ausführen!"
@@ -56,43 +39,28 @@ check_host() {
success "Proxmox Host erkannt" success "Proxmox Host erkannt"
} }
# ── Container-Auswahl ─────────────────────────────────────────────────────────
select_container() { select_container() {
step "Freqtrade Container auswählen" step "Freqtrade Container auswählen"
local -a display_list=() local -a display_list=()
while IFS= read -r line; do while IFS= read -r line; do
local ct_id status hostname tags local ct_id status hostname
ct_id=$(echo "$line" | awk '{print $1}') ct_id=$(echo "$line" | awk '{print $1}')
status=$(echo "$line" | awk '{print $2}') status=$(echo "$line" | awk '{print $2}')
[[ "$ct_id" =~ ^[0-9]+$ ]] || continue [[ "$ct_id" =~ ^[0-9]+$ ]] || continue
hostname=$(pct config "$ct_id" 2>/dev/null | awk '/^hostname:/{print $2}' || echo "?") hostname=$(pct config "$ct_id" 2>/dev/null | awk '/^hostname:/{print $2}' || echo "?")
tags=$(pct config "$ct_id" 2>/dev/null | awk '/^tags:/{print $2}' || echo "") display_list+=("${ct_id}|${hostname}|${status}")
if echo "$tags" | grep -qi "freqtrade"; then
display_list+=("${ct_id}|${hostname}|${status}")
fi
done < <(pct list 2>/dev/null | tail -n +2) done < <(pct list 2>/dev/null | tail -n +2)
[[ ${#display_list[@]} -eq 0 ]] && error "Keine Container mit Tag 'freqtrade' gefunden!" echo -e " ${BOLD}Nr ID Hostname${NC}"
echo -e " ${BOLD}Nr ID Hostname Status${NC}"
echo -e " ${BLUE}─────────────────────────────────────────${NC}"
local i=1 local i=1
for entry in "${display_list[@]}"; do for entry in "${display_list[@]}"; do
IFS='|' read -r cid cname cstatus <<< "$entry" IFS='|' read -r cid cname cstatus <<< "$entry"
printf " ${CYAN}%-4s${NC} %-8s %-18s %-10s\n" "$i" "$cid" "$cname" "$cstatus" printf " ${CYAN}%-4s${NC} %-8s %-18s\n" "$i" "$cid" "$cname"
((i++)) ((i++))
done done
echo echo
ask "Container Nummer wählen" "1"; local sel_nr="$REPLY"
local sel_nr=1
[[ ${#display_list[@]} -gt 1 ]] && { ask "Container Nummer wählen" "1"; sel_nr="$REPLY"; }
IFS='|' read -r SEL_ID SEL_NAME SEL_STATUS <<< "${display_list[$((sel_nr-1))]}" 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}"
if [[ "$SEL_STATUS" != "running" ]]; then if [[ "$SEL_STATUS" != "running" ]]; then
info "Starte Container..." info "Starte Container..."
@@ -100,86 +68,83 @@ select_container() {
fi fi
} }
# ── TUN-Device & Ordner einrichten ───────────────────────────────────────────── setup_base_system() {
setup_system() { step "Grundsystem & VPN-Ordner vorbereiten"
step "System & VPN-Ordner vorbereiten"
# 1. TUN-Device in LXC Config schreiben # TUN-Device in LXC Config
local conf="/etc/pve/lxc/${SEL_ID}.conf" local conf="/etc/pve/lxc/${SEL_ID}.conf"
if ! grep -q "lxc.mount.entry: /dev/net/tun" "$conf"; then if ! grep -q "lxc.mount.entry: /dev/net/tun" "$conf"; then
info "Trage TUN-Device in Config ein..." info "Konfiguriere TUN-Device..."
cat >> "$conf" << 'TUNCFG' cat >> "$conf" << 'TUNCFG'
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
pct stop "$SEL_ID" && sleep 3 && pct start "$SEL_ID" pct stop "$SEL_ID" && sleep 2 && pct start "$SEL_ID" && sleep 5
sleep 5
success "TUN-Device eingerichtet & Container neu gestartet"
else
success "TUN-Device war bereits konfiguriert"
fi fi
# 2. Ordner und Datei erstellen & Rechte setzen # VPN Ordner erstellen (BEVOR Filebrowser ihn braucht)
pct exec "$SEL_ID" -- bash -c " pct exec "$SEL_ID" -- bash -c "
mkdir -p /opt/docker-projekte/VPN mkdir -p /opt/docker-projekte/VPN
touch /opt/docker-projekte/VPN/custom.conf touch /opt/docker-projekte/VPN/custom.conf
chown 1000:1000 -R /opt/docker-projekte/VPN chown 1000:1000 -R /opt/docker-projekte/VPN
" "
success "VPN-Ordner und custom.conf erstellt (/opt/docker-projekte/VPN)" success "VPN Ordner ist bereit."
} }
# ── Konfiguration abfragen & Datei befüllen lassen ───────────────────────────── update_filebrowser() {
collect_and_wait() { step "Filebrowser Anbindung (Vorbereitung)"
step "NordVPN Credentials & Config" local FB_DIR="/opt/docker-projekte/filebrowser"
local FB_YML="${FB_DIR}/docker-compose.yml"
if pct exec "$SEL_ID" -- bash -c "[ -f ${FB_YML} ]"; then
if ! pct exec "$SEL_ID" -- bash -c "grep -q '/opt/docker-projekte/VPN:/srv/VPN' ${FB_YML}"; then
info "Binde VPN-Ordner in Filebrowser ein..."
pct exec "$SEL_ID" -- bash -c "sed -i '/volumes:/a \\ - /opt/docker-projekte/VPN:/srv/VPN' ${FB_YML}"
pct exec "$SEL_ID" -- bash -c "cd ${FB_DIR} && docker compose down && docker compose up -d"
success "Filebrowser neu gestartet. VPN-Ordner ist jetzt im Web-UI sichtbar!"
else
success "Filebrowser bereits konfiguriert."
fi
else
warn "Filebrowser nicht gefunden. Du musst die custom.conf manuell bearbeiten."
fi
}
collect_and_wait() {
step "Konfiguration & User-Input"
echo -e " ${YELLOW}Hinweis: Bitte nutze die Service-Credentials von der NordVPN-Website!${NC}"
ask "NordVPN Service-Username" ask "NordVPN Service-Username"
NORD_USER="$REPLY" NORD_USER="$REPLY"
ask "NordVPN Service-Passwort" ask "NordVPN Service-Passwort"
NORD_PASS="$REPLY" NORD_PASS="$REPLY"
echo -e "\n${BOLD}${CYAN}=== WICHTIGER SCHRITT ===${NC}" echo -e "\n${BOLD}${CYAN}=== JETZT CUSTOM.CONF BEFÜLLEN ===${NC}"
echo -e "Bitte öffne nun auf deinem Server (oder via SFTP/Filebrowser) die Datei im Container:" echo -e "Öffne dein Filebrowser Web-Interface (${BOLD}Port 8081${NC})."
echo -e " ${BOLD}/opt/docker-projekte/VPN/custom.conf${NC}" echo -e "Gehe in den Ordner ${BOLD}VPN${NC} und bearbeite die ${BOLD}custom.conf${NC}."
echo -e "Füge dort den kompletten Text deiner NordVPN-Konfigurationsdatei (.ovpn) ein und speichere." echo -e "Füge dort den Inhalt deiner .ovpn Datei von NordVPN ein."
echo -e "Tipp: Du kannst auch in einer zweiten Konsole ausführen:"
echo -e " pct enter ${SEL_ID} und dann nano /opt/docker-projekte/VPN/custom.conf"
while true; do while true; do
echo echo
if confirm "Hast du die custom.conf befüllt und gespeichert?"; then if confirm "Ist die custom.conf im Filebrowser gespeichert?"; then
# Kurzer Check, ob die Datei nicht mehr leer ist
local size local size
size=$(pct exec "$SEL_ID" -- stat -c%s /opt/docker-projekte/VPN/custom.conf 2>/dev/null || echo 0) size=$(pct exec "$SEL_ID" -- stat -c%s /opt/docker-projekte/VPN/custom.conf 2>/dev/null || echo 0)
if [[ "$size" -gt 10 ]]; then [[ "$size" -gt 10 ]] && { success "Inhalt erkannt!"; break; }
success "Datei ist befüllt!" warn "Die Datei ist noch leer oder zu klein. Bitte nochmal prüfen."
break
else
warn "Die Datei scheint noch leer zu sein. Bitte überprüfe das."
fi
fi fi
done done
} }
# ── Docker Compose schreiben & anwenden ──────────────────────────────────────── deploy_vpn_stack() {
deploy_stack() { step "VPN & Freqtrade Stack starten"
step "Docker Stack anwenden"
local FT_DIR="/opt/docker-projekte/freqtrade" local FT_DIR="/opt/docker-projekte/freqtrade"
# Lokales Subnetz automatisch ermitteln (z.B. 192.168.178.0/24) # Subnetz ermitteln
local SUBNET local SUBNET
SUBNET=$(pct exec "$SEL_ID" -- bash -c "ip -o -f inet addr show eth0 | awk '{print \$4}' | sed 's/\.[0-9]\{1,3\}\//.0\//'" 2>/dev/null || echo "192.168.0.0/24") SUBNET=$(pct exec "$SEL_ID" -- bash -c "ip -o -f inet addr show eth0 | awk '{print \$4}' | sed 's/\.[0-9]\{1,3\}\//.0\//'" 2>/dev/null || echo "192.168.0.0/24")
info "Ermitteltes lokales Subnetz: ${SUBNET}"
# Alten Stack stoppen info "Schreibe neue docker-compose.yml für Freqtrade..."
info "Stoppe aktuellen Stack..."
pct exec "$SEL_ID" -- bash -c "cd ${FT_DIR} && docker compose down 2>/dev/null || true"
# Neue docker-compose.yml generieren
info "Schreibe neue docker-compose.yml..."
pct exec "$SEL_ID" -- bash -c "cat > ${FT_DIR}/docker-compose.yml << 'COMPOSEEOF' pct exec "$SEL_ID" -- bash -c "cat > ${FT_DIR}/docker-compose.yml << 'COMPOSEEOF'
version: '3.8' version: '3.8'
services: services:
gluetun: gluetun:
image: qmcgaw/gluetun:latest image: qmcgaw/gluetun:latest
@@ -195,7 +160,6 @@ services:
- OPENVPN_CUSTOM_CONFIG=/gluetun/custom.conf - OPENVPN_CUSTOM_CONFIG=/gluetun/custom.conf
- OPENVPN_USER=${NORD_USER} - OPENVPN_USER=${NORD_USER}
- OPENVPN_PASSWORD=${NORD_PASS} - OPENVPN_PASSWORD=${NORD_PASS}
# Automatisch ermitteltes lokales Netz für Erreichbarkeit
- FIREWALL_OUTBOUND_SUBNETS=${SUBNET} - FIREWALL_OUTBOUND_SUBNETS=${SUBNET}
volumes: volumes:
- /opt/docker-projekte/VPN:/gluetun - /opt/docker-projekte/VPN:/gluetun
@@ -220,70 +184,25 @@ services:
--strategy SampleStrategy --strategy SampleStrategy
COMPOSEEOF" COMPOSEEOF"
# Stack starten pct exec "$SEL_ID" -- bash -c "cd ${FT_DIR} && docker compose down 2>/dev/null || true"
info "Starte Stack neu..."
pct exec "$SEL_ID" -- bash -c "cd ${FT_DIR} && docker compose up -d" pct exec "$SEL_ID" -- bash -c "cd ${FT_DIR} && docker compose up -d"
sleep 5 success "Freqtrade & VPN Stack gestartet!"
success "Deployment abgeschlossen!"
} }
# ── Filebrowser anpassen ───────────────────────────────────────────────────────
update_filebrowser() {
step "Filebrowser aktualisieren"
local FB_DIR="/opt/docker-projekte/filebrowser"
local FB_YML="${FB_DIR}/docker-compose.yml"
# Prüfen, ob der Filebrowser überhaupt da ist
if pct exec "$SEL_ID" -- bash -c "[ -f ${FB_YML} ]"; then
info "Filebrowser gefunden. Prüfe Konfiguration..."
# Prüfen, ob der Mount schon existiert, um Doppel-Einträge zu vermeiden
if pct exec "$SEL_ID" -- bash -c "grep -q '/opt/docker-projekte/VPN:/srv/VPN' ${FB_YML}"; then
success "VPN-Ordner ist bereits im Filebrowser gemountet."
else
info "Füge VPN-Mountpunkt zur docker-compose.yml hinzu..."
# Fügt die Zeile exakt nach 'volumes:' ein
pct exec "$SEL_ID" -- bash -c "sed -i '/volumes:/a \\ - /opt/docker-projekte/VPN:/srv/VPN' ${FB_YML}"
success "Konfiguration ergänzt."
info "Starte Filebrowser neu..."
pct exec "$SEL_ID" -- bash -c "cd ${FB_DIR} && docker compose down && docker compose up -d"
success "Filebrowser ist neugestartet und hat jetzt Zugriff auf den VPN-Ordner!"
fi
else
info "Kein Filebrowser unter ${FB_DIR} gefunden. Überspringe diesen Schritt."
fi
}
# ── Ergebnis anzeigen ──────────────────────────────────────────────────────────
show_result() {
# VPN IP Check
local VPN_IP
VPN_IP=$(pct exec "$SEL_ID" -- bash -c "docker exec gluetun wget -qO- https://ifconfig.me 2>/dev/null" || echo "FEHLER")
local SUBNET
SUBNET=$(pct exec "$SEL_ID" -- bash -c "ip -o -f inet addr show eth0 | awk '{print \$4}' | sed 's/\.[0-9]\{1,3\}\//.0\//'" 2>/dev/null || echo "Lokales Netz")
echo
echo -e "${BOLD}${GREEN}╔══════════════════════════════════════════╗${NC}"
echo -e "${BOLD}${GREEN}║ ✅ Setup erfolgreich abgeschlossen! ║${NC}"
echo -e "${BOLD}${GREEN}╚══════════════════════════════════════════╝${NC}"
echo -e " Neue externe VPN-IP des Bots: ${CYAN}${VPN_IP}${NC}"
echo -e " Dein lokales Subnetz (${SUBNET}) wurde in der Firewall freigegeben."
echo -e " Das Freqtrade-Webinterface bleibt über Port 8080 erreichbar."
echo -e " Der Ordner 'VPN' steht dir jetzt in deinem Filebrowser zur Verfügung!"
}
# ── Hauptprogramm ──────────────────────────────────────────────────────────────
main() { main() {
print_banner print_banner
check_host check_host
select_container select_container
setup_system setup_base_system
collect_and_wait
deploy_stack
update_filebrowser update_filebrowser
show_result collect_and_wait
deploy_vpn_stack
# Finaler IP Check
local IP
IP=$(pct exec "$SEL_ID" -- bash -c "docker exec gluetun wget -qO- https://ifconfig.me 2>/dev/null" || echo "Check fehlgeschlagen")
echo -e "\n${GREEN}FERTIG! Externe VPN-IP: ${BOLD}${IP}${NC}"
} }
main "$@" main "$@"