Some checks failed
/ validate-docker-compose (push) Has been cancelled
- Removed outdated configuration files and scripts. - Introduced a new setup script to streamline environment and Authelia configuration updates. - Enhanced .gitignore to exclude unnecessary files. - Updated README to reflect new setup process and configuration details for Authelia v4.38+.
392 lines
16 KiB
Bash
392 lines
16 KiB
Bash
#!/bin/bash
|
|
|
|
# Combined update script for docker-compose-nas
|
|
# - Updates .env file from .env.example while preserving values
|
|
# - Updates Authelia configuration from example file
|
|
# - Configures services with correct paths and API keys
|
|
# Created: April 26, 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"
|
|
AUTHELIA_CONFIG="authelia/configuration.yml"
|
|
AUTHELIA_CONFIG_EXAMPLE="authelia/configuration.example.yml"
|
|
AUTHELIA_CONFIG_BACKUP="authelia/configuration.${TIMESTAMP}.bak"
|
|
|
|
# Print section header
|
|
print_header() {
|
|
echo -e "\n${CYAN}${BOLD}$1${NC}"
|
|
echo -e "${CYAN}$(printf '=%.0s' $(seq 1 ${#1}))${NC}"
|
|
}
|
|
|
|
# Check if a file exists
|
|
check_file() {
|
|
if [ ! -f "$1" ]; then
|
|
echo -e "${RED}Error: $1 doesn't exist${NC}"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# Function to create a backup
|
|
create_backup() {
|
|
echo -e "${BLUE}Creating backup of $1 as $2...${NC}"
|
|
cp "$1" "$2"
|
|
}
|
|
|
|
##################################################
|
|
# PART 1: Update .env file from .env.example
|
|
##################################################
|
|
|
|
update_env_file() {
|
|
print_header "Environment File Update Tool"
|
|
|
|
# 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}"
|
|
return 0
|
|
fi
|
|
|
|
if ! check_file "$ENV_EXAMPLE"; then
|
|
return 1
|
|
fi
|
|
|
|
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}Environment update cancelled.${NC}"
|
|
return 0
|
|
fi
|
|
|
|
# Create backup of current .env
|
|
create_backup "$ENV_FILE" "$ENV_BACKUP"
|
|
|
|
# Store current env values
|
|
echo -e "${BLUE}Reading current environment values...${NC}"
|
|
declare -A current_values
|
|
declare -A current_keys_present
|
|
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"
|
|
# Track that this key existed in original file, regardless of value
|
|
current_keys_present["$key"]=1
|
|
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]}"
|
|
|
|
# Mark the key as used if it exists in the original file
|
|
if [[ -n "${current_keys_present[$key]}" ]]; then
|
|
used_keys["$key"]=1
|
|
|
|
# Replace the line with the current value if one exists
|
|
if [[ -n "${current_values[$key]}" ]]; then
|
|
sed -i "s|^$key=.*$|$key=${current_values[$key]}|" "$ENV_FILE.new"
|
|
fi
|
|
# If key doesn't exist in original file and has empty/placeholder value
|
|
elif [[ -z "$default_value" ]] || [[ "$default_value" == '""' ]] || [[ "$default_value" == "''" ]]; then
|
|
new_keys+=("$key")
|
|
|
|
# Special attention for Authelia keys
|
|
if [[ "$key" == AUTHELIA_*_SECRET* ]] || [[ "$key" == AUTHELIA_*_KEY* ]]; 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}Environment 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}"
|
|
}
|
|
|
|
##################################################
|
|
# PART 2: Update Authelia configuration
|
|
##################################################
|
|
|
|
update_authelia_config() {
|
|
print_header "Authelia Configuration Update Tool"
|
|
|
|
# Check if files exist
|
|
if ! check_file "$AUTHELIA_CONFIG_EXAMPLE"; then
|
|
echo -e "${RED}Error: Example configuration file doesn't exist${NC}"
|
|
return 1
|
|
fi
|
|
|
|
# If config file doesn't exist, create it from example
|
|
if [ ! -f "$AUTHELIA_CONFIG" ]; then
|
|
echo -e "${YELLOW}Authelia configuration file doesn't exist, creating from example...${NC}"
|
|
cp "$AUTHELIA_CONFIG_EXAMPLE" "$AUTHELIA_CONFIG"
|
|
echo -e "${GREEN}Created new Authelia configuration file.${NC}"
|
|
return 0
|
|
fi
|
|
|
|
echo -e "${BLUE}This will update your Authelia configuration based on the example file${NC}"
|
|
echo -e "${BLUE}Backup will be created as: $AUTHELIA_CONFIG_BACKUP${NC}"
|
|
echo -e "${YELLOW}Continue? [y/N]:${NC}"
|
|
read -r answer
|
|
if [[ ! "$answer" =~ ^[Yy]$ ]]; then
|
|
echo -e "${RED}Authelia config update cancelled.${NC}"
|
|
return 0
|
|
fi
|
|
|
|
# Create backup of current config
|
|
create_backup "$AUTHELIA_CONFIG" "$AUTHELIA_CONFIG_BACKUP"
|
|
|
|
# Copy the example file over the current one
|
|
cp "$AUTHELIA_CONFIG_EXAMPLE" "$AUTHELIA_CONFIG"
|
|
|
|
# Get the tailnet domain from .env for proper configuration
|
|
if [ -f "$ENV_FILE" ]; then
|
|
TAILNET_DOMAIN=$(grep -o "TAILSCALE_TAILNET_DOMAIN=.*" "$ENV_FILE" | cut -d'=' -f2 | tr -d '"' | tr -d "'")
|
|
TAILSCALE_HOSTNAME=$(grep -o "TAILSCALE_HOSTNAME=.*" "$ENV_FILE" | cut -d'=' -f2 | tr -d '"' | tr -d "'")
|
|
|
|
if [ -n "$TAILNET_DOMAIN" ] && [ -n "$TAILSCALE_HOSTNAME" ]; then
|
|
# Extract the base domain (e.g., from "example.ts.net" get "ts.net")
|
|
BASE_DOMAIN=$(echo "$TAILNET_DOMAIN" | grep -o '[^.]\+\.[^.]\+$')
|
|
|
|
# Replace placeholders with actual values
|
|
# For cookie domain, use the base domain (e.g., "ts.net" not "*.ts.net")
|
|
sed -i "s/domain: 'ts.net'/domain: '$BASE_DOMAIN'/g" "$AUTHELIA_CONFIG"
|
|
|
|
# For access control rules, wildcard pattern is allowed
|
|
sed -i "s/domain: '\*.ts.net'/domain: '\*.$BASE_DOMAIN'/g" "$AUTHELIA_CONFIG"
|
|
|
|
# For URLs, use the full hostname
|
|
sed -i "s/https:\/\/tailscale-nas.ts.net/https:\/\/$TAILSCALE_HOSTNAME.$TAILNET_DOMAIN/g" "$AUTHELIA_CONFIG"
|
|
|
|
echo -e "${GREEN}Configured Authelia with your Tailscale domain:${NC}"
|
|
echo -e "${CYAN} - Base domain for cookies: ${GREEN}$BASE_DOMAIN${NC}"
|
|
echo -e "${CYAN} - Access control for: ${GREEN}*.$BASE_DOMAIN${NC}"
|
|
echo -e "${CYAN} - Authelia URL: ${GREEN}https://$TAILSCALE_HOSTNAME.$TAILNET_DOMAIN${NC}"
|
|
else
|
|
echo -e "${YELLOW}Warning: Could not find both TAILSCALE_HOSTNAME and TAILSCALE_TAILNET_DOMAIN in .env${NC}"
|
|
echo -e "${YELLOW}You may need to manually edit $AUTHELIA_CONFIG to set your domains correctly${NC}"
|
|
fi
|
|
fi
|
|
|
|
echo -e "${GREEN}${BOLD}Authelia Configuration Update Complete!${NC}"
|
|
echo -e "${BLUE}${BOLD}Note:${NC} Original config backed up to: $AUTHELIA_CONFIG_BACKUP"
|
|
}
|
|
|
|
##################################################
|
|
# PART 3: Update Service Configurations
|
|
##################################################
|
|
|
|
update_arr_config() {
|
|
local container=$1
|
|
local path=$2
|
|
|
|
echo -e "${BLUE}Updating ${container} configuration...${NC}"
|
|
until [ -f "${CONFIG_ROOT:-.}"/"$container"/config.xml ]; do sleep 1; done
|
|
sed -i.bak "s/<UrlBase><\/UrlBase>/<UrlBase>\/$path<\/UrlBase>/" "${CONFIG_ROOT:-.}"/"$container"/config.xml && rm "${CONFIG_ROOT:-.}"/"$container"/config.xml.bak
|
|
|
|
CONTAINER_NAME_UPPER=$(echo "$container" | tr '[:lower:]' '[:upper:]')
|
|
sed -i.bak 's/^'"${CONTAINER_NAME_UPPER}"'_API_KEY=.*/'"${CONTAINER_NAME_UPPER}"'_API_KEY='"$(sed -n 's/.*<ApiKey>\(.*\)<\/ApiKey>.*/\1/p' "${CONFIG_ROOT:-.}"/"$container"/config.xml)"'/' .env && rm .env.bak
|
|
|
|
echo -e "${GREEN}Update of ${container} configuration complete, restarting...${NC}"
|
|
docker compose restart "$container"
|
|
}
|
|
|
|
update_qbittorrent_config() {
|
|
local container=$1
|
|
|
|
echo -e "${BLUE}Updating ${container} configuration...${NC}"
|
|
docker compose stop "$container"
|
|
until [ -f "${CONFIG_ROOT:-.}"/"$container"/qBittorrent/qBittorrent.conf ]; do sleep 1; done
|
|
sed -i.bak '/WebUI\\ServerDomains=*/a WebUI\\Password_PBKDF2="@ByteArray(ARQ77eY1NUZaQsuDHbIMCA==:0WMRkYTUWVT9wVvdDtHAjU9b3b7uB8NR1Gur2hmQCvCDpm39Q+PsJRJPaCU51dEiz+dTzh8qbPsL8WkFljQYFQ==)"' "${CONFIG_ROOT:-.}"/"$container"/qBittorrent/qBittorrent.conf && rm "${CONFIG_ROOT:-.}"/"$container"/qBittorrent/qBittorrent.conf.bak
|
|
|
|
echo -e "${GREEN}Update of ${container} configuration complete, restarting...${NC}"
|
|
docker compose start "$container"
|
|
}
|
|
|
|
update_bazarr_config() {
|
|
local container=$1
|
|
|
|
echo -e "${BLUE}Updating ${container} configuration...${NC}"
|
|
until [ -f "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml ]; do sleep 1; done
|
|
sed -i.bak "s/base_url: ''/base_url: '\/$container'/" "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml && rm "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml.bak
|
|
sed -i.bak "s/use_radarr: false/use_radarr: true/" "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml && rm "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml.bak
|
|
sed -i.bak "s/use_sonarr: false/use_sonarr: true/" "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml && rm "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml.bak
|
|
|
|
until [ -f "${CONFIG_ROOT:-.}"/sonarr/config.xml ]; do sleep 1; done
|
|
SONARR_API_KEY=$(sed -n 's/.*<ApiKey>\(.*\)<\/ApiKey>.*/\1/p' "${CONFIG_ROOT:-.}"/sonarr/config.xml)
|
|
sed -i.bak "/sonarr:/,/^radarr:/ { s/apikey: .*/apikey: $SONARR_API_KEY/; s/base_url: .*/base_url: \/sonarr/; s/ip: .*/ip: sonarr/ }" "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml && rm "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml.bak
|
|
|
|
until [ -f "${CONFIG_ROOT:-.}"/radarr/config.xml ]; do sleep 1; done
|
|
RADARR_API_KEY=$(sed -n 's/.*<ApiKey>\(.*\)<\/ApiKey>.*/\1/p' "${CONFIG_ROOT:-.}"/radarr/config.xml)
|
|
sed -i.bak "/radarr:/,/^sonarr:/ { s/apikey: .*/apikey: $RADARR_API_KEY/; s/base_url: .*/base_url: \/radarr/; s/ip: .*/ip: radarr/ }" "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml && rm "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml.bak
|
|
|
|
sed -i.bak 's/^BAZARR_API_KEY=.*/BAZARR_API_KEY='"$(sed -n 's/.*apikey: \(.*\)*/\1/p' "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml | head -n 1)"'/' .env && rm .env.bak
|
|
|
|
echo -e "${GREEN}Update of ${container} configuration complete, restarting...${NC}"
|
|
docker compose restart "$container"
|
|
}
|
|
|
|
update_service_configs() {
|
|
print_header "Service Configuration Update Tool"
|
|
|
|
echo -e "${BLUE}This will update service configurations for running containers${NC}"
|
|
echo -e "${BLUE}It will set proper URL bases and extract API keys${NC}"
|
|
echo -e "${YELLOW}Continue? [y/N]:${NC}"
|
|
read -r answer
|
|
if [[ ! "$answer" =~ ^[Yy]$ ]]; then
|
|
echo -e "${RED}Service configuration update cancelled.${NC}"
|
|
return 0
|
|
fi
|
|
|
|
# Check if Docker is running
|
|
if ! docker ps > /dev/null 2>&1; then
|
|
echo -e "${RED}Error: Docker is not running or you don't have permission to use it.${NC}"
|
|
echo -e "${YELLOW}Make sure Docker is running and you have proper permissions.${NC}"
|
|
return 1
|
|
fi
|
|
|
|
echo -e "${BLUE}Checking for running containers to update...${NC}"
|
|
for container in $(docker ps --format '{{.Names}}'); do
|
|
if [[ "$container" =~ ^(radarr|sonarr|lidarr|prowlarr)$ ]]; then
|
|
update_arr_config "$container" "$container"
|
|
elif [[ "$container" =~ ^(bazarr)$ ]]; then
|
|
update_bazarr_config "$container"
|
|
elif [[ "$container" =~ ^(qbittorrent)$ ]]; then
|
|
update_qbittorrent_config "$container"
|
|
fi
|
|
done
|
|
|
|
echo -e "\n${GREEN}${BOLD}Service Configuration Update Complete!${NC}"
|
|
}
|
|
|
|
##################################################
|
|
# MAIN SCRIPT
|
|
##################################################
|
|
|
|
# Display main menu
|
|
print_header "Docker Compose NAS - Setup Tool"
|
|
echo -e "${BLUE}This tool will help you configure your Docker Compose NAS setup${NC}"
|
|
echo -e "${BLUE}Choose one or more options to run:${NC}"
|
|
echo -e " ${CYAN}1. ${NC}Update .env file from .env.example"
|
|
echo -e " ${CYAN}2. ${NC}Update Authelia configuration"
|
|
echo -e " ${CYAN}3. ${NC}Update service configurations"
|
|
echo -e " ${CYAN}4. ${NC}Run ALL updates"
|
|
echo -e " ${CYAN}q. ${NC}Quit"
|
|
echo
|
|
|
|
CHOICE="0"
|
|
while [[ "$CHOICE" != "q" ]]; do
|
|
echo -e "${YELLOW}Enter your choice [1-4 or q to quit]: ${NC}"
|
|
read -r CHOICE
|
|
|
|
case "$CHOICE" in
|
|
1) update_env_file ;;
|
|
2) update_authelia_config ;;
|
|
3) update_service_configs ;;
|
|
4)
|
|
update_env_file
|
|
update_authelia_config
|
|
update_service_configs
|
|
CHOICE="q" # Exit after running all
|
|
;;
|
|
q|Q)
|
|
echo -e "${GREEN}Exiting setup tool.${NC}"
|
|
exit 0
|
|
;;
|
|
*) echo -e "${RED}Invalid choice. Please try again.${NC}" ;;
|
|
esac
|
|
done
|
|
|
|
echo -e "\n${GREEN}${BOLD}All updates completed!${NC}"
|
|
echo -e "${BLUE}Be sure to restart any services that were updated:${NC}"
|
|
echo -e " ${CYAN}docker compose restart${NC}"
|
|
echo -e "\n${BLUE}If you updated the Authelia configuration, restart Authelia:${NC}"
|
|
echo -e " ${CYAN}docker compose restart authelia${NC}" |