Commit Graph

97 Commits

Author SHA1 Message Date
JaviPege
20be39799b Merge branch 'main' into feature/optional-services 2025-11-11 11:08:20 +01:00
JaviPege
4d411b7fcd Merge pull request #16 from marcomarinho/seerr
[WIP] Move from Overseerr to Seerr
2025-11-10 13:39:14 +01:00
Marco Marinho
7d29501741 Move from Overseerr to Seerr
Overseerr and Jellyseerr will be merged and be called Seerr, so let's prepare for it
2025-11-01 18:36:12 +00:00
JaviPege
83475255b6 refactor: add core system functions (step 1 of reorganization)
Created 6 new core system functions to group all CORE service operations:
- setup_core_users(): Creates rclone, radarr, sonarr, prowlarr, decypharr, zilean, zurg
- setup_core_directories(): Creates all core config and data directories
- setup_core_permissions(): Sets permissions for core directories
- setup_core_files(): Copies/creates rclone.conf, zurg config, decypharr config
- start_core_services(): Starts 10 core Docker containers
- configure_core_services(): Configures radarr, sonarr, prowlarr, decypharr

These functions group ALL operations for core services (minimum functional system).
Next step: Create optional service functions and refactor PHASE 3/4.

Part of reorganization plan to prepare for dynamic service selection.
2025-10-23 00:09:25 +02:00
JaviPege
67975acfd5 feat: add Decypharr authentication configuration
Added configure_decypharr_authentication() atomic function to configure
Decypharr authentication when user enables auth during setup.

Implementation:
- New atomic function: configure_decypharr_authentication(port, username, password)
- Uses Decypharr's specific endpoint: POST /api/update-auth
- Payload format: {username, password, confirm_password}
- Called after Sonarr authentication when AUTH_ENABLED=true

This ensures Decypharr is protected with the same credentials as
Radarr, Sonarr, and Prowlarr when authentication is enabled.
2025-10-22 23:56:18 +02:00
JaviPege
c2ac6923e6 chore: remove debug JSON logging from add_download_client
The debug logging was added temporarily to diagnose JSON syntax errors.
Issue is now fixed (DECYPHARR_CONTAINER_PORT was missing from .env.defaults).
Removing debug output to keep installation logs clean.
2025-10-22 23:43:48 +02:00
JaviPege
82e822eb28 fix: use API v1 for Prowlarr authentication instead of v3
Problem:
- configure_arr_authentication was hardcoded to use /api/v3/ for all services
- Prowlarr uses /api/v1/ while Radarr/Sonarr use /api/v3/
- This caused 'Failed to get Prowlarr config for authentication setup' error

Solution:
- Added optional 6th parameter 'api_version' to configure_arr_authentication
- Defaults to 'v3' for Radarr/Sonarr (backward compatible)
- Pass 'v1' explicitly when calling for Prowlarr

This fixes Prowlarr authentication configuration during setup.
2025-10-22 23:35:09 +02:00
JaviPege
159933d076 fix: add DECYPHARR_CONTAINER_PORT to .env.defaults
Problem:
- DECYPHARR_CONTAINER_PORT was referenced in setup.sh but not defined in .env.defaults
- This caused $DECYPHARR_CONTAINER_PORT to be empty, generating invalid JSON
- Invalid JSON error: "'}' is an invalid start of a value" in fields[1].value

Solution:
- Added DECYPHARR_CONTAINER_PORT=8282 to .env.defaults
- This is the internal container port (8282) vs the host port (8283)
- Docker containers communicate using internal ports within the network

This fixes the JSON parse error when adding Decypharr as download client.
2025-10-22 23:29:00 +02:00
JaviPege
f31cfcc0f4 debug: show raw JSON before jq parsing 2025-10-22 23:26:32 +02:00
JaviPege
25942c64ec Revert "fix: use correct download_api_key parameter in add_download_client call"
This reverts commit 1127a62ad5.
2025-10-22 23:23:16 +02:00
JaviPege
1127a62ad5 fix: use correct download_api_key parameter in add_download_client call
Problem:
- configure_arr_service was passing $api_key (Radarr/Sonarr API key) twice
- Should pass $download_api_key (parameter 6) as the client API key
- This caused the wrong API key to be used for Decypharr configuration

