Skip to content

feat: add NetAlertX ProxmoxVE helper scripts#1491

Open
JVKeller wants to merge 5 commits intonetalertx:mainfrom
JVKeller:feat/proxmox-installer
Open

feat: add NetAlertX ProxmoxVE helper scripts#1491
JVKeller wants to merge 5 commits intonetalertx:mainfrom
JVKeller:feat/proxmox-installer

Conversation

@JVKeller
Copy link
Contributor

@JVKeller JVKeller commented Feb 5, 2026

@jokob-sk @ingoratsdorf @adamoutler

This PR introduces the NetAlertX helper scripts to provide a streamlined, automated installation of the NetAlertX network security monitoring tool on Proxmox VE.

📝 Description

NetAlertX is a comprehensive WiFi / LAN intruder detector and network monitor. These scripts automate the creation of a Debian-based LXC container, the installation of all necessary runtimes (PHP 8.4, Python 3.13+), and the configuration of environment variables to ensure a "plug-and-play" experience.

✨ Features

  • Automated LXC Creation: Based on the latest Debian template.
  • Modern Web Stack: Automated setup of PHP 8.4 (via setup_php helper) and NGINX.
  • Hardened Python Environment: Dedicated virtual environment in /opt/netalertx-env with automated dependency management.
  • Security Best Practices:
    • Uses setcap on key binaries (nmap, arp-scan, python3) to allow network scanning without requiring full root privileges.
    • Compatible with unprivileged containers.
  • Self-Healing Startup: Includes a robust startup script that manages PYTHONPATH, creates missing package indicators (__init__.py), and ensures the correct working directory.
  • Timezone Sync: Automatically synchronizes the container's system timezone to the application configuration.
  • Update Integration: Fully implemented update_script() in the CT script, allowing users to pull latest releases and rebuild dependencies via the helper menu.

🛠️ Compliance & Standards

  • Follows the official /ct and /install templates.
  • Uses standardized helper functions (source /dev/stdin <<<"$FUNCTIONS_FILE_PATH").
  • Implements correct output suppression using $STD.
  • Includes standard header metadata (Author, License, Source).
  • Passed local audits for path resolution and dependency management.

🚀 How to Test

# You should be able override the fork with mine, or make your own.
# Paste this into your pve node. (not in a container!)

export 
REPOS_URL="https://raw.githubusercontent.com/JVKeller/NetAlertX/main"
bash -c "$(wget -qLO - ${REPOS_URL}/install/proxmox/ct/netalertx.sh)"

Summary by CodeRabbit

  • Documentation

    • Added a comprehensive Proxmox VE installation guide with Quick Start, two deployment options (host helper or standalone), hybrid storage strategy, environment variables, post-install access (default port 20211), service management, and maintenance notes.
  • New Features

    • Native Proxmox LXC installer/template with automated provisioning, mirror/local install paths, bridge auto-detection, persistent log/API storage, systemd service and startup scripts, NGINX/PHP integration, and hardware vendor DB update support.
  • Chores

    • Added pydantic to Proxmox install requirements.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 5, 2026

📝 Walkthrough

Walkthrough

Adds a Proxmox VE deployment for NetAlertX: LXC template, container installer and in-container installer, updated README and INSTALLATION_GUIDE, NGINX FastCGI env mappings, persistent storage and systemd service integration, bridge detection, update routine, and a new Python dependency.

Changes

Cohort / File(s) Summary
Documentation
install/proxmox/INSTALLATION_GUIDE.md, install/proxmox/README.md
New detailed installation guide and README updated to present two installer invocation options (Proxmox helper script on host or standalone installer inside LXC/VM).
LXC template / orchestration
install/proxmox/ct/netalertx.sh
New CT template script: exports metadata, bridge auto-detection with fallbacks and selection, support for mirror vs local installer sources, verbose logging, and an update_script() workflow to pull and restart the app.
In-container installer
install/proxmox/install/netalertx-install.sh
New comprehensive installer: installs system packages, configures PHP 8.4 and Python venv at /opt/netalertx-env, clones repo to /app, sets permissions, configures NGINX, creates start script and systemd unit, applies capabilities, and updates hardware vendor DB.
Installer refactor & service config
install/proxmox/proxmox-install-netalertx.sh, install/proxmox/netalertx.conf
Refactors to persistent /app storage and /opt/netalertx-env venv; start script and systemd unit export NETALERTX_* env vars and declare RuntimeDirectory; NGINX config now forwards FastCGI env mappings (NETALERTX_CONFIG, NETALERTX_LOG, NETALERTX_DATA, NETALERTX_API).
Dependencies
install/proxmox/requirements.txt
Adds pydantic to the Proxmox installer Python requirements.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Proxmox as Proxmox VE (host)
    participant Orchestrator as netalertx.sh (CT template)
    participant Container as LXC Container
    participant Installer as netalertx-install.sh
    participant System as Systemd / OS services
    participant Nginx as NGINX & PHP-FPM
    participant App as NetAlertX

    User->>Orchestrator: run template (local or mirror)
    Orchestrator->>Proxmox: create LXC with metadata
    Orchestrator->>Container: push installer (if local) or trigger remote install
    Container->>Installer: execute installation steps
    Installer->>System: apt installs, PHP setup, venv creation
    Installer->>Container: clone /app, create persistent dirs, set permissions
    Installer->>Nginx: deploy config (FastCGI envs) and restart
    Installer->>System: create start script & systemd unit, enable service
    System->>App: start NetAlertX service
    Nginx->>App: proxy/frontend requests via FastCGI envs
    App-->>User: service accessible (host:PORT)
