Files
proxmox-authelia/setup_authelia.sh
2025-12-30 06:05:46 -08:00

273 lines
8.3 KiB
Bash
Executable File

#!/bin/bash
set -u
# --- CONFIGURATION ---
CONFIG_DIR="/etc/authelia"
CONFIG_FILE="$CONFIG_DIR/configuration.yml"
USERS_FILE="$CONFIG_DIR/users_database.yml"
OIDC_KEY="$CONFIG_DIR/oidc.key"
SECRETS_FILE="$CONFIG_DIR/client_secrets.txt"
AUTHELIA_BIN="authelia"
SERVICE_USER="authelia"
SERVICE_GROUP="authelia"
# --- 1. PREP & STOP ---
echo "🛑 Stopping Authelia..."
systemctl stop authelia || true
# Only wipe DB if we are NOT using a persistent storage key
if [[ -z "${AUTHELIA_STORAGE_KEY:-}" ]] && [[ -f "$CONFIG_DIR/db.sqlite3" ]]; then
echo "🗑️ Random key detected. Wiping database to prevent crash..."
rm "$CONFIG_DIR/db.sqlite3"
fi
mkdir -p "$CONFIG_DIR"
# --- 1.5 INSTALL RUNTIME WRAPPER (NEW) ---
echo "🔧 Installing Runtime Wrapper..."
if [[ -f "./start_authelia.sh" ]]; then
cp ./start_authelia.sh /usr/local/bin/start-authelia.sh
chmod +x /usr/local/bin/start-authelia.sh
else
echo "❌ ERROR: start_authelia.sh missing! Run this from your git repo folder."
exit 1
fi
# --- 1.6 CONFIGURE SYSTEMD (NEW) ---
echo "⚙️ Configuring Systemd..."
mkdir -p /etc/systemd/system/authelia.service.d
cat <<EOF > /etc/systemd/system/authelia.service.d/override.conf
[Service]
# Disable Sandbox to allow reading /mnt/secrets
PrivateUsers=no
# Use our wrapper script instead of the binary directly
ExecStart=
ExecStart=/usr/local/bin/start-authelia.sh
EOF
systemctl daemon-reload
# --- 2. LOAD SETUP SECRETS (Updated for Robustness) ---
echo "🔍 Checking environment..."
ADMIN_PASS="${AUTHELIA_ADMIN_PASSWORD:-}"
MAIL_PASS="${MAIL_ADMIN_PASSWORD:-}"
ADMIN_EMAIL="admin@poppyglen.cc"
# Source the setup-time secrets file if it exists
if [[ -f "/mnt/secrets/authelia.env" ]]; then
echo " -> Sourcing /mnt/secrets/authelia.env"
set -a
. /mnt/secrets/authelia.env
set +a
# Update variables if they were loaded from file
[[ -n "${AUTHELIA_ADMIN_PASSWORD:-}" ]] && ADMIN_PASS="$AUTHELIA_ADMIN_PASSWORD"
[[ -n "${MAIL_ADMIN_EMAIL:-}" ]] && ADMIN_EMAIL="$MAIL_ADMIN_EMAIL"
[[ -n "${MAIL_ADMIN_PASSWORD:-}" ]] && MAIL_PASS="$MAIL_ADMIN_PASSWORD"
[[ -n "${LLDAP_URL:-}" ]] && LLDAP_URL="$LLDAP_URL"
[[ -n "${LLDAP_BASE_DN:-}" ]] && LLDAP_BASE_DN="$LLDAP_BASE_DN"
[[ -n "${LLDAP_BIND_USER:-}" ]] && LLDAP_BIND_USER="$LLDAP_BIND_USER"
[[ -n "${LLDAP_BIND_PASSWORD:-}" ]] && LLDAP_BIND_PASSWORD="$LLDAP_BIND_PASSWORD"
fi
if [[ -z "$ADMIN_PASS" ]]; then read -sp "Enter Admin Password: " ADMIN_PASS; echo; fi
if [[ -z "$MAIL_PASS" ]]; then read -sp "Enter Mail Password: " MAIL_PASS; echo; fi
# --- 3. GENERATE KEYS & HASHES ---
echo "🔑 Handling Keys..."
# Use Env variable if exists, otherwise generate (but warn)
JWT_SECRET="${AUTHELIA_JWT_SECRET:-$(openssl rand -hex 32)}"
SESSION_SECRET="${AUTHELIA_SESSION_SECRET:-$(openssl rand -hex 32)}"
STORAGE_KEY="${AUTHELIA_STORAGE_KEY:-$(openssl rand -hex 32)}"
HMAC_SECRET="${AUTHELIA_HMAC_SECRET:-$(openssl rand -hex 32)}"
if [[ -z "${AUTHELIA_STORAGE_KEY:-}" ]]; then
echo "⚠️ WARNING: Generating RANDOM Storage Key. Existing DB will be unreadable!"
else
echo "✅ Using persistent keys from environment."
fi
# Keep OIDC Key generation (usually fine to keep static too, but this works)
if [[ ! -f "$OIDC_KEY" ]]; then
openssl genpkey -algorithm RSA -out "$OIDC_KEY" -pkeyopt rsa_keygen_bits:4096
chmod 600 "$OIDC_KEY"
fi
OIDC_KEY_CONTENT=$(cat "$OIDC_KEY" | sed 's/^/ /')
echo "🎲 Handling Client Secrets..."
# Use Env variable if exists, otherwise generate random
NEXTCLOUD_PLAIN="${NEXTCLOUD_CLIENT_SECRET:-$(openssl rand -hex 32)}"
JELLYFIN_PLAIN="${JELLYFIN_CLIENT_SECRET:-$(openssl rand -hex 32)}"
IMMICH_PLAIN="${IMMICH_CLIENT_SECRET:-$(openssl rand -hex 32)}"
echo "🔒 Hashing Client Secrets..."
hash_secret() {
$AUTHELIA_BIN crypto hash generate pbkdf2 --variant sha512 --password "$1" | awk '{print $NF}'
}
# These hashes go into configuration.yml
NEXTCLOUD_HASH=$(hash_secret "$NEXTCLOUD_PLAIN")
JELLYFIN_HASH=$(hash_secret "$JELLYFIN_PLAIN")
IMMICH_HASH=$(hash_secret "$IMMICH_PLAIN")
# --- 4. GENERATE CONFIG ---
echo "📝 Writing Clean Configuration..."
cat <<EOF > "$CONFIG_FILE"
server:
address: tcp://0.0.0.0:9091
log:
level: info
identity_validation:
reset_password:
jwt_secret: "$JWT_SECRET"
authentication_backend:
ldap:
implementation: custom
address: $LLDAP_URL
timeout: 5s
start_tls: false
base_dn: $LLDAP_BASE_DN
additional_users_dn: ou=people
additional_groups_dn: ou=groups
user: $LLDAP_BIND_USER
password: "$LLDAP_BIND_PASSWORD"
attributes:
username: uid
display_name: displayName
group_name: cn
mail: mail
member_of: memberOf
users_filter: (&({username_attribute}={input})(objectClass=person))
groups_filter: (&(member={dn})(objectClass=groupOfUniqueNames))
access_control:
default_policy: deny
rules:
- domain: "auth.poppyglen.cc"
policy: bypass
- domain: "*.poppyglen.cc"
policy: two_factor
subject: ["group:admins", "group:users"]
session:
secret: "$SESSION_SECRET"
cookies:
- name: poppy_session
domain: poppyglen.cc
authelia_url: https://auth.poppyglen.cc
redis:
host: 192.168.0.120
port: 6379
database_index: 1
storage:
encryption_key: "$STORAGE_KEY"
local:
path: $CONFIG_DIR/db.sqlite3
notifier:
disable_startup_check: true
smtp:
address: "submission://mail.poppyglen.cc:587"
username: "$ADMIN_EMAIL"
password: "$MAIL_PASS"
sender: "Authelia <$ADMIN_EMAIL>"
identifier: "authelia.poppyglen.cc"
tls:
skip_verify: true
identity_providers:
oidc:
hmac_secret: "$HMAC_SECRET"
jwks:
- key: |
$OIDC_KEY_CONTENT
key_id: 'poppyglen-oidc-key'
algorithm: 'RS256'
use: 'sig'
clients:
- client_id: nextcloud
client_name: Nextcloud
client_secret: "$NEXTCLOUD_HASH"
public: false
authorization_policy: two_factor
token_endpoint_auth_method: 'client_secret_post'
redirect_uris:
- https://cloud.poppyglen.cc/apps/user_oidc/code
scopes:
- openid
- profile
- email
- groups
userinfo_signed_response_alg: none
- client_id: jellyfin
client_name: Jellyfin
client_secret: "$JELLYFIN_HASH"
public: false
authorization_policy: two_factor
redirect_uris:
- https://jellyfin.poppyglen.cc/sso/OID/redirect/authelia
scopes:
- openid
- profile
- email
- groups
userinfo_signed_response_alg: none
- client_id: immich
client_name: Immich
client_secret: "$IMMICH_HASH"
public: false
authorization_policy: two_factor
require_pkce: false
pkce_challenge_method: ''
redirect_uris:
- https://immich.poppyglen.cc/auth/login
- https://immich.poppyglen.cc/user-settings
- app.immich:///oauth-callback
scopes:
- openid
- profile
- email
- groups
response_types:
- code
grant_types:
- authorization_code
access_token_signed_response_alg: none
userinfo_signed_response_alg: none
token_endpoint_auth_method: client_secret_post
EOF
# --- 6. PERMISSIONS & VALIDATION ---
echo "🔧 Fixing Permissions..."
if ! id "$SERVICE_USER" &>/dev/null; then
echo "⚠️ User '$SERVICE_USER' does not exist. Creating system user..."
useradd -r -s /bin/false "$SERVICE_USER" || echo "Failed to create user."
fi
chown -R "$SERVICE_USER":"$SERVICE_GROUP" "$CONFIG_DIR"
chmod 600 "$CONFIG_FILE" "$USERS_FILE" "$OIDC_KEY"
chmod 700 "$CONFIG_DIR"
echo "🧪 PRE-FLIGHT CHECK..."
if ! su -s /bin/bash "$SERVICE_USER" -c "cat $OIDC_KEY > /dev/null"; then
echo "❌ Permission Error: '$SERVICE_USER' cannot read keys."
chmod 644 "$OIDC_KEY" "$CONFIG_FILE" "$USERS_FILE"
else
echo "✅ Permission Check Passed."
fi
echo "🚀 Starting Authelia..."
systemctl start authelia
cat <<EOF > "$SECRETS_FILE"
# ---------------------------------------------------------
# AUTHELIA CLIENT SECRETS (Use these in your Apps)
# ---------------------------------------------------------
NEXTCLOUD_SECRET=$NEXTCLOUD_PLAIN
JELLYFIN_SECRET=$JELLYFIN_PLAIN
IMMICH_SECRET=$IMMICH_PLAIN
EOF
chmod 600 "$SECRETS_FILE"
echo "✅ SUCCESS! Service Started."
echo " Client Secrets saved to: $SECRETS_FILE"