Solution:
- Changed line 38 in setup-services.sh to use $download_api_key instead of $api_key
- Now correctly passes the download client's API key to add_download_client
2025-10-22 23:22:16 +02:00
JaviPege
1adaaaf434 debug: add JSON validation logging to add_download_client 2025-10-22 23:21:33 +02:00
JaviPege
53f9106f0d fix: remove 'local' declaration outside function scope
Problem:
- Line 1290 had 'local status' inside a for loop in the main script scope
- 'local' can only be used inside functions in Bash
- This caused 17 errors: 'local: can only be used in a function'

Solution:
- Changed 'local status' to 'status=""' (regular variable initialization)
- The variable is properly scoped to the loop iteration

This fixes the error seen during service validation phase.
2025-10-22 23:19:15 +02:00
JaviPege
51809da2c1 fix: use Decypharr internal container port for inter-container communication
Problem:
- Radarr and Sonarr were trying to connect to Decypharr using the host port (8283)
- Docker containers must use internal container ports when communicating within the network
- Decypharr listens on port 8282 internally, mapped to 8283 on the host

Solution:
- Added DECYPHARR_CONTAINER_PORT=8282 to .env.defaults
- Updated configure_arr_service calls to use $DECYPHARR_CONTAINER_PORT (8282)
  instead of $DECYPHARR_PORT (8283)

This fixes the "Connection refused (decypharr:8283)" error when adding
Decypharr as download client to Radarr and Sonarr.
2025-10-22 23:15:07 +02:00
JaviPege
ffbed2eff0 fix: replace all hardcoded ports with env variables from .env.defaults
Replaced hardcoded ports throughout setup.sh:
- RADARR_PORT (7878 → $RADARR_PORT)
- SONARR_PORT (8989 → $SONARR_PORT)
- PROWLARR_PORT (9696 → $PROWLARR_PORT)
- TRAEFIK_DASHBOARD_PORT (8080 → $TRAEFIK_DASHBOARD_PORT)
- DECYPHARR_PORT (8282 → $DECYPHARR_PORT)

Updated calls to:
- wait_for_http_service()
- api_post_request()
- configure_arr_service()
- configure_arr_authentication()
- remove_default_profiles()
- add_arr_to_prowlarr()
- get_prowlarr_app_id()
- trigger_prowlarr_sync()

All ports now read from .env.defaults, making configuration truly dynamic.
2025-10-22 23:03:49 +02:00
JaviPege
104327610c fix: remove hardcoded ports from Prowlarr atomic functions
Changed get_prowlarr_app_id() and trigger_prowlarr_sync() to accept port as parameter:
- get_prowlarr_app_id(port, api_key, app_name, output_var)
- trigger_prowlarr_sync(port, api_key, app_id)

This makes functions truly reusable for any Prowlarr instance on any port.
Updated all call sites to pass port 9696 explicitly.
2025-10-22 23:01:10 +02:00
JaviPege
e4ac4827f2 refactor: complete refactoring lines 935-1570 with atomic functions (iteration 13)
Refactored remaining sections:
- Prowlarr indexers: Use api_post_request() for 4 indexers (saves repetitive curl calls)
- Prowlarr sync: Use get_prowlarr_app_id() + trigger_prowlarr_sync() (2 apps)
- Recyclarr: Use run_recyclarr_sync() (replaces 20+ lines of awk/docker run)
- Prowlarr auth: Use configure_arr_authentication()
- API keys save: Use append_to_file()
- Final restart: Use run_docker_compose_up()

Total refactoring summary (iterations 10-13):
- Created 13 atomic functions
- Reduced ~200 lines of repetitive code
- All functions called N times as designed
- Maintained 100% original behavior
- No new functions needed for this iteration
2025-10-22 22:58:45 +02:00
JaviPege
b3b608d90d refactor: use atomic functions for Docker startup and *arr authentication (iteration 12)
Refactored lines ~1214-1395:
- Use run_docker_compose_up() for Docker startup
- Use validate_docker_service() in loop for service validation
- Use get_docker_health_status() in loop for health checking
- Use wait_for_http_service() for HTTP service readiness
- Use wait_for_docker_health() for Decypharr
- Use configure_arr_authentication() for Radarr/Sonarr auth (replaces 60+ lines)

