Docker materialises a missing bind-mount source as an empty directory when a
container starts. The WebUI compose mounts ./libreportal.config as a file, so a
container start before the config landed left a directory at that path — and it
was self-perpetuating:
- copyFolder's tar extract aborted the whole source copy with
"libreportal/libreportal.config: Cannot open: File exists" (exit 2)
- dockerConfigSetupToContainer guards on [ ! -f ], which a directory fails, so
copyFile dropped the real config INSIDE the stub
- the closing -e / -r sanity checks both pass on a directory
The installer then reported success while libreportal-service crash-looped on
EISDIR reading /app/libreportal.config, leaving the WebUI unreachable.
Add repairStubDirForFile: promote a same-named file out of the stub, drop the
directory, and report if the path still isn't a regular file. Call it before the
WebUI source copy and before the per-app config copy (covers every app, not just
the WebUI), and tighten the closing existence check from -e to -f so a stub can
never pass validation again.
Signed-off-by: librelad <librelad@digitalangels.vip>
252 lines
12 KiB
Bash
Executable File
252 lines
12 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
dockerConfigSetupToContainer()
|
|
{
|
|
local silent_flag="$1"
|
|
local app_name="$2"
|
|
local flags="$3"
|
|
local config_overrides="$4"
|
|
|
|
local target_path="$containers_dir$app_name"
|
|
local source_file="$install_containers_dir$app_name/$app_name.config"
|
|
local config_file="$app_name.config"
|
|
|
|
if [ "$app_name" == "" ]; then
|
|
isError "The app_name is empty."
|
|
fi
|
|
|
|
if [ -d "$target_path" ]; then
|
|
if [ "$silent_flag" == "loud" ]; then
|
|
isNotice "The directory '$target_path' already exists."
|
|
fi
|
|
else
|
|
createFolders "$silent_flag" "" "$target_path"
|
|
fi
|
|
|
|
if [ ! -f "$source_file" ]; then
|
|
isError "The config file '$source_file' does not exist."
|
|
fi
|
|
|
|
# Atomic file write function
|
|
atomicWriteConfig() {
|
|
local content="$1"
|
|
local target_file="$2"
|
|
local temp_file="${target_file}.tmp.$$"
|
|
|
|
# Write to temp file first
|
|
echo "$content" > "$temp_file"
|
|
|
|
# Atomic rename (instantaneous)
|
|
mv "$temp_file" "$target_file"
|
|
}
|
|
|
|
# The compose file bind-mounts this config as a FILE. If the container ever
|
|
# started before it landed, Docker left a directory here — clear it before the
|
|
# copy, or the config gets written inside it and the app boots on a directory.
|
|
repairStubDirForFile "$target_path/$config_file" "$silent_flag"
|
|
|
|
if [ ! -f "$target_path/$config_file" ]; then
|
|
if [ "$silent_flag" == "loud" ]; then
|
|
isNotice "Copying config file to '$target_path/$config_file'..."
|
|
fi
|
|
copyFile "$silent_flag" "$source_file" "$target_path/$config_file" $sudo_user_name | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1
|
|
fi
|
|
|
|
if [[ -n "$config_overrides" ]]; then
|
|
local deployed_config_pre="$target_path/$config_file"
|
|
if [[ -f "$deployed_config_pre" ]]; then
|
|
IFS='|' read -ra override_pairs_pre <<< "$config_overrides"
|
|
for pair in "${override_pairs_pre[@]}"; do
|
|
if [[ "$pair" =~ ^(CFG_[A-Z0-9_]+)=(.*)$ ]]; then
|
|
local _value="${BASH_REMATCH[2]//%7C/|}"
|
|
updateConfigOption "${BASH_REMATCH[1]}" "$_value" "$deployed_config_pre"
|
|
fi
|
|
done
|
|
fi
|
|
fi
|
|
|
|
if runFileOp grep -qE 'RANDOMIZED(PASSWORD|USERNAME|BCRYPTPASSWORD|HEX|VAPID|APPKEY)[0-9]*' "$target_path/$config_file" 2>/dev/null; then
|
|
scanFileForRandomPasswordKeysUsers "$target_path/$config_file"
|
|
runFileOp chmod a+r "$target_path/$config_file" 2>/dev/null || true
|
|
source "$target_path/$config_file"
|
|
fi
|
|
|
|
fixConfigPermissions $silent_flag $app_name;
|
|
|
|
# Must be a regular file, not just present: a Docker-created bind-mount
|
|
# directory satisfies -e and -r but makes the container exit on boot.
|
|
if [ ! -f "$target_path/$config_file" ]; then
|
|
isError "File $target_path/$config_file does not exist, or is not a regular file"
|
|
fi
|
|
|
|
# Check if the user has read permission on target_path/config_file
|
|
if [ ! -r "$target_path/$config_file" ]; then
|
|
isError "Insufficient permissions to read $target_path/$config_file"
|
|
fi
|
|
|
|
if [[ "$flags" == "install" ]]; then
|
|
if [ -f "$target_path/$config_file" ]; then
|
|
# Same content check
|
|
if runFileOp cmp -s "$source_file" "$target_path/$config_file"; then
|
|
isNotice "Config file for $app_name contains no edits."
|
|
while true; do
|
|
#isQuestion "? (y/n): "
|
|
#read -rp "" editconfigaccept
|
|
#echo ""
|
|
editconfigaccept="n" # No longer needed due to webui
|
|
case $editconfigaccept in
|
|
[yY])
|
|
# Calculate checksum of the original file
|
|
local original_checksum=$(runFileOp md5sum "$target_path/$config_file")
|
|
# Open the file with $CFG_TEXT_EDITOR for editing
|
|
runFileOp $CFG_TEXT_EDITOR "$target_path/$config_file"
|
|
# Calculate checksum of the edited file
|
|
local edited_checksum=$(runFileOp md5sum "$target_path/$config_file")
|
|
# Compare the checksums to check if changes were made
|
|
if [[ "$original_checksum" != "$edited_checksum" ]]; then
|
|
source $target_path/$config_file
|
|
initializeAppVariables $app_name;
|
|
isSuccessful "Changes have been made to the $config_file."
|
|
fi
|
|
break
|
|
;;
|
|
[nN])
|
|
break # Exit the loop without updating
|
|
;;
|
|
*)
|
|
isNotice "Please provide a valid input (y or n)."
|
|
;;
|
|
esac
|
|
done
|
|
else
|
|
echo ""
|
|
isNotice "Config file for $app_name has been updated..."
|
|
echo ""
|
|
while true; do
|
|
#isQuestion "Would you like to reset the config file? (y/n): "
|
|
#read -rp "" resetconfigaccept
|
|
#echo ""
|
|
resetconfigaccept="n" # No longer needed due to webui
|
|
case $resetconfigaccept in
|
|
[yY])
|
|
isNotice "Resetting $app_name config file."
|
|
copyFile "loud" "$source_file" "$target_path/$config_file" $docker_install_user | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1
|
|
source $target_path/$config_file
|
|
dockerConfigSetupToContainer "loud" $app_name;
|
|
while true; do
|
|
#isQuestion "Would you like to make edits to the config file? (y/n): "
|
|
#read -rp "" editconfigaccept
|
|
#echo ""
|
|
editconfigaccept="n" # No longer needed due to webui
|
|
case $editconfigaccept in
|
|
[yY])
|
|
# Calculate the checksum of the original file
|
|
local original_checksum=$(runFileOp md5sum "$target_path/$config_file")
|
|
|
|
# Open the file with $CFG_TEXT_EDITOR for editing
|
|
runFileOp $CFG_TEXT_EDITOR "$target_path/$config_file"
|
|
|
|
# Calculate the checksum of the edited file
|
|
local edited_checksum=$(runFileOp md5sum "$target_path/$config_file")
|
|
|
|
# Compare the checksums to check if changes were made
|
|
if [[ "$original_checksum" != "$edited_checksum" ]]; then
|
|
source $target_path/$config_file
|
|
initializeAppVariables $app_name;
|
|
isSuccessful "Changes have been made to the $config_file."
|
|
fi
|
|
break
|
|
;;
|
|
[nN])
|
|
break # Exit the loop without updating
|
|
;;
|
|
*)
|
|
isNotice "Please provide a valid input (y or n)."
|
|
;;
|
|
esac
|
|
done
|
|
break
|
|
;;
|
|
[nN])
|
|
while true; do
|
|
#isQuestion "Would you like to make edits to the config file? (y/n): "
|
|
#read -rp "" editconfigaccept
|
|
#echo ""
|
|
editconfigaccept="n" # No longer needed due to webui
|
|
case $editconfigaccept in
|
|
[yY])
|
|
# Calculate the checksum of the original file
|
|
local original_checksum=$(runFileOp md5sum "$target_path/$config_file")
|
|
|
|
# Open the file with $CFG_TEXT_EDITOR for editing
|
|
runFileOp $CFG_TEXT_EDITOR "$target_path/$config_file"
|
|
|
|
# Calculate the checksum of the edited file
|
|
local edited_checksum=$(runFileOp md5sum "$target_path/$config_file")
|
|
|
|
# Compare the checksums to check if changes were made
|
|
if [[ "$original_checksum" != "$edited_checksum" ]]; then
|
|
source $target_path/$config_file
|
|
initializeAppVariables $app_name;
|
|
isSuccessful "Changes have been made to the $config_file."
|
|
fi
|
|
break
|
|
;;
|
|
[nN])
|
|
break # Exit the loop without updating
|
|
;;
|
|
*)
|
|
isNotice "Please provide a valid input (y or n)."
|
|
;;
|
|
esac
|
|
done
|
|
break # Exit the loop without updating
|
|
;;
|
|
*)
|
|
isNotice "Please provide a valid input (y or n)."
|
|
;;
|
|
esac
|
|
done
|
|
fi
|
|
else
|
|
isNotice "Config file for $app_name does not exist. Creating it..."
|
|
copyFile "loud" "$source_file" "$target_path/$config_file" $docker_install_user | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1
|
|
isNotice "Config file for $app_name contains no edits."
|
|
while true; do
|
|
#isQuestion "Would you like to make edits to the config file? (y/n): "
|
|
#read -rp "" editconfigaccept
|
|
#echo ""
|
|
editconfigaccept="n" # No longer needed due to webui
|
|
case $editconfigaccept in
|
|
[yY])
|
|
# Calculate the checksum of the original file
|
|
local original_checksum=$(runFileOp md5sum "$target_path/$config_file")
|
|
|
|
# Open the file with $CFG_TEXT_EDITOR for editing
|
|
runFileOp $CFG_TEXT_EDITOR "$target_path/$config_file"
|
|
|
|
# Calculate the checksum of the edited file
|
|
local edited_checksum=$(runFileOp md5sum "$target_path/$config_file")
|
|
|
|
# Compare the checksums to check if changes were made
|
|
if [[ "$original_checksum" != "$edited_checksum" ]]; then
|
|
source $target_path/$config_file
|
|
initializeAppVariables $app_name;
|
|
isSuccessful "Changes have been made to the $config_file."
|
|
fi
|
|
break
|
|
;;
|
|
[nN])
|
|
break # Exit the loop without updating
|
|
;;
|
|
*)
|
|
isNotice "Please provide a valid input (y or n)."
|
|
;;
|
|
esac
|
|
done
|
|
fi
|
|
fi
|
|
|
|
sourceScanFiles "app_configs";
|
|
}
|