Dateien nach "scripts" hochladen
This commit is contained in:
@@ -0,0 +1,279 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# Freqtrade NordVPN Addon (Gluetun)
|
||||||
|
# Ergänzt eine bestehende Freqtrade-Installation um NordVPN-Routing.
|
||||||
|
# Läuft im FREQTRADE LXC (nicht 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}"; }
|
||||||
|
|
||||||
|
ask() {
|
||||||
|
local prompt="$1" default="${2:-}"
|
||||||
|
if [[ -n "$default" ]]; then
|
||||||
|
echo -ne "${YELLOW} ➜ ${NC}${prompt} [${CYAN}${default}${NC}]: "
|
||||||
|
else
|
||||||
|
echo -ne "${YELLOW} ➜ ${NC}${prompt}: "
|
||||||
|
fi
|
||||||
|
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]$ ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
print_banner() {
|
||||||
|
clear
|
||||||
|
echo -e "${BOLD}${BLUE}"
|
||||||
|
echo " _ _ _ ___ ___ _ _"
|
||||||
|
echo " | \| |___ _ _ __ | \ \ \ / / | \| |"
|
||||||
|
echo " | .\` / _ \ '_/ _\` \ V /\ V /| | .\` |"
|
||||||
|
echo " |_|\_\___/_| \__,_|\_/ \_/ |_|_|\_|"
|
||||||
|
echo " Freqtrade + NordVPN Addon (Gluetun)"
|
||||||
|
echo -e "${NC}"
|
||||||
|
echo -e " ${CYAN}Ergänzt Freqtrade um NordVPN-Routing via Gluetun${NC}"
|
||||||
|
echo -e " ${YELLOW}Läuft im Freqtrade LXC – nicht auf dem Proxmox Host!${NC}\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_requirements() {
|
||||||
|
step "Voraussetzungen prüfen"
|
||||||
|
[[ $EUID -ne 0 ]] && error "Bitte als root ausführen!"
|
||||||
|
command -v docker &>/dev/null || error "Docker nicht gefunden."
|
||||||
|
docker compose version &>/dev/null || error "Docker Compose Plugin nicht gefunden."
|
||||||
|
success "Docker + Compose vorhanden"
|
||||||
|
|
||||||
|
FT_DIR=""
|
||||||
|
for candidate in /opt/docker-projekte/freqtrade /opt/freqtrade; do
|
||||||
|
if [[ -f "$candidate/docker-compose.yml" ]] && [[ -d "$candidate/user_data" ]]; then
|
||||||
|
FT_DIR="$candidate"; break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
[[ -z "$FT_DIR" ]] && error "Keine Freqtrade-Installation gefunden in /opt/docker-projekte/freqtrade/"
|
||||||
|
success "Freqtrade gefunden: $FT_DIR"
|
||||||
|
|
||||||
|
if [[ ! -e /dev/net/tun ]]; then
|
||||||
|
warn "/dev/net/tun fehlt – lege an..."
|
||||||
|
mkdir -p /dev/net
|
||||||
|
mknod /dev/net/tun c 10 200 2>/dev/null || true
|
||||||
|
chmod 600 /dev/net/tun 2>/dev/null || true
|
||||||
|
[[ ! -e /dev/net/tun ]] && error "/dev/net/tun konnte nicht erstellt werden.\nBitte im Proxmox Host prüfen ob in /etc/pve/lxc/<ID>.conf diese Zeilen stehen:\n lxc.cgroup2.devices.allow: c 10:200 rwm\n lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file\n\nHinweis: proxmox-install.sh richtet das automatisch ein."
|
||||||
|
fi
|
||||||
|
success "/dev/net/tun vorhanden"
|
||||||
|
}
|
||||||
|
|
||||||
|
collect_config() {
|
||||||
|
step "NordVPN Konfiguration"
|
||||||
|
echo -e "\n ${BOLD}Service-Credentials${NC} findest du unter:"
|
||||||
|
echo -e " ${CYAN}https://my.nordaccount.com → NordVPN → 'Set up NordVPN manually'${NC}"
|
||||||
|
echo -e " ${RED} Nicht deine E-Mail/Passwort – die Service-Credentials!${NC}\n"
|
||||||
|
|
||||||
|
ask "NordVPN Service-Username"
|
||||||
|
NORD_USER="$REPLY"
|
||||||
|
[[ -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!"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e " ${BOLD}VPN-Server Modus:${NC}"
|
||||||
|
echo -e " ${CYAN}1)${NC} Serverland – normaler Server (IP kann wechseln)"
|
||||||
|
echo -e " ${CYAN}2)${NC} Hostname – spezifischen Server/Dedicated-IP pinnen"
|
||||||
|
ask "Auswahl [1/2]" "1"
|
||||||
|
VPN_MODE="$REPLY"
|
||||||
|
|
||||||
|
if [[ "$VPN_MODE" == "2" ]]; then
|
||||||
|
ask "Hostname (z.B. de123.nordvpn.com)"
|
||||||
|
VPN_HOSTNAME="$REPLY"; VPN_COUNTRY=""
|
||||||
|
else
|
||||||
|
ask "Serverland" "Germany"
|
||||||
|
VPN_COUNTRY="$REPLY"; VPN_HOSTNAME=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
CURRENT_PORT=$(grep -oP '"0\.0\.0\.0:\K\d+(?=:\d+")' "$FT_DIR/docker-compose.yml" 2>/dev/null | head -1 || echo "8080")
|
||||||
|
ask "FreqUI Port" "$CURRENT_PORT"
|
||||||
|
FT_PORT="$REPLY"
|
||||||
|
|
||||||
|
echo -e "\n${BOLD}${BLUE}══════════ Zusammenfassung ══════════${NC}"
|
||||||
|
echo -e " Freqtrade: ${CYAN}$FT_DIR${NC}"
|
||||||
|
echo -e " NordVPN User: ${CYAN}$NORD_USER${NC}"
|
||||||
|
if [[ -n "$VPN_HOSTNAME" ]]; then
|
||||||
|
echo -e " VPN Server: ${CYAN}$VPN_HOSTNAME${NC}"
|
||||||
|
else
|
||||||
|
echo -e " VPN Land: ${CYAN}$VPN_COUNTRY${NC}"
|
||||||
|
fi
|
||||||
|
echo -e " FreqUI Port: ${CYAN}$FT_PORT${NC}"
|
||||||
|
echo -e "${BOLD}${BLUE}=====================================\n${NC}"
|
||||||
|
|
||||||
|
confirm "Einrichten?" || { info "Abgebrochen."; exit 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
backup_and_stop() {
|
||||||
|
step "Backup & Stack stoppen"
|
||||||
|
local BAK="$FT_DIR/docker-compose.yml.bak-$(date +%Y%m%d_%H%M%S)"
|
||||||
|
cp "$FT_DIR/docker-compose.yml" "$BAK"
|
||||||
|
success "Backup: $BAK"
|
||||||
|
|
||||||
|
cd "$FT_DIR"
|
||||||
|
if docker compose ps --quiet 2>/dev/null | grep -q .; then
|
||||||
|
docker compose down; success "Stack gestoppt"
|
||||||
|
else
|
||||||
|
info "Kein laufender Stack"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
write_env() {
|
||||||
|
step ".env schreiben"
|
||||||
|
[[ -f "$FT_DIR/.env" ]] && cp "$FT_DIR/.env" "$FT_DIR/.env.bak-$(date +%Y%m%d_%H%M%S)"
|
||||||
|
cat > "$FT_DIR/.env" << ENVEOF
|
||||||
|
# NordVPN Service-Credentials
|
||||||
|
# Quelle: https://my.nordaccount.com → NordVPN → Set up NordVPN manually
|
||||||
|
OPENVPN_USER=${NORD_USER}
|
||||||
|
OPENVPN_PASSWORD=${NORD_PASS}
|
||||||
|
ENVEOF
|
||||||
|
chmod 600 "$FT_DIR/.env"
|
||||||
|
success ".env gespeichert (chmod 600)"
|
||||||
|
}
|
||||||
|
|
||||||
|
write_compose() {
|
||||||
|
step "docker-compose.yml erstellen"
|
||||||
|
|
||||||
|
local VPN_SERVER_LINE=""
|
||||||
|
if [[ -n "$VPN_HOSTNAME" ]]; then
|
||||||
|
VPN_SERVER_LINE=" - SERVER_HOSTNAMES=${VPN_HOSTNAME}"
|
||||||
|
else
|
||||||
|
VPN_SERVER_LINE=" - SERVER_COUNTRIES=${VPN_COUNTRY}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat > "$FT_DIR/docker-compose.yml" << COMPOSEEOF
|
||||||
|
# Freqtrade + NordVPN/Gluetun | $(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
# Netzwerk: [Freqtrade] → [Gluetun] → NordVPN → Internet
|
||||||
|
# WebUI: http://LXC-IP:${FT_PORT} (Port liegt bei Gluetun!)
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# VPN-Gateway – exponiert alle Ports
|
||||||
|
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 – KEIN ports: hier, läuft über Gluetun-Netzwerk
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
start_and_verify() {
|
||||||
|
step "Stack starten & VPN prüfen"
|
||||||
|
cd "$FT_DIR"
|
||||||
|
docker compose up -d
|
||||||
|
echo
|
||||||
|
info "Warte auf VPN-Verbindung (bis zu 90s)..."
|
||||||
|
|
||||||
|
local tries=0 vpn_ok=false
|
||||||
|
while [[ $tries -lt 18 ]]; do
|
||||||
|
sleep 5; echo -n "."
|
||||||
|
docker exec gluetun wget -qO- https://ipinfo.io/ip &>/dev/null && { vpn_ok=true; break; }
|
||||||
|
((tries++))
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [[ "$vpn_ok" == "true" ]]; then
|
||||||
|
VPN_IP=$(docker exec gluetun wget -qO- https://ipinfo.io/ip 2>/dev/null)
|
||||||
|
success "VPN verbunden! Ausgehende IP: ${BOLD}${VPN_IP}${NC}"
|
||||||
|
else
|
||||||
|
warn "VPN-Verbindung Timeout. Prüfe: docker logs gluetun"
|
||||||
|
VPN_IP="unbekannt – prüfe: docker exec gluetun wget -qO- https://ipinfo.io/ip"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 5
|
||||||
|
docker ps | grep -q "freqtrade" && success "Freqtrade läuft" || warn "Freqtrade prüfen: docker logs freqtrade"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_result() {
|
||||||
|
local LXC_IP; LXC_IP=$(hostname -I | awk '{print $1}')
|
||||||
|
echo
|
||||||
|
echo -e "${BOLD}${GREEN}╔═══════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${BOLD}${GREEN}║ ✅ NordVPN Addon 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} ${CYAN}${VPN_IP}${NC}"
|
||||||
|
echo
|
||||||
|
echo -e " ${BOLD}${YELLOW}⚠ Binance API-Key anpassen:${NC}"
|
||||||
|
echo -e " ${YELLOW}In Binance → API Management → IP-Beschränkung${NC}"
|
||||||
|
echo -e " ${YELLOW}Die NordVPN-IP eintragen (nicht mehr die Home-IP)!${NC}"
|
||||||
|
echo
|
||||||
|
echo -e " ${BOLD}Befehle:${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}cd $FT_DIR && docker compose restart${NC} # Neustart"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
print_banner
|
||||||
|
check_requirements
|
||||||
|
collect_config
|
||||||
|
backup_and_stop
|
||||||
|
write_env
|
||||||
|
write_compose
|
||||||
|
start_and_verify
|
||||||
|
show_result
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
@@ -0,0 +1,539 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# Freqtrade Proxmox Installer
|
||||||
|
# Erstellt automatisch einen Docker-LXC und installiert Freqtrade darin.
|
||||||
|
# Läuft auf dem PROXMOX HOST.
|
||||||
|
#
|
||||||
|
# Quelle: https://git.obraasch.de/olli1986/freqtrade-proxmox-deploy
|
||||||
|
# =============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ── Farben ────────────────────────────────────────────────────────────────────
|
||||||
|
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}"; }
|
||||||
|
|
||||||
|
ask() {
|
||||||
|
local prompt="$1" default="${2:-}"
|
||||||
|
if [[ -n "$default" ]]; then
|
||||||
|
echo -ne "${YELLOW} ➜ ${NC}${prompt} [${CYAN}${default}${NC}]: "
|
||||||
|
else
|
||||||
|
echo -ne "${YELLOW} ➜ ${NC}${prompt}: "
|
||||||
|
fi
|
||||||
|
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]$ ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Voraussetzungen ───────────────────────────────────────────────────────────
|
||||||
|
check_host() {
|
||||||
|
[[ $EUID -ne 0 ]] && error "Bitte als root ausführen!"
|
||||||
|
command -v pct &>/dev/null || error "pct nicht gefunden – läuft das auf einem Proxmox Host?"
|
||||||
|
command -v pvesh &>/dev/null || error "pvesh nicht gefunden – läuft das auf einem Proxmox Host?"
|
||||||
|
command -v pveam &>/dev/null || error "pveam nicht gefunden."
|
||||||
|
success "Proxmox Host erkannt"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Banner ────────────────────────────────────────────────────────────────────
|
||||||
|
print_banner() {
|
||||||
|
clear
|
||||||
|
echo -e "${BOLD}${BLUE}"
|
||||||
|
cat << 'BANNER'
|
||||||
|
___ _ _
|
||||||
|
| _ \_ _ _____ _| |_ _ __ _____ __ | |_ ___ ___
|
||||||
|
| _/ '_/ _ \ \ / | ' \/ _ \ \ / / | _/ -_) _ \
|
||||||
|
|_| |_| \___/_\_\_|_||_\___/_\_\_| \__\___\___/
|
||||||
|
+ NordVPN + Proxmox LXC Installer
|
||||||
|
BANNER
|
||||||
|
echo -e "${NC}"
|
||||||
|
echo -e " ${CYAN}Freqtrade vollautomatischer Installer für Proxmox${NC}"
|
||||||
|
echo -e " ${CYAN}git.obraasch.de/olli1986/freqtrade-proxmox-deploy${NC}\n"
|
||||||
|
echo -e " ${YELLOW}⚠ Nur für Test- und Lernzwecke. Trading auf eigenes Risiko!${NC}\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Verfügbare Ressourcen ermitteln ───────────────────────────────────────────
|
||||||
|
detect_resources() {
|
||||||
|
# Nächste freie CT-ID
|
||||||
|
NEXT_ID=$(pvesh get /cluster/nextid 2>/dev/null | tr -d '[:space:]' || echo "100")
|
||||||
|
|
||||||
|
# Verfügbare Storages (für LXC-Rootfs)
|
||||||
|
STORAGES=$(pvesm status 2>/dev/null | awk 'NR>1 && $2!="dir" || $2=="dir" {print $1}' | tr '\n' ' ' || echo "local-lvm local")
|
||||||
|
|
||||||
|
# Verfügbare Bridges
|
||||||
|
BRIDGES=$(ip link show 2>/dev/null | grep -oP '(?<=: )vmbr\d+' | tr '\n' ' ' || echo "vmbr0")
|
||||||
|
|
||||||
|
# Erster Storage als Default
|
||||||
|
DEFAULT_STORAGE=$(pvesm status 2>/dev/null | awk 'NR==2{print $1}' || echo "local-lvm")
|
||||||
|
|
||||||
|
# Erste Bridge als Default
|
||||||
|
DEFAULT_BRIDGE=$(ip link show 2>/dev/null | grep -oP '(?<=: )vmbr\d+' | head -1 || echo "vmbr0")
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Template holen ────────────────────────────────────────────────────────────
|
||||||
|
prepare_template() {
|
||||||
|
step "Debian 12 Template prüfen"
|
||||||
|
|
||||||
|
# Suche lokal vorhandenes Debian 12 Template
|
||||||
|
TEMPLATE_FILE=$(pveam list local 2>/dev/null | grep -oP 'debian-12-standard_\S+' | head -1 || true)
|
||||||
|
|
||||||
|
if [[ -z "$TEMPLATE_FILE" ]]; then
|
||||||
|
info "Template nicht lokal vorhanden – lade herunter..."
|
||||||
|
pveam update &>/dev/null || warn "pveam update fehlgeschlagen, versuche trotzdem..."
|
||||||
|
|
||||||
|
# Neuestes Debian 12 Template aus der Liste holen
|
||||||
|
TEMPLATE_FILE=$(pveam available --section system 2>/dev/null \
|
||||||
|
| grep -oP 'debian-12-standard_\S+' | sort -V | tail -1 || true)
|
||||||
|
|
||||||
|
[[ -z "$TEMPLATE_FILE" ]] && TEMPLATE_FILE="debian-12-standard_12.7-1_amd64.tar.zst"
|
||||||
|
|
||||||
|
info "Lade Template: $TEMPLATE_FILE"
|
||||||
|
pveam download local "$TEMPLATE_FILE" || error "Template-Download fehlgeschlagen!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
TEMPLATE_PATH="local:vztmpl/${TEMPLATE_FILE}"
|
||||||
|
success "Template bereit: $TEMPLATE_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Konfiguration abfragen ────────────────────────────────────────────────────
|
||||||
|
collect_config() {
|
||||||
|
step "LXC Konfiguration"
|
||||||
|
echo -e " ${CYAN}Verfügbare Storages:${NC} $STORAGES"
|
||||||
|
echo -e " ${CYAN}Verfügbare Bridges:${NC} $BRIDGES\n"
|
||||||
|
|
||||||
|
ask "LXC Container-ID" "$NEXT_ID"
|
||||||
|
CT_ID="$REPLY"
|
||||||
|
[[ "$CT_ID" =~ ^[0-9]+$ ]] || error "Container-ID muss eine Zahl sein!"
|
||||||
|
pct status "$CT_ID" &>/dev/null && error "Container-ID $CT_ID existiert bereits!"
|
||||||
|
|
||||||
|
ask "Hostname" "freqtrade"
|
||||||
|
CT_HOST="$REPLY"
|
||||||
|
|
||||||
|
ask "CPU Kerne" "2"
|
||||||
|
CT_CORES="$REPLY"
|
||||||
|
|
||||||
|
ask "RAM in MB" "2048"
|
||||||
|
CT_RAM="$REPLY"
|
||||||
|
|
||||||
|
ask "Swap in MB" "512"
|
||||||
|
CT_SWAP="$REPLY"
|
||||||
|
|
||||||
|
ask "Disk-Größe in GB" "10"
|
||||||
|
CT_DISK="$REPLY"
|
||||||
|
|
||||||
|
ask "Storage Pool" "$DEFAULT_STORAGE"
|
||||||
|
CT_STORAGE="$REPLY"
|
||||||
|
|
||||||
|
ask "Netzwerk-Bridge" "$DEFAULT_BRIDGE"
|
||||||
|
CT_BRIDGE="$REPLY"
|
||||||
|
|
||||||
|
ask "Netzwerk (dhcp oder z.B. 192.168.1.100/24)" "dhcp"
|
||||||
|
CT_IP="$REPLY"
|
||||||
|
|
||||||
|
if [[ "$CT_IP" != "dhcp" ]]; then
|
||||||
|
ask "Gateway (nur bei statischer IP nötig)"
|
||||||
|
CT_GW="$REPLY"
|
||||||
|
else
|
||||||
|
CT_GW=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
ask_secret "Root-Passwort für den LXC"
|
||||||
|
CT_PASS="$REPLY"
|
||||||
|
[[ ${#CT_PASS} -lt 8 ]] && error "Passwort muss mind. 8 Zeichen haben!"
|
||||||
|
|
||||||
|
step "Freqtrade Konfiguration"
|
||||||
|
|
||||||
|
ask "FreqUI Port" "8080"
|
||||||
|
FT_PORT="$REPLY"
|
||||||
|
|
||||||
|
ask "Börse" "binance"
|
||||||
|
FT_EXCHANGE="$REPLY"
|
||||||
|
|
||||||
|
ask "Stake-Währung" "USDC"
|
||||||
|
FT_STAKE="$REPLY"
|
||||||
|
|
||||||
|
ask "Max. offene Trades" "3"
|
||||||
|
FT_MAX_TRADES="$REPLY"
|
||||||
|
|
||||||
|
ask "Timeframe" "5m"
|
||||||
|
FT_TIMEFRAME="$REPLY"
|
||||||
|
|
||||||
|
ask "FreqUI Benutzername" "freqtrader"
|
||||||
|
FT_API_USER="$REPLY"
|
||||||
|
|
||||||
|
ask_secret "FreqUI Passwort (min. 8 Zeichen)"
|
||||||
|
FT_API_PASS="$REPLY"
|
||||||
|
[[ ${#FT_API_PASS} -lt 8 ]] && error "FreqUI Passwort muss mind. 8 Zeichen haben!"
|
||||||
|
|
||||||
|
if confirm "Telegram-Benachrichtigungen aktivieren?"; then
|
||||||
|
FT_TELEGRAM=true
|
||||||
|
ask "Telegram Bot-Token"
|
||||||
|
TG_TOKEN="$REPLY"
|
||||||
|
ask "Telegram Chat-ID"
|
||||||
|
TG_CHATID="$REPLY"
|
||||||
|
else
|
||||||
|
FT_TELEGRAM=false
|
||||||
|
TG_TOKEN=""
|
||||||
|
TG_CHATID=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if confirm "Filebrowser (Web-Dateimanager) installieren?"; then
|
||||||
|
INSTALL_FB=true
|
||||||
|
ask "Filebrowser Port" "8081"
|
||||||
|
FB_PORT="$REPLY"
|
||||||
|
else
|
||||||
|
INSTALL_FB=false
|
||||||
|
FB_PORT="8081"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Zusammenfassung ──
|
||||||
|
echo -e "\n${BOLD}${BLUE}══════════════ Zusammenfassung ══════════════${NC}"
|
||||||
|
echo -e " CT-ID: ${CYAN}$CT_ID${NC} Hostname: ${CYAN}$CT_HOST${NC}"
|
||||||
|
echo -e " CPU/RAM: ${CYAN}$CT_CORES Kerne / ${CT_RAM}MB RAM / ${CT_SWAP}MB Swap${NC}"
|
||||||
|
echo -e " Disk: ${CYAN}${CT_DISK}GB auf $CT_STORAGE${NC}"
|
||||||
|
echo -e " Netzwerk: ${CYAN}$CT_IP via $CT_BRIDGE${NC}"
|
||||||
|
echo -e " FreqUI Port: ${CYAN}$FT_PORT${NC} Börse: ${CYAN}$FT_EXCHANGE${NC}"
|
||||||
|
echo -e " Filebrowser: $([ "$INSTALL_FB" = true ] && echo "${CYAN}Ja (Port $FB_PORT)${NC}" || echo "${CYAN}Nein${NC}")"
|
||||||
|
echo -e " Telegram: $([ "$FT_TELEGRAM" = true ] && echo "${CYAN}Ja${NC}" || echo "${CYAN}Nein${NC}")"
|
||||||
|
echo -e "${BOLD}${BLUE}════════════════════════════════════════════${NC}\n"
|
||||||
|
|
||||||
|
confirm "Installation starten?" || { info "Abgebrochen."; exit 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── LXC erstellen ─────────────────────────────────────────────────────────────
|
||||||
|
create_lxc() {
|
||||||
|
step "LXC Container $CT_ID erstellen"
|
||||||
|
|
||||||
|
local NET_CONFIG
|
||||||
|
if [[ "$CT_IP" == "dhcp" ]]; then
|
||||||
|
NET_CONFIG="name=eth0,bridge=${CT_BRIDGE},ip=dhcp,firewall=1"
|
||||||
|
else
|
||||||
|
NET_CONFIG="name=eth0,bridge=${CT_BRIDGE},ip=${CT_IP},gw=${CT_GW},firewall=1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
pct create "$CT_ID" "$TEMPLATE_PATH" \
|
||||||
|
--hostname "$CT_HOST" \
|
||||||
|
--password "$CT_PASS" \
|
||||||
|
--cores "$CT_CORES" \
|
||||||
|
--memory "$CT_RAM" \
|
||||||
|
--swap "$CT_SWAP" \
|
||||||
|
--rootfs "${CT_STORAGE}:${CT_DISK}" \
|
||||||
|
--net0 "$NET_CONFIG" \
|
||||||
|
--features "nesting=1,keyctl=1" \
|
||||||
|
--unprivileged 1 \
|
||||||
|
--onboot 1 \
|
||||||
|
--timezone "Europe/Berlin" \
|
||||||
|
--start 0
|
||||||
|
|
||||||
|
# TUN-Device für spätere VPN-Nutzung vorbereiten
|
||||||
|
cat >> "/etc/pve/lxc/${CT_ID}.conf" << 'TUNCFG'
|
||||||
|
# TUN-Device für NordVPN/Gluetun (wird von install-vpn.sh genutzt)
|
||||||
|
lxc.cgroup2.devices.allow: c 10:200 rwm
|
||||||
|
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
|
||||||
|
TUNCFG
|
||||||
|
|
||||||
|
success "LXC $CT_ID erstellt (mit TUN-Device vorbereitet)"
|
||||||
|
|
||||||
|
# Starten
|
||||||
|
info "Starte Container..."
|
||||||
|
pct start "$CT_ID"
|
||||||
|
|
||||||
|
info "Warte auf Netzwerk..."
|
||||||
|
local tries=0
|
||||||
|
until pct exec "$CT_ID" -- bash -c "ip route | grep -q default" 2>/dev/null; do
|
||||||
|
sleep 3; ((tries++))
|
||||||
|
[[ $tries -ge 20 ]] && error "Netzwerk im LXC nicht erreichbar. Prüfe Bridge/IP."
|
||||||
|
echo -n "."
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
success "Container läuft und hat Netzwerk"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Inneres Setup-Script generieren und ausführen ─────────────────────────────
|
||||||
|
run_inner_setup() {
|
||||||
|
step "Freqtrade innerhalb des LXC installieren"
|
||||||
|
|
||||||
|
# Zufällige Secrets für FreqUI generieren
|
||||||
|
JWT_SECRET=$(openssl rand -hex 32 2>/dev/null || tr -dc 'a-f0-9' < /dev/urandom | head -c 64)
|
||||||
|
WS_TOKEN=$(openssl rand -hex 16 2>/dev/null || tr -dc 'a-f0-9' < /dev/urandom | head -c 32)
|
||||||
|
|
||||||
|
# Telegram-Block für config.json vorbereiten
|
||||||
|
if [[ "$FT_TELEGRAM" == "true" ]]; then
|
||||||
|
TG_JSON='"telegram": {"enabled": true, "token": "'"$TG_TOKEN"'", "chat_id": "'"$TG_CHATID"'"},'
|
||||||
|
else
|
||||||
|
TG_JSON='"telegram": {"enabled": false, "token": "", "chat_id": ""},'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Inner-Script in eine Temp-Datei schreiben (Variablen werden jetzt expandiert)
|
||||||
|
cat > /tmp/ft_inner_setup.sh << INNEREOF
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
||||||
|
CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
|
||||||
|
ok() { echo -e "\${GREEN}[ OK ]\${NC} \$*"; }
|
||||||
|
inf() { echo -e "\${CYAN}[INF]\${NC} \$*"; }
|
||||||
|
fail() { echo -e "\${RED}[ERR]\${NC} \$*"; exit 1; }
|
||||||
|
|
||||||
|
INSTALL_DIR="/opt/docker-projekte"
|
||||||
|
FT_DIR="\$INSTALL_DIR/freqtrade"
|
||||||
|
FT_PORT="${FT_PORT}"
|
||||||
|
FT_EXCHANGE="${FT_EXCHANGE}"
|
||||||
|
FT_STAKE="${FT_STAKE}"
|
||||||
|
FT_MAX_TRADES="${FT_MAX_TRADES}"
|
||||||
|
FT_TIMEFRAME="${FT_TIMEFRAME}"
|
||||||
|
FT_API_USER="${FT_API_USER}"
|
||||||
|
FT_API_PASS="${FT_API_PASS}"
|
||||||
|
JWT_SECRET="${JWT_SECRET}"
|
||||||
|
WS_TOKEN="${WS_TOKEN}"
|
||||||
|
INSTALL_FB="${INSTALL_FB}"
|
||||||
|
FB_PORT="${FB_PORT}"
|
||||||
|
|
||||||
|
# ── System-Pakete ─────────────────────────────────────────────────────────────
|
||||||
|
inf "System aktualisieren..."
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install -y -qq curl ca-certificates gnupg lsb-release net-tools
|
||||||
|
ok "Systempakete installiert"
|
||||||
|
|
||||||
|
# ── Docker installieren ───────────────────────────────────────────────────────
|
||||||
|
inf "Docker installieren..."
|
||||||
|
curl -fsSL https://get.docker.com | sh > /dev/null 2>&1
|
||||||
|
systemctl enable docker --now > /dev/null 2>&1
|
||||||
|
ok "Docker installiert: \$(docker --version)"
|
||||||
|
|
||||||
|
# ── Verzeichnisse anlegen ─────────────────────────────────────────────────────
|
||||||
|
mkdir -p "\$FT_DIR"
|
||||||
|
mkdir -p "\$INSTALL_DIR/filebrowser/config"
|
||||||
|
mkdir -p "\$INSTALL_DIR/filebrowser/database"
|
||||||
|
ok "Verzeichnisse angelegt"
|
||||||
|
|
||||||
|
# ── Filebrowser (optional) ────────────────────────────────────────────────────
|
||||||
|
if [[ "\$INSTALL_FB" == "true" ]]; then
|
||||||
|
inf "Filebrowser installieren..."
|
||||||
|
cat > "\$INSTALL_DIR/filebrowser/docker-compose.yml" << 'FBEOF'
|
||||||
|
services:
|
||||||
|
filebrowser:
|
||||||
|
image: filebrowser/filebrowser:latest
|
||||||
|
container_name: filebrowser
|
||||||
|
user: "0:0"
|
||||||
|
ports:
|
||||||
|
- "FBPORT:8080"
|
||||||
|
volumes:
|
||||||
|
- /opt/docker-projekte:/srv
|
||||||
|
- /opt/docker-projekte/filebrowser/database:/database
|
||||||
|
- /opt/docker-projekte/filebrowser/config:/config
|
||||||
|
command: ["--address","0.0.0.0","--port","8080",
|
||||||
|
"--database","/database/filebrowser.db",
|
||||||
|
"--root","/srv","--noauth=false"]
|
||||||
|
restart: unless-stopped
|
||||||
|
FBEOF
|
||||||
|
# Port einsetzen (war im Heredoc wegen einfacher Anführungszeichen nicht ersetzt)
|
||||||
|
sed -i "s/FBPORT/\${FB_PORT}/g" "\$INSTALL_DIR/filebrowser/docker-compose.yml"
|
||||||
|
|
||||||
|
cd "\$INSTALL_DIR/filebrowser"
|
||||||
|
docker compose up -d > /dev/null 2>&1
|
||||||
|
sleep 4
|
||||||
|
FB_PASS=\$(docker logs filebrowser 2>&1 | grep -oP "(?<=randomly generated password: )\S+" | tail -1 || echo "siehe: docker logs filebrowser")
|
||||||
|
ok "Filebrowser gestartet – Passwort: \$FB_PASS"
|
||||||
|
echo "FILEBROWSER_PASS=\$FB_PASS" >> /root/ft_install_info.txt
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Freqtrade docker-compose.yml ──────────────────────────────────────────────
|
||||||
|
inf "Freqtrade docker-compose.yml herunterladen..."
|
||||||
|
cd "\$FT_DIR"
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/freqtrade/freqtrade/stable/docker-compose.yml \
|
||||||
|
-o docker-compose.yml
|
||||||
|
# Nur localhost → 0.0.0.0 für WebUI-Erreichbarkeit
|
||||||
|
sed -i 's/127\.0\.0\.1/0.0.0.0/g' docker-compose.yml
|
||||||
|
ok "docker-compose.yml vorbereitet"
|
||||||
|
|
||||||
|
# ── user_data Verzeichnis erstellen ───────────────────────────────────────────
|
||||||
|
inf "user_data erstellen..."
|
||||||
|
docker compose run --rm freqtrade create-userdir --userdir user_data > /dev/null 2>&1
|
||||||
|
ok "user_data erstellt"
|
||||||
|
|
||||||
|
# ── config.json generieren ────────────────────────────────────────────────────
|
||||||
|
inf "config.json erstellen..."
|
||||||
|
cat > "\$FT_DIR/user_data/config.json" << CONFIGEOF
|
||||||
|
{
|
||||||
|
"max_open_trades": ${FT_MAX_TRADES},
|
||||||
|
"stake_currency": "${FT_STAKE}",
|
||||||
|
"stake_amount": "unlimited",
|
||||||
|
"tradable_balance_ratio": 0.99,
|
||||||
|
"fiat_display_currency": "EUR",
|
||||||
|
"timeframe": "${FT_TIMEFRAME}",
|
||||||
|
"dry_run": true,
|
||||||
|
"dry_run_wallet": 1000,
|
||||||
|
"cancel_open_orders_on_exit": false,
|
||||||
|
"trading_mode": "spot",
|
||||||
|
"margin_mode": "",
|
||||||
|
"unfilledtimeout": {
|
||||||
|
"entry": 10,
|
||||||
|
"exit": 10,
|
||||||
|
"exit_timeout_count": 0,
|
||||||
|
"unit": "minutes"
|
||||||
|
},
|
||||||
|
"entry_pricing": {
|
||||||
|
"price_side": "same",
|
||||||
|
"use_order_book": true,
|
||||||
|
"order_book_top": 1,
|
||||||
|
"price_last_balance": 0.0,
|
||||||
|
"check_depth_of_market": {"enabled": false, "bids_to_ask_delta": 1}
|
||||||
|
},
|
||||||
|
"exit_pricing": {
|
||||||
|
"price_side": "same",
|
||||||
|
"use_order_book": true,
|
||||||
|
"order_book_top": 1
|
||||||
|
},
|
||||||
|
"exchange": {
|
||||||
|
"name": "${FT_EXCHANGE}",
|
||||||
|
"key": "",
|
||||||
|
"secret": "",
|
||||||
|
"ccxt_config": {},
|
||||||
|
"ccxt_async_config": {}
|
||||||
|
},
|
||||||
|
"pairlists": [{"method": "StaticPairList"}],
|
||||||
|
"pair_whitelist": [
|
||||||
|
"${FT_STAKE}/USDT",
|
||||||
|
"BTC/${FT_STAKE}",
|
||||||
|
"ETH/${FT_STAKE}"
|
||||||
|
],
|
||||||
|
${TG_JSON}
|
||||||
|
"api_server": {
|
||||||
|
"enabled": true,
|
||||||
|
"listen_ip_address": "0.0.0.0",
|
||||||
|
"listen_port": 8080,
|
||||||
|
"verbosity": "error",
|
||||||
|
"enable_openapi": false,
|
||||||
|
"jwt_secret_key": "${JWT_SECRET}",
|
||||||
|
"ws_token": "${WS_TOKEN}",
|
||||||
|
"CORS_origins": [],
|
||||||
|
"username": "${FT_API_USER}",
|
||||||
|
"password": "${FT_API_PASS}"
|
||||||
|
},
|
||||||
|
"bot_name": "freqtrade",
|
||||||
|
"initial_state": "running",
|
||||||
|
"force_entry_enable": false,
|
||||||
|
"internals": {"process_throttle_secs": 5}
|
||||||
|
}
|
||||||
|
CONFIGEOF
|
||||||
|
ok "config.json erstellt"
|
||||||
|
|
||||||
|
# ── Freqtrade starten ─────────────────────────────────────────────────────────
|
||||||
|
inf "Freqtrade starten..."
|
||||||
|
cd "\$FT_DIR"
|
||||||
|
docker compose up -d > /dev/null 2>&1
|
||||||
|
sleep 5
|
||||||
|
if docker ps | grep -q freqtrade; then
|
||||||
|
ok "Freqtrade läuft"
|
||||||
|
else
|
||||||
|
fail "Freqtrade gestartet nicht – prüfe: docker logs freqtrade"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Info-Datei für Proxmox-Script ─────────────────────────────────────────────
|
||||||
|
LXC_IP=\$(hostname -I | awk '{print \$1}')
|
||||||
|
cat > /root/ft_install_info.txt << INFOEOF
|
||||||
|
LXC_IP=\$LXC_IP
|
||||||
|
FT_PORT=${FT_PORT}
|
||||||
|
FT_API_USER=${FT_API_USER}
|
||||||
|
FB_PORT=${FB_PORT}
|
||||||
|
INSTALL_FB=${INSTALL_FB}
|
||||||
|
INFOEOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Freqtrade Installation abgeschlossen ==="
|
||||||
|
echo "WebUI: http://\$LXC_IP:${FT_PORT}"
|
||||||
|
echo "User: ${FT_API_USER}"
|
||||||
|
INNEREOF
|
||||||
|
|
||||||
|
# Script in den LXC schieben und ausführen
|
||||||
|
pct push "$CT_ID" /tmp/ft_inner_setup.sh /root/ft_setup.sh
|
||||||
|
pct exec "$CT_ID" -- chmod +x /root/ft_setup.sh
|
||||||
|
info "Starte Installation im LXC (kann 2-3 Minuten dauern)..."
|
||||||
|
pct exec "$CT_ID" -- bash /root/ft_setup.sh
|
||||||
|
|
||||||
|
rm -f /tmp/ft_inner_setup.sh
|
||||||
|
success "Installation im LXC abgeschlossen"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Ergebnis anzeigen ─────────────────────────────────────────────────────────
|
||||||
|
show_result() {
|
||||||
|
# Info-Datei aus dem LXC lesen
|
||||||
|
local TMP_INFO="/tmp/ft_info_${CT_ID}.txt"
|
||||||
|
pct pull "$CT_ID" /root/ft_install_info.txt "$TMP_INFO" 2>/dev/null || true
|
||||||
|
|
||||||
|
LXC_IP=""
|
||||||
|
FB_PASS=""
|
||||||
|
if [[ -f "$TMP_INFO" ]]; then
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$TMP_INFO"
|
||||||
|
rm -f "$TMP_INFO"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Falls IP leer, über pct ermitteln
|
||||||
|
if [[ -z "$LXC_IP" ]]; then
|
||||||
|
LXC_IP=$(pct exec "$CT_ID" -- hostname -I 2>/dev/null | awk '{print $1}' || echo "unbekannt")
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "${BOLD}${GREEN}╔══════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${BOLD}${GREEN}║ ✅ Installation erfolgreich! ║${NC}"
|
||||||
|
echo -e "${BOLD}${GREEN}╚══════════════════════════════════════════╝${NC}"
|
||||||
|
echo
|
||||||
|
echo -e " ${BOLD}LXC Container:${NC} ID ${CYAN}$CT_ID${NC} | Host: ${CYAN}$CT_HOST${NC}"
|
||||||
|
echo -e " ${BOLD}IP-Adresse:${NC} ${CYAN}$LXC_IP${NC}"
|
||||||
|
echo
|
||||||
|
echo -e " ${BOLD}${GREEN}FreqUI (Freqtrade WebUI):${NC}"
|
||||||
|
echo -e " ${CYAN}http://${LXC_IP}:${FT_PORT}${NC}"
|
||||||
|
echo -e " Benutzer: ${CYAN}$FT_API_USER${NC}"
|
||||||
|
echo
|
||||||
|
if [[ "$INSTALL_FB" == "true" ]]; then
|
||||||
|
echo -e " ${BOLD}${GREEN}Filebrowser (Dateimanager):${NC}"
|
||||||
|
echo -e " ${CYAN}http://${LXC_IP}:${FB_PORT}${NC}"
|
||||||
|
echo -e " Benutzer: ${CYAN}admin${NC}"
|
||||||
|
[[ -n "${FILEBROWSER_PASS:-}" ]] && echo -e " Passwort: ${CYAN}$FILEBROWSER_PASS${NC} ${YELLOW}← sofort ändern!${NC}"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
echo -e " ${BOLD}Config-Datei:${NC}"
|
||||||
|
echo -e " ${CYAN}/opt/docker-projekte/freqtrade/user_data/config.json${NC}"
|
||||||
|
echo
|
||||||
|
echo -e " ${BOLD}${YELLOW}Nächste Schritte:${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}3. Für NordVPN: install-vpn.sh im LXC ausführen${NC}"
|
||||||
|
echo
|
||||||
|
echo -e " ${BOLD}NordVPN Addon (im LXC ausführen):${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
|
||||||
|
echo -e " ${BOLD}LXC Konsole öffnen:${NC}"
|
||||||
|
echo -e " ${CYAN}pct enter $CT_ID${NC}"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Hauptprogramm ─────────────────────────────────────────────────────────────
|
||||||
|
main() {
|
||||||
|
print_banner
|
||||||
|
check_host
|
||||||
|
detect_resources
|
||||||
|
prepare_template
|
||||||
|
collect_config
|
||||||
|
create_lxc
|
||||||
|
run_inner_setup
|
||||||
|
show_result
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
Reference in New Issue
Block a user