Compare commits

..

No commits in common. "bace5020443cb4c31a7af3ff4b0a0f32bcd23973" and "c6a27d28c45bfe3c145d21b9745d6545e7d01638" have entirely different histories.

10 changed files with 25 additions and 34 deletions

View File

@ -1191,12 +1191,6 @@ completeInitMessage()
fi fi
} }
# Only run the installer entrypoint (root check + init flow) when init.sh is
# EXECUTED directly. When it's SOURCED — start.sh loads init.sh for its function
# defs at runtime, and under Model A start.sh runs as the manager, not root — the
# defs above are all that's wanted and this root check must NOT fire.
[[ "${BASH_SOURCE[0]}" != "${0}" ]] && return 0 2>/dev/null
if [[ $EUID -ne 0 ]]; then if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root." echo "This script must be run as root."
exit 1 exit 1

View File

@ -24,17 +24,17 @@ appStatus()
isHeader "App Status: $app_name" isHeader "App Status: $app_name"
# Check if container is running # Check if container is running
if runFileOp docker ps --format '{{.Names}}' | grep -q "^${app_name}$"; then if docker ps --format '{{.Names}}' | grep -q "^${app_name}$"; then
isSuccessful "Container: RUNNING" isSuccessful "Container: RUNNING"
else else
isNotice "Container: STOPPED" isNotice "Container: STOPPED"
fi fi
# Show basic container info if running # Show basic container info if running
if runFileOp docker ps --format '{{.Names}}' | grep -q "^${app_name}$"; then if docker ps --format '{{.Names}}' | grep -q "^${app_name}$"; then
echo "" echo ""
echo "Container Information:" echo "Container Information:"
runFileOp docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep "$app_name" || echo "No port information available" docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep "$app_name" || echo "No port information available"
fi fi
echo "" echo ""

View File

@ -148,9 +148,9 @@ _backupDbWaitReady()
good=0 good=0
case "$kind" in case "$kind" in
postgres) postgres)
runFileOp docker exec "$container" sh -c 'export PGPASSWORD="${POSTGRES_PASSWORD:-}"; psql -U "${POSTGRES_USER:-postgres}" -d "${POSTGRES_DB:-${POSTGRES_USER:-postgres}}" -tAc "SELECT 1"' >/dev/null 2>&1 && good=1 ;; docker exec "$container" sh -c 'export PGPASSWORD="${POSTGRES_PASSWORD:-}"; psql -U "${POSTGRES_USER:-postgres}" -d "${POSTGRES_DB:-${POSTGRES_USER:-postgres}}" -tAc "SELECT 1"' >/dev/null 2>&1 && good=1 ;;
*) *)
runFileOp docker exec "$container" sh -c 'RP="${MARIADB_ROOT_PASSWORD:-$MYSQL_ROOT_PASSWORD}"; mariadb -uroot -p"$RP" -N -e "SELECT 1" 2>/dev/null || mysql -uroot -p"$RP" -N -e "SELECT 1"' >/dev/null 2>&1 && good=1 ;; docker exec "$container" sh -c 'RP="${MARIADB_ROOT_PASSWORD:-$MYSQL_ROOT_PASSWORD}"; mariadb -uroot -p"$RP" -N -e "SELECT 1" 2>/dev/null || mysql -uroot -p"$RP" -N -e "SELECT 1"' >/dev/null 2>&1 && good=1 ;;
esac esac
if [[ $good -eq 1 ]]; then if [[ $good -eq 1 ]]; then
ok=$((ok + 1)) ok=$((ok + 1))
@ -199,7 +199,7 @@ backupDbDump()
case "$kind" in case "$kind" in
postgres) postgres)
isNotice "Dumping postgres ($container) — live, consistent" isNotice "Dumping postgres ($container) — live, consistent"
if runFileOp docker exec "$container" sh -c \ if docker exec "$container" sh -c \
'export PGPASSWORD="${POSTGRES_PASSWORD:-}"; pg_dump --clean --if-exists -U "${POSTGRES_USER:-postgres}" -d "${POSTGRES_DB:-${POSTGRES_USER:-postgres}}"' \ 'export PGPASSWORD="${POSTGRES_PASSWORD:-}"; pg_dump --clean --if-exists -U "${POSTGRES_USER:-postgres}" -d "${POSTGRES_DB:-${POSTGRES_USER:-postgres}}"' \
2>/dev/null | gzip | runFileWrite "$dump"; then 2>/dev/null | gzip | runFileWrite "$dump"; then
isSuccessful "postgres dump written ($container)" isSuccessful "postgres dump written ($container)"
@ -209,7 +209,7 @@ backupDbDump()
;; ;;
mysql|mariadb) mysql|mariadb)
isNotice "Dumping $kind ($container) — live, consistent" isNotice "Dumping $kind ($container) — live, consistent"
if runFileOp docker exec "$container" sh -c \ if docker exec "$container" sh -c \
'RP="${MARIADB_ROOT_PASSWORD:-$MYSQL_ROOT_PASSWORD}"; DB="${MARIADB_DATABASE:-$MYSQL_DATABASE}"; (mariadb-dump -uroot -p"$RP" --single-transaction --routines --triggers --databases "$DB" 2>/dev/null || mysqldump -uroot -p"$RP" --single-transaction --routines --triggers --databases "$DB")' \ 'RP="${MARIADB_ROOT_PASSWORD:-$MYSQL_ROOT_PASSWORD}"; DB="${MARIADB_DATABASE:-$MYSQL_DATABASE}"; (mariadb-dump -uroot -p"$RP" --single-transaction --routines --triggers --databases "$DB" 2>/dev/null || mysqldump -uroot -p"$RP" --single-transaction --routines --triggers --databases "$DB")' \
2>/dev/null | gzip | runFileWrite "$dump"; then 2>/dev/null | gzip | runFileWrite "$dump"; then
isSuccessful "$kind dump written ($container)" isSuccessful "$kind dump written ($container)"

