From 12baa5cdf3dcd9749c808e59a0e3815bd01e872e Mon Sep 17 00:00:00 2001 From: EZ-Homelab Date: Thu, 22 Jan 2026 16:08:39 -0500 Subject: [PATCH] Fix EZ-Homelab scripts for successful fresh installs - Fix Authelia config template paths (/data/ -> /config/) - Add secret placeholder replacement in deploy script - Add user database placeholder replacement - Add automatic dashboard stack deployment (Homepage, Homarr) - Remove incorrect Portainer reference from infrastructure log - Update deployment steps and final summary --- config-templates/authelia/configuration.yml | 4 +- scripts/deploy-homelab.sh | 81 +++++++-- scripts/setup-homelab.sh | 173 +++++++++++++++++--- 3 files changed, 222 insertions(+), 36 deletions(-) diff --git a/config-templates/authelia/configuration.yml b/config-templates/authelia/configuration.yml index 717022b..9b7912b 100644 --- a/config-templates/authelia/configuration.yml +++ b/config-templates/authelia/configuration.yml @@ -73,9 +73,9 @@ regulation: storage: encryption_key: ${AUTHELIA_STORAGE_ENCRYPTION_KEY} local: - path: /data/db.sqlite3 + path: /config/db.sqlite3 notifier: # File-based notifications (for development/testing) filesystem: - filename: /data/notification.txt + filename: /config/notification.txt diff --git a/scripts/deploy-homelab.sh b/scripts/deploy-homelab.sh index 248e617..aa0f25b 100755 --- a/scripts/deploy-homelab.sh +++ b/scripts/deploy-homelab.sh @@ -127,6 +127,20 @@ if [ -d "/opt/stacks/core/authelia" ]; then fi cp -r "$REPO_DIR/config-templates/authelia" /opt/stacks/core/ +# Replace domain placeholders in Authelia config +sed -i "s/your-domain.duckdns.org/${DOMAIN}/g" /opt/stacks/core/authelia/configuration.yml + +# Replace secret placeholders in Authelia config +source /opt/stacks/core/.env +sed -i "s|\${AUTHELIA_JWT_SECRET}|${AUTHELIA_JWT_SECRET}|g" /opt/stacks/core/authelia/configuration.yml +sed -i "s|\${AUTHELIA_SESSION_SECRET}|${AUTHELIA_SESSION_SECRET}|g" /opt/stacks/core/authelia/configuration.yml +sed -i "s|\${AUTHELIA_STORAGE_ENCRYPTION_KEY}|${AUTHELIA_STORAGE_ENCRYPTION_KEY}|g" /opt/stacks/core/authelia/configuration.yml + +# Replace placeholders in Authelia users database +sed -i "s/admin/${AUTHELIA_ADMIN_USER}/g" /opt/stacks/core/authelia/users_database.yml +sed -i "s/admin@example.com/${AUTHELIA_ADMIN_EMAIL}/g" /opt/stacks/core/authelia/users_database.yml +sed -i "s|\$argon2id\$v=19\$m=65536,t=3,p=4\$CHANGEME|${AUTHELIA_ADMIN_PASSWORD}|g" /opt/stacks/core/authelia/users_database.yml + if [ -f "/opt/stacks/core/.env" ]; then log_warning ".env already exists in /opt/stacks/core/" log_info "Creating backup: .env.backup.$(date +%Y%m%d_%H%M%S)" @@ -156,7 +170,6 @@ echo "" # Step 4: Deploy infrastructure stack (Dockge and monitoring tools) log_info "Step 4/6: Deploying infrastructure stack..." log_info " - Dockge (Docker Compose Manager)" -log_info " - Portainer (Alternative Docker UI)" log_info " - Pi-hole (DNS Ad Blocker)" log_info " - Watchtower (Container Updates)" log_info " - Dozzle (Log Viewer)" @@ -175,8 +188,33 @@ docker compose up -d log_success "Infrastructure stack deployed" echo "" -# Step 5: Deploy Dokuwiki -log_info "Step 5/6: Deploying Dokuwiki wiki platform..." +# Step 5: Deploy dashboard stack +log_info "Step 5/7: Deploying dashboard stack..." +log_info " - Homepage (Application Dashboard)" +log_info " - Homarr (Modern Dashboard)" +echo "" + +# Create dashboards directory +mkdir -p /opt/stacks/dashboards + +# Copy dashboards compose file +cp "$REPO_DIR/docker-compose/dashboards/docker-compose.yml" /opt/stacks/dashboards/docker-compose.yml +cp "$REPO_DIR/.env" /opt/stacks/dashboards/.env + +# Copy homepage config +if [ -d "$REPO_DIR/docker-compose/dashboards/homepage" ]; then + cp -r "$REPO_DIR/docker-compose/dashboards/homepage" /opt/stacks/dashboards/ +fi + +# Deploy dashboards stack +cd /opt/stacks/dashboards +docker compose up -d + +log_success "Dashboard stack deployed" +echo "" + +# Step 6: Deploy Dokuwiki +log_info "Step 6/7: Deploying Dokuwiki wiki platform..." log_info " - DokuWiki (File-based wiki with pre-configured content)" echo "" @@ -187,9 +225,23 @@ mkdir -p /opt/stacks/dokuwiki/config cp "$REPO_DIR/config-templates/dokuwiki/docker-compose.yml" /opt/stacks/dokuwiki/docker-compose.yml # Copy pre-configured Dokuwiki config, content, and keys -cp -r "$REPO_DIR/config-templates/dokuwiki/conf" /opt/stacks/dokuwiki/config/ -cp -r "$REPO_DIR/config-templates/dokuwiki/data" /opt/stacks/dokuwiki/config/ -cp -r "$REPO_DIR/config-templates/dokuwiki/keys" /opt/stacks/dokuwiki/config/ +if [ -d "$REPO_DIR/config-templates/dokuwiki/conf" ]; then + cp -r "$REPO_DIR/config-templates/dokuwiki/conf" /opt/stacks/dokuwiki/config/ +else + log_warning "Dokuwiki conf directory not found, skipping..." +fi + +if [ -d "$REPO_DIR/config-templates/dokuwiki/data" ]; then + cp -r "$REPO_DIR/config-templates/dokuwiki/data" /opt/stacks/dokuwiki/config/ +else + log_warning "Dokuwiki data directory not found, skipping..." +fi + +if [ -d "$REPO_DIR/config-templates/dokuwiki/keys" ]; then + cp -r "$REPO_DIR/config-templates/dokuwiki/keys" /opt/stacks/dokuwiki/config/ +else + log_warning "Dokuwiki keys directory not found, skipping..." +fi # Set proper ownership for Dokuwiki config sudo chown -R 1000:1000 /opt/stacks/dokuwiki/config @@ -262,8 +314,10 @@ echo "" log_info "Access your services:" echo "" echo " 🚀 Dockge: $DOCKGE_URL" -echo " � Wiki: https://wiki.${DOMAIN}" -echo " �🔒 Authelia: https://auth.${DOMAIN}" +echo " 📊 Homepage: https://home.${DOMAIN}" +echo " 🎯 Homarr: https://homarr.${DOMAIN}" +echo " 📖 Wiki: https://wiki.${DOMAIN}" +echo " 🔒 Authelia: https://auth.${DOMAIN}" echo " 🔀 Traefik: https://traefik.${DOMAIN}" echo "" log_info "Next steps:" @@ -271,11 +325,14 @@ echo "" echo " 1. Log in to Dockge using your Authelia credentials" echo " (configured in /opt/stacks/core/authelia/users_database.yml)" echo "" -echo " 2. Access your pre-deployed Dokuwiki at https://wiki.${DOMAIN}" +echo " 2. Access your dashboards:" +echo " - Homepage: https://home.${DOMAIN} (AI-configurable dashboard)" +echo " - Homarr: https://homarr.${DOMAIN} (Modern dashboard)" +echo "" +echo " 3. Access your pre-deployed Dokuwiki at https://wiki.${DOMAIN}" echo " (admin/admin credentials)" echo "" -echo " 3. Deploy additional stacks through Dockge's web UI:" -echo " - dashboards.yml (Homepage, Homarr)" +echo " 4. Deploy additional stacks through Dockge's web UI:" echo " - media.yml (Plex, Jellyfin, Sonarr, Radarr, etc.)" echo " - media-extended.yml (Readarr, Lidarr, etc.)" echo " - homeassistant.yml (Home Assistant and accessories)" @@ -283,7 +340,7 @@ echo " - productivity.yml (Nextcloud, Gitea, additional wikis)" echo " - monitoring.yml (Grafana, Prometheus, etc.)" echo " - utilities.yml (Backups, code editors, etc.)" echo "" -echo " 3. Configure services via the AI assistant in VS Code" +echo " 5. Configure services via the AI assistant in VS Code" echo "" echo "==========================================" echo "" diff --git a/scripts/setup-homelab.sh b/scripts/setup-homelab.sh index a0113e1..815975c 100755 --- a/scripts/setup-homelab.sh +++ b/scripts/setup-homelab.sh @@ -36,23 +36,20 @@ if [ "$EUID" -ne 0 ]; then fi # Get the actual user who invoked sudo -ACTUAL_USER="${SUDO_USER:-$USER}" -if [ "$ACTUAL_USER" = "root" ]; then - log_error "Please run this script with sudo, not as root user" - exit 1 -fi +ACTUAL_USER=${SUDO_USER:-$USER} -log_info "Setting up AI-Homelab for user: $ACTUAL_USER" -echo "" +# Get script directory and repo directory +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +REPO_DIR="$( cd "$SCRIPT_DIR/.." && pwd )" # Step 1: System Update -log_info "Step 1/9: Updating system packages..." +log_info "Step 1/10: Updating system packages..." apt-get update && apt-get upgrade -y log_success "System updated successfully" echo "" # Step 2: Install Required Packages -log_info "Step 2/9: Installing required packages..." +log_info "Step 2/10: Installing required packages..." # Update package list first to avoid issues apt-get update @@ -80,7 +77,7 @@ log_success "Required packages installed" echo "" # Step 3: Install Docker -log_info "Step 3/9: Installing Docker..." +log_info "Step 3/10: Installing Docker..." if command -v docker &> /dev/null && docker --version &> /dev/null; then log_warning "Docker is already installed ($(docker --version))" else @@ -99,12 +96,16 @@ else apt-get update apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin - log_success "Docker installed successfully ($(docker --version))" + # Start and enable Docker service + systemctl start docker + systemctl enable docker + + log_success "Docker installed and service started ($(docker --version))" fi echo "" # Step 4: Configure User Groups -log_info "Step 4/9: Configuring user groups..." +log_info "Step 4/10: Configuring user groups..." # Add user to sudo group if not already if groups "$ACTUAL_USER" | grep -q '\bsudo\b'; then @@ -124,7 +125,7 @@ fi echo "" # Step 5: Configure Firewall -log_info "Step 5/9: Configuring firewall..." +log_info "Step 5/10: Configuring firewall..." # Enable UFW if not already enabled if ufw status | grep -q "Status: active"; then log_warning "Firewall is already active" @@ -148,7 +149,7 @@ log_success "HTTP/HTTPS ports allowed in firewall" echo "" # Step 6: Configure SSH -log_info "Step 6/9: Configuring SSH server..." +log_info "Step 6/10: Configuring SSH server..." systemctl enable ssh systemctl start ssh @@ -163,7 +164,7 @@ fi echo "" # Step 7: Detect and Install NVIDIA Drivers (if applicable) -log_info "Step 7/9: Checking for NVIDIA GPU..." +log_info "Step 7/10: Checking for NVIDIA GPU..." # Detect NVIDIA GPU if lspci | grep -i nvidia > /dev/null; then @@ -177,10 +178,17 @@ if lspci | grep -i nvidia > /dev/null; then NVIDIA_INSTALLED=true else log_info "Installing NVIDIA drivers..." + # Install kernel headers first (required for NVIDIA driver) + apt-get install -y linux-headers-amd64 # Install NVIDIA driver (non-interactive) - apt-get install -y nvidia-driver - log_success "NVIDIA drivers installed" - NVIDIA_INSTALLED=false + if apt-get install -y nvidia-driver; then + log_success "NVIDIA drivers installed" + NVIDIA_INSTALLED=false + else + log_warning "NVIDIA driver installation failed. You may need to install manually after reboot." + log_info "Try: sudo apt update && sudo apt install nvidia-driver" + NVIDIA_INSTALLED=false # Still set to false to trigger reboot reminder + fi fi # Check if NVIDIA Container Toolkit is installed @@ -214,7 +222,7 @@ else fi # Step 8: Create Directory Structure -log_info "Step 8/9: Creating directory structure..." +log_info "Step 8/10: Creating directory structure..." mkdir -p /opt/stacks mkdir -p /opt/dockge/data mkdir -p /mnt/media/{movies,tv,music,books,photos} @@ -251,7 +259,7 @@ log_success "Directory structure created" echo "" # Step 9: Create Docker Networks -log_info "Step 9/9: Creating Docker networks..." +log_info "Step 9/10: Creating Docker networks..." su - "$ACTUAL_USER" -c "docker network create homelab-network 2>/dev/null || true" su - "$ACTUAL_USER" -c "docker network create traefik-network 2>/dev/null || true" su - "$ACTUAL_USER" -c "docker network create media-network 2>/dev/null || true" @@ -259,6 +267,127 @@ su - "$ACTUAL_USER" -c "docker network create dockerproxy-network 2>/dev/null || log_success "Docker networks created" echo "" +# Step 10: Generate Authelia Secrets +log_info "Step 10/10: Generating Authelia secrets..." + +# Check if .env file exists, create from example if needed +if [ ! -f "$REPO_DIR/.env" ]; then + if [ -f "$REPO_DIR/.env.example" ]; then + cp "$REPO_DIR/.env.example" "$REPO_DIR/.env" + log_info ".env file created from .env.example" + else + log_error ".env and .env.example files not found in $REPO_DIR" + exit 1 + fi +fi + +# Generate cryptographic secrets +log_info "Generating Authelia JWT secret..." +AUTHELIA_JWT_SECRET=$(openssl rand -hex 64) + +log_info "Generating Authelia session secret..." +AUTHELIA_SESSION_SECRET=$(openssl rand -hex 64) + +log_info "Generating Authelia storage encryption key..." +AUTHELIA_STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 64) + +# Check for existing default credentials in .env +source "$REPO_DIR/.env" +USE_DEFAULTS=false +if [ -n "$DEFAULT_USER" ] && [ -n "$DEFAULT_PASSWORD" ] && [ -n "$DEFAULT_EMAIL" ]; then + echo "" + echo "Found existing default credentials in .env:" + echo " User: $DEFAULT_USER" + echo " Email: $DEFAULT_EMAIL" + echo " Password: [hidden]" + echo "" + read -p "Use these for Authelia admin? (Y/n): " USE_DEFAULT + USE_DEFAULT=${USE_DEFAULT:-y} + if [[ "$USE_DEFAULT" =~ ^[Yy]$ ]]; then + USE_DEFAULTS=true + ADMIN_USER=$DEFAULT_USER + ADMIN_EMAIL=$DEFAULT_EMAIL + ADMIN_PASSWORD=$DEFAULT_PASSWORD + fi +fi + +if [ "$USE_DEFAULTS" = false ]; then + # Prompt for admin credentials + log_info "Configuring Authelia admin user..." + echo "" + echo "Authelia Admin Configuration:" + echo "==============================" + + read -p "Admin username (default: admin): " ADMIN_USER + ADMIN_USER=${ADMIN_USER:-admin} + + read -p "Admin email: " ADMIN_EMAIL + while [ -z "$ADMIN_EMAIL" ]; do + log_error "Email is required" + read -p "Admin email: " ADMIN_EMAIL + done + + # Prompt for password with confirmation + while true; do + read -s -p "Admin password: " ADMIN_PASSWORD + echo "" + read -s -p "Confirm password: " ADMIN_PASSWORD_CONFIRM + echo "" + if [ "$ADMIN_PASSWORD" = "$ADMIN_PASSWORD_CONFIRM" ]; then + break + else + log_error "Passwords do not match. Please try again." + fi + done +fi + +# Generate password hash using Authelia Docker image +log_info "Generating password hash (this may take 30-60 seconds)..." + +# Check if Docker is running +if ! docker info > /dev/null 2>&1; then + log_error "Docker is not running. Please check Docker installation." + exit 1 +fi + +# Pull the Authelia image first +log_info "Pulling Authelia image..." +if ! docker pull authelia/authelia:latest > /dev/null 2>&1; then + log_error "Failed to pull Authelia image. Please check internet connectivity." + exit 1 +fi + +# Generate the hash +ADMIN_PASSWORD_HASH=$(docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password "$ADMIN_PASSWORD" 2>&1 | grep -o '"[^"]*"' | tr -d '"') + +if [ -z "$ADMIN_PASSWORD_HASH" ]; then + log_error "Failed to generate password hash. Please check Docker connectivity." + log_info "Debug: Trying manual hash generation..." + # Fallback: generate a basic hash using openssl (not recommended for production) + ADMIN_PASSWORD_HASH=$(echo -n "$ADMIN_PASSWORD" | openssl dgst -sha256 | cut -d' ' -f2) + if [ -n "$ADMIN_PASSWORD_HASH" ]; then + log_warning "Using fallback hash method. Please regenerate with proper Authelia hash later." + else + exit 1 + fi +fi + +# Update .env file with generated values +log_info "Updating .env file with generated secrets..." + +# Use sed to replace the placeholder values +sed -i "s/AUTHELIA_JWT_SECRET=.*/AUTHELIA_JWT_SECRET=$AUTHELIA_JWT_SECRET/" "$REPO_DIR/.env" +sed -i "s/AUTHELIA_SESSION_SECRET=.*/AUTHELIA_SESSION_SECRET=$AUTHELIA_SESSION_SECRET/" "$REPO_DIR/.env" +sed -i "s/AUTHELIA_STORAGE_ENCRYPTION_KEY=.*/AUTHELIA_STORAGE_ENCRYPTION_KEY=$AUTHELIA_STORAGE_ENCRYPTION_KEY/" "$REPO_DIR/.env" + +# Uncomment and set admin credentials +sed -i "s/# AUTHELIA_ADMIN_USER=.*/AUTHELIA_ADMIN_USER=$ADMIN_USER/" "$REPO_DIR/.env" +sed -i "s/# AUTHELIA_ADMIN_EMAIL=.*/AUTHELIA_ADMIN_EMAIL=$ADMIN_EMAIL/" "$REPO_DIR/.env" +sed -i "s/# AUTHELIA_ADMIN_PASSWORD=.*/AUTHELIA_ADMIN_PASSWORD=$ADMIN_PASSWORD_HASH/" "$REPO_DIR/.env" + +log_success "Authelia secrets and admin credentials generated" +echo "" + # Final Summary echo "" echo "==========================================" @@ -270,8 +399,8 @@ echo "" echo " 1. Log out and log back in for group changes to take effect" echo " (or run: newgrp docker)" echo "" -echo " 2. Navigate to your AI-Homelab repository:" -echo " cd ~/AI-Homelab" +echo " 2. Navigate to your EZ-Homelab repository:" +echo " cd ~/EZ-Homelab" echo "" echo " 3. Edit the .env file with your configuration:" echo " cp .env.example .env"