Loading

Possibly related PRs

Poem

🐰 I hopped through scripts with nimble feet,

Built bridges, venvs, dirs tidy and neat,
NGINX hums and systemd keeps time,
Containers rise, services step in line,
NetAlertX wakes — a rabbit's small rhyme. 🎋

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main objective: adding Proxmox VE helper scripts for automated NetAlertX installation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@install/proxmox/install/netalertx-install.sh`:
- Around line 199-203: The chmod -R a+rwx "$INSTALL_DIR" makes the whole install
world-writable; instead restrict write access to owner/group (www-data) and
leave others read/execute only: remove the chmod -R a+rwx line and replace it
with setting file/dir modes like u=rwX,g=rwX,o=rX for the tree and make
directories setgid so new files inherit the www-data group (e.g. set directory
mode to 2775), ensure the web-writable parts referenced (front/ and the DB file
${INSTALL_DIR}/db/app.db) are owned by or writable for www-data (chgrp/chown to
www-data and ensure group write), and keep the existing chgrp and chown commands
but apply them only to the needed paths rather than the entire INSTALL_DIR.

In `@install/proxmox/INSTALLATION_GUIDE.md`:
- Around line 68-70: The fenced code block containing the example URL
("http://YOUR_SERVER_IP:YOUR_PORT") is missing a language tag which triggers
MD040; update that fenced block by adding a language identifier (e.g., use
```text) immediately after the opening backticks so the block becomes a fenced
code block with a language tag, preserving the existing content exactly.

In `@install/proxmox/proxmox-install-netalertx.sh`:
- Around line 289-298: The mkdir step creates "${INSTALL_DIR}/log" and
"${INSTALL_DIR}/api" as root so the subsequent sudo -u www-data touch calls can
fail; after creating the directories with mkdir -p, change ownership of those
directories to www-data (chown -R www-data:www-data "${INSTALL_DIR}/log"
"${INSTALL_DIR}/api") before calling sudo -u www-data touch, or alternatively
create the directories as www-data (sudo -u www-data mkdir -p ...) so that the
later touch commands succeed; ensure chown/chmod ordering is:
mkdir/mkdir-as-www-data -> chown (if needed) -> sudo -u www-data touch -> chmod.

In `@install/proxmox/README.md`:
- Around line 14-18: Update the Proxmox VE Helper Script (Recommended) command
in the README to use the canonical helper-script URL instead of the personal
fork; replace the wget URL string
"https://github.com/JVKeller/NetAlertX/raw/proxmox-baremetal-installer/install/proxmox/ct/netalertx.sh"
used in the bash -c "$(wget -qLO - <URL>)" line with the canonical URL
referenced in INSTALLATION_GUIDE.md so the primary install path points to the
official repository.
🧹 Nitpick comments (1)
install/proxmox/install/netalertx-install.sh (1)

237-246: Deduplicate NETALERTX_TMP/PORT exports.

The repeated lines add noise without changing behavior.

🧹 Suggested cleanup
 export NETALERTX_TMP=/app
 export PORT=${PORT}
-export NETALERTX_TMP=/app
-export PORT=${PORT}
 export PYTHONPATH=/app

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
install/proxmox/proxmox-install-netalertx.sh (1)

369-369: ⚠️ Potential issue | 🟠 Major

Systemd service PORT variable will not be expanded.

The heredoc on line 369 uses 'EOF' (quoted), which prevents shell variable expansion. This means ${PORT} on line 392 will be written literally as ${PORT} instead of the actual port number (e.g., 20211).

In contrast, the start script heredoc (line 333) uses unquoted EOF, so ${PORT} expands correctly there.

🔧 Suggested fix - Remove quotes from EOF delimiter
-cat > /etc/systemd/system/netalertx.service << 'EOF'
+cat > /etc/systemd/system/netalertx.service << EOF
 [Unit]
 Description=NetAlertX Service

Note: After removing the quotes, you'll also need to escape any literal $ characters in the service file that should NOT be expanded (if any).

Also applies to: 392-392

🧹 Nitpick comments (2)
install/proxmox/proxmox-install-netalertx.sh (2)

336-343: Environment variables are duplicated between start script and systemd service.

The NETALERTX_* environment variables are defined in both the generated start script (lines 336-343) and the systemd service file (lines 386-393). While this redundancy ensures the variables are set regardless of how the script is invoked, consider consolidating to a single source of truth (preferably the systemd service) to simplify maintenance.

Also applies to: 386-393


345-348: Self-healing __init__.py creation may mask packaging issues.

The __init__.py files for /app/front/ and /app/front/plugins/ do not exist in the repository but are being created at startup. This defensive measure could hide legitimate packaging problems. These files should either be committed to the repository as part of proper package structure, or their creation should be removed if they're genuinely not needed for the application's import structure.

@JVKeller
Copy link
Contributor Author

JVKeller commented Feb 5, 2026

looks like I made the bunny happy.

@adamoutler
Copy link
Collaborator

Is this using hardware install instead of docker install?

@adamoutler
Copy link
Collaborator

adamoutler commented Feb 5, 2026

