mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
/data and /tmp standarization
This commit is contained in:
@@ -6,12 +6,20 @@ This document describes the filesystem structure of the NetAlertX production Doc
|
||||
## Directory Structure
|
||||
|
||||
### `/app` - Main Application Directory
|
||||
The core application location where NetAlertX runs. This directory contains the main application code and working data, with source code directories mounted in read-only mode for security. It provides the runtime environment for all NetAlertX operations including device scanning, web interface, and data processing.
|
||||
The core application location where NetAlertX runs. This directory contains only the application code in production. Configuration, database files, and logs now live in dedicated `/data` and `/tmp` mounts to keep the runtime read-only and auditable.
|
||||
|
||||
The core application location. Contains:
|
||||
- Source code directories (`back`, `front`, `server`) copied in read-only mode
|
||||
- Working directories for runtime data (`config`, `db`, `log`)
|
||||
- Other directories are not needed in production and are excluded
|
||||
- Service orchestration scripts under `/services`
|
||||
- No persistent data or logs—those are redirected to `/data` and `/tmp`
|
||||
|
||||
### `/data` - Persistent Configuration and Database
|
||||
Writable volume that stores administrator-managed settings and database state. The entrypoint ensures directories are owned by the `netalertx` user (UID 20211).
|
||||
|
||||
Contains:
|
||||
- `/data/config` - persisted settings such as `app.conf`
|
||||
- `/data/db` - SQLite database files (e.g., `app.db`)
|
||||
- Optional host bind mounts for backups or external sync
|
||||
|
||||
### `/build` - Build-Time Scripts
|
||||
Temporary directory used during Docker image building to prepare the container environment. Scripts in this directory run during the build process to set up the system before it's locked down for production use. This ensures the container is properly configured before runtime.
|
||||
@@ -59,10 +67,13 @@ Pre-startup checks and specialized maintenance tools:
|
||||
- `list-ports.sh` - Network port enumeration script
|
||||
- `opnsense_leases/` - OPNsense DHCP lease integration tools
|
||||
|
||||
#### `/services/run` - Runtime Data
|
||||
Directory for storing runtime data and logs generated by services during container operation. This provides a centralized location for monitoring service activity and troubleshooting issues that occur during normal operation.
|
||||
### `/tmp` - Ephemeral Runtime Data
|
||||
All writable runtime data is consolidated under `/tmp`, which is mounted as `tmpfs` by default for speed and automatic cleanup on restart.
|
||||
|
||||
- `logs/` - Service runtime log files
|
||||
- `/tmp/log` - Application, PHP, and plugin logs (bind mount to persist between restarts)
|
||||
- `/tmp/api` - Cached API responses for the UI (configurable via `NETALERTX_API` environment variable)
|
||||
- `/tmp/nginx/active-config` - Optional override directory for nginx configuration
|
||||
- `/tmp/run` - Runtime socket and temp directories for nginx and PHP (`client_body`, `proxy`, `php.sock`, etc.)
|
||||
|
||||
#### Service Control Scripts
|
||||
Scripts that start and manage the core services required for NetAlertX operation. These scripts handle the initialization of the web server, application server, task scheduler, and backend processing components that work together to provide network monitoring functionality.
|
||||
|
||||
0
install/production-filesystem/app/log/IP_changes.log → install/production-filesystem/data/.gitkeep
Executable file → Normal file
0
install/production-filesystem/app/log/IP_changes.log → install/production-filesystem/data/.gitkeep
Executable file → Normal file
@@ -13,12 +13,13 @@ RESET=$(printf '\033[0m')
|
||||
|
||||
# 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}
|
||||
${NETALERTX_DB_FILE}
|
||||
"
|
||||
|
||||
@@ -39,7 +40,7 @@ if [ "$(id -u)" -eq 0 ]; then
|
||||
* switch to the default USER in the image (20211:20211)
|
||||
|
||||
IMPORTANT: This corrective mode automatically adjusts ownership of
|
||||
/app/db and /app/config directories to the netalertx user, ensuring
|
||||
/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
|
||||
@@ -54,8 +55,8 @@ EOF
|
||||
chown -R netalertx ${READ_WRITE_PATHS} 2>/dev/null || true
|
||||
|
||||
# Set directory and file permissions for all read-write paths
|
||||
find ${READ_WRITE_PATHS} -type d -exec chmod u+rwx {}
|
||||
find ${READ_WRITE_PATHS} -type f -exec chmod u+rw {}
|
||||
find ${READ_WRITE_PATHS} -type d -exec chmod u+rwx {} \;
|
||||
find ${READ_WRITE_PATHS} -type f -exec chmod u+rw {} \;
|
||||
echo Permissions fixed for read-write paths. Please restart the container as user 20211.
|
||||
sleep infinity & wait $!
|
||||
fi
|
||||
|
||||
145
install/production-filesystem/entrypoint.d/01-data-migration.sh
Executable file
145
install/production-filesystem/entrypoint.d/01-data-migration.sh
Executable file
@@ -0,0 +1,145 @@
|
||||
#!/bin/sh
|
||||
# 01-data-migration.sh - consolidate legacy /app mounts into /data
|
||||
|
||||
set -eu
|
||||
|
||||
YELLOW=$(printf '\033[1;33m')
|
||||
CYAN=$(printf '\033[1;36m')
|
||||
RED=$(printf '\033[1;31m')
|
||||
RESET=$(printf '\033[0m')
|
||||
|
||||
DATA_DIR=${NETALERTX_DATA:-/data}
|
||||
TARGET_CONFIG=${NETALERTX_CONFIG:-${DATA_DIR}/config}
|
||||
TARGET_DB=${NETALERTX_DB:-${DATA_DIR}/db}
|
||||
LEGACY_CONFIG=/app/config
|
||||
LEGACY_DB=/app/db
|
||||
MARKER_NAME=.migration
|
||||
|
||||
is_mounted() {
|
||||
local path="$1"
|
||||
if [ ! -d "${path}" ]; then
|
||||
return 1
|
||||
fi
|
||||
mountpoint -q "${path}" 2>/dev/null
|
||||
}
|
||||
|
||||
warn_unmount_legacy() {
|
||||
>&2 printf "%s" "${YELLOW}"
|
||||
>&2 cat <<EOF
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
⚠️ ATTENTION: Legacy mounts detected at ${LEGACY_CONFIG} or ${LEGACY_DB}.
|
||||
|
||||
Migration markers are present. Your data now lives under ${DATA_DIR}.
|
||||
Unmount the legacy /app/config and /app/db paths from your docker-compose
|
||||
file to avoid stale mounts on future starts.
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
}
|
||||
|
||||
fatal_missing_data_mount() {
|
||||
>&2 printf "%s" "${RED}"
|
||||
>&2 cat <<EOF
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
❌ CRITICAL: /data is not mounted but legacy mounts are still present.
|
||||
|
||||
Mount the new consolidated volume at ${DATA_DIR} so data can be migrated.
|
||||
Once mounted, restart the container to complete migration automatically.
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
}
|
||||
|
||||
migrate_legacy_mounts() {
|
||||
>&2 printf "%s" "${CYAN}"
|
||||
>&2 cat <<EOF
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
🛠️ Migrating legacy /app mounts into ${DATA_DIR}.
|
||||
|
||||
Existing configuration and database files will be copied into the new
|
||||
consolidated volume. This runs once per environment.
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
|
||||
mkdir -p "${TARGET_CONFIG}" "${TARGET_DB}" || return 1
|
||||
chmod 700 "${TARGET_CONFIG}" "${TARGET_DB}" 2>/dev/null || true
|
||||
|
||||
if ! cp -a "${LEGACY_CONFIG}/." "${TARGET_CONFIG}/"; then
|
||||
>&2 printf "%s" "${RED}"
|
||||
>&2 echo "Migration failed while copying configuration files."
|
||||
>&2 printf "%s" "${RESET}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! cp -a "${LEGACY_DB}/." "${TARGET_DB}/"; then
|
||||
>&2 printf "%s" "${RED}"
|
||||
>&2 echo "Migration failed while copying database files."
|
||||
>&2 printf "%s" "${RESET}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
touch "${LEGACY_CONFIG}/${MARKER_NAME}" "${LEGACY_DB}/${MARKER_NAME}" 2>/dev/null || true
|
||||
|
||||
warn_unmount_legacy
|
||||
return 0
|
||||
}
|
||||
|
||||
CONFIG_MARKED=false
|
||||
DB_MARKED=false
|
||||
[ -f "${LEGACY_CONFIG}/${MARKER_NAME}" ] && CONFIG_MARKED=true
|
||||
[ -f "${LEGACY_DB}/${MARKER_NAME}" ] && DB_MARKED=true
|
||||
|
||||
if ${CONFIG_MARKED} || ${DB_MARKED}; then
|
||||
warn_unmount_legacy
|
||||
exit 0
|
||||
fi
|
||||
|
||||
CONFIG_MOUNTED=false
|
||||
DB_MOUNTED=false
|
||||
DATA_MOUNTED=false
|
||||
is_mounted "${LEGACY_CONFIG}" && CONFIG_MOUNTED=true
|
||||
is_mounted "${LEGACY_DB}" && DB_MOUNTED=true
|
||||
is_mounted "${DATA_DIR}" && DATA_MOUNTED=true
|
||||
|
||||
# Nothing to migrate if legacy mounts are absent
|
||||
if ! ${CONFIG_MOUNTED} && ! ${DB_MOUNTED}; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Partial legacy mount state, notify and exit
|
||||
if ${CONFIG_MOUNTED} && ! ${DB_MOUNTED}; then
|
||||
>&2 printf "%s" "${YELLOW}"
|
||||
>&2 cat <<EOF
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
⚠️ ATTENTION: /app/config is still mounted but /app/db is not.
|
||||
|
||||
Mount both legacy paths alongside ${DATA_DIR} to migrate automatically,
|
||||
or unmount /app/config entirely.
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ${DB_MOUNTED} && ! ${CONFIG_MOUNTED}; then
|
||||
>&2 printf "%s" "${YELLOW}"
|
||||
>&2 cat <<EOF
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
⚠️ ATTENTION: /app/db is still mounted but /app/config is not.
|
||||
|
||||
Mount both legacy paths alongside ${DATA_DIR} to migrate automatically,
|
||||
or unmount /app/db entirely.
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! ${DATA_MOUNTED}; then
|
||||
fatal_missing_data_mount
|
||||
exit 1
|
||||
fi
|
||||
|
||||
migrate_legacy_mounts || exit 1
|
||||
exit 0
|
||||
@@ -7,30 +7,60 @@ from dataclasses import dataclass
|
||||
# if NETALERTX_DEBUG is 1 then exit
|
||||
if os.environ.get("NETALERTX_DEBUG") == "1":
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
@dataclass
|
||||
class MountCheckResult:
|
||||
"""Object to track mount status and potential issues."""
|
||||
|
||||
var_name: str
|
||||
path: str = ""
|
||||
is_writeable: bool = False
|
||||
is_mounted: bool = False
|
||||
is_mount_point: bool = False
|
||||
is_ramdisk: bool = False
|
||||
underlying_fs_is_ramdisk: bool = False # Track this separately
|
||||
underlying_fs_is_ramdisk: bool = False # Track this separately
|
||||
fstype: str = "N/A"
|
||||
error: bool = False
|
||||
write_error: bool = False
|
||||
performance_issue: bool = False
|
||||
dataloss_risk: bool = False
|
||||
category: str = ""
|
||||
role: str = ""
|
||||
group: str = ""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class PathSpec:
|
||||
"""Describes how a filesystem path should behave."""
|
||||
|
||||
var_name: str
|
||||
category: str # e.g. persist, ramdisk
|
||||
role: str # primary, sub, secondary
|
||||
group: str # logical grouping for primary/sub relationships
|
||||
|
||||
|
||||
PATH_SPECS = (
|
||||
PathSpec("NETALERTX_DATA", "persist", "primary", "data"),
|
||||
PathSpec("NETALERTX_DB", "persist", "sub", "data"),
|
||||
PathSpec("NETALERTX_CONFIG", "persist", "sub", "data"),
|
||||
PathSpec("SYSTEM_SERVICES_RUN_TMP", "ramdisk", "primary", "tmp"),
|
||||
PathSpec("NETALERTX_API", "ramdisk", "sub", "tmp"),
|
||||
PathSpec("NETALERTX_LOG", "ramdisk", "sub", "tmp"),
|
||||
PathSpec("SYSTEM_SERVICES_RUN", "ramdisk", "sub", "tmp"),
|
||||
PathSpec("SYSTEM_SERVICES_ACTIVE_CONFIG", "ramdisk", "secondary", "tmp"),
|
||||
)
|
||||
|
||||
|
||||
def get_mount_info():
|
||||
"""Parses /proc/mounts to get a dict of {mount_point: fstype}."""
|
||||
mounts = {}
|
||||
try:
|
||||
with open('/proc/mounts', 'r') as f:
|
||||
with open("/proc/mounts", "r") as f:
|
||||
for line in f:
|
||||
parts = line.strip().split()
|
||||
if len(parts) >= 3:
|
||||
mount_point = parts[1].replace('\\040', ' ')
|
||||
mount_point = parts[1].replace("\\040", " ")
|
||||
fstype = parts[2]
|
||||
mounts[mount_point] = fstype
|
||||
except FileNotFoundError:
|
||||
@@ -38,78 +68,112 @@ def get_mount_info():
|
||||
return None
|
||||
return mounts
|
||||
|
||||
def analyze_path(var_name, is_persistent, mounted_filesystems, non_persistent_fstypes, read_only_vars):
|
||||
|
||||
def _resolve_writeable_state(target_path: str) -> bool:
|
||||
"""Determine if a path is writeable, ascending to the first existing parent."""
|
||||
|
||||
current = target_path
|
||||
seen: set[str] = set()
|
||||
while True:
|
||||
if current in seen:
|
||||
break
|
||||
seen.add(current)
|
||||
|
||||
if os.path.exists(current):
|
||||
return os.access(current, os.W_OK)
|
||||
|
||||
parent_dir = os.path.dirname(current)
|
||||
if not parent_dir or parent_dir == current:
|
||||
break
|
||||
current = parent_dir
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def analyze_path(
|
||||
spec: PathSpec,
|
||||
mounted_filesystems,
|
||||
non_persistent_fstypes,
|
||||
):
|
||||
"""
|
||||
Analyzes a single path, checking for errors, performance, and dataloss.
|
||||
"""
|
||||
result = MountCheckResult(var_name=var_name)
|
||||
target_path = os.environ.get(var_name)
|
||||
result = MountCheckResult(
|
||||
var_name=spec.var_name,
|
||||
category=spec.category,
|
||||
role=spec.role,
|
||||
group=spec.group,
|
||||
)
|
||||
target_path = os.environ.get(spec.var_name)
|
||||
|
||||
if target_path is None:
|
||||
result.path = f"({var_name} unset)"
|
||||
result.path = f"({spec.var_name} unset)"
|
||||
result.error = True
|
||||
return result
|
||||
|
||||
|
||||
result.path = target_path
|
||||
|
||||
# --- 1. Check Write Permissions ---
|
||||
is_writeable = os.access(target_path, os.W_OK)
|
||||
|
||||
if not is_writeable and not os.path.exists(target_path):
|
||||
parent_dir = os.path.dirname(target_path)
|
||||
if os.access(parent_dir, os.W_OK):
|
||||
is_writeable = True
|
||||
|
||||
result.is_writeable = is_writeable
|
||||
|
||||
if var_name not in read_only_vars and not result.is_writeable:
|
||||
result.is_writeable = _resolve_writeable_state(target_path)
|
||||
|
||||
if not result.is_writeable:
|
||||
result.error = True
|
||||
result.write_error = True
|
||||
if spec.role != "secondary":
|
||||
result.write_error = True
|
||||
|
||||
# --- 2. Check Filesystem Type (Parent and Self) ---
|
||||
parent_mount_fstype = ""
|
||||
longest_mount = ""
|
||||
|
||||
for mount_point, fstype in mounted_filesystems.items():
|
||||
if target_path.startswith(mount_point):
|
||||
if len(mount_point) > len(longest_mount):
|
||||
longest_mount = mount_point
|
||||
normalized = mount_point.rstrip("/") if mount_point != "/" else "/"
|
||||
if target_path == normalized or target_path.startswith(f"{normalized}/"):
|
||||
if len(normalized) > len(longest_mount):
|
||||
longest_mount = normalized
|
||||
parent_mount_fstype = fstype
|
||||
|
||||
|
||||
result.underlying_fs_is_ramdisk = parent_mount_fstype in non_persistent_fstypes
|
||||
|
||||
|
||||
if parent_mount_fstype:
|
||||
result.fstype = parent_mount_fstype
|
||||
|
||||
# --- 3. Check if path IS a mount point ---
|
||||
if target_path in mounted_filesystems:
|
||||
result.is_mounted = True
|
||||
result.is_mount_point = True
|
||||
result.fstype = mounted_filesystems[target_path]
|
||||
result.is_ramdisk = result.fstype in non_persistent_fstypes
|
||||
else:
|
||||
result.is_mounted = False
|
||||
result.is_ramdisk = False
|
||||
if longest_mount and longest_mount != "/":
|
||||
if target_path == longest_mount or target_path.startswith(
|
||||
f"{longest_mount}/"
|
||||
):
|
||||
result.is_mounted = True
|
||||
result.fstype = parent_mount_fstype
|
||||
result.is_ramdisk = parent_mount_fstype in non_persistent_fstypes
|
||||
|
||||
# --- 4. Apply Risk Logic ---
|
||||
if is_persistent:
|
||||
if result.underlying_fs_is_ramdisk:
|
||||
if spec.category == "persist":
|
||||
if result.underlying_fs_is_ramdisk or result.is_ramdisk:
|
||||
result.dataloss_risk = True
|
||||
|
||||
|
||||
if not result.is_mounted:
|
||||
result.dataloss_risk = True
|
||||
|
||||
else:
|
||||
# Performance issue if it's not a ramdisk mount
|
||||
|
||||
elif spec.category == "ramdisk":
|
||||
if not result.is_mounted or not result.is_ramdisk:
|
||||
result.performance_issue = True
|
||||
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def print_warning_message():
|
||||
"""Prints a formatted warning to stderr."""
|
||||
YELLOW = '\033[1;33m'
|
||||
RESET = '\033[0m'
|
||||
|
||||
YELLOW = "\033[1;33m"
|
||||
RESET = "\033[0m"
|
||||
|
||||
message = (
|
||||
"══════════════════════════════════════════════════════════════════════════════\n"
|
||||
"⚠️ ATTENTION: Configuration issues detected (marked with ❌).\n\n"
|
||||
@@ -122,61 +186,139 @@ def print_warning_message():
|
||||
" https://github.com/jokob-sk/NetAlertX/blob/main/docs/docker-troubleshooting/mount-configuration-issues.md\n"
|
||||
"══════════════════════════════════════════════════════════════════════════════\n"
|
||||
)
|
||||
|
||||
|
||||
print(f"{YELLOW}{message}{RESET}", file=sys.stderr)
|
||||
|
||||
def main():
|
||||
NON_PERSISTENT_FSTYPES = {'tmpfs', 'ramfs'}
|
||||
PERSISTENT_VARS = {'NETALERTX_DB', 'NETALERTX_CONFIG'}
|
||||
# Define all possible read-only vars
|
||||
READ_ONLY_VARS = {'SYSTEM_NGINX_CONFIG', 'SYSTEM_SERVICES_ACTIVE_CONFIG'}
|
||||
|
||||
# Base paths to check
|
||||
PATHS_TO_CHECK = {
|
||||
'NETALERTX_DB': True,
|
||||
'NETALERTX_CONFIG': True,
|
||||
'NETALERTX_API': False,
|
||||
'NETALERTX_LOG': False,
|
||||
'SYSTEM_SERVICES_RUN': False,
|
||||
}
|
||||
|
||||
# *** KEY CHANGE: Conditionally add path based on PORT ***
|
||||
port_val = os.environ.get("PORT")
|
||||
if port_val is not None and port_val != "20211":
|
||||
PATHS_TO_CHECK['SYSTEM_SERVICES_ACTIVE_CONFIG'] = False
|
||||
# *** END KEY CHANGE ***
|
||||
def _get_active_specs() -> list[PathSpec]:
|
||||
"""Return the path specifications that should be evaluated for this run."""
|
||||
|
||||
return list(PATH_SPECS)
|
||||
|
||||
|
||||
def _sub_result_is_healthy(result: MountCheckResult) -> bool:
|
||||
"""Determine if a sub-path result satisfies its expected constraints."""
|
||||
|
||||
if result.category == "persist":
|
||||
if not result.is_mounted:
|
||||
return False
|
||||
if result.dataloss_risk or result.write_error or result.error:
|
||||
return False
|
||||
return True
|
||||
|
||||
if result.category == "ramdisk":
|
||||
if not result.is_mounted or not result.is_ramdisk:
|
||||
return False
|
||||
if result.performance_issue or result.write_error or result.error:
|
||||
return False
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _apply_primary_rules(specs: list[PathSpec], results_map: dict[str, MountCheckResult]) -> list[MountCheckResult]:
|
||||
"""Suppress or flag primary rows based on the state of their sub-paths."""
|
||||
|
||||
final_results: list[MountCheckResult] = []
|
||||
specs_by_group: dict[str, list[PathSpec]] = {}
|
||||
for spec in specs:
|
||||
specs_by_group.setdefault(spec.group, []).append(spec)
|
||||
|
||||
for spec in specs:
|
||||
result = results_map.get(spec.var_name)
|
||||
if result is None:
|
||||
continue
|
||||
|
||||
if spec.role == "primary":
|
||||
group_specs = specs_by_group.get(spec.group, [])
|
||||
sub_results_all = [
|
||||
results_map[s.var_name]
|
||||
for s in group_specs
|
||||
if s.var_name in results_map and s.var_name != spec.var_name
|
||||
]
|
||||
core_sub_results = [
|
||||
results_map[s.var_name]
|
||||
for s in group_specs
|
||||
if s.var_name in results_map and s.role == "sub"
|
||||
]
|
||||
|
||||
sub_mount_points = [sub for sub in sub_results_all if sub.is_mount_point]
|
||||
core_mount_points = [sub for sub in core_sub_results if sub.is_mount_point]
|
||||
all_core_subs_healthy = bool(core_sub_results) and all(
|
||||
_sub_result_is_healthy(sub) for sub in core_sub_results
|
||||
)
|
||||
all_core_subs_are_mounts = bool(core_sub_results) and len(core_mount_points) == len(core_sub_results)
|
||||
|
||||
if all_core_subs_healthy:
|
||||
if result.write_error:
|
||||
result.write_error = False
|
||||
if not result.is_writeable:
|
||||
result.is_writeable = True
|
||||
if spec.category == "persist" and result.dataloss_risk:
|
||||
result.dataloss_risk = False
|
||||
if result.error and not (result.performance_issue or result.dataloss_risk or result.write_error):
|
||||
result.error = False
|
||||
|
||||
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:
|
||||
suppress_primary = True
|
||||
|
||||
if suppress_primary:
|
||||
# All sub-paths are healthy and mounted; suppress the aggregate row.
|
||||
continue
|
||||
|
||||
if sub_mount_points and result.is_mount_point:
|
||||
result.error = True
|
||||
if result.category == "persist":
|
||||
result.dataloss_risk = True
|
||||
elif result.category == "ramdisk":
|
||||
result.performance_issue = True
|
||||
|
||||
final_results.append(result)
|
||||
|
||||
return final_results
|
||||
|
||||
|
||||
def main():
|
||||
NON_PERSISTENT_FSTYPES = {"tmpfs", "ramfs"}
|
||||
|
||||
active_specs = _get_active_specs()
|
||||
|
||||
mounted_filesystems = get_mount_info()
|
||||
if mounted_filesystems is None:
|
||||
sys.exit(1)
|
||||
|
||||
results = []
|
||||
has_issues = False
|
||||
has_write_errors = False
|
||||
for var_name, is_persistent in PATHS_TO_CHECK.items():
|
||||
result = analyze_path(
|
||||
var_name, is_persistent,
|
||||
mounted_filesystems, NON_PERSISTENT_FSTYPES, READ_ONLY_VARS
|
||||
results_map: dict[str, MountCheckResult] = {}
|
||||
for spec in active_specs:
|
||||
results_map[spec.var_name] = analyze_path(
|
||||
spec,
|
||||
mounted_filesystems,
|
||||
NON_PERSISTENT_FSTYPES,
|
||||
)
|
||||
if result.dataloss_risk or result.error or result.write_error or result.performance_issue:
|
||||
has_issues = True
|
||||
if result.write_error:
|
||||
has_write_errors = True
|
||||
results.append(result)
|
||||
|
||||
results = _apply_primary_rules(active_specs, results_map)
|
||||
|
||||
has_issues = any(
|
||||
r.dataloss_risk or r.error or r.write_error or r.performance_issue
|
||||
for r in results
|
||||
)
|
||||
has_write_errors = any(r.write_error for r in results)
|
||||
|
||||
if has_issues or True: # Always print table for diagnostic purposes
|
||||
# --- Print Table ---
|
||||
headers = ["Path", "Writeable", "Mount", "RAMDisk", "Performance", "DataLoss"]
|
||||
|
||||
|
||||
CHECK_SYMBOL = "✅"
|
||||
CROSS_SYMBOL = "❌"
|
||||
BLANK_SYMBOL = "➖"
|
||||
|
||||
bool_to_check = lambda is_good: CHECK_SYMBOL if is_good else CROSS_SYMBOL
|
||||
BLANK_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[0] = max(col_widths[0], len(str(r.path)))
|
||||
|
||||
header_fmt = (
|
||||
f" {{:<{col_widths[0]}}} |"
|
||||
@@ -186,7 +328,7 @@ def main():
|
||||
f" {{:^{col_widths[4]}}} |"
|
||||
f" {{:^{col_widths[5]}}} "
|
||||
)
|
||||
|
||||
|
||||
row_fmt = (
|
||||
f" {{:<{col_widths[0]}}} |"
|
||||
f" {{:^{col_widths[1]}}}|" # No space
|
||||
@@ -195,59 +337,64 @@ def main():
|
||||
f" {{:^{col_widths[4]}}}|" # No space
|
||||
f" {{:^{col_widths[5]}}} " # DataLoss is last, needs space
|
||||
)
|
||||
|
||||
separator = (
|
||||
"-" * (col_widths[0] + 2) + "+" +
|
||||
"-" * (col_widths[1] + 2) + "+" +
|
||||
"-" * (col_widths[2] + 2) + "+" +
|
||||
"-" * (col_widths[3] + 2) + "+" +
|
||||
"-" * (col_widths[4] + 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)
|
||||
)
|
||||
])
|
||||
|
||||
print(header_fmt.format(*headers))
|
||||
print(separator)
|
||||
for r in results:
|
||||
is_persistent = r.var_name in PERSISTENT_VARS
|
||||
|
||||
# --- Symbol Logic ---
|
||||
# Symbol Logic
|
||||
write_symbol = bool_to_check(r.is_writeable)
|
||||
# Special case for read-only vars
|
||||
if r.var_name in READ_ONLY_VARS:
|
||||
write_symbol = CHECK_SYMBOL
|
||||
|
||||
mount_symbol = CHECK_SYMBOL if r.is_mounted else CROSS_SYMBOL
|
||||
|
||||
ramdisk_symbol = ""
|
||||
if is_persistent:
|
||||
ramdisk_symbol = CROSS_SYMBOL if r.underlying_fs_is_ramdisk else BLANK_SYMBOL
|
||||
else:
|
||||
ramdisk_symbol = CHECK_SYMBOL if r.is_ramdisk else CROSS_SYMBOL
|
||||
|
||||
if is_persistent:
|
||||
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
|
||||
else:
|
||||
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)
|
||||
|
||||
print(row_fmt.format(
|
||||
r.path,
|
||||
write_symbol,
|
||||
mount_symbol,
|
||||
ramdisk_symbol,
|
||||
perf_symbol,
|
||||
dataloss_symbol
|
||||
))
|
||||
|
||||
print(
|
||||
row_fmt.format(
|
||||
r.path,
|
||||
write_symbol,
|
||||
mount_symbol,
|
||||
ramdisk_symbol,
|
||||
perf_symbol,
|
||||
dataloss_symbol,
|
||||
)
|
||||
)
|
||||
|
||||
# --- Print Warning ---
|
||||
if has_issues:
|
||||
print("\n", file=sys.stderr)
|
||||
print_warning_message()
|
||||
|
||||
|
||||
# Exit with error only if there are write permission issues
|
||||
if has_write_errors and os.environ.get("NETALERTX_DEBUG") != "1":
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
||||
@@ -3,6 +3,43 @@
|
||||
# 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."
|
||||
@@ -10,6 +47,7 @@ check_mandatory_folders() {
|
||||
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
|
||||
@@ -19,6 +57,7 @@ check_mandatory_folders() {
|
||||
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
|
||||
@@ -28,6 +67,7 @@ check_mandatory_folders() {
|
||||
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
|
||||
|
||||
@@ -57,7 +57,7 @@ EOF
|
||||
>&2 printf "%s" "${YELLOW}"
|
||||
>&2 cat <<EOF
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
⚠️ ATTENTION: Write permission denied.
|
||||
⚠️ ATTENTION: Read permission denied (write permission denied).
|
||||
|
||||
The application cannot write to "${path}". This will prevent it from
|
||||
saving data, logs, or configuration.
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
# 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
|
||||
# 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
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Get bounding capabilities from /proc/self/status (what can be acquired)
|
||||
BND_HEX=$(grep '^CapBnd:' /proc/self/status 2>/dev/null | awk '{print $2}' | tr -d '\t')
|
||||
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#!/bin/bash
|
||||
# read-only-mode.sh detects and warns if running read-write on the root filesystem.
|
||||
|
||||
# This check is skipped in devcontainer mode as the devcontainer is not set up to run
|
||||
# read-only and this would always trigger a warning. RW is required for development
|
||||
# in the devcontainer.
|
||||
if [ "${NETALERTX_DEBUG}" == "1" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if the root filesystem is mounted as read-only
|
||||
if ! awk '$2 == "/" && $4 ~ /ro/ {found=1} END {exit !found}' /proc/mounts; then
|
||||
cat <<EOF
|
||||
|
||||
@@ -37,8 +37,18 @@
|
||||
#
|
||||
################################################################################
|
||||
|
||||
# Allow direct command execution (e.g., `docker run -it netalertx bash`).
|
||||
if [ "$#" -gt 0 ]; then
|
||||
case "$1" in
|
||||
bash|/bin/bash|sh|/bin/sh)
|
||||
exec "$@"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Banner display
|
||||
RED='\033[1;31m'
|
||||
GREY='\033[90m'
|
||||
RESET='\033[0m'
|
||||
printf "${RED}"
|
||||
echo '
|
||||
@@ -64,25 +74,50 @@ for script in ${ENTRYPOINT_CHECKS}/*; do
|
||||
echo "Skipping startup checks as SKIP_TESTS is set."
|
||||
break
|
||||
fi
|
||||
script_name=$(basename "$script" | sed 's/^[0-9]*-//;s/\.sh$//;s/-/ /g')
|
||||
echo " --> ${script_name}"
|
||||
script_name=$(basename "$script" | sed 's/^[0-9]*-//;s/\.(sh|py)$//;s/-/ /g')
|
||||
echo "--> ${script_name} "
|
||||
if [ -n "${SKIP_STARTUP_CHECKS:-}" ] && echo "${SKIP_STARTUP_CHECKS}" | grep -q "\b${script_name}\b"; then
|
||||
printf "${GREY}skip${RESET}\n"
|
||||
continue
|
||||
fi
|
||||
|
||||
"$script"
|
||||
NETALERTX_DOCKER_ERROR_CHECK=$?
|
||||
|
||||
if [ ${NETALERTX_DOCKER_ERROR_CHECK} -ne 0 ]; then
|
||||
if [ ${NETALERTX_DOCKER_ERROR_CHECK} -eq 1 ]; then
|
||||
>&2 printf "%s" "${RED}"
|
||||
>&2 cat <<EOF
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
❌ NetAlertX startup aborted: critical failure in ${script_name}.
|
||||
https://github.com/jokob-sk/NetAlertX/blob/main/docs/docker-troubleshooting/troubleshooting.md
|
||||
══════════════════════════════════════════════════════════════════════════════
|
||||
EOF
|
||||
>&2 printf "%s" "${RESET}"
|
||||
|
||||
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
|
||||
FAILED_STATUS="${NETALERTX_DOCKER_ERROR_CHECK}"
|
||||
echo "${script_name}: FAILED with ${FAILED_STATUS}"
|
||||
echo "Failure detected in: ${script}"
|
||||
# Continue to next check instead of exiting immediately
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
if [ -n "${FAILED_STATUS}" ]; then
|
||||
echo "Container startup checks failed with exit code ${FAILED_STATUS}."
|
||||
# Continue with startup despite failures for testing purposes
|
||||
if [ "${NETALERTX_DEBUG:-0}" -eq 1 ]; then
|
||||
echo "NETALERTX_DEBUG=1, continuing despite failed pre-checks."
|
||||
else
|
||||
exit "${FAILED_STATUS}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Set APP_CONF_OVERRIDE based on GRAPHQL_PORT if not already set
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Nginx's conf is in /services/config/nginx/conf.active. This is the default configuration when run as a read-only container without a mount.
|
||||
Nginx's active configuration lives in /tmp/nginx/active-config by default when the container runs read-only without a bind mount.
|
||||
|
||||
With a tmpfs mount on /services/config/nginx/conf.active, the nginx template will be rewritten to allow ENV customization of listen address and port.
|
||||
Mounting a writable directory at /tmp/nginx/active-config allows the entrypoint to rewrite the nginx template so LISTEN_ADDR and PORT environment overrides take effect.
|
||||
|
||||
The act of running /services/start-nginx.sh writes a new nginx.conf file, using envsubst, then starts nginx based on the parameters in that file.
|
||||
|
||||
|
||||
1
install/production-filesystem/services/config/nginx/conf.active
Symbolic link
1
install/production-filesystem/services/config/nginx/conf.active
Symbolic link
@@ -0,0 +1 @@
|
||||
/tmp/nginx/active-config
|
||||
@@ -5,7 +5,9 @@ worker_processes auto;
|
||||
pcre_jit on;
|
||||
|
||||
# Configures default error logger.
|
||||
error_log /app/log/nginx-error.log warn;
|
||||
error_log /tmp/log/nginx-error.log warn;
|
||||
|
||||
pid /tmp/run/nginx.pid;
|
||||
|
||||
events {
|
||||
# The maximum number of simultaneous connections that can be opened by
|
||||
@@ -16,11 +18,11 @@ events {
|
||||
http {
|
||||
|
||||
# Mapping of temp paths for various nginx modules.
|
||||
client_body_temp_path /services/run/tmp/client_body;
|
||||
proxy_temp_path /services/run/tmp/proxy;
|
||||
fastcgi_temp_path /services/run/tmp/fastcgi;
|
||||
uwsgi_temp_path /services/run/tmp/uwsgi;
|
||||
scgi_temp_path /services/run/tmp/scgi;
|
||||
client_body_temp_path /tmp/nginx/client_body;
|
||||
proxy_temp_path /tmp/nginx/proxy;
|
||||
fastcgi_temp_path /tmp/nginx/fastcgi;
|
||||
uwsgi_temp_path /tmp/nginx/uwsgi;
|
||||
scgi_temp_path /tmp/nginx/scgi;
|
||||
|
||||
# Includes mapping of file name extensions to MIME types of responses
|
||||
# and defines the default type.
|
||||
@@ -86,7 +88,7 @@ http {
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
# Sets the path, format, and configuration for a buffered log write.
|
||||
access_log /app/log/nginx-access.log main;
|
||||
access_log /tmp/log/nginx-access.log main;
|
||||
|
||||
|
||||
# Virtual host config
|
||||
@@ -101,7 +103,7 @@ http {
|
||||
location ~* \.php$ {
|
||||
# Set Cache-Control header to prevent caching on the first load
|
||||
add_header Cache-Control "no-store";
|
||||
fastcgi_pass unix:/services/run/php.sock;
|
||||
fastcgi_pass unix:/tmp/run/php.sock;
|
||||
include /services/config/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
;
|
||||
|
||||
[global]
|
||||
pid = /services/run/php8.3-fpm.pid
|
||||
error_log = /app/log/app.php_errors.log
|
||||
pid = /tmp/run/php8.3-fpm.pid
|
||||
error_log = /tmp/log/app.php_errors.log
|
||||
include=/services/config/php/php-fpm.d/*.conf
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
; (IPv6 and IPv4-mapped) on a specific port;
|
||||
; '/path/to/unix/socket' - to listen on a unix socket.
|
||||
; Note: This value is mandatory.
|
||||
listen = /services/run/php.sock
|
||||
listen = /tmp/run/php.sock
|
||||
|
||||
; Set listen(2) backlog.
|
||||
; Default Value: 511 (-1 on Linux, FreeBSD and OpenBSD)
|
||||
@@ -465,9 +465,9 @@ pm.max_spare_servers = 3
|
||||
; Default Value: clean env
|
||||
;env[HOSTNAME] = $HOSTNAME
|
||||
env[PATH] = /opt/venv:/usr/local/bin:/usr/bin:/bin
|
||||
env[TMP] = /services/run/tmp
|
||||
env[TMPDIR] = /services/run/tmp
|
||||
env[TEMP] = /services/run/tmp
|
||||
env[TMP] = /tmp/run/tmp
|
||||
env[TMPDIR] = /tmp/run/tmp
|
||||
env[TEMP] = /tmp/run/tmp
|
||||
|
||||
; Additional php.ini defines, specific to this pool of workers. These settings
|
||||
; overwrite the values previously defined in the php.ini. The directives are the
|
||||
@@ -489,9 +489,9 @@ env[TEMP] = /services/run/tmp
|
||||
; Default Value: nothing is defined by default except the values in php.ini and
|
||||
; specified at startup with the -d argument
|
||||
;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com
|
||||
php_admin_value[sys_temp_dir] = /services/run/tmp
|
||||
php_admin_value[upload_tmp_dir] = /services/run/tmp
|
||||
php_admin_value[session.save_path] = /services/run/tmp
|
||||
php_admin_value[sys_temp_dir] = /tmp/run/tmp
|
||||
php_admin_value[upload_tmp_dir] = /tmp/run/tmp
|
||||
php_admin_value[session.save_path] = /tmp/run/tmp
|
||||
php_admin_value[output_buffering] = 262144
|
||||
php_admin_flag[implicit_flush] = off
|
||||
php_admin_value[realpath_cache_size] = 4096K
|
||||
|
||||
@@ -15,8 +15,8 @@ set -euo pipefail
|
||||
# /usr/share/arp-scan
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
TEMP_FILE="/services/run/tmp/ieee-oui.txt.tmp"
|
||||
OUTPUT_FILE="/services/run/tmp/ieee-oui.txt"
|
||||
TEMP_FILE="${SYSTEM_SERVICES_RUN_TMP}/ieee-oui.txt.tmp"
|
||||
OUTPUT_FILE="${SYSTEM_SERVICES_RUN_TMP}/ieee-oui.txt"
|
||||
|
||||
# Download the file using wget to stdout and process it
|
||||
if ! wget --timeout=30 --tries=3 "https://standards-oui.ieee.org/oui/oui.txt" -O /dev/stdout 2>/dev/null | \
|
||||
|
||||
@@ -11,5 +11,5 @@ done
|
||||
# Force kill if graceful shutdown failed
|
||||
killall -KILL python3 &>/dev/null
|
||||
|
||||
echo "Starting python3 $(cat /services/config/python/backend-extra-launch-parameters 2>/dev/null) -m server > /app/log/stdout.log 2> >(tee /app/log/stderr.log >&2)"
|
||||
exec python3 $(cat /services/config/python/backend-extra-launch-parameters 2>/dev/null) -m server > /app/log/stdout.log 2> >(tee /app/log/stderr.log >&2)
|
||||
echo "Starting python3 $(cat /services/config/python/backend-extra-launch-parameters 2>/dev/null) -m server > ${NETALERTX_LOG}/stdout.log 2> >(tee ${NETALERTX_LOG}/stderr.log >&2)"
|
||||
exec python3 $(cat /services/config/python/backend-extra-launch-parameters 2>/dev/null) -m server > ${NETALERTX_LOG}/stdout.log 2> >(tee ${NETALERTX_LOG}/stderr.log >&2)
|
||||
|
||||
@@ -4,14 +4,13 @@ set -euo pipefail
|
||||
|
||||
LOG_DIR=${NETALERTX_LOG}
|
||||
RUN_DIR=${SYSTEM_SERVICES_RUN}
|
||||
TMP_DIR=${SYSTEM_SERVICES_RUN_TMP}
|
||||
TMP_DIR=/tmp/nginx
|
||||
SYSTEM_NGINX_CONFIG_TEMPLATE="/services/config/nginx/netalertx.conf.template"
|
||||
SYSTEM_NGINX_CONFIG_FILE="/services/config/nginx/conf.active/netalertx.conf"
|
||||
|
||||
# Create directories if they don't exist
|
||||
mkdir -p "${LOG_DIR}" "${RUN_DIR}" "${TMP_DIR}"
|
||||
|
||||
|
||||
nginx_pid=""
|
||||
|
||||
cleanup() {
|
||||
@@ -43,15 +42,18 @@ fi
|
||||
trap cleanup EXIT
|
||||
trap forward_signal INT TERM
|
||||
|
||||
# Ensure temp dirs have correct permissions
|
||||
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_NGINX_CONFIG_FILE}\" -g \"error_log /dev/stderr; error_log ${NETALERTX_LOG}/nginx-error.log; pid ${RUN_DIR}/nginx.pid; daemon off;\" &"
|
||||
echo "Starting /usr/sbin/nginx -p \"${RUN_DIR}/\" -c \"${SYSTEM_NGINX_CONFIG_FILE}\" -g \"error_log /dev/stderr; error_log ${NETALERTX_LOG}/nginx-error.log; daemon off;\" &"
|
||||
/usr/sbin/nginx \
|
||||
-p "${RUN_DIR}/" \
|
||||
-c "${SYSTEM_NGINX_CONFIG_FILE}" \
|
||||
-g "error_log /dev/stderr; error_log ${NETALERTX_LOG}/nginx-error.log; pid ${RUN_DIR}/nginx.pid; daemon off;" &
|
||||
-g "error_log /dev/stderr; error_log ${NETALERTX_LOG}/nginx-error.log; daemon off;" &
|
||||
nginx_pid=$!
|
||||
|
||||
wait "${nginx_pid}"
|
||||
|
||||
0
install/production-filesystem/app/log/report_output.json → install/production-filesystem/tmp/log/plugins/.dockerignore
Executable file → Normal file
0
install/production-filesystem/app/log/report_output.json → install/production-filesystem/tmp/log/plugins/.dockerignore
Executable file → Normal file
0
install/production-filesystem/tmp/log/stderr.log
Executable file
0
install/production-filesystem/tmp/log/stderr.log
Executable file
0
install/production-filesystem/tmp/log/stdout.log
Executable file
0
install/production-filesystem/tmp/log/stdout.log
Executable file
@@ -5,7 +5,7 @@ worker_processes auto;
|
||||
pcre_jit on;
|
||||
|
||||
# Configures default error logger.
|
||||
error_log /app/log/nginx-error.log warn;
|
||||
error_log /tmp/log/nginx-error.log warn;
|
||||
|
||||
events {
|
||||
# The maximum number of simultaneous connections that can be opened by
|
||||
@@ -16,11 +16,11 @@ events {
|
||||
http {
|
||||
|
||||
# Mapping of temp paths for various nginx modules.
|
||||
client_body_temp_path /services/run/tmp/client_body;
|
||||
proxy_temp_path /services/run/tmp/proxy;
|
||||
fastcgi_temp_path /services/run/tmp/fastcgi;
|
||||
uwsgi_temp_path /services/run/tmp/uwsgi;
|
||||
scgi_temp_path /services/run/tmp/scgi;
|
||||
client_body_temp_path /tmp/run/tmp/client_body;
|
||||
proxy_temp_path /tmp/run/tmp/proxy;
|
||||
fastcgi_temp_path /tmp/run/tmp/fastcgi;
|
||||
uwsgi_temp_path /tmp/run/tmp/uwsgi;
|
||||
scgi_temp_path /tmp/run/tmp/scgi;
|
||||
|
||||
# Includes mapping of file name extensions to MIME types of responses
|
||||
# and defines the default type.
|
||||
@@ -93,7 +93,7 @@ http {
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
# Sets the path, format, and configuration for a buffered log write.
|
||||
access_log /app/log/nginx-access.log main;
|
||||
access_log /tmp/log/nginx-access.log main;
|
||||
|
||||
|
||||
# Virtual host config
|
||||
@@ -109,7 +109,7 @@ http {
|
||||
try_files $uri =404;
|
||||
# Set Cache-Control header to prevent caching on the first load
|
||||
add_header Cache-Control "no-store";
|
||||
fastcgi_pass unix:/services/run/php.sock;
|
||||
fastcgi_pass unix:/tmp/run/php.sock;
|
||||
include /services/config/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
||||
0
install/production-filesystem/tmp/run/.dockerignore
Normal file
0
install/production-filesystem/tmp/run/.dockerignore
Normal file
Reference in New Issue
Block a user