refactor: Consolidate Authelia configuration management and update setup scripts
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+.
This commit is contained in:
Jose Daniel G. Percy 2025-04-26 00:32:24 +08:00
parent 6e17920cfd
commit 6d9139408d
6 changed files with 426 additions and 237 deletions

2
.gitignore vendored
View File

@ -1,6 +1,8 @@
*.env
.idea
docker-compose.override.yml
/authelia/*.yml
!/authelia/configuration.example.yml
/homepage/logs
/homepage/*.yaml
/homepage/*.css

View File

@ -154,21 +154,25 @@ After completing all [Required Setup Steps](#required-setup-steps) above, follow
nano authelia/users_database.yml
```
4. **Start the Stack:**
4. **Run the Setup Script:**
```bash
# Make helper script executable (if needed)
chmod +x ./update-config.sh
chmod +x ./update-env.sh
# Make the script executable
chmod +x ./update-setup.sh
# Run the setup tool
./update-setup.sh
```
This interactive script will guide you through:
- Updating your `.env` file while preserving existing values
- Configuring Authelia with your Tailscale domain settings
- Setting up service configurations and retrieving API keys
5. **Start the Stack:**
```bash
# Start containers
docker compose up -d
```
5. **Configure Service API Keys** (after stack is running):
```bash
# Optional: Run config script to set API keys
./update-config.sh
```
*(Wait for containers to download and start)*
6. **Access Your NAS:**
- Open `https://<TAILSCALE_HOSTNAME>.<TAILSCALE_TAILNET_DOMAIN>/`
@ -395,13 +399,11 @@ If you are running Docker on a host with SELinux enabled (like Fedora, CentOS, R
### Authelia v4.38+ Configuration
Authelia v4.38+ introduces significant changes to its configuration structure, particularly for session domains and authentication flows. This Docker Compose template has been updated to support these changes, making it easier to set up:
Authelia v4.38+ introduces significant changes to its configuration structure, particularly for session domains and authentication flows. The setup in this repository has been carefully configured to work with these changes:
1. **Simplified Configuration**: The setup now uses a more reliable approach with wildcard domain matching (`*.ts.net`) that works properly with Tailscale domains. This eliminates environment variable interpolation issues that were causing errors in previous versions.
1. **Domain Configuration**: The configuration now properly uses the base Tailscale domain (e.g., `ts.net`) for cookies rather than a wildcard domain, which is not allowed for cookie configuration in Authelia v4.38+. Wildcards are still used in access control rules where they are permitted.
2. **No Manual YAML Editing Required**: You don't need to edit the Authelia configuration file manually. The important settings are configured through environment variables in the Docker Compose setup.
3. **Required Secret Variables**: You only need to set these four variables in your `.env` file:
2. **Required Secret Variables**: You must set these four variables in your `.env` file:
- `AUTHELIA_JWT_SECRET`: Used for password reset tokens
- `AUTHELIA_SESSION_SECRET`: Used for session cookie encryption
- `AUTHELIA_STORAGE_ENCRYPTION_KEY`: Used for database encryption
@ -409,16 +411,20 @@ Authelia v4.38+ introduces significant changes to its configuration structure, p
Generate strong random values for these with: `openssl rand -hex 32`
4. **File Permissions Fixed**: The Authelia container now runs with your user ID and group ID, preventing permission issues when managing the configuration files with git or other tools.
3. **Automatic Domain Setup**: The `update-setup.sh` script automatically:
- Extracts your Tailscale base domain (e.g., `ts.net`) from your `.env` file
- Configures cookie domains properly without wildcards
- Sets the correct URLs based on your Tailscale hostname
5. **Common Error Solutions**: If you encounter configuration errors like these:
```
error decoding 'session.cookies[0].authelia_url': could not decode 'https://${APP_HOSTNAME}'
can't be specified at the same time: option 'domain' and option 'cookies'
```
The solution is already implemented in the updated configuration. No manual fixes needed.
4. **File Permissions**: The Authelia container runs with your user ID and group ID, preventing permission issues when managing the configuration files with git or other tools.
If you need to make changes to the domain settings for some reason, edit `authelia/configuration.yml` and modify the `*.ts.net` wildcard pattern to match your specific domain. For most setups using Tailscale, the default configuration will work without any changes.
If you encounter any of these common errors, running the setup script should resolve them:
```
error: option 'domain' must be the domain you wish to protect not a wildcard domain
error: option 'authelia_url' does not share a cookie scope with domain
error: can't be specified at the same time: option 'domain' and option 'cookies'
configuration key 'jwt_secret' is deprecated in 4.38.0
```
After making changes to the configuration, restart Authelia with:
```bash

View File

@ -22,8 +22,8 @@ session:
password: ${AUTHELIA_SESSION_REDIS_PASSWORD}
database_index: 0
cookies:
# Using a wildcard domain pattern - works for Tailscale domains
- domain: '*.ts.net'
# Using parent domain to allow proper cookie scope
- domain: 'ts.net'
authelia_url: 'https://tailscale-nas.ts.net'
default_redirection_url: 'https://tailscale-nas.ts.net/home'
same_site: lax
@ -56,7 +56,7 @@ authentication_backend:
access_control:
default_policy: deny
rules:
# This will match any Tailscale domain
# This will match any Tailscale domain - using wildcard with domains is allowed in rules
- domain: '*.ts.net'
policy: one_factor

View File

@ -1,49 +0,0 @@
#!/bin/bash
# See https://stackoverflow.com/a/44864004 for the sed GNU/BSD compatible hack
function update_arr_config {
echo "Updating ${container} configuration..."
until [ -f "${CONFIG_ROOT:-.}"/"$container"/config.xml ]; do sleep 1; done
sed -i.bak "s/<UrlBase><\/UrlBase>/<UrlBase>\/$1<\/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 "Update of ${container} configuration complete, restarting..."
docker compose restart "$container"
}
function update_qbittorrent_config {
echo "Updating ${container} configuration..."
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 "Update of ${container} configuration complete, restarting..."
docker compose start "$container"
}
function update_bazarr_config {
echo "Updating ${container} configuration..."
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 "Update of ${container} configuration complete, restarting..."
docker compose restart "$container"
}
for container in $(docker ps --format '{{.Names}}'); do
if [[ "$container" =~ ^(radarr|sonarr|lidarr|prowlarr)$ ]]; then
update_arr_config "$container"
elif [[ "$container" =~ ^(bazarr)$ ]]; then
update_bazarr_config "$container"
elif [[ "$container" =~ ^(qbittorrent)$ ]]; then
update_qbittorrent_config "$container"
fi
done

View File

@ -1,162 +0,0 @@
#!/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
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}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}"

392
update-setup.sh Normal file
View File

@ -0,0 +1,392 @@
#!/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}"