refactor: Consolidate Authelia configuration management and update setup scripts
Some checks failed
/ validate-docker-compose (push) Has been cancelled
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:
parent
6e17920cfd
commit
6d9139408d
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,6 +1,8 @@
|
||||
*.env
|
||||
.idea
|
||||
docker-compose.override.yml
|
||||
/authelia/*.yml
|
||||
!/authelia/configuration.example.yml
|
||||
/homepage/logs
|
||||
/homepage/*.yaml
|
||||
/homepage/*.css
|
||||
|
||||
52
README.md
52
README.md
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
162
update-env.sh
162
update-env.sh
@ -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
392
update-setup.sh
Normal 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}"
|
||||
Loading…
x
Reference in New Issue
Block a user