feat(setup): hub mode triggers setup wizard with infra backup restore
docker-setup.sh --hub-customer now generates a minimal controller.yaml (no customer.id) instead of installing full hub config, triggering the setup wizard on first run. Hub credentials are passed via env vars (FELHOM_SETUP_CUSTOMER_ID, FELHOM_SETUP_PASSWORD) so the wizard auto-fills and auto-processes Hub API calls. Welcome page shows three options in hub mode: restore from Hub (primary), restore from local drives, or fresh install. On error, falls back to manual form with error displayed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+24
-4
@@ -94,16 +94,17 @@ The script supports three mutually exclusive TLS modes:
|
||||
|
||||
### Hub mode
|
||||
|
||||
When both `--hub-customer` and `--hub-password` are provided, the script downloads a
|
||||
pre-configured `controller.yaml` from the Felhom Hub **before any infra setup begins**,
|
||||
then extracts the stored values to auto-configure everything — no additional flags needed:
|
||||
When both `--hub-customer` and `--hub-password` are provided, the script downloads the
|
||||
customer's config from the Felhom Hub **before any infra setup begins** to extract
|
||||
infrastructure variables (domain, email, CF tokens), then generates a **minimal**
|
||||
`controller.yaml` without `customer.id` — triggering the setup wizard on first run.
|
||||
|
||||
```
|
||||
GET https://hub.felhom.eu/api/v1/config/{customer_id}
|
||||
Header: X-Retrieval-Password: {password}
|
||||
```
|
||||
|
||||
The downloaded config is parsed early in the run and populates:
|
||||
The downloaded config is parsed early and populates infrastructure variables:
|
||||
|
||||
| Extracted field | Used for |
|
||||
|-----------------|----------|
|
||||
@@ -114,6 +115,25 @@ The downloaded config is parsed early in the run and populates:
|
||||
|
||||
CLI flags always take precedence — passing `--domain` overrides the hub value.
|
||||
|
||||
The hub credentials are passed to the controller via environment variables
|
||||
(`FELHOM_SETUP_CUSTOMER_ID`, `FELHOM_SETUP_PASSWORD`) so the setup wizard auto-fills
|
||||
them. On first access, the wizard offers three choices:
|
||||
|
||||
1. **Restore from Hub** — downloads infra backup (settings, encryption keys, restic
|
||||
passwords, disk layout) and restores everything. Credentials are auto-processed.
|
||||
2. **Restore from local drive** — scans connected drives for `.felhom-infra-backup/`.
|
||||
3. **Fresh install** — downloads config only, starts with clean settings.
|
||||
|
||||
```
|
||||
docker-setup.sh --hub-customer demo-felhom --hub-password xxx
|
||||
→ downloads config for infra vars (domain, CF tokens)
|
||||
→ generates minimal controller.yaml (no customer.id)
|
||||
→ passes hub credentials via env vars
|
||||
→ controller starts in setup mode
|
||||
→ user opens http://<ip>:8081
|
||||
→ setup wizard: restore / local scan / fresh install
|
||||
```
|
||||
|
||||
On failure (wrong credentials, network error):
|
||||
- Script exits immediately with the HTTP status code and the failing URL
|
||||
- Nothing is installed
|
||||
|
||||
+42
-18
@@ -31,8 +31,8 @@
|
||||
# --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)
|
||||
# --hub-customer ID Download config from Felhom Hub: customer ID
|
||||
# --hub-password PW Download config from Felhom Hub: retrieval password
|
||||
# --hub-customer ID Hub mode: pre-seed setup wizard with customer ID
|
||||
# --hub-password PW Hub mode: retrieval password for setup wizard
|
||||
# --traefik-password PW Password for Traefik dashboard (default: auto-generated)
|
||||
# --self-signed-cert Generate self-signed wildcard certificate
|
||||
# --skip-filebrowser Skip FileBrowser installation
|
||||
@@ -219,8 +219,8 @@ OPTIONS:
|
||||
--bootstrap Install sudo (run first on fresh Debian)
|
||||
--domain DOMAIN Base domain for services (required)
|
||||
--customer ID Customer identifier (optional, set in web wizard)
|
||||
--hub-customer ID Download config from Felhom Hub: customer ID
|
||||
--hub-password PW Download config from Felhom Hub: retrieval password
|
||||
--hub-customer ID Hub mode: pre-seed setup wizard with customer ID
|
||||
--hub-password PW Hub mode: retrieval password for setup 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)
|
||||
@@ -274,7 +274,7 @@ EXAMPLES:
|
||||
--ip 192.168.0.50 --email certs@felhom.eu --cf-token cf-xxx \
|
||||
--cf-tunnel-token eyJhIjoi...
|
||||
|
||||
# Hub mode — download pre-configured controller.yaml from Felhom Hub
|
||||
# Hub mode — setup wizard with pre-seeded credentials (offers restore/fresh choice)
|
||||
sudo ./docker-setup.sh --hub-customer demo-felhom --hub-password <retrieval-password>
|
||||
EOF
|
||||
}
|
||||
@@ -1585,24 +1585,41 @@ generate_minimal_config() {
|
||||
mkdir -p "${CONTROLLER_DIR}"
|
||||
|
||||
if [[ -n "$HUB_CUSTOMER" ]]; then
|
||||
log_step "${step_num}/$(get_total_steps) - Installing controller.yaml from Felhom Hub..."
|
||||
log_step "${step_num}/$(get_total_steps) - Generating minimal controller.yaml (setup wizard will handle full config)..."
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
echo -e "${CYAN}[DRY-RUN]${NC} Would install hub controller.yaml to ${CONTROLLER_DIR}/controller.yaml"
|
||||
echo -e "${CYAN}[DRY-RUN]${NC} Would generate minimal controller.yaml for setup wizard"
|
||||
echo -e "${CYAN}[DRY-RUN]${NC} Hub credentials pre-seeded via env vars (customer: ${HUB_CUSTOMER})"
|
||||
return
|
||||
fi
|
||||
|
||||
# Config was already downloaded by apply_hub_config() early in main()
|
||||
# Discard full hub config — we only needed it for infra vars (domain, CF tokens)
|
||||
if [[ -n "$HUB_CONFIG_TMP" && -f "$HUB_CONFIG_TMP" ]]; then
|
||||
mv "${HUB_CONFIG_TMP}" "${CONTROLLER_DIR}/controller.yaml"
|
||||
rm -f "${HUB_CONFIG_TMP}"
|
||||
HUB_CONFIG_TMP=""
|
||||
else
|
||||
log_error "Hub config temp file not found — apply_hub_config() may not have run"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Generate minimal config WITHOUT customer.id — triggers setup wizard
|
||||
# The setup wizard will download full config + offer infra backup restore
|
||||
cat > "${CONTROLLER_DIR}/controller.yaml" << YAMLEOF
|
||||
# Auto-generated by docker-setup.sh v${SCRIPT_VERSION} on $(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
# Hub mode: full configuration via web setup wizard (credentials pre-seeded)
|
||||
# Setup wizard: https://felhom.${BASE_DOMAIN} or http://<ip>:8081
|
||||
|
||||
customer:
|
||||
domain: "${BASE_DOMAIN}"
|
||||
|
||||
paths:
|
||||
data_dir: "/opt/docker/felhom-controller/data"
|
||||
stacks_dir: "/opt/docker/stacks"
|
||||
|
||||
web:
|
||||
listen: ":8080"
|
||||
setup_listen: ":8081"
|
||||
YAMLEOF
|
||||
|
||||
chmod 600 "${CONTROLLER_DIR}/controller.yaml"
|
||||
log_success "controller.yaml installed from Felhom Hub (customer: ${HUB_CUSTOMER})"
|
||||
log_success "Minimal controller.yaml generated (setup wizard will offer restore/fresh choice)"
|
||||
return
|
||||
fi
|
||||
|
||||
@@ -1663,6 +1680,13 @@ install_controller() {
|
||||
ctrl_certresolver_label=' - "traefik.http.routers.controller.tls.certresolver=letsencrypt"'
|
||||
fi
|
||||
|
||||
# Hub mode: pass pre-seeded credentials to setup wizard via env vars
|
||||
local hub_setup_env=""
|
||||
if [[ -n "$HUB_CUSTOMER" ]]; then
|
||||
hub_setup_env=" - FELHOM_SETUP_CUSTOMER_ID=${HUB_CUSTOMER}
|
||||
- FELHOM_SETUP_PASSWORD=${HUB_PASSWORD}"
|
||||
fi
|
||||
|
||||
cat > "${CONTROLLER_DIR}/docker-compose.yml" << EOF
|
||||
# Felhom Controller — Central management dashboard
|
||||
# Domain: felhom.${BASE_DOMAIN}
|
||||
@@ -1697,6 +1721,7 @@ services:
|
||||
environment:
|
||||
- TZ=Europe/Budapest
|
||||
- HOST_IP=$(get_server_ip)
|
||||
${hub_setup_env}
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.controller.rule=Host(\`felhom.${BASE_DOMAIN}\`)"
|
||||
@@ -1763,7 +1788,7 @@ print_summary() {
|
||||
echo -e "${BOLD}Server IP:${NC} ${server_ip}"
|
||||
echo -e "${BOLD}Domain:${NC} *.${BASE_DOMAIN}"
|
||||
if [[ -n "$HUB_CUSTOMER" ]]; then
|
||||
echo -e "${BOLD}Customer:${NC} ${HUB_CUSTOMER} (from Hub)"
|
||||
echo -e "${BOLD}Customer:${NC} ${HUB_CUSTOMER} (Hub credentials pre-seeded for setup wizard)"
|
||||
elif [[ -n "$CUSTOMER_ID" ]]; then
|
||||
echo -e "${BOLD}Customer:${NC} ${CUSTOMER_ID}"
|
||||
fi
|
||||
@@ -1857,10 +1882,9 @@ main() {
|
||||
if [[ "$SELF_SIGNED_CERT" == true ]]; then
|
||||
echo " 5. Generate self-signed certificate"
|
||||
fi
|
||||
echo " - Generate minimal controller.yaml"
|
||||
if [[ -n "$HUB_CUSTOMER" ]]; then
|
||||
echo " - Download controller.yaml from Felhom Hub (customer: ${HUB_CUSTOMER})"
|
||||
else
|
||||
echo " - Generate minimal controller.yaml"
|
||||
echo " (Hub mode: setup wizard pre-seeded for ${HUB_CUSTOMER})"
|
||||
fi
|
||||
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)")"
|
||||
@@ -1869,7 +1893,7 @@ main() {
|
||||
echo ""
|
||||
echo " Domain: *.${BASE_DOMAIN}"
|
||||
if [[ -n "$HUB_CUSTOMER" ]]; then
|
||||
echo " Hub customer: ${HUB_CUSTOMER} (config downloaded from Hub)"
|
||||
echo " Hub customer: ${HUB_CUSTOMER} (setup wizard will offer restore/fresh choice)"
|
||||
else
|
||||
echo " Customer: ${CUSTOMER_ID:-<none — will be set in web setup wizard>}"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user