Removed inline wait_for_service() function (now using wait_for_http_service).
All functions called N times as designed. No new functions created.
2025-10-22 22:56:54 +02:00
JaviPege
bebb11a05d refactor: add 10 atomic functions for API/healthcheck/recyclarr (iteration 11)
Added atomic functions (4-13):
- wait_for_http_service(name, url, max_attempts, sleep_sec): Wait for HTTP service
- wait_for_docker_health(container, max_attempts, sleep_sec): Wait for healthy container
- api_get_request(url, api_key, output_var): Generic GET with API key
- api_put_request(url, api_key, json_data): Generic PUT with HTTP code validation
- api_post_request(url, api_key, json_data): Generic POST request
- configure_arr_authentication(service, port, api_key, user, pass): Configure *arr auth
- get_prowlarr_app_id(api_key, app_name, output_var): Get Prowlarr app ID
- trigger_prowlarr_sync(api_key, app_id): Trigger sync to ONE app
- run_recyclarr_sync(config_file, radarr_key, sonarr_key): Run recyclarr with injected keys
- append_to_file(file_path, content): Append to file

All functions are atomic and designed to be called N times.
Next: Refactor lines 935-1401 using these atomic functions.
2025-10-22 22:53:48 +02:00
JaviPege
5bf229bb4f refactor: add 3 atomic Docker functions (iteration 10)
Added atomic functions for Docker operations:
- run_docker_compose_up(compose_dir): Execute docker compose with validation
- validate_docker_service(service_name): Check if ONE service is running (call N times)
- get_docker_health_status(container_name, output_var): Get health status of ONE container

These functions will be used to refactor lines 935-1401 (service startup and configuration).
Next: Create remaining 10 atomic functions for API operations, healthchecks, and Prowlarr.
2025-10-22 22:49:23 +02:00
JaviPege
b55bd06bb5 refactor: convert healthcheck creation and cleanup prompt to atomic functions
- Use create_file_from_content() for healthcheck test file
- Use create_folder() for healthcheck directory
- Convert cleanup prompt to ask_user_input()
- No new functions created, only reused existing validated functions
2025-10-22 22:43:59 +02:00
JaviPege
705b0dca3a refactor: Convert healthcheck and autoconfig prompts to use atomic functions
- Replaced mount healthcheck prompt with ask_user_input()
- Replaced cron job prompt with ask_user_input()
- Replaced auto-configuration prompt with ask_user_input()
- Used copy_file() for healthcheck script installation
- Used create_folder() for logs directory
- Used copy_file() for .env.local generation
- All prompts and file operations now use atomic functions

Eighth iteration - healthcheck and phase 4 prompts.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 22:38:41 +02:00
JaviPege
253c37e52d refactor: Add create_file_from_content and refactor Zurg/Decypharr config
- Created create_file_from_content(dest, content, owner, perms) - atomic function
- Replaced Zurg config.yml creation with create_file_from_content()
- Replaced Decypharr config.json creation with create_file_from_content()
- Replaced Decypharr auth.json and torrents.json with create_file_from_content()
- Used create_folder() for Decypharr subdirectories
- All config file creation now uses atomic, reusable functions

Seventh iteration - config file creation atomic functions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 22:37:06 +02:00
JaviPege
a7405790ee refactor: Add atomic file operations functions (set_permissions, copy_file, download_file)
- Created set_permissions(path, perms, owner) - reusable for any path
- Created copy_file(source, dest, owner, perms) - reusable for file copying
- Created download_file(url, dest, owner, perms) - reusable for downloads
- Replaced permission setting with multiple set_permissions() calls
- Replaced recyclarr/rclone file copies with copy_file()
- Replaced indexer downloads with download_file()
- All functions are 100% atomic and reusable

Sixth iteration - file operations atomic functions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 22:30:46 +02:00
JaviPege
bf620dfc19 fix: Restore original docker-compose.yml with all services
Restored docker-compose.yml from main branch to maintain full functionality
while we continue step-by-step refactoring. The file was previously modified
by compose-generator.sh which caused service validation to fail.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 22:20:53 +02:00
JaviPege
101b103a53 refactor: Add atomic create_folder function and show_installation_summary
- Created create_folder(path, owner, permissions) - fully reusable atomic function
- Created show_installation_summary() - displays configuration summary
- Replaced PHASE 2 summary section with show_installation_summary()
- Used ask_user_input() for installation confirmation
- Replaced directory creation with multiple create_folder() calls (15 calls total)
- Each folder creation is now atomic and reusable