View File

@ -18,8 +18,8 @@ checkDockerNetworkRequirement()
((preinstallneeded++)) ((preinstallneeded++))
fi fi
elif [[ $CFG_DOCKER_INSTALL_TYPE == "rooted" ]]; then elif [[ $CFG_DOCKER_INSTALL_TYPE == "rooted" ]]; then
if runFileOp docker network inspect $CFG_NETWORK_NAME > /dev/null 2>&1; then if docker network inspect $CFG_NETWORK_NAME > /dev/null 2>&1; then
local current_subnet=$(runFileOp docker network inspect $CFG_NETWORK_NAME --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' 2>/dev/null) local current_subnet=$(docker network inspect $CFG_NETWORK_NAME --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' 2>/dev/null)
if [[ "$current_subnet" == "$CFG_NETWORK_SUBNET" ]]; then if [[ "$current_subnet" == "$CFG_NETWORK_SUBNET" ]]; then
isSuccessful "Docker Network $CFG_NETWORK_NAME exists with matching subnet" isSuccessful "Docker Network $CFG_NETWORK_NAME exists with matching subnet"

View File

@ -1,17 +1,14 @@
#!/bin/bash #!/bin/bash
checkRootRequirement() checkRootRequirement()
{ {
if [[ $CFG_REQUIREMENT_ROOT == "true" ]]; then if [[ $CFG_REQUIREMENT_ROOT == "true" ]]; then
# Model A least-privilege: the app runs AS the manager user and escalates # Check if script is run as root
# only specific commands via runSystem, so accept the manager as well as if [[ $EUID -ne 0 ]]; then
# root — not root-only. (init.sh keeps its own install-time root check.) echo "This script must be run as root."
local mgr="${sudo_user_name:-libreportal}"
if [[ $EUID -eq 0 || "$(id -un)" == "$mgr" ]]; then
isSuccessful "Running as $(id -un)."
else
echo "This script must be run as root or the manager user ($mgr)."
exit 1 exit 1
else
isSuccessful "Script ran under root user."
fi fi
fi fi
} }

View File

@ -204,7 +204,7 @@ validateDockerService() {
} }
validateContainerHealth() { validateContainerHealth() {
local containerInfo=$(runFileOp docker ps -a --filter "name=libreportal-service" --format "{{.Status}}|{{.Names}}" 2>/dev/null) local containerInfo=$(docker ps -a --filter "name=libreportal-service" --format "{{.Status}}|{{.Names}}" 2>/dev/null)
if [ -z "$containerInfo" ]; then if [ -z "$containerInfo" ]; then
healthLogError "LibrePortal WebUI container not found" healthLogError "LibrePortal WebUI container not found"
@ -214,7 +214,7 @@ validateContainerHealth() {
if echo "$status" | grep -q "Up"; then if echo "$status" | grep -q "Up"; then
# Check if container is responsive # Check if container is responsive
if runFileOp docker exec libreportal-service pgrep -f "node.*webui" >/dev/null 2>&1; then if docker exec libreportal-service pgrep -f "node.*webui" >/dev/null 2>&1; then
healthLogSuccess "Container is running and responsive" healthLogSuccess "Container is running and responsive"
else else
healthLogWarning "Container is running but WebUI process not found" healthLogWarning "Container is running but WebUI process not found"
@ -226,7 +226,7 @@ validateContainerHealth() {
validateWebUIReadiness() { validateWebUIReadiness() {
# Get the actual port mapping from the container # Get the actual port mapping from the container
local portMapping=$(runFileOp docker port libreportal-service 2>/dev/null | head -1) local portMapping=$(docker port libreportal-service 2>/dev/null | head -1)
if [ -z "$portMapping" ]; then if [ -z "$portMapping" ]; then
healthLogWarning "No port mapping found for libreportal-service container" healthLogWarning "No port mapping found for libreportal-service container"

View File

@ -4,6 +4,6 @@ dockerCheckAppHealthDetails()
{ {
local app_name="$1" local app_name="$1"
result=$(runFileOp docker inspect --format "{{json .State.Health }}" $app_name | jq) result=$(docker inspect --format "{{json .State.Health }}" $app_name | jq)
checkSuccess "Getting $app_name health details." checkSuccess "Getting $app_name health details."
} }

View File

@ -4,6 +4,6 @@ dockerCheckAppHealthStatus()
{ {
local app_name="$1" local app_name="$1"
result=$(runFileOp docker inspect --format "{{json .State.Health.Status }}" $app_name) result=$(docker inspect --format "{{json .State.Health.Status }}" $app_name)
checkSuccess "Getting $app_name health status." checkSuccess "Getting $app_name health status."
} }

View File

@ -7,11 +7,11 @@ dockerPruneAppNetworks()
if [ ! -z "$app_name" ]; then if [ ! -z "$app_name" ]; then
local networks_found=false local networks_found=false
# Prune all networks except those containing the specified app_name # Prune all networks except those containing the specified app_name
for network_id in $(runFileOp docker network ls --quiet); do for network_id in $(docker network ls --quiet); do
network_name=$(runFileOp docker network inspect --format '{{.Name}}' "$network_id") network_name=$(docker network inspect --format '{{.Name}}' "$network_id")
if [[ "$network_name" == *"$app_name"* ]]; then if [[ "$network_name" == *"$app_name"* ]]; then
local result=$(dockerCommandRun "docker network rm "$network_id"") local result=$(dockerCommandRun "docker network rm "$network_id"")
checkSuccess "Removing the unused runFileOp docker network - $network_name" checkSuccess "Removing the unused docker network - $network_name"
networks_found=true networks_found=true
fi fi
done done

View File

@ -14,7 +14,7 @@ ipIsAvailable()
local existing=$(sqlite3 "$docker_dir/$db_file" "SELECT resource_value FROM network_resources WHERE resource_type = 'ip' AND resource_value = '$test_ip' AND status = 'active';" 2>/dev/null) local existing=$(sqlite3 "$docker_dir/$db_file" "SELECT resource_value FROM network_resources WHERE resource_type = 'ip' AND resource_value = '$test_ip' AND status = 'active';" 2>/dev/null)
if [[ -n "$existing" ]]; then if [[ -n "$existing" ]]; then
ip_available="" ip_available=""
elif runFileOp docker network inspect $CFG_NETWORK_NAME --format '{{range .Containers}}{{.IPv4Address}} {{end}}' 2>/dev/null | grep -q "$test_ip"; then elif docker network inspect $CFG_NETWORK_NAME --format '{{range .Containers}}{{.IPv4Address}} {{end}}' 2>/dev/null | grep -q "$test_ip"; then
ip_available="" ip_available=""
else else
ip_available="$test_ip" ip_available="$test_ip"