Merge claude/1

This commit is contained in:
librelad 2026-05-24 00:12:06 +01:00
commit fa2df5dffe
19 changed files with 95 additions and 83 deletions

View File

@ -2,4 +2,4 @@
# Rootless Networking - Network stack and behaviour for rootless Docker **ADVANCED** # Rootless Networking - Network stack and behaviour for rootless Docker **ADVANCED**
# ================================================================================ # ================================================================================
CFG_ROOTLESS_NET=pasta # Rootless Network Driver - Network stack for rootless Docker; pasta (default): faster and preserves the real client source IP; slirp4netns: legacy fallback if pasta misbehaves. The matching rootlesskit port driver is selected automatically. **ADVANCED** [pasta:Pasta (recommended)|slirp4netns:slirp4netns (fallback)] CFG_ROOTLESS_NET=slirp4netns # Rootless Network Driver - Network stack for rootless Docker; slirp4netns (default): reliable everywhere; pasta: faster and preserves the real client source IP BUT on Debian the shipped passt AppArmor profile denies the ptrace it needs to open the container netns, so the daemon won't start unless that profile is relaxed. The matching rootlesskit port driver is selected automatically. **ADVANCED** [slirp4netns:slirp4netns (default, reliable)|pasta:Pasta (faster, needs AppArmor override)]

View File

@ -60,10 +60,10 @@ installAuthelia()
dockerComposeSetupFile $app_name; dockerComposeSetupFile $app_name;
local result=$(copyResource "$app_name" "configuration.yml" "config" | runFileWrite -a "$logs_dir/$docker_log_file" 2>&1) local result=$(copyResource "$app_name" "configuration.yml" "config" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1)
checkSuccess "Copying configuration.yml to $containers_dir$app_name/config" checkSuccess "Copying configuration.yml to $containers_dir$app_name/config"
local result=$(copyResource "$app_name" "users_database.yml" "config" | runFileWrite -a "$logs_dir/$docker_log_file" 2>&1) local result=$(copyResource "$app_name" "users_database.yml" "config" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1)
checkSuccess "Copying users_database.yml to $containers_dir$app_name/config" checkSuccess "Copying users_database.yml to $containers_dir$app_name/config"
local authelia_config_file="$containers_dir$app_name/config/configuration.yml" local authelia_config_file="$containers_dir$app_name/config/configuration.yml"

View File

@ -54,7 +54,7 @@ installHeadscale()
local result=$(createFolders "loud" $docker_install_user $containers_dir$app_name/config) local result=$(createFolders "loud" $docker_install_user $containers_dir$app_name/config)
checkSuccess "Create config folder" checkSuccess "Create config folder"
local result=$(copyResource "$app_name" "config.yaml" "config" | runFileWrite -a "$logs_dir/$docker_log_file" 2>&1) local result=$(copyResource "$app_name" "config.yaml" "config" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1)
checkSuccess "Copying config.yaml to config folder." checkSuccess "Copying config.yaml to config folder."
configSetupFileWithData $app_name "config.yaml" "config"; configSetupFileWithData $app_name "config.yaml" "config";

View File

@ -57,7 +57,7 @@ installPrometheus()
local result=$(createTouch "$containers_dir$app_name/$app_name/$app_name.yml" $docker_install_user) local result=$(createTouch "$containers_dir$app_name/$app_name/$app_name.yml" $docker_install_user)
checkSuccess "Created $app_name.yml file for $app_name" checkSuccess "Created $app_name.yml file for $app_name"
local result=$(copyResource "$app_name" "$app_name.yml" "$app_name" | runFileWrite -a "$logs_dir/$docker_log_file" 2>&1) local result=$(copyResource "$app_name" "$app_name.yml" "$app_name" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1)
checkSuccess "Copying $app_name.yml to containers folder." checkSuccess "Copying $app_name.yml to containers folder."
((menu_number++)) ((menu_number++))

View File

@ -53,7 +53,7 @@ installUnbound()
monitoringToggleAppConfig "$app_name" "docker-compose.yml"; monitoringToggleAppConfig "$app_name" "docker-compose.yml";
local result=$(copyResource "$app_name" "unbound.conf" "etc" | runFileWrite -a "$logs_dir/$docker_log_file" 2>&1) local result=$(copyResource "$app_name" "unbound.conf" "etc" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1)
checkSuccess "Copying unbound.conf to containers folder." checkSuccess "Copying unbound.conf to containers folder."
monitoringToggleAppConfig "$app_name" "etc/unbound.conf"; monitoringToggleAppConfig "$app_name" "etc/unbound.conf";

View File

