Add additional startup checks

This commit is contained in:
Adam Outler
2025-10-22 23:51:36 +00:00
parent 1af19fe9fd
commit 0851680ef6
4 changed files with 187 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
#!/bin/sh
# check-network-mode.sh - detect when the container is not using host networking.
DEFAULT_IF="$(ip route show default 0.0.0.0/0 2>/dev/null | awk 'NR==1 {print $5}')"
if [ -z "${DEFAULT_IF}" ]; then
# No default route; nothing to validate.
exit 0
fi
IF_LINK_INFO="$(ip link show "${DEFAULT_IF}" 2>/dev/null)"
IF_IP="$(ip -4 addr show "${DEFAULT_IF}" 2>/dev/null | awk '/inet / {print $2}' | head -n1)"
IF_MAC=""
if [ -r "/sys/class/net/${DEFAULT_IF}/address" ]; then
IF_MAC="$(cat "/sys/class/net/${DEFAULT_IF}/address")"
fi
looks_like_bridge="0"
case "${IF_MAC}" in
02:42:*) looks_like_bridge="1" ;;
00:00:00:00:00:00) looks_like_bridge="1" ;;
"") ;; # leave as is
esac
case "${IF_IP}" in
172.1[6-9].*|172.2[0-9].*|172.3[0-1].*) looks_like_bridge="1" ;;
192.168.65.*) looks_like_bridge="1" ;;
esac
if echo "${IF_LINK_INFO}" | grep -q "@if"; then
looks_like_bridge="1"
fi
if [ "${looks_like_bridge}" -ne 1 ]; then
exit 0
fi
YELLOW=$(printf '\033[1;33m')
RESET=$(printf '\033[0m')
>&2 printf "%s" "${YELLOW}"
>&2 cat <<EOF
══════════════════════════════════════════════════════════════════════════════
⚠️ ATTENTION: NetAlertX is not running with --network=host.
Bridge networking blocks passive discovery (ARP, NBNS, mDNS) and active
scanning accuracy. Most plugins expect raw access to the LAN through host
networking and CAP_NET_RAW capabilities.
Restart the container with:
docker run --network=host --cap-add=NET_RAW --cap-add=NET_ADMIN --cap-add=NET_BIND_SERVICE
or set "network_mode: host" in docker-compose.yml.
══════════════════════════════════════════════════════════════════════════════
EOF
>&2 printf "%s" "${RESET}"
exit 1

View File

@@ -0,0 +1,50 @@
#!/bin/sh
# check-nginx-config.sh - verify nginx conf.active mount is writable when startup needs to render config.
CONF_ACTIVE_DIR="${SYSTEM_NGINX_CONFIG}/conf.active"
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 [ ! -d "${CONF_ACTIVE_DIR}" ]; then
YELLOW=$(printf '\033[1;33m')
RESET=$(printf '\033[0m')
>&2 printf "%s" "${YELLOW}"
>&2 cat <<EOF
══════════════════════════════════════════════════════════════════════════════
⚠️ ATTENTION: Nginx configuration mount ${CONF_ACTIVE_DIR} is missing.
Custom listen address or port changes require a writable nginx conf.active
directory. Without it, the container falls back to defaults and ignores
your overrides.
Create a bind mount:
--mount type=bind,src=/path/on/host,dst=${CONF_ACTIVE_DIR}
and ensure it is owned by the netalertx user (20211:20211) with 700 perms.
══════════════════════════════════════════════════════════════════════════════
EOF
>&2 printf "%s" "${RESET}"
exit 1
fi
TMP_FILE="${CONF_ACTIVE_DIR}/.netalertx-write-test"
if ! ( : >"${TMP_FILE}" ) 2>/dev/null; then
YELLOW=$(printf '\033[1;33m')
RESET=$(printf '\033[0m')
>&2 printf "%s" "${YELLOW}"
>&2 cat <<EOF
══════════════════════════════════════════════════════════════════════════════
⚠️ ATTENTION: Unable to write to ${TARGET_FILE}.
Ensure the conf.active mount is writable by the netalertx user before
changing LISTEN_ADDR or PORT. Fix permissions:
chown -R 20211:20211 ${CONF_ACTIVE_DIR}
find ${CONF_ACTIVE_DIR} -type d -exec chmod 700 {} +
find ${CONF_ACTIVE_DIR} -type f -exec chmod 600 {} +
══════════════════════════════════════════════════════════════════════════════
EOF
>&2 printf "%s" "${RESET}"
exit 1
fi
rm -f "${TMP_FILE}"
exit 0

View File

@@ -0,0 +1,40 @@
#!/bin/sh
# check-storage-extra.sh - ensure additional NetAlertX directories are persistent mounts.
warn_if_not_persistent_mount() {
path="$1"
label="$2"
if awk -v target="${path}" '$5 == target {found=1} END {exit found ? 0 : 1}' /proc/self/mountinfo; then
return 0
fi
failures=1
YELLOW=$(printf '\033[1;33m')
RESET=$(printf '\033[0m')
>&2 printf "%s" "${YELLOW}"
>&2 cat <<EOF
══════════════════════════════════════════════════════════════════════════════
⚠️ ATTENTION: ${path} is not a persistent mount.
${label} relies on host storage to persist data across container restarts.
Mount this directory from the host or a named volume before trusting the
container's output.
Example:
--mount type=bind,src=/path/on/host,dst=${path}
══════════════════════════════════════════════════════════════════════════════
EOF
>&2 printf "%s" "${RESET}"
}
failures=0
warn_if_not_persistent_mount "${NETALERTX_LOG}" "Logs"
warn_if_not_persistent_mount "${NETALERTX_API}" "API JSON cache"
warn_if_not_persistent_mount "${SYSTEM_SERVICES_RUN}" "Runtime work directory"
if [ "${failures}" -ne 0 ]; then
sleep 5
exit 1
fi
exit 0

View File

@@ -0,0 +1,42 @@
#!/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="20211"
fi
if [ -z "${EXPECTED_GID}" ]; then
EXPECTED_GID="20211"
fi
if [ "${CURRENT_UID}" -eq "${EXPECTED_UID}" ] && [ "${CURRENT_GID}" -eq "${EXPECTED_GID}" ]; then
exit 0
fi
YELLOW=$(printf '\033[1;33m')
RESET=$(printf '\033[0m')
>&2 printf "%s" "${YELLOW}"
>&2 cat <<EOF
══════════════════════════════════════════════════════════════════════════════
⚠️ ATTENTION: NetAlertX is running as UID ${CURRENT_UID}:${CURRENT_GID}.
Hardened permissions, file ownership, and runtime isolation expect the
dedicated service account (${EXPECTED_USER} -> ${EXPECTED_UID}:${EXPECTED_GID}).
When you override the container user (for example, docker run --user 1000:1000
or a Compose "user:" directive), NetAlertX loses crucial safeguards and
future upgrades may silently fail.
Restore the container to the default user:
* Remove any custom --user flag
* Delete "user:" overrides in compose files
* Recreate the container so volume ownership is reset
══════════════════════════════════════════════════════════════════════════════
EOF
>&2 printf "%s" "${RESET}"
exit 1