fix(authelia): Authentication management and middleware errors
Some checks failed
/ validate-docker-compose (push) Has been cancelled
Some checks failed
/ validate-docker-compose (push) Has been cancelled
- Fix middleware "true@docker" does not exist errors - Integrate authentication management directly into update-setup.sh - Add command-line support for managing service authentication - Add backup file cleanup functionality - Update README with new authentication management instructions - Remove standalone manage-auth.sh script
This commit is contained in:
parent
5d7a162647
commit
a74707dc1f
55
README.md
55
README.md
@ -25,7 +25,7 @@ The core idea is to manage media libraries (movies, TV shows, music), automate d
|
|||||||
- [(Optional) VPN Configuration](#optional-vpn-configuration)
|
- [(Optional) VPN Configuration](#optional-vpn-configuration)
|
||||||
- [(Optional) Traefik DNS Challenge](#optional-traefik-dns-challenge)
|
- [(Optional) Traefik DNS Challenge](#optional-traefik-dns-challenge)
|
||||||
- [Service Access](#service-access)
|
- [Service Access](#service-access)
|
||||||
- [Configuring Authentication Per Service](#configuring-authentication-per-service)
|
- [Managing Service Authentication](#managing-service-authentication)
|
||||||
- [Optional Services](#optional-services)
|
- [Optional Services](#optional-services)
|
||||||
- [Troubleshooting](#troubleshooting)
|
- [Troubleshooting](#troubleshooting)
|
||||||
- [Middleware Not Found Errors](#middleware-not-found-errors)
|
- [Middleware Not Found Errors](#middleware-not-found-errors)
|
||||||
@ -362,34 +362,57 @@ Authelia uses the `authelia/users_database.yml` file to manage users.
|
|||||||
|
|
||||||
## Service Access
|
## Service Access
|
||||||
|
|
||||||
With the default Tailscale setup and Authelia enabled, services are securely accessible via HTTPS using your Tailscale node's name or IP. Authentication is controlled by the `AUTH_*` environment variables.
|
With the default Tailscale setup and Authelia enabled, services are securely accessible via HTTPS using your Tailscale node's name or IP. Authentication is controlled by the included `update-setup.sh` script.
|
||||||
|
|
||||||
* **Login Portal:** `https://<TAILSCALE_NODE>/` (Redirects unauthenticated users here for secured services)
|
* **Login Portal:** `https://<TAILSCALE_NODE>/` (Redirects unauthenticated users here for secured services)
|
||||||
* **Homepage Dashboard:** `https://<TAILSCALE_NODE>/home` (Requires login if `AUTH_HOMEPAGE=true`)
|
* **Homepage Dashboard:** `https://<TAILSCALE_NODE>/home` (Requires login by default)
|
||||||
* **Sonarr:** `https://<TAILSCALE_NODE>/sonarr` (Requires login if `AUTH_SONARR=true`)
|
* **Sonarr:** `https://<TAILSCALE_NODE>/sonarr` (Requires login by default)
|
||||||
* **Radarr:** `https://<TAILSCALE_NODE>/radarr` (Requires login if `AUTH_RADARR=true`)
|
* **Radarr:** `https://<TAILSCALE_NODE>/radarr` (Requires login by default)
|
||||||
* **qBittorrent:** `https://<TAILSCALE_NODE>/qbittorrent` (Requires login if `AUTH_QBITTORRENT=true`)
|
* **qBittorrent:** `https://<TAILSCALE_NODE>/qbittorrent` (Requires login by default)
|
||||||
* **Jellyfin:** `https://<TAILSCALE_NODE>/jellyfin` (Requires login if `AUTH_JELLYFIN=true`, default is `false`)
|
* **Jellyfin:** `https://<TAILSCALE_NODE>/jellyfin` (Requires login by default)
|
||||||
* ...and so on.
|
* ...and so on.
|
||||||
|
|
||||||
Replace `<TAILSCALE_NODE>` with your Tailscale device name (e.g., `tailscale-nas.your-tailnet.ts.net`) or its Tailscale IP address.
|
Replace `<TAILSCALE_NODE>` with your Tailscale device name (e.g., `tailscale-nas.your-tailnet.ts.net`) or its Tailscale IP address.
|
||||||
|
|
||||||
If you configure DNS for your `APP_HOSTNAME` variable to point to the Tailscale IP, you can use `https://<APP_HOSTNAME>/<service_path>`.
|
If you configure DNS for your `APP_HOSTNAME` variable to point to the Tailscale IP, you can use `https://<APP_HOSTNAME>/<service_path>`.
|
||||||
|
|
||||||
### Configuring Authentication Per Service
|
### Managing Service Authentication
|
||||||
|
|
||||||
You can control which services require authentication by setting the appropriate variables in your `.env` file:
|
You can control which services require authentication using the updated `update-setup.sh` script:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Example: Allow Jellyfin and qBittorrent without authentication, require it for others
|
# List all services and their authentication status
|
||||||
AUTH_JELLYFIN=false
|
./update-setup.sh list-auth
|
||||||
AUTH_QBITTORRENT=false
|
|
||||||
AUTH_SONARR=true
|
# Disable authentication for Jellyfin (no login required)
|
||||||
AUTH_RADARR=true
|
./update-setup.sh disable-auth jellyfin
|
||||||
# ...and so on
|
|
||||||
|
# Enable authentication for Jellyfin (login required)
|
||||||
|
./update-setup.sh enable-auth jellyfin
|
||||||
|
|
||||||
|
# Disable authentication for all services
|
||||||
|
./update-setup.sh disable-all-auth
|
||||||
|
|
||||||
|
# Enable authentication for all services
|
||||||
|
./update-setup.sh enable-all-auth
|
||||||
|
|
||||||
|
# Clean up backup files (keeps most recent by default)
|
||||||
|
./update-setup.sh cleanup
|
||||||
|
|
||||||
|
# View all available commands
|
||||||
|
./update-setup.sh help
|
||||||
```
|
```
|
||||||
|
|
||||||
If a variable is not explicitly set, authentication defaults to `true` for that service (except for Jellyfin, which defaults to `false`).
|
You can also manage authentication through the interactive menu by running `./update-setup.sh` and selecting option 5.
|
||||||
|
|
||||||
|
After making changes, restart your stack for the changes to take effect:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose down
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
This approach gives you complete control over which services require authentication, without needing to manually edit configuration files.
|
||||||
|
|
||||||
## Optional Services
|
## Optional Services
|
||||||
|
|
||||||
|
|||||||
302
manage-auth.sh
302
manage-auth.sh
@ -1,302 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Authentication Management Script for docker-compose-nas
|
|
||||||
# Enables or disables Authelia authentication for specific services
|
|
||||||
# Created: April 26, 2025
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Color definitions
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[0;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
CYAN='\033[0;36m'
|
|
||||||
BOLD='\033[1m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# Files
|
|
||||||
COMPOSE_FILE="docker-compose.yml"
|
|
||||||
TIMESTAMP=$(date +"%Y%m%d-%H%M%S")
|
|
||||||
BACKUP_FILE="docker-compose.${TIMESTAMP}.bak"
|
|
||||||
|
|
||||||
# Print section header
|
|
||||||
print_header() {
|
|
||||||
echo -e "\n${CYAN}${BOLD}$1${NC}"
|
|
||||||
echo -e "${CYAN}$(printf '=%.0s' $(seq 1 ${#1}))${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create a backup of the docker-compose.yml file
|
|
||||||
create_backup() {
|
|
||||||
echo -e "${BLUE}Creating backup of $COMPOSE_FILE as $BACKUP_FILE...${NC}"
|
|
||||||
cp "$COMPOSE_FILE" "$BACKUP_FILE"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get the current auth status for a service
|
|
||||||
get_auth_status() {
|
|
||||||
local service=$1
|
|
||||||
# Check if the service has authelia-auth middleware
|
|
||||||
if grep -q "traefik.http.routers.$service.middlewares=.*authelia-auth" "$COMPOSE_FILE"; then
|
|
||||||
echo "enabled"
|
|
||||||
elif grep -q "traefik.http.routers.$service.middlewares=" "$COMPOSE_FILE"; then
|
|
||||||
# Service has middlewares, but no authelia-auth
|
|
||||||
echo "disabled"
|
|
||||||
else
|
|
||||||
echo "unknown"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Enable authentication for a service
|
|
||||||
enable_auth() {
|
|
||||||
local service=$1
|
|
||||||
echo -e "${BLUE}Enabling authentication for $service...${NC}"
|
|
||||||
|
|
||||||
# Check if the service exists in the compose file
|
|
||||||
if ! grep -q "container_name: $service" "$COMPOSE_FILE"; then
|
|
||||||
echo -e "${RED}Service $service not found in $COMPOSE_FILE${NC}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Update the middlewares configuration
|
|
||||||
# This is a bit complex because different services have different middleware configurations
|
|
||||||
# We need to find the existing middlewares line and add authelia-auth if it doesn't exist
|
|
||||||
|
|
||||||
# First, find the service section
|
|
||||||
local service_start=$(grep -n "container_name: $service" "$COMPOSE_FILE" | cut -d':' -f1)
|
|
||||||
if [ -z "$service_start" ]; then
|
|
||||||
echo -e "${RED}Could not find service $service in $COMPOSE_FILE${NC}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Find the next service or EOF
|
|
||||||
local next_service=$(tail -n +$((service_start+1)) "$COMPOSE_FILE" | grep -n "container_name:" | head -1 | cut -d':' -f1)
|
|
||||||
if [ -n "$next_service" ]; then
|
|
||||||
next_service=$((service_start + next_service))
|
|
||||||
else
|
|
||||||
next_service=$(wc -l < "$COMPOSE_FILE")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Extract the service section
|
|
||||||
local service_section=$(sed -n "${service_start},${next_service}p" "$COMPOSE_FILE")
|
|
||||||
|
|
||||||
# Find if there's a middlewares line
|
|
||||||
if echo "$service_section" | grep -q "traefik.http.routers.$service.middlewares="; then
|
|
||||||
# Get the middlewares line
|
|
||||||
local middlewares_line=$(echo "$service_section" | grep "traefik.http.routers.$service.middlewares=")
|
|
||||||
|
|
||||||
# Check if authelia-auth is already in the middlewares
|
|
||||||
if echo "$middlewares_line" | grep -q "authelia-auth@docker"; then
|
|
||||||
echo -e "${GREEN}Authentication already enabled for $service${NC}"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Add authelia-auth to the middlewares
|
|
||||||
# Different patterns depending on what's in the middlewares line
|
|
||||||
if echo "$middlewares_line" | grep -q "middlewares=$"; then
|
|
||||||
# Empty middlewares
|
|
||||||
sed -i "s|traefik.http.routers.$service.middlewares=|traefik.http.routers.$service.middlewares=authelia-auth@docker|" "$COMPOSE_FILE"
|
|
||||||
elif echo "$middlewares_line" | grep -q "middlewares=.*@docker"; then
|
|
||||||
# Already has some middleware with @docker
|
|
||||||
sed -i "s|traefik.http.routers.$service.middlewares=\(.*\)@docker|traefik.http.routers.$service.middlewares=\1,authelia-auth@docker|" "$COMPOSE_FILE"
|
|
||||||
else
|
|
||||||
# Has middlewares but no @docker suffix
|
|
||||||
sed -i "s|traefik.http.routers.$service.middlewares=\(.*\)|traefik.http.routers.$service.middlewares=\1,authelia-auth@docker|" "$COMPOSE_FILE"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# No middlewares line, add one
|
|
||||||
local labels_line=$(echo "$service_section" | grep -n "labels:" | cut -d':' -f1)
|
|
||||||
if [ -z "$labels_line" ]; then
|
|
||||||
echo -e "${RED}Could not find labels section for service $service${NC}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Insert the middlewares line after the rule line
|
|
||||||
local rule_line=$(echo "$service_section" | grep -n "traefik.http.routers.$service.rule=" | cut -d':' -f1)
|
|
||||||
if [ -n "$rule_line" ]; then
|
|
||||||
rule_line=$((service_start + rule_line))
|
|
||||||
sed -i "${rule_line}a \ \ \ \ \ \ - traefik.http.routers.$service.middlewares=authelia-auth@docker" "$COMPOSE_FILE"
|
|
||||||
else
|
|
||||||
echo -e "${RED}Could not find rule line for service $service${NC}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "${GREEN}Authentication enabled for $service${NC}"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# Disable authentication for a service
|
|
||||||
disable_auth() {
|
|
||||||
local service=$1
|
|
||||||
echo -e "${BLUE}Disabling authentication for $service...${NC}"
|
|
||||||
|
|
||||||
# Check if the service exists in the compose file
|
|
||||||
if ! grep -q "container_name: $service" "$COMPOSE_FILE"; then
|
|
||||||
echo -e "${RED}Service $service not found in $COMPOSE_FILE${NC}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Update the middlewares configuration by removing authelia-auth
|
|
||||||
|
|
||||||
# First, find if there's a middlewares line with authelia-auth
|
|
||||||
if grep -q "traefik.http.routers.$service.middlewares=.*authelia-auth@docker" "$COMPOSE_FILE"; then
|
|
||||||
# Simple case: only authelia-auth
|
|
||||||
if grep -q "traefik.http.routers.$service.middlewares=authelia-auth@docker" "$COMPOSE_FILE"; then
|
|
||||||
# Remove authelia-auth@docker, leaving only the label prefix
|
|
||||||
sed -i "s|traefik.http.routers.$service.middlewares=authelia-auth@docker|traefik.http.routers.$service.middlewares=|" "$COMPOSE_FILE"
|
|
||||||
# authelia-auth is at the beginning with a comma
|
|
||||||
elif grep -q "traefik.http.routers.$service.middlewares=authelia-auth@docker," "$COMPOSE_FILE"; then
|
|
||||||
# Remove authelia-auth@docker,
|
|
||||||
sed -i "s|traefik.http.routers.$service.middlewares=authelia-auth@docker,|traefik.http.routers.$service.middlewares=|" "$COMPOSE_FILE"
|
|
||||||
# authelia-auth is at the end with a comma before it
|
|
||||||
elif grep -q "traefik.http.routers.$service.middlewares=.*,authelia-auth@docker" "$COMPOSE_FILE"; then
|
|
||||||
# Remove ,authelia-auth@docker
|
|
||||||
sed -i "s|,authelia-auth@docker||" "$COMPOSE_FILE"
|
|
||||||
# authelia-auth is in the middle
|
|
||||||
elif grep -q "traefik.http.routers.$service.middlewares=.*,authelia-auth@docker,.*" "$COMPOSE_FILE"; then
|
|
||||||
# Remove ,authelia-auth@docker
|
|
||||||
sed -i "s|,authelia-auth@docker,|,|" "$COMPOSE_FILE"
|
|
||||||
else
|
|
||||||
echo -e "${RED}Could not determine how to remove authelia-auth from middlewares for $service${NC}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "${GREEN}Authentication disabled for $service${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${GREEN}Authentication already disabled for $service${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# List services and their auth status
|
|
||||||
list_services() {
|
|
||||||
print_header "Services Authentication Status"
|
|
||||||
|
|
||||||
echo -e "${BLUE}Checking services in $COMPOSE_FILE...${NC}"
|
|
||||||
echo -e "${CYAN}SERVICE\t\tAUTH STATUS${NC}"
|
|
||||||
echo -e "${CYAN}-------\t\t-----------${NC}"
|
|
||||||
|
|
||||||
# Find all container names
|
|
||||||
local services=$(grep "container_name:" "$COMPOSE_FILE" | awk '{print $3}')
|
|
||||||
|
|
||||||
for service in $services; do
|
|
||||||
# Skip infrastructure containers
|
|
||||||
if [[ "$service" == "redis" || "$service" == "authelia" || "$service" == "traefik" || "$service" == "tailscale" || "$service" == "watchtower" || "$service" == "autoheal" || "$service" == "middlewares" ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
local status=$(get_auth_status "$service")
|
|
||||||
|
|
||||||
# Pad service name for better formatting
|
|
||||||
printf "${BOLD}%-20s${NC}" "$service"
|
|
||||||
|
|
||||||
case "$status" in
|
|
||||||
"enabled")
|
|
||||||
echo -e "${GREEN}Enabled${NC}"
|
|
||||||
;;
|
|
||||||
"disabled")
|
|
||||||
echo -e "${YELLOW}Disabled${NC}"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo -e "${RED}Unknown${NC}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Display help
|
|
||||||
show_help() {
|
|
||||||
print_header "Authentication Management Script"
|
|
||||||
echo -e "Usage: $0 [options]"
|
|
||||||
echo -e ""
|
|
||||||
echo -e "Options:"
|
|
||||||
echo -e " ${CYAN}list${NC} List all services and their auth status"
|
|
||||||
echo -e " ${CYAN}enable <service>${NC} Enable authentication for a service"
|
|
||||||
echo -e " ${CYAN}disable <service>${NC} Disable authentication for a service"
|
|
||||||
echo -e " ${CYAN}enable-all${NC} Enable authentication for all services"
|
|
||||||
echo -e " ${CYAN}disable-all${NC} Disable authentication for all services"
|
|
||||||
echo -e " ${CYAN}help${NC} Show this help message"
|
|
||||||
echo -e ""
|
|
||||||
echo -e "Examples:"
|
|
||||||
echo -e " $0 list"
|
|
||||||
echo -e " $0 enable jellyfin"
|
|
||||||
echo -e " $0 disable homepage"
|
|
||||||
echo -e " $0 enable-all"
|
|
||||||
echo -e ""
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main function
|
|
||||||
main() {
|
|
||||||
if [ $# -eq 0 ]; then
|
|
||||||
show_help
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create backup of compose file
|
|
||||||
create_backup
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
"list")
|
|
||||||
list_services
|
|
||||||
;;
|
|
||||||
"enable")
|
|
||||||
if [ -z "$2" ]; then
|
|
||||||
echo -e "${RED}Error: No service specified${NC}"
|
|
||||||
echo -e "Usage: $0 enable <service>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
enable_auth "$2"
|
|
||||||
;;
|
|
||||||
"disable")
|
|
||||||
if [ -z "$2" ]; then
|
|
||||||
echo -e "${RED}Error: No service specified${NC}"
|
|
||||||
echo -e "Usage: $0 disable <service>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
disable_auth "$2"
|
|
||||||
;;
|
|
||||||
"enable-all")
|
|
||||||
print_header "Enabling Authentication for All Services"
|
|
||||||
|
|
||||||
local services=$(grep "container_name:" "$COMPOSE_FILE" | awk '{print $3}')
|
|
||||||
for service in $services; do
|
|
||||||
# Skip infrastructure containers
|
|
||||||
if [[ "$service" == "redis" || "$service" == "authelia" || "$service" == "traefik" || "$service" == "tailscale" || "$service" == "watchtower" || "$service" == "autoheal" || "$service" == "middlewares" ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
enable_auth "$service"
|
|
||||||
done
|
|
||||||
;;
|
|
||||||
"disable-all")
|
|
||||||
print_header "Disabling Authentication for All Services"
|
|
||||||
|
|
||||||
local services=$(grep "container_name:" "$COMPOSE_FILE" | awk '{print $3}')
|
|
||||||
for service in $services; do
|
|
||||||
# Skip infrastructure containers
|
|
||||||
if [[ "$service" == "redis" || "$service" == "authelia" || "$service" == "traefik" || "$service" == "tailscale" || "$service" == "watchtower" || "$service" == "autoheal" || "$service" == "middlewares" ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
disable_auth "$service"
|
|
||||||
done
|
|
||||||
;;
|
|
||||||
"help")
|
|
||||||
show_help
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo -e "${RED}Error: Unknown command: $1${NC}"
|
|
||||||
show_help
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo -e "\n${GREEN}${BOLD}Done!${NC}"
|
|
||||||
echo -e "${BLUE}Original configuration backed up to: $BACKUP_FILE${NC}"
|
|
||||||
echo -e "${YELLOW}Remember to restart the stack for changes to take effect:${NC}"
|
|
||||||
echo -e "${CYAN} docker compose down${NC}"
|
|
||||||
echo -e "${CYAN} docker compose up -d${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
468
update-setup.sh
468
update-setup.sh
@ -5,6 +5,7 @@
|
|||||||
# - Updates Authelia configuration from example file
|
# - Updates Authelia configuration from example file
|
||||||
# - Configures services with correct paths and API keys
|
# - Configures services with correct paths and API keys
|
||||||
# - Manages Authelia accounts
|
# - Manages Authelia accounts
|
||||||
|
# - Controls service authentication requirements
|
||||||
# Created: April 26, 2025
|
# Created: April 26, 2025
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
@ -27,6 +28,8 @@ ENV_BACKUP=".env.${TIMESTAMP}.bak"
|
|||||||
AUTHELIA_CONFIG="authelia/configuration.yml"
|
AUTHELIA_CONFIG="authelia/configuration.yml"
|
||||||
AUTHELIA_CONFIG_EXAMPLE="authelia/configuration.example.yml"
|
AUTHELIA_CONFIG_EXAMPLE="authelia/configuration.example.yml"
|
||||||
AUTHELIA_CONFIG_BACKUP="authelia/configuration.${TIMESTAMP}.bak"
|
AUTHELIA_CONFIG_BACKUP="authelia/configuration.${TIMESTAMP}.bak"
|
||||||
|
COMPOSE_FILE="docker-compose.yml"
|
||||||
|
COMPOSE_BACKUP="docker-compose.${TIMESTAMP}.bak"
|
||||||
|
|
||||||
# Print section header
|
# Print section header
|
||||||
print_header() {
|
print_header() {
|
||||||
@ -336,7 +339,6 @@ update_service_configs() {
|
|||||||
# Additional utility functions
|
# Additional utility functions
|
||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
# Function to generate a random passphrase with random separators and numbers
|
|
||||||
generate_passphrase() {
|
generate_passphrase() {
|
||||||
local words=(
|
local words=(
|
||||||
"apple" "banana" "cherry" "dragon" "eagle" "forest" "guitar" "harbor"
|
"apple" "banana" "cherry" "dragon" "eagle" "forest" "guitar" "harbor"
|
||||||
@ -348,32 +350,345 @@ generate_passphrase() {
|
|||||||
|
|
||||||
local separators=( "-" "_" "." "+" "=" "*" "~" "^" "@" "#" "%" "&" "!" "?" )
|
local separators=( "-" "_" "." "+" "=" "*" "~" "^" "@" "#" "%" "&" "!" "?" )
|
||||||
|
|
||||||
# Generate a random number between 100 and 999
|
|
||||||
local random_num=$((RANDOM % 900 + 100))
|
local random_num=$((RANDOM % 900 + 100))
|
||||||
|
|
||||||
# Select 3 random words
|
|
||||||
local selected_words=()
|
local selected_words=()
|
||||||
for i in {1..3}; do
|
for i in {1..3}; do
|
||||||
local index=$((RANDOM % ${#words[@]}))
|
local index=$((RANDOM % ${#words[@]}))
|
||||||
selected_words+=(${words[$index]})
|
selected_words+=(${words[$index]})
|
||||||
done
|
done
|
||||||
|
|
||||||
# Select 2 random separators
|
|
||||||
local separator1=${separators[$((RANDOM % ${#separators[@]}))]}
|
local separator1=${separators[$((RANDOM % ${#separators[@]}))]}
|
||||||
local separator2=${separators[$((RANDOM % ${#separators[@]}))]}
|
local separator2=${separators[$((RANDOM % ${#separators[@]}))]}
|
||||||
|
|
||||||
# Combine to form passphrase: word1-word2_word3123
|
|
||||||
echo "${selected_words[0]}${separator1}${selected_words[1]}${separator2}${selected_words[2]}${random_num}"
|
echo "${selected_words[0]}${separator1}${selected_words[1]}${separator2}${selected_words[2]}${random_num}"
|
||||||
}
|
}
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
# PART 6: Authelia Account Management
|
# PART 4: Authentication Management
|
||||||
|
##################################################
|
||||||
|
|
||||||
|
get_auth_status() {
|
||||||
|
local service=$1
|
||||||
|
if grep -q "traefik.http.routers.$service.middlewares=.*authelia-auth" "$COMPOSE_FILE"; then
|
||||||
|
echo "enabled"
|
||||||
|
elif grep -q "traefik.http.routers.$service.middlewares=" "$COMPOSE_FILE"; then
|
||||||
|
echo "disabled"
|
||||||
|
else
|
||||||
|
echo "unknown"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_auth() {
|
||||||
|
local service=$1
|
||||||
|
echo -e "${BLUE}Enabling authentication for $service...${NC}"
|
||||||
|
|
||||||
|
if ! grep -q "container_name: $service" "$COMPOSE_FILE"; then
|
||||||
|
echo -e "${RED}Service $service not found in $COMPOSE_FILE${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local service_start=$(grep -n "container_name: $service" "$COMPOSE_FILE" | cut -d':' -f1)
|
||||||
|
if [ -z "$service_start" ]; then
|
||||||
|
echo -e "${RED}Could not find service $service in $COMPOSE_FILE${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local next_service=$(tail -n +$((service_start+1)) "$COMPOSE_FILE" | grep -n "container_name:" | head -1 | cut -d':' -f1)
|
||||||
|
if [ -n "$next_service" ]; then
|
||||||
|
next_service=$((service_start + next_service))
|
||||||
|
else
|
||||||
|
next_service=$(wc -l < "$COMPOSE_FILE")
|
||||||
|
fi
|
||||||
|
|
||||||
|
local service_section=$(sed -n "${service_start},${next_service}p" "$COMPOSE_FILE")
|
||||||
|
|
||||||
|
if echo "$service_section" | grep -q "traefik.http.routers.$service.middlewares="; then
|
||||||
|
local middlewares_line=$(echo "$service_section" | grep "traefik.http.routers.$service.middlewares=")
|
||||||
|
|
||||||
|
if echo "$middlewares_line" | grep -q "authelia-auth@docker"; then
|
||||||
|
echo -e "${GREEN}Authentication already enabled for $service${NC}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if echo "$middlewares_line" | grep -q "middlewares=$"; then
|
||||||
|
sed -i "s|traefik.http.routers.$service.middlewares=|traefik.http.routers.$service.middlewares=authelia-auth@docker|" "$COMPOSE_FILE"
|
||||||
|
elif echo "$middlewares_line" | grep -q "middlewares=.*@docker"; then
|
||||||
|
sed -i "s|traefik.http.routers.$service.middlewares=\(.*\)@docker|traefik.http.routers.$service.middlewares=\1,authelia-auth@docker|" "$COMPOSE_FILE"
|
||||||
|
else
|
||||||
|
sed -i "s|traefik.http.routers.$service.middlewares=\(.*\)|traefik.http.routers.$service.middlewares=\1,authelia-auth@docker|" "$COMPOSE_FILE"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
local labels_line=$(echo "$service_section" | grep -n "labels:" | cut -d':' -f1)
|
||||||
|
if [ -z "$labels_line" ]; then
|
||||||
|
echo -e "${RED}Could not find labels section for service $service${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local rule_line=$(echo "$service_section" | grep -n "traefik.http.routers.$service.rule=" | cut -d':' -f1)
|
||||||
|
if [ -n "$rule_line" ]; then
|
||||||
|
rule_line=$((service_start + rule_line))
|
||||||
|
sed -i "${rule_line}a \ \ \ \ \ \ - traefik.http.routers.$service.middlewares=authelia-auth@docker" "$COMPOSE_FILE"
|
||||||
|
else
|
||||||
|
echo -e "${RED}Could not find rule line for service $service${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Authentication enabled for $service${NC}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
disable_auth() {
|
||||||
|
local service=$1
|
||||||
|
echo -e "${BLUE}Disabling authentication for $service...${NC}"
|
||||||
|
|
||||||
|
if ! grep -q "container_name: $service" "$COMPOSE_FILE"; then
|
||||||
|
echo -e "${RED}Service $service not found in $COMPOSE_FILE${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q "traefik.http.routers.$service.middlewares=.*authelia-auth@docker" "$COMPOSE_FILE"; then
|
||||||
|
if grep -q "traefik.http.routers.$service.middlewares=authelia-auth@docker" "$COMPOSE_FILE"; then
|
||||||
|
sed -i "s|traefik.http.routers.$service.middlewares=authelia-auth@docker|traefik.http.routers.$service.middlewares=|" "$COMPOSE_FILE"
|
||||||
|
elif grep -q "traefik.http.routers.$service.middlewares=authelia-auth@docker," "$COMPOSE_FILE"; then
|
||||||
|
sed -i "s|traefik.http.routers.$service.middlewares=authelia-auth@docker,|traefik.http.routers.$service.middlewares=|" "$COMPOSE_FILE"
|
||||||
|
elif grep -q "traefik.http.routers.$service.middlewares=.*,authelia-auth@docker" "$COMPOSE_FILE"; then
|
||||||
|
sed -i "s|,authelia-auth@docker||" "$COMPOSE_FILE"
|
||||||
|
elif grep -q "traefik.http.routers.$service.middlewares=.*,authelia-auth@docker,.*" "$COMPOSE_FILE"; then
|
||||||
|
sed -i "s|,authelia-auth@docker,|,|" "$COMPOSE_FILE"
|
||||||
|
else
|
||||||
|
echo -e "${RED}Could not determine how to remove authelia-auth from middlewares for $service${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Authentication disabled for $service${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}Authentication already disabled for $service${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
list_services() {
|
||||||
|
print_header "Services Authentication Status"
|
||||||
|
|
||||||
|
echo -e "${BLUE}Checking services in $COMPOSE_FILE...${NC}"
|
||||||
|
echo -e "${CYAN}SERVICE\t\tAUTH STATUS${NC}"
|
||||||
|
echo -e "${CYAN}-------\t\t-----------${NC}"
|
||||||
|
|
||||||
|
local services=$(grep "container_name:" "$COMPOSE_FILE" | awk '{print $3}')
|
||||||
|
local service_count=0
|
||||||
|
|
||||||
|
for service in $services; do
|
||||||
|
if [[ "$service" == "redis" || "$service" == "authelia" || "$service" == "traefik" || "$service" == "tailscale" || "$service" == "watchtower" || "$service" == "autoheal" || "$service" == "middlewares" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
local status=$(get_auth_status "$service")
|
||||||
|
|
||||||
|
printf "${BOLD}%-20s${NC}" "$service"
|
||||||
|
|
||||||
|
case "$status" in
|
||||||
|
"enabled")
|
||||||
|
echo -e "${GREEN}Enabled${NC}"
|
||||||
|
service_count=$((service_count + 1))
|
||||||
|
;;
|
||||||
|
"disabled")
|
||||||
|
echo -e "${YELLOW}Disabled${NC}"
|
||||||
|
service_count=$((service_count + 1))
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}Unknown${NC}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $service_count -eq 0 ]; then
|
||||||
|
echo -e "${YELLOW}No services found with authentication status.${NC}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup_backups() {
|
||||||
|
print_header "Backup Files Cleanup"
|
||||||
|
|
||||||
|
echo -e "${BLUE}Searching for backup files...${NC}"
|
||||||
|
|
||||||
|
local env_backups=$(find . -maxdepth 1 -name ".env.*.bak" | sort)
|
||||||
|
local compose_backups=$(find . -maxdepth 1 -name "docker-compose.*.bak" | sort)
|
||||||
|
local authelia_backups=$(find ./authelia -maxdepth 1 -name "configuration.*.bak" 2>/dev/null | sort)
|
||||||
|
|
||||||
|
local env_count=$(echo "$env_backups" | grep -c "^")
|
||||||
|
local compose_count=$(echo "$compose_backups" | grep -c "^")
|
||||||
|
local authelia_count=$(echo "$authelia_backups" | grep -c "^")
|
||||||
|
|
||||||
|
echo -e "${CYAN}Found:${NC}"
|
||||||
|
echo -e " - ${CYAN}$env_count .env backup files${NC}"
|
||||||
|
echo -e " - ${CYAN}$compose_count docker-compose.yml backup files${NC}"
|
||||||
|
echo -e " - ${CYAN}$authelia_count Authelia configuration backup files${NC}"
|
||||||
|
|
||||||
|
local total_count=$((env_count + compose_count + authelia_count))
|
||||||
|
|
||||||
|
if [ $total_count -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}No backup files found.${NC}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Do you want to delete all backup files? [y/N]:${NC}"
|
||||||
|
read -r answer
|
||||||
|
if [[ ! "$answer" =~ ^[Yy]$ ]]; then
|
||||||
|
echo -e "${YELLOW}Would you like to keep the most recent backup of each type? [Y/n]:${NC}"
|
||||||
|
read -r keep_recent
|
||||||
|
|
||||||
|
if [[ "$keep_recent" =~ ^[Nn]$ ]]; then
|
||||||
|
echo -e "${RED}Backup cleanup cancelled.${NC}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $env_count -gt 1 ]; then
|
||||||
|
local keep_env=$(echo "$env_backups" | tail -1)
|
||||||
|
local del_env=$(echo "$env_backups" | grep -v "$keep_env")
|
||||||
|
echo -e "${BLUE}Keeping most recent .env backup: ${CYAN}$keep_env${NC}"
|
||||||
|
echo -e "${BLUE}Deleting ${CYAN}$((env_count - 1))${BLUE} older .env backups${NC}"
|
||||||
|
for file in $del_env; do
|
||||||
|
rm "$file"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $compose_count -gt 1 ]; then
|
||||||
|
local keep_compose=$(echo "$compose_backups" | tail -1)
|
||||||
|
local del_compose=$(echo "$compose_backups" | grep -v "$keep_compose")
|
||||||
|
echo -e "${BLUE}Keeping most recent docker-compose.yml backup: ${CYAN}$keep_compose${NC}"
|
||||||
|
echo -e "${BLUE}Deleting ${CYAN}$((compose_count - 1))${BLUE} older docker-compose.yml backups${NC}"
|
||||||
|
for file in $del_compose; do
|
||||||
|
rm "$file"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $authelia_count -gt 1 ]; then
|
||||||
|
local keep_authelia=$(echo "$authelia_backups" | tail -1)
|
||||||
|
local del_authelia=$(echo "$authelia_backups" | grep -v "$keep_authelia")
|
||||||
|
echo -e "${BLUE}Keeping most recent Authelia config backup: ${CYAN}$keep_authelia${NC}"
|
||||||
|
echo -e "${BLUE}Deleting ${CYAN}$((authelia_count - 1))${BLUE} older Authelia config backups${NC}"
|
||||||
|
for file in $del_authelia; do
|
||||||
|
rm "$file"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Cleanup completed with most recent backups retained.${NC}"
|
||||||
|
else
|
||||||
|
for file in $env_backups $compose_backups $authelia_backups; do
|
||||||
|
rm "$file"
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}All $total_count backup files have been deleted.${NC}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
manage_auth() {
|
||||||
|
print_header "Authentication Management"
|
||||||
|
|
||||||
|
echo -e "${BLUE}This tool lets you control which services require authentication${NC}"
|
||||||
|
echo -e "${BLUE}Choose an option:${NC}"
|
||||||
|
echo -e " ${CYAN}1. ${NC}List services and their authentication status"
|
||||||
|
echo -e " ${CYAN}2. ${NC}Enable authentication for a service"
|
||||||
|
echo -e " ${CYAN}3. ${NC}Disable authentication for a service"
|
||||||
|
echo -e " ${CYAN}4. ${NC}Enable authentication for all services"
|
||||||
|
echo -e " ${CYAN}5. ${NC}Disable authentication for all services"
|
||||||
|
echo -e " ${CYAN}6. ${NC}Return to main menu"
|
||||||
|
echo
|
||||||
|
|
||||||
|
local choice
|
||||||
|
while true; do
|
||||||
|
echo -e "${YELLOW}Enter your choice [1-6]: ${NC}"
|
||||||
|
read -r choice
|
||||||
|
|
||||||
|
case "$choice" in
|
||||||
|
1)
|
||||||
|
list_services
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
create_backup "$COMPOSE_FILE" "$COMPOSE_BACKUP"
|
||||||
|
|
||||||
|
echo -e "${BLUE}Enter the service name to enable authentication for:${NC}"
|
||||||
|
read -r service
|
||||||
|
if [ -z "$service" ]; then
|
||||||
|
echo -e "${RED}No service name provided.${NC}"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
enable_auth "$service"
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Remember to restart the stack for changes to take effect:${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose down${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose up -d${NC}"
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
create_backup "$COMPOSE_FILE" "$COMPOSE_BACKUP"
|
||||||
|
|
||||||
|
echo -e "${BLUE}Enter the service name to disable authentication for:${NC}"
|
||||||
|
read -r service
|
||||||
|
if [ -z "$service" ]; then
|
||||||
|
echo -e "${RED}No service name provided.${NC}"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
disable_auth "$service"
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Remember to restart the stack for changes to take effect:${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose down${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose up -d${NC}"
|
||||||
|
;;
|
||||||
|
4)
|
||||||
|
create_backup "$COMPOSE_FILE" "$COMPOSE_BACKUP"
|
||||||
|
|
||||||
|
echo -e "${BLUE}Enabling authentication for all services...${NC}"
|
||||||
|
local services=$(grep "container_name:" "$COMPOSE_FILE" | awk '{print $3}')
|
||||||
|
for service in $services; do
|
||||||
|
if [[ "$service" == "redis" || "$service" == "authelia" || "$service" == "traefik" || "$service" == "tailscale" || "$service" == "watchtower" || "$service" == "autoheal" || "$service" == "middlewares" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
enable_auth "$service"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Remember to restart the stack for changes to take effect:${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose down${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose up -d${NC}"
|
||||||
|
;;
|
||||||
|
5)
|
||||||
|
create_backup "$COMPOSE_FILE" "$COMPOSE_BACKUP"
|
||||||
|
|
||||||
|
echo -e "${BLUE}Disabling authentication for all services...${NC}"
|
||||||
|
local services=$(grep "container_name:" "$COMPOSE_FILE" | awk '{print $3}')
|
||||||
|
for service in $services; do
|
||||||
|
if [[ "$service" == "redis" || "$service" == "authelia" || "$service" == "traefik" || "$service" == "tailscale" || "$service" == "watchtower" || "$service" == "autoheal" || "$service" == "middlewares" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
disable_auth "$service"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Remember to restart the stack for changes to take effect:${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose down${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose up -d${NC}"
|
||||||
|
;;
|
||||||
|
6)
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}Invalid choice. Please try again.${NC}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
##################################################
|
||||||
|
# PART 5: Authelia Account Management
|
||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
manage_authelia_accounts() {
|
manage_authelia_accounts() {
|
||||||
print_header "Authelia Account Management"
|
print_header "Authelia Account Management"
|
||||||
|
|
||||||
# Check if the users_database.yml file exists
|
|
||||||
local users_file="${CONFIG_ROOT:-.}/authelia/users_database.yml"
|
local users_file="${CONFIG_ROOT:-.}/authelia/users_database.yml"
|
||||||
|
|
||||||
if [ ! -f "$users_file" ]; then
|
if [ ! -f "$users_file" ]; then
|
||||||
@ -381,17 +696,14 @@ manage_authelia_accounts() {
|
|||||||
echo -e "${YELLOW}Would you like to create a new users database file? [y/N]:${NC}"
|
echo -e "${YELLOW}Would you like to create a new users database file? [y/N]:${NC}"
|
||||||
read -r answer
|
read -r answer
|
||||||
if [[ "$answer" =~ ^[Yy]$ ]]; then
|
if [[ "$answer" =~ ^[Yy]$ ]]; then
|
||||||
# Create minimal users database file
|
|
||||||
cat > "$users_file" <<EOL
|
cat > "$users_file" <<EOL
|
||||||
# Authelia User Database
|
# Authelia User Database
|
||||||
# Documentation: https://www.authelia.com/configuration/security/authentication/file/
|
# Documentation: https://www.authelia.com/configuration/security/authentication/file/
|
||||||
|
|
||||||
users:
|
users:
|
||||||
# First user is typically considered the admin in access rules
|
|
||||||
admin:
|
admin:
|
||||||
displayname: "Admin User"
|
displayname: "Admin User"
|
||||||
# Replace this hash with one generated for your desired password!
|
password: "$argon2id$v=19$m=102400,t=1,p=8$PBf/L9l3s7LwN6jX/B3tVg$9+q3kL8VAbpWj9Gv9Z6uA5bA4zT1fB2fH3aD5c6b7e8"
|
||||||
password: "$argon2id$v=19$m=102400,t=1,p=8$PBf/L9l3s7LwN6jX/B3tVg$9+q3kL8VAbpWj9Gv9Z6uA5bA4zT1fB2fH3aD5c6b7e8" # Example hash for 'password'
|
|
||||||
email: admin@example.com
|
email: admin@example.com
|
||||||
groups:
|
groups:
|
||||||
- admins
|
- admins
|
||||||
@ -404,23 +716,19 @@ EOL
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Backup users file
|
|
||||||
local backup_file="${users_file}.${TIMESTAMP}.bak"
|
local backup_file="${users_file}.${TIMESTAMP}.bak"
|
||||||
cp "$users_file" "$backup_file"
|
cp "$users_file" "$backup_file"
|
||||||
echo -e "${BLUE}Backed up users database to ${backup_file}${NC}"
|
echo -e "${BLUE}Backed up users database to ${backup_file}${NC}"
|
||||||
|
|
||||||
# Main loop for adding users
|
|
||||||
while true; do
|
while true; do
|
||||||
echo -e "\n${CYAN}${BOLD}Add Authelia User${NC}"
|
echo -e "\n${CYAN}${BOLD}Add Authelia User${NC}"
|
||||||
echo -e "${BLUE}Enter a username (or press Enter to finish):${NC}"
|
echo -e "${BLUE}Enter a username (or press Enter to finish):${NC}"
|
||||||
read -r username
|
read -r username
|
||||||
|
|
||||||
# Exit if no username provided
|
|
||||||
if [ -z "$username" ]; then
|
if [ -z "$username" ]; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if username already exists
|
|
||||||
if grep -q "^[[:space:]]*${username}:" "$users_file"; then
|
if grep -q "^[[:space:]]*${username}:" "$users_file"; then
|
||||||
echo -e "${YELLOW}Warning: User '${username}' already exists.${NC}"
|
echo -e "${YELLOW}Warning: User '${username}' already exists.${NC}"
|
||||||
echo -e "${YELLOW}Would you like to update this user? [y/N]:${NC}"
|
echo -e "${YELLOW}Would you like to update this user? [y/N]:${NC}"
|
||||||
@ -431,42 +739,36 @@ EOL
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get display name
|
|
||||||
echo -e "${BLUE}Enter display name for ${username}:${NC}"
|
echo -e "${BLUE}Enter display name for ${username}:${NC}"
|
||||||
read -r displayname
|
read -r displayname
|
||||||
if [ -z "$displayname" ]; then
|
if [ -z "$displayname" ]; then
|
||||||
displayname="$username" # Use username as display name if not provided
|
displayname="$username"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get email
|
|
||||||
echo -e "${BLUE}Enter email for ${username}:${NC}"
|
echo -e "${BLUE}Enter email for ${username}:${NC}"
|
||||||
read -r email
|
read -r email
|
||||||
if [ -z "$email" ]; then
|
if [ -z "$email" ]; then
|
||||||
email="${username}@example.com" # Use default email if not provided
|
email="${username}@example.com"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Groups
|
|
||||||
echo -e "${BLUE}Select group(s) for ${username} (comma-separated, default: users):${NC}"
|
echo -e "${BLUE}Select group(s) for ${username} (comma-separated, default: users):${NC}"
|
||||||
echo -e "${CYAN}Available groups: admins, users${NC}"
|
echo -e "${CYAN}Available groups: admins, users${NC}"
|
||||||
read -r groups
|
read -r groups
|
||||||
if [ -z "$groups" ]; then
|
if [ -z "$groups" ]; then
|
||||||
groups="users" # Default group
|
groups="users"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Convert comma-separated groups to YAML format
|
|
||||||
IFS=',' read -ra group_array <<< "$groups"
|
IFS=',' read -ra group_array <<< "$groups"
|
||||||
formatted_groups=""
|
formatted_groups=""
|
||||||
for group in "${group_array[@]}"; do
|
for group in "${group_array[@]}"; do
|
||||||
formatted_groups+=" - $(echo $group | xargs)\n"
|
formatted_groups+=" - $(echo $group | xargs)\n"
|
||||||
done
|
done
|
||||||
|
|
||||||
# Generate a secure passphrase
|
|
||||||
generated_passphrase=$(generate_passphrase)
|
generated_passphrase=$(generate_passphrase)
|
||||||
echo -e "${GREEN}Generated passphrase: ${BOLD}${generated_passphrase}${NC}"
|
echo -e "${GREEN}Generated passphrase: ${BOLD}${generated_passphrase}${NC}"
|
||||||
echo -e "${YELLOW}Do you want to use this passphrase? [Y/n]:${NC}"
|
echo -e "${YELLOW}Do you want to use this passphrase? [Y/n]:${NC}"
|
||||||
read -r use_generated
|
read -r use_generated
|
||||||
|
|
||||||
# If user doesn't want the generated passphrase, ask for a custom one
|
|
||||||
if [[ "$use_generated" =~ ^[Nn]$ ]]; then
|
if [[ "$use_generated" =~ ^[Nn]$ ]]; then
|
||||||
echo -e "${BLUE}Enter a custom password for ${username}:${NC}"
|
echo -e "${BLUE}Enter a custom password for ${username}:${NC}"
|
||||||
read -rs password
|
read -rs password
|
||||||
@ -480,7 +782,6 @@ EOL
|
|||||||
|
|
||||||
echo -e "${CYAN}Generating password hash...${NC}"
|
echo -e "${CYAN}Generating password hash...${NC}"
|
||||||
|
|
||||||
# Generate password hash using Docker Compose
|
|
||||||
password_hash=$(docker compose run --rm authelia authelia crypto hash generate argon2 --password "$password" 2>/dev/null)
|
password_hash=$(docker compose run --rm authelia authelia crypto hash generate argon2 --password "$password" 2>/dev/null)
|
||||||
|
|
||||||
if [ -z "$password_hash" ]; then
|
if [ -z "$password_hash" ]; then
|
||||||
@ -494,10 +795,8 @@ EOL
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Strip the "Digest: " prefix if present
|
|
||||||
password_hash=$(echo "$password_hash" | sed 's/^Digest: //')
|
password_hash=$(echo "$password_hash" | sed 's/^Digest: //')
|
||||||
|
|
||||||
# Verify hash format
|
|
||||||
if [[ ! "$password_hash" =~ ^\$argon2id.*$ ]]; then
|
if [[ ! "$password_hash" =~ ^\$argon2id.*$ ]]; then
|
||||||
echo -e "${RED}Error: Generated hash does not have the expected format. Actual value:${NC}"
|
echo -e "${RED}Error: Generated hash does not have the expected format. Actual value:${NC}"
|
||||||
echo -e "${YELLOW}$password_hash${NC}"
|
echo -e "${YELLOW}$password_hash${NC}"
|
||||||
@ -507,15 +806,11 @@ EOL
|
|||||||
|
|
||||||
echo -e "${GREEN}Password hash generated successfully.${NC}"
|
echo -e "${GREEN}Password hash generated successfully.${NC}"
|
||||||
|
|
||||||
# Check if user already exists in the file and update
|
|
||||||
if grep -q "^[[:space:]]*${username}:" "$users_file"; then
|
if grep -q "^[[:space:]]*${username}:" "$users_file"; then
|
||||||
# User exists, update entry by commenting out old lines and adding new ones
|
|
||||||
sed -i "/^[[:space:]]*${username}:/,/^[[:space:]]*[a-zA-Z0-9_-]\+:/ s/^/# UPDATED: /" "$users_file"
|
sed -i "/^[[:space:]]*${username}:/,/^[[:space:]]*[a-zA-Z0-9_-]\+:/ s/^/# UPDATED: /" "$users_file"
|
||||||
# Remove the last comment marker if it matched a different user
|
|
||||||
sed -i "0,/^# UPDATED: [[:space:]]*[a-zA-Z0-9_-]\+:/ s/^# UPDATED: //" "$users_file"
|
sed -i "0,/^# UPDATED: [[:space:]]*[a-zA-Z0-9_-]\+:/ s/^# UPDATED: //" "$users_file"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Add user to the file
|
|
||||||
cat >> "$users_file" <<EOL
|
cat >> "$users_file" <<EOL
|
||||||
${username}:
|
${username}:
|
||||||
displayname: "${displayname}"
|
displayname: "${displayname}"
|
||||||
@ -534,7 +829,6 @@ EOL
|
|||||||
echo -e "${BLUE}Users file updated: ${users_file}${NC}"
|
echo -e "${BLUE}Users file updated: ${users_file}${NC}"
|
||||||
echo -e "${BLUE}Backup saved as: ${backup_file}${NC}"
|
echo -e "${BLUE}Backup saved as: ${backup_file}${NC}"
|
||||||
|
|
||||||
# Ask if user wants to restart Authelia
|
|
||||||
echo -e "${YELLOW}Would you like to restart Authelia to apply changes? [y/N]:${NC}"
|
echo -e "${YELLOW}Would you like to restart Authelia to apply changes? [y/N]:${NC}"
|
||||||
read -r restart
|
read -r restart
|
||||||
if [[ "$restart" =~ ^[Yy]$ ]]; then
|
if [[ "$restart" =~ ^[Yy]$ ]]; then
|
||||||
@ -553,7 +847,103 @@ EOL
|
|||||||
# MAIN SCRIPT
|
# MAIN SCRIPT
|
||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
# Display main menu
|
if [ $# -gt 0 ]; then
|
||||||
|
case "$1" in
|
||||||
|
"list-auth")
|
||||||
|
list_services
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
"enable-auth")
|
||||||
|
if [ -z "$2" ]; then
|
||||||
|
echo -e "${RED}Error: No service specified${NC}"
|
||||||
|
echo -e "Usage: $0 enable-auth <service>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
create_backup "$COMPOSE_FILE" "$COMPOSE_BACKUP"
|
||||||
|
enable_auth "$2"
|
||||||
|
|
||||||
|
echo -e "\n${YELLOW}Remember to restart the stack for changes to take effect:${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose down${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose up -d${NC}"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
"disable-auth")
|
||||||
|
if [ -z "$2" ]; then
|
||||||
|
echo -e "${RED}Error: No service specified${NC}"
|
||||||
|
echo -e "Usage: $0 disable-auth <service>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
create_backup "$COMPOSE_FILE" "$COMPOSE_BACKUP"
|
||||||
|
disable_auth "$2"
|
||||||
|
|
||||||
|
echo -e "\n${YELLOW}Remember to restart the stack for changes to take effect:${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose down${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose up -d${NC}"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
"enable-all-auth")
|
||||||
|
create_backup "$COMPOSE_FILE" "$COMPOSE_BACKUP"
|
||||||
|
|
||||||
|
echo -e "${BLUE}Enabling authentication for all services...${NC}"
|
||||||
|
local services=$(grep "container_name:" "$COMPOSE_FILE" | awk '{print $3}')
|
||||||
|
for service in $services; do
|
||||||
|
if [[ "$service" == "redis" || "$service" == "authelia" || "$service" == "traefik" || "$service" == "tailscale" || "$service" == "watchtower" || "$service" == "autoheal" || "$service" == "middlewares" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
enable_auth "$service"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "\n${YELLOW}Remember to restart the stack for changes to take effect:${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose down${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose up -d${NC}"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
"disable-all-auth")
|
||||||
|
create_backup "$COMPOSE_FILE" "$COMPOSE_BACKUP"
|
||||||
|
|
||||||
|
echo -e "${BLUE}Disabling authentication for all services...${NC}"
|
||||||
|
local services=$(grep "container_name:" "$COMPOSE_FILE" | awk '{print $3}')
|
||||||
|
for service in $services; do
|
||||||
|
if [[ "$service" == "redis" || "$service" == "authelia" || "$service" == "traefik" || "$service" == "tailscale" || "$service" == "watchtower" || "$service" == "autoheal" || "$service" == "middlewares" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
disable_auth "$service"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "\n${YELLOW}Remember to restart the stack for changes to take effect:${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose down${NC}"
|
||||||
|
echo -e " ${CYAN}docker compose up -d${NC}"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
"cleanup")
|
||||||
|
cleanup_backups
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
"help")
|
||||||
|
print_header "Docker Compose NAS - Setup Tool"
|
||||||
|
echo -e "${BLUE}Usage: $0 [command] [arguments]${NC}"
|
||||||
|
echo -e "${BLUE}Commands:${NC}"
|
||||||
|
echo -e " ${CYAN}list-auth${NC} List authentication status for all services"
|
||||||
|
echo -e " ${CYAN}enable-auth <service>${NC} Enable authentication for a specific service"
|
||||||
|
echo -e " ${CYAN}disable-auth <service>${NC} Disable authentication for a specific service"
|
||||||
|
echo -e " ${CYAN}enable-all-auth${NC} Enable authentication for all services"
|
||||||
|
echo -e " ${CYAN}disable-all-auth${NC} Disable authentication for all services"
|
||||||
|
echo -e " ${CYAN}cleanup${NC} Clean up backup files"
|
||||||
|
echo -e " ${CYAN}help${NC} Show this help message"
|
||||||
|
echo -e ""
|
||||||
|
echo -e "${BLUE}Without arguments, the script will start in interactive mode.${NC}"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}Unknown command: $1${NC}"
|
||||||
|
echo -e "${BLUE}Run '$0 help' for usage information${NC}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
print_header "Docker Compose NAS - Setup Tool"
|
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}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 "${BLUE}Choose one or more options to run:${NC}"
|
||||||
@ -561,13 +951,15 @@ echo -e " ${CYAN}1. ${NC}Update .env file from .env.example"
|
|||||||
echo -e " ${CYAN}2. ${NC}Update Authelia configuration"
|
echo -e " ${CYAN}2. ${NC}Update Authelia configuration"
|
||||||
echo -e " ${CYAN}3. ${NC}Update service configurations"
|
echo -e " ${CYAN}3. ${NC}Update service configurations"
|
||||||
echo -e " ${CYAN}4. ${NC}Manage Authelia accounts"
|
echo -e " ${CYAN}4. ${NC}Manage Authelia accounts"
|
||||||
echo -e " ${CYAN}5. ${NC}Run ALL updates"
|
echo -e " ${CYAN}5. ${NC}Manage service authentication"
|
||||||
|
echo -e " ${CYAN}6. ${NC}Clean up backup files"
|
||||||
|
echo -e " ${CYAN}7. ${NC}Run ALL updates"
|
||||||
echo -e " ${CYAN}q. ${NC}Quit"
|
echo -e " ${CYAN}q. ${NC}Quit"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
CHOICE="0"
|
CHOICE="0"
|
||||||
while [[ "$CHOICE" != "q" ]]; do
|
while [[ "$CHOICE" != "q" ]]; do
|
||||||
echo -e "${YELLOW}Enter your choice [1-5 or q to quit]: ${NC}"
|
echo -e "${YELLOW}Enter your choice [1-7 or q to quit]: ${NC}"
|
||||||
read -r CHOICE
|
read -r CHOICE
|
||||||
|
|
||||||
case "$CHOICE" in
|
case "$CHOICE" in
|
||||||
@ -575,12 +967,14 @@ while [[ "$CHOICE" != "q" ]]; do
|
|||||||
2) update_authelia_config ;;
|
2) update_authelia_config ;;
|
||||||
3) update_service_configs ;;
|
3) update_service_configs ;;
|
||||||
4) manage_authelia_accounts ;;
|
4) manage_authelia_accounts ;;
|
||||||
5)
|
5) manage_auth ;;
|
||||||
|
6) cleanup_backups ;;
|
||||||
|
7)
|
||||||
update_env_file
|
update_env_file
|
||||||
update_authelia_config
|
update_authelia_config
|
||||||
update_service_configs
|
update_service_configs
|
||||||
manage_authelia_accounts
|
manage_authelia_accounts
|
||||||
CHOICE="q" # Exit after running all
|
CHOICE="q"
|
||||||
;;
|
;;
|
||||||
q|Q)
|
q|Q)
|
||||||
echo -e "${GREEN}Exiting setup tool.${NC}"
|
echo -e "${GREEN}Exiting setup tool.${NC}"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user