Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions install/proxmox/INSTALLATION_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# NetAlertX Installation Guide for Proxmox VE

## Quick Start (ProxmoxVE LXC Container)

To create a NetAlertX LXC container on Proxmox VE, run this command on your Proxmox host:

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

This will:
- Create a Debian 13 LXC container
- Install all dependencies automatically
- Configure NetAlertX with NGINX on port 20211
- Start the service automatically

### Update Existing Installation

To update an existing NetAlertX container:
- Type ```update``` in the NetAlertX LXC Console
- Or run this command on your Proxmox host:
```bash
bash -c "$(wget -qLO - https://github.com/community-scripts/ProxmoxVE/raw/main/ct/netalertx.sh)" -s update
```

---

## Installation Process Overview

### 1. **System Preparation**
- Updates system packages

### 2. **Dependency Installation**
- Installs NGINX web server
- Installs Python 3 and development tools
- Installs network scanning tools (nmap, arp-scan, fping, etc.)
- Installs system utilities (sqlite3, dnsutils, avahi-daemon, etc.)

### 3. **Application Setup**
- Clones NetAlertX repository to `/app`
- Creates Python virtual environment at `/opt/netalertx-env`
- Installs Python dependencies from requirements.txt
- Configures NGINX with default port 20211

### 4. **File Structure Creation**
- Creates persistent directories for `/app/log` and `/app/api`
- Creates log files and plugin directories
- Copies initial database and configuration files
- Sets secure file permissions (www-data user/group)
- Configures systemd RuntimeDirectory (`/run/netalertx`) for volatile service files

### 5. **Service Configuration**
- Creates startup script at `/app/start.netalertx.sh`
- Installs systemd service (`netalertx.service`)
- Enables auto-start on boot
- Starts NetAlertX and NGINX services

### 6. **Hardware Vendor Database**
- Updates IEEE OUI database for MAC address vendor identification (if not present)

---

## Post-Installation

### Accessing NetAlertX

After successful installation, access the web interface at:

```
http://YOUR_SERVER_IP:YOUR_PORT
```

**Default port**: 20211

To find your server IP:
```bash
ip -4 route get 1.1.1.1 | awk '{for(i=1;i<=NF;i++) if ($i=="src") {print $(i+1); exit}}'
```

### Service Management

```bash
# Check service status
systemctl status netalertx.service

# View real-time logs
journalctl -u netalertx.service -f

# Restart service
systemctl restart netalertx.service

# Stop service
systemctl stop netalertx.service
```

---

## Important File Locations

| Component | Location |
|-----------|----------|
| Installation Directory | `/app` |
| Configuration File | `/app/config/app.conf` |
| Database File | `/app/db/app.db` |
| NGINX Configuration | `/etc/nginx/conf.d/netalertx.conf` |
| Web UI (symlink) | `/var/www/html/netalertx` → `/app/front` |
| Python Virtual Env | `/opt/netalertx-env` |
| Systemd Service | `/etc/systemd/system/netalertx.service` |
| Startup Script | `/app/start.netalertx.sh` |
| Application Logs | `/app/log/` (persistent) |
| API Files | `/app/api/` (persistent) |
| Service Runtime | `/run/netalertx/` (tmpfs, systemd-managed) |

### Storage Strategy (Hybrid Approach)

**Persistent Storage** (survives reboots):
- `/app/log/app.log` - Main application log
- `/app/log/execution_queue.log` - Task execution log
- `/app/log/app_front.log` - Frontend log
- `/app/log/app.php_errors.log` - PHP error log
- `/app/log/stderr.log` - Standard error output
- `/app/log/stdout.log` - Standard output
- `/app/log/db_is_locked.log` - Database lock log
- `/app/api/user_notifications.json` - User notification data

**Volatile Storage** (tmpfs, cleared on reboot):
- `/run/netalertx/` - Systemd-managed runtime directory for service temporary files

Systemd service logs are always available via: `journalctl -u netalertx.service`

---

## Environment Variables

The installation script supports the following environment variables:

| Variable | Description | Default |
|----------|-------------|---------|
| `NETALERTX_ASSUME_YES` | Skip all interactive prompts | (not set) |
| `ASSUME_YES` | Alternative to NETALERTX_ASSUME_YES | (not set) |
| `PORT` | HTTP port for web interface | 20211 |
| `NETALERTX_FORCE` | Force installation without prompts | (not set) |

---

## Security Considerations

- **Runtime directory**: Systemd manages `/run/netalertx/` as tmpfs with `noexec,nosuid,nodev` flags
- **File permissions**: Application files restricted to `www-data` user/group only (mode 0750)
- **Service isolation**: Runs as unprivileged `www-data` user
- **Automatic restart**: Service configured to restart on failure
- **Persistent logs**: Application logs survive reboots for debugging and audit trails

---

## Additional Resources

- **GitHub Repository**: https://github.com/netalertx/NetAlertX
- **Issue Tracker**: https://github.com/netalertx/NetAlertX/issues
- **Documentation**: https://docs.netalertx.com
11 changes: 9 additions & 2 deletions install/proxmox/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,16 @@ An installer script for deploying NetAlertX on Proxmox VE (Debian-based) system

