v0.22.0: First-run setup wizard, local infra backup, hub verification
New controller features:
- Web-based setup wizard replaces docker-setup.sh interactive config
- Dual listener: :8080 (Traefik) + :8081 (direct HTTP for LAN)
- Drive scanner finds .felhom-infra-backup/ on all block devices
- Hub recovery pull (GET /api/v1/recovery/{id}) with retrieval password
- Fresh install: Hub config download or manual wizard
- CSRF protection, state persistence, Hungarian UI
- Local infra backup written to all connected drives after each backup cycle
- .felhom-infra-backup/backup.json + metadata.json with SHA256 checksum
- Hub verification: parse customer_blocked from report push response
- Limited mode after 7 days without verification
- Recovery info page on Settings + recovery-info.txt file generation
- Pending events queue: DR events sent to Hub on next report push
- docker-setup.sh v6.0.0: removed interactive wizard, minimal controller.yaml only
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+80
-366
@@ -1,17 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
#===============================================================================
|
||||
# Felhom Infrastructure Setup v5.0
|
||||
# Felhom Infrastructure Setup v6.0
|
||||
# Prepares a Debian 13 server for Felhom homeserver deployment
|
||||
#
|
||||
# This script sets up the complete infrastructure:
|
||||
# This script sets up the infrastructure:
|
||||
# - Docker Engine + Compose
|
||||
# - Traefik reverse proxy
|
||||
# - TLS certificates (Let's Encrypt via Cloudflare DNS or self-signed)
|
||||
# - Interactive configuration wizard (generates controller.yaml)
|
||||
# - Cloudflare Tunnel connector (optional, configured via wizard)
|
||||
# - Minimal controller.yaml (full configuration via web UI setup wizard)
|
||||
# - Cloudflare Tunnel connector (optional, via --cf-tunnel-token)
|
||||
# - FileBrowser Quantum (web-based file manager)
|
||||
# - Felhom Controller (automatic deployment + dashboard)
|
||||
# - Felhom Controller (with web-based setup wizard on :8081)
|
||||
# - Helper tools (ctop, lazydocker, shell aliases)
|
||||
#
|
||||
# Application stacks are managed via the felhom-controller dashboard.
|
||||
@@ -26,10 +26,11 @@
|
||||
# --gateway ADDRESS Gateway address (default: 192.168.0.1)
|
||||
# --dns ADDRESS DNS server (default: 1.1.1.1,8.8.8.8)
|
||||
# --interface NAME Network interface (default: auto-detect)
|
||||
# --domain DOMAIN Base domain (pre-seeds wizard)
|
||||
# --email EMAIL ACME email (pre-seeds wizard)
|
||||
# --cf-token TOKEN Cloudflare API token (pre-seeds wizard)
|
||||
# --customer ID Customer identifier (pre-seeds wizard)
|
||||
# --domain DOMAIN Base domain for services (required)
|
||||
# --email EMAIL ACME email for Let's Encrypt
|
||||
# --cf-token TOKEN Cloudflare API token for DNS-01 TLS
|
||||
# --cf-tunnel-token TK Cloudflare Tunnel token (optional)
|
||||
# --customer ID Customer identifier (optional, set in web wizard)
|
||||
# --traefik-password PW Password for Traefik dashboard (default: auto-generated)
|
||||
# --self-signed-cert Generate self-signed wildcard certificate
|
||||
# --skip-filebrowser Skip FileBrowser installation
|
||||
@@ -119,7 +120,7 @@ done
|
||||
#-------------------------------------------------------------------------------
|
||||
# Configuration
|
||||
#-------------------------------------------------------------------------------
|
||||
SCRIPT_VERSION="5.0.0"
|
||||
SCRIPT_VERSION="6.0.0"
|
||||
|
||||
# Default values
|
||||
STATIC_IP=""
|
||||
@@ -135,9 +136,7 @@ DRY_RUN=false
|
||||
SELF_SIGNED_CERT=false
|
||||
DEBUG_MODE=false
|
||||
CUSTOMER_ID=""
|
||||
HUB_CUSTOMER_ID=""
|
||||
HUB_PASSWORD=""
|
||||
HUB_URL="https://hub.felhom.eu"
|
||||
CF_TUNNEL_TOKEN=""
|
||||
|
||||
# Directories
|
||||
DOCKER_DATA_DIR="/opt/docker"
|
||||
@@ -193,11 +192,12 @@ print_banner() {
|
||||
|
||||
print_help() {
|
||||
cat << 'EOF'
|
||||
Felhom Infrastructure Setup v5.0
|
||||
Felhom Infrastructure Setup v6.0
|
||||
|
||||
Prepares a Debian 13 server for Felhom homeserver deployment. Installs
|
||||
infrastructure, runs an interactive configuration wizard, generates
|
||||
controller.yaml, and deploys felhom-controller — all in one run.
|
||||
infrastructure, generates a minimal controller.yaml, and deploys
|
||||
felhom-controller. Full configuration is completed via the web-based
|
||||
setup wizard at http://<ip>:8081.
|
||||
|
||||
USAGE:
|
||||
./docker-setup.sh --bootstrap # First, on fresh Debian
|
||||
@@ -205,14 +205,15 @@ USAGE:
|
||||
|
||||
OPTIONS:
|
||||
--bootstrap Install sudo (run first on fresh Debian)
|
||||
--customer ID Customer identifier (pre-seeds wizard)
|
||||
--domain DOMAIN Base domain for services (required)
|
||||
--customer ID Customer identifier (optional, set in web wizard)
|
||||
--ip ADDRESS Static IP address
|
||||
--gateway ADDRESS Gateway (default: 192.168.0.1)
|
||||
--dns ADDRESS DNS servers, comma-separated (default: 1.1.1.1,8.8.8.8)
|
||||
--interface NAME Network interface (default: auto-detect)
|
||||
--domain DOMAIN Base domain for services (pre-seeds wizard)
|
||||
--email EMAIL Email for Let's Encrypt (pre-seeds wizard)
|
||||
--cf-token TOKEN Cloudflare API token for DNS-01 (pre-seeds wizard)
|
||||
--email EMAIL Email for Let's Encrypt
|
||||
--cf-token TOKEN Cloudflare API token for DNS-01 TLS
|
||||
--cf-tunnel-token TK Cloudflare Tunnel token (optional)
|
||||
--traefik-password PW Password for Traefik dashboard (default: auto-generated)
|
||||
--self-signed-cert Generate self-signed wildcard certificate (fallback)
|
||||
--skip-filebrowser Skip FileBrowser installation
|
||||
@@ -220,9 +221,6 @@ OPTIONS:
|
||||
--debug Enable verbose debug output
|
||||
-h, --help Show this help
|
||||
|
||||
CLI options pre-seed the interactive wizard — values can be changed
|
||||
during the wizard prompts.
|
||||
|
||||
TLS CERTIFICATE OPTIONS:
|
||||
There are three TLS modes (in order of preference):
|
||||
|
||||
@@ -241,9 +239,9 @@ WHAT THIS SCRIPT INSTALLS:
|
||||
2. Docker Engine + Docker Compose
|
||||
3. Traefik reverse proxy (with dashboard)
|
||||
4. TLS certificates (Let's Encrypt or self-signed)
|
||||
5. Felhom Controller (with interactive configuration wizard)
|
||||
5. Felhom Controller (with web-based setup wizard on :8081)
|
||||
6. FileBrowser Quantum (web file manager at files.<domain>)
|
||||
7. Cloudflare Tunnel (if configured in wizard)
|
||||
7. Cloudflare Tunnel (if --cf-tunnel-token provided)
|
||||
8. Helper tools (ctop, lazydocker, shell aliases)
|
||||
|
||||
EXAMPLES:
|
||||
@@ -251,15 +249,16 @@ EXAMPLES:
|
||||
sudo ./docker-setup.sh --domain demo-felhom.eu --customer demo-felhom \
|
||||
--email certs@felhom.eu --cf-token cf-xxxxxxxxxxxx
|
||||
|
||||
# Minimal (wizard will prompt for everything)
|
||||
sudo ./docker-setup.sh
|
||||
# Minimal (setup wizard handles everything)
|
||||
sudo ./docker-setup.sh --domain example.com
|
||||
|
||||
# Self-signed cert (offline/testing)
|
||||
sudo ./docker-setup.sh --domain example.com --self-signed-cert
|
||||
|
||||
# Full setup with static IP
|
||||
# Full setup with static IP + Cloudflare Tunnel
|
||||
sudo ./docker-setup.sh --domain demo-felhom.eu --customer demo-felhom \
|
||||
--ip 192.168.0.50 --email certs@felhom.eu --cf-token cf-xxxxxxxxxxxx
|
||||
--ip 192.168.0.50 --email certs@felhom.eu --cf-token cf-xxx \
|
||||
--cf-tunnel-token eyJhIjoi...
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -304,12 +303,9 @@ parse_args() {
|
||||
--customer)
|
||||
require_arg "$1" "${2:-}"
|
||||
CUSTOMER_ID="$2"; shift 2 ;;
|
||||
--hub-customer)
|
||||
--cf-tunnel-token)
|
||||
require_arg "$1" "${2:-}"
|
||||
HUB_CUSTOMER_ID="$2"; shift 2 ;;
|
||||
--hub-password)
|
||||
require_arg "$1" "${2:-}"
|
||||
HUB_PASSWORD="$2"; shift 2 ;;
|
||||
CF_TUNNEL_TOKEN="$2"; shift 2 ;;
|
||||
--self-signed-cert) SELF_SIGNED_CERT=true; shift ;;
|
||||
--skip-filebrowser) SKIP_FILEBROWSER=true; shift ;;
|
||||
--dry-run) DRY_RUN=true; shift ;;
|
||||
@@ -445,8 +441,8 @@ detect_network_manager_debug() {
|
||||
|
||||
# Calculate total number of steps dynamically
|
||||
get_total_steps() {
|
||||
local total=8 # base: packages, network, docker, traefik, cert, wizard, controller, tools
|
||||
[[ -n "${WIZ_CF_TUNNEL_TOKEN:-}" ]] && ((total++))
|
||||
local total=7 # base: packages, network, docker, traefik, cert, controller, tools
|
||||
[[ -n "${CF_TUNNEL_TOKEN:-}" ]] && ((total++))
|
||||
[[ "$SKIP_FILEBROWSER" != true ]] && ((total++))
|
||||
echo "$total"
|
||||
}
|
||||
@@ -1029,12 +1025,12 @@ EOF
|
||||
# Step 4b: Install Cloudflare Tunnel connector (optional)
|
||||
#-------------------------------------------------------------------------------
|
||||
install_cloudflare_tunnel() {
|
||||
if [[ -z "${WIZ_CF_TUNNEL_TOKEN:-}" ]]; then
|
||||
log_skip "Cloudflare Tunnel not configured (skipped in wizard)"
|
||||
if [[ -z "${CF_TUNNEL_TOKEN:-}" ]]; then
|
||||
log_skip "Cloudflare Tunnel not configured (use --cf-tunnel-token to enable)"
|
||||
return
|
||||
fi
|
||||
|
||||
local step_num=6
|
||||
local step_num=5
|
||||
[[ "$SELF_SIGNED_CERT" == true ]] && ((step_num++))
|
||||
log_step "${step_num}/$(get_total_steps) - Installing Cloudflare Tunnel connector..."
|
||||
|
||||
@@ -1061,7 +1057,7 @@ services:
|
||||
restart: unless-stopped
|
||||
command: tunnel run
|
||||
environment:
|
||||
- TUNNEL_TOKEN="${WIZ_CF_TUNNEL_TOKEN}"
|
||||
- TUNNEL_TOKEN="${CF_TUNNEL_TOKEN}"
|
||||
dns:
|
||||
- 1.1.1.1
|
||||
- 8.8.8.8
|
||||
@@ -1232,9 +1228,9 @@ install_filebrowser() {
|
||||
fi
|
||||
|
||||
# Calculate step number dynamically
|
||||
local step_num=6
|
||||
local step_num=5
|
||||
[[ "$SELF_SIGNED_CERT" == true ]] && ((step_num++))
|
||||
[[ -n "${WIZ_CF_TUNNEL_TOKEN:-}" ]] && ((step_num++))
|
||||
[[ -n "${CF_TUNNEL_TOKEN:-}" ]] && ((step_num++))
|
||||
log_step "${step_num}/$(get_total_steps) - Installing FileBrowser Quantum..."
|
||||
|
||||
# Discover drive mounts for FileBrowser volumes
|
||||
@@ -1257,15 +1253,8 @@ install_filebrowser() {
|
||||
done
|
||||
fi
|
||||
|
||||
# Also add system_data_path from wizard if it's not already in /mnt
|
||||
if [[ -n "${WIZ_SYSTEM_DATA_PATH:-}" && -d "${WIZ_SYSTEM_DATA_PATH}" ]]; then
|
||||
local sdp_name
|
||||
sdp_name=$(basename "${WIZ_SYSTEM_DATA_PATH}")
|
||||
if ! echo "$volume_lines" | grep -qF "${WIZ_SYSTEM_DATA_PATH}"; then
|
||||
volume_lines+=" - \"${WIZ_SYSTEM_DATA_PATH}:/srv/${sdp_name}\""$'\n'
|
||||
((found_mounts++))
|
||||
fi
|
||||
fi
|
||||
# Note: system_data_path is now configured via the web setup wizard,
|
||||
# FileBrowser mounts will be synced by the controller after setup completes.
|
||||
|
||||
if [[ $found_mounts -eq 0 ]]; then
|
||||
log_warn "No mount points found in /mnt/ — FileBrowser will have no drive volumes."
|
||||
@@ -1439,322 +1428,57 @@ EOF
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Configuration wizard — generates controller.yaml
|
||||
# Generate minimal controller.yaml — full configuration via web UI setup wizard
|
||||
#-------------------------------------------------------------------------------
|
||||
# Wizard variables (populated by prompts, used by later steps)
|
||||
WIZ_CUSTOMER_ID=""
|
||||
WIZ_CUSTOMER_NAME=""
|
||||
WIZ_DOMAIN=""
|
||||
WIZ_EMAIL=""
|
||||
WIZ_CF_TUNNEL_TOKEN=""
|
||||
WIZ_CF_API_TOKEN=""
|
||||
WIZ_SYSTEM_DATA_PATH=""
|
||||
WIZ_PASSWORD_HASH=""
|
||||
WIZ_SESSION_SECRET=""
|
||||
WIZ_GIT_REPO=""
|
||||
WIZ_GIT_USERNAME=""
|
||||
WIZ_GIT_TOKEN=""
|
||||
WIZ_HC_HEARTBEAT=""
|
||||
WIZ_HC_SYSTEM=""
|
||||
WIZ_HC_DBDUMP=""
|
||||
WIZ_HC_BACKUP=""
|
||||
WIZ_HC_INTEGRITY=""
|
||||
|
||||
CONTROLLER_DIR="/opt/docker/felhom-controller"
|
||||
|
||||
run_config_wizard() {
|
||||
generate_minimal_config() {
|
||||
local step_num=5
|
||||
[[ "$SELF_SIGNED_CERT" == true ]] && ((step_num++))
|
||||
log_step "${step_num}/$(get_total_steps) - Running configuration wizard..."
|
||||
log_step "${step_num}/$(get_total_steps) - Generating minimal controller.yaml..."
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}${CYAN}===========================================================${NC}"
|
||||
echo -e "${BOLD}${CYAN} Felhom Controller Configuration Wizard${NC}"
|
||||
echo -e "${BOLD}${CYAN}===========================================================${NC}"
|
||||
echo ""
|
||||
|
||||
# In dry-run mode, skip all interactive prompts and set dummy values
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
echo -e "${CYAN}[DRY-RUN]${NC} Would run interactive wizard and generate controller.yaml"
|
||||
WIZ_CUSTOMER_ID="${CUSTOMER_ID:-demo-felhom}"
|
||||
WIZ_CUSTOMER_NAME="${WIZ_CUSTOMER_ID}"
|
||||
WIZ_DOMAIN="${BASE_DOMAIN:-homeserver.local}"
|
||||
WIZ_EMAIL="${ACME_EMAIL:-}"
|
||||
WIZ_CF_TUNNEL_TOKEN=""
|
||||
WIZ_CF_API_TOKEN="${CF_DNS_API_TOKEN:-}"
|
||||
WIZ_SYSTEM_DATA_PATH="/mnt/sys_drive"
|
||||
WIZ_PASSWORD_HASH='<would-be-generated>'
|
||||
WIZ_SESSION_SECRET='<would-be-generated>'
|
||||
WIZ_GIT_REPO="https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git"
|
||||
WIZ_GIT_USERNAME=""
|
||||
WIZ_GIT_TOKEN=""
|
||||
WIZ_HC_HEARTBEAT=""
|
||||
WIZ_HC_SYSTEM=""
|
||||
WIZ_HC_DBDUMP=""
|
||||
WIZ_HC_BACKUP=""
|
||||
WIZ_HC_INTEGRITY=""
|
||||
echo -e "${CYAN}[DRY-RUN]${NC} Would generate minimal controller.yaml (full setup via web UI)"
|
||||
return
|
||||
fi
|
||||
|
||||
# --- Hub download mode ---
|
||||
# If hub credentials are provided, download pre-configured YAML and skip wizard
|
||||
if [[ -n "$HUB_CUSTOMER_ID" && -n "$HUB_PASSWORD" ]]; then
|
||||
log_info "Downloading configuration from Felhom Hub for customer: $HUB_CUSTOMER_ID"
|
||||
mkdir -p "${CONTROLLER_DIR}"
|
||||
local tmp_yaml="${CONTROLLER_DIR}/controller.yaml.tmp"
|
||||
local http_code
|
||||
http_code=$(curl -fsSL -o "$tmp_yaml" -w "%{http_code}" \
|
||||
"${HUB_URL}/api/v1/config/${HUB_CUSTOMER_ID}" \
|
||||
-H "X-Retrieval-Password: ${HUB_PASSWORD}" \
|
||||
2>/dev/null) || true
|
||||
|
||||
if [[ "$http_code" == "200" ]] && [[ -s "$tmp_yaml" ]] && grep -q '^customer:' "$tmp_yaml"; then
|
||||
mv "$tmp_yaml" "${CONTROLLER_DIR}/controller.yaml"
|
||||
chmod 600 "${CONTROLLER_DIR}/controller.yaml"
|
||||
log_success "Configuration downloaded for customer: $HUB_CUSTOMER_ID"
|
||||
|
||||
# Extract key variables that later steps depend on
|
||||
WIZ_CUSTOMER_ID="$HUB_CUSTOMER_ID"
|
||||
WIZ_DOMAIN=$(grep -oP '^\s+domain:\s*"\K[^"]+' "${CONTROLLER_DIR}/controller.yaml" || echo "")
|
||||
WIZ_CF_TUNNEL_TOKEN=$(grep -oP '^\s+cf_tunnel_token:\s*"\K[^"]+' "${CONTROLLER_DIR}/controller.yaml" || echo "")
|
||||
WIZ_CF_API_TOKEN=$(grep -oP '^\s+cf_api_token:\s*"\K[^"]+' "${CONTROLLER_DIR}/controller.yaml" || echo "")
|
||||
WIZ_EMAIL=$(grep -oP '^\s+email:\s*"\K[^"]+' "${CONTROLLER_DIR}/controller.yaml" || echo "")
|
||||
|
||||
# Update global variables that other steps depend on
|
||||
BASE_DOMAIN="${WIZ_DOMAIN}"
|
||||
CUSTOMER_ID="${WIZ_CUSTOMER_ID}"
|
||||
CF_DNS_API_TOKEN="${WIZ_CF_API_TOKEN}"
|
||||
ACME_EMAIL="${WIZ_EMAIL}"
|
||||
return # Skip interactive wizard
|
||||
else
|
||||
rm -f "$tmp_yaml"
|
||||
log_warn "Hub download failed (HTTP ${http_code}). Falling back to manual configuration."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Pre-seed from CLI flags
|
||||
local def_customer="${CUSTOMER_ID}"
|
||||
local def_domain="${BASE_DOMAIN}"
|
||||
local def_email="${ACME_EMAIL}"
|
||||
local def_cf_api="${CF_DNS_API_TOKEN}"
|
||||
|
||||
# --- Customer identity ---
|
||||
echo -e "${BOLD}--- Customer identity ---${NC}"
|
||||
read -rp "Customer ID [${def_customer:-demo-felhom}]: " input
|
||||
WIZ_CUSTOMER_ID="${input:-${def_customer:-demo-felhom}}"
|
||||
|
||||
read -rp "Customer display name [${WIZ_CUSTOMER_ID}]: " input
|
||||
WIZ_CUSTOMER_NAME="${input:-${WIZ_CUSTOMER_ID}}"
|
||||
|
||||
read -rp "Domain [${def_domain}]: " input
|
||||
WIZ_DOMAIN="${input:-${def_domain}}"
|
||||
|
||||
read -rp "Customer email (optional) [${def_email}]: " input
|
||||
WIZ_EMAIL="${input:-${def_email}}"
|
||||
echo ""
|
||||
|
||||
# --- Infrastructure secrets ---
|
||||
echo -e "${BOLD}--- Infrastructure secrets ---${NC}"
|
||||
read -rp "Cloudflare Tunnel token (optional, leave empty to skip) []: " WIZ_CF_TUNNEL_TOKEN
|
||||
|
||||
read -rp "Cloudflare API token (for DNS-01 certs, optional) [${def_cf_api}]: " input
|
||||
WIZ_CF_API_TOKEN="${input:-${def_cf_api}}"
|
||||
echo ""
|
||||
|
||||
# --- Paths ---
|
||||
echo -e "${BOLD}--- Paths ---${NC}"
|
||||
echo " System data partition mount point"
|
||||
echo " (if the system drive was partitioned for user data,"
|
||||
echo " provide the mount point, e.g., /mnt/sys_drive)"
|
||||
read -rp "System data path [/mnt/sys_drive]: " input
|
||||
WIZ_SYSTEM_DATA_PATH="${input:-/mnt/sys_drive}"
|
||||
echo ""
|
||||
|
||||
# --- Dashboard password ---
|
||||
echo -e "${BOLD}--- Dashboard password ---${NC}"
|
||||
echo " Set a password for the controller dashboard."
|
||||
echo " (leave empty for first-visit setup prompt)"
|
||||
read -rsp "Dashboard password []: " wiz_password
|
||||
echo ""
|
||||
if [[ -n "$wiz_password" ]]; then
|
||||
# Hash with htpasswd (apache2-utils installed in step 1)
|
||||
if command -v htpasswd &>/dev/null; then
|
||||
WIZ_PASSWORD_HASH=$(htpasswd -bnBC 10 "" "$wiz_password" 2>/dev/null | cut -d: -f2)
|
||||
if [[ ! "$WIZ_PASSWORD_HASH" =~ ^\$2[aby]\$ ]]; then
|
||||
log_warn "htpasswd failed — trying Python fallback"
|
||||
WIZ_PASSWORD_HASH=""
|
||||
fi
|
||||
fi
|
||||
if [[ -z "$WIZ_PASSWORD_HASH" ]] && command -v python3 &>/dev/null; then
|
||||
WIZ_PASSWORD_HASH=$(python3 -c "import bcrypt; print(bcrypt.hashpw(b'${wiz_password}', bcrypt.gensalt(10)).decode())" 2>/dev/null || echo "")
|
||||
fi
|
||||
if [[ -z "$WIZ_PASSWORD_HASH" ]]; then
|
||||
log_warn "Could not hash password — dashboard will prompt on first visit"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Generate session secret
|
||||
WIZ_SESSION_SECRET=$(openssl rand -hex 32)
|
||||
|
||||
# --- Git sync ---
|
||||
echo -e "${BOLD}--- Git sync ---${NC}"
|
||||
read -rp "App catalog repository URL [https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git]: " input
|
||||
WIZ_GIT_REPO="${input:-https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git}"
|
||||
|
||||
read -rp "Git username []: " WIZ_GIT_USERNAME
|
||||
read -rp "Git token []: " WIZ_GIT_TOKEN
|
||||
echo ""
|
||||
|
||||
# --- Healthcheck monitoring ---
|
||||
echo -e "${BOLD}--- Healthcheck monitoring ---${NC}"
|
||||
echo " Healthchecks.io ping UUIDs (leave empty to skip):"
|
||||
read -rp " Heartbeat UUID []: " WIZ_HC_HEARTBEAT
|
||||
read -rp " System health UUID []: " WIZ_HC_SYSTEM
|
||||
read -rp " DB dump UUID []: " WIZ_HC_DBDUMP
|
||||
read -rp " Backup UUID []: " WIZ_HC_BACKUP
|
||||
read -rp " Backup integrity UUID []: " WIZ_HC_INTEGRITY
|
||||
echo ""
|
||||
|
||||
# Update global variables that other steps depend on
|
||||
BASE_DOMAIN="${WIZ_DOMAIN}"
|
||||
CUSTOMER_ID="${WIZ_CUSTOMER_ID}"
|
||||
CF_DNS_API_TOKEN="${WIZ_CF_API_TOKEN}"
|
||||
ACME_EMAIL="${WIZ_EMAIL}"
|
||||
|
||||
# --- Validate required fields ---
|
||||
if [[ -z "$WIZ_CUSTOMER_ID" ]] || [[ "$WIZ_CUSTOMER_ID" == "demo-felhom" ]]; then
|
||||
log_error "Customer ID is required and cannot be the default 'demo-felhom'"
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "$WIZ_DOMAIN" ]] || [[ "$WIZ_DOMAIN" == "homeserver.local" ]]; then
|
||||
log_error "A real domain is required (not 'homeserver.local')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Generate controller.yaml ---
|
||||
mkdir -p "${CONTROLLER_DIR}"
|
||||
|
||||
# Build optional customer.id line
|
||||
local customer_id_line=""
|
||||
if [[ -n "$CUSTOMER_ID" ]]; then
|
||||
customer_id_line=" id: \"${CUSTOMER_ID}\""
|
||||
fi
|
||||
|
||||
cat > "${CONTROLLER_DIR}/controller.yaml" << YAMLEOF
|
||||
# Felhom Controller Configuration
|
||||
# Generated by docker-setup.sh v${SCRIPT_VERSION} on $(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
# Auto-generated by docker-setup.sh v${SCRIPT_VERSION} on $(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
# Complete setup via web UI at https://felhom.${BASE_DOMAIN} or http://<ip>:8081
|
||||
|
||||
customer:
|
||||
id: "${WIZ_CUSTOMER_ID}"
|
||||
name: "${WIZ_CUSTOMER_NAME}"
|
||||
domain: "${WIZ_DOMAIN}"
|
||||
email: "${WIZ_EMAIL}"
|
||||
telegram_chat_id: ""
|
||||
|
||||
infrastructure:
|
||||
cf_tunnel_token: "${WIZ_CF_TUNNEL_TOKEN}"
|
||||
cf_api_token: "${WIZ_CF_API_TOKEN}"
|
||||
${customer_id_line}
|
||||
domain: "${BASE_DOMAIN}"
|
||||
|
||||
paths:
|
||||
stacks_dir: "/opt/docker/stacks"
|
||||
data_dir: "/opt/docker/felhom-controller/data"
|
||||
system_data_path: "${WIZ_SYSTEM_DATA_PATH}"
|
||||
|
||||
system:
|
||||
reserved_memory_mb: 384
|
||||
stacks_dir: "/opt/docker/stacks"
|
||||
|
||||
web:
|
||||
listen: ":8080"
|
||||
password_hash: "${WIZ_PASSWORD_HASH}"
|
||||
session_secret: "${WIZ_SESSION_SECRET}"
|
||||
|
||||
git:
|
||||
repo_url: "${WIZ_GIT_REPO}"
|
||||
branch: "main"
|
||||
sync_interval: "15m"
|
||||
username: "${WIZ_GIT_USERNAME}"
|
||||
token: "${WIZ_GIT_TOKEN}"
|
||||
|
||||
stacks:
|
||||
protected:
|
||||
- "traefik"
|
||||
- "cloudflared"
|
||||
- "felhom-controller"
|
||||
- "filebrowser"
|
||||
update_window: "03:00-05:00"
|
||||
compose_command: ""
|
||||
|
||||
backup:
|
||||
enabled: true
|
||||
restic_password_file: "/opt/docker/felhom-controller/data/restic-password"
|
||||
db_dump_schedule: "02:30"
|
||||
restic_schedule: "03:00"
|
||||
retention:
|
||||
keep_daily: 7
|
||||
keep_weekly: 4
|
||||
keep_monthly: 6
|
||||
prune_schedule: "weekly"
|
||||
|
||||
monitoring:
|
||||
enabled: true
|
||||
healthchecks_base: "https://status.felhom.eu"
|
||||
ping_uuids:
|
||||
heartbeat: "${WIZ_HC_HEARTBEAT}"
|
||||
system_health: "${WIZ_HC_SYSTEM}"
|
||||
db_dump: "${WIZ_HC_DBDUMP}"
|
||||
backup: "${WIZ_HC_BACKUP}"
|
||||
backup_integrity: "${WIZ_HC_INTEGRITY}"
|
||||
system_health_interval: "5m"
|
||||
health_check_schedule: "06:00"
|
||||
thresholds:
|
||||
disk_warn_percent: 80
|
||||
disk_crit_percent: 90
|
||||
backup_max_age_hours: 36
|
||||
cpu_warn_percent: 90
|
||||
memory_warn_percent: 85
|
||||
temperature_warn_celsius: 75
|
||||
|
||||
hub:
|
||||
enabled: true
|
||||
url: "https://hub.felhom.eu"
|
||||
api_key: "094091de545ce28795c47ac2158fc30750db5c24a621c49329b001ee8db57fb8"
|
||||
push_interval: "15m"
|
||||
|
||||
self_update:
|
||||
enabled: true
|
||||
check_interval: "6h"
|
||||
image: "gitea.dooplex.hu/admin/felhom-controller"
|
||||
auto_update: false
|
||||
health_timeout_seconds: 60
|
||||
|
||||
notifications:
|
||||
customer_events:
|
||||
- "disk_warning"
|
||||
- "backup_failed"
|
||||
- "update_available"
|
||||
- "security_update"
|
||||
operator_events:
|
||||
- "disk_critical"
|
||||
- "backup_failed"
|
||||
- "self_update_failed"
|
||||
- "container_unhealthy"
|
||||
|
||||
logging:
|
||||
level: "info"
|
||||
file: ""
|
||||
max_size_mb: 10
|
||||
max_files: 3
|
||||
|
||||
assets:
|
||||
source_url: "https://felhom.eu"
|
||||
setup_listen: ":8081"
|
||||
YAMLEOF
|
||||
|
||||
chmod 600 "${CONTROLLER_DIR}/controller.yaml"
|
||||
log_success "controller.yaml generated at ${CONTROLLER_DIR}/controller.yaml"
|
||||
log_success "Minimal controller.yaml generated (full config via web setup wizard)"
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Deploy felhom-controller
|
||||
#-------------------------------------------------------------------------------
|
||||
install_controller() {
|
||||
local step_num=6
|
||||
local step_num=5
|
||||
[[ "$SELF_SIGNED_CERT" == true ]] && ((step_num++))
|
||||
[[ -n "${WIZ_CF_TUNNEL_TOKEN:-}" ]] && ((step_num++))
|
||||
[[ -n "${CF_TUNNEL_TOKEN:-}" ]] && ((step_num++))
|
||||
[[ "$SKIP_FILEBROWSER" != true ]] && ((step_num++))
|
||||
log_step "${step_num}/$(get_total_steps) - Deploying felhom-controller..."
|
||||
|
||||
@@ -1784,9 +1508,10 @@ services:
|
||||
privileged: true
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- "8081:8081"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ${CONTROLLER_DIR}/controller.yaml:/opt/docker/felhom-controller/controller.yaml:ro
|
||||
- ${CONTROLLER_DIR}/controller.yaml:/opt/docker/felhom-controller/controller.yaml
|
||||
- controller-data:/opt/docker/felhom-controller/data
|
||||
- /opt/docker/stacks:/opt/docker/stacks
|
||||
- /srv/backups:/srv/backups
|
||||
@@ -1855,20 +1580,30 @@ print_summary() {
|
||||
server_ip=$(get_server_ip)
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}${GREEN}-==================================================================¬${NC}"
|
||||
echo -e "${BOLD}${GREEN}¦ Infrastructure Setup Complete! ¦${NC}"
|
||||
echo -e "${BOLD}${GREEN}L==================================================================-${NC}"
|
||||
echo -e "${BOLD}${GREEN}═══════════════════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${BOLD}${GREEN} Felhom Controller telepítve!${NC}"
|
||||
echo ""
|
||||
echo -e "${BOLD}${GREEN} A beállítás folytatásához nyissa meg a böngészőben:${NC}"
|
||||
echo ""
|
||||
echo -e "${BOLD}${GREEN} ► https://felhom.${BASE_DOMAIN} (ajánlott)${NC}"
|
||||
echo ""
|
||||
echo -e "${BOLD}${GREEN} Ha a fenti cím nem érhető el (pl. nincs internet):${NC}"
|
||||
echo -e "${BOLD}${GREEN} ► http://${server_ip}:8081 (helyi hálózat, tartalék)${NC}"
|
||||
echo -e "${BOLD}${GREEN}═══════════════════════════════════════════════════════════════════${NC}"
|
||||
echo ""
|
||||
echo -e "${BOLD}Server IP:${NC} ${server_ip}"
|
||||
echo -e "${BOLD}Domain:${NC} *.${BASE_DOMAIN}"
|
||||
echo -e "${BOLD}Customer:${NC} ${CUSTOMER_ID}"
|
||||
if [[ -n "$CUSTOMER_ID" ]]; then
|
||||
echo -e "${BOLD}Customer:${NC} ${CUSTOMER_ID}"
|
||||
fi
|
||||
echo ""
|
||||
echo -e "${BOLD}Services:${NC}"
|
||||
echo " • Felhom Controller: https://felhom.${BASE_DOMAIN}"
|
||||
echo " L| Config: ${CONTROLLER_DIR}/controller.yaml"
|
||||
echo " L| Setup: http://${server_ip}:8081 (direct HTTP)"
|
||||
echo " • Traefik Dashboard: https://traefik.${BASE_DOMAIN}/dashboard/"
|
||||
echo " L| Credentials: admin / ${TRAEFIK_PASSWORD}"
|
||||
if [[ -n "${WIZ_CF_TUNNEL_TOKEN:-}" ]]; then
|
||||
if [[ -n "${CF_TUNNEL_TOKEN:-}" ]]; then
|
||||
echo " • Cloudflare Tunnel: Active (routes configured in CF dashboard)"
|
||||
echo " L| Container: cloudflared"
|
||||
echo " L| Config: ${CLOUDFLARED_DIR}/docker-compose.yml"
|
||||
@@ -1878,7 +1613,6 @@ print_summary() {
|
||||
echo " • FileBrowser: https://files.${BASE_DOMAIN}"
|
||||
echo " L| Default login: admin / admin (change immediately!)"
|
||||
fi
|
||||
echo -e " • Hub reporting: ${GREEN}enabled${NC} (hub.felhom.eu)"
|
||||
echo ""
|
||||
echo -e "${BOLD}DNS Setup Required:${NC}"
|
||||
echo " Add wildcard record to your DNS (Pi-hole, router, etc.):"
|
||||
@@ -1907,26 +1641,6 @@ print_summary() {
|
||||
echo " ACME email: ${ACME_EMAIL}"
|
||||
echo ""
|
||||
fi
|
||||
echo -e "${BOLD}${CYAN}===================================================================${NC}"
|
||||
echo -e "${BOLD}${CYAN} MANAGING APPLICATION STACKS ${NC}"
|
||||
echo -e "${BOLD}${CYAN}===================================================================${NC}"
|
||||
echo ""
|
||||
echo " Deploy and manage applications via the controller dashboard:"
|
||||
echo ""
|
||||
echo " 1. Open https://felhom.${BASE_DOMAIN}"
|
||||
echo " 2. Browse available apps on the Alkalmazások page"
|
||||
echo " 3. Click Telepítés to deploy"
|
||||
echo ""
|
||||
if [[ -n "$CUSTOMER_ID" ]]; then
|
||||
echo -e "${BOLD}${YELLOW}Disaster Recovery:${NC}"
|
||||
echo " If this is a reinstallation, the controller will automatically:"
|
||||
echo " 1. Contact the Hub for your previous configuration"
|
||||
echo " 2. Mount your existing storage drives"
|
||||
echo " 3. Detect and offer to restore your applications"
|
||||
echo ""
|
||||
echo " Open https://felhom.${BASE_DOMAIN} to monitor the restore process."
|
||||
echo ""
|
||||
fi
|
||||
echo -e "${BOLD}Quick Commands:${NC}"
|
||||
echo " dps → List containers"
|
||||
echo " dlogs <n> → View container logs"
|
||||
@@ -1968,14 +1682,14 @@ main() {
|
||||
if [[ "$SELF_SIGNED_CERT" == true ]]; then
|
||||
echo " 5. Generate self-signed certificate"
|
||||
fi
|
||||
echo " - Run configuration wizard (generates controller.yaml)"
|
||||
echo " - Install Cloudflare Tunnel (if configured in wizard)"
|
||||
echo " - Generate minimal controller.yaml"
|
||||
echo " - Install Cloudflare Tunnel: $([[ -n "$CF_TUNNEL_TOKEN" ]] && echo "yes" || echo "skip")"
|
||||
echo " - Install FileBrowser: $([[ "$SKIP_FILEBROWSER" == true ]] && echo "skip" || echo "yes (auto-discover drives)")"
|
||||
echo " - Deploy felhom-controller"
|
||||
echo " - Install helper tools (ctop, lazydocker, aliases)"
|
||||
echo ""
|
||||
echo " Domain: *.${BASE_DOMAIN}"
|
||||
echo " Customer: ${CUSTOMER_ID:-<none — will be set in wizard>}"
|
||||
echo " Customer: ${CUSTOMER_ID:-<none — will be set in web setup wizard>}"
|
||||
echo " Traefik password: ${TRAEFIK_PASSWORD}"
|
||||
if [[ -n "$ACME_EMAIL" && -n "$CF_DNS_API_TOKEN" ]]; then
|
||||
echo -e " TLS: ${GREEN}Let's Encrypt (Cloudflare DNS-01)${NC}"
|
||||
@@ -2005,7 +1719,7 @@ main() {
|
||||
install_docker
|
||||
install_traefik
|
||||
generate_self_signed_cert
|
||||
run_config_wizard
|
||||
generate_minimal_config
|
||||
install_cloudflare_tunnel
|
||||
install_filebrowser
|
||||
install_controller
|
||||
|
||||
Reference in New Issue
Block a user