I was really hoping we could do something more than a debian 13 hardware install next time. I can't get ProxMox working in a VM and my servers are all reserved for other tasks. Can you try something like this and see if it works?

Docker installation makes it way easier to upgrade, manage, maintain, and even uninstall if absolutely required. This project can't support hardware installation, but if we can get it to work in a container, then we can enhance user experience and provide support.


Step 1: Create the Container

Where: Run on Proxmox Node Shell.
Action: Launches the wizard. Select Advanced -> Privileged: Yes.

bash -c "$(wget -qLO - https://github.com/community-scripts/ProxmoxVE/raw/main/ct/docker.sh)"

Step 2: Install NetAlertX

Where: Run inside the new Container Console.
Action: Downloads config, patches it for Proxmox, and starts.

mkdir -p /opt/netalertx/data && cd /opt/netalertx
wget -qO docker-compose.yml https://raw.githubusercontent.com/netalertx/rpi-image/refs/heads/master/root_filesystem/opt/netalertx/docker-compose.yml

docker compose up -d

Access: http://<IP>:20211 (UI) or 20212 (API)

@JVKeller
Copy link
Contributor Author

JVKeller commented Feb 6, 2026

Yes. This will install at the hardware level outside the containers. Super easy if someone wants to work on the code base!

I think it just boils down to options and what different people are used to running. Docker isn't harder to use, it just uses a different tool set that a different user might want to use, just like running in HomeAssistant.

With the PVE Helper scripts line this one, all you have to do is literally type "update" in the console and it takes care of it.
One line to fully install, one work to update the entire server. Makes it real easy to try out new apps.

Also, the way it's set up, the helper script just builds the LXC container, with options for an advanced config, and then calls a new version of the 'baremetal' installer to actual populate and build the environment. That script (install/proxmox/install/netalertx-install.sh) could be ran by itself on deb/Ubuntu server directly.

Btw, of you want to set up Proxmox in a VM, you can start with a vanilla Debian13 container, and install Proxmox on top of it.

@jokob-sk
Copy link
Collaborator

jokob-sk commented Feb 6, 2026

I’m happy to keep the Proxmox/Hardware install scripts around if the community helps support them - just note there’s no official support, and Docker is still the recommended way to install.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Fix all issues with AI agents
In `@install/proxmox/ct/netalertx.sh`:
- Around line 33-54: After performing the sed/eval override of build_container
(both the REPOS_URL mirror branch and the LOCAL_INSTALLER branch), immediately
re-read the function (e.g., new_func=$(declare -f build_container)) and verify
it contains the expected unique substring from your replacement (for the mirror
branch check for the ${REPOS_URL}/install/proxmox/install/${var_install}.sh
pattern or another fixed marker; for the local branch check for the pct push
"/root/install.sh" or lxc-attach ... /root/install.sh fragment); if the check
fails, log a clear error via msg_error including the attempted replacement and
exit non-zero so the script does not continue using the unmodified
build_container; use the existing symbols original_func, build_container,
REPOS_URL, and LOCAL_INSTALLER to locate and validate the change.
- Around line 103-135: The update_script() currently runs a bare git pull and an
unsuppressed pip install and then always restarts the service; fix it by making
git update deterministic and error-checked (e.g., inside update_script() use git
stash push --include-untracked or run git fetch && git reset --hard origin/main
to force a known state, or explicitly restore config/app.conf after update), run
pip install while suppressing output with the existing $STD variable (activate
venv at /opt/netalertx-env/bin/activate then pip install -r
install/proxmox/requirements.txt $STD), and add error handling: check the exit
status of the git and pip commands and if either fails call msg_error and exit
without restarting the service (do not run systemctl start netalertx.service on
failure); reference update_script, git pull, pip install,
/opt/netalertx-env/bin/activate, config/app.conf, and systemctl start/stop
netalertx.service when applying the changes.