### Installation

## Download and run the installer
#### Proxmox VE Helper Script (Recommended)
This is the easiest way to deploy NetAlertX on Proxmox. Run this command on your Proxmox host:
```bash
wget https://raw.githubusercontent.com/jokob-sk/NetAlertX/refs/heads/main/install/proxmox/proxmox-install-netalertx.sh -O proxmox-install-netalertx.sh && chmod +x proxmox-install-netalertx.sh && ./proxmox-install-netalertx.sh
bash -c "$(wget -qLO - https://github.com/netalertx/NetAlertX/raw/main/install/proxmox/ct/netalertx.sh)"
```

#### Standalone Script (Inside existing LXC/VM)
Download and run the installer inside a fresh Debian/Ubuntu system:
```bash
wget https://raw.githubusercontent.com/netalertx/NetAlertX/main/install/proxmox/proxmox-install-netalertx.sh -O proxmox-install-netalertx.sh && chmod +x proxmox-install-netalertx.sh && ./proxmox-install-netalertx.sh
```

## 📋 What This Installer Does
Expand Down
153 changes: 153 additions & 0 deletions install/proxmox/ct/netalertx.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#!/usr/bin/env bash

# Copyright (c) 2021-2026 community-scripts ORG
# Author: JVKeller

# License: GPL 3.0 | NetAlertX | https://github.com/netalertx/NetAlertX/blob/main/LICENSE.txt
# Source: https://github.com/netalertx/NetAlertX

# License: MIT | ProxmoxVE | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/ProxmoxVE

# Import main orchestrator
source <(curl -fsSL https://github.com/community-scripts/ProxmoxVE/raw/main/misc/build.func)

# Application Configuration
APP="NetAlertX"
var_tags="network;monitoring;security"
var_cpu="2"
var_ram="2048"
var_disk="10"
# Container Type & OS
var_os="debian"
var_version="13"
var_unprivileged="1"
# var_password="root" # Uncomment if you want to hardcode a password for testing

# Standard initialization
header_info "$APP"
variables
color
catch_errors

# 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
Comment on lines +33 to +54
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.


# Export variables to ensure they're passed to the installation script
export NSAPP APP var_os var_version var_cpu var_ram var_disk var_unprivileged PORT VERBOSE REPO_URL

# Support verbose logging
if [[ "${VERBOSE:-no}" == "yes" ]]; then
set -x
STD=""
fi

# Automatically detect bridge if vmbr0 is missing
if ! ip link show vmbr0 >/dev/null 2>&1 || [[ "$(cat /sys/class/net/vmbr0/bridge/bridge_id 2>/dev/null)" == "" ]]; then
# Get List of Bridges using multiple methods
# shellcheck disable=SC2207,SC2010 # Working pattern for bridge detection
BRIDGES=($(ip -o link show type bridge | awk -F': ' '{print $2}') $(ls /sys/class/net | grep vmbr | grep -v "vmbr0"))
# Remove duplicates
# shellcheck disable=SC2207 # Working pattern for deduplication
BRIDGES=($(echo "${BRIDGES[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))

if [ ${#BRIDGES[@]} -eq 0 ]; then
# Fallback to pvesh if available
if command -v pvesh >/dev/null 2>&1; then
# shellcheck disable=SC2207,SC2046 # Working pattern for pvesh output
BRIDGES=($(pvesh get /nodes/$(hostname)/network --type bridge --output-format json | grep -oP '"iface":"\K[^"]+'))
fi
fi

if [ ${#BRIDGES[@]} -eq 0 ]; then
msg_error "No network bridges (vmbr) detected. Please create a Linux Bridge in Proxmox first."
exit 1
elif [ ${#BRIDGES[@]} -eq 1 ]; then
export var_bridge="${BRIDGES[0]}"
msg_info "Using detected bridge: ${var_bridge}"
else
# Multiple bridges found, let the user pick
BRIDGE_MENU=()
for b in "${BRIDGES[@]}"; do
BRIDGE_MENU+=("$b" "Network Bridge")
done
# shellcheck disable=SC2155 # Standard whiptail pattern
export var_bridge=$(whiptail --title "Select Network Bridge" --menu "vmbr0 not found. Please select a valid bridge:" 15 60 5 "${BRIDGE_MENU[@]}" 3>&1 1>&2 2>&3)
if [ -z "$var_bridge" ]; then
msg_error "No bridge selected. Aborting."
exit 1
fi
fi
fi

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
}
Comment on lines +103 to +135
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.


# Start the container creation workflow
start

# Build the container with selected configuration
build_container

# Set container description/notes in Proxmox UI
description

# Display success message
msg_ok "Completed successfully!\n"

echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:${PORT:-20211}${CL}"
echo -e "${INFO}${YW} Service Management:${CL}"
echo -e "${TAB}systemctl status netalertx.service${CL}"
Loading