The main sweep — ~260 call sites across ~100 files move from string
concatenation on a single root to appDir/storageAppDirs/storageAppConfigs.
On a single-root install the resolved paths are identical, so this is a
no-op until a location is registered.
Enumerators were the interesting half. `for d in "$containers_dir"/*/`
appears in the menus, the registry/artifact scanners and the DNS setup —
and a shell glob cannot list a rootless 751 tree at all, which is the
same bug config_find_file.sh already documents in a comment. Routing them
through storageAppDirs (which enumerates as the owning user) fixes that
alongside the multi-root work.
Three places needed judgement rather than substitution:
db_app_scan.sh deletes database rows and port allocations for apps whose
folder is missing, and reaps "empty" app dirs. With a storage location
unmounted, every app on it looks exactly like that. Each of those
branches now gates on appStorageAvailable first — an app on an unplugged
drive is skipped with a notice, never deleted.
instance_create.sh rewrites cloned hooks so an instance touches its own
directory instead of the base app's. Its sed matched ${containers_dir}<type>,
which this sweep just replaced with $(appDir <type>) — so it would have
silently stopped redirecting, and an instance would have written to the
original's files (the adguard auth adapter case its own comment warns
about). Now matches both appDir forms, verified against bare, quoted,
unrelated-app, legacy and prose cases.
peer_shell/peer_pull streamed and extracted relative to the primary root.
Both now use the app's own root, and peer_shell keeps a single-root
fallback since it runs as a restricted SSH shell with no LibrePortal env.
Also fixes a pre-existing bug found on the way: webui_app_config.sh
tested "$containers_dir/frontend/data/last_update", one level short of the
real tree under the libreportal app dir, so the WebUI refresh trigger
after a config update has never once fired.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
112 lines
4.1 KiB
Bash
112 lines
4.1 KiB
Bash
#!/bin/bash
|
|
|
|
# Authelia install hooks — requirements check, config + secrets bootstrap,
|
|
# admin account provisioning, and an end-of-install credentials notice.
|
|
|
|
authelia_install_pre()
|
|
{
|
|
local app_name="$1"
|
|
if ! appInstallCheckRequirements "$app_name" "$CFG_AUTHELIA_REQUIRES"; then
|
|
authelia=n
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
authelia_install_post_compose()
|
|
{
|
|
local app_name="$1"
|
|
|
|
local result
|
|
result=$(copyResource "$app_name" "configuration.yml" "config" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1)
|
|
checkSuccess "Copying configuration.yml to $(appDir "$app_name")/config"
|
|
|
|
result=$(copyResource "$app_name" "users_database.yml" "config" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1)
|
|
checkSuccess "Copying users_database.yml to $(appDir "$app_name")/config"
|
|
|
|
local authelia_config_file="$(appDir "$app_name")/config/configuration.yml"
|
|
runFileOp sed -i "s|AUTHELIA_THEME_PLACEHOLDER|$CFG_AUTHELIA_THEME|g" "$authelia_config_file"
|
|
runFileOp sed -i "s|AUTHELIA_DOMAIN_PLACEHOLDER|$domain_full|g" "$authelia_config_file"
|
|
runFileOp sed -i "s|AUTHELIA_HOST_PLACEHOLDER|$host_setup|g" "$authelia_config_file"
|
|
checkSuccess "Substituting Authelia configuration values (theme=$CFG_AUTHELIA_THEME domain=$domain_full host=$host_setup)"
|
|
|
|
local authelia_secrets_dir="$(appDir "$app_name")/secrets"
|
|
runFileOp mkdir -p "$authelia_secrets_dir"
|
|
local secret_name secret_file
|
|
for secret_name in JWT_SECRET SESSION_SECRET STORAGE_ENCRYPTION_KEY; do
|
|
secret_file="$authelia_secrets_dir/$secret_name"
|
|
if [[ ! -s "$secret_file" ]]; then
|
|
openssl rand -hex 64 | runFileWrite "$secret_file"
|
|
runFileOp chmod 600 "$secret_file"
|
|
fi
|
|
done
|
|
runFileOp chown -R "$docker_install_user":"$docker_install_user" "$authelia_secrets_dir"
|
|
checkSuccess "Generated Authelia secrets at $authelia_secrets_dir"
|
|
|
|
# Authelia's metrics block lives in configuration.yml (not the compose),
|
|
# so toggle it here. The driver already toggled docker-compose.yml.
|
|
monitoringToggleAppConfig "$app_name" "config/configuration.yml"
|
|
}
|
|
|
|
authelia_install_post_start()
|
|
{
|
|
local app_name="$1"
|
|
|
|
((menu_number++))
|
|
echo ""
|
|
echo "---- $menu_number. Configuring Authelia admin account"
|
|
echo ""
|
|
|
|
local authelia_admin_user="${CFG_AUTHELIA_ADMIN_USERNAME:-admin}"
|
|
local authelia_admin_pass="${CFG_AUTHELIA_ADMIN_PASSWORD_1:-authelia}"
|
|
local authelia_users_file="$(appDir "$app_name")/config/users_database.yml"
|
|
local authelia_attempts=0
|
|
while ((authelia_attempts < 30)); do
|
|
if runFileOp docker exec authelia-service authelia --version >/dev/null 2>&1; then
|
|
break
|
|
fi
|
|
sleep 2
|
|
((authelia_attempts++))
|
|
done
|
|
|
|
if ((authelia_attempts >= 30)); then
|
|
isNotice "Authelia container did not become responsive in time — admin left at default (admin / authelia)."
|
|
return 0
|
|
fi
|
|
|
|
local authelia_hash
|
|
authelia_hash=$(runFileOp docker exec authelia-service authelia crypto hash generate argon2 --password "$authelia_admin_pass" 2>/dev/null \
|
|
| grep -oE '\$argon2[^[:space:]]+')
|
|
if [[ -z "$authelia_hash" ]]; then
|
|
isNotice "Could not generate Authelia password hash — admin left at default (admin / authelia)."
|
|
return 0
|
|
fi
|
|
|
|
runFileWrite "$authelia_users_file" <<EOF
|
|
---
|
|
users:
|
|
${authelia_admin_user}:
|
|
disabled: false
|
|
displayname: "Admin"
|
|
password: "${authelia_hash}"
|
|
email: ${authelia_admin_user}@${domain_full:-example.com}
|
|
groups:
|
|
- admins
|
|
EOF
|
|
runFileOp chown "$docker_install_user":"$docker_install_user" "$authelia_users_file"
|
|
isSuccessful "Configured Authelia admin (user: $authelia_admin_user)."
|
|
dockerComposeRestart "$app_name"
|
|
}
|
|
|
|
authelia_install_post()
|
|
{
|
|
local app_name="$1"
|
|
local authelia_admin_user="${CFG_AUTHELIA_ADMIN_USERNAME:-admin}"
|
|
local authelia_admin_pass="${CFG_AUTHELIA_ADMIN_PASSWORD_1:-authelia}"
|
|
echo ""
|
|
isNotice "Authelia admin login:"
|
|
echo ""
|
|
echo " Username : ${authelia_admin_user}"
|
|
echo " Password : ${authelia_admin_pass}"
|
|
echo ""
|
|
}
|