#!/usr/bin/env bash # PlayBull Homelab-Installer — Ziel: ~/bestewebsite/bestewebsite # DuckDNS + playbull.service + Cloudflare Tunnel (cloudflared service install) set -euo pipefail if [[ "${EUID}" -ne 0 ]]; then echo "Bitte als root ausfuehren: sudo bash deploy/install-homelab.sh" >&2 exit 1 fi SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" if [[ ! -f "${SCRIPT_DIR}/env.homelab" ]]; then cp "${SCRIPT_DIR}/env.homelab.example" "${SCRIPT_DIR}/env.homelab" echo "deploy/env.homelab erstellt — Token eintragen und erneut starten." >&2 exit 1 fi # shellcheck source=/dev/null source <(sed 's/\r$//' "${SCRIPT_DIR}/env.homelab") APP_PORT="${APP_PORT:-3080}" APP_DIR="${APP_DIR:-/home/gizzler/bestewebsite/bestewebsite}" APP_DIR="${APP_DIR//$'\r'/}" APP_USER="${APP_USER:-gizzler}" APP_USER="${APP_USER//$'\r'/}" DUCKDNS_DOMAIN="${DUCKDNS_DOMAIN:-}" DUCKDNS_DOMAIN="${DUCKDNS_DOMAIN//$'\r'/}" DUCKDNS_TOKEN="${DUCKDNS_TOKEN:-}" DUCKDNS_TOKEN="${DUCKDNS_TOKEN//$'\r'/}" APP_DOMAIN="${APP_DOMAIN:-trilogyhub.de}" APP_DOMAIN="${APP_DOMAIN//$'\r'/}" CLOUDFLARE_API_TOKEN="${CLOUDFLARE_API_TOKEN:-}" CLOUDFLARE_API_TOKEN="${CLOUDFLARE_API_TOKEN//$'\r'/}" CLOUDFLARE_ZONE_ID="${CLOUDFLARE_ZONE_ID:-}" CLOUDFLARE_ZONE_ID="${CLOUDFLARE_ZONE_ID//$'\r'/}" CLOUDFLARE_TUNNEL_TOKEN="${CLOUDFLARE_TUNNEL_TOKEN:-}" CLOUDFLARE_TUNNEL_TOKEN="${CLOUDFLARE_TUNNEL_TOKEN//$'\r'/}" JWT_SECRET="${JWT_SECRET:-}" JWT_SECRET="${JWT_SECRET//$'\r'/}" FINNHUB_API_KEY="${FINNHUB_API_KEY:-}" FINNHUB_API_KEY="${FINNHUB_API_KEY//$'\r'/}" echo "==> PlayBull / Trilogy Hub Homelab Setup" echo " Domain: ${APP_DOMAIN}" echo " Port: ${APP_PORT}" echo " Pfad: ${APP_DIR}" echo "" install_unit() { local src="$1" dest="$2" sed -e "s|__APP_DIR__|${APP_DIR}|g" \ -e "s|__APP_USER__|${APP_USER}|g" \ "${src}" > "${dest}" } need_pkg() { command -v "$1" >/dev/null 2>&1; } if [[ "${SKIP_APT:-0}" != "1" ]] && command -v apt-get >/dev/null 2>&1; then echo "==> Paketlisten aktualisieren..." apt-get update -qq PKGS=(curl ca-certificates rsync build-essential libvips-dev) MISSING=() for p in "${PKGS[@]}"; do need_pkg "$p" || MISSING+=("$p"); done if ((${#MISSING[@]})); then apt-get install -y "${MISSING[@]}" fi elif [[ "${SKIP_APT:-0}" != "1" ]] && command -v dnf >/dev/null 2>&1; then dnf install -y curl ca-certificates rsync gcc-c++ make vips-devel fi if ! command -v cloudflared >/dev/null 2>&1; then echo "==> cloudflared installieren" ARCH="$(uname -m)" case "${ARCH}" in x86_64) CF_ARCH=amd64 ;; aarch64|arm64) CF_ARCH=arm64 ;; *) echo "Unsupported arch: ${ARCH}" >&2; exit 1 ;; esac curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${CF_ARCH}" \ -o /usr/local/bin/cloudflared chmod +x /usr/local/bin/cloudflared ln -sf /usr/local/bin/cloudflared /usr/bin/cloudflared fi if ! command -v node >/dev/null 2>&1 || [[ "$(node -p "process.versions.node.split('.')[0]")" -lt 24 ]]; then echo "==> Node.js 24 installieren (NodeSource)" if command -v apt-get >/dev/null 2>&1; then curl -fsSL https://deb.nodesource.com/setup_24.x | bash - apt-get install -y nodejs else dnf install -y nodejs fi fi mkdir -p "${APP_DIR}" "${APP_DIR}/data" "${APP_DIR}/public/uploads" if [[ "${REPO_ROOT}" != "${APP_DIR}" ]]; then echo "==> Dateien nach ${APP_DIR} synchronisieren" rsync -a --delete \ --exclude node_modules \ --exclude data \ --exclude .git \ --exclude server.js \ --exclude server.py \ --exclude start.bat \ "${REPO_ROOT}/" "${APP_DIR}/" fi chown -R "${APP_USER}:${APP_USER}" "${APP_DIR}" 2>/dev/null || true chmod +x "${APP_DIR}/deploy/duckdns-update.sh" \ "${APP_DIR}/deploy/cloudflare-ddns-update.sh" \ "${APP_DIR}/deploy/finish-on-server.sh" \ "${APP_DIR}/deploy/sync-user.sh" 2>/dev/null || true # ---- .env (nur ergaenzen, nicht ueberschreiben) ---- ENV_FILE="${APP_DIR}/.env" touch "${ENV_FILE}" grep -q '^PORT=' "${ENV_FILE}" 2>/dev/null \ && sed -i "s/^PORT=.*/PORT=${APP_PORT}/" "${ENV_FILE}" \ || echo "PORT=${APP_PORT}" >> "${ENV_FILE}" grep -q '^TRUST_PROXY=' "${ENV_FILE}" 2>/dev/null || echo "TRUST_PROXY=1" >> "${ENV_FILE}" grep -q '^START_BALANCE=' "${ENV_FILE}" 2>/dev/null || echo "START_BALANCE=10000" >> "${ENV_FILE}" grep -q '^JWT_SECRET=' "${ENV_FILE}" 2>/dev/null || { [[ -n "${JWT_SECRET:-}" ]] && echo "JWT_SECRET=${JWT_SECRET}" >> "${ENV_FILE}"; } grep -q '^FINNHUB_API_KEY=' "${ENV_FILE}" 2>/dev/null || { [[ -n "${FINNHUB_API_KEY:-}" ]] && echo "FINNHUB_API_KEY=${FINNHUB_API_KEY}" >> "${ENV_FILE}"; } if [[ "${APP_USER}" == "root" ]]; then bash -c "cd '${APP_DIR}' && npm install --omit=dev" else sudo -u "${APP_USER}" bash -c "cd '${APP_DIR}' && npm install --omit=dev" fi # ---- Alten bestewebsite-Service abloesen ---- if systemctl is-active --quiet bestewebsite.service 2>/dev/null; then echo "==> bestewebsite.service stoppen (Migration zu playbull)" systemctl stop bestewebsite.service fi systemctl disable bestewebsite.service 2>/dev/null || true # ---- Cloudflare Tunnel (wie bestewebsite: cloudflared service install) ---- if [[ -n "${CLOUDFLARE_TUNNEL_TOKEN:-}" ]]; then echo "==> Cloudflare Tunnel" systemctl stop cloudflared-playbull.service 2>/dev/null || true systemctl disable cloudflared-playbull.service 2>/dev/null || true cloudflared service uninstall 2>/dev/null || true cloudflared service install "${CLOUDFLARE_TUNNEL_TOKEN}" systemctl enable cloudflared systemctl restart cloudflared echo " cloudflared gestartet." else echo "" echo ">>> CLOUDFLARE_TUNNEL_TOKEN fehlt in deploy/env.homelab" echo " Zero Trust → Tunnel → Public Hostname: ${APP_DOMAIN} -> http://127.0.0.1:${APP_PORT}" echo "" fi # ---- Cloudflare Dynamic DNS (ersetzt DuckDNS) ---- echo "==> Cloudflare DDNS Timer" install_unit "${APP_DIR}/deploy/systemd/cloudflare-ddns-update.service" /etc/systemd/system/cloudflare-ddns-update.service cp "${APP_DIR}/deploy/systemd/cloudflare-ddns-update.timer" /etc/systemd/system/ chmod 600 "${APP_DIR}/deploy/env.homelab" if [[ -n "${CLOUDFLARE_API_TOKEN:-}" && -n "${CLOUDFLARE_ZONE_ID:-}" ]]; then "${APP_DIR}/deploy/cloudflare-ddns-update.sh" || echo " Cloudflare-DDNS fehlgeschlagen (API/Zone pruefen)" else echo " Cloudflare-DDNS uebersprungen (CLOUDFLARE_API_TOKEN oder ZONE_ID leer)" fi # ---- DuckDNS (legacy, optional) ---- if [[ -n "${DUCKDNS_TOKEN:-}" ]]; then echo "==> DuckDNS (legacy)" install_unit "${APP_DIR}/deploy/systemd/duckdns-update.service" /etc/systemd/system/duckdns-update.service cp "${APP_DIR}/deploy/systemd/duckdns-update.timer" /etc/systemd/system/ "${APP_DIR}/deploy/duckdns-update.sh" || true fi # ---- playbull systemd ---- echo "==> playbull.service" install_unit "${APP_DIR}/deploy/systemd/playbull.service" /etc/systemd/system/playbull.service systemctl daemon-reload if [[ -n "${CLOUDFLARE_API_TOKEN:-}" && -n "${CLOUDFLARE_ZONE_ID:-}" ]]; then systemctl enable --now cloudflare-ddns-update.timer systemctl start cloudflare-ddns-update.service || true else systemctl disable cloudflare-ddns-update.timer 2>/dev/null || true fi if [[ -n "${DUCKDNS_TOKEN:-}" ]]; then systemctl enable --now duckdns-update.timer systemctl start duckdns-update.service || true else systemctl disable duckdns-update.timer 2>/dev/null || true fi systemctl enable --now playbull.service systemctl restart playbull.service # ---- Optional Nginx ---- if [[ "${USE_NGINX_VHOST:-0}" == "1" ]]; then echo "==> Nginx VHost (optional)" if command -v apt-get >/dev/null 2>&1; then apt-get install -y nginx certbot python3-certbot-nginx fi cp "${APP_DIR}/deploy/nginx/playbull.conf" /etc/nginx/sites-available/playbull ln -sf /etc/nginx/sites-available/playbull /etc/nginx/sites-enabled/playbull certbot --nginx -d "${APP_DOMAIN}" -d "www.${APP_DOMAIN}" --non-interactive --agree-tos -m "admin@${APP_DOMAIN}" || true nginx -t && systemctl reload nginx fi echo "" echo "=== Fertig ===" echo "Pfad: ${APP_DIR}" echo "Intern: http://127.0.0.1:${APP_PORT}" echo "DuckDNS: ${DUCKDNS_DOMAIN:-(deaktiviert)}" echo "Status: systemctl status playbull cloudflared cloudflare-ddns-update.timer" if [[ -n "${CLOUDFLARE_TUNNEL_TOKEN:-}" ]]; then echo "HTTPS: https://${APP_DOMAIN}" fi echo "" echo "Hinweis: JWT_SECRET und FINNHUB_API_KEY in ${ENV_FILE} pruefen, dann:" echo " sudo systemctl restart playbull"