Fifth iteration - proper atomic functions approach.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 22:06:48 +02:00
JaviPege
7a3b51b27c fix: Remove extra blank line after password in authentication flow
Removed duplicate echo at end of ask_password and reorganized blank lines
in authentication section to prevent double spacing between prompts.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 21:59:51 +02:00
JaviPege
d58456f3fa refactor: Add atomic UID/GID conflict checking and env file creation
- Created check_uid_conflict() to verify and assign available UIDs
- Created check_gid_conflict() to verify and assign available GIDs
- Created create_env_install() to generate .env.install file
- Refactored UID/GID checking to iterate over users using atomic functions
- Simplified conflict detection logic with reusable components

Fourth iteration - atomic function composition for user management.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 21:57:26 +02:00
JaviPege
bb770acf43 fix: Add blank line after password input in ask_password
Ensures consistent spacing after password prompt, matching ask_user_input behavior.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 21:53:34 +02:00
JaviPege
c05d21521c fix: Skip title/separator in ask_user_input when title is empty
Prevents extra blank lines and separators when using ask_user_input
with empty title for follow-up prompts (like username after auth choice).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 21:53:21 +02:00
JaviPege
3f44183f68 refactor: Add ask_password() and convert auth/traefik sections using atomic functions
- Created ask_password() reusable function for hidden password input
- Converted Service Authentication using: ask_user_input + ask_password
- Converted Traefik configuration using: ask_user_input (with conditional domain)
- All functions are reusable atomic components

Third iteration - atomic function composition approach.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 21:48:02 +02:00
JaviPege
14305c8f21 refactor: Convert timezone, Real-Debrid token, and Plex claim prompts to ask_user_input
- Replaced Timezone Configuration with ask_user_input()
- Replaced Real-Debrid API Token with ask_user_input() (required=true)
- Replaced Plex Claim Token with ask_user_input() (optional)

Second iteration - step by step validation approach.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 21:42:04 +02:00
JaviPege
25ee0eb31e refactor: Add atomic functions (check_root, check_existing_config, ask_user_input)
- Created check_root() function for root verification
- Created check_existing_config() for .env.install detection
- Created ask_user_input() as standard method for user prompts
- Replaced Installation Directory prompt with ask_user_input()

First iteration of modular refactoring - rest of code remains unchanged.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 21:40:00 +02:00
JaviPege
afc6309fda Add sleep action and 10s delay after Decypharr healthcheck
Added sleep action to setup-executor.sh to allow waiting for services
to fully initialize after Docker healthcheck passes. Applied 10s delay
after Decypharr healthcheck in both radarr.json and sonarr.json to
ensure qBittorrent API on port 8283 is fully ready before attempting
to add download client.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 19:50:37 +02:00
JaviPege
f478781643 fix: Revert to simple healthcheck (matching original setup.sh)
Reverted complex curl-based checks back to original logic.

Original setup.sh ONLY checks Docker healthcheck:
- docker inspect -f '{{.State.Health.Status}}'
- Waits until status = 'healthy'
- No additional HTTP verification needed

Previous attempts with curl were over-engineering.
Decypharr healthcheck is sufficient - it validates qBittorrent API is ready.

Matches original working behavior from main branch.
2025-10-22 19:44:41 +02:00
JaviPege
0e507be7ca fix: Pre-pull curlimages/curl to avoid wait_for_service hangs
Problem:
- docker run curlimages/curl hangs on first execution
- Image download happens during wait loop
- Can exceed timeout or hang indefinitely

Solution:
- Check if curlimages/curl already present
- Pre-pull image BEFORE entering wait loop
- Subsequent docker run commands are instant
- Prevents timeout issues during service waits
2025-10-22 19:38:15 +02:00
JaviPege
34891a3a3e fix: Increase Decypharr wait timeout to 120s
- 60s timeout insufficient for first run
- curlimages/curl image needs to download (adds ~20-30s)
- Decypharr qBittorrent needs time to start
- 120s provides adequate buffer for both

