@@ -18,6 +18,7 @@ MEDIA_SERVER=plex
1818TDARR_MODE=native
1919CLOUD_STORAGE=false
2020NAS_STORAGE=false
21+ FORCE_CONFIGURE=false
2122
2223usage () {
2324 cat << EOF
@@ -31,6 +32,7 @@ Options:
3132 --tdarr-docker Shortcut for --tdarr-mode docker
3233 --cloud-storage Enable cloud storage (rclone + mergerfs)
3334 --nas-storage Enable NAS storage via SFTP (rclone + mergerfs)
35+ --force-configure Re-run configure.sh even if configure.done exists
3436 --non-interactive Skip interactive prompts (manual Seerr wiring required)
3537 --help Show this help message
3638
@@ -40,6 +42,7 @@ Examples:
4042 bash bootstrap.sh --tdarr-docker
4143 bash bootstrap.sh --jellyfin --cloud-storage --tdarr-docker
4244 bash bootstrap.sh --jellyfin --nas-storage --tdarr-docker
45+ bash bootstrap.sh --force-configure
4346 bash bootstrap.sh --media-dir /Volumes/T9/Media --non-interactive
4447EOF
4548}
@@ -87,6 +90,10 @@ while [[ $# -gt 0 ]]; do
8790 CLOUD_STORAGE=true
8891 shift
8992 ;;
93+ --force-configure)
94+ FORCE_CONFIGURE=true
95+ shift
96+ ;;
9097 --non-interactive)
9198 NON_INTERACTIVE=true
9299 shift
@@ -221,6 +228,60 @@ wait_for_healthy_container() {
221228 return 1
222229}
223230
231+ wait_for_services_batch () {
232+ local timeout_seconds=" ${1:- 90} "
233+ shift
234+ local names=()
235+ local urls=()
236+ local ready=()
237+ local total ready_count start now elapsed i status
238+
239+ while [[ $# -gt 1 ]]; do
240+ names+=(" $1 " )
241+ urls+=(" $2 " )
242+ shift 2
243+ done
244+
245+ total=" ${# names[@]} "
246+ ready_count=0
247+ for (( i = 0 ; i < total; i++ )) ; do
248+ ready[$i ]=0
249+ done
250+
251+ start=$( date +%s)
252+ while true ; do
253+ for (( i = 0 ; i < total; i++ )) ; do
254+ if [[ " ${ready[$i]} " -eq 1 ]]; then
255+ continue
256+ fi
257+ status=$( curl -s -o /dev/null -w " %{http_code}" --max-time 3 " ${urls[$i]} " 2> /dev/null || true)
258+ if [[ " $status " =~ ^(200| 301| 302| 401| 403)$ ]]; then
259+ ready[$i ]=1
260+ ready_count=$(( ready_count + 1 ))
261+ echo -e " ${GREEN} OK${NC} ${names[$i]} is reachable"
262+ fi
263+ done
264+
265+ if [[ " $ready_count " -eq " $total " ]]; then
266+ return 0
267+ fi
268+
269+ now=$( date +%s)
270+ elapsed=$(( now - start))
271+ if [[ " $elapsed " -ge " $timeout_seconds " ]]; then
272+ local pending=()
273+ for (( i = 0 ; i < total; i++ )) ; do
274+ if [[ " ${ready[$i]} " -eq 0 ]]; then
275+ pending+=(" ${names[$i]} " )
276+ fi
277+ done
278+ echo -e " ${YELLOW} WARN${NC} Timed out waiting after ${timeout_seconds} s: ${pending[*]} "
279+ return 1
280+ fi
281+ sleep 2
282+ done
283+ }
284+
224285INSTALLED_RUNTIME=$( detect_installed_runtime)
225286
226287if ! docker info & > /dev/null; then
442503
443504echo " "
444505echo " Waiting for core services..."
445- wait_for_service " qBittorrent" " http://localhost:8080" || true
446- wait_for_service " Prowlarr" " http://localhost:9696" || true
447- wait_for_service " Radarr" " http://localhost:7878" || true
448- wait_for_service " Sonarr" " http://localhost:8989" || true
449- wait_for_service " Seerr" " http://localhost:5055" || true
506+ core_service_checks=(
507+ " qBittorrent" " http://localhost:8080"
508+ " Prowlarr" " http://localhost:9696"
509+ " Radarr" " http://localhost:7878"
510+ " Sonarr" " http://localhost:8989"
511+ " Seerr" " http://localhost:5055"
512+ )
450513if [[ " $MEDIA_SERVER " == " jellyfin" ]]; then
451- wait_for_service " Jellyfin" " http://localhost:8096/health" || true
514+ core_service_checks+=( " Jellyfin" " http://localhost:8096/health" )
452515fi
516+ if [[ " $TDARR_MODE " == " docker" ]]; then
517+ core_service_checks+=(" Tdarr" " http://localhost:8265" )
518+ fi
519+ wait_for_services_batch 90 " ${core_service_checks[@]} " || true
453520
454521if [[ " $CLOUD_ACTIVE " == true ]]; then
455522 echo " "
@@ -467,17 +534,18 @@ if [[ "$TDARR_MODE" == "native" ]]; then
467534 echo " bash scripts/setup-tdarr-native.sh --media-dir $MEDIA_DIR "
468535 exit 1
469536 fi
470- else
471- wait_for_service " Tdarr" " http://localhost:8265" || true
472537fi
473538
474539# Configure
475540echo " "
541+ CONFIG_ARGS=(--skip-wait)
476542if [[ " $NON_INTERACTIVE " == true ]]; then
477- bash scripts/configure.sh --non-interactive
478- else
479- bash scripts/configure.sh
543+ CONFIG_ARGS+=(--non-interactive)
544+ fi
545+ if [[ " $FORCE_CONFIGURE " == true ]]; then
546+ CONFIG_ARGS+=(--force)
480547fi
548+ bash scripts/configure.sh " ${CONFIG_ARGS[@]} "
481549
482550# Install automation
483551echo " "
0 commit comments