diff --git a/update-env.sh b/update-env.sh new file mode 100755 index 0000000..06aba1e --- /dev/null +++ b/update-env.sh @@ -0,0 +1,158 @@ +#!/bin/bash + +# env-update.sh - Update environment variables from .env.example to .env +# Preserves existing values while updating structure and highlighting changes +# Created: April 25, 2025 + +set -e + +# Color definitions +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +MAGENTA='\033[0;35m' +CYAN='\033[0;36m' +BOLD='\033[1m' +NC='\033[0m' # No Color + +# Files +ENV_FILE=".env" +ENV_EXAMPLE=".env.example" +TIMESTAMP=$(date +"%Y%m%d-%H%M%S") +ENV_BACKUP=".env.${TIMESTAMP}.bak" + +# Check if files exist +if [ ! -f "$ENV_FILE" ]; then + echo -e "${RED}Error: $ENV_FILE doesn't exist${NC}" + echo -e "Creating a new $ENV_FILE from $ENV_EXAMPLE" + cp "$ENV_EXAMPLE" "$ENV_FILE" + echo -e "${GREEN}Done! Please review and fill in required values in $ENV_FILE${NC}" + exit 0 +fi + +if [ ! -f "$ENV_EXAMPLE" ]; then + echo -e "${RED}Error: $ENV_EXAMPLE doesn't exist${NC}" + exit 1 +fi + +echo -e "${CYAN}${BOLD}Environment File Update Tool${NC}" +echo -e "${CYAN}============================${NC}" +echo -e "${BLUE}This will update your $ENV_FILE based on the structure in $ENV_EXAMPLE${NC}" +echo -e "${BLUE}Your existing values will be preserved where possible${NC}" +echo -e "${BLUE}Backup will be created as: $ENV_BACKUP${NC}" +echo -e "${YELLOW}Continue? [y/N]:${NC}" +read -r answer +if [[ ! "$answer" =~ ^[Yy]$ ]]; then + echo -e "${RED}Cancelled.${NC}" + exit 0 +fi + +# Create backup of current .env +echo -e "${BLUE}Creating backup of current $ENV_FILE as $ENV_BACKUP...${NC}" +cp "$ENV_FILE" "$ENV_BACKUP" + +# Store current env values +echo -e "${BLUE}Reading current environment values...${NC}" +declare -A current_values +while IFS='=' read -r key value; do + # Skip comments and empty lines + if [[ ! "$key" =~ ^#.*$ ]] && [[ ! -z "$key" ]]; then + # Clean up any comments after the value + value=$(echo "$value" | sed 's/[[:space:]]*#.*$//') + # Trim leading/trailing whitespace + key=$(echo "$key" | xargs) + value=$(echo "$value" | xargs) + # Store in associative array if key is not empty + if [[ ! -z "$key" ]]; then + current_values["$key"]="$value" + fi + fi +done < "$ENV_FILE" + +# Create new env file from example +echo -e "${BLUE}Creating new $ENV_FILE from $ENV_EXAMPLE...${NC}" +cp "$ENV_EXAMPLE" "$ENV_FILE.new" + +# Track which keys from the current env have been used +declare -A used_keys +# Track new keys that need attention +new_keys=() +# Track keys with special warnings +special_keys=() + +# Process the template and fill in values from current env +while IFS= read -r line; do + if [[ "$line" =~ ^([A-Za-z0-9_]+)=(.*)$ ]]; then + key="${BASH_REMATCH[1]}" + default_value="${BASH_REMATCH[2]}" + + # Check if this key exists in current values + if [[ -n "${current_values[$key]}" ]]; then + # Replace the line with the current value + sed -i "s|^$key=.*$|$key=${current_values[$key]}|" "$ENV_FILE.new" + used_keys["$key"]=1 + else + # Mark new keys that need attention (those without default values) + if [[ -z "$default_value" ]] || [[ "$default_value" == '""' ]] || [[ "$default_value" == "''" ]]; then + new_keys+=("$key") + fi + + # Special attention for Authelia keys + if [[ "$key" == AUTHELIA_* ]] && [[ -z "$default_value" ]]; then + special_keys+=("$key") + fi + fi + fi +done < "$ENV_FILE.new" + +# Create section for unused/deprecated keys at the bottom of the file +echo -e "\n\n# --- DEPRECATED OR UNUSED KEYS (Kept for Reference) ---" >> "$ENV_FILE.new" +echo -e "# Keys below were in your original .env but aren't in the current .env.example" >> "$ENV_FILE.new" +echo -e "# They may be deprecated or renamed. Review and remove if no longer needed\n" >> "$ENV_FILE.new" + +unused_keys_count=0 +for key in "${!current_values[@]}"; do + if [[ -z "${used_keys[$key]}" ]]; then + echo "$key=${current_values[$key]} # DEPRECATED/UNUSED - Review" >> "$ENV_FILE.new" + unused_keys_count=$((unused_keys_count + 1)) + fi +done + +# Replace the old file with the new one +mv "$ENV_FILE.new" "$ENV_FILE" + +# Generate summary +echo -e "\n${GREEN}${BOLD}Update Complete!${NC}" +echo -e "${BLUE}Summary:${NC}" +echo -e " - ${CYAN}Original config backed up to: $ENV_BACKUP${NC}" +echo -e " - ${CYAN}Updated .env structure to match .env.example${NC}" +echo -e " - ${CYAN}Preserved ${#used_keys[@]} existing values${NC}" + +if [[ $unused_keys_count -gt 0 ]]; then + echo -e " - ${YELLOW}Found $unused_keys_count deprecated/unused keys${NC}" + echo -e " ${YELLOW}These have been moved to the bottom of the file with warnings${NC}" +fi + +if [[ ${#new_keys[@]} -gt 0 ]]; then + echo -e "\n${YELLOW}${BOLD}NEW KEYS NEEDING ATTENTION:${NC}" + echo -e "${YELLOW}The following keys are new and may need values set:${NC}" + for key in "${new_keys[@]}"; do + echo -e " - ${MAGENTA}$key${NC}" + done +fi + +if [[ ${#special_keys[@]} -gt 0 ]]; then + echo -e "\n${RED}${BOLD}IMPORTANT SECURITY KEYS:${NC}" + echo -e "${RED}The following keys require secure values:${NC}" + for key in "${special_keys[@]}"; do + echo -e " - ${MAGENTA}$key${NC}" + + # Specific advice for Authelia keys + if [[ "$key" == AUTHELIA_*_SECRET* ]] || [[ "$key" == AUTHELIA_*_KEY* ]]; then + echo -e " ${CYAN}Generate with: ${GREEN}openssl rand -hex 32${NC}" + fi + done +fi + +echo -e "\n${BLUE}Review your updated $ENV_FILE file and adjust any values as needed.${NC}" \ No newline at end of file