Affects radarr.json and sonarr.json
2025-10-22 19:31:16 +02:00
JaviPege
e0628b2e7c fix: Test port accessibility from Docker network, not host
CRITICAL: Previous curl test ran on HOST, not in Docker network

Problem:
- wait_for_service curl ran on ubuntu host
- Reported port 8283 accessible from host perspective
- But Radarr connects from INSIDE Docker network (mediacenter)
- Port may be accessible from host but NOT from Docker network

Solution:
- Use 'docker run --rm --network mediacenter curlimages/curl'
- This spawns ephemeral container in same network as services
- Tests connectivity exactly as Radarr/Sonarr will experience it
- Only reports ready when port accessible from Docker network perspective

This ensures wait_for_service validates the actual network path services use.
2025-10-22 19:27:38 +02:00
JaviPege
9b785d3271 fix: Add HTTP port verification in wait_for_service
CRITICAL FIX: Docker healthy != port accessible

Problem:
- wait_for_service only checked Docker healthcheck status
- Decypharr healthcheck passes before qBittorrent API port 8283 is ready
- Resulted in 'Connection refused' when trying to add download client

Solution:
- After container reports healthy, verify port with curl request
- curl -sf checks if HTTP port actually responds
- 2 second connect timeout to fail fast
- Only returns success when BOTH healthy AND port accessible

This ensures services are truly ready before attempting API configuration.
2025-10-22 19:15:49 +02:00
JaviPege
170dfd1354 fix: Add wait_for_service for Decypharr before connecting
- Decypharr was not fully ready when radarr/sonarr tried to connect
- Added wait_for_service step before add_download_client in both services
- This ensures Decypharr port 8283 is accessible before connection attempt
- Fixes HTTP 400 'Connection refused (decypharr:8283)' error
2025-10-22 19:02:57 +02:00
JaviPege
aec0fe4aa3 fix: Replace ((i++)) with i=$((i + 1)) to avoid set -e issues
CRITICAL FIX: ((i++)) causes script termination with set -e

Problem:
- Bash arithmetic ((...)) returns the result of the expression
- ((i++)) increments i from 0 to 1 and returns 1 (the NEW value)
- With 'set -e', any command returning non-zero terminates the script
- This caused setup-executor to exit after first step completion

Solution:
- Use i=$((i + 1)) instead of ((i++))
- This always returns exit code 0
- Script can continue to subsequent steps

This was the final blocker preventing auto-configuration from working.
2025-10-22 18:56:55 +02:00
JaviPege
d55f0d111d fix: Redirect all logging output to stderr
CRITICAL FIX: All log functions now write to stderr (>&2) instead of stdout.

Problem:
- When using command substitution like $(extract_api_key service)
- Log messages from extract_api_key were captured along with the API key
- This caused the variable to contain logs + API key instead of just API key
- Subsequent commands failed silently with 'set -e'

Solution:
- Redirect all echo output in log functions to stderr
- Only actual return values (via echo without >&2) go to stdout
- This allows clean command substitution without interference from logs

Affects: log_info, log_success, log_warning, log_error, log_debug, log_section, log_operation
2025-10-22 18:53:58 +02:00
JaviPege
9b3a99c25a fix: Define ROOT_DIR in setup-executor.sh
- setup-executor.sh was failing silently when ROOT_DIR was undefined
- ROOT_DIR is used in recyclarr configuration but was never initialized
- Now defaults to /mediacenter if not set via environment variable
- Allows setup-executor.sh to run both from setup.sh and standalone
2025-10-22 18:46:06 +02:00
JaviPege
042a785bf6 fix: Preserve SETUP_LOG_DIR across script invocations
- Prevents setup-executor.sh from creating a new log directory
- Only initializes SETUP_LOG_DIR if not already set
- Allows parent script (setup.sh) log directory to be inherited
- Fixes 'No such file or directory' error in setup-executor.sh
2025-10-22 18:42:47 +02:00
JaviPege
f8fd005041 fix: Quote SELECTED_TEMPLATES in .env.install to handle spaces
Fixes error when writing templates with slashes to .env.install.
Without quotes, 'core mediaplayers/plex extras/overseerr' was treated
as a command instead of a string value.
2025-10-22 18:24:38 +02:00
JaviPege
9c2a253945 feat: Integrate template system into setup.sh - MAJOR REFACTOR
Fully integrated the modular template system into setup.sh, reducing code
from 1426 to 1076 lines (-350 lines, -25% code).

