updated scripts
This commit is contained in:
+44
-15
@@ -28,10 +28,8 @@ sudo ./docker-setup.sh \
|
|||||||
--cf-token "your-cloudflare-api-token" \
|
--cf-token "your-cloudflare-api-token" \
|
||||||
--customer "customer-1"
|
--customer "customer-1"
|
||||||
|
|
||||||
# Hub mode — download pre-configured controller.yaml from Felhom Hub
|
# Hub mode — one-liner: all infra settings (domain, email, CF tokens) come from Hub
|
||||||
sudo ./docker-setup.sh \
|
sudo ./docker-setup.sh \
|
||||||
--domain example.com \
|
|
||||||
--email admin@example.com \
|
|
||||||
--hub-customer "customer-1" \
|
--hub-customer "customer-1" \
|
||||||
--hub-password "retrieval-password-from-hub"
|
--hub-password "retrieval-password-from-hub"
|
||||||
```
|
```
|
||||||
@@ -94,26 +92,33 @@ The script supports three mutually exclusive TLS modes:
|
|||||||
- Generates 10-year wildcard cert with custom CA
|
- Generates 10-year wildcard cert with custom CA
|
||||||
- CA cert copied to user home for manual device import
|
- CA cert copied to user home for manual device import
|
||||||
|
|
||||||
### Hub download mode
|
### Hub mode
|
||||||
|
|
||||||
When both `--hub-customer` and `--hub-password` are provided, the script downloads a
|
When both `--hub-customer` and `--hub-password` are provided, the script downloads a
|
||||||
pre-configured `controller.yaml` from the Felhom Hub instead of running the interactive wizard:
|
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:
|
||||||
|
|
||||||
```
|
```
|
||||||
GET https://hub.felhom.eu/api/v1/config/{customer_id}
|
GET https://hub.felhom.eu/api/v1/config/{customer_id}
|
||||||
Header: X-Retrieval-Password: {password}
|
Header: X-Retrieval-Password: {password}
|
||||||
```
|
```
|
||||||
|
|
||||||
On success:
|
The downloaded config is parsed early in the run and populates:
|
||||||
- Saves downloaded YAML as `controller.yaml` (permissions 600)
|
|
||||||
- Extracts domain, email, CF tokens for use by subsequent setup steps (Traefik, Cloudflare Tunnel)
|
|
||||||
- Skips the interactive wizard entirely
|
|
||||||
|
|
||||||
On failure:
|
| Extracted field | Used for |
|
||||||
- Logs a warning with HTTP status code
|
|-----------------|----------|
|
||||||
- Falls back to the interactive wizard
|
| `customer.domain` | Traefik routing, TLS cert SANs, DNS display |
|
||||||
|
| `customer.email` | Let's Encrypt ACME registration |
|
||||||
|
| `infrastructure.cf_api_token` | Traefik DNS-01 TLS challenge |
|
||||||
|
| `infrastructure.cf_tunnel_token` | Cloudflare Tunnel connector |
|
||||||
|
|
||||||
Hub credentials are created in the Hub web UI at `https://hub.felhom.eu/configs`.
|
CLI flags always take precedence — passing `--domain` overrides the hub value.
|
||||||
|
|
||||||
|
On failure (wrong credentials, network error):
|
||||||
|
- Script exits immediately with the HTTP status code and the failing URL
|
||||||
|
- Nothing is installed
|
||||||
|
|
||||||
|
Hub credentials are found in the Hub web UI under the customer's **Credentials** section.
|
||||||
|
|
||||||
### Configuration wizard
|
### Configuration wizard
|
||||||
|
|
||||||
@@ -220,8 +225,8 @@ sudo ./felhom-wipe.sh --level full --yes
|
|||||||
|-------|-----------------|
|
|-------|-----------------|
|
||||||
| `soft` | Controller state files only: `settings.json`, `metrics.db`, `setup-state.json`, `update-state.json`, `session-data.json`, `snapshot-history.json` |
|
| `soft` | Controller state files only: `settings.json`, `metrics.db`, `setup-state.json`, `update-state.json`, `session-data.json`, `snapshot-history.json` |
|
||||||
| `controller` | Soft + all non-infra Docker containers, all Docker volumes (except `portainer_data`), all stack directories (skips protected stacks by default) |
|
| `controller` | Soft + all non-infra Docker containers, all Docker volumes (except `portainer_data`), all stack directories (skips protected stacks by default) |
|
||||||
| `full` | `controller`-level cleanup + `felhom-data/` on all storage drives (appdata, backups). Also removes old-style `appdata/` and `backups/` directories for pre-v0.26.0 compatibility. Infra containers (including felhom-controller) are **preserved**; controller is restarted after cleanup. |
|
| `full` | `controller`-level cleanup + `felhom-data/` on all storage drives (appdata, backups). Also removes old-style `appdata/` and `backups/` directories for pre-v0.26.0 compatibility. Removes `/mnt/.felhom-scan/` (stale DR scan dir). Infra containers (including felhom-controller) are **preserved**; controller is restarted after cleanup. |
|
||||||
| `nuclear` | Full + all infra containers (controller, traefik, cloudflared, portainer), DR markers (`.felhom-infra-backup/` on all drives), `docker system prune -af --volumes`, and all infra config directories (`/opt/docker/felhom-controller/`, `/opt/docker/traefik/`, `/opt/docker/cloudflared/`, `/opt/docker/stacks/`) |
|
| `nuclear` | Full + all infra containers (controller, traefik, cloudflared, portainer), DR markers (`.felhom-infra-backup/` on all drives), raw helper mounts (`/mnt/.felhom-raw/` — unmount bind+raw, strip fstab entries), `/mnt/.felhom-scan/`, `docker system prune -af --volumes`, and all infra config directories (`/opt/docker/felhom-controller/`, `/opt/docker/traefik/`, `/opt/docker/cloudflared/`, `/opt/docker/stacks/`) |
|
||||||
|
|
||||||
### CLI options
|
### CLI options
|
||||||
|
|
||||||
@@ -237,11 +242,35 @@ sudo ./felhom-wipe.sh --level full --yes
|
|||||||
- Reads registered storage paths from `settings.json`
|
- Reads registered storage paths from `settings.json`
|
||||||
- Also scans `/mnt/*/` for `felhom-data/` or legacy `appdata/` directories not in the registry
|
- Also scans `/mnt/*/` for `felhom-data/` or legacy `appdata/` directories not in the registry
|
||||||
|
|
||||||
|
### Raw helper mounts
|
||||||
|
|
||||||
|
The attach wizard creates a two-level mount structure for pre-formatted drives:
|
||||||
|
|
||||||
|
```
|
||||||
|
/dev/sdb1 (physical partition)
|
||||||
|
└─ /mnt/.felhom-raw/hdd_1/ ← raw mount (persists in fstab, backs the bind)
|
||||||
|
└─ felhom_data/
|
||||||
|
└─ /mnt/hdd_1/ ← bind mount (what apps actually use)
|
||||||
|
```
|
||||||
|
|
||||||
|
Both `fstab` entries survive reboots. On `nuclear` wipe, the script:
|
||||||
|
1. Unmounts bind mounts (e.g. `/mnt/hdd_1`) first
|
||||||
|
2. Unmounts raw mounts (e.g. `/mnt/.felhom-raw/hdd_1`)
|
||||||
|
3. Strips both `fstab` entries
|
||||||
|
4. Removes the now-empty `/mnt/.felhom-raw/` directory
|
||||||
|
|
||||||
|
The physical data on the drive partition is **not touched** — only the mount point
|
||||||
|
directories (empty after unmounting) are removed.
|
||||||
|
|
||||||
|
`/mnt/.felhom-scan/` is a separate ephemeral directory used only during the DR setup
|
||||||
|
wizard to temporarily inspect drives. It is cleaned up from `full` level onwards.
|
||||||
|
|
||||||
### What is preserved
|
### What is preserved
|
||||||
|
|
||||||
- OS and system files
|
- OS and system files
|
||||||
- Infrastructure containers and config (unless `nuclear`)
|
- Infrastructure containers and config (unless `nuclear`)
|
||||||
- User files: `Dokumentumok/`, `media/`, other non-felhom directories on drives
|
- User files: `Dokumentumok/`, `media/`, other non-felhom directories on drives
|
||||||
|
- Drive data — raw mounts are unmounted but partition contents are untouched
|
||||||
- DR markers on drives (unless `nuclear`)
|
- DR markers on drives (unless `nuclear`)
|
||||||
|
|
||||||
### Safety
|
### Safety
|
||||||
|
|||||||
+105
-20
@@ -144,6 +144,11 @@ CUSTOMER_ID=""
|
|||||||
CF_TUNNEL_TOKEN=""
|
CF_TUNNEL_TOKEN=""
|
||||||
HUB_CUSTOMER=""
|
HUB_CUSTOMER=""
|
||||||
HUB_PASSWORD=""
|
HUB_PASSWORD=""
|
||||||
|
HUB_CONFIG_TMP="" # path to downloaded hub config temp file (set by apply_hub_config)
|
||||||
|
DOMAIN_FROM_CLI=false
|
||||||
|
EMAIL_FROM_CLI=false
|
||||||
|
CF_TOKEN_FROM_CLI=false
|
||||||
|
CF_TUNNEL_FROM_CLI=false
|
||||||
|
|
||||||
# Directories
|
# Directories
|
||||||
DOCKER_DATA_DIR="/opt/docker"
|
DOCKER_DATA_DIR="/opt/docker"
|
||||||
@@ -302,13 +307,13 @@ parse_args() {
|
|||||||
INTERFACE="$2"; shift 2 ;;
|
INTERFACE="$2"; shift 2 ;;
|
||||||
--domain)
|
--domain)
|
||||||
require_arg "$1" "${2:-}"
|
require_arg "$1" "${2:-}"
|
||||||
BASE_DOMAIN="$2"; shift 2 ;;
|
BASE_DOMAIN="$2"; DOMAIN_FROM_CLI=true; shift 2 ;;
|
||||||
--email)
|
--email)
|
||||||
require_arg "$1" "${2:-}"
|
require_arg "$1" "${2:-}"
|
||||||
ACME_EMAIL="$2"; shift 2 ;;
|
ACME_EMAIL="$2"; EMAIL_FROM_CLI=true; shift 2 ;;
|
||||||
--cf-token)
|
--cf-token)
|
||||||
require_arg "$1" "${2:-}"
|
require_arg "$1" "${2:-}"
|
||||||
CF_DNS_API_TOKEN="$2"; shift 2 ;;
|
CF_DNS_API_TOKEN="$2"; CF_TOKEN_FROM_CLI=true; shift 2 ;;
|
||||||
--traefik-password)
|
--traefik-password)
|
||||||
require_arg "$1" "${2:-}"
|
require_arg "$1" "${2:-}"
|
||||||
TRAEFIK_PASSWORD="$2"; shift 2 ;;
|
TRAEFIK_PASSWORD="$2"; shift 2 ;;
|
||||||
@@ -317,7 +322,7 @@ parse_args() {
|
|||||||
CUSTOMER_ID="$2"; shift 2 ;;
|
CUSTOMER_ID="$2"; shift 2 ;;
|
||||||
--cf-tunnel-token)
|
--cf-tunnel-token)
|
||||||
require_arg "$1" "${2:-}"
|
require_arg "$1" "${2:-}"
|
||||||
CF_TUNNEL_TOKEN="$2"; shift 2 ;;
|
CF_TUNNEL_TOKEN="$2"; CF_TUNNEL_FROM_CLI=true; shift 2 ;;
|
||||||
--hub-customer)
|
--hub-customer)
|
||||||
require_arg "$1" "${2:-}"
|
require_arg "$1" "${2:-}"
|
||||||
HUB_CUSTOMER="$2"; shift 2 ;;
|
HUB_CUSTOMER="$2"; shift 2 ;;
|
||||||
@@ -1461,6 +1466,88 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# YAML helper: extract a single string value from a section+key
|
||||||
|
# Usage: yaml_get <file> <top-level-section> <key>
|
||||||
|
# Handles both quoted ("value") and unquoted values.
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
yaml_get() {
|
||||||
|
local file="$1" section="$2" key="$3"
|
||||||
|
awk -v s="${section}:" -v k=" ${key}:" '
|
||||||
|
/^[[:alpha:]]/ { in_s = ($0 == s) }
|
||||||
|
in_s && index($0, k) == 1 {
|
||||||
|
sub(/^[^:]*: */, ""); gsub(/^"|"$/, ""); print; exit
|
||||||
|
}
|
||||||
|
' "$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Hub mode: download controller.yaml early and extract infra vars
|
||||||
|
# Called from main() before Traefik/infra setup so BASE_DOMAIN etc. are ready.
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
apply_hub_config() {
|
||||||
|
[[ -z "$HUB_CUSTOMER" ]] && return
|
||||||
|
|
||||||
|
log_info "Fetching configuration from Felhom Hub (customer: ${HUB_CUSTOMER})..."
|
||||||
|
|
||||||
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
|
echo -e "${CYAN}[DRY-RUN]${NC} Would fetch: https://hub.felhom.eu/api/v1/config/${HUB_CUSTOMER}"
|
||||||
|
echo -e "${CYAN}[DRY-RUN]${NC} Would apply domain, email, CF tokens from hub config"
|
||||||
|
# Set plausible placeholders so the plan display is meaningful
|
||||||
|
[[ "$DOMAIN_FROM_CLI" == false ]] && BASE_DOMAIN="<hub-domain>"
|
||||||
|
[[ "$EMAIL_FROM_CLI" == false ]] && ACME_EMAIL="<hub-email>"
|
||||||
|
[[ "$CF_TOKEN_FROM_CLI" == false ]] && CF_DNS_API_TOKEN="<hub-cf-token>"
|
||||||
|
[[ "$CF_TUNNEL_FROM_CLI" == false ]] && CF_TUNNEL_TOKEN="<hub-cf-tunnel-token>"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
HUB_CONFIG_TMP=$(mktemp /tmp/felhom-hub-config-XXXXXX.yaml)
|
||||||
|
|
||||||
|
local hub_url="https://hub.felhom.eu/api/v1/config/${HUB_CUSTOMER}"
|
||||||
|
local http_code
|
||||||
|
http_code=$(curl -fsSL \
|
||||||
|
-H "X-Retrieval-Password: ${HUB_PASSWORD}" \
|
||||||
|
-o "${HUB_CONFIG_TMP}" \
|
||||||
|
-w "%{http_code}" \
|
||||||
|
"${hub_url}" 2>&1) || true
|
||||||
|
|
||||||
|
if [[ "$http_code" != "200" ]]; then
|
||||||
|
rm -f "${HUB_CONFIG_TMP}"
|
||||||
|
HUB_CONFIG_TMP=""
|
||||||
|
log_error "Failed to fetch config from Felhom Hub (HTTP ${http_code})"
|
||||||
|
log_error "URL: ${hub_url}"
|
||||||
|
log_error "Check the customer ID and retrieval password, then re-run."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "Hub config fetched successfully"
|
||||||
|
|
||||||
|
# Extract values from hub YAML
|
||||||
|
local hub_domain hub_email hub_cf_token hub_tunnel_token
|
||||||
|
hub_domain=$(yaml_get "${HUB_CONFIG_TMP}" "customer" "domain")
|
||||||
|
hub_email=$(yaml_get "${HUB_CONFIG_TMP}" "customer" "email")
|
||||||
|
hub_cf_token=$(yaml_get "${HUB_CONFIG_TMP}" "infrastructure" "cf_api_token")
|
||||||
|
hub_tunnel_token=$(yaml_get "${HUB_CONFIG_TMP}" "infrastructure" "cf_tunnel_token")
|
||||||
|
|
||||||
|
# Apply to script vars — CLI flags always take precedence
|
||||||
|
if [[ "$DOMAIN_FROM_CLI" == false && -n "$hub_domain" ]]; then
|
||||||
|
BASE_DOMAIN="$hub_domain"
|
||||||
|
log_info " domain: ${BASE_DOMAIN} (from Hub)"
|
||||||
|
fi
|
||||||
|
if [[ "$EMAIL_FROM_CLI" == false && -n "$hub_email" ]]; then
|
||||||
|
ACME_EMAIL="$hub_email"
|
||||||
|
log_info " email: ${ACME_EMAIL} (from Hub)"
|
||||||
|
fi
|
||||||
|
if [[ "$CF_TOKEN_FROM_CLI" == false && -n "$hub_cf_token" ]]; then
|
||||||
|
CF_DNS_API_TOKEN="$hub_cf_token"
|
||||||
|
log_info " cf_api_token: ${CF_DNS_API_TOKEN:0:6}... (from Hub)"
|
||||||
|
fi
|
||||||
|
if [[ "$CF_TUNNEL_FROM_CLI" == false && -n "$hub_tunnel_token" ]]; then
|
||||||
|
CF_TUNNEL_TOKEN="$hub_tunnel_token"
|
||||||
|
log_info " cf_tunnel_token: ${CF_TUNNEL_TOKEN:0:6}... (from Hub)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Generate minimal controller.yaml — full configuration via web UI setup wizard
|
# Generate minimal controller.yaml — full configuration via web UI setup wizard
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
@@ -1474,30 +1561,24 @@ generate_minimal_config() {
|
|||||||
mkdir -p "${CONTROLLER_DIR}"
|
mkdir -p "${CONTROLLER_DIR}"
|
||||||
|
|
||||||
if [[ -n "$HUB_CUSTOMER" ]]; then
|
if [[ -n "$HUB_CUSTOMER" ]]; then
|
||||||
log_step "${step_num}/$(get_total_steps) - Downloading controller.yaml from Felhom Hub..."
|
log_step "${step_num}/$(get_total_steps) - Installing controller.yaml from Felhom Hub..."
|
||||||
|
|
||||||
if [[ "$DRY_RUN" == true ]]; then
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
echo -e "${CYAN}[DRY-RUN]${NC} Would download controller.yaml from https://hub.felhom.eu/api/v1/config/${HUB_CUSTOMER}"
|
echo -e "${CYAN}[DRY-RUN]${NC} Would install hub controller.yaml to ${CONTROLLER_DIR}/controller.yaml"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local hub_url="https://hub.felhom.eu/api/v1/config/${HUB_CUSTOMER}"
|
# Config was already downloaded by apply_hub_config() early in main()
|
||||||
local http_code
|
if [[ -n "$HUB_CONFIG_TMP" && -f "$HUB_CONFIG_TMP" ]]; then
|
||||||
http_code=$(curl -fsSL \
|
mv "${HUB_CONFIG_TMP}" "${CONTROLLER_DIR}/controller.yaml"
|
||||||
-H "X-Retrieval-Password: ${HUB_PASSWORD}" \
|
HUB_CONFIG_TMP=""
|
||||||
-o "${CONTROLLER_DIR}/controller.yaml" \
|
|
||||||
-w "%{http_code}" \
|
|
||||||
"${hub_url}" 2>&1) || true
|
|
||||||
|
|
||||||
if [[ "$http_code" == "200" ]]; then
|
|
||||||
chmod 600 "${CONTROLLER_DIR}/controller.yaml"
|
|
||||||
log_success "controller.yaml downloaded from Felhom Hub (customer: ${HUB_CUSTOMER})"
|
|
||||||
else
|
else
|
||||||
log_error "Failed to download controller.yaml from Hub (HTTP ${http_code})"
|
log_error "Hub config temp file not found — apply_hub_config() may not have run"
|
||||||
log_error "URL: ${hub_url}"
|
|
||||||
log_error "Check the customer ID and retrieval password, then re-run."
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
chmod 600 "${CONTROLLER_DIR}/controller.yaml"
|
||||||
|
log_success "controller.yaml installed from Felhom Hub (customer: ${HUB_CUSTOMER})"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1735,6 +1816,10 @@ main() {
|
|||||||
set -x
|
set -x
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Hub mode: download config early so BASE_DOMAIN, ACME_EMAIL, CF tokens are
|
||||||
|
# available before Traefik and other infra steps run
|
||||||
|
apply_hub_config
|
||||||
|
|
||||||
print_banner
|
print_banner
|
||||||
check_debian
|
check_debian
|
||||||
|
|
||||||
|
|||||||
@@ -209,6 +209,16 @@ print_plan() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "$LEVEL" == "full" || "$LEVEL" == "nuclear" ]]; then
|
||||||
|
echo ""
|
||||||
|
echo -e "${CYAN}Mount cleanup:${NC}"
|
||||||
|
if [ -d /mnt/.felhom-scan ]; then
|
||||||
|
echo -e " ${YELLOW}DELETE${NC} /mnt/.felhom-scan/ (stale scan dir)"
|
||||||
|
else
|
||||||
|
echo -e " ${GREEN}(no .felhom-scan dir)${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "$LEVEL" == "full" || "$LEVEL" == "nuclear" ]]; then
|
if [[ "$LEVEL" == "full" || "$LEVEL" == "nuclear" ]]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}Storage data:${NC}"
|
echo -e "${CYAN}Storage data:${NC}"
|
||||||
@@ -239,6 +249,21 @@ print_plan() {
|
|||||||
echo -e " ${RED}DELETE${NC} Cloudflared container"
|
echo -e " ${RED}DELETE${NC} Cloudflared container"
|
||||||
echo -e " ${RED}DELETE${NC} Portainer container + volume"
|
echo -e " ${RED}DELETE${NC} Portainer container + volume"
|
||||||
echo -e " ${RED}DELETE${NC} .felhom-infra-backup/ (DR markers on all drives)"
|
echo -e " ${RED}DELETE${NC} .felhom-infra-backup/ (DR markers on all drives)"
|
||||||
|
if [ -d /mnt/.felhom-raw ]; then
|
||||||
|
echo -e " ${RED}UNMOUNT+DELETE${NC} /mnt/.felhom-raw/ (raw helper mounts + fstab entries)"
|
||||||
|
# Show each raw mount and its bind target
|
||||||
|
for rmp in /mnt/.felhom-raw/*/; do
|
||||||
|
[ -d "$rmp" ] || continue
|
||||||
|
local label; label=$(basename "$rmp")
|
||||||
|
local bind_target
|
||||||
|
bind_target=$(grep -E "^/mnt/\.felhom-raw/${label}/" /etc/fstab 2>/dev/null | awk '{print $2}' | head -1 || true)
|
||||||
|
if [ -n "$bind_target" ]; then
|
||||||
|
echo -e " ${RED}umount${NC} ${bind_target} (bind) → ${rmp} (raw)"
|
||||||
|
else
|
||||||
|
echo -e " ${RED}umount${NC} ${rmp} (raw, no bind found)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
echo -e " ${RED}DELETE${NC} All Docker data (docker system prune -af --volumes)"
|
echo -e " ${RED}DELETE${NC} All Docker data (docker system prune -af --volumes)"
|
||||||
echo -e " ${RED}DELETE${NC} $COMPOSE_DIR/ (controller compose + .env)"
|
echo -e " ${RED}DELETE${NC} $COMPOSE_DIR/ (controller compose + .env)"
|
||||||
local infra_root; infra_root=$(dirname "$COMPOSE_DIR")
|
local infra_root; infra_root=$(dirname "$COMPOSE_DIR")
|
||||||
@@ -264,6 +289,57 @@ print_plan() {
|
|||||||
echo ""
|
echo ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# --- Mount Cleanup Helpers ---
|
||||||
|
|
||||||
|
# cleanup_scan_dir: remove /mnt/.felhom-scan/ (ephemeral DR scan staging dir).
|
||||||
|
# Always empty after normal operation; safe to rm -rf unconditionally.
|
||||||
|
cleanup_scan_dir() {
|
||||||
|
if [ -d /mnt/.felhom-scan ]; then
|
||||||
|
rm -rf /mnt/.felhom-scan && info " Removed: /mnt/.felhom-scan/"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# cleanup_raw_mounts: unmount bind mounts, unmount raw helper mounts, strip
|
||||||
|
# /etc/fstab entries, then remove the now-empty /mnt/.felhom-raw/ directory.
|
||||||
|
#
|
||||||
|
# Raw mounts are created by the attach wizard (two-level: raw partition mount +
|
||||||
|
# bind mount from subfolder). Both fstab entries must be removed so they don't
|
||||||
|
# cause errors on next boot. Order: bind umount first, then raw umount.
|
||||||
|
cleanup_raw_mounts() {
|
||||||
|
[ -d /mnt/.felhom-raw ] || return
|
||||||
|
|
||||||
|
info "Cleaning up raw helper mounts (/mnt/.felhom-raw/)..."
|
||||||
|
|
||||||
|
# 1. Unmount bind mounts whose source is inside .felhom-raw (field 1 matches)
|
||||||
|
if [ -f /etc/fstab ]; then
|
||||||
|
local bind_targets
|
||||||
|
bind_targets=$(grep -E '^/mnt/\.felhom-raw/' /etc/fstab | awk '{print $2}' || true)
|
||||||
|
for mp in $bind_targets; do
|
||||||
|
if mountpoint -q "$mp" 2>/dev/null; then
|
||||||
|
umount -l "$mp" 2>/dev/null && info " Unmounted bind: $mp" \
|
||||||
|
|| warn " Could not unmount bind: $mp"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2. Unmount raw partition mounts (field 2 matches /mnt/.felhom-raw/*)
|
||||||
|
for mp in /mnt/.felhom-raw/*/; do
|
||||||
|
[ -d "$mp" ] || continue
|
||||||
|
if mountpoint -q "$mp" 2>/dev/null; then
|
||||||
|
umount -l "$mp" 2>/dev/null && info " Unmounted raw: $mp" \
|
||||||
|
|| warn " Could not unmount raw: $mp"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# 3. Strip all .felhom-raw entries from fstab (both raw and bind lines)
|
||||||
|
if [ -f /etc/fstab ] && grep -q '\.felhom-raw' /etc/fstab 2>/dev/null; then
|
||||||
|
sed -i '\|\.felhom-raw|d' /etc/fstab && info " Removed .felhom-raw entries from /etc/fstab"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. Remove directory — safe now that mounts are gone
|
||||||
|
rm -rf /mnt/.felhom-raw && info " Removed: /mnt/.felhom-raw/"
|
||||||
|
}
|
||||||
|
|
||||||
# --- Wipe Functions ---
|
# --- Wipe Functions ---
|
||||||
|
|
||||||
do_soft_wipe() {
|
do_soft_wipe() {
|
||||||
@@ -336,6 +412,9 @@ do_full_wipe() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Remove stale scan dir (ephemeral DR staging — always safe to remove)
|
||||||
|
cleanup_scan_dir
|
||||||
|
|
||||||
# Restart controller after all cleanup is done
|
# Restart controller after all cleanup is done
|
||||||
info "Restarting controller..."
|
info "Restarting controller..."
|
||||||
docker restart felhom-controller 2>/dev/null || warn "Could not restart controller"
|
docker restart felhom-controller 2>/dev/null || warn "Could not restart controller"
|
||||||
@@ -358,6 +437,10 @@ do_nuclear_wipe() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Unmount raw helper mounts, strip fstab entries, remove dirs
|
||||||
|
# (scan dir already removed by do_full_wipe above)
|
||||||
|
cleanup_raw_mounts
|
||||||
|
|
||||||
# Remove all Docker data
|
# Remove all Docker data
|
||||||
warn "Pruning all Docker data..."
|
warn "Pruning all Docker data..."
|
||||||
docker system prune -af --volumes 2>/dev/null || warn "Docker prune failed"
|
docker system prune -af --volumes 2>/dev/null || warn "Docker prune failed"
|
||||||
|
|||||||
Reference in New Issue
Block a user