docker-setup.sh v5.0: Config wizard, controller deployment, FileBrowser rewrite
Complete TASK.md implementation: - §1: Version bump to 5.0.0, updated banner and header comment - §3+§4: Remove --cf-tunnel-token and --hdd-path CLI options (deprecated) - §5: Rewrite install_filebrowser() with auto drive discovery from /mnt/ - §6: New install_controller() deploys felhom-controller with compose - §7: Interactive run_config_wizard() generates controller.yaml - §9: install_cloudflare_tunnel() reads from wizard variable - §10: New execution order: infra → wizard → tunnel → filebrowser → controller - §11: Fix print_summary() — controller URL, hub status, fix CUSTOMER_ID bug - §12: Update print_help() for new workflow Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+453
-128
@@ -1,16 +1,18 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# Docker + Felhom Infrastructure Setup v4.0
|
# Felhom Infrastructure Setup v5.0
|
||||||
# Prepares a Debian 13 server for Felhom homeserver deployment
|
# Prepares a Debian 13 server for Felhom homeserver deployment
|
||||||
#
|
#
|
||||||
# This script sets up the infrastructure:
|
# This script sets up the complete infrastructure:
|
||||||
# - Docker Engine + Compose
|
# - Docker Engine + Compose
|
||||||
# - Traefik reverse proxy
|
# - Traefik reverse proxy
|
||||||
# - TLS certificates (Let's Encrypt via Cloudflare DNS or self-signed)
|
# - TLS certificates (Let's Encrypt via Cloudflare DNS or self-signed)
|
||||||
# - Cloudflare Tunnel connector (optional, for external access)
|
# - Interactive configuration wizard (generates controller.yaml)
|
||||||
# - FileBrowser Quantum (web-based file manager for HDD data)
|
# - Cloudflare Tunnel connector (optional, configured via wizard)
|
||||||
# - Felhom Controller (deployed separately)
|
# - FileBrowser Quantum (web-based file manager)
|
||||||
|
# - Felhom Controller (automatic deployment + dashboard)
|
||||||
|
# - Helper tools (ctop, lazydocker, shell aliases)
|
||||||
#
|
#
|
||||||
# Application stacks are managed via the felhom-controller dashboard.
|
# Application stacks are managed via the felhom-controller dashboard.
|
||||||
#
|
#
|
||||||
@@ -24,10 +26,10 @@
|
|||||||
# --gateway ADDRESS Gateway address (default: 192.168.0.1)
|
# --gateway ADDRESS Gateway address (default: 192.168.0.1)
|
||||||
# --dns ADDRESS DNS server (default: 1.1.1.1,8.8.8.8)
|
# --dns ADDRESS DNS server (default: 1.1.1.1,8.8.8.8)
|
||||||
# --interface NAME Network interface (default: auto-detect)
|
# --interface NAME Network interface (default: auto-detect)
|
||||||
# --domain DOMAIN Base domain for services (default: homeserver.local)
|
# --domain DOMAIN Base domain (pre-seeds wizard)
|
||||||
# --email EMAIL Email for Let's Encrypt certificates
|
# --email EMAIL ACME email (pre-seeds wizard)
|
||||||
# --cf-token TOKEN Cloudflare API token for DNS-01 challenge
|
# --cf-token TOKEN Cloudflare API token (pre-seeds wizard)
|
||||||
# --cf-tunnel-token TK Cloudflare Tunnel token for external access
|
# --customer ID Customer identifier (pre-seeds wizard)
|
||||||
# --traefik-password PW Password for Traefik dashboard (default: auto-generated)
|
# --traefik-password PW Password for Traefik dashboard (default: auto-generated)
|
||||||
# --self-signed-cert Generate self-signed wildcard certificate
|
# --self-signed-cert Generate self-signed wildcard certificate
|
||||||
# --skip-filebrowser Skip FileBrowser installation
|
# --skip-filebrowser Skip FileBrowser installation
|
||||||
@@ -37,7 +39,7 @@
|
|||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
# sudo ./docker-setup.sh --domain demo-felhom.eu --customer demo-felhom \
|
# sudo ./docker-setup.sh --domain demo-felhom.eu --customer demo-felhom \
|
||||||
# --email certs@felhom.eu --cf-token cf-xxx --cf-tunnel-token eyJhIjo...
|
# --email certs@felhom.eu --cf-token cf-xxx
|
||||||
#
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
|
|
||||||
@@ -117,7 +119,7 @@ done
|
|||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Configuration
|
# Configuration
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
SCRIPT_VERSION="3.6.0"
|
SCRIPT_VERSION="5.0.0"
|
||||||
|
|
||||||
# Default values
|
# Default values
|
||||||
STATIC_IP=""
|
STATIC_IP=""
|
||||||
@@ -127,10 +129,8 @@ INTERFACE=""
|
|||||||
BASE_DOMAIN="homeserver.local"
|
BASE_DOMAIN="homeserver.local"
|
||||||
ACME_EMAIL=""
|
ACME_EMAIL=""
|
||||||
CF_DNS_API_TOKEN=""
|
CF_DNS_API_TOKEN=""
|
||||||
CF_TUNNEL_TOKEN=""
|
|
||||||
TRAEFIK_PASSWORD=""
|
TRAEFIK_PASSWORD=""
|
||||||
SKIP_FILEBROWSER=false
|
SKIP_FILEBROWSER=false
|
||||||
HDD_PATH=""
|
|
||||||
DRY_RUN=false
|
DRY_RUN=false
|
||||||
SELF_SIGNED_CERT=false
|
SELF_SIGNED_CERT=false
|
||||||
DEBUG_MODE=false
|
DEBUG_MODE=false
|
||||||
@@ -183,17 +183,18 @@ trap 'on_error $LINENO' ERR
|
|||||||
print_banner() {
|
print_banner() {
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BOLD}${BLUE}-==================================================================¬${NC}"
|
echo -e "${BOLD}${BLUE}-==================================================================¬${NC}"
|
||||||
echo -e "${BOLD}${BLUE}¦ Docker + Felhom Infrastructure Setup v${SCRIPT_VERSION} ¦${NC}"
|
echo -e "${BOLD}${BLUE}¦ Felhom Infrastructure Setup v${SCRIPT_VERSION} ¦${NC}"
|
||||||
echo -e "${BOLD}${BLUE}L==================================================================-${NC}"
|
echo -e "${BOLD}${BLUE}L==================================================================-${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
}
|
}
|
||||||
|
|
||||||
print_help() {
|
print_help() {
|
||||||
cat << 'EOF'
|
cat << 'EOF'
|
||||||
Docker + Felhom Infrastructure Setup v4.0
|
Felhom Infrastructure Setup v5.0
|
||||||
|
|
||||||
This script prepares a Debian 13 server with Docker infrastructure for Felhom homeserver.
|
Prepares a Debian 13 server for Felhom homeserver deployment. Installs
|
||||||
Application stacks are managed via the felhom-controller dashboard.
|
infrastructure, runs an interactive configuration wizard, generates
|
||||||
|
controller.yaml, and deploys felhom-controller — all in one run.
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
./docker-setup.sh --bootstrap # First, on fresh Debian
|
./docker-setup.sh --bootstrap # First, on fresh Debian
|
||||||
@@ -201,16 +202,14 @@ USAGE:
|
|||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
--bootstrap Install sudo (run first on fresh Debian)
|
--bootstrap Install sudo (run first on fresh Debian)
|
||||||
--customer ID Customer identifier (e.g., demo-felhom)
|
--customer ID Customer identifier (pre-seeds wizard)
|
||||||
--ip ADDRESS Static IP address
|
--ip ADDRESS Static IP address
|
||||||
--gateway ADDRESS Gateway (default: 192.168.0.1)
|
--gateway ADDRESS Gateway (default: 192.168.0.1)
|
||||||
--dns ADDRESS DNS servers, comma-separated (default: 1.1.1.1,8.8.8.8)
|
--dns ADDRESS DNS servers, comma-separated (default: 1.1.1.1,8.8.8.8)
|
||||||
--interface NAME Network interface (default: auto-detect)
|
--interface NAME Network interface (default: auto-detect)
|
||||||
--domain DOMAIN Base domain for services (default: homeserver.local)
|
--domain DOMAIN Base domain for services (pre-seeds wizard)
|
||||||
--email EMAIL Email for Let's Encrypt certificates
|
--email EMAIL Email for Let's Encrypt (pre-seeds wizard)
|
||||||
--cf-token TOKEN Cloudflare API token for DNS-01 challenge (recommended)
|
--cf-token TOKEN Cloudflare API token for DNS-01 (pre-seeds wizard)
|
||||||
--cf-tunnel-token TK Cloudflare Tunnel token for external access
|
|
||||||
--hdd-path PATH HDD mount path (e.g., /mnt/hdd_1) for FileBrowser
|
|
||||||
--traefik-password PW Password for Traefik dashboard (default: auto-generated)
|
--traefik-password PW Password for Traefik dashboard (default: auto-generated)
|
||||||
--self-signed-cert Generate self-signed wildcard certificate (fallback)
|
--self-signed-cert Generate self-signed wildcard certificate (fallback)
|
||||||
--skip-filebrowser Skip FileBrowser installation
|
--skip-filebrowser Skip FileBrowser installation
|
||||||
@@ -218,12 +217,14 @@ OPTIONS:
|
|||||||
--debug Enable verbose debug output
|
--debug Enable verbose debug output
|
||||||
-h, --help Show this help
|
-h, --help Show this help
|
||||||
|
|
||||||
|
CLI options pre-seed the interactive wizard — values can be changed
|
||||||
|
during the wizard prompts.
|
||||||
|
|
||||||
TLS CERTIFICATE OPTIONS:
|
TLS CERTIFICATE OPTIONS:
|
||||||
There are three TLS modes (in order of preference):
|
There are three TLS modes (in order of preference):
|
||||||
|
|
||||||
1. Let's Encrypt + Cloudflare DNS (recommended for Felhom customers):
|
1. Let's Encrypt + Cloudflare DNS (recommended for Felhom customers):
|
||||||
--email certs@felhom.eu --cf-token <cloudflare-api-token>
|
--email certs@felhom.eu --cf-token <cloudflare-api-token>
|
||||||
Uses DNS-01 challenge. Works with Cloudflare Tunnel, no port 80 needed.
|
|
||||||
|
|
||||||
2. Let's Encrypt + HTTP-01 (public servers without Cloudflare Tunnel):
|
2. Let's Encrypt + HTTP-01 (public servers without Cloudflare Tunnel):
|
||||||
--email admin@example.com
|
--email admin@example.com
|
||||||
@@ -231,38 +232,31 @@ TLS CERTIFICATE OPTIONS:
|
|||||||
|
|
||||||
3. Self-signed certificate (offline / no internet):
|
3. Self-signed certificate (offline / no internet):
|
||||||
--self-signed-cert
|
--self-signed-cert
|
||||||
Generates a CA + wildcard cert. Requires manual CA import on all devices.
|
|
||||||
|
|
||||||
WHAT THIS SCRIPT INSTALLS:
|
WHAT THIS SCRIPT INSTALLS:
|
||||||
1. Base packages (curl, git, htop, etc.)
|
1. Base packages (curl, git, htop, etc.)
|
||||||
2. Docker Engine + Docker Compose
|
2. Docker Engine + Docker Compose
|
||||||
3. Traefik reverse proxy (with dashboard)
|
3. Traefik reverse proxy (with dashboard)
|
||||||
4. Cloudflare Tunnel connector (if --cf-tunnel-token provided)
|
4. TLS certificates (Let's Encrypt or self-signed)
|
||||||
5. TLS certificates (Let's Encrypt or self-signed)
|
5. Felhom Controller (with interactive configuration wizard)
|
||||||
6. FileBrowser Quantum (web file manager at files.<domain>)
|
6. FileBrowser Quantum (web file manager at files.<domain>)
|
||||||
7. Helper tools (ctop, lazydocker, shell aliases)
|
7. Cloudflare Tunnel (if configured in wizard)
|
||||||
|
8. Helper tools (ctop, lazydocker, shell aliases)
|
||||||
DEPLOYING APPLICATIONS:
|
|
||||||
After infrastructure setup, deploy the felhom-controller to manage apps
|
|
||||||
via the web dashboard at felhom.<domain>.
|
|
||||||
|
|
||||||
EXAMPLES:
|
EXAMPLES:
|
||||||
# Felhom customer deployment (recommended — full stack with tunnel)
|
# Felhom customer deployment (recommended)
|
||||||
sudo ./docker-setup.sh --domain demo-felhom.eu --customer demo-felhom \
|
|
||||||
--email certs@felhom.eu --cf-token cf-xxxxxxxxxxxx \
|
|
||||||
--cf-tunnel-token eyJhIjoixxxxxxxx...
|
|
||||||
|
|
||||||
# Without tunnel (local access only, or custom ingress)
|
|
||||||
sudo ./docker-setup.sh --domain demo-felhom.eu --customer demo-felhom \
|
sudo ./docker-setup.sh --domain demo-felhom.eu --customer demo-felhom \
|
||||||
--email certs@felhom.eu --cf-token cf-xxxxxxxxxxxx
|
--email certs@felhom.eu --cf-token cf-xxxxxxxxxxxx
|
||||||
|
|
||||||
|
# Minimal (wizard will prompt for everything)
|
||||||
|
sudo ./docker-setup.sh
|
||||||
|
|
||||||
# Self-signed cert (offline/testing)
|
# Self-signed cert (offline/testing)
|
||||||
sudo ./docker-setup.sh --domain example.com --self-signed-cert
|
sudo ./docker-setup.sh --domain example.com --self-signed-cert
|
||||||
|
|
||||||
# Full setup with static IP
|
# Full setup with static IP
|
||||||
sudo ./docker-setup.sh --domain demo-felhom.eu --customer demo-felhom \
|
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-xxxxxxxxxxxx
|
||||||
--cf-tunnel-token eyJhIjoixxxxxxxx...
|
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,9 +295,6 @@ parse_args() {
|
|||||||
--cf-token)
|
--cf-token)
|
||||||
require_arg "$1" "${2:-}"
|
require_arg "$1" "${2:-}"
|
||||||
CF_DNS_API_TOKEN="$2"; shift 2 ;;
|
CF_DNS_API_TOKEN="$2"; shift 2 ;;
|
||||||
--cf-tunnel-token)
|
|
||||||
require_arg "$1" "${2:-}"
|
|
||||||
CF_TUNNEL_TOKEN="$2"; shift 2 ;;
|
|
||||||
--traefik-password)
|
--traefik-password)
|
||||||
require_arg "$1" "${2:-}"
|
require_arg "$1" "${2:-}"
|
||||||
TRAEFIK_PASSWORD="$2"; shift 2 ;;
|
TRAEFIK_PASSWORD="$2"; shift 2 ;;
|
||||||
@@ -312,9 +303,6 @@ parse_args() {
|
|||||||
CUSTOMER_ID="$2"; shift 2 ;;
|
CUSTOMER_ID="$2"; shift 2 ;;
|
||||||
--self-signed-cert) SELF_SIGNED_CERT=true; shift ;;
|
--self-signed-cert) SELF_SIGNED_CERT=true; shift ;;
|
||||||
--skip-filebrowser) SKIP_FILEBROWSER=true; shift ;;
|
--skip-filebrowser) SKIP_FILEBROWSER=true; shift ;;
|
||||||
--hdd-path)
|
|
||||||
require_arg "$1" "${2:-}"
|
|
||||||
HDD_PATH="$2"; shift 2 ;;
|
|
||||||
--dry-run) DRY_RUN=true; shift ;;
|
--dry-run) DRY_RUN=true; shift ;;
|
||||||
--debug) DEBUG_MODE=true; shift ;;
|
--debug) DEBUG_MODE=true; shift ;;
|
||||||
-h|--help) print_help; exit 0 ;;
|
-h|--help) print_help; exit 0 ;;
|
||||||
@@ -373,12 +361,6 @@ parse_args() {
|
|||||||
log_warn "Let's Encrypt will be used; self-signed cert will serve as fallback"
|
log_warn "Let's Encrypt will be used; self-signed cert will serve as fallback"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Warn if tunnel token provided without Cloudflare DNS (unusual but valid)
|
|
||||||
if [[ -n "$CF_TUNNEL_TOKEN" && -z "$CF_DNS_API_TOKEN" ]]; then
|
|
||||||
log_warn "Cloudflare Tunnel without DNS-01 challenge"
|
|
||||||
log_warn "External HTTPS will work, but certs must be managed separately"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Validate CUSTOMER_ID format if provided
|
# Validate CUSTOMER_ID format if provided
|
||||||
if [[ -n "$CUSTOMER_ID" ]]; then
|
if [[ -n "$CUSTOMER_ID" ]]; then
|
||||||
if [[ ! "$CUSTOMER_ID" =~ ^[a-zA-Z0-9_-]+$ ]]; then
|
if [[ ! "$CUSTOMER_ID" =~ ^[a-zA-Z0-9_-]+$ ]]; then
|
||||||
@@ -454,9 +436,8 @@ detect_network_manager_debug() {
|
|||||||
|
|
||||||
# Calculate total number of steps dynamically
|
# Calculate total number of steps dynamically
|
||||||
get_total_steps() {
|
get_total_steps() {
|
||||||
local total=5 # base: packages, network, docker, traefik, tools
|
local total=8 # base: packages, network, docker, traefik, cert, wizard, controller, tools
|
||||||
[[ -n "$CF_TUNNEL_TOKEN" ]] && ((total++))
|
[[ -n "${WIZ_CF_TUNNEL_TOKEN:-}" ]] && ((total++))
|
||||||
[[ "$SELF_SIGNED_CERT" == true ]] && ((total++))
|
|
||||||
[[ "$SKIP_FILEBROWSER" != true ]] && ((total++))
|
[[ "$SKIP_FILEBROWSER" != true ]] && ((total++))
|
||||||
echo "$total"
|
echo "$total"
|
||||||
}
|
}
|
||||||
@@ -1039,12 +1020,14 @@ EOF
|
|||||||
# Step 4b: Install Cloudflare Tunnel connector (optional)
|
# Step 4b: Install Cloudflare Tunnel connector (optional)
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
install_cloudflare_tunnel() {
|
install_cloudflare_tunnel() {
|
||||||
if [[ -z "$CF_TUNNEL_TOKEN" ]]; then
|
if [[ -z "${WIZ_CF_TUNNEL_TOKEN:-}" ]]; then
|
||||||
log_skip "Cloudflare Tunnel not configured (no --cf-tunnel-token)"
|
log_skip "Cloudflare Tunnel not configured (skipped in wizard)"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log_step "5/$(get_total_steps) - Installing Cloudflare Tunnel connector..."
|
local step_num=6
|
||||||
|
[[ "$SELF_SIGNED_CERT" == true ]] && ((step_num++))
|
||||||
|
log_step "${step_num}/$(get_total_steps) - Installing Cloudflare Tunnel connector..."
|
||||||
|
|
||||||
if [[ "$DRY_RUN" == true ]]; then
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
echo -e "${CYAN}[DRY-RUN]${NC} Would deploy cloudflared tunnel connector"
|
echo -e "${CYAN}[DRY-RUN]${NC} Would deploy cloudflared tunnel connector"
|
||||||
@@ -1069,7 +1052,7 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: tunnel run
|
command: tunnel run
|
||||||
environment:
|
environment:
|
||||||
- TUNNEL_TOKEN=${CF_TUNNEL_TOKEN}
|
- TUNNEL_TOKEN=${WIZ_CF_TUNNEL_TOKEN}
|
||||||
dns:
|
dns:
|
||||||
- 1.1.1.1
|
- 1.1.1.1
|
||||||
- 8.8.8.8
|
- 8.8.8.8
|
||||||
@@ -1115,10 +1098,7 @@ generate_self_signed_cert() {
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Calculate step number dynamically
|
log_step "5/$(get_total_steps) - Generating self-signed certificate..."
|
||||||
local step_num=5
|
|
||||||
[[ -n "$CF_TUNNEL_TOKEN" ]] && ((step_num++))
|
|
||||||
log_step "${step_num}/$(get_total_steps) - Generating self-signed certificate..."
|
|
||||||
|
|
||||||
if [[ "$DRY_RUN" == true ]]; then
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
echo -e "${CYAN}[DRY-RUN]${NC} Would generate self-signed cert for *.${BASE_DOMAIN}"
|
echo -e "${CYAN}[DRY-RUN]${NC} Would generate self-signed cert for *.${BASE_DOMAIN}"
|
||||||
@@ -1234,7 +1214,7 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Step 6: Install FileBrowser Quantum (infrastructure file manager)
|
# Install FileBrowser Quantum (infrastructure file manager)
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
install_filebrowser() {
|
install_filebrowser() {
|
||||||
if [[ "$SKIP_FILEBROWSER" == true ]]; then
|
if [[ "$SKIP_FILEBROWSER" == true ]]; then
|
||||||
@@ -1242,26 +1222,52 @@ install_filebrowser() {
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "$HDD_PATH" ]]; then
|
|
||||||
log_warn "FileBrowser skipped — no HDD path configured (use --hdd-path)."
|
|
||||||
log_warn "Deploy manually after HDD setup."
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -d "$HDD_PATH" ]]; then
|
|
||||||
log_warn "FileBrowser skipped — HDD path $HDD_PATH does not exist."
|
|
||||||
log_warn "Run hdd-setup.sh first, then re-run with --hdd-path."
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Calculate step number dynamically
|
# Calculate step number dynamically
|
||||||
local step_num=5
|
local step_num=6
|
||||||
[[ -n "$CF_TUNNEL_TOKEN" ]] && ((step_num++))
|
|
||||||
[[ "$SELF_SIGNED_CERT" == true ]] && ((step_num++))
|
[[ "$SELF_SIGNED_CERT" == true ]] && ((step_num++))
|
||||||
|
[[ -n "${WIZ_CF_TUNNEL_TOKEN:-}" ]] && ((step_num++))
|
||||||
log_step "${step_num}/$(get_total_steps) - Installing FileBrowser Quantum..."
|
log_step "${step_num}/$(get_total_steps) - Installing FileBrowser Quantum..."
|
||||||
|
|
||||||
|
# Discover drive mounts for FileBrowser volumes
|
||||||
|
local volume_lines=""
|
||||||
|
local mount_comment=""
|
||||||
|
local found_mounts=0
|
||||||
|
|
||||||
|
# Scan /mnt/ for existing mount points (e.g., /mnt/hdd_1, /mnt/sys_drive)
|
||||||
|
if [[ -d /mnt ]]; then
|
||||||
|
for mp in /mnt/*/; do
|
||||||
|
[[ ! -d "$mp" ]] && continue
|
||||||
|
local name
|
||||||
|
name=$(basename "$mp")
|
||||||
|
# Skip hidden dirs and raw mount dirs
|
||||||
|
[[ "$name" == .* ]] && continue
|
||||||
|
[[ "$name" == .felhom-raw ]] && continue
|
||||||
|
volume_lines+=" - ${mp%/}:/srv/${name}"$'\n'
|
||||||
|
mount_comment+=" # ${mp%/} → /srv/${name}"$'\n'
|
||||||
|
((found_mounts++))
|
||||||
|
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 -q "${WIZ_SYSTEM_DATA_PATH}"; then
|
||||||
|
volume_lines+=" - ${WIZ_SYSTEM_DATA_PATH}:/srv/${sdp_name}"$'\n'
|
||||||
|
((found_mounts++))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $found_mounts -eq 0 ]]; then
|
||||||
|
log_warn "No mount points found in /mnt/ — FileBrowser will have no drive volumes."
|
||||||
|
log_warn "Drives can be attached later via the controller dashboard."
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "$DRY_RUN" == true ]]; then
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
echo -e "${CYAN}[DRY-RUN]${NC} Would install FileBrowser Quantum at files.${BASE_DOMAIN}"
|
echo -e "${CYAN}[DRY-RUN]${NC} Would install FileBrowser Quantum at files.${BASE_DOMAIN}"
|
||||||
|
if [[ $found_mounts -gt 0 ]]; then
|
||||||
|
echo -e "${CYAN}[DRY-RUN]${NC} Would mount ${found_mounts} drive(s)"
|
||||||
|
fi
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1277,12 +1283,7 @@ install_filebrowser() {
|
|||||||
cat > "${FILEBROWSER_DIR}/docker-compose.yml" << EOF
|
cat > "${FILEBROWSER_DIR}/docker-compose.yml" << EOF
|
||||||
# FileBrowser Quantum — Infrastructure file manager
|
# FileBrowser Quantum — Infrastructure file manager
|
||||||
# Domain: files.${BASE_DOMAIN}
|
# Domain: files.${BASE_DOMAIN}
|
||||||
# Deployed by docker-setup.sh — do NOT remove
|
# Deployed by docker-setup.sh v${SCRIPT_VERSION}
|
||||||
#
|
|
||||||
# Mount permissions:
|
|
||||||
# /srv/appdata/ → HDD appdata/ (READ-ONLY — app data)
|
|
||||||
# /srv/media/ → HDD media/ (read-write — user media)
|
|
||||||
# /srv/Dokumentumok/ → HDD Dokumentumok/ (read-write — user documents)
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
filebrowser:
|
filebrowser:
|
||||||
@@ -1293,10 +1294,7 @@ services:
|
|||||||
- TZ=Europe/Budapest
|
- TZ=Europe/Budapest
|
||||||
volumes:
|
volumes:
|
||||||
- filebrowser_data:/home/filebrowser/data
|
- filebrowser_data:/home/filebrowser/data
|
||||||
- \${HDD_PATH}/appdata:/srv/appdata:ro
|
${volume_lines} networks:
|
||||||
- \${HDD_PATH}/media:/srv/media
|
|
||||||
- \${HDD_PATH}/Dokumentumok:/srv/Dokumentumok
|
|
||||||
networks:
|
|
||||||
- traefik-public
|
- traefik-public
|
||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
@@ -1310,7 +1308,7 @@ services:
|
|||||||
start_period: 15s
|
start_period: 15s
|
||||||
labels:
|
labels:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.filebrowser.rule=Host(\`files.\${DOMAIN}\`)"
|
- "traefik.http.routers.filebrowser.rule=Host(\`files.${BASE_DOMAIN}\`)"
|
||||||
- "traefik.http.routers.filebrowser.entrypoints=websecure"
|
- "traefik.http.routers.filebrowser.entrypoints=websecure"
|
||||||
- "traefik.http.routers.filebrowser.tls=true"
|
- "traefik.http.routers.filebrowser.tls=true"
|
||||||
${fb_certresolver_label}
|
${fb_certresolver_label}
|
||||||
@@ -1351,13 +1349,6 @@ app_info:
|
|||||||
- Külső HDD csatlakoztatva és felcsatolva
|
- Külső HDD csatlakoztatva és felcsatolva
|
||||||
METAEOF
|
METAEOF
|
||||||
|
|
||||||
# Create .env file
|
|
||||||
cat > "${FILEBROWSER_DIR}/.env" << ENVEOF
|
|
||||||
# FileBrowser environment — generated by docker-setup.sh
|
|
||||||
DOMAIN=${BASE_DOMAIN}
|
|
||||||
HDD_PATH=${HDD_PATH}
|
|
||||||
ENVEOF
|
|
||||||
|
|
||||||
cd "${FILEBROWSER_DIR}"
|
cd "${FILEBROWSER_DIR}"
|
||||||
log_info "Pulling FileBrowser image..."
|
log_info "Pulling FileBrowser image..."
|
||||||
docker compose pull -q
|
docker compose pull -q
|
||||||
@@ -1438,13 +1429,354 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Configuration wizard — generates controller.yaml
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# 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() {
|
||||||
|
local step_num=5
|
||||||
|
[[ "$SELF_SIGNED_CERT" == true ]] && ((step_num++))
|
||||||
|
log_step "${step_num}/$(get_total_steps) - Running configuration wizard..."
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${BOLD}${CYAN}===========================================================${NC}"
|
||||||
|
echo -e "${BOLD}${CYAN} Felhom Controller Configuration Wizard${NC}"
|
||||||
|
echo -e "${BOLD}${CYAN}===========================================================${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 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" | tr -d ':\n')
|
||||||
|
elif 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}"
|
||||||
|
|
||||||
|
# --- Generate controller.yaml ---
|
||||||
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
|
echo -e "${CYAN}[DRY-RUN]${NC} Would generate ${CONTROLLER_DIR}/controller.yaml"
|
||||||
|
echo -e "${CYAN}[DRY-RUN]${NC} Customer: ${WIZ_CUSTOMER_ID}, Domain: ${WIZ_DOMAIN}"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${CONTROLLER_DIR}"
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
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}"
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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"
|
||||||
|
YAMLEOF
|
||||||
|
|
||||||
|
chmod 600 "${CONTROLLER_DIR}/controller.yaml"
|
||||||
|
log_success "controller.yaml generated at ${CONTROLLER_DIR}/controller.yaml"
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Deploy felhom-controller
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
install_controller() {
|
||||||
|
local step_num=6
|
||||||
|
[[ "$SELF_SIGNED_CERT" == true ]] && ((step_num++))
|
||||||
|
[[ -n "${WIZ_CF_TUNNEL_TOKEN:-}" ]] && ((step_num++))
|
||||||
|
[[ "$SKIP_FILEBROWSER" != true ]] && ((step_num++))
|
||||||
|
log_step "${step_num}/$(get_total_steps) - Deploying felhom-controller..."
|
||||||
|
|
||||||
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
|
echo -e "${CYAN}[DRY-RUN]${NC} Would deploy felhom-controller at felhom.${BASE_DOMAIN}"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${CONTROLLER_DIR}"
|
||||||
|
|
||||||
|
# Build certresolver label if Let's Encrypt is configured
|
||||||
|
local ctrl_certresolver_label=""
|
||||||
|
if [[ -n "$ACME_EMAIL" ]]; then
|
||||||
|
ctrl_certresolver_label=' - "traefik.http.routers.controller.tls.certresolver=letsencrypt"'
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat > "${CONTROLLER_DIR}/docker-compose.yml" << EOF
|
||||||
|
# Felhom Controller — Central management dashboard
|
||||||
|
# Domain: felhom.${BASE_DOMAIN}
|
||||||
|
# Deployed by docker-setup.sh v${SCRIPT_VERSION}
|
||||||
|
|
||||||
|
services:
|
||||||
|
felhom-controller:
|
||||||
|
image: gitea.dooplex.hu/admin/felhom-controller:latest
|
||||||
|
container_name: felhom-controller
|
||||||
|
restart: unless-stopped
|
||||||
|
privileged: true
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ${CONTROLLER_DIR}/controller.yaml:/opt/docker/felhom-controller/controller.yaml:ro
|
||||||
|
- controller-data:/opt/docker/felhom-controller/data
|
||||||
|
- /opt/docker/stacks:/opt/docker/stacks
|
||||||
|
- /srv/backups:/srv/backups
|
||||||
|
- type: bind
|
||||||
|
source: /mnt
|
||||||
|
target: /mnt
|
||||||
|
bind:
|
||||||
|
propagation: rshared
|
||||||
|
- /sys:/host/sys:ro
|
||||||
|
- /etc/os-release:/host/etc/os-release:ro
|
||||||
|
- /etc/hostname:/host/etc/hostname:ro
|
||||||
|
- /dev:/host-dev:rw
|
||||||
|
- /etc/fstab:/host-fstab
|
||||||
|
- /run/udev:/run/udev:ro
|
||||||
|
environment:
|
||||||
|
- TZ=Europe/Budapest
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.controller.rule=Host(\`felhom.${BASE_DOMAIN}\`)"
|
||||||
|
- "traefik.http.routers.controller.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.controller.tls=true"
|
||||||
|
${ctrl_certresolver_label}
|
||||||
|
- "traefik.http.services.controller.loadbalancer.server.port=8080"
|
||||||
|
- "traefik.docker.network=traefik-public"
|
||||||
|
- "felhom.managed=true"
|
||||||
|
- "felhom.component=controller"
|
||||||
|
networks:
|
||||||
|
- traefik-public
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8080/api/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
start_period: 10s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
controller-data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik-public:
|
||||||
|
external: true
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cd "${CONTROLLER_DIR}"
|
||||||
|
log_info "Pulling felhom-controller image..."
|
||||||
|
docker compose pull -q
|
||||||
|
log_info "Starting felhom-controller..."
|
||||||
|
docker compose up -d --quiet-pull
|
||||||
|
|
||||||
|
# Wait for health check
|
||||||
|
sleep 5
|
||||||
|
if docker ps --filter "name=felhom-controller" --filter "status=running" -q | grep -q .; then
|
||||||
|
log_success "felhom-controller deployed at felhom.${BASE_DOMAIN}"
|
||||||
|
else
|
||||||
|
log_error "felhom-controller container is not running!"
|
||||||
|
docker compose logs --tail=20 felhom-controller
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Print summary
|
# Print summary
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
print_summary() {
|
print_summary() {
|
||||||
local server_ip
|
local server_ip
|
||||||
server_ip=$(get_server_ip)
|
server_ip=$(get_server_ip)
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BOLD}${GREEN}-==================================================================¬${NC}"
|
echo -e "${BOLD}${GREEN}-==================================================================¬${NC}"
|
||||||
echo -e "${BOLD}${GREEN}¦ Infrastructure Setup Complete! ¦${NC}"
|
echo -e "${BOLD}${GREEN}¦ Infrastructure Setup Complete! ¦${NC}"
|
||||||
@@ -1452,20 +1784,24 @@ print_summary() {
|
|||||||
echo ""
|
echo ""
|
||||||
echo -e "${BOLD}Server IP:${NC} ${server_ip}"
|
echo -e "${BOLD}Server IP:${NC} ${server_ip}"
|
||||||
echo -e "${BOLD}Domain:${NC} *.${BASE_DOMAIN}"
|
echo -e "${BOLD}Domain:${NC} *.${BASE_DOMAIN}"
|
||||||
|
echo -e "${BOLD}Customer:${NC} ${CUSTOMER_ID}"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BOLD}Services:${NC}"
|
echo -e "${BOLD}Services:${NC}"
|
||||||
|
echo " • Felhom Controller: https://felhom.${BASE_DOMAIN}"
|
||||||
|
echo " L| Config: ${CONTROLLER_DIR}/controller.yaml"
|
||||||
echo " • Traefik Dashboard: https://traefik.${BASE_DOMAIN}/dashboard/"
|
echo " • Traefik Dashboard: https://traefik.${BASE_DOMAIN}/dashboard/"
|
||||||
echo " L| Credentials: admin / ${TRAEFIK_PASSWORD}"
|
echo " L| Credentials: admin / ${TRAEFIK_PASSWORD}"
|
||||||
if [[ -n "$CF_TUNNEL_TOKEN" ]]; then
|
if [[ -n "${WIZ_CF_TUNNEL_TOKEN:-}" ]]; then
|
||||||
echo " • Cloudflare Tunnel: Active (routes configured in CF dashboard)"
|
echo " • Cloudflare Tunnel: Active (routes configured in CF dashboard)"
|
||||||
echo " L| Container: cloudflared"
|
echo " L| Container: cloudflared"
|
||||||
echo " L| Config: ${CLOUDFLARED_DIR}/docker-compose.yml"
|
echo " L| Config: ${CLOUDFLARED_DIR}/docker-compose.yml"
|
||||||
echo " L| Check: docker logs cloudflared"
|
echo " L| Check: docker logs cloudflared"
|
||||||
fi
|
fi
|
||||||
if [[ "$SKIP_FILEBROWSER" != true ]] && [[ -n "$HDD_PATH" ]]; then
|
if [[ "$SKIP_FILEBROWSER" != true ]]; then
|
||||||
echo " • FileBrowser: https://files.${BASE_DOMAIN}"
|
echo " • FileBrowser: https://files.${BASE_DOMAIN}"
|
||||||
echo " L| Default login: admin / admin (change immediately!)"
|
echo " L| Default login: admin / admin (change immediately!)"
|
||||||
fi
|
fi
|
||||||
|
echo -e " • Hub reporting: ${GREEN}enabled${NC} (hub.felhom.eu)"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BOLD}DNS Setup Required:${NC}"
|
echo -e "${BOLD}DNS Setup Required:${NC}"
|
||||||
echo " Add wildcard record to your DNS (Pi-hole, router, etc.):"
|
echo " Add wildcard record to your DNS (Pi-hole, router, etc.):"
|
||||||
@@ -1495,22 +1831,14 @@ print_summary() {
|
|||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
echo -e "${BOLD}${CYAN}===================================================================${NC}"
|
echo -e "${BOLD}${CYAN}===================================================================${NC}"
|
||||||
echo -e "${BOLD}${CYAN} DEPLOYING APPLICATION STACKS ${NC}"
|
echo -e "${BOLD}${CYAN} MANAGING APPLICATION STACKS ${NC}"
|
||||||
echo -e "${BOLD}${CYAN}===================================================================${NC}"
|
echo -e "${BOLD}${CYAN}===================================================================${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo " Deploy applications via the Felhom Controller dashboard:"
|
echo " Deploy and manage applications via the controller dashboard:"
|
||||||
echo ""
|
echo ""
|
||||||
echo " 1. Deploy felhom-controller (see controller/README.md)"
|
echo " 1. Open https://felhom.${BASE_DOMAIN}"
|
||||||
echo " 2. Open https://felhom.${BASE_DOMAIN}"
|
echo " 2. Browse available apps on the Alkalmazások page"
|
||||||
echo " 3. Browse available apps on the Alkalmazások page"
|
echo " 3. Click Telepítés to deploy"
|
||||||
echo " 4. Click Telepítés to deploy"
|
|
||||||
if [[ -n "$CUSTOMER_ID" ]]; then
|
|
||||||
echo ""
|
|
||||||
echo -e "${BOLD}Customer:${NC} ${CUSTOMER_ID}"
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}Note: No --customer specified. Templates use the generic catalog.${NC}"
|
|
||||||
echo -e "${YELLOW}Env vars (passwords, secrets) must be filled in manually.${NC}"
|
|
||||||
fi
|
|
||||||
echo ""
|
echo ""
|
||||||
if [[ -n "$CUSTOMER_ID" ]]; then
|
if [[ -n "$CUSTOMER_ID" ]]; then
|
||||||
echo -e "${BOLD}${YELLOW}Disaster Recovery:${NC}"
|
echo -e "${BOLD}${YELLOW}Disaster Recovery:${NC}"
|
||||||
@@ -1560,19 +1888,17 @@ main() {
|
|||||||
echo " 2. Configure network (Static IP: ${STATIC_IP:-DHCP})"
|
echo " 2. Configure network (Static IP: ${STATIC_IP:-DHCP})"
|
||||||
echo " 3. Install Docker Engine + Compose"
|
echo " 3. Install Docker Engine + Compose"
|
||||||
echo " 4. Install Traefik reverse proxy"
|
echo " 4. Install Traefik reverse proxy"
|
||||||
if [[ -n "$CF_TUNNEL_TOKEN" ]]; then
|
|
||||||
echo -e " 5. Install Cloudflare Tunnel connector: ${GREEN}yes${NC}"
|
|
||||||
else
|
|
||||||
echo -e " - Cloudflare Tunnel: ${CYAN}skip (no --cf-tunnel-token)${NC}"
|
|
||||||
fi
|
|
||||||
if [[ "$SELF_SIGNED_CERT" == true ]]; then
|
if [[ "$SELF_SIGNED_CERT" == true ]]; then
|
||||||
echo " - Generate self-signed certificate: yes"
|
echo " 5. Generate self-signed certificate"
|
||||||
fi
|
fi
|
||||||
echo " - Install FileBrowser: $([[ "$SKIP_FILEBROWSER" == true ]] && echo "skip" || echo "$([[ -n "$HDD_PATH" ]] && echo "yes (HDD: $HDD_PATH)" || echo "skip (no --hdd-path)")")"
|
echo " - Run configuration wizard (generates controller.yaml)"
|
||||||
|
echo " - Install Cloudflare Tunnel (if configured in wizard)"
|
||||||
|
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 " - Install helper tools (ctop, lazydocker, aliases)"
|
||||||
echo ""
|
echo ""
|
||||||
echo " Domain: *.${BASE_DOMAIN}"
|
echo " Domain: *.${BASE_DOMAIN}"
|
||||||
echo " Customer: ${CUSTOMER_ID:-<none — generic catalog>}"
|
echo " Customer: ${CUSTOMER_ID:-<none — will be set in wizard>}"
|
||||||
echo " Traefik password: ${TRAEFIK_PASSWORD}"
|
echo " Traefik password: ${TRAEFIK_PASSWORD}"
|
||||||
if [[ -n "$ACME_EMAIL" && -n "$CF_DNS_API_TOKEN" ]]; then
|
if [[ -n "$ACME_EMAIL" && -n "$CF_DNS_API_TOKEN" ]]; then
|
||||||
echo -e " TLS: ${GREEN}Let's Encrypt (Cloudflare DNS-01)${NC}"
|
echo -e " TLS: ${GREEN}Let's Encrypt (Cloudflare DNS-01)${NC}"
|
||||||
@@ -1586,29 +1912,28 @@ main() {
|
|||||||
else
|
else
|
||||||
echo -e " TLS: ${RED}None (Traefik default cert)${NC}"
|
echo -e " TLS: ${RED}None (Traefik default cert)${NC}"
|
||||||
fi
|
fi
|
||||||
if [[ -n "$CF_TUNNEL_TOKEN" ]]; then
|
|
||||||
echo " CF tunnel token: ${CF_TUNNEL_TOKEN:0:12}... (masked)"
|
|
||||||
fi
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
if [[ "$DRY_RUN" == true ]]; then
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
echo -e "${YELLOW}DRY RUN - no changes will be made${NC}"
|
echo -e "${YELLOW}DRY RUN - no changes will be made${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
read -p "Continue? [y/N] " -n 1 -r
|
read -p "Continue? [y/N] " -n 1 -r
|
||||||
echo
|
echo
|
||||||
[[ ! $REPLY =~ ^[Yy]$ ]] && exit 0
|
[[ ! $REPLY =~ ^[Yy]$ ]] && exit 0
|
||||||
|
|
||||||
install_base_packages
|
install_base_packages
|
||||||
configure_static_ip
|
configure_static_ip
|
||||||
install_docker
|
install_docker
|
||||||
install_traefik
|
install_traefik
|
||||||
install_cloudflare_tunnel
|
|
||||||
generate_self_signed_cert
|
generate_self_signed_cert
|
||||||
|
run_config_wizard
|
||||||
|
install_cloudflare_tunnel
|
||||||
install_filebrowser
|
install_filebrowser
|
||||||
|
install_controller
|
||||||
install_tools_and_configure
|
install_tools_and_configure
|
||||||
|
|
||||||
print_summary
|
print_summary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user