88551536e6
Amp-Thread-ID: https://ampcode.com/threads/T-019cc404-c628-759e-a50b-f5eeea35b91f Co-authored-by: Amp <amp@ampcode.com>
810 lines
24 KiB
Bash
810 lines
24 KiB
Bash
#!/bin/bash
|
|
################################################################################
|
|
# Script Name: add-http-auth.sh
|
|
# Version: 3.0
|
|
# Description: Add HTTP Basic Auth to Prometheus stack reverse proxies
|
|
# Supports both nginx and Apache — auto-detects which is in use.
|
|
# Uses non-destructive include snippets to preserve existing
|
|
# HTTPS/certbot configs.
|
|
#
|
|
# Author: Phil Connor
|
|
# Contact: contact@mylinux.work
|
|
# Website: https://mylinux.work
|
|
# License: MIT
|
|
#
|
|
# Supported Services:
|
|
# - Prometheus (port 9090)
|
|
# - Alertmanager (port 9093)
|
|
# - Mimir (port 9009) — optionally protects /api/v1/push
|
|
# - Loki (port 3100) — optionally protects /loki/api/v1/push
|
|
#
|
|
# Supported Web Servers:
|
|
# - nginx — inserts 'include' snippets into location blocks
|
|
# - Apache — inserts 'Include' snippets into <Location> blocks
|
|
#
|
|
# Usage:
|
|
# sudo ./add-http-auth.sh
|
|
# sudo ./add-http-auth.sh --remove
|
|
# sudo ./add-http-auth.sh --status
|
|
#
|
|
################################################################################
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_VERSION="3.0"
|
|
BACKUP_DIR="/var/backups/http-auth"
|
|
|
|
# Detected at runtime
|
|
WEB_SERVER="" # "nginx" or "apache"
|
|
CONFIG_DIR="" # where vhost configs live
|
|
SNIPPET_DIR="" # where auth snippets go
|
|
AUTH_DIR="" # where htpasswd files go
|
|
WEB_USER="" # www-data, nginx, apache, etc.
|
|
SERVICE_NAME="" # systemd service name
|
|
|
|
# Service definitions: name|nginx_config|apache_config|port
|
|
SERVICES=(
|
|
"prometheus|prometheus.conf|prometheus.conf|9090"
|
|
"alertmanager|alerts.conf|alerts.conf|9093"
|
|
"mimir|mimir.conf|mimir.conf|9009"
|
|
"loki|loki.conf|loki.conf|3100"
|
|
)
|
|
|
|
# ============================================================================
|
|
# HELPER FUNCTIONS
|
|
# ============================================================================
|
|
|
|
show_usage() {
|
|
cat <<EOF
|
|
Usage: $0 [OPTIONS]
|
|
|
|
Add HTTP Basic Auth to Prometheus stack reverse proxies (v${SCRIPT_VERSION}).
|
|
Supports both nginx and Apache — auto-detects which is in use.
|
|
|
|
OPTIONS:
|
|
--remove Remove auth from all services (restore backups)
|
|
--status Show current auth status for each service
|
|
-h, --help Show this help
|
|
|
|
EXAMPLES:
|
|
$0 # Interactive setup
|
|
$0 --status # Check which services have auth enabled
|
|
$0 --remove # Remove auth and restore original configs
|
|
|
|
EOF
|
|
exit 0
|
|
}
|
|
|
|
die() {
|
|
echo "ERROR: $1" >&2
|
|
exit 1
|
|
}
|
|
|
|
warn() {
|
|
echo "WARNING: $1" >&2
|
|
}
|
|
|
|
# Get the config filename for the current web server
|
|
get_config_file() {
|
|
local entry="$1"
|
|
local name nginx_conf apache_conf port
|
|
IFS='|' read -r name nginx_conf apache_conf port <<< "$entry"
|
|
if [ "$WEB_SERVER" = "nginx" ]; then
|
|
echo "$nginx_conf"
|
|
else
|
|
echo "$apache_conf"
|
|
fi
|
|
}
|
|
|
|
get_service_name() {
|
|
local entry="$1"
|
|
IFS='|' read -r name _ _ _ <<< "$entry"
|
|
echo "$name"
|
|
}
|
|
|
|
get_service_port() {
|
|
local entry="$1"
|
|
IFS='|' read -r _ _ _ port <<< "$entry"
|
|
echo "$port"
|
|
}
|
|
|
|
# ============================================================================
|
|
# WEB SERVER DETECTION
|
|
# ============================================================================
|
|
|
|
detect_web_server() {
|
|
local has_nginx=false
|
|
local has_apache=false
|
|
|
|
if command -v nginx &>/dev/null && systemctl is-active --quiet nginx 2>/dev/null; then
|
|
has_nginx=true
|
|
fi
|
|
|
|
if command -v apache2ctl &>/dev/null && systemctl is-active --quiet apache2 2>/dev/null; then
|
|
has_apache=true
|
|
elif command -v httpd &>/dev/null && systemctl is-active --quiet httpd 2>/dev/null; then
|
|
has_apache=true
|
|
fi
|
|
|
|
if [ "$has_nginx" = true ] && [ "$has_apache" = true ]; then
|
|
echo ""
|
|
echo "Both nginx and Apache detected. Which are you using for reverse proxies?"
|
|
echo " 1) nginx"
|
|
echo " 2) Apache"
|
|
read -r -p "Select [1]: " choice
|
|
case "${choice:-1}" in
|
|
2) WEB_SERVER="apache" ;;
|
|
*) WEB_SERVER="nginx" ;;
|
|
esac
|
|
elif [ "$has_nginx" = true ]; then
|
|
WEB_SERVER="nginx"
|
|
elif [ "$has_apache" = true ]; then
|
|
WEB_SERVER="apache"
|
|
else
|
|
die "Neither nginx nor Apache detected as running"
|
|
fi
|
|
|
|
echo " Detected web server: ${WEB_SERVER}"
|
|
}
|
|
|
|
# Set paths based on detected web server
|
|
configure_paths() {
|
|
if [ "$WEB_SERVER" = "nginx" ]; then
|
|
if [ -d "/etc/nginx/sites-available" ]; then
|
|
CONFIG_DIR="/etc/nginx/sites-available"
|
|
elif [ -d "/etc/nginx/conf.d" ]; then
|
|
CONFIG_DIR="/etc/nginx/conf.d"
|
|
else
|
|
die "nginx config directory not found"
|
|
fi
|
|
SNIPPET_DIR="/etc/nginx/snippets"
|
|
AUTH_DIR="/etc/nginx/auth"
|
|
SERVICE_NAME="nginx"
|
|
|
|
if id "www-data" &>/dev/null; then
|
|
WEB_USER="www-data"
|
|
elif id "nginx" &>/dev/null; then
|
|
WEB_USER="nginx"
|
|
else
|
|
WEB_USER="root"
|
|
fi
|
|
else
|
|
# Apache
|
|
if [ -d "/etc/apache2/sites-available" ]; then
|
|
CONFIG_DIR="/etc/apache2/sites-available"
|
|
SNIPPET_DIR="/etc/apache2/conf-available"
|
|
SERVICE_NAME="apache2"
|
|
elif [ -d "/etc/httpd/conf.d" ]; then
|
|
CONFIG_DIR="/etc/httpd/conf.d"
|
|
SNIPPET_DIR="/etc/httpd/conf.d"
|
|
SERVICE_NAME="httpd"
|
|
else
|
|
die "Apache config directory not found"
|
|
fi
|
|
AUTH_DIR="/etc/httpd/auth"
|
|
[ -d "/etc/apache2" ] && AUTH_DIR="/etc/apache2/auth"
|
|
|
|
if id "www-data" &>/dev/null; then
|
|
WEB_USER="www-data"
|
|
elif id "apache" &>/dev/null; then
|
|
WEB_USER="apache"
|
|
else
|
|
WEB_USER="root"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# HTTPS DETECTION
|
|
# ============================================================================
|
|
|
|
has_https() {
|
|
local config_file="$1"
|
|
if [ "$WEB_SERVER" = "nginx" ]; then
|
|
grep -qE 'listen\s+.*443\s+ssl' "$config_file" 2>/dev/null
|
|
else
|
|
grep -qE 'SSLEngine\s+on|<VirtualHost\s+\*:443' "$config_file" 2>/dev/null
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# AUTH SNIPPET CHECK
|
|
# ============================================================================
|
|
|
|
has_auth_snippet() {
|
|
local config_file="$1"
|
|
local service="$2"
|
|
if [ "$WEB_SERVER" = "nginx" ]; then
|
|
grep -qF "include ${SNIPPET_DIR}/auth-${service}.conf" "$config_file" 2>/dev/null
|
|
else
|
|
grep -qF "Include ${SNIPPET_DIR}/auth-${service}.conf" "$config_file" 2>/dev/null
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# SETUP FUNCTIONS
|
|
# ============================================================================
|
|
|
|
install_htpasswd() {
|
|
if command -v htpasswd &>/dev/null; then
|
|
return 0
|
|
fi
|
|
|
|
echo "Installing htpasswd..."
|
|
if command -v apt-get &>/dev/null; then
|
|
apt-get -y install apache2-utils
|
|
elif command -v dnf &>/dev/null; then
|
|
dnf -y install httpd-tools
|
|
elif command -v yum &>/dev/null; then
|
|
yum -y install httpd-tools
|
|
else
|
|
die "Cannot install htpasswd — install apache2-utils or httpd-tools manually"
|
|
fi
|
|
}
|
|
|
|
backup_config() {
|
|
local config_file="$1"
|
|
local timestamp
|
|
timestamp=$(date +%F_%H%M%S)
|
|
local backup_path="${BACKUP_DIR}/${timestamp}"
|
|
|
|
mkdir -p "$backup_path"
|
|
cp "$config_file" "$backup_path/"
|
|
echo " Backed up to ${backup_path}/$(basename "$config_file")"
|
|
}
|
|
|
|
# ============================================================================
|
|
# NGINX-SPECIFIC FUNCTIONS
|
|
# ============================================================================
|
|
|
|
nginx_create_snippet() {
|
|
local service="$1"
|
|
local display_name="$2"
|
|
|
|
cat > "${SNIPPET_DIR}/auth-${service}.conf" <<EOF
|
|
# Auth snippet for ${display_name} — managed by add-http-auth.sh
|
|
auth_basic "${display_name} - Authentication Required";
|
|
auth_basic_user_file ${AUTH_DIR}/.htpasswd-${service};
|
|
EOF
|
|
|
|
echo " Created ${SNIPPET_DIR}/auth-${service}.conf"
|
|
}
|
|
|
|
nginx_insert_auth() {
|
|
local config_file="$1"
|
|
local service="$2"
|
|
local include_line=" include ${SNIPPET_DIR}/auth-${service}.conf;"
|
|
|
|
if has_auth_snippet "$config_file" "$service"; then
|
|
echo " Auth already configured in $(basename "$config_file") — skipping"
|
|
return 0
|
|
fi
|
|
|
|
backup_config "$config_file"
|
|
|
|
local temp_file
|
|
temp_file=$(mktemp)
|
|
|
|
awk -v inc="$include_line" '
|
|
/location \/ \{/ && !done {
|
|
print
|
|
print inc
|
|
done = 1
|
|
next
|
|
}
|
|
{ print }
|
|
' "$config_file" > "$temp_file"
|
|
|
|
mv "$temp_file" "$config_file"
|
|
echo " Inserted auth include into $(basename "$config_file")"
|
|
}
|
|
|
|
nginx_insert_push_auth() {
|
|
local config_file="$1"
|
|
local service="$2"
|
|
|
|
if grep -q "location.*/api/v1/push" "$config_file" && \
|
|
! grep -A2 "location.*/api/v1/push" "$config_file" | grep -qF "auth-${service}.conf"; then
|
|
local temp_file
|
|
temp_file=$(mktemp)
|
|
local include_line=" include ${SNIPPET_DIR}/auth-${service}.conf;"
|
|
awk -v inc="$include_line" '
|
|
/location.*\/api\/v1\/push/ && !push_done {
|
|
print
|
|
print inc
|
|
push_done = 1
|
|
next
|
|
}
|
|
{ print }
|
|
' "$config_file" > "$temp_file"
|
|
mv "$temp_file" "$config_file"
|
|
echo " Protected push endpoint with auth"
|
|
fi
|
|
}
|
|
|
|
nginx_remove_auth() {
|
|
local config_file="$1"
|
|
local service="$2"
|
|
|
|
local temp_file
|
|
temp_file=$(mktemp)
|
|
grep -vF "include ${SNIPPET_DIR}/auth-${service}.conf" "$config_file" > "$temp_file"
|
|
mv "$temp_file" "$config_file"
|
|
}
|
|
|
|
nginx_test_config() {
|
|
nginx -t 2>&1
|
|
}
|
|
|
|
# ============================================================================
|
|
# APACHE-SPECIFIC FUNCTIONS
|
|
# ============================================================================
|
|
|
|
apache_create_snippet() {
|
|
local service="$1"
|
|
local display_name="$2"
|
|
|
|
cat > "${SNIPPET_DIR}/auth-${service}.conf" <<EOF
|
|
# Auth snippet for ${display_name} — managed by add-http-auth.sh
|
|
AuthType Basic
|
|
AuthName "${display_name} - Authentication Required"
|
|
AuthUserFile ${AUTH_DIR}/.htpasswd-${service}
|
|
Require valid-user
|
|
EOF
|
|
|
|
echo " Created ${SNIPPET_DIR}/auth-${service}.conf"
|
|
}
|
|
|
|
apache_insert_auth() {
|
|
local config_file="$1"
|
|
local service="$2"
|
|
local include_line=" Include ${SNIPPET_DIR}/auth-${service}.conf"
|
|
|
|
if has_auth_snippet "$config_file" "$service"; then
|
|
echo " Auth already configured in $(basename "$config_file") — skipping"
|
|
return 0
|
|
fi
|
|
|
|
backup_config "$config_file"
|
|
|
|
# Check if config uses <Location /> or <Proxy *>
|
|
local temp_file
|
|
temp_file=$(mktemp)
|
|
|
|
if grep -qE '<Location\s+/\s*>' "$config_file"; then
|
|
# Insert after <Location /> opening tag
|
|
awk -v inc="$include_line" '
|
|
/<Location\s+\/\s*>/ && !done {
|
|
print
|
|
print inc
|
|
done = 1
|
|
next
|
|
}
|
|
{ print }
|
|
' "$config_file" > "$temp_file"
|
|
elif grep -qE '<Proxy\s+' "$config_file"; then
|
|
# Insert inside <VirtualHost> before the first ProxyPass
|
|
awk -v inc="$include_line" -v sdir="${SNIPPET_DIR}" -v svc="$service" '
|
|
/ProxyPass\s/ && !done {
|
|
# Add a Location block with auth before ProxyPass
|
|
print " <Location />"
|
|
print inc
|
|
print " </Location>"
|
|
print ""
|
|
done = 1
|
|
}
|
|
{ print }
|
|
' "$config_file" > "$temp_file"
|
|
else
|
|
# No Location or Proxy block found — add a Location block before </VirtualHost>
|
|
awk -v inc="$include_line" '
|
|
/<\/VirtualHost>/ && !done {
|
|
print ""
|
|
print " <Location />"
|
|
print inc
|
|
print " </Location>"
|
|
print ""
|
|
done = 1
|
|
}
|
|
{ print }
|
|
' "$config_file" > "$temp_file"
|
|
fi
|
|
|
|
mv "$temp_file" "$config_file"
|
|
echo " Inserted auth into $(basename "$config_file")"
|
|
}
|
|
|
|
apache_insert_push_auth() {
|
|
local config_file="$1"
|
|
local service="$2"
|
|
local push_path=""
|
|
|
|
if [ "$service" = "mimir" ]; then
|
|
push_path="/api/v1/push"
|
|
elif [ "$service" = "loki" ]; then
|
|
push_path="/loki/api/v1/push"
|
|
else
|
|
return 0
|
|
fi
|
|
|
|
# Check if there's already a Location block for the push path
|
|
if grep -qF "$push_path" "$config_file" && \
|
|
! grep -A3 "$push_path" "$config_file" | grep -qF "auth-${service}.conf"; then
|
|
backup_config "$config_file"
|
|
local temp_file
|
|
temp_file=$(mktemp)
|
|
local include_line=" Include ${SNIPPET_DIR}/auth-${service}.conf"
|
|
awk -v path="$push_path" -v inc="$include_line" '
|
|
$0 ~ path && /Location/ && !push_done {
|
|
print
|
|
print inc
|
|
push_done = 1
|
|
next
|
|
}
|
|
{ print }
|
|
' "$config_file" > "$temp_file"
|
|
mv "$temp_file" "$config_file"
|
|
echo " Protected push endpoint with auth"
|
|
fi
|
|
}
|
|
|
|
apache_remove_auth() {
|
|
local config_file="$1"
|
|
local service="$2"
|
|
|
|
local temp_file
|
|
temp_file=$(mktemp)
|
|
grep -vF "Include ${SNIPPET_DIR}/auth-${service}.conf" "$config_file" > "$temp_file"
|
|
mv "$temp_file" "$config_file"
|
|
}
|
|
|
|
apache_test_config() {
|
|
if command -v apache2ctl &>/dev/null; then
|
|
apache2ctl configtest 2>&1
|
|
else
|
|
httpd -t 2>&1
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# GENERIC WRAPPERS (dispatch to nginx or apache functions)
|
|
# ============================================================================
|
|
|
|
create_snippet() {
|
|
if [ "$WEB_SERVER" = "nginx" ]; then
|
|
nginx_create_snippet "$@"
|
|
else
|
|
apache_create_snippet "$@"
|
|
fi
|
|
}
|
|
|
|
insert_auth() {
|
|
if [ "$WEB_SERVER" = "nginx" ]; then
|
|
nginx_insert_auth "$@"
|
|
else
|
|
apache_insert_auth "$@"
|
|
fi
|
|
}
|
|
|
|
insert_push_auth() {
|
|
if [ "$WEB_SERVER" = "nginx" ]; then
|
|
nginx_insert_push_auth "$@"
|
|
else
|
|
apache_insert_push_auth "$@"
|
|
fi
|
|
}
|
|
|
|
remove_auth_from_config() {
|
|
if [ "$WEB_SERVER" = "nginx" ]; then
|
|
nginx_remove_auth "$@"
|
|
else
|
|
apache_remove_auth "$@"
|
|
fi
|
|
}
|
|
|
|
test_config() {
|
|
if [ "$WEB_SERVER" = "nginx" ]; then
|
|
nginx_test_config
|
|
else
|
|
apache_test_config
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# STATUS & REMOVE
|
|
# ============================================================================
|
|
|
|
show_status() {
|
|
detect_web_server
|
|
configure_paths
|
|
|
|
echo ""
|
|
echo "=========================================="
|
|
echo "HTTP Basic Auth Status (${WEB_SERVER})"
|
|
echo "=========================================="
|
|
echo ""
|
|
|
|
for entry in "${SERVICES[@]}"; do
|
|
local name config_file
|
|
name=$(get_service_name "$entry")
|
|
config_file=$(get_config_file "$entry")
|
|
local display_name
|
|
display_name="${name^}"
|
|
local full_path="${CONFIG_DIR}/${config_file}"
|
|
|
|
printf " %-14s " "${display_name}:"
|
|
|
|
if [ ! -f "$full_path" ]; then
|
|
echo "no config found"
|
|
continue
|
|
fi
|
|
|
|
if has_auth_snippet "$full_path" "$name"; then
|
|
if [ -f "${AUTH_DIR}/.htpasswd-${name}" ]; then
|
|
echo "ENABLED (htpasswd + snippet)"
|
|
else
|
|
echo "BROKEN (snippet exists but htpasswd file missing)"
|
|
fi
|
|
else
|
|
echo "not configured"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "Web server: ${WEB_SERVER}"
|
|
echo "Config dir: ${CONFIG_DIR}"
|
|
echo "Snippet dir: ${SNIPPET_DIR}"
|
|
echo "Auth dir: ${AUTH_DIR}"
|
|
echo "Backup dir: ${BACKUP_DIR}"
|
|
echo ""
|
|
}
|
|
|
|
do_remove() {
|
|
detect_web_server
|
|
configure_paths
|
|
|
|
echo ""
|
|
echo "Removing HTTP Basic Auth from all services (${WEB_SERVER})..."
|
|
echo ""
|
|
|
|
for entry in "${SERVICES[@]}"; do
|
|
local name config_file
|
|
name=$(get_service_name "$entry")
|
|
config_file=$(get_config_file "$entry")
|
|
local full_path="${CONFIG_DIR}/${config_file}"
|
|
|
|
if [ ! -f "$full_path" ]; then
|
|
continue
|
|
fi
|
|
|
|
if has_auth_snippet "$full_path" "$name"; then
|
|
backup_config "$full_path"
|
|
remove_auth_from_config "$full_path" "$name"
|
|
echo " Removed auth from ${config_file}"
|
|
fi
|
|
|
|
rm -f "${SNIPPET_DIR}/auth-${name}.conf"
|
|
done
|
|
|
|
echo ""
|
|
echo "Testing ${WEB_SERVER} configuration..."
|
|
if test_config; then
|
|
systemctl reload "$SERVICE_NAME"
|
|
echo ""
|
|
echo "Auth removed and ${WEB_SERVER} reloaded."
|
|
else
|
|
warn "${WEB_SERVER} config test failed — check your config manually"
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# MAIN SETUP
|
|
# ============================================================================
|
|
|
|
setup_auth() {
|
|
detect_web_server
|
|
configure_paths
|
|
|
|
echo ""
|
|
echo "=========================================="
|
|
echo "Add HTTP Basic Auth to Prometheus Stack"
|
|
echo "Version: ${SCRIPT_VERSION} (${WEB_SERVER})"
|
|
echo "=========================================="
|
|
|
|
# Check for HTTPS
|
|
local has_any_https=false
|
|
for entry in "${SERVICES[@]}"; do
|
|
local name config_file
|
|
name=$(get_service_name "$entry")
|
|
config_file=$(get_config_file "$entry")
|
|
local full_path="${CONFIG_DIR}/${config_file}"
|
|
if [ -f "$full_path" ] && has_https "$full_path"; then
|
|
has_any_https=true
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ "$has_any_https" = false ]; then
|
|
echo ""
|
|
warn "No HTTPS configuration detected!"
|
|
echo " Basic Auth over HTTP sends credentials in cleartext."
|
|
echo " Strongly recommended: run certbot first to enable HTTPS."
|
|
echo ""
|
|
read -r -p "Continue without HTTPS? [y/N]: " confirm
|
|
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
|
echo "Aborted. Run certbot first, then re-run this script."
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# Detect which services have configs
|
|
echo ""
|
|
echo "Detected services:"
|
|
local found_any=false
|
|
for entry in "${SERVICES[@]}"; do
|
|
local name config_file
|
|
name=$(get_service_name "$entry")
|
|
config_file=$(get_config_file "$entry")
|
|
local full_path="${CONFIG_DIR}/${config_file}"
|
|
if [ -f "$full_path" ]; then
|
|
local https_status="HTTP"
|
|
has_https "$full_path" && https_status="HTTPS"
|
|
echo " ✓ ${name} (${config_file}) [${https_status}]"
|
|
found_any=true
|
|
fi
|
|
done
|
|
|
|
if [ "$found_any" = false ]; then
|
|
die "No service configs found in ${CONFIG_DIR}. Set up ${WEB_SERVER} reverse proxies first."
|
|
fi
|
|
|
|
echo ""
|
|
|
|
# Ask about push endpoint protection
|
|
local protect_push=false
|
|
echo "Mimir and Loki have push endpoints used by remote agents."
|
|
echo "Protecting them requires configuring credentials in Prometheus/Alloy."
|
|
read -r -p "Protect push endpoints with auth too? [y/N]: " push_confirm
|
|
if [[ "$push_confirm" =~ ^[Yy]$ ]]; then
|
|
protect_push=true
|
|
fi
|
|
|
|
# Ask about shared vs per-service credentials
|
|
local shared_creds=false
|
|
local shared_htpasswd=""
|
|
echo ""
|
|
echo "Credential mode:"
|
|
echo " 1) Same username/password for all services"
|
|
echo " 2) Different credentials per service"
|
|
read -r -p "Select [1]: " cred_mode
|
|
if [[ "${cred_mode:-1}" != "2" ]]; then
|
|
shared_creds=true
|
|
read -r -p "Username for all services [admin]: " shared_user
|
|
shared_user=${shared_user:-admin}
|
|
# Create a temporary shared htpasswd file — will be copied per service
|
|
shared_htpasswd=$(mktemp)
|
|
htpasswd -c "$shared_htpasswd" "$shared_user"
|
|
fi
|
|
|
|
# Create directories
|
|
mkdir -p "$AUTH_DIR" "$SNIPPET_DIR" "$BACKUP_DIR"
|
|
|
|
echo ""
|
|
|
|
# Set up auth for each detected service
|
|
for entry in "${SERVICES[@]}"; do
|
|
local name config_file port
|
|
name=$(get_service_name "$entry")
|
|
config_file=$(get_config_file "$entry")
|
|
port=$(get_service_port "$entry")
|
|
local full_path="${CONFIG_DIR}/${config_file}"
|
|
|
|
if [ ! -f "$full_path" ]; then
|
|
continue
|
|
fi
|
|
|
|
local display_name
|
|
display_name="${name^}"
|
|
|
|
echo "--- ${display_name} ---"
|
|
|
|
# Create htpasswd file
|
|
if [ "$shared_creds" = true ]; then
|
|
if [ -f "${AUTH_DIR}/.htpasswd-${name}" ]; then
|
|
read -r -p " htpasswd file exists. Overwrite with shared credentials? [Y/n]: " overwrite
|
|
if [[ "$overwrite" =~ ^[Nn]$ ]]; then
|
|
echo " Keeping existing htpasswd"
|
|
else
|
|
cp "$shared_htpasswd" "${AUTH_DIR}/.htpasswd-${name}"
|
|
echo " Using shared credentials"
|
|
fi
|
|
else
|
|
cp "$shared_htpasswd" "${AUTH_DIR}/.htpasswd-${name}"
|
|
echo " Using shared credentials"
|
|
fi
|
|
else
|
|
if [ -f "${AUTH_DIR}/.htpasswd-${name}" ]; then
|
|
read -r -p " htpasswd file exists. Recreate? [y/N]: " recreate
|
|
if [[ ! "$recreate" =~ ^[Yy]$ ]]; then
|
|
echo " Keeping existing htpasswd"
|
|
else
|
|
read -r -p " Username [admin]: " username
|
|
username=${username:-admin}
|
|
htpasswd -c "${AUTH_DIR}/.htpasswd-${name}" "$username"
|
|
fi
|
|
else
|
|
read -r -p " Username [admin]: " username
|
|
username=${username:-admin}
|
|
htpasswd -c "${AUTH_DIR}/.htpasswd-${name}" "$username"
|
|
fi
|
|
fi
|
|
|
|
# Create auth snippet
|
|
create_snippet "$name" "$display_name"
|
|
|
|
# Insert into main location/proxy block
|
|
insert_auth "$full_path" "$name"
|
|
|
|
# Handle push endpoints for Mimir and Loki
|
|
if [[ "$name" == "mimir" ]] || [[ "$name" == "loki" ]]; then
|
|
if [ "$protect_push" = true ]; then
|
|
insert_push_auth "$full_path" "$name"
|
|
else
|
|
echo " ⚠ Push endpoint left open — consider IP restrictions"
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
done
|
|
|
|
# Clean up shared temp file
|
|
[ -n "$shared_htpasswd" ] && rm -f "$shared_htpasswd"
|
|
|
|
# Set permissions on htpasswd files
|
|
chmod 640 "${AUTH_DIR}"/.htpasswd-* 2>/dev/null || true
|
|
chown "root:${WEB_USER}" "${AUTH_DIR}"/.htpasswd-* 2>/dev/null || true
|
|
|
|
# Test and reload
|
|
echo "Testing ${WEB_SERVER} configuration..."
|
|
if test_config; then
|
|
systemctl reload "$SERVICE_NAME"
|
|
echo ""
|
|
echo "=========================================="
|
|
echo "HTTP Basic Auth Successfully Configured!"
|
|
echo "=========================================="
|
|
echo ""
|
|
echo "Web server: ${WEB_SERVER}"
|
|
echo "Backups: ${BACKUP_DIR}"
|
|
echo ""
|
|
echo "To remove auth later: $0 --remove"
|
|
echo "To check status: $0 --status"
|
|
else
|
|
echo ""
|
|
echo "${WEB_SERVER} configuration test FAILED!"
|
|
echo "Your backups are in ${BACKUP_DIR} — restore manually if needed."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# MAIN
|
|
# ============================================================================
|
|
|
|
main() {
|
|
if [[ $EUID -ne 0 ]]; then
|
|
die "This script must be run as root"
|
|
fi
|
|
|
|
case "${1:-}" in
|
|
-h|--help) show_usage ;;
|
|
--remove) do_remove ;;
|
|
--status) show_status ;;
|
|
*)
|
|
install_htpasswd
|
|
setup_auth
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|