harden(desudo): convert crontab daemon, db-scan, port-allocation subsystems

All operate on /docker data-plane (DB at $docker_dir, compose files,
task dir /docker/.../frontend/data/tasks): sqlite3/find/sed/mkdir/chmod/
chown/mv/rm/mkfifo/truncate/install/tee -> runFileOp/runFileWrite. The
two systemctl enable/start calls in the check processor -> runSystem.
Dropped spurious sudo on text-only echo/grep/date in db_app_scan.
Byte-identical in rooted.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
librelad 2026-05-23 23:36:13 +01:00
parent 6e0dc04dd7
commit 582664aadf
6 changed files with 68 additions and 68 deletions

View File

@ -471,7 +471,7 @@ repairDirectoryStructure() {
# Create main tasks directory # Create main tasks directory
if [ ! -d "$TASK_DIR" ]; then if [ ! -d "$TASK_DIR" ]; then
healthLogInfo "Creating tasks directory: $TASK_DIR" healthLogInfo "Creating tasks directory: $TASK_DIR"
sudo mkdir -p "$TASK_DIR" || { runFileOp mkdir -p "$TASK_DIR" || {
healthLogError "Failed to create tasks directory" healthLogError "Failed to create tasks directory"
exit 1 exit 1
} }
@ -482,7 +482,7 @@ repairDirectoryStructure() {
local dirPath="$TASK_DIR/$dir" local dirPath="$TASK_DIR/$dir"
if [ ! -d "$dirPath" ]; then if [ ! -d "$dirPath" ]; then
healthLogInfo "Creating directory: $dirPath" healthLogInfo "Creating directory: $dirPath"
sudo mkdir -p "$dirPath" || { runFileOp mkdir -p "$dirPath" || {
healthLogError "Failed to create directory: $dirPath" healthLogError "Failed to create directory: $dirPath"
exit 1 exit 1
} }
@ -505,10 +505,10 @@ repairFileSystem() {
healthLogInfo "Creating missing file: $file" healthLogInfo "Creating missing file: $file"
case "$file" in case "$file" in
"queue.json") "queue.json")
echo "[]" | sudo tee "$filePath" > /dev/null && ((repaired++)) echo "[]" | runFileWrite "$filePath" && ((repaired++))
;; ;;
"current.json") "current.json")
echo "{}" | sudo tee "$filePath" > /dev/null && ((repaired++)) echo "{}" | runFileWrite "$filePath" && ((repaired++))
;; ;;
esac esac
fi fi
@ -521,19 +521,19 @@ repairPermissions() {
healthLogInfo "Repairing permissions..." healthLogInfo "Repairing permissions..."
# Fix directory permissions # Fix directory permissions
sudo chmod 755 "$TASK_DIR" 2>/dev/null runFileOp chmod 755 "$TASK_DIR" 2>/dev/null
# Fix file permissions # Fix file permissions
for file in "${CRITICAL_FILES[@]}"; do for file in "${CRITICAL_FILES[@]}"; do
local filePath="$TASK_DIR/$file" local filePath="$TASK_DIR/$file"
if [ -f "$filePath" ]; then if [ -f "$filePath" ]; then
sudo chmod 644 "$filePath" 2>/dev/null runFileOp chmod 644 "$filePath" 2>/dev/null
fi fi
done done
# Set ownership (if docker_install_user is available) # Set ownership (if docker_install_user is available)
if [ -n "$docker_install_user" ]; then if [ -n "$docker_install_user" ]; then
sudo chown -R $docker_install_user:$docker_install_user "$TASK_DIR" 2>/dev/null runFileOp chown -R $docker_install_user:$docker_install_user "$TASK_DIR" 2>/dev/null
fi fi
healthLogSuccess "Permissions repaired" healthLogSuccess "Permissions repaired"
@ -548,7 +548,7 @@ repairTaskSystem() {
if [ -f "$TASK_DIR/queue.json" ]; then if [ -f "$TASK_DIR/queue.json" ]; then
if ! python3 -c "import json; json.load(open('$TASK_DIR/queue.json'))" 2>/dev/null; then if ! python3 -c "import json; json.load(open('$TASK_DIR/queue.json'))" 2>/dev/null; then
healthLogInfo "Repairing corrupted queue.json" healthLogInfo "Repairing corrupted queue.json"
echo "[]" | sudo tee "$TASK_DIR/queue.json" > /dev/null && ((repaired++)) echo "[]" | runFileWrite "$TASK_DIR/queue.json" && ((repaired++))
fi fi
fi fi
@ -556,7 +556,7 @@ repairTaskSystem() {
if [ -f "$TASK_DIR/current.json" ]; then if [ -f "$TASK_DIR/current.json" ]; then
if ! python3 -c "import json; json.load(open('$TASK_DIR/current.json'))" 2>/dev/null; then if ! python3 -c "import json; json.load(open('$TASK_DIR/current.json'))" 2>/dev/null; then
healthLogInfo "Repairing corrupted current.json" healthLogInfo "Repairing corrupted current.json"
echo "{}" | sudo tee "$TASK_DIR/current.json" > /dev/null && ((repaired++)) echo "{}" | runFileWrite "$TASK_DIR/current.json" && ((repaired++))
fi fi
fi fi
@ -577,7 +577,7 @@ repairTaskSystem() {
local taskId=$(basename "$taskFile" .json) local taskId=$(basename "$taskFile" .json)
if ! echo "$queueContent $currentContent" | grep -q "$taskId"; then if ! echo "$queueContent $currentContent" | grep -q "$taskId"; then
healthLogInfo "Removing orphaned task file: $taskId" healthLogInfo "Removing orphaned task file: $taskId"
sudo rm -f "$taskFile" && ((repaired++)) runFileOp rm -f "$taskFile" && ((repaired++))
fi fi
fi fi
done done
@ -591,13 +591,13 @@ repairSystemService() {
# Enable service if not enabled # Enable service if not enabled
if ! systemctl is-enabled --quiet "$SERVICE_NAME" 2>/dev/null; then if ! systemctl is-enabled --quiet "$SERVICE_NAME" 2>/dev/null; then
healthLogInfo "Enabling systemd service: $SERVICE_NAME" healthLogInfo "Enabling systemd service: $SERVICE_NAME"
sudo systemctl enable "$SERVICE_NAME" 2>/dev/null runSystem systemctl enable "$SERVICE_NAME" 2>/dev/null
fi fi
# Start service if not active # Start service if not active
if ! systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then if ! systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
healthLogInfo "Starting systemd service: $SERVICE_NAME" healthLogInfo "Starting systemd service: $SERVICE_NAME"
sudo systemctl start "$SERVICE_NAME" 2>/dev/null runSystem systemctl start "$SERVICE_NAME" 2>/dev/null
fi fi
healthLogSuccess "Systemd service repaired" healthLogSuccess "Systemd service repaired"
@ -636,7 +636,7 @@ generateHealthReport() {
report+="}" report+="}"
report+="}" report+="}"
echo "$report" | sudo tee "$HEALTH_REPORT_FILE" > /dev/null echo "$report" | runFileWrite "$HEALTH_REPORT_FILE"
healthLogSuccess "Health report generated: $HEALTH_REPORT_FILE" healthLogSuccess "Health report generated: $HEALTH_REPORT_FILE"
} }
@ -662,8 +662,8 @@ performMaintenance() {
local fileSizeMB=$((fileSize / 1024 / 1024)) local fileSizeMB=$((fileSize / 1024 / 1024))
if [ $fileSizeMB -gt $MAX_LOG_SIZE_MB ]; then if [ $fileSizeMB -gt $MAX_LOG_SIZE_MB ]; then
healthLogInfo "Rotating large log: $(basename $logFile) (${fileSizeMB}MB)" healthLogInfo "Rotating large log: $(basename $logFile) (${fileSizeMB}MB)"
sudo mv "$logFile" "${logFile}.old" runFileOp mv "$logFile" "${logFile}.old"
sudo touch "$logFile" runFileOp touch "$logFile"
fi fi
fi fi
fi fi

View File

@ -47,9 +47,9 @@ IDLE_POLL_SECS=3 # max time we'll block on FIFO before re-scanning anyway
# LOGGING # LOGGING
# ============================================================================ # ============================================================================
logInfo() { echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO ] $*" | sudo tee -a "$LOG_FILE" >/dev/null; } logInfo() { echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO ] $*" | runFileWrite -a "$LOG_FILE"; }
logError() { echo "$(date '+%Y-%m-%d %H:%M:%S') [ERROR] $*" | sudo tee -a "$LOG_FILE" >/dev/null; } logError() { echo "$(date '+%Y-%m-%d %H:%M:%S') [ERROR] $*" | runFileWrite -a "$LOG_FILE"; }
logDebug() { [[ "${LOG_LEVEL:-INFO}" == "DEBUG" ]] && echo "$(date '+%Y-%m-%d %H:%M:%S') [DEBUG] $*" | sudo tee -a "$LOG_FILE" >/dev/null; } logDebug() { [[ "${LOG_LEVEL:-INFO}" == "DEBUG" ]] && echo "$(date '+%Y-%m-%d %H:%M:%S') [DEBUG] $*" | runFileWrite -a "$LOG_FILE"; }
# ============================================================================ # ============================================================================
# FILE OPS — atomic writes, JSON helpers # FILE OPS — atomic writes, JSON helpers
@ -61,9 +61,9 @@ logDebug() { [[ "${LOG_LEVEL:-INFO}" == "DEBUG" ]] && echo "$(date '+%Y-%m-%d %H
writeAtomic() { writeAtomic() {
local target="$1"; local content="$2" local target="$1"; local content="$2"
local tmp="${target}.tmp.$$" local tmp="${target}.tmp.$$"
printf '%s' "$content" | sudo tee "$tmp" >/dev/null printf '%s' "$content" | runFileWrite "$tmp"
sudo chmod 644 "$tmp" 2>/dev/null runFileOp chmod 644 "$tmp" 2>/dev/null
sudo mv "$tmp" "$target" runFileOp mv "$tmp" "$target"
} }
# Update one or more fields on a task file, atomically. Args after taskFile # Update one or more fields on a task file, atomically. Args after taskFile
@ -83,8 +83,8 @@ updateTaskFields() {
local tmp="${taskFile}.tmp.$$" local tmp="${taskFile}.tmp.$$"
jq "${jqArgs[@]}" "$jqExpr" "$taskFile" 2>/dev/null > "$tmp" \ jq "${jqArgs[@]}" "$jqExpr" "$taskFile" 2>/dev/null > "$tmp" \
&& sudo chmod 644 "$tmp" 2>/dev/null \ && runFileOp chmod 644 "$tmp" 2>/dev/null \
&& sudo mv "$tmp" "$taskFile" && runFileOp mv "$tmp" "$taskFile"
} }
readTaskField() { readTaskField() {
@ -99,16 +99,16 @@ readTaskField() {
# ============================================================================ # ============================================================================
setupTaskDir() { setupTaskDir() {
sudo mkdir -p "$TASK_DIR" runFileOp mkdir -p "$TASK_DIR"
if [[ ! -p "$FIFO" ]]; then if [[ ! -p "$FIFO" ]]; then
# Remove any stale non-FIFO file at that path before creating the FIFO. # Remove any stale non-FIFO file at that path before creating the FIFO.
[[ -e "$FIFO" ]] && sudo rm -f "$FIFO" [[ -e "$FIFO" ]] && runFileOp rm -f "$FIFO"
sudo mkfifo "$FIFO" 2>/dev/null runFileOp mkfifo "$FIFO" 2>/dev/null
fi fi
sudo chmod 666 "$FIFO" 2>/dev/null runFileOp chmod 666 "$FIFO" 2>/dev/null
sudo chmod 755 "$TASK_DIR" 2>/dev/null runFileOp chmod 755 "$TASK_DIR" 2>/dev/null
if [[ -n "$docker_install_user" ]]; then if [[ -n "$docker_install_user" ]]; then
sudo chown -R "$docker_install_user":"$docker_install_user" "$TASK_DIR" 2>/dev/null runFileOp chown -R "$docker_install_user":"$docker_install_user" "$TASK_DIR" 2>/dev/null
fi fi
} }
@ -129,7 +129,7 @@ acquireSingletonLock() {
logInfo "Another task processor is already running; this instance will exit." logInfo "Another task processor is already running; this instance will exit."
exit 0 exit 0
fi fi
echo $$ | sudo tee "${LOCK_FILE}.pid" >/dev/null 2>&1 echo $$ | runFileWrite "${LOCK_FILE}.pid" 2>/dev/null
} }
# ============================================================================ # ============================================================================
@ -194,7 +194,7 @@ runTask() {
logInfo "Task $taskId starting: $command" logInfo "Task $taskId starting: $command"
# Any pre-existing cancel marker is stale; remove it. # Any pre-existing cancel marker is stale; remove it.
[[ -f "$cancelMarker" ]] && sudo rm -f "$cancelMarker" [[ -f "$cancelMarker" ]] && runFileOp rm -f "$cancelMarker"
# Mark running with initial heartbeat. # Mark running with initial heartbeat.
local now; now=$(date -Iseconds) local now; now=$(date -Iseconds)
@ -211,11 +211,11 @@ runTask() {
# task immediately exited with rc=1. # task immediately exited with rc=1.
local daemonUser; daemonUser=$(id -un) local daemonUser; daemonUser=$(id -un)
if [[ -f "$logFile" ]]; then if [[ -f "$logFile" ]]; then
sudo chown "$daemonUser":"$daemonUser" "$logFile" 2>/dev/null runFileOp chown "$daemonUser":"$daemonUser" "$logFile" 2>/dev/null
sudo chmod 664 "$logFile" 2>/dev/null runFileOp chmod 664 "$logFile" 2>/dev/null
: > "$logFile" 2>/dev/null || sudo truncate -s 0 "$logFile" 2>/dev/null : > "$logFile" 2>/dev/null || runFileOp truncate -s 0 "$logFile" 2>/dev/null
else else
: > "$logFile" 2>/dev/null || sudo install -o "$daemonUser" -g "$daemonUser" -m 664 /dev/null "$logFile" : > "$logFile" 2>/dev/null || runFileOp install -o "$daemonUser" -g "$daemonUser" -m 664 /dev/null "$logFile"
fi fi
export LIBREPORTAL_NONINTERACTIVE=1 export LIBREPORTAL_NONINTERACTIVE=1
@ -261,7 +261,7 @@ runTask() {
logInfo "Task $taskId did not exit on TERM; sending SIGKILL." logInfo "Task $taskId did not exit on TERM; sending SIGKILL."
kill -KILL "-$cmdPid" 2>/dev/null kill -KILL "-$cmdPid" 2>/dev/null
fi fi
sudo rm -f "$cancelMarker" runFileOp rm -f "$cancelMarker"
exit 0 exit 0
fi fi
sleep 1 sleep 1
@ -287,7 +287,7 @@ runTask() {
if [[ -f "$cancelMarker" ]] || [[ $rc -eq 143 ]] || [[ $rc -eq 137 ]]; then if [[ -f "$cancelMarker" ]] || [[ $rc -eq 143 ]] || [[ $rc -eq 137 ]]; then
finalStatus="cancelled" finalStatus="cancelled"
errorMessage="Cancelled by user." errorMessage="Cancelled by user."
sudo rm -f "$cancelMarker" 2>/dev/null runFileOp rm -f "$cancelMarker" 2>/dev/null
elif [[ $rc -ne 0 ]]; then elif [[ $rc -ne 0 ]]; then
finalStatus="failed" finalStatus="failed"
errorMessage="Command exited with status $rc." errorMessage="Command exited with status $rc."
@ -301,7 +301,7 @@ runTask() {
error_message "$errorMessage" error_message "$errorMessage"
if [[ -n "$docker_install_user" ]]; then if [[ -n "$docker_install_user" ]]; then
sudo chown "$docker_install_user":"$docker_install_user" "$logFile" 2>/dev/null runFileOp chown "$docker_install_user":"$docker_install_user" "$logFile" 2>/dev/null
fi fi
case "$finalStatus" in case "$finalStatus" in
@ -370,7 +370,7 @@ cleanupZeroByteFiles() {
for f in "$TASK_DIR"/task_*; do for f in "$TASK_DIR"/task_*; do
[[ -f "$f" ]] || continue [[ -f "$f" ]] || continue
[[ -s "$f" ]] && continue [[ -s "$f" ]] && continue
sudo rm -f "$f" runFileOp rm -f "$f"
done done
} }

View File

@ -20,7 +20,7 @@ databaseAppScan()
fi fi
# Scan the folder and retrieve folder names # Scan the folder and retrieve folder names
local folder_names=$(sudo find "$containers_dir" -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) local folder_names=$(runFileOp find "$containers_dir" -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)
# Check if no folders are found # Check if no folders are found
if [ -z "$folder_names" ]; then if [ -z "$folder_names" ]; then
@ -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=$(sudo sqlite3 "$docker_dir/$db_file" "SELECT name, status, uninstall_date FROM apps;") local existing_folders=$(runFileOp 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=$(sudo sqlite3 "$docker_dir/$db_file" "UPDATE apps SET status = 1, uninstall_date = NULL WHERE name = '$folder_name';") local result=$(runFileOp 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
@ -61,10 +61,10 @@ databaseAppScan()
# Check if the folder contains a valid .config file # Check if the folder contains a valid .config file
if [ -f "$app_dir/$app_name.config" ]; then if [ -f "$app_dir/$app_name.config" ]; then
# Extract the date and time from the folder name (if present) # Extract the date and time from the folder name (if present)
local folder_datetime=$(sudo echo "$app_name" | sudo grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}') local folder_datetime=$(echo "$app_name" | grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}')
if [ -z "$folder_datetime" ]; then if [ -z "$folder_datetime" ]; then
# If no date and time are found in the folder name, use the current date and time # If no date and time are found in the folder name, use the current date and time
local folder_datetime=$(sudo date "+%Y-%m-%d %H:%M:%S") local folder_datetime=$(date "+%Y-%m-%d %H:%M:%S")
fi fi
# Split folder_datetime into date and time variables # Split folder_datetime into date and time variables
@ -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=$(sudo sqlite3 "$docker_dir/$db_file" "INSERT INTO apps (name, status, install_date, install_time) VALUES ('$app_name', 1, '$folder_date', '$folder_time');") 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');")
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=$(sudo sqlite3 "$docker_dir/$db_file" "DELETE FROM apps WHERE name = '$app_name';") local result=$(runFileOp 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;
@ -117,7 +117,7 @@ databaseAppScan()
if [[ "$folder_name" != "libreportal" ]]; then if [[ "$folder_name" != "libreportal" ]]; then
folder_path="$containers_dir/$folder_name" folder_path="$containers_dir/$folder_name"
if [ -d "$folder_path" ]; then if [ -d "$folder_path" ]; then
local num_files=$(sudo find "$folder_path" -maxdepth 1 -type f | wc -l) local num_files=$(runFileOp find "$folder_path" -maxdepth 1 -type f | wc -l)
# Check if the folder is empty, contains only a config file, has only a migrate.txt file, or contains both # Check if the folder is empty, contains only a config file, has only a migrate.txt file, or contains both
if [ "$num_files" -eq 0 ]; then if [ "$num_files" -eq 0 ]; then
@ -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=$(sudo sqlite3 "$docker_dir/$db_file" "DELETE FROM apps WHERE name = '$folder_name';") local result=$(runFileOp 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=$(sudo sqlite3 "$docker_dir/$db_file" "SELECT name FROM apps WHERE name = '$app_name' AND status = 1;") local app_check=$(runFileOp 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=$(sudo sqlite3 "$docker_dir/$db_file" "SELECT install_date, install_time FROM apps WHERE name = '$app_name';") local app_details=$(runFileOp 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=$(sudo 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=$(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)
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=$(sudo 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=$(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)
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=$(sudo sqlite3 "$docker_dir/$db_file" "SELECT name FROM apps WHERE name = 'traefik' AND status = 1;" 2>/dev/null) local traefik_installed=$(runFileOp 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=$(sudo sqlite3 "$docker_dir/$db_file" "SELECT resource_value FROM options WHERE option = 'domain_${app_name^^}_DOMAIN';" 2>/dev/null) _domain=$(runFileOp 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

@ -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=$(sudo 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=$(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)
if [[ -n "$existing" ]]; then if [[ -n "$existing" ]]; then
# UPDATE existing ports # UPDATE existing ports
if [[ -n "$parent_service" ]]; then if [[ -n "$parent_service" ]]; then
sudo 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 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
else else
sudo 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 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
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
sudo 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 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
else else
sudo 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 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
fi fi
isSuccessful "Allocated port: $port_mapping" isSuccessful "Allocated port: $port_mapping"
fi fi

View File

@ -70,7 +70,7 @@ portUpdateComposeTags()
# tag is still re-findable if the user later re-enables the port. # tag is still re-findable if the user later re-enables the port.
if [[ -z "$port_for_tag" ]]; then if [[ -z "$port_for_tag" ]]; then
if [[ "$access_type_for_tag" == "disabled" ]]; then if [[ "$access_type_for_tag" == "disabled" ]]; then
sudo sed -i 's@^\(\s*\)- "PORTS_DATA_'"$port_num"'" #LIBREPORTAL|'"$port_tag"'@\1# - "PORTS_DATA_'"$port_num"'" #LIBREPORTAL|'"$port_tag"'@g' "$full_file_path" runFileOp sed -i 's@^\(\s*\)- "PORTS_DATA_'"$port_num"'" #LIBREPORTAL|'"$port_tag"'@\1# - "PORTS_DATA_'"$port_num"'" #LIBREPORTAL|'"$port_tag"'@g' "$full_file_path"
isSuccessful "Port $port_tag is disabled — placeholder commented out in compose." isSuccessful "Port $port_tag is disabled — placeholder commented out in compose."
else else
isNotice "No port allocation found for $port_tag, skipping..." isNotice "No port allocation found for $port_tag, skipping..."
@ -94,11 +94,11 @@ portUpdateComposeTags()
# Check if access type is disabled - if so, comment out the port line after updating # Check if access type is disabled - if so, comment out the port line after updating
if [[ "$access_type_for_tag" == "disabled" ]]; then if [[ "$access_type_for_tag" == "disabled" ]]; then
# Comment out the port line in docker-compose.yml using the actual port data # Comment out the port line in docker-compose.yml using the actual port data
sudo sed -i 's@ - "'"$combined_port"'" #LIBREPORTAL|'"$port_tag"'@ # - "'"$combined_port"'" #LIBREPORTAL|'"$port_tag"'@g' "$full_file_path" runFileOp sed -i 's@ - "'"$combined_port"'" #LIBREPORTAL|'"$port_tag"'@ # - "'"$combined_port"'" #LIBREPORTAL|'"$port_tag"'@g' "$full_file_path"
isSuccessful "Port $port_tag has been disabled as per config" isSuccessful "Port $port_tag has been disabled as per config"
else else
# Uncomment the port line if it was previously disabled # Uncomment the port line if it was previously disabled
sudo sed -i 's@ # - "'"$combined_port"'" #LIBREPORTAL|'"$port_tag"'@ - "'"$combined_port"'" #LIBREPORTAL|'"$port_tag"'@g' "$full_file_path" runFileOp sed -i 's@ # - "'"$combined_port"'" #LIBREPORTAL|'"$port_tag"'@ - "'"$combined_port"'" #LIBREPORTAL|'"$port_tag"'@g' "$full_file_path"
isSuccessful "Port $port_tag has been enabled as per config" isSuccessful "Port $port_tag has been enabled as per config"
fi fi
@ -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
sudo 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_combined', '$combined_port', '$db_service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null
sudo 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_external', '$port_for_tag', '$db_service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null
sudo 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', 'port_tag_internal', '$internal_port_for_tag', '$db_service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null
sudo 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', 'traefik_managed', '$traefik_managed_for_tag', '$db_service_name', 'active', CURRENT_DATE, CURRENT_TIME);" 2>/dev/null
sudo 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 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
else else
# Log disabled port with 'disabled' status # Log disabled port with 'disabled' status
sudo 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 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
fi fi
done done