- Add traefik.docker.network=traefik-network label to homepage service - Prevent Traefik from using wrong IP from homelab-network - Resolve 504 Gateway Timeout issues after authentication - Update various docker-compose configurations and templates - Clean up unused configuration files
10 KiB
EZ-Homelab Script Audit Report
Generated: 30 January 2026
Executive Summary
The ez-homelab.sh script is a comprehensive Bash-based deployment tool for the EZ-Homelab project. It handles system setup, Docker configuration, and multi-stage service deployment. The script supports three main deployment modes with varying complexity. While functional for infrastructure-only deployments (Option 3), the core-only deployment (Option 2) has critical issues with Authelia secret generation and configuration that prevent successful deployment.
Script Architecture
Global Variables & Constants
- Color codes: RED, GREEN, YELLOW, BLUE, NC for console output formatting
- Logging functions:
log_info(),log_success(),log_warning(),log_error() - Deployment flags: DEPLOY_CORE, DEPLOY_INFRASTRUCTURE, DEPLOY_DASHBOARDS, SETUP_STACKS
- Configuration variables: DOMAIN, SERVER_IP, ADMIN_USER, etc.
- Path variables: SCRIPT_DIR, REPO_DIR, ACTUAL_USER
Core Functions
1. replace_env_placeholders()
Purpose: Replaces ${VAR} placeholders in files with actual environment variable values
Process:
- Takes file path as argument
- Uses
grepto find all${VAR}patterns - Checks if each variable exists in environment
- Uses
sedfor replacement:s|\${VAR}|${!VAR}|g - Accumulates missing variables in
MISSING_VARS_SUMMARYIssues: - Only reports missing variables at end, doesn't fail deployment
- No validation of replacement success
2. generate_shared_ca()
Purpose: Creates shared Certificate Authority for multi-server TLS Process:
- Creates
/opt/stacks/core/shared-ca/directory - Generates 4096-bit RSA CA key and certificate (365 days validity)
- Sets ownership to
$ACTUAL_USER:$ACTUAL_USEROutput: ca.pem, ca-key.pem files
3. setup_multi_server_tls()
Purpose: Configures TLS for remote Docker access using shared CA Process:
- Prompts for core server IP if not set
- Tests SSH connectivity (key auth first, then password)
- Fetches CA certificates from core server via SCP
- Calls
setup_docker_tls()if successful Issues: - Complex SSH authentication logic
- No fallback if CA fetch fails
- TLS_ISSUES_SUMMARY populated but not always accurate
4. load_env_file()
Purpose: Loads existing configuration from .env file
Process:
- Checks for
$REPO_DIR/.envexistence - Sources the file if found
- Displays current configuration values
- Returns 0 if file exists, 1 if not Issues: No validation of loaded values
5. save_env_file()
Purpose: Persists configuration to .env file
Process:
- Creates
.envfrom.env.exampleif needed - Updates values using
sedreplacements - For core deployment: generates Authelia secrets and password hash Critical Issue: Authelia secret generation is here, but may not be called in all deployment paths
6. prompt_for_values()
Purpose: Interactive configuration collection Process:
- Shows current/default values
- Allows user to accept defaults or enter custom values
- Handles sensitive inputs (passwords) with
-sflag - Sets ADMIN_* variables for core deployment Issues: Complex logic with many conditional branches
7. system_setup()
Purpose: Performs initial system configuration (requires root) Process:
- System package updates
- Installs prerequisites (curl, wget, git, etc.)
- Installs/configures Docker and Docker Compose
- Generates shared CA
- Configures Docker TLS
- Sets up UFW firewall
- Configures automatic updates
- Creates Docker networks
- Sets directory ownership Issues:
- Requires logout/login for Docker group changes
- No rollback on failure
8. deploy_dockge()
Purpose: Deploys Dockge stack management interface Process:
- Copies compose file and .env to
/opt/dockge/ - Replaces placeholders
- Runs
docker compose up -dOutput: Dockge service running
9. deploy_core()
Purpose: Deploys core infrastructure stack Process:
- Copies compose file and .env to
/opt/stacks/core/ - Copies Traefik and Authelia config templates
- Replaces placeholders in all config files
- Generates shared CA
- Replaces Authelia-specific secrets and user data
- Runs
docker compose up -dCritical Issues:
- Assumes Authelia secrets exist in environment
- No validation that secrets were generated
- Complex placeholder replacement logic
10. deploy_infrastructure() / deploy_dashboards()
Purpose: Deploy additional service stacks Process: Similar to deploy_core but simpler
- Copy files, replace placeholders, deploy Issues: Conditional Authelia middleware removal when core not deployed
11. setup_docker_tls()
Purpose: Configures Docker daemon for TLS Process:
- Creates TLS directory
- Uses shared CA or generates local CA
- Generates server and client certificates
- Updates Docker daemon.json
- Modifies systemd service for TCP 2376
- Restarts Docker service
12. setup_stacks_for_dockge()
Purpose: Prepares all service stacks for Dockge management Process:
- Iterates through predefined stack list
- Copies compose files and configs
- Replaces placeholders
- Prepares but doesn't deploy stacks
Deployment Flow Analysis
Option 1: Default Setup
Flags: DEPLOY_CORE=true, DEPLOY_INFRASTRUCTURE=true, DEPLOY_DASHBOARDS=true, SETUP_STACKS=true Flow:
- System setup (if needed)
- Prompt for values
- Save env file (generates Authelia secrets)
- Deploy Dockge
- Deploy core (uses generated secrets)
- Deploy infrastructure
- Deploy dashboards
- Setup stacks for Dockge
Option 2: Core Only
Flags: DEPLOY_CORE=true, DEPLOY_INFRASTRUCTURE=false, DEPLOY_DASHBOARDS=true, SETUP_STACKS=true Flow:
- System setup (if needed)
- Prompt for values
- Save env file (generates Authelia secrets)
- Deploy Dockge
- Deploy core (uses generated secrets)
- Deploy dashboards
- Setup stacks for Dockge
Option 3: Infrastructure Only
Flags: DEPLOY_CORE=false, DEPLOY_INFRASTRUCTURE=true, DEPLOY_DASHBOARDS=false, SETUP_STACKS=true Flow:
- System setup (if needed)
- Prompt for values
- Save env file (no Authelia secrets generated)
- Setup multi-server TLS
- Deploy Dockge
- Deploy infrastructure
- Setup stacks for Dockge
Critical Issues Identified
1. Authelia Secret Generation Timing (Option 2)
Problem: In Option 2, save_env_file() is called and should generate Authelia secrets, but the deployment may fail if secrets aren't properly set.
Root Cause: The save_env_file() function generates secrets only when DEPLOY_CORE=true, but the generation logic may not execute or persist correctly.
Impact: Authelia container fails to start due to missing JWT_SECRET, SESSION_SECRET, or STORAGE_ENCRYPTION_KEY
2. Environment Variable Persistence
Problem: After save_env_file(), the script sources the .env file, but there may be a timing issue where variables aren't available for deploy_core().
Evidence: The script does source "$REPO_DIR/.env" in perform_deployment(), but if secrets weren't saved properly, they'll be empty.
3. Placeholder Replacement Order
Problem: replace_env_placeholders() is called during deployment, but if environment variables are missing, replacements fail silently.
Impact: Configuration files contain literal ${VAR} strings instead of actual values.
4. Authelia Password Hash Generation
Problem: Password hash generation happens in save_env_file(), but requires Docker to be running and Authelia image to be available.
Issues:
- May fail if Docker isn't ready
- Uses complex docker run command that could timeout
- No fallback if hash generation fails
5. Multi-Server TLS Complexity
Problem: setup_multi_server_tls() has complex SSH logic that can fail in multiple ways.
Issues:
- SSH key vs password detection unreliable
- No retry logic for connection failures
- Error reporting doesn't clearly indicate resolution steps
6. Directory Creation Race Conditions
Problem: Script creates directories with sudo, then tries to write files as regular user. Potential Issue: Permission conflicts if ownership isn't set correctly.
Recommendations
Immediate Fixes for Option 2
-
Add Secret Validation: After
save_env_file(), validate that all required Authelia secrets exist before proceeding with deployment. -
Improve Error Handling: Make
replace_env_placeholders()fail deployment if critical variables are missing. -
Add Authelia Health Check: After core deployment, verify Authelia container is running and healthy.
Structural Improvements
-
Separate Secret Generation: Move Authelia secret generation to a dedicated function called before deployment.
-
Add Pre-deployment Validation: Create a validation function that checks all required environment variables and Docker state before starting deployment.
-
Simplify TLS Setup: Reduce complexity in multi-server TLS setup with better error handling and user guidance.
-
Add Rollback Capability: Implement cleanup functions for failed deployments.
Code Quality
-
Reduce Function Complexity: Break down large functions like
deploy_core()into smaller, testable units. -
Add Logging: Increase verbosity for debugging deployment issues.
-
Configuration Management: Consider using a configuration file format (YAML/JSON) instead of .env for complex setups.
Testing Recommendations
-
Unit Test Functions: Test individual functions like
replace_env_placeholders()andgenerate_shared_ca()in isolation. -
Integration Testing: Test each deployment option in a clean environment.
-
Error Scenario Testing: Test failure modes (missing Docker, network issues, invalid credentials).
Conclusion
The ez-homelab.sh script is a solid foundation for automated homelab deployment, but Option 2 (Core Only) has critical issues with Authelia secret management that prevent reliable deployment. The script needs focused improvements in error handling, validation, and secret generation to achieve the reliability required for critical infrastructure deployment.