In `@install/proxmox/install/netalertx-install.sh`:
- Around line 150-157: The PHP-FPM socket detection using PHP_FPM_SOCKET=$(find
/run/php/ -name "php*-fpm.sock" | head -n 1) can run before PHP-FPM is started
and thus leave /etc/nginx/conf.d/netalertx.conf pointing to a non-existent
socket; update the install script to perform this detection after PHP-FPM is
started (or wait/retry briefly) and add a deterministic fallback (e.g.,
unix:/run/php/php8.4-fpm.sock) when PHP_FPM_SOCKET is empty so the sed
replacement against netalertx.conf always sets a valid socket; adjust the block
that calls msg_info/msg_warn and the sed invocation accordingly to use
PHP_FPM_SOCKET or the fallback.
- Around line 66-72: The REPO_URL is used unsafely in the git clone call;
validate REPO_URL (e.g., ensure it matches a safe URL/ssh/https pattern) before
use, then call git clone with a double-dash to separate options from positional
args and remove the trailing slash on INSTALL_DIR; specifically update the git
clone invocation in the script that uses REPO_URL and INSTALL_DIR to: validate
REPO_URL, then run git clone -- "$REPO_URL" "$INSTALL_DIR" (ensure quoting), and
keep the existing rm -rf "$INSTALL_DIR" and cd "$INSTALL_DIR" logic unchanged.
- Around line 101-116: Remove the setcap call that grants network capabilities
to the Python interpreter (the BINARY_PYTHON / setcap
cap_net_raw,cap_net_admin+eip invocation) to avoid elevating every Python
process; instead rely on the existing sudo configuration or create a small
dedicated wrapper with capabilities for the specific scanner commands
(nmap/arp-scan/nbtscan/traceroute). Also remove the duplicated status message by
deleting the extra msg_ok "Installed Python Dependencies" so it only prints
once. Ensure references to BINARY_PYTHON, setcap, and msg_ok are updated
accordingly.
- Around line 234-263: Remove the duplicate export lines for NETALERTX_TMP and
PORT in the startup heredoc that writes INSTALL_DIR/start.netalertx.sh
(duplicates currently set via the heredoc content referencing NETALERTX_TMP and
PORT); also decide whether runtime values should be captured at install time —
if you want the script to retain variable references for later, change the
heredoc to a literal form (use <<'EOF' or escape ${SERVER_IP}/${PORT}) so
${SERVER_IP} and ${PORT} are not expanded at install time, and add a brief
comment in the heredoc clarifying the intended behavior.
- Around line 206-212: The sudoers heredoc currently hardcodes paths; replace
those literals with the dynamically resolved path variables used earlier (e.g.,
the variables that were set when locating binaries for nmap, arp-scan, nbtscan,
traceroute, the venv python and system python — use their exact variable names
from the script such as NMAP_BIN, ARP_SCAN_BIN, NBTSCAN_BIN, TRACEROUTE_BIN,
VENV_PYTHON, PYTHON3_BIN), ensure each variable is non-empty (or fallback to
command -v) before writing /etc/sudoers.d/netalertx, and keep the existing chmod
440 and msg_ok/msg_info calls. This guarantees the sudoers file grants sudo to
the actual resolved binary paths rather than hardcoded locations.
🧹 Nitpick comments (6)
install/proxmox/install/netalertx-install.sh (3)

174-176: Unquoted brace expansion in touch command.

Line 175 uses brace expansion ${INSTALL_DIR}/log/{app.log,...} which works, but if any path component contained spaces, it would break. More importantly, if sudo -u www-data touch fails (e.g., permission issue), the error is silently swallowed since there's no error checking.

This is a minor robustness concern given the controlled environment.


267-300: Systemd service configuration is reasonable but consider adding security hardening directives.

The service runs as www-data which is good. However, for a network monitoring tool, consider adding systemd sandboxing directives to limit the blast radius (e.g., ProtectSystem=, ProtectHome=, NoNewPrivileges=). NoNewPrivileges=true would conflict with setcap/sudo usage, so that needs careful thought, but directives like ProtectHome=yes are safe here.


22-58: Large dependency list — consider documenting why each package is needed.