**PHASE 1 - Configuration (Lines 170-198):**
- Added interactive template selector
- Default: core + plex + overseerr
- Custom: User selects media server and optional services
- Validates dependencies automatically
- Saves SELECTED_TEMPLATES to .env.install

**PHASE 2 - Summary (Lines 369-379):**
- Displays selected templates with descriptions
- Shows what will be installed before proceeding

**PHASE 3 - Installation (Lines 460-512):**
- Generates docker-compose.yml dynamically from templates
- Creates config directories based on selected services only
- Sets permissions dynamically for selected services only
- No more hardcoded service lists

**PHASE 4 - Auto-Configuration (Lines 889-917):**
- REPLACED ~350 lines of manual configuration code
- Single call to setup-executor.sh with selected templates
- setup-executor reads service JSONs and executes steps
- Automatic: API key extraction, root folders, download clients,
  indexers, Prowlarr sync, Recyclarr, etc.

**Service Validation (Lines 807-820):**
- Dynamic service list from selected templates
- Filters out setup-only services (recyclarr, networks, volumes)
- No more hardcoded EXPECTED_SERVICES array

**Helper Scripts Created:**
- scripts/get-services-list.sh: Extracts service names from templates
- scripts/get-config-dirs.sh: Returns services needing config dirs

**Benefits:**
 Modular: Users choose exactly what to install
 Maintainable: Add services = create JSON, no setup.sh changes
 Scalable: Easy to add new templates/services
 Less code: -350 lines (-25%)
 Dependencies: Automatically validated (e.g., Overseerr requires Plex)

**Testing:**
- Validates templates exist
- Checks JSON syntax
- Helper scripts tested with multiple template combinations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 18:15:46 +02:00
JaviPege
64820aeead feat: Add template selector with dependency validation
Created comprehensive template configuration system with dependency management:

**Template Configuration Files:**
- Created template.conf for all extras (8 total)
- Dependencies properly configured:
  * Plex-dependent: overseerr, tautulli, plextraktsync
  * Standalone: homarr, traefik, dashdot, pinchflat, watchtower

**Template Selector Script:**
- scripts/template-selector.sh: Interactive template selection
- Validates dependencies automatically
- Filters available options based on media server choice
- Shows proper descriptions from template.conf
- Returns space-separated list of templates

**Key Features:**
- Media server selection (Plex or None)
- Dynamic extras filtering based on dependencies
- If Plex not selected: Hides Overseerr, Tautulli, PlexTraktSync
- If Plex selected: Shows all compatible extras
- Summary confirmation before proceeding

**Testing:**
✓ With Plex: Shows 8 optional services
✓ Without Plex: Shows only 5 standalone services
✓ Dependency validation works correctly
✓ Output format correct for compose-generator

**Files Added:**
- scripts/template-selector.sh (executable)
- 8x templates/extras/*/template.conf
- 4x templates/extras/*/services.list

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 18:07:31 +02:00
JaviPege
6b68c98201 feat: Complete per-service JSON configuration system
Completed the modular template system with per-service JSON configurations:

**Service JSON Files Created (13 total):**
- Core services: radarr, sonarr, prowlarr, zilean, decypharr, autoscan
- Setup-only: recyclarr (TRaSH Guide quality profiles)
- Optional services: plex, overseerr, tautulli, homarr, traefik, traefik-socket-proxy

**Key Features:**
- Each service has its own JSON defining setup steps
- services.list defines installation order (service names, not yml files)
- compose-generator maps service names to .yml files dynamically
- Supports setup-only services (recyclarr) with null compose_file
- Quality profile management: deletes defaults, then runs recyclarr

**Updated Components:**
- scripts/compose-generator.sh: Handles null compose_file, maps service names
- scripts/setup-executor.sh: execute_service_setup() for per-service execution
- All services.list files: Changed from .yml references to service names

