Dateien nach "scripts" hochladen

This commit is contained in:
2026-04-22 13:09:22 +02:00
parent d51a612764
commit 2c62afcb34
+101 -36
View File
@@ -1,7 +1,13 @@
#!/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)
# Ablauf: System -> Ordner -> Filebrowser -> User-Input -> VPN-Start # Läuft komplett auf dem PROXMOX HOST.
# - 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
@@ -27,11 +33,22 @@ confirm() {
read -r ans; [[ "$ans" =~ ^[jJyY]$ ]] read -r ans; [[ "$ans" =~ ^[jJyY]$ ]]
} }
# ── Banner ─────────────────────────────────────────────────────────────────────
print_banner() { print_banner() {
clear clear
echo -e "${BOLD}${BLUE} NordVPN Custom Config Installer (Filebrowser-First)${NC}\n" echo -e "${BOLD}${BLUE}"
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!"
@@ -39,28 +56,43 @@ 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 local ct_id status hostname tags
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 "")
if echo "$tags" | grep -qi "freqtrade"; then
display_list+=("${ct_id}|${hostname}|${status}") 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)
echo -e " ${BOLD}Nr ID Hostname${NC}" [[ ${#display_list[@]} -eq 0 ]] && error "Keine Container mit Tag 'freqtrade' gefunden!"
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\n" "$i" "$cid" "$cname" printf " ${CYAN}%-4s${NC} %-8s %-18s %-10s\n" "$i" "$cid" "$cname" "$cstatus"
((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..."
@@ -68,83 +100,113 @@ select_container() {
fi fi
} }
setup_base_system() { # ── TUN-Device & Ordner einrichten ─────────────────────────────────────────────
step "Grundsystem & VPN-Ordner vorbereiten" setup_system() {
step "System & VPN-Ordner vorbereiten"
# TUN-Device in LXC Config # 1. TUN-Device in LXC Config schreiben
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 "Konfiguriere TUN-Device..." info "Trage TUN-Device in Config ein..."
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 2 && pct start "$SEL_ID" && sleep 5 pct stop "$SEL_ID" && sleep 3 && pct start "$SEL_ID"
sleep 5
success "TUN-Device eingerichtet & Container neu gestartet"
else
success "TUN-Device war bereits konfiguriert"
fi fi
# VPN Ordner erstellen (BEVOR Filebrowser ihn braucht) # 2. Ordner und Datei erstellen & Rechte setzen
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 ist bereit." success "VPN-Ordner und custom.conf erstellt (/opt/docker-projekte/VPN)"
} }
# ── Filebrowser anpassen ───────────────────────────────────────────────────────
update_filebrowser() { update_filebrowser() {
step "Filebrowser Anbindung (Vorbereitung)" step "Filebrowser aktualisieren"
local FB_DIR="/opt/docker-projekte/filebrowser" local FB_DIR="/opt/docker-projekte/filebrowser"
local FB_YML="${FB_DIR}/docker-compose.yml" 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 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 "Filebrowser gefunden. Prüfe Konfiguration..."
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}" # Prüfen, ob der Mount schon existiert, um Doppel-Einträge zu vermeiden
pct exec "$SEL_ID" -- bash -c "cd ${FB_DIR} && docker compose down && docker compose up -d" if pct exec "$SEL_ID" -- bash -c "grep -q '/opt/docker-projekte/VPN:/srv/VPN' ${FB_YML}"; then
success "Filebrowser neu gestartet. VPN-Ordner ist jetzt im Web-UI sichtbar!" success "VPN-Ordner ist bereits im Filebrowser gemountet."
else else
success "Filebrowser bereits konfiguriert." 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 fi
else else
warn "Filebrowser nicht gefunden. Du musst die custom.conf manuell bearbeiten." info "Kein Filebrowser unter ${FB_DIR} gefunden. Überspringe diesen Schritt."
fi fi
} }
# ── Konfiguration abfragen & Datei befüllen lassen ─────────────────────────────
collect_and_wait() { collect_and_wait() {
step "Konfiguration & User-Input" step "NordVPN Credentials & Config"
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}=== JETZT CUSTOM.CONF BEFÜLLEN ===${NC}" echo -e "\n${BOLD}${CYAN}=== WICHTIGER SCHRITT ===${NC}"
echo -e "Öffne dein Filebrowser Web-Interface (${BOLD}Port 8081${NC})." echo -e "Bitte öffne nun auf deinem Server (oder via SFTP/Filebrowser) die Datei im Container:"
echo -e "Gehe in den Ordner ${BOLD}VPN${NC} und bearbeite die ${BOLD}custom.conf${NC}." echo -e " ${BOLD}/opt/docker-projekte/VPN/custom.conf${NC}"
echo -e "Füge dort den Inhalt deiner .ovpn Datei von NordVPN ein." echo -e "Füge dort den kompletten Text deiner NordVPN-Konfigurationsdatei (.ovpn) ein und speichere."
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 "Ist die custom.conf im Filebrowser gespeichert?"; then if confirm "Hast du die custom.conf befüllt und 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)
[[ "$size" -gt 10 ]] && { success "Inhalt erkannt!"; break; } if [[ "$size" -gt 10 ]]; then
warn "Die Datei ist noch leer oder zu klein. Bitte nochmal prüfen." success "Datei ist befüllt!"
break
else
warn "Die Datei scheint noch leer zu sein. Bitte überprüfe das."
fi
fi fi
done done
} }
deploy_vpn_stack() { # ── Docker Compose schreiben & anwenden ────────────────────────────────────────
step "VPN & Freqtrade Stack starten" deploy_stack() {
step "Docker Stack anwenden"
local FT_DIR="/opt/docker-projekte/freqtrade" local FT_DIR="/opt/docker-projekte/freqtrade"
# Subnetz ermitteln # Lokales Subnetz automatisch ermitteln (z.B. 192.168.178.0/24)
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}"
info "Schreibe neue docker-compose.yml für Freqtrade..." # Alten Stack stoppen
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
@@ -160,6 +222,7 @@ 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
@@ -184,10 +247,12 @@ services:
--strategy SampleStrategy --strategy SampleStrategy
COMPOSEEOF" COMPOSEEOF"
pct exec "$SEL_ID" -- bash -c "cd ${FT_DIR} && docker compose down 2>/dev/null || true" # Stack starten
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"
success "Freqtrade & VPN Stack gestartet!" sleep 5
success "Deployment abgeschlossen!"
} }
main() { main() {