This installs ~30 packages. A brief inline comment grouping them by purpose (e.g., # Network scanning tools, # Build tools, # Runtime) would help future maintainers understand which are essential vs. optional.

Minor: tini is typically used as a Docker init process; it's unusual in a systemd-managed LXC container. Is it actually needed here?

install/proxmox/ct/netalertx.sh (3)

65-101: Bridge detection logic is thorough with good fallbacks.

The multi-method approach (ip link → sysfs → pvesh) with user prompting for multiple bridges is well thought out. The error handling for no-bridge-found is appropriate.

One minor note: line 69 concatenates two sources without deduplication by interface type — ip -o link show type bridge could return non-vmbr bridges (e.g., docker0, br-*). The grep vmbr on the sysfs path filters correctly, but the ip command output isn't filtered. The sort -u dedup on line 72 handles exact duplicates but not irrelevant bridges.

Consider filtering ip output to vmbr* bridges only
-  BRIDGES=($(ip -o link show type bridge | awk -F': ' '{print $2}') $(ls /sys/class/net | grep vmbr | grep -v "vmbr0"))
+  BRIDGES=($(ip -o link show type bridge | awk -F': ' '{print $2}' | grep '^vmbr') $(ls /sys/class/net 2>/dev/null | grep '^vmbr' | grep -v '^vmbr0$'))

12-13: Sourcing remote code from an unpinned branch over HTTPS.

source <(curl -fsSL https://...ProxmoxVE/raw/main/misc/build.func) fetches and executes arbitrary code from main with no integrity verification. This is standard practice for Proxmox community scripts, but be aware that any upstream compromise or breaking change will silently propagate. Consider pinning to a commit SHA for production use.


56-57: Exporting REPO_URL without validation.

REPO_URL is exported and eventually consumed by git clone in the install script. If a user sets REPO_URL to a value containing shell metacharacters, it flows through unchecked. The install script side was noted separately, but the export here is the origin point.

Comment on lines +33 to +54
# Support running from a mirror
if [[ -n "${REPOS_URL}" ]]; then
# Only show info message in verbose mode to avoid UI overlap
if [[ "${VERBOSE:-no}" == "yes" ]]; then
msg_info "Using custom repository: ${REPOS_URL}"
fi
# Override build_container to use the custom repo URL
original_func=$(declare -f build_container)
# Map official ProxmoxVE path to NetAlertX fork path - EXTREMELY SURGICAL to avoid core breakages
eval "$(echo "$original_func" | sed "s|https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/\${var_install}.sh|${REPOS_URL}/install/proxmox/install/\${var_install}.sh|g")"
fi

# Define local installer path for testing
LOCAL_INSTALLER="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../../install/${NSAPP:-netalertx}-install.sh"

# Override build_container to use local install script if available
if [[ -f "$LOCAL_INSTALLER" ]]; then
msg_info "Using local installer from $LOCAL_INSTALLER"
original_func=$(declare -f build_container)
replacement="pct push \"\$CTID\" \"$LOCAL_INSTALLER\" /root/install.sh && lxc-attach -n \"\$CTID\" -- bash /root/install.sh"
eval "$(echo "$original_func" | sed "s|lxc-attach.*install/\${var_install}.sh.*|$replacement|")"
fi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

sed-based function body rewriting is extremely fragile.

Both the mirror override (line 42) and the local installer override (line 53) rewrite build_container's body using sed pattern matching against an internal string in the upstream build.func. If the upstream function changes even slightly (e.g., whitespace, variable quoting, path restructuring), these sed replacements will silently fail, and the script will execute the original unmodified function — cloning from the wrong source without any error.

At minimum, add a post-override verification that the replacement actually took effect:

Proposed verification after each override
  eval "$(echo "$original_func" | sed "s|https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/\${var_install}.sh|${REPOS_URL}/install/proxmox/install/\${var_install}.sh|g")"
+  # Verify the override took effect
+  if declare -f build_container | grep -q "community-scripts/ProxmoxVE"; then
+    msg_error "Failed to override build_container with custom REPOS_URL. The upstream function signature may have changed."
+    exit 1
+  fi
 fi
🤖 Prompt for AI Agents
In `@install/proxmox/ct/netalertx.sh` around lines 33 - 54, After performing the
sed/eval override of build_container (both the REPOS_URL mirror branch and the
LOCAL_INSTALLER branch), immediately re-read the function (e.g.,
new_func=$(declare -f build_container)) and verify it contains the expected
unique substring from your replacement (for the mirror branch check for the
${REPOS_URL}/install/proxmox/install/${var_install}.sh pattern or another fixed
marker; for the local branch check for the pct push "/root/install.sh" or
lxc-attach ... /root/install.sh fragment); if the check fails, log a clear error
via msg_error including the attempted replacement and exit non-zero so the
script does not continue using the unmodified build_container; use the existing
symbols original_func, build_container, REPOS_URL, and LOCAL_INSTALLER to locate
and validate the change.

Comment on lines +103 to +135
function update_script() {
header_info
check_container_storage
check_container_resources

if [[ ! -d /app ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi

msg_info "Stopping ${APP} Service"
systemctl stop netalertx.service
msg_ok "Stopped ${APP} Service"

msg_info "Updating ${APP}"
cd /app || exit
git pull
msg_ok "Updated ${APP}"

msg_info "Updating Python Dependencies"
# shellcheck disable=SC1091 # venv activation script
source /opt/netalertx-env/bin/activate
pip install -r install/proxmox/requirements.txt
deactivate
msg_ok "Updated Python Dependencies"

msg_info "Starting ${APP} Service"
systemctl start netalertx.service
msg_ok "Started ${APP} Service"

msg_ok "Update Complete"
exit
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

update_script() uses bare git pull and unsuppressed pip install.

  1. git pull (line 119) doesn't specify a remote or branch, and doesn't handle local modifications (e.g., the config/app.conf that was modified during install with timezone settings). A dirty working tree will cause git pull to fail. Consider git stash or git checkout -- . before pulling, or use git fetch + git reset --hard origin/main if a clean state is desired.

  2. pip install on line 125 doesn't use $STD for output suppression, unlike the install script (line 96). This is inconsistent.

  3. No error handling — if git pull or pip install fails, the service is restarted anyway with potentially broken state.

Proposed improvements
   msg_info "Updating ${APP}"
   cd /app || exit
-  git pull
+  # Config files are in /app/config (not tracked), so working tree should be clean
+  $STD git fetch origin
+  $STD git reset --hard origin/main
   msg_ok "Updated ${APP}"
   
   msg_info "Updating Python Dependencies"
   # shellcheck disable=SC1091  # venv activation script
   source /opt/netalertx-env/bin/activate
-  pip install -r install/proxmox/requirements.txt
+  $STD pip install -r install/proxmox/requirements.txt
   deactivate
   msg_ok "Updated Python Dependencies"
🤖 Prompt for AI Agents
In `@install/proxmox/ct/netalertx.sh` around lines 103 - 135, The update_script()
currently runs a bare git pull and an unsuppressed pip install and then always
restarts the service; fix it by making git update deterministic and
error-checked (e.g., inside update_script() use git stash push
--include-untracked or run git fetch && git reset --hard origin/main to force a
known state, or explicitly restore config/app.conf after update), run pip
install while suppressing output with the existing $STD variable (activate venv
at /opt/netalertx-env/bin/activate then pip install -r
install/proxmox/requirements.txt $STD), and add error handling: check the exit
status of the git and pip commands and if either fails call msg_error and exit
without restarting the service (do not run systemctl start netalertx.service on
failure); reference update_script, git pull, pip install,
/opt/netalertx-env/bin/activate, config/app.conf, and systemctl start/stop
netalertx.service when applying the changes.

Comment on lines +66 to +72
INSTALL_DIR="/app"
# Default repository if not specified
REPO_URL="${REPO_URL:-https://github.com/netalertx/NetAlertX.git}"
# Ensure directory is empty
rm -rf "$INSTALL_DIR"
git clone "$REPO_URL" "$INSTALL_DIR/" --quiet
cd "$INSTALL_DIR" || exit
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Unsanitized REPO_URL is passed directly to git clone.

If REPO_URL is set by an external caller (e.g., environment variable from the CT script), a malicious value could inject arguments into the git clone command. Use -- to separate options from the positional argument, and validate the URL format.

Proposed fix
-git clone "$REPO_URL" "$INSTALL_DIR/" --quiet
+git clone --quiet -- "$REPO_URL" "$INSTALL_DIR"

Also note the trailing / on "$INSTALL_DIR/" is unnecessary and inconsistent with the rest of the script.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
INSTALL_DIR="/app"
# Default repository if not specified
REPO_URL="${REPO_URL:-https://github.com/netalertx/NetAlertX.git}"
# Ensure directory is empty
rm -rf "$INSTALL_DIR"
git clone "$REPO_URL" "$INSTALL_DIR/" --quiet
cd "$INSTALL_DIR" || exit
INSTALL_DIR="/app"
# Default repository if not specified
REPO_URL="${REPO_URL:-https://github.com/netalertx/NetAlertX.git}"
# Ensure directory is empty
rm -rf "$INSTALL_DIR"
git clone --quiet -- "$REPO_URL" "$INSTALL_DIR"
cd "$INSTALL_DIR" || exit
🤖 Prompt for AI Agents
In `@install/proxmox/install/netalertx-install.sh` around lines 66 - 72, The
REPO_URL is used unsafely in the git clone call; validate REPO_URL (e.g., ensure
it matches a safe URL/ssh/https pattern) before use, then call git clone with a
double-dash to separate options from positional args and remove the trailing
slash on INSTALL_DIR; specifically update the git clone invocation in the script
that uses REPO_URL and INSTALL_DIR to: validate REPO_URL, then run git clone --
"$REPO_URL" "$INSTALL_DIR" (ensure quoting), and keep the existing rm -rf
"$INSTALL_DIR" and cd "$INSTALL_DIR" logic unchanged.

Comment on lines +101 to +116
# ============================================================================
msg_info "Applying Security Capabilities"
# Dynamically find binary paths as they can vary between /usr/bin and /usr/sbin
BINARY_NMAP=$(command -v nmap)
BINARY_ARPSCAN=$(command -v arp-scan)
BINARY_NBTSCAN=$(command -v nbtscan)
BINARY_TRACEROUTE=$(command -v traceroute)
BINARY_PYTHON=$(readlink -f /opt/netalertx-env/bin/python)

[[ -n "$BINARY_NMAP" ]] && setcap cap_net_raw,cap_net_admin+eip "$BINARY_NMAP" || true
[[ -n "$BINARY_ARPSCAN" ]] && setcap cap_net_raw,cap_net_admin+eip "$BINARY_ARPSCAN" || true
[[ -n "$BINARY_NBTSCAN" ]] && setcap cap_net_raw,cap_net_admin,cap_net_bind_service+eip "$BINARY_NBTSCAN" || true
[[ -n "$BINARY_TRACEROUTE" ]] && setcap cap_net_raw,cap_net_admin+eip "$BINARY_TRACEROUTE" || true
[[ -n "$BINARY_PYTHON" ]] && setcap cap_net_raw,cap_net_admin+eip "$BINARY_PYTHON" || true
msg_ok "Security capabilities applied"
msg_ok "Installed Python Dependencies"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Granting cap_net_raw,cap_net_admin to the Python interpreter is overly broad and a security risk.

setcap on the Python binary (line 114) means every Python script executed via this interpreter inherits raw-network capabilities — not just NetAlertX. Combined with the www-data service user, this significantly expands the attack surface. Prefer running only the specific scanning commands via sudo (which you already configure in sudoers on line 209) or use a small wrapper script with capabilities instead.

Also, line 116 duplicates the "Installed Python Dependencies" message already printed on line 99.

Proposed fix — drop setcap on Python, remove duplicate message
 [[ -n "$BINARY_TRACEROUTE" ]] && setcap cap_net_raw,cap_net_admin+eip "$BINARY_TRACEROUTE" || true
-[[ -n "$BINARY_PYTHON" ]] && setcap cap_net_raw,cap_net_admin+eip "$BINARY_PYTHON" || true
 msg_ok "Security capabilities applied"
-msg_ok "Installed Python Dependencies"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# ============================================================================
msg_info "Applying Security Capabilities"
# Dynamically find binary paths as they can vary between /usr/bin and /usr/sbin
BINARY_NMAP=$(command -v nmap)
BINARY_ARPSCAN=$(command -v arp-scan)
BINARY_NBTSCAN=$(command -v nbtscan)
BINARY_TRACEROUTE=$(command -v traceroute)
BINARY_PYTHON=$(readlink -f /opt/netalertx-env/bin/python)
[[ -n "$BINARY_NMAP" ]] && setcap cap_net_raw,cap_net_admin+eip "$BINARY_NMAP" || true
[[ -n "$BINARY_ARPSCAN" ]] && setcap cap_net_raw,cap_net_admin+eip "$BINARY_ARPSCAN" || true
[[ -n "$BINARY_NBTSCAN" ]] && setcap cap_net_raw,cap_net_admin,cap_net_bind_service+eip "$BINARY_NBTSCAN" || true
[[ -n "$BINARY_TRACEROUTE" ]] && setcap cap_net_raw,cap_net_admin+eip "$BINARY_TRACEROUTE" || true
[[ -n "$BINARY_PYTHON" ]] && setcap cap_net_raw,cap_net_admin+eip "$BINARY_PYTHON" || true
msg_ok "Security capabilities applied"
msg_ok "Installed Python Dependencies"
# ============================================================================
msg_info "Applying Security Capabilities"
# Dynamically find binary paths as they can vary between /usr/bin and /usr/sbin
BINARY_NMAP=$(command -v nmap)
BINARY_ARPSCAN=$(command -v arp-scan)
BINARY_NBTSCAN=$(command -v nbtscan)
BINARY_TRACEROUTE=$(command -v traceroute)
BINARY_PYTHON=$(readlink -f /opt/netalertx-env/bin/python)
[[ -n "$BINARY_NMAP" ]] && setcap cap_net_raw,cap_net_admin+eip "$BINARY_NMAP" || true
[[ -n "$BINARY_ARPSCAN" ]] && setcap cap_net_raw,cap_net_admin+eip "$BINARY_ARPSCAN" || true
[[ -n "$BINARY_NBTSCAN" ]] && setcap cap_net_raw,cap_net_admin,cap_net_bind_service+eip "$BINARY_NBTSCAN" || true
[[ -n "$BINARY_TRACEROUTE" ]] && setcap cap_net_raw,cap_net_admin+eip "$BINARY_TRACEROUTE" || true
msg_ok "Security capabilities applied"
🤖 Prompt for AI Agents
In `@install/proxmox/install/netalertx-install.sh` around lines 101 - 116, Remove
the setcap call that grants network capabilities to the Python interpreter (the
BINARY_PYTHON / setcap cap_net_raw,cap_net_admin+eip invocation) to avoid
elevating every Python process; instead rely on the existing sudo configuration
or create a small dedicated wrapper with capabilities for the specific scanner
commands (nmap/arp-scan/nbtscan/traceroute). Also remove the duplicated status
message by deleting the extra msg_ok "Installed Python Dependencies" so it only
prints once. Ensure references to BINARY_PYTHON, setcap, and msg_ok are updated
accordingly.

Comment on lines +150 to +157
# Detect PHP-FPM socket and update NGINX config
PHP_FPM_SOCKET=$(find /run/php/ -name "php*-fpm.sock" | head -n 1)
if [[ -n "$PHP_FPM_SOCKET" ]]; then
msg_info "Detected PHP-FPM socket: $PHP_FPM_SOCKET"
sed -i "s|unix:/var/run/php/php-fpm.sock;|unix:$PHP_FPM_SOCKET;|g" /etc/nginx/conf.d/netalertx.conf
else
msg_warn "Could not detect PHP-FPM socket path automatically"
fi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

PHP-FPM socket detection may fail if the service hasn't fully started yet.

find /run/php/ -name "php*-fpm.sock" runs during installation before PHP-FPM is started (line 219). The socket file may not exist at this point, causing the detection to silently fail and leaving the NGINX config with a non-functional upstream. Consider moving this detection block after PHP-FPM is started, or at least add a fallback to the known 8.4 socket path.

Proposed fix — use a known fallback
 PHP_FPM_SOCKET=$(find /run/php/ -name "php*-fpm.sock" | head -n 1)
+if [[ -z "$PHP_FPM_SOCKET" ]]; then
+  # Fallback to expected PHP 8.4 socket path
+  PHP_FPM_SOCKET="/run/php/php8.4-fpm.sock"
+fi
 if [[ -n "$PHP_FPM_SOCKET" ]]; then
🤖 Prompt for AI Agents
In `@install/proxmox/install/netalertx-install.sh` around lines 150 - 157, The
PHP-FPM socket detection using PHP_FPM_SOCKET=$(find /run/php/ -name
"php*-fpm.sock" | head -n 1) can run before PHP-FPM is started and thus leave
/etc/nginx/conf.d/netalertx.conf pointing to a non-existent socket; update the
install script to perform this detection after PHP-FPM is started (or wait/retry
briefly) and add a deterministic fallback (e.g., unix:/run/php/php8.4-fpm.sock)
when PHP_FPM_SOCKET is empty so the sed replacement against netalertx.conf
always sets a valid socket; adjust the block that calls msg_info/msg_warn and
the sed invocation accordingly to use PHP_FPM_SOCKET or the fallback.

Comment on lines +206 to +212
# Configure sudoers for www-data (Needed for Init Checks & Tools)
msg_info "Configuring Sudoers"
cat > /etc/sudoers.d/netalertx <<EOF
www-data ALL=(ALL) NOPASSWD: /usr/bin/nmap, /usr/sbin/arp-scan, /usr/bin/nbtscan, /usr/bin/traceroute, /opt/netalertx-env/bin/python, /usr/bin/python3
EOF
chmod 440 /etc/sudoers.d/netalertx
msg_ok "Sudoers configured"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Sudoers entry hardcodes binary paths that may not match the system.

Lines 104–108 dynamically resolve binary paths (e.g., arp-scan might be at /usr/bin/arp-scan), but the sudoers file on line 209 hardcodes /usr/sbin/arp-scan and /usr/bin/nmap. If the detected paths differ, www-data will be denied sudo for those tools. Use the dynamically resolved variables instead.

Proposed fix
+# Build sudoers using resolved paths
 cat > /etc/sudoers.d/netalertx <<EOF
-www-data ALL=(ALL) NOPASSWD: /usr/bin/nmap, /usr/sbin/arp-scan, /usr/bin/nbtscan, /usr/bin/traceroute, /opt/netalertx-env/bin/python, /usr/bin/python3
+www-data ALL=(ALL) NOPASSWD: ${BINARY_NMAP}, ${BINARY_ARPSCAN}, ${BINARY_NBTSCAN}, ${BINARY_TRACEROUTE}, /opt/netalertx-env/bin/python, /usr/bin/python3
 EOF
🤖 Prompt for AI Agents
In `@install/proxmox/install/netalertx-install.sh` around lines 206 - 212, The
sudoers heredoc currently hardcodes paths; replace those literals with the
dynamically resolved path variables used earlier (e.g., the variables that were
set when locating binaries for nmap, arp-scan, nbtscan, traceroute, the venv
python and system python — use their exact variable names from the script such
as NMAP_BIN, ARP_SCAN_BIN, NBTSCAN_BIN, TRACEROUTE_BIN, VENV_PYTHON,
PYTHON3_BIN), ensure each variable is non-empty (or fallback to command -v)
before writing /etc/sudoers.d/netalertx, and keep the existing chmod 440 and
msg_ok/msg_info calls. This guarantees the sudoers file grants sudo to the
actual resolved binary paths rather than hardcoded locations.

Comment on lines +234 to +263
# Create startup script
cat > "$INSTALL_DIR/start.netalertx.sh" <<EOF
#!/usr/bin/env bash

# NetAlertX environment variables
export NETALERTX_CONFIG=/app/config
export NETALERTX_LOG=/app/log
export NETALERTX_DATA=/app
export NETALERTX_API=/app/api
export NETALERTX_TMP=/app
export PORT=${PORT}
export NETALERTX_TMP=/app
export PORT=${PORT}
export PYTHONPATH=/app

# Ensure package structure exists (Self-healing)
touch /app/front/__init__.py
touch /app/front/plugins/__init__.py

# Activate the virtual python environment
source /opt/netalertx-env/bin/activate

echo -e "--------------------------------------------------------------------------"
echo -e "Starting NetAlertX - navigate to http://${SERVER_IP}:${PORT}"
echo -e "--------------------------------------------------------------------------"

# Start the NetAlertX python script
cd /app
python server/
EOF
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Duplicate environment variable exports in the startup script heredoc.

NETALERTX_TMP and PORT are each exported twice (lines 243–244 and 245–246). This is a copy-paste error.

Also, since the heredoc is unquoted (<<EOF), all ${…} variables are expanded at install time. This is fine for SERVER_IP and PORT, but means the startup script is not portable if these values change later. If that's intentional, consider adding a comment to clarify.

Proposed fix — remove duplicate lines
 export NETALERTX_TMP=/app
 export PORT=${PORT}
-export NETALERTX_TMP=/app
-export PORT=${PORT}
 export PYTHONPATH=/app
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Create startup script
cat > "$INSTALL_DIR/start.netalertx.sh" <<EOF
#!/usr/bin/env bash
# NetAlertX environment variables
export NETALERTX_CONFIG=/app/config
export NETALERTX_LOG=/app/log
export NETALERTX_DATA=/app
export NETALERTX_API=/app/api
export NETALERTX_TMP=/app
export PORT=${PORT}
export NETALERTX_TMP=/app
export PORT=${PORT}
export PYTHONPATH=/app
# Ensure package structure exists (Self-healing)
touch /app/front/__init__.py
touch /app/front/plugins/__init__.py
# Activate the virtual python environment
source /opt/netalertx-env/bin/activate
echo -e "--------------------------------------------------------------------------"
echo -e "Starting NetAlertX - navigate to http://${SERVER_IP}:${PORT}"
echo -e "--------------------------------------------------------------------------"
# Start the NetAlertX python script
cd /app
python server/
EOF
# Create startup script
cat > "$INSTALL_DIR/start.netalertx.sh" <<EOF
#!/usr/bin/env bash
# NetAlertX environment variables
export NETALERTX_CONFIG=/app/config
export NETALERTX_LOG=/app/log
export NETALERTX_DATA=/app
export NETALERTX_API=/app/api
export NETALERTX_TMP=/app
export PORT=${PORT}
export PYTHONPATH=/app
# Ensure package structure exists (Self-healing)
touch /app/front/__init__.py
touch /app/front/plugins/__init__.py
# Activate the virtual python environment
source /opt/netalertx-env/bin/activate
echo -e "--------------------------------------------------------------------------"
echo -e "Starting NetAlertX - navigate to http://${SERVER_IP}:${PORT}"
echo -e "--------------------------------------------------------------------------"
# Start the NetAlertX python script
cd /app
python server/
EOF
🤖 Prompt for AI Agents
In `@install/proxmox/install/netalertx-install.sh` around lines 234 - 263, Remove
the duplicate export lines for NETALERTX_TMP and PORT in the startup heredoc
that writes INSTALL_DIR/start.netalertx.sh (duplicates currently set via the
heredoc content referencing NETALERTX_TMP and PORT); also decide whether runtime
values should be captured at install time — if you want the script to retain
variable references for later, change the heredoc to a literal form (use <<'EOF'
or escape ${SERVER_IP}/${PORT}) so ${SERVER_IP} and ${PORT} are not expanded at
install time, and add a brief comment in the heredoc clarifying the intended
behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants