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>
144 lines
4.4 KiB
Bash
Executable File
144 lines
4.4 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
headscaleCommands()
|
|
{
|
|
# Setup Headscale for Localhost
|
|
if [[ "$headscaleclientlocal" == [yY] ]]; then
|
|
setupHeadscale localhost;
|
|
fi
|
|
|
|
# Setup Headscale for app
|
|
if [[ "$headscaleclientapp" == [yY] ]]; then
|
|
local app_names=()
|
|
local app_dir
|
|
|
|
isHeader "Install Headscale Apps List"
|
|
|
|
# Find all subdirectories under the directory where your apps are installed
|
|
while IFS= read -r app_dir; do
|
|
if [[ -d "$app_dir" ]]; then
|
|
# Extract the app name (folder name)
|
|
local app_name=$(basename "$app_dir")
|
|
local app_names+=("$app_name")
|
|
fi
|
|
done < <(storageAppDirs)
|
|
|
|
# Check if any apps were found
|
|
if [ ${#app_names[@]} -eq 0 ]; then
|
|
isNotice "No apps found in the installation directory."
|
|
fi
|
|
|
|
# List numbered options for app names
|
|
isNotice "Select an app to set up Headscale for:"
|
|
echo ""
|
|
for i in "${!app_names[@]}"; do
|
|
isOption "$((i + 1)). ${app_names[i]}"
|
|
done
|
|
|
|
# Read user input for app selection
|
|
echo ""
|
|
isQuestion "Enter the number of the app (or 'x' to exit): "
|
|
read -p "" selected_option
|
|
|
|
case "$selected_option" in
|
|
[1-9]*)
|
|
# Check if the selected option is a valid number
|
|
if ((selected_option >= 1 && selected_option <= ${#app_names[@]})); then
|
|
local selected_app="${app_names[selected_option - 1]}"
|
|
|
|
# Call the setupHeadscale function with the selected app name
|
|
setupHeadscale "$selected_app"
|
|
else
|
|
isNotice "Invalid app number. Please choose a valid option."
|
|
fi
|
|
;;
|
|
x)
|
|
isNotice "Exiting..."
|
|
;;
|
|
*)
|
|
isNotice "Invalid option. Please choose a valid option or 'x' to exit."
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
# Create a user
|
|
if [[ "$headscaleusercreate" == [yY] ]]; then
|
|
echo ""
|
|
echo "---- Creating user $CFG_INSTALL_NAME for Headscale :"
|
|
echo ""
|
|
local CFG_INSTALL_NAME=$(echo "$CFG_INSTALL_NAME" | tr '[:upper:]' '[:lower:]')
|
|
dockerCommandRun "docker exec headscale headscale users create $CFG_INSTALL_NAME"
|
|
echo ""
|
|
isNotice "Press Enter to continue..."
|
|
read
|
|
fi
|
|
|
|
# Create a user
|
|
if [[ "$headscaleusercreate" == [yY] ]]; then
|
|
echo ""
|
|
echo "---- Creating user $CFG_INSTALL_NAME for Headscale :"
|
|
echo ""
|
|
local CFG_INSTALL_NAME=$(echo "$CFG_INSTALL_NAME" | tr '[:upper:]' '[:lower:]')
|
|
dockerCommandRun "docker exec headscale headscale users create $CFG_INSTALL_NAME"
|
|
echo ""
|
|
isNotice "Press Enter to continue..."
|
|
read
|
|
fi
|
|
|
|
# Create a key
|
|
if [[ "$headscaleapikeyscreate" == [yY] ]]; then
|
|
echo ""
|
|
echo "---- Generating Auth Key in Headscale for user $CFG_INSTALL_NAME :"
|
|
echo ""
|
|
local CFG_INSTALL_NAME=$(echo "$CFG_INSTALL_NAME" | tr '[:upper:]' '[:lower:]')
|
|
dockerCommandRun "docker exec headscale headscale preauthkeys create -e 1h -u $CFG_INSTALL_NAME"
|
|
echo ""
|
|
isNotice "Press Enter to continue..."
|
|
read
|
|
fi
|
|
|
|
# Show list of keys
|
|
if [[ "$headscaleapikeyslist" == [yY] ]]; then
|
|
echo ""
|
|
echo "---- Showing all Headscale API Keys :"
|
|
echo ""
|
|
dockerCommandRun "docker exec headscale headscale apikeys list"
|
|
echo ""
|
|
isNotice "Press Enter to continue..."
|
|
read
|
|
fi
|
|
|
|
# Show list of nodes
|
|
if [[ "$headscalenodeslist" == [yY] ]]; then
|
|
echo ""
|
|
echo "---- Showing all Headscale Nodes :"
|
|
echo ""
|
|
dockerCommandRun "docker exec headscale headscale nodes list"
|
|
echo ""
|
|
isNotice "Press Enter to continue..."
|
|
read
|
|
fi
|
|
|
|
# Show list of users
|
|
if [[ "$headscaleuserlist" == [yY] ]]; then
|
|
echo ""
|
|
echo "---- Showing all Headscale Users :"
|
|
echo ""
|
|
dockerCommandRun "docker exec headscale headscale user list"
|
|
echo ""
|
|
isNotice "Press Enter to continue..."
|
|
read
|
|
fi
|
|
|
|
# Show version
|
|
if [[ "$headscaleversion" == [yY] ]]; then
|
|
echo ""
|
|
checkSuccess "Showing the Headscale Version :"
|
|
echo ""
|
|
dockerCommandRun "docker exec headscale headscale version"
|
|
echo ""
|
|
isNotice "Press Enter to continue..."
|
|
read
|
|
fi
|
|
}
|