@ -44,7 +44,7 @@ dockerConfigSetupToContainer()
if [ "$silent_flag" == "loud" ]; then if [ "$silent_flag" == "loud" ]; then
isNotice "Copying config file to '$target_path/$config_file'..." isNotice "Copying config file to '$target_path/$config_file'..."
fi fi
copyFile "$silent_flag" "$source_file" "$target_path/$config_file" $sudo_user_name | runFileWrite -a "$logs_dir/$docker_log_file" 2>&1 copyFile "$silent_flag" "$source_file" "$target_path/$config_file" $sudo_user_name | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1
fi fi
if [[ -n "$config_overrides" ]]; then if [[ -n "$config_overrides" ]]; then
@ -124,7 +124,7 @@ dockerConfigSetupToContainer()
case $resetconfigaccept in case $resetconfigaccept in
[yY]) [yY])
isNotice "Resetting $app_name config file." isNotice "Resetting $app_name config file."
copyFile "loud" "$source_file" "$target_path/$config_file" $docker_install_user | runFileWrite -a "$logs_dir/$docker_log_file" 2>&1 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 source $target_path/$config_file
dockerConfigSetupToContainer "loud" $app_name; dockerConfigSetupToContainer "loud" $app_name;
while true; do while true; do
@ -204,7 +204,7 @@ dockerConfigSetupToContainer()
fi fi
else else
isNotice "Config file for $app_name does not exist. Creating it..." isNotice "Config file for $app_name does not exist. Creating it..."
copyFile "loud" "$source_file" "$target_path/$config_file" $docker_install_user | runFileWrite -a "$logs_dir/$docker_log_file" 2>&1 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." isNotice "Config file for $app_name contains no edits."
while true; do while true; do
#isQuestion "Would you like to make edits to the config file? (y/n): " #isQuestion "Would you like to make edits to the config file? (y/n): "

View File

@ -62,7 +62,7 @@ tagsProcessorGluetunForwardedPorts()
if [[ ! -f "$docker_dir/$db_file" ]]; then return 0; fi if [[ ! -f "$docker_dir/$db_file" ]]; then return 0; fi
local installed_apps local installed_apps
installed_apps=$(runFileOp sqlite3 "$docker_dir/$db_file" \ installed_apps=$(runInstallOp sqlite3 "$docker_dir/$db_file" \
"SELECT name FROM apps WHERE status = 1 ORDER BY name;" 2>/dev/null) "SELECT name FROM apps WHERE status = 1 ORDER BY name;" 2>/dev/null)
local routed_lines="" local routed_lines=""
@ -75,7 +75,7 @@ tagsProcessorGluetunForwardedPorts()
[[ "$net" != "gluetun" ]] && continue [[ "$net" != "gluetun" ]] && continue
local ports local ports
ports=$(runFileOp sqlite3 "$docker_dir/$db_file" \ ports=$(runInstallOp sqlite3 "$docker_dir/$db_file" \
"SELECT resource_value FROM network_resources WHERE app_name = '$app' AND resource_type = 'port' AND status = 'active';" 2>/dev/null) "SELECT resource_value FROM network_resources WHERE app_name = '$app' AND resource_type = 'port' AND status = 'active';" 2>/dev/null)
while IFS= read -r p; do while IFS= read -r p; do
[[ -z "$p" ]] && continue [[ -z "$p" ]] && continue

View File

@ -31,7 +31,7 @@ databaseAppScan()
local updated_count=0 local updated_count=0
# Get the list of all folder names and statuses from the database # Get the list of all folder names and statuses from the database
local existing_folders=$(runFileOp sqlite3 "$docker_dir/$db_file" "SELECT name, status, uninstall_date FROM apps;") local existing_folders=$(runInstallOp sqlite3 "$docker_dir/$db_file" "SELECT name, status, uninstall_date FROM apps;")
# Create an array to store existing folder names in the database # Create an array to store existing folder names in the database
local existing_folder_names=() local existing_folder_names=()
@ -43,7 +43,7 @@ databaseAppScan()
if (( status == 0 )); then if (( status == 0 )); then
isNotice "The folder for $folder_name has been found." isNotice "The folder for $folder_name has been found."
# Update the database to set the status to 1 (installed) and unset the uninstall_date # Update the database to set the status to 1 (installed) and unset the uninstall_date
local result=$(runFileOp sqlite3 "$docker_dir/$db_file" "UPDATE apps SET status = 1, uninstall_date = NULL WHERE name = '$folder_name';") local result=$(runInstallOp sqlite3 "$docker_dir/$db_file" "UPDATE apps SET status = 1, uninstall_date = NULL WHERE name = '$folder_name';")
checkSuccess "Updating apps database for $folder_name to installed status." checkSuccess "Updating apps database for $folder_name to installed status."
((updated_count++)) # Increment updated_count ((updated_count++)) # Increment updated_count
fi fi
@ -72,7 +72,7 @@ databaseAppScan()
local folder_time=$(echo "$folder_datetime" | awk '{print $2}') local folder_time=$(echo "$folder_datetime" | awk '{print $2}')
# Add the new entry to the database with a default status of 1 (installed) and the extracted or current date # Add the new entry to the database with a default status of 1 (installed) and the extracted or current date
local result=$(runFileOp sqlite3 "$docker_dir/$db_file" "INSERT INTO apps (name, status, install_date, install_time) VALUES ('$app_name', 1, '$folder_date', '$folder_time');") local result=$(runInstallOp sqlite3 "$docker_dir/$db_file" "INSERT INTO apps (name, status, install_date, install_time) VALUES ('$app_name', 1, '$folder_date', '$folder_time');")
checkSuccess "Adding $app_name to the apps database." checkSuccess "Adding $app_name to the apps database."
((updated_count++)) # Increment updated_count ((updated_count++)) # Increment updated_count
fi fi
@ -97,7 +97,7 @@ databaseAppScan()
isNotice "Folder $folder_name no longer exists. Removing from the Database." isNotice "Folder $folder_name no longer exists. Removing from the Database."
# Delete the entry from the apps table # Delete the entry from the apps table
local result=$(runFileOp sqlite3 "$docker_dir/$db_file" "DELETE FROM apps WHERE name = '$app_name';") local result=$(runInstallOp sqlite3 "$docker_dir/$db_file" "DELETE FROM apps WHERE name = '$app_name';")
checkSuccess "Removing $app_name from the apps database." checkSuccess "Removing $app_name from the apps database."
portsRemoveFromDatabase $app_name; portsRemoveFromDatabase $app_name;
@ -196,7 +196,7 @@ databaseAppScan()
else else
# If the folder doesn't exist in the directory, uninstall it from the database # If the folder doesn't exist in the directory, uninstall it from the database
isNotice "Folder $folder_name does not exist. Removing from the Database." isNotice "Folder $folder_name does not exist. Removing from the Database."
local result=$(runFileOp sqlite3 "$docker_dir/$db_file" "DELETE FROM apps WHERE name = '$folder_name';") local result=$(runInstallOp sqlite3 "$docker_dir/$db_file" "DELETE FROM apps WHERE name = '$folder_name';")
checkSuccess "Removing $folder_name from the apps database." checkSuccess "Removing $folder_name from the apps database."
((updated_count++)) # Increment updated_count ((updated_count++)) # Increment updated_count
fi fi

