mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-04-04 17:21:23 -07:00
New PUID startup sequence
This commit is contained in:
@@ -1,68 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# 0-storage-permission.sh: Fix permissions if running as root.
|
||||
#
|
||||
# This script checks if running as root and fixes ownership and permissions
|
||||
# for read-write paths to ensure proper operation.
|
||||
|
||||
# --- Color Codes ---
|
||||
MAGENTA=$(printf '\033[1;35m')
|
||||
RESET=$(printf '\033[0m')
|
||||
|
||||
# --- Main Logic ---
|
||||
|
||||
# Define paths that need read-write access
|
||||
READ_WRITE_PATHS="
|
||||
${NETALERTX_DATA}
|
||||
${NETALERTX_DB}
|
||||
${NETALERTX_API}
|
||||
${NETALERTX_LOG}
|
||||
${SYSTEM_SERVICES_RUN}
|
||||
${NETALERTX_CONFIG}
|
||||
${NETALERTX_CONFIG_FILE}
|
||||
${NETALERTX_DB_FILE}
|
||||
"
|
||||
|
||||
TARGET_USER="${NETALERTX_USER:-netalertx}"
|
||||
|
||||
# If running as root, fix permissions first
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
>&2 printf "%s" "${MAGENTA}"
|
||||
>&2 cat <<'EOF'
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
🚨 CRITICAL SECURITY ALERT: NetAlertX is running as ROOT (UID 0)! 🚨
|
||||
|
||||
This configuration bypasses all built-in security hardening measures.
|
||||
You've granted a network monitoring application unrestricted access to
|
||||
your host system. A successful compromise here could jeopardize your
|
||||
entire infrastructure.
|
||||
|
||||
IMMEDIATE ACTION REQUIRED: Switch to the dedicated 'netalertx' user:
|
||||
* Remove any 'user:' directive specifying UID 0 from docker-compose.yml or
|
||||
* switch to the default USER in the image (20211:20211)
|
||||
|
||||
IMPORTANT: This corrective mode automatically adjusts ownership of
|
||||
/data/db and /data/config directories to the netalertx user, ensuring
|
||||
proper operation in subsequent runs.
|
||||
|
||||
Remember: Never operate security-critical tools as root unless you're
|
||||
actively trying to get pwned.
|
||||
|
||||
https://github.com/jokob-sk/NetAlertX/blob/main/docs/docker-troubleshooting/running-as-root.md
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
|
||||
# Set ownership and permissions for each read-write path individually
|
||||
printf '%s\n' "${READ_WRITE_PATHS}" | while IFS= read -r path; do
|
||||
[ -n "${path}" ] || continue
|
||||
chown -R "${TARGET_USER}" "${path}" 2>/dev/null || true
|
||||
find "${path}" -type d -exec chmod u+rwx {} \;
|
||||
find "${path}" -type f -exec chmod u+rw {} \;
|
||||
done
|
||||
echo Permissions fixed for read-write paths. Please restart the container as user ${TARGET_USER}.
|
||||
sleep infinity & wait $!
|
||||
fi
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
#!/bin/sh
|
||||
# 01-data-migration.sh - consolidate legacy /app mounts into /data
|
||||
# 05-data-migration.sh - Consolidate legacy /app mounts into /data
|
||||
#
|
||||
# This script migrates NetAlertX data from legacy mount points (/app/config and /app/db)
|
||||
# to the new consolidated /data directory. It runs during container startup as part of the
|
||||
# entrypoint process.
|
||||
#
|
||||
# Function:
|
||||
# - Checks for existing migration markers to avoid re-migration.
|
||||
# - Detects if legacy directories are mounted.
|
||||
# - Ensures the new /data directory is mounted.
|
||||
# - Copies configuration and database files from legacy paths to /data.
|
||||
# - Sets migration markers in legacy directories to prevent future migrations.
|
||||
# - Provides warnings and errors for various mount states.
|
||||
#
|
||||
# Migration Conditions:
|
||||
# - Both /app/config and /app/db must be mounted (legacy mounts present).
|
||||
# - /data must be mounted (new consolidated volume).
|
||||
# - No .migration marker files exist in legacy directories (not already migrated).
|
||||
#
|
||||
# Exit Codes:
|
||||
# - 0: Success, no action needed, or migration completed.
|
||||
# - 1: Migration failure (e.g., copy errors).
|
||||
#
|
||||
# The script exits early with 0 for non-fatal conditions like partial mounts or already migrated.
|
||||
|
||||
set -eu
|
||||
|
||||
@@ -37,7 +60,7 @@ EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
}
|
||||
|
||||
fatal_missing_data_mount() {
|
||||
possibly_fatal_missing_data_mount() { # Fatal if read-only mode, data loss if not.
|
||||
>&2 printf "%s" "${RED}"
|
||||
>&2 cat <<EOF
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
@@ -137,8 +160,11 @@ EOF
|
||||
fi
|
||||
|
||||
if ! ${DATA_MOUNTED}; then
|
||||
fatal_missing_data_mount
|
||||
exit 1
|
||||
# Warn about missing /data mount. Migration cannot proceed, but we allow container
|
||||
# startup to continue. Data written to /data will be ephemeral, though legacy
|
||||
# mount data remains safe and accessible.
|
||||
possibly_fatal_missing_data_mount
|
||||
exit 0
|
||||
fi
|
||||
|
||||
migrate_legacy_mounts || exit 1
|
||||
|
||||
69
install/production-filesystem/entrypoint.d/10-capabilities-audit.sh
Executable file
69
install/production-filesystem/entrypoint.d/10-capabilities-audit.sh
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/bin/sh
|
||||
# 10-capabilities-audit.sh - Inspects the container bounding set for required privileges.
|
||||
#
|
||||
# This script runs early to detect missing capabilities that would cause later
|
||||
# scripts (like Python-based checks) to fail with "Operation not permitted".
|
||||
|
||||
RED=$(printf '\033[1;31m')
|
||||
YELLOW=$(printf '\033[1;33m')
|
||||
GREY=$(printf '\033[90m')
|
||||
RESET=$(printf '\033[0m')
|
||||
|
||||
# Parse Bounding Set from /proc/self/status
|
||||
cap_bnd_hex=$(awk '/CapBnd/ {print $2}' /proc/self/status 2>/dev/null || echo "0")
|
||||
# Convert hex to dec (POSIX compliant)
|
||||
cap_bnd_dec=$(awk -v hex="$cap_bnd_hex" 'BEGIN { h = "0x" hex; if (h ~ /^0x[0-9A-Fa-f]+$/) { printf "%d", h } else { print 0 } }')
|
||||
|
||||
has_cap() {
|
||||
bit=$1
|
||||
# Check if bit is set in cap_bnd_dec
|
||||
[ $(( (cap_bnd_dec >> bit) & 1 )) -eq 1 ]
|
||||
}
|
||||
|
||||
# 1. ALERT: Python Requirements (NET_RAW=13, NET_ADMIN=12)
|
||||
if ! has_cap 13 || ! has_cap 12; then
|
||||
printf "%s" "${RED}"
|
||||
cat <<'EOF'
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
🚨 ALERT: Python execution capabilities (NET_RAW/NET_ADMIN) are missing.
|
||||
|
||||
The Python binary in this image has file capabilities (+eip) that
|
||||
require these bits in the container's bounding set. Without them,
|
||||
the binary will fail to execute (Operation not permitted).
|
||||
|
||||
Restart with: --cap-add=NET_RAW --cap-add=NET_ADMIN
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
printf "%s" "${RESET}"
|
||||
fi
|
||||
|
||||
# 2. WARNING: NET_BIND_SERVICE (10)
|
||||
if ! has_cap 10; then
|
||||
printf "%s" "${YELLOW}"
|
||||
cat <<'EOF'
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
⚠️ WARNING: Reduced functionality (NET_BIND_SERVICE missing).
|
||||
|
||||
Tools like nbtscan cannot bind to privileged ports (UDP 137).
|
||||
This will reduce discovery accuracy for legacy devices.
|
||||
|
||||
Consider adding: --cap-add=NET_BIND_SERVICE
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
printf "%s" "${RESET}"
|
||||
fi
|
||||
|
||||
# 3. NOTE: Security Context (CHOWN=0, SETGID=6, SETUID=7)
|
||||
missing_admin=""
|
||||
has_cap 0 || missing_admin="${missing_admin} CHOWN"
|
||||
has_cap 6 || missing_admin="${missing_admin} SETGID"
|
||||
has_cap 7 || missing_admin="${missing_admin} SETUID"
|
||||
|
||||
if [ -n "${missing_admin}" ]; then
|
||||
printf "%sSecurity context: Operational capabilities (%s) not granted.%s\n" "${GREY}" "${missing_admin# }" "${RESET}"
|
||||
if echo "${missing_admin}" | grep -q "CHOWN"; then
|
||||
printf "%sSee https://github.com/jokob-sk/NetAlertX/blob/main/docs/docker-troubleshooting/missing-capabilities.md%s\n" "${GREY}" "${RESET}"
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -326,8 +326,7 @@ def _apply_primary_rules(specs: list[PathSpec], results_map: dict[str, MountChec
|
||||
|
||||
suppress_primary = False
|
||||
if all_core_subs_healthy and all_core_subs_are_mounts:
|
||||
if not result.is_mount_point and not result.error and not result.write_error and not result.read_error:
|
||||
suppress_primary = True
|
||||
suppress_primary = True
|
||||
|
||||
if suppress_primary:
|
||||
# All sub-paths are healthy and mounted; suppress the aggregate row.
|
||||
@@ -368,104 +367,110 @@ def main():
|
||||
r.dataloss_risk or r.error or r.write_error or r.read_error or r.performance_issue
|
||||
for r in results
|
||||
)
|
||||
has_rw_errors = any(r.write_error or r.read_error for r in results)
|
||||
has_rw_errors = any(
|
||||
(r.write_error or r.read_error) and r.category == "persist"
|
||||
for r in results
|
||||
)
|
||||
has_primary_dataloss = any(
|
||||
r.category == "persist" and r.role == "primary" and r.dataloss_risk and r.is_mount_point
|
||||
for r in results
|
||||
)
|
||||
|
||||
if has_issues or True: # Always print table for diagnostic purposes
|
||||
# --- Print Table ---
|
||||
headers = ["Path", "R", "W", "Mount", "RAMDisk", "Performance", "DataLoss"]
|
||||
# --- Print Table ---
|
||||
headers = ["Path", "R", "W", "Mount", "RAMDisk", "Performance", "DataLoss"]
|
||||
|
||||
CHECK_SYMBOL = "✅"
|
||||
CROSS_SYMBOL = "❌"
|
||||
BLANK_SYMBOL = "➖"
|
||||
CHECK_SYMBOL = "✅"
|
||||
CROSS_SYMBOL = "❌"
|
||||
BLANK_SYMBOL = "➖"
|
||||
|
||||
def bool_to_check(is_good):
|
||||
return CHECK_SYMBOL if is_good else CROSS_SYMBOL
|
||||
def bool_to_check(is_good):
|
||||
return CHECK_SYMBOL if is_good else CROSS_SYMBOL
|
||||
|
||||
col_widths = [len(h) for h in headers]
|
||||
for r in results:
|
||||
col_widths[0] = max(col_widths[0], len(str(r.path)))
|
||||
col_widths = [len(h) for h in headers]
|
||||
for r in results:
|
||||
col_widths[0] = max(col_widths[0], len(str(r.path)))
|
||||
|
||||
header_fmt = (
|
||||
f" {{:<{col_widths[0]}}} |"
|
||||
f" {{:^{col_widths[1]}}} |"
|
||||
f" {{:^{col_widths[2]}}} |"
|
||||
f" {{:^{col_widths[3]}}} |"
|
||||
f" {{:^{col_widths[4]}}} |"
|
||||
f" {{:^{col_widths[5]}}} |"
|
||||
f" {{:^{col_widths[6]}}} "
|
||||
)
|
||||
header_fmt = (
|
||||
f" {{:<{col_widths[0]}}} |"
|
||||
f" {{:^{col_widths[1]}}} |"
|
||||
f" {{:^{col_widths[2]}}} |"
|
||||
f" {{:^{col_widths[3]}}} |"
|
||||
f" {{:^{col_widths[4]}}} |"
|
||||
f" {{:^{col_widths[5]}}} |"
|
||||
f" {{:^{col_widths[6]}}} "
|
||||
)
|
||||
|
||||
row_fmt = (
|
||||
f" {{:<{col_widths[0]}}} |"
|
||||
f" {{:^{col_widths[1]}}}|" # No space
|
||||
f" {{:^{col_widths[2]}}}|" # No space
|
||||
f" {{:^{col_widths[3]}}}|" # No space
|
||||
f" {{:^{col_widths[4]}}}|" # No space
|
||||
f" {{:^{col_widths[5]}}}|" # No space
|
||||
f" {{:^{col_widths[6]}}} " # DataLoss is last, needs space
|
||||
)
|
||||
row_fmt = (
|
||||
f" {{:<{col_widths[0]}}} |"
|
||||
f" {{:^{col_widths[1]}}}|" # No space - intentional
|
||||
f" {{:^{col_widths[2]}}}|" # No space - intentional
|
||||
f" {{:^{col_widths[3]}}}|" # No space - intentional
|
||||
f" {{:^{col_widths[4]}}}|" # No space - intentional
|
||||
f" {{:^{col_widths[5]}}}|" # No space - intentional
|
||||
f" {{:^{col_widths[6]}}} " # DataLoss is last, needs space
|
||||
)
|
||||
|
||||
separator = "".join([
|
||||
"-" * (col_widths[0] + 2),
|
||||
"+",
|
||||
"-" * (col_widths[1] + 2),
|
||||
"+",
|
||||
"-" * (col_widths[2] + 2),
|
||||
"+",
|
||||
"-" * (col_widths[3] + 2),
|
||||
"+",
|
||||
"-" * (col_widths[4] + 2),
|
||||
"+",
|
||||
"-" * (col_widths[5] + 2),
|
||||
"+",
|
||||
"-" * (col_widths[6] + 2)
|
||||
])
|
||||
separator = "".join([
|
||||
"-" * (col_widths[0] + 2),
|
||||
"+",
|
||||
"-" * (col_widths[1] + 2),
|
||||
"+",
|
||||
"-" * (col_widths[2] + 2),
|
||||
"+",
|
||||
"-" * (col_widths[3] + 2),
|
||||
"+",
|
||||
"-" * (col_widths[4] + 2),
|
||||
"+",
|
||||
"-" * (col_widths[5] + 2),
|
||||
"+",
|
||||
"-" * (col_widths[6] + 2)
|
||||
])
|
||||
|
||||
print(header_fmt.format(*headers), file=sys.stderr)
|
||||
print(separator, file=sys.stderr)
|
||||
for r in results:
|
||||
# Symbol Logic
|
||||
read_symbol = bool_to_check(r.is_readable)
|
||||
write_symbol = bool_to_check(r.is_writeable)
|
||||
print(header_fmt.format(*headers), file=sys.stderr)
|
||||
print(separator, file=sys.stderr)
|
||||
for r in results:
|
||||
# Symbol Logic
|
||||
read_symbol = bool_to_check(r.is_readable)
|
||||
write_symbol = bool_to_check(r.is_writeable)
|
||||
|
||||
mount_symbol = CHECK_SYMBOL if r.is_mounted else CROSS_SYMBOL
|
||||
mount_symbol = CHECK_SYMBOL if r.is_mounted else CROSS_SYMBOL
|
||||
|
||||
if r.category == "persist":
|
||||
if r.underlying_fs_is_ramdisk or r.is_ramdisk:
|
||||
ramdisk_symbol = CROSS_SYMBOL
|
||||
else:
|
||||
ramdisk_symbol = BLANK_SYMBOL
|
||||
perf_symbol = BLANK_SYMBOL
|
||||
elif r.category == "ramdisk":
|
||||
ramdisk_symbol = CHECK_SYMBOL if r.is_ramdisk else CROSS_SYMBOL
|
||||
perf_symbol = bool_to_check(not r.performance_issue)
|
||||
if r.category == "persist":
|
||||
if r.underlying_fs_is_ramdisk or r.is_ramdisk:
|
||||
ramdisk_symbol = CROSS_SYMBOL
|
||||
else:
|
||||
ramdisk_symbol = BLANK_SYMBOL
|
||||
perf_symbol = bool_to_check(not r.performance_issue)
|
||||
perf_symbol = BLANK_SYMBOL
|
||||
elif r.category == "ramdisk":
|
||||
ramdisk_symbol = CHECK_SYMBOL if r.is_ramdisk else CROSS_SYMBOL
|
||||
perf_symbol = bool_to_check(not r.performance_issue)
|
||||
else:
|
||||
ramdisk_symbol = BLANK_SYMBOL
|
||||
perf_symbol = bool_to_check(not r.performance_issue)
|
||||
|
||||
dataloss_symbol = bool_to_check(not r.dataloss_risk)
|
||||
dataloss_symbol = bool_to_check(not r.dataloss_risk)
|
||||
|
||||
print(
|
||||
row_fmt.format(
|
||||
r.path,
|
||||
read_symbol,
|
||||
write_symbol,
|
||||
mount_symbol,
|
||||
ramdisk_symbol,
|
||||
perf_symbol,
|
||||
dataloss_symbol,
|
||||
),
|
||||
file=sys.stderr
|
||||
)
|
||||
print(
|
||||
row_fmt.format(
|
||||
r.path,
|
||||
read_symbol,
|
||||
write_symbol,
|
||||
mount_symbol,
|
||||
ramdisk_symbol,
|
||||
perf_symbol,
|
||||
dataloss_symbol,
|
||||
),
|
||||
file=sys.stderr
|
||||
)
|
||||
|
||||
# --- Print Warning ---
|
||||
if has_issues:
|
||||
print("\n", file=sys.stderr)
|
||||
print_warning_message(results)
|
||||
# --- Print Warning ---
|
||||
if has_issues:
|
||||
print("\n", file=sys.stderr)
|
||||
print_warning_message(results)
|
||||
|
||||
# Exit with error only if there are read/write permission issues
|
||||
if has_rw_errors and os.environ.get("NETALERTX_DEBUG") != "1":
|
||||
sys.exit(1)
|
||||
# Exit with error only if there are read/write permission issues
|
||||
if (has_rw_errors or has_primary_dataloss) and os.environ.get("NETALERTX_DEBUG") != "1":
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
set -eu
|
||||
|
||||
YELLOW=$(printf '\033[1;33m')
|
||||
CYAN=$(printf '\033[1;36m')
|
||||
RED=$(printf '\033[1;31m')
|
||||
RESET=$(printf '\033[0m')
|
||||
@@ -1,93 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Initialize required directories and log files
|
||||
# These must exist before services start to avoid permission/write errors
|
||||
|
||||
check_mandatory_folders() {
|
||||
# Base volatile directories live on /tmp mounts and must always exist
|
||||
if [ ! -d "${NETALERTX_LOG}" ]; then
|
||||
echo " * Creating NetAlertX log directory."
|
||||
if ! mkdir -p "${NETALERTX_LOG}"; then
|
||||
echo "Error: Failed to create log directory: ${NETALERTX_LOG}"
|
||||
return 1
|
||||
fi
|
||||
chmod 700 "${NETALERTX_LOG}" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
if [ ! -d "${NETALERTX_API}" ]; then
|
||||
echo " * Creating NetAlertX API cache."
|
||||
if ! mkdir -p "${NETALERTX_API}"; then
|
||||
echo "Error: Failed to create API cache directory: ${NETALERTX_API}"
|
||||
return 1
|
||||
fi
|
||||
chmod 700 "${NETALERTX_API}" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
if [ ! -d "${SYSTEM_SERVICES_RUN}" ]; then
|
||||
echo " * Creating System services runtime directory."
|
||||
if ! mkdir -p "${SYSTEM_SERVICES_RUN}"; then
|
||||
echo "Error: Failed to create System services runtime directory: ${SYSTEM_SERVICES_RUN}"
|
||||
return 1
|
||||
fi
|
||||
chmod 700 "${SYSTEM_SERVICES_RUN}" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
if [ ! -d "${SYSTEM_SERVICES_ACTIVE_CONFIG}" ]; then
|
||||
echo " * Creating nginx active configuration directory."
|
||||
if ! mkdir -p "${SYSTEM_SERVICES_ACTIVE_CONFIG}"; then
|
||||
echo "Error: Failed to create nginx active configuration directory: ${SYSTEM_SERVICES_ACTIVE_CONFIG}"
|
||||
return 1
|
||||
fi
|
||||
chmod 700 "${SYSTEM_SERVICES_ACTIVE_CONFIG}" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Check and create plugins log directory
|
||||
if [ ! -d "${NETALERTX_PLUGINS_LOG}" ]; then
|
||||
echo " * Creating Plugins log."
|
||||
if ! mkdir -p "${NETALERTX_PLUGINS_LOG}"; then
|
||||
echo "Error: Failed to create plugins log directory: ${NETALERTX_PLUGINS_LOG}"
|
||||
return 1
|
||||
fi
|
||||
chmod 700 "${NETALERTX_PLUGINS_LOG}" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Check and create system services run log directory
|
||||
if [ ! -d "${SYSTEM_SERVICES_RUN_LOG}" ]; then
|
||||
echo " * Creating System services run log."
|
||||
if ! mkdir -p "${SYSTEM_SERVICES_RUN_LOG}"; then
|
||||
echo "Error: Failed to create system services run log directory: ${SYSTEM_SERVICES_RUN_LOG}"
|
||||
return 1
|
||||
fi
|
||||
chmod 700 "${SYSTEM_SERVICES_RUN_LOG}" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Check and create system services run tmp directory
|
||||
if [ ! -d "${SYSTEM_SERVICES_RUN_TMP}" ]; then
|
||||
echo " * Creating System services run tmp."
|
||||
if ! mkdir -p "${SYSTEM_SERVICES_RUN_TMP}"; then
|
||||
echo "Error: Failed to create system services run tmp directory: ${SYSTEM_SERVICES_RUN_TMP}"
|
||||
return 1
|
||||
fi
|
||||
chmod 700 "${SYSTEM_SERVICES_RUN_TMP}" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Check and create DB locked log file
|
||||
if [ ! -f "${LOG_DB_IS_LOCKED}" ]; then
|
||||
echo " * Creating DB locked log."
|
||||
if ! touch "${LOG_DB_IS_LOCKED}"; then
|
||||
echo "Error: Failed to create DB locked log file: ${LOG_DB_IS_LOCKED}"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check and create execution queue log file
|
||||
if [ ! -f "${LOG_EXECUTION_QUEUE}" ]; then
|
||||
echo " * Creating Execution queue log."
|
||||
if ! touch "${LOG_EXECUTION_QUEUE}"; then
|
||||
echo "Error: Failed to create execution queue log file: ${LOG_EXECUTION_QUEUE}"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Run the function
|
||||
check_mandatory_folders
|
||||
103
install/production-filesystem/entrypoint.d/30-mandatory-folders.sh
Executable file
103
install/production-filesystem/entrypoint.d/30-mandatory-folders.sh
Executable file
@@ -0,0 +1,103 @@
|
||||
#!/bin/sh
|
||||
# Initialize required directories and log files
|
||||
# These must exist before services start to avoid permission/write errors
|
||||
# This script is intended to enhance observability of system startup issues.
|
||||
|
||||
|
||||
|
||||
is_tmp_path() {
|
||||
case "$1" in
|
||||
/tmp/*|/tmp) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
warn_tmp_skip() {
|
||||
echo "Warning: Unable to create $2 at $1 (tmpfs not writable with current capabilities)."
|
||||
}
|
||||
|
||||
ensure_dir() {
|
||||
# When creating as the user running the services, we ensure correct ownership and access
|
||||
path="$1"
|
||||
label="$2"
|
||||
if ! mkdir -p "${path}" 2>/dev/null; then
|
||||
if is_tmp_path "${path}"; then
|
||||
warn_tmp_skip "${path}" "${label}"
|
||||
return 0
|
||||
fi
|
||||
echo "Error: Failed to create ${label}: ${path}"
|
||||
return 1
|
||||
fi
|
||||
chmod 700 "${path}" 2>/dev/null || true
|
||||
}
|
||||
|
||||
ensure_file() {
|
||||
path="$1"
|
||||
label="$2"
|
||||
# When we touch as the user running the services, we ensure correct ownership
|
||||
if ! touch "${path}" 2>/dev/null; then
|
||||
if is_tmp_path "${path}"; then
|
||||
warn_tmp_skip "${path}" "${label}"
|
||||
return 0
|
||||
fi
|
||||
echo "Error: Failed to create ${label}: ${path}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_mandatory_folders() {
|
||||
# Base volatile directories live on /tmp mounts and must always exist
|
||||
if [ ! -d "${NETALERTX_LOG}" ]; then
|
||||
echo " * Creating NetAlertX log directory."
|
||||
ensure_dir "${NETALERTX_LOG}" "log directory" || return 1
|
||||
fi
|
||||
|
||||
if [ ! -d "${NETALERTX_API}" ]; then
|
||||
echo " * Creating NetAlertX API cache."
|
||||
ensure_dir "${NETALERTX_API}" "API cache directory" || return 1
|
||||
fi
|
||||
|
||||
if [ ! -d "${SYSTEM_SERVICES_RUN}" ]; then
|
||||
echo " * Creating System services runtime directory."
|
||||
ensure_dir "${SYSTEM_SERVICES_RUN}" "System services runtime directory" || return 1
|
||||
fi
|
||||
|
||||
if [ ! -d "${SYSTEM_SERVICES_ACTIVE_CONFIG}" ]; then
|
||||
echo " * Creating nginx active configuration directory."
|
||||
ensure_dir "${SYSTEM_SERVICES_ACTIVE_CONFIG}" "nginx active configuration directory" || return 1
|
||||
fi
|
||||
|
||||
# Check and create plugins log directory
|
||||
if [ ! -d "${NETALERTX_PLUGINS_LOG}" ]; then
|
||||
echo " * Creating Plugins log."
|
||||
ensure_dir "${NETALERTX_PLUGINS_LOG}" "plugins log directory" || return 1
|
||||
fi
|
||||
|
||||
# Check and create system services run log directory
|
||||
if [ ! -d "${SYSTEM_SERVICES_RUN_LOG}" ]; then
|
||||
echo " * Creating System services run log."
|
||||
ensure_dir "${SYSTEM_SERVICES_RUN_LOG}" "system services run log directory" || return 1
|
||||
fi
|
||||
|
||||
# Check and create system services run tmp directory
|
||||
if [ ! -d "${SYSTEM_SERVICES_RUN_TMP}" ]; then
|
||||
echo " * Creating System services run tmp."
|
||||
ensure_dir "${SYSTEM_SERVICES_RUN_TMP}" "system services run tmp directory" || return 1
|
||||
fi
|
||||
|
||||
# Check and create DB locked log file
|
||||
if [ ! -f "${LOG_DB_IS_LOCKED}" ]; then
|
||||
echo " * Creating DB locked log."
|
||||
ensure_file "${LOG_DB_IS_LOCKED}" "DB locked log file" || return 1
|
||||
fi
|
||||
|
||||
# Check and create execution queue log file
|
||||
if [ ! -f "${LOG_EXECUTION_QUEUE}" ]; then
|
||||
echo " * Creating Execution queue log."
|
||||
ensure_file "${LOG_EXECUTION_QUEUE}" "execution queue log file" || return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Create the folders and files.
|
||||
# Create a log message for observability if any fail.
|
||||
check_mandatory_folders
|
||||
@@ -4,8 +4,8 @@
|
||||
OVERRIDE_FILE="${NETALERTX_CONFIG}/app_conf_override.json"
|
||||
|
||||
# Ensure config directory exists
|
||||
mkdir -p "$(dirname "$NETALERTX_CONFIG")" || {
|
||||
>&2 echo "ERROR: Failed to create config directory $(dirname "$NETALERTX_CONFIG")"
|
||||
mkdir -p "$NETALERTX_CONFIG" || {
|
||||
>&2 echo "ERROR: Failed to create config directory $NETALERTX_CONFIG"
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# 30-writable-config.sh: Verify read/write permissions for config and database files.
|
||||
# 40-writable-config.sh: Verify read/write permissions for config and database files.
|
||||
#
|
||||
# This script ensures that the application can read from and write to the
|
||||
# critical configuration and database files after startup.
|
||||
@@ -72,7 +72,7 @@ EOF
|
||||
>&2 printf "%s" "${YELLOW}"
|
||||
>&2 cat <<EOF
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
⚠️ ATTENTION: Read permission denied (write permission denied).
|
||||
⚠️ ATTENTION: Write permission denied.
|
||||
|
||||
The application cannot write to "${path}". This will prevent it from
|
||||
saving data, logs, or configuration.
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/bin/sh
|
||||
# check-nginx-config.sh - verify nginx conf.active mount is writable when PORT != 20211.
|
||||
|
||||
|
||||
# Only check nginx config writability if PORT is not the default 20211
|
||||
if [ "${PORT:-20211}" = "20211" ]; then
|
||||
exit 0
|
||||
@@ -9,7 +10,7 @@ fi
|
||||
CONF_ACTIVE_DIR="${SYSTEM_SERVICES_ACTIVE_CONFIG}"
|
||||
TARGET_FILE="${CONF_ACTIVE_DIR}/netalertx.conf"
|
||||
|
||||
# If the directory is missing entirely we warn and exit failure so the caller can see the message.
|
||||
# If the directory is missing entirely we warn and exit 0 to allow startup with defaults.
|
||||
if [ ! -d "${CONF_ACTIVE_DIR}" ]; then
|
||||
YELLOW=$(printf '\033[1;33m')
|
||||
RESET=$(printf '\033[0m')
|
||||
@@ -30,7 +31,7 @@ if [ ! -d "${CONF_ACTIVE_DIR}" ]; then
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
exit 1
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TMP_FILE="${CONF_ACTIVE_DIR}/.netalertx-write-test"
|
||||
@@ -52,7 +53,7 @@ if ! ( : >"${TMP_FILE}" ) 2>/dev/null; then
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
exit 1
|
||||
exit 0 # Nginx can continue using default config on port 20211
|
||||
fi
|
||||
rm -f "${TMP_FILE}"
|
||||
|
||||
48
install/production-filesystem/entrypoint.d/60-expected-user-id-match.sh
Executable file
48
install/production-filesystem/entrypoint.d/60-expected-user-id-match.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/bin/sh
|
||||
# expected-user-id-match.sh - ensure the container is running as the intended runtime UID/GID.
|
||||
|
||||
EXPECTED_USER="${NETALERTX_USER:-netalertx}"
|
||||
CURRENT_UID="$(id -u)"
|
||||
CURRENT_GID="$(id -g)"
|
||||
|
||||
# If PUID/PGID explicitly set, require that we are running as them.
|
||||
if [ -n "${PUID:-}" ] || [ -n "${PGID:-}" ]; then
|
||||
TARGET_UID="${PUID:-${CURRENT_UID}}"
|
||||
TARGET_GID="${PGID:-${CURRENT_GID}}"
|
||||
|
||||
if [ "${CURRENT_UID}" -ne "${TARGET_UID}" ] || [ "${CURRENT_GID}" -ne "${TARGET_GID}" ]; then
|
||||
if [ "${NETALERTX_PRIVDROP_FAILED:-0}" -ne 0 ]; then
|
||||
>&2 printf 'Note: PUID/PGID=%s:%s requested but privilege drop failed; continuing as UID %s GID %s. See docs/docker-troubleshooting/missing-capabilities.md\n' \
|
||||
"${TARGET_UID}" "${TARGET_GID}" "${CURRENT_UID}" "${CURRENT_GID}"
|
||||
exit 0
|
||||
fi
|
||||
if [ "${CURRENT_UID}" -ne 0 ]; then
|
||||
>&2 printf 'Note: PUID/PGID=%s:%s requested but container is running as fixed UID %s GID %s; PUID/PGID will not be applied.\n' \
|
||||
"${TARGET_UID}" "${TARGET_GID}" "${CURRENT_UID}" "${CURRENT_GID}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
>&2 printf 'FATAL: NetAlertX running as UID %s GID %s, expected PUID/PGID %s:%s\n' \
|
||||
"${CURRENT_UID}" "${CURRENT_GID}" "${TARGET_UID}" "${TARGET_GID}"
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
EXPECTED_UID="$(getent passwd "${EXPECTED_USER}" 2>/dev/null | cut -d: -f3)"
|
||||
EXPECTED_GID="$(getent passwd "${EXPECTED_USER}" 2>/dev/null | cut -d: -f4)"
|
||||
|
||||
# Fallback to known defaults when lookups fail
|
||||
if [ -z "${EXPECTED_UID}" ]; then
|
||||
EXPECTED_UID="${CURRENT_UID}"
|
||||
fi
|
||||
if [ -z "${EXPECTED_GID}" ]; then
|
||||
EXPECTED_GID="${CURRENT_GID}"
|
||||
fi
|
||||
|
||||
if [ "${CURRENT_UID}" -eq "${EXPECTED_UID}" ] && [ "${CURRENT_GID}" -eq "${EXPECTED_GID}" ]; then
|
||||
exit 0
|
||||
fi
|
||||
>&2 printf '\nNetAlertX note: current UID %s GID %s, expected UID %s GID %s\n' \
|
||||
"${CURRENT_UID}" "${CURRENT_GID}" "${EXPECTED_UID}" "${EXPECTED_GID}"
|
||||
exit 0
|
||||
@@ -1,23 +0,0 @@
|
||||
#!/bin/sh
|
||||
# check-user-netalertx.sh - ensure the container is running as the hardened service user.
|
||||
|
||||
EXPECTED_USER="${NETALERTX_USER:-netalertx}"
|
||||
EXPECTED_UID="$(getent passwd "${EXPECTED_USER}" 2>/dev/null | cut -d: -f3)"
|
||||
EXPECTED_GID="$(getent passwd "${EXPECTED_USER}" 2>/dev/null | cut -d: -f4)"
|
||||
CURRENT_UID="$(id -u)"
|
||||
CURRENT_GID="$(id -g)"
|
||||
|
||||
# Fallback to known defaults when lookups fail
|
||||
if [ -z "${EXPECTED_UID}" ]; then
|
||||
EXPECTED_UID="${CURRENT_UID}"
|
||||
fi
|
||||
if [ -z "${EXPECTED_GID}" ]; then
|
||||
EXPECTED_GID="${CURRENT_GID}"
|
||||
fi
|
||||
|
||||
if [ "${CURRENT_UID}" -eq "${EXPECTED_UID}" ] && [ "${CURRENT_GID}" -eq "${EXPECTED_GID}" ]; then
|
||||
exit 0
|
||||
fi
|
||||
>&2 printf '\nNetAlertX note: current UID %s GID %s, expected UID %s GID %s\n' \
|
||||
"${CURRENT_UID}" "${CURRENT_GID}" "${EXPECTED_UID}" "${EXPECTED_GID}"
|
||||
exit 0
|
||||
@@ -1,33 +0,0 @@
|
||||
#!/bin/sh
|
||||
# layer-2-network.sh - Uses a real nmap command to detect missing container
|
||||
# privileges and warns the user. It is silent on success.
|
||||
|
||||
# Run a fast nmap command that requires raw sockets, capturing only stderr.
|
||||
ERROR_OUTPUT=$(nmap --privileged -sS -p 20211 127.0.0.1 2>&1)
|
||||
EXIT_CODE=$?
|
||||
|
||||
# Flag common capability errors regardless of exact exit code.
|
||||
if [ "$EXIT_CODE" -ne 0 ] && \
|
||||
echo "$ERROR_OUTPUT" | grep -q -e "Operation not permitted" -e "requires root privileges"
|
||||
then
|
||||
YELLOW=$(printf '\033[1;33m')
|
||||
RESET=$(printf '\033[0m')
|
||||
>&2 printf "%s" "${YELLOW}"
|
||||
>&2 cat <<'EOF'
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
⚠️ ATTENTION: Raw network capabilities are missing.
|
||||
|
||||
Tools that rely on NET_RAW/NET_ADMIN/NET_BIND_SERVICE (e.g. nmap -sS,
|
||||
arp-scan, nbtscan) will not function. Restart the container with:
|
||||
|
||||
--cap-add=NET_RAW --cap-add=NET_ADMIN --cap-add=NET_BIND_SERVICE
|
||||
|
||||
Without those caps, NetAlertX cannot inspect your network. Fix it before
|
||||
trusting any results.
|
||||
|
||||
https://github.com/jokob-sk/NetAlertX/blob/main/docs/docker-troubleshooting/missing-capabilities.md
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
fi
|
||||
exit 0 # Always exit success even after warnings
|
||||
@@ -1,13 +1,13 @@
|
||||
#!/bin/bash
|
||||
# Bash used in this check for simplicty of math operations.
|
||||
#!/bin/sh
|
||||
# POSIX-compliant shell script for capability checking.
|
||||
# excessive-capabilities.sh checks that no more than the necessary
|
||||
# NET_ADMIN NET_BIND_SERVICE and NET_RAW capabilities are present.
|
||||
|
||||
|
||||
# if we are running in devcontainer then we should exit imemditely without checking
|
||||
# if we are running in devcontainer then we should exit immediately without checking
|
||||
# The devcontainer is set up to have additional permissions which are not granted
|
||||
# in production so this check would always fail there.
|
||||
if [ "${NETALERTX_DEBUG}" == "1" ]; then
|
||||
if [ "${NETALERTX_DEBUG}" = "1" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -18,8 +18,8 @@ if [ -z "$BND_HEX" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Convert hex to decimal
|
||||
BND_DEC=$(( 16#$BND_HEX )) || exit 0
|
||||
#POSIX compliant base16 on permissions
|
||||
BND_DEC=$(awk 'BEGIN { h = "0x'"$BND_HEX"'"; if (h ~ /^0x[0-9A-Fa-f]+$/) { printf "%d", h; exit 0 } else { exit 1 } }') || exit 0
|
||||
|
||||
# Allowed capabilities: NET_BIND_SERVICE (10), NET_ADMIN (12), NET_RAW (13)
|
||||
ALLOWED_DEC=$(( ( 1 << 10 ) | ( 1 << 12 ) | ( 1 << 13 ) ))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
################################################################################
|
||||
# NetAlertX Container Entrypoint
|
||||
@@ -46,6 +46,17 @@ if [ "$#" -gt 0 ]; then
|
||||
esac
|
||||
fi
|
||||
|
||||
# If invoked directly (bypassing root-entrypoint), re-enter through it once for priming
|
||||
# and privilege drop. Guard with ENTRYPOINT_PRIMED to avoid loops when root-entrypoint
|
||||
# hands control back to this script.
|
||||
if [ "${ENTRYPOINT_PRIMED:-0}" != "1" ] && [ "$(id -u)" -eq 0 ] && [ -x "/root-entrypoint.sh" ]; then
|
||||
>&2 cat <<'EOF'
|
||||
NetAlertX is running as ROOT (UID 0). Prefer setting PUID/PGID to 20211 for better isolation.
|
||||
EOF
|
||||
export ENTRYPOINT_PRIMED=1
|
||||
exec /root-entrypoint.sh "$@"
|
||||
fi
|
||||
|
||||
# Banner display
|
||||
RED='\033[1;31m'
|
||||
GREY='\033[90m'
|
||||
@@ -92,12 +103,9 @@ https://github.com/jokob-sk/NetAlertX/blob/main/docs/docker-troubleshooting/trou
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
|
||||
FAILED_STATUS="1"
|
||||
if [ "${NETALERTX_DEBUG:-0}" -eq 1 ]; then
|
||||
|
||||
FAILED_STATUS="1"
|
||||
echo "NETALERTX_DEBUG=1, continuing despite critical failure in ${script_name}."
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
elif [ ${NETALERTX_DOCKER_ERROR_CHECK} -ne 0 ]; then
|
||||
# fail but continue checks so user can see all issues
|
||||
@@ -264,9 +272,6 @@ trap on_signal INT TERM
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
# Service Startup Section
|
||||
################################################################################
|
||||
# Start services based on environment configuration
|
||||
|
||||
# Only start crond scheduler on Alpine (non-Debian) environments
|
||||
|
||||
130
install/production-filesystem/root-entrypoint.sh
Normal file
130
install/production-filesystem/root-entrypoint.sh
Normal file
@@ -0,0 +1,130 @@
|
||||
#!/bin/bash
|
||||
# NetAlertX Root-Priming Entrypoint — best-effort permission priming 🔧
|
||||
#
|
||||
# Purpose:
|
||||
# - Provide a runtime, best-effort remedy for host volume ownership/mode issues
|
||||
# (common on appliances like Synology where Docker volume copy‑up is limited).
|
||||
# - Ensure writable paths exist, attempt to `chown`/`chmod` to a runtime `PUID`/`PGID`
|
||||
# (defaults to 20211), then drop privileges via `su-exec` if possible.
|
||||
#
|
||||
# Design & behavior notes:
|
||||
# - This script is intentionally *non-fatal* for chown/chmod failures; operations are
|
||||
# best-effort so we avoid blocking container startup on imperfect hosts.
|
||||
# - Runtime defaults are used so the image works without requiring build-time args.
|
||||
# - If the container is started as non-root (`user:`), priming is skipped and it's the
|
||||
# operator's responsibility to ensure matching ownership on the host.
|
||||
# - If `su-exec` cannot drop privileges, we log a note and continue as the current user
|
||||
# rather than aborting (keeps first-run resilient).
|
||||
#
|
||||
# Operational recommendation:
|
||||
# - For deterministic ownership, explicitly set `PUID`/`PGID` (or pre-chown host volumes),
|
||||
# and when hardening capabilities add `cap_add: [CHOWN]` so priming can succeed.
|
||||
|
||||
PUID="${PUID:-${NETALERTX_UID:-20211}}"
|
||||
PGID="${PGID:-${NETALERTX_GID:-20211}}"
|
||||
|
||||
# Pretty terminal colors used for fatal messages (kept minimal + POSIX printf)
|
||||
RED=$(printf '\033[1;31m')
|
||||
RESET=$(printf '\033[0m')
|
||||
|
||||
|
||||
_validate_id() {
|
||||
value="$1"
|
||||
name="$2"
|
||||
|
||||
if ! printf '%s' "${value}" | grep -qxE '[0-9]+'; then
|
||||
>&2 printf "%s" "${RED}"
|
||||
>&2 cat <<EOF
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
🔒 SECURITY - FATAL: invalid ${name} value (non-numeric)
|
||||
|
||||
Startup halted because the provided ${name} environmental variable
|
||||
contains non-digit characters. This is a deliberate security measure to
|
||||
prevent environment-variable command injection while the container runs as
|
||||
root during initial startup.
|
||||
|
||||
Action: set a numeric ${name} (for example: PUID=1000) in your environment
|
||||
or docker-compose file and restart the container. Default: 20211.
|
||||
|
||||
For more information and troubleshooting, see:
|
||||
https://github.com/jokob-sk/NetAlertX/blob/main/docs/docker-troubleshooting/PUID_PGID_SECURITY.md
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
_validate_id "${PUID}" "PUID"
|
||||
_validate_id "${PGID}" "PGID"
|
||||
|
||||
_cap_bits_warn_missing_setid() {
|
||||
cap_hex=$(awk '/CapEff/ {print $2}' /proc/self/status 2>/dev/null || echo "")
|
||||
[ -n "${cap_hex}" ] || return
|
||||
|
||||
# POSIX compliant base16 on permissions
|
||||
cap_dec=$(awk 'BEGIN { h = "0x'"${cap_hex}"'"; if (h ~ /^0x[0-9A-Fa-f]+$/) { printf "%d", h } else { print 0 } }')
|
||||
|
||||
has_setgid=0
|
||||
has_setuid=0
|
||||
has_net_caps=0
|
||||
|
||||
if [ $((cap_dec & (1 << 6))) -ne 0 ]; then
|
||||
has_setgid=1
|
||||
fi
|
||||
if [ $((cap_dec & (1 << 7))) -ne 0 ]; then
|
||||
has_setuid=1
|
||||
fi
|
||||
if [ $((cap_dec & (1 << 10))) -ne 0 ] || [ $((cap_dec & (1 << 12))) -ne 0 ] || [ $((cap_dec & (1 << 13))) -ne 0 ]; then
|
||||
has_net_caps=1
|
||||
fi
|
||||
|
||||
if [ "${has_net_caps}" -eq 1 ] && { [ "${has_setgid}" -eq 0 ] || [ "${has_setuid}" -eq 0 ]; }; then
|
||||
>&2 echo "Note: CAP_SETUID/CAP_SETGID unavailable alongside NET_* caps; continuing as current user."
|
||||
fi
|
||||
}
|
||||
|
||||
_cap_bits_warn_missing_setid
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
if [ -n "${PUID:-}" ] || [ -n "${PGID:-}" ]; then
|
||||
>&2 printf 'Note: container running as UID %s GID %s; requested PUID/PGID=%s:%s will not be applied.\n' \
|
||||
"$(id -u)" "$(id -g)" "${PUID}" "${PGID}"
|
||||
fi
|
||||
exec /entrypoint.sh "$@"
|
||||
fi
|
||||
|
||||
if [ "${PUID}" -eq 0 ]; then
|
||||
>&2 echo "WARNING: Running as root (PUID=0). Prefer a non-root PUID. See https://github.com/jokob-sk/NetAlertX/blob/main/docs/docker-troubleshooting/file-permissions.md"
|
||||
exec /entrypoint.sh "$@"
|
||||
fi
|
||||
|
||||
_prime_paths() {
|
||||
runtime_root="${NETALERTX_RUNTIME_BASE:-/tmp}"
|
||||
paths="/tmp ${NETALERTX_DATA:-/data} ${NETALERTX_CONFIG:-/data/config} ${NETALERTX_DB:-/data/db} ${NETALERTX_LOG:-${runtime_root}/log} ${NETALERTX_PLUGINS_LOG:-${runtime_root}/log/plugins} ${NETALERTX_API:-${runtime_root}/api} ${SYSTEM_SERVICES_RUN:-${runtime_root}/run} ${SYSTEM_SERVICES_RUN_TMP:-${runtime_root}/run/tmp} ${SYSTEM_SERVICES_RUN_LOG:-${runtime_root}/run/logs} ${SYSTEM_SERVICES_ACTIVE_CONFIG:-${runtime_root}/nginx/active-config} ${runtime_root}/nginx"
|
||||
|
||||
chmod 1777 /tmp 2>/dev/null || true
|
||||
|
||||
for path in ${paths}; do
|
||||
[ -n "${path}" ] || continue
|
||||
if [ "${path}" = "/tmp" ]; then
|
||||
continue
|
||||
fi
|
||||
install -d -o "${PUID}" -g "${PGID}" -m 700 "${path}" 2>/dev/null || true
|
||||
chown -R "${PUID}:${PGID}" "${path}" 2>/dev/null || true
|
||||
chmod -R u+rwX "${path}" 2>/dev/null || true
|
||||
done
|
||||
|
||||
>&2 echo "Permissions prepared for PUID=${PUID}."
|
||||
}
|
||||
|
||||
_prime_paths
|
||||
|
||||
unset NETALERTX_PRIVDROP_FAILED
|
||||
if ! su-exec "${PUID}:${PGID}" /entrypoint.sh "$@"; then
|
||||
rc=$?
|
||||
export NETALERTX_PRIVDROP_FAILED=1
|
||||
export NETALERTX_CHECK_ONLY="${NETALERTX_CHECK_ONLY:-1}"
|
||||
>&2 echo "Note: su-exec failed (exit ${rc}); continuing as current user without privilege drop."
|
||||
exec /entrypoint.sh "$@"
|
||||
fi
|
||||
@@ -54,11 +54,11 @@ chmod -R 777 "/tmp/nginx" 2>/dev/null || true
|
||||
|
||||
# Execute nginx with overrides
|
||||
# echo the full nginx command then run it
|
||||
echo "Starting /usr/sbin/nginx -p \"${RUN_DIR}/\" -c \"${SYSTEM_SERVICES_ACTIVE_CONFIG_FILE}\" -g \"error_log /dev/stderr; error_log ${NETALERTX_LOG}/nginx-error.log; daemon off;\" &"
|
||||
echo "Starting /usr/sbin/nginx -p \"${RUN_DIR}/\" -c \"${SYSTEM_SERVICES_ACTIVE_CONFIG_FILE}\" -g \"error_log stderr; error_log ${NETALERTX_LOG}/nginx-error.log; daemon off;\" &"
|
||||
/usr/sbin/nginx \
|
||||
-p "${RUN_DIR}/" \
|
||||
-c "${SYSTEM_SERVICES_ACTIVE_CONFIG_FILE}" \
|
||||
-g "error_log /dev/stderr; error_log ${NETALERTX_LOG}/nginx-error.log; daemon off;" &
|
||||
-g "error_log stderr; error_log ${NETALERTX_LOG}/nginx-error.log; daemon off;" &
|
||||
nginx_pid=$!
|
||||
|
||||
wait "${nginx_pid}"
|
||||
|
||||
@@ -26,8 +26,9 @@ done
|
||||
trap cleanup EXIT
|
||||
trap forward_signal INT TERM
|
||||
|
||||
echo "Starting /usr/sbin/php-fpm83 -y \"${PHP_FPM_CONFIG_FILE}\" -F >>\"${LOG_APP_PHP_ERRORS}\" 2>/dev/stderr &"
|
||||
/usr/sbin/php-fpm83 -y "${PHP_FPM_CONFIG_FILE}" -F >>"${LOG_APP_PHP_ERRORS}" 2> /dev/stderr &
|
||||
echo "Starting /usr/sbin/php-fpm83 -y \"${PHP_FPM_CONFIG_FILE}\" -F (tee stderr to app.php_errors.log)"
|
||||
php_fpm_cmd=(/usr/sbin/php-fpm83 -y "${PHP_FPM_CONFIG_FILE}" -F)
|
||||
"${php_fpm_cmd[@]}" 2> >(tee -a "${LOG_APP_PHP_ERRORS}" >&2) &
|
||||
php_fpm_pid=$!
|
||||
|
||||
wait "${php_fpm_pid}"
|
||||
|
||||
Reference in New Issue
Block a user