**Setup Actions:**
- wait_for_service, extract_api_key, add_root_folder
- add_download_client, add_arr_to_prowlarr, add_indexer_to_prowlarr
- delete_default_quality_profiles, run_recyclarr
- log_info, log_success, log_warning

**Testing:**
✓ compose-generator: Generates docker-compose.yml correctly
✓ All JSON files validated with jq
✓ Successfully tested with core + mediaplayers/plex + extras

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 18:00:44 +02:00
JaviPege
fedcc1a6c8 Add JSON-based dynamic setup configuration system
**New System:**
- Declarative JSON configuration for template setup steps
- Dynamic execution engine that reads JSON and calls functions
- Centralized action reference documentation

**Components:**

1. **setup-executor.sh**
   - Parses setup.json files
   - Executes actions dynamically
   - Manages runtime variables (API keys, etc)
   - Supports 10+ configuration actions

2. **setup.json files per template**
   - core: 16 configuration steps
   - mediaplayers/plex: Simple service wait + info
   - extras/overseerr: Info display with API keys

3. **SETUP-ACTIONS.md**
   - Complete reference for all available actions
   - Parameter documentation
   - Usage examples for each action

**Supported Actions:**
- wait_for_service: Wait for service health
- extract_api_key: Extract and store API keys
- add_root_folder: Configure media folders
- add_download_client: Add download clients
- add_indexer_to_prowlarr: Add indexers
- add_arr_to_prowlarr: Connect *arr to Prowlarr
- delete_default_quality_profiles: Remove default profiles
- run_recyclarr: Create TRaSH Guide profiles
- log_info/success/warning: Display messages

**Benefits:**
- No hardcoded setup scripts per template
- Easy to add new templates - just create setup.json
- Reusable actions across all templates
- Variable expansion support (${RADARR_API_KEY}, etc)
- Maintainable: Change function signature once, works everywhere

**Example Usage:**
```bash
# Execute setup for core template
./scripts/setup-executor.sh core

# Execute multiple templates
./scripts/setup-executor.sh core mediaplayers/plex extras/overseerr
```

**JSON Format:**
```json
{
  "name": "template-name",
  "description": "Template description",
  "steps": [
    {
      "action": "wait_for_service",
      "description": "Human-readable description",
      "params": {
        "service": "radarr",
        "port": 7878
      }
    }
  ]
}
```

**Next Steps:**
- Integrate setup-executor.sh into main setup.sh
- Add more optional templates with setup.json
- Create interactive template selector

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 17:50:46 +02:00
JaviPege
65596c2a10 Add modular template system for service deployment
**New Features:**
- Template-based deployment system for modular stack configuration
- Automatic dependency resolution
- Dynamic docker-compose.yml generation

**Template Structure:**
```
templates/
├── core/                 # Required base stack (*arr + dependencies)
├── mediaplayers/         # Media server options (plex, jellyfin)
└── extras/               # Optional services (overseerr, tautulli, etc)
```

**Templates Created:**
- core: Minimal *arr stack (11 services)
  - Infrastructure, Zurg, Rclone, Radarr, Sonarr, Prowlarr, Zilean, Decypharr, Autoscan
- mediaplayers/plex: Plex Media Server
- extras/overseerr: Request management (depends on plex)
- extras/tautulli: Plex analytics
- extras/homarr: Dashboard
- extras/traefik: Reverse proxy with HTTPS

**Compose Generator (compose-generator.sh):**
- Reads template metadata and dependencies
- Resolves dependency tree automatically
- Merges services.list files in correct order
- Generates categorized docker-compose.yml with comments
- Prevents duplicate service includes

**Usage:**
```bash
# Core only
./scripts/compose-generator.sh core

# Plex + Overseerr (auto-includes core dependency)
./scripts/compose-generator.sh mediaplayers/plex extras/overseerr

# Full stack
./scripts/compose-generator.sh core mediaplayers/plex extras/overseerr extras/tautulli extras/homarr
```

**Template Configuration:**
Each template contains:
- template.conf: Metadata (name, description, dependencies, category)
- services.list: Docker Compose service files to include
- setup.sh (future): Post-deployment configuration script

**Next Steps:**
- Integrate with setup.sh to prompt user for template selection
- Create setup.sh scripts for each template
- Add more optional templates (dashdot, pinchflat, watchtower, etc)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 17:43:25 +02:00