View File

@ -17,16 +17,16 @@ databaseListInstalledApp()
isNotice "Database file not found. Make sure it's installed." isNotice "Database file not found. Make sure it's installed."
else else
# Check if app exists and is installed # Check if app exists and is installed
local app_check=$(runFileOp sqlite3 "$docker_dir/$db_file" "SELECT name FROM apps WHERE name = '$app_name' AND status = 1;") local app_check=$(runInstallOp sqlite3 "$docker_dir/$db_file" "SELECT name FROM apps WHERE name = '$app_name' AND status = 1;")
if [ -z "$app_check" ]; then if [ -z "$app_check" ]; then
isNotice "App '$app_name' not found or not installed." isNotice "App '$app_name' not found or not installed."
else else
local app_details=$(runFileOp sqlite3 "$docker_dir/$db_file" "SELECT install_date, install_time FROM apps WHERE name = '$app_name';") local app_details=$(runInstallOp sqlite3 "$docker_dir/$db_file" "SELECT install_date, install_time FROM apps WHERE name = '$app_name';")
printf "\e[33m📦 %s\e[0m (Installed: %s)\n" "$app_name" "$app_details" printf "\e[33m📦 %s\e[0m (Installed: %s)\n" "$app_name" "$app_details"
# Get all Docker services with IPs for this app # Get all Docker services with IPs for this app
local docker_services=$(runFileOp sqlite3 "$docker_dir/$db_file" "SELECT DISTINCT service_name, resource_value FROM network_resources WHERE app_name = '$app_name' AND resource_type = 'ip' AND status = 'active' ORDER BY service_name;" 2>/dev/null) local docker_services=$(runInstallOp sqlite3 "$docker_dir/$db_file" "SELECT DISTINCT service_name, resource_value FROM network_resources WHERE app_name = '$app_name' AND resource_type = 'ip' AND status = 'active' ORDER BY service_name;" 2>/dev/null)
if [[ -n "$docker_services" ]]; then if [[ -n "$docker_services" ]]; then
local service_count=0 local service_count=0
@ -44,7 +44,7 @@ databaseListInstalledApp()
printf "%s \e[94m🔌 Service:\e[0m %s (IP: %s)\n" "$connector" "$docker_service_name" "$docker_service_ip" printf "%s \e[94m🔌 Service:\e[0m %s (IP: %s)\n" "$connector" "$docker_service_name" "$docker_service_ip"
# Get all ports for this Docker service # Get all ports for this Docker service
local service_ports=$(runFileOp sqlite3 "$docker_dir/$db_file" "SELECT service_name, resource_value FROM network_resources WHERE app_name = '$app_name' AND resource_type = 'port' AND parent_service = '$docker_service_name' AND status = 'active' ORDER BY service_name;" 2>/dev/null) local service_ports=$(runInstallOp sqlite3 "$docker_dir/$db_file" "SELECT service_name, resource_value FROM network_resources WHERE app_name = '$app_name' AND resource_type = 'port' AND parent_service = '$docker_service_name' AND status = 'active' ORDER BY service_name;" 2>/dev/null)
if [[ -n "$service_ports" ]]; then if [[ -n "$service_ports" ]]; then
local port_count=0 local port_count=0
@ -97,7 +97,7 @@ databaseListInstalledApp()
fi fi
# Check if Traefik is installed # Check if Traefik is installed
local traefik_installed=$(runFileOp sqlite3 "$docker_dir/$db_file" "SELECT name FROM apps WHERE name = 'traefik' AND status = 1;" 2>/dev/null) local traefik_installed=$(runInstallOp sqlite3 "$docker_dir/$db_file" "SELECT name FROM apps WHERE name = 'traefik' AND status = 1;" 2>/dev/null)
# Per-port URL path: 10th column of the matching # Per-port URL path: 10th column of the matching
# CFG_<APP>_PORT_N row in the deployed config. Find the # CFG_<APP>_PORT_N row in the deployed config. Find the
@ -137,7 +137,7 @@ databaseListInstalledApp()
local _domain="" local _domain=""
if [[ -n "$traefik_installed" ]]; then if [[ -n "$traefik_installed" ]]; then
_domain=$(runFileOp sqlite3 "$docker_dir/$db_file" "SELECT resource_value FROM options WHERE option = 'domain_${app_name^^}_DOMAIN';" 2>/dev/null) _domain=$(runInstallOp sqlite3 "$docker_dir/$db_file" "SELECT resource_value FROM options WHERE option = 'domain_${app_name^^}_DOMAIN';" 2>/dev/null)
fi fi
local _path_idx _p local _path_idx _p

View File

@ -51,13 +51,15 @@ runSystem() {
sudo "$@" sudo "$@"
} }
# Op on the manager install dir / shipped templates — the LibrePortal clone and # Op on a MANAGER-owned path — the LibrePortal clone + shipped templates AND the
# its container templates, owned by the manager user that runs the runtime. # /docker management layer the runtime owns (apps DB, configs/, logs/, scripts).
# rooted -> sudo <cmd> (install tree is root-owned; byte-identical) # In rootless these are owned by the manager user; ops on them need no privilege.
# rootless -> <cmd> (the manager user already owns it — no privilege) # rooted -> sudo <cmd> (root-owned; byte-identical)
# For copies that read the install tree and write into /docker (two different # rootless -> <cmd> (runs as the current user: root at install-time,
# owners in rootless), don't use this for the whole copy — read here and pipe # the manager user at runtime — both can access)
# into runFileWrite so each side runs as the correct owner. # Container-owned data under /docker/containers/<app>/ is NOT this — use runFileOp.
# For copies that read manager files and write container-owned ones, read here
# and pipe into runFileWrite so each side runs as the correct owner.
runInstallOp() { runInstallOp() {
if [[ "$CFG_DOCKER_INSTALL_TYPE" == "rootless" ]]; then if [[ "$CFG_DOCKER_INSTALL_TYPE" == "rootless" ]]; then
"$@" "$@"
@ -65,3 +67,22 @@ runInstallOp() {
sudo "$@" sudo "$@"
fi fi
} }
# Write stdin to a MANAGER-owned path (apps DB sidecars, configs/, logs/ — e.g.
# the /docker/logs log-append idiom). Mirror of runFileWrite for the manager
# owner. Pass -a/--append as the first arg to append.
# rooted -> sudo tee
# rootless -> tee as the current (manager) user
runInstallWrite() {
local append=""
if [[ "$1" == "-a" || "$1" == "--append" ]]; then
append=" -a"
shift
fi
local dest="$1"
if [[ "$CFG_DOCKER_INSTALL_TYPE" == "rootless" ]]; then
tee$append "$dest" >/dev/null
else
sudo tee$append "$dest" >/dev/null
fi
}

View File

@ -40,7 +40,7 @@ dockerComposeSetupFile()
isError "The source file '$source_file' does not exist." isError "The source file '$source_file' does not exist."
fi fi
copyFile "loud" "$source_file" "$target_file" $docker_install_user | runFileWrite -a "$logs_dir/$docker_log_file" 2>&1 copyFile "loud" "$source_file" "$target_file" $docker_install_user | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
isError "Failed to copy the source file to '$target_path'. Check '$docker_log_file' for more details." isError "Failed to copy the source file to '$target_path'. Check '$docker_log_file' for more details."

View File

@ -212,29 +212,20 @@ EOL"
# Enabling unprivileged user namespaces (needed for rootless) widens the # Enabling unprivileged user namespaces (needed for rootless) widens the
# kernel attack surface reachable by unprivileged users. Offset that by # kernel attack surface reachable by unprivileged users. Offset that by
# closing the surfaces that local-privilege-escalation chains lean on: # closing the surfaces that local-privilege-escalation chains lean on:
# kptr_restrict hides kernel pointers (defeats info-leak primitives), # kptr_restrict hides kernel pointers (info-leak primitives), ptrace_scope
# ptrace_scope blocks cross-process ptrace (limits credential theft after # blocks cross-process ptrace (credential theft post-compromise), and
# a compromise), and bpf_jit_harden hardens the JIT against spraying. # bpf_jit_harden hardens the JIT against spraying. Written under
# All three are distro-portable and have negligible runtime impact. # /etc/sysctl.d/ so `sysctl --system` actually loads it — LibrePortal's
if ! grep -qF "# LIBREPORTAL KERNEL HARDENING START" "$sysctl"; then # own $sysctl path (/etc/sysctl/…) is non-standard and is NOT read by
# `sysctl --system`.
local result=$(echo '# LIBREPORTAL KERNEL HARDENING START' | sudo tee -a "$sysctl" > /dev/null) local hardening_conf="/etc/sysctl.d/99-libreportal-hardening.conf"
checkSuccess "Adding kernel hardening header to sysctl" sudo bash -c "cat > '$hardening_conf'" <<'EOL'
# LibrePortal kernel LPE-surface hardening (paired with rootless unprivileged userns)
local result=$(echo 'kernel.kptr_restrict=2' | sudo tee -a "$sysctl" > /dev/null) kernel.kptr_restrict=2
checkSuccess "Restricting kernel pointer exposure (kptr_restrict)" kernel.yama.ptrace_scope=1
net.core.bpf_jit_harden=2
local result=$(echo 'kernel.yama.ptrace_scope=1' | sudo tee -a "$sysctl" > /dev/null) EOL
checkSuccess "Restricting cross-process ptrace (yama.ptrace_scope)" checkSuccess "Writing kernel LPE-surface hardening to $hardening_conf"
local result=$(echo 'net.core.bpf_jit_harden=2' | sudo tee -a "$sysctl" > /dev/null)
checkSuccess "Hardening the BPF JIT (bpf_jit_harden)"
local result=$(echo '# LIBREPORTAL KERNEL HARDENING END' | sudo tee -a "$sysctl" > /dev/null)
checkSuccess "Adding kernel hardening end to sysctl"
isSuccessful "Applied kernel LPE-surface hardening"
fi
local result=$(sudo sysctl --system) local result=$(sudo sysctl --system)
checkSuccess "Applying changes to sysctl" checkSuccess "Applying changes to sysctl"

View File

@ -5,7 +5,7 @@ function checkSuccess()
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
isSuccessful "$1" isSuccessful "$1"
if [ -f "$logs_dir/$docker_log_file" ]; then if [ -f "$logs_dir/$docker_log_file" ]; then
echo "✓ Success $1" | runFileWrite -a "$logs_dir/$docker_log_file" >/dev/null echo "✓ Success $1" | runInstallWrite -a "$logs_dir/$docker_log_file" >/dev/null
fi fi
else else
isError "$1" isError "$1"
@ -14,8 +14,8 @@ function checkSuccess()
# blocking on read. # blocking on read.
if [[ "$LIBREPORTAL_NONINTERACTIVE" == "1" ]] || [ ! -t 0 ]; then if [[ "$LIBREPORTAL_NONINTERACTIVE" == "1" ]] || [ ! -t 0 ]; then
if [ -f "$logs_dir/$docker_log_file" ]; then if [ -f "$logs_dir/$docker_log_file" ]; then
isError " $1" | runFileWrite -a "$logs_dir/$docker_log_file" >/dev/null isError " $1" | runInstallWrite -a "$logs_dir/$docker_log_file" >/dev/null
echo "===================================" | runFileWrite -a "$logs_dir/$docker_log_file" >/dev/null echo "===================================" | runInstallWrite -a "$logs_dir/$docker_log_file" >/dev/null
fi fi
isNotice "Non-interactive mode: aborting on error." isNotice "Non-interactive mode: aborting on error."
exit 1 exit 1
@ -36,15 +36,15 @@ function checkSuccess()
if [[ "$error_occurred" == [xX] ]]; then if [[ "$error_occurred" == [xX] ]]; then
# Log the error output to the log file # Log the error output to the log file
isError " $1" | runFileWrite -a "$logs_dir/$docker_log_file" isError " $1" | runInstallWrite -a "$logs_dir/$docker_log_file"
echo "===================================" | runFileWrite -a "$logs_dir/$docker_log_file" echo "===================================" | runInstallWrite -a "$logs_dir/$docker_log_file"
exit 1 # Exit the script with a non-zero status to stop the current action exit 1 # Exit the script with a non-zero status to stop the current action
fi fi
if [[ "$error_occurred" == [mM] ]]; then if [[ "$error_occurred" == [mM] ]]; then
# Log the error output to the log file # Log the error output to the log file
isError " $1" | runFileWrite -a "$logs_dir/$docker_log_file" isError " $1" | runInstallWrite -a "$logs_dir/$docker_log_file"
echo "===================================" | runFileWrite -a "$logs_dir/$docker_log_file" echo "===================================" | runInstallWrite -a "$logs_dir/$docker_log_file"
if [[ "$initial_command2" == "terminal" ]]; then if [[ "$initial_command2" == "terminal" ]]; then
resetToMenu; resetToMenu;
fi fi

View File

@ -18,7 +18,7 @@ fixAppFolderPermissions()
# Updating $containers_dir with execute permissions # Updating $containers_dir with execute permissions
if [ -d "$containers_dir" ]; then if [ -d "$containers_dir" ]; then
local result=$(runFileOp chmod +x "$containers_dir" > /dev/null 2>&1) local result=$(runSystem chmod +x "$containers_dir" > /dev/null 2>&1)
if [ "$silent_flag" == "loud" ]; then if [ "$silent_flag" == "loud" ]; then
checkSuccess "Updating $containers_dir with execute permissions." checkSuccess "Updating $containers_dir with execute permissions."
fi fi
@ -30,7 +30,7 @@ fixAppFolderPermissions()
# Updating $containers_dir$app_name with execute permissions # Updating $containers_dir$app_name with execute permissions
if [ -d "$containers_dir$app_name" ]; then if [ -d "$containers_dir$app_name" ]; then
local result=$(runFileOp chmod +x "$containers_dir$app_name" > /dev/null 2>&1) local result=$(runSystem chmod +x "$containers_dir$app_name" > /dev/null 2>&1)
if [ "$silent_flag" == "loud" ]; then if [ "$silent_flag" == "loud" ]; then
checkSuccess "Updating $containers_dir$app_name with execute permissions." checkSuccess "Updating $containers_dir$app_name with execute permissions."
fi fi
@ -42,7 +42,7 @@ fixAppFolderPermissions()
# Updating $app_name with read permissions # Updating $app_name with read permissions
if [ -d "$containers_dir$app_name" ]; then if [ -d "$containers_dir$app_name" ]; then
local result=$(runFileOp chmod o+r "$containers_dir$app_name") local result=$(runSystem chmod o+r "$containers_dir$app_name")
if [ "$silent_flag" == "loud" ]; then if [ "$silent_flag" == "loud" ]; then
checkSuccess "Updating $app_name with read permissions" checkSuccess "Updating $app_name with read permissions"
fi fi
@ -54,7 +54,7 @@ fixAppFolderPermissions()
# Updating compose file(s) for LibrePortal access # Updating compose file(s) for LibrePortal access
if [ -d "$containers_dir$app_name" ]; then if [ -d "$containers_dir$app_name" ]; then
local result=$(runFileOp find "$containers_dir$app_name" -type f -name '*docker-compose*' -exec chmod o+r {} \;) local result=$(runSystem find "$containers_dir$app_name" -type f -name '*docker-compose*' -exec chmod o+r {} \;)
if [ "$silent_flag" == "loud" ]; then if [ "$silent_flag" == "loud" ]; then
isNotice "Updating compose file(s) for LibrePortal access" isNotice "Updating compose file(s) for LibrePortal access"
fi fi
@ -70,7 +70,7 @@ fixAppFolderPermissions()
local file_path="$containers_dir$app_name/$file" local file_path="$containers_dir$app_name/$file"
# Check if the file exists # Check if the file exists
if [ -e "$file_path" ]; then if [ -e "$file_path" ]; then
local result=$(runFileOp chown $docker_install_user:$docker_install_user "$file_path") local result=$(runSystem chown $docker_install_user:$docker_install_user "$file_path")
if [ "$silent_flag" == "loud" ]; then if [ "$silent_flag" == "loud" ]; then
checkSuccess "Updating $file with $docker_install_user ownership" checkSuccess "Updating $file with $docker_install_user ownership"
fi fi

View File

@ -5,23 +5,23 @@ fixFolderPermissions()
local silent_flag="$1" local silent_flag="$1"
local app_name="$2" local app_name="$2"
local result=$(runFileOp chmod +x "$docker_dir" > /dev/null 2>&1) local result=$(runSystem chmod +x "$docker_dir" > /dev/null 2>&1)
if [ "$silent_flag" == "loud" ]; then if [ "$silent_flag" == "loud" ]; then
checkSuccess "Updating $docker_dir with execute permissions." checkSuccess "Updating $docker_dir with execute permissions."
fi fi
local result=$(runFileOp chmod +x "$containers_dir" > /dev/null 2>&1) local result=$(runSystem chmod +x "$containers_dir" > /dev/null 2>&1)
if [ "$silent_flag" == "loud" ]; then if [ "$silent_flag" == "loud" ]; then
checkSuccess "Updating $containers_dir with execute permissions." checkSuccess "Updating $containers_dir with execute permissions."
fi fi
local result=$(runFileOp find "$script_dir" "$ssl_dir" "$ssh_dir" "$backup_dir" "$restore_dir" "$migrate_dir" -maxdepth 2 -type d -exec chmod +x {} \;) local result=$(runSystem find "$script_dir" "$ssl_dir" "$ssh_dir" "$backup_dir" "$restore_dir" "$migrate_dir" -maxdepth 2 -type d -exec chmod +x {} \;)
if [ "$silent_flag" == "loud" ]; then if [ "$silent_flag" == "loud" ]; then
checkSuccess "Adding execute permissions for $docker_install_user user" checkSuccess "Adding execute permissions for $docker_install_user user"
fi fi
# Install user related # Install user related
local result=$(runFileOp chown $docker_install_user:$docker_install_user "$containers_dir" > /dev/null 2>&1) local result=$(runSystem chown $docker_install_user:$docker_install_user "$containers_dir" > /dev/null 2>&1)
if [ "$silent_flag" == "loud" ]; then if [ "$silent_flag" == "loud" ]; then
checkSuccess "Updating $containers_dir with $docker_install_user ownership" checkSuccess "Updating $containers_dir with $docker_install_user ownership"
fi fi

View File

@ -8,7 +8,7 @@ tailscaleInstallToContainer()
local result=$(createFolders "loud" $docker_install_user $containers_dir$app_name/tailscale) local result=$(createFolders "loud" $docker_install_user $containers_dir$app_name/tailscale)
checkSuccess "Creating Tailscale folder" checkSuccess "Creating Tailscale folder"
copyFile "loud" "${install_scripts_dir}tailscale.sh" "$containers_dir$app_name/tailscale/tailscale.sh" $docker_install_user | runFileWrite -a "$logs_dir/$docker_log_file" 2>&1 copyFile "loud" "${install_scripts_dir}tailscale.sh" "$containers_dir$app_name/tailscale/tailscale.sh" $docker_install_user | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1
if [[ "$type" != "install" ]]; then if [[ "$type" != "install" ]]; then
dockerComposeRestart $app_name; dockerComposeRestart $app_name;

View File

@ -17,7 +17,7 @@
monitoringInstalledApps() monitoringInstalledApps()
{ {
[[ -f "$docker_dir/$db_file" ]] || return 0 [[ -f "$docker_dir/$db_file" ]] || return 0
runFileOp sqlite3 "$docker_dir/$db_file" \ runInstallOp sqlite3 "$docker_dir/$db_file" \
"SELECT name FROM apps WHERE status = 1 ORDER BY name;" 2>/dev/null "SELECT name FROM apps WHERE status = 1 ORDER BY name;" 2>/dev/null
} }
@ -26,7 +26,7 @@ monitoringIsInstalled()
{ {
[[ -f "$docker_dir/$db_file" ]] || return 1 [[ -f "$docker_dir/$db_file" ]] || return 1
local n local n
n="$(runFileOp sqlite3 "$docker_dir/$db_file" \ n="$(runInstallOp sqlite3 "$docker_dir/$db_file" \
"SELECT COUNT(*) FROM apps WHERE name = '$1' AND status = 1;" 2>/dev/null)" "SELECT COUNT(*) FROM apps WHERE name = '$1' AND status = 1;" 2>/dev/null)"
[[ -n "$n" && "$n" -gt 0 ]] [[ -n "$n" && "$n" -gt 0 ]]
} }

View File

@ -9,23 +9,23 @@ portStoreMapping()
local parent_service="$4" # parent Docker service (optional) local parent_service="$4" # parent Docker service (optional)
# Check if ports already exist for this app/service # Check if ports already exist for this app/service
local existing=$(runFileOp sqlite3 "$docker_dir/$db_file" "SELECT resource_value FROM network_resources WHERE app_name='$app_name' AND resource_type='port' AND service_name='$service_name' AND status='active';" 2>/dev/null) local existing=$(runInstallOp sqlite3 "$docker_dir/$db_file" "SELECT resource_value FROM network_resources WHERE app_name='$app_name' AND resource_type='port' AND service_name='$service_name' AND status='active';" 2>/dev/null)
if [[ -n "$existing" ]]; then if [[ -n "$existing" ]]; then
# UPDATE existing ports # UPDATE existing ports
if [[ -n "$parent_service" ]]; then if [[ -n "$parent_service" ]]; then
runFileOp sqlite3 "$docker_dir/$db_file" "UPDATE network_resources SET resource_value='$port_mapping', parent_service='$parent_service', created_time=CURRENT_TIME WHERE app_name='$app_name' AND resource_type='port' AND service_name='$service_name';" 2>/dev/null runInstallOp sqlite3 "$docker_dir/$db_file" "UPDATE network_resources SET resource_value='$port_mapping', parent_service='$parent_service', created_time=CURRENT_TIME WHERE app_name='$app_name' AND resource_type='port' AND service_name='$service_name';" 2>/dev/null
else else
runFileOp sqlite3 "$docker_dir/$db_file" "UPDATE network_resources SET resource_value='$port_mapping', created_time=CURRENT_TIME WHERE app_name='$app_name' AND resource_type='port' AND service_name='$service_name';" 2>/dev/null runInstallOp sqlite3 "$docker_dir/$db_file" "UPDATE network_resources SET resource_value='$port_mapping', created_time=CURRENT_TIME WHERE app_name='$app_name' AND resource_type='port' AND service_name='$service_name';" 2>/dev/null
fi fi
isNotice "Updated ports for $app_name/$service_name" isNotice "Updated ports for $app_name/$service_name"
#isNotice "Updated ports for $app_name/$service_name: $existing → $port_mapping" #isNotice "Updated ports for $app_name/$service_name: $existing → $port_mapping"
else else
# INSERT new ports # INSERT new ports
if [[ -n "$parent_service" ]]; then if [[ -n "$parent_service" ]]; then
runFileOp sqlite3 "$docker_dir/$db_file" "INSERT INTO network_resources (app_name, resource_type, resource_value, service_name, parent_service, status, created_date, created_time) VALUES ('$app_name', 'port', '$port_mapping', '$service_name', '$parent_service', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null runInstallOp sqlite3 "$docker_dir/$db_file" "INSERT INTO network_resources (app_name, resource_type, resource_value, service_name, parent_service, status, created_date, created_time) VALUES ('$app_name', 'port', '$port_mapping', '$service_name', '$parent_service', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null
else else
runFileOp sqlite3 "$docker_dir/$db_file" "INSERT INTO network_resources (app_name, resource_type, resource_value, service_name, status, created_date, created_time) VALUES ('$app_name', 'port', '$port_mapping', '$service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null runInstallOp sqlite3 "$docker_dir/$db_file" "INSERT INTO network_resources (app_name, resource_type, resource_value, service_name, status, created_date, created_time) VALUES ('$app_name', 'port', '$port_mapping', '$service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null
fi fi
isSuccessful "Allocated port: $port_mapping" isSuccessful "Allocated port: $port_mapping"
fi fi

View File

@ -108,14 +108,14 @@ portUpdateComposeTags()
# Only log to database if port is not disabled # Only log to database if port is not disabled
if [[ "$access_type_for_tag" != "disabled" ]]; then if [[ "$access_type_for_tag" != "disabled" ]]; then
# Log to database # Log to database
runFileOp sqlite3 "$docker_dir/$db_file" "INSERT OR REPLACE INTO network_resources (app_name, resource_type, resource_value, service_name, status, created_date, created_time) VALUES ('$app_name', 'port_tag_combined', '$combined_port', '$db_service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null runInstallOp sqlite3 "$docker_dir/$db_file" "INSERT OR REPLACE INTO network_resources (app_name, resource_type, resource_value, service_name, status, created_date, created_time) VALUES ('$app_name', 'port_tag_combined', '$combined_port', '$db_service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null
runFileOp sqlite3 "$docker_dir/$db_file" "INSERT OR REPLACE INTO network_resources (app_name, resource_type, resource_value, service_name, status, created_date, created_time) VALUES ('$app_name', 'port_tag_external', '$port_for_tag', '$db_service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null runInstallOp sqlite3 "$docker_dir/$db_file" "INSERT OR REPLACE INTO network_resources (app_name, resource_type, resource_value, service_name, status, created_date, created_time) VALUES ('$app_name', 'port_tag_external', '$port_for_tag', '$db_service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null
runFileOp sqlite3 "$docker_dir/$db_file" "INSERT OR REPLACE INTO network_resources (app_name, resource_type, resource_value, service_name, status, created_date, created_time) VALUES ('$app_name', 'port_tag_internal', '$internal_port_for_tag', '$db_service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null runInstallOp sqlite3 "$docker_dir/$db_file" "INSERT OR REPLACE INTO network_resources (app_name, resource_type, resource_value, service_name, status, created_date, created_time) VALUES ('$app_name', 'port_tag_internal', '$internal_port_for_tag', '$db_service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null
runFileOp sqlite3 "$docker_dir/$db_file" "INSERT OR REPLACE INTO network_resources (app_name, resource_type, resource_value, service_name, status, created_date, created_time) VALUES ('$app_name', 'traefik_managed', '$traefik_managed_for_tag', '$db_service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null runInstallOp sqlite3 "$docker_dir/$db_file" "INSERT OR REPLACE INTO network_resources (app_name, resource_type, resource_value, service_name, status, created_date, created_time) VALUES ('$app_name', 'traefik_managed', '$traefik_managed_for_tag', '$db_service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null
runFileOp sqlite3 "$docker_dir/$db_file" "INSERT OR REPLACE INTO network_resources (app_name, resource_type, resource_value, service_name, status, created_date, created_time) VALUES ('$app_name', 'url_accessible', '$url_accessible_for_tag', '$db_service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null runInstallOp sqlite3 "$docker_dir/$db_file" "INSERT OR REPLACE INTO network_resources (app_name, resource_type, resource_value, service_name, status, created_date, created_time) VALUES ('$app_name', 'url_accessible', '$url_accessible_for_tag', '$db_service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null
else else
# Log disabled port with 'disabled' status # Log disabled port with 'disabled' status
runFileOp sqlite3 "$docker_dir/$db_file" "INSERT OR REPLACE INTO network_resources (app_name, resource_type, resource_value, service_name, status, created_date, created_time) VALUES ('$app_name', 'port_tag_combined', '$combined_port', '$db_service_name', 'disabled', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null runInstallOp sqlite3 "$docker_dir/$db_file" "INSERT OR REPLACE INTO network_resources (app_name, resource_type, resource_value, service_name, status, created_date, created_time) VALUES ('$app_name', 'port_tag_combined', '$combined_port', '$db_service_name', 'disabled', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null
fi fi
done done