Conversation
Adds bare metal installer for ubuntu. Tested with version 24.04. You may want to or have to change the PHPVERSION variable in the start script for other versions
WalkthroughAdds three Ubuntu-targeted artifacts: an installer entrypoint, a startup/orchestration script, and an Nginx site config to install, update, or start NetAlertX, handling apt packages, PHP‑FPM (PHP 8.3), Python venv, tmpfs mounts, config/db copying, and launching the Python service. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Admin as Admin
participant Installer as install.ubuntu.sh
participant Git as Git/Repo
participant Starter as start.ubuntu.sh
participant System as System (apt, services, mounts)
participant Nginx as Nginx & PHP‑FPM
participant App as NetAlertX (Python)
Admin ->> Installer: run (arg or interactive)
Installer ->> System: ensure apt, sudo, git
Installer ->> System: check /app exists
alt /app exists && mode=install
Installer ->> System: stop nginx, kill python, unmount /app/api,/app/front
Installer ->> System: remove /app contents
Installer ->> Git: clone repo -> /app
else /app exists && mode=update
Installer ->> System: stop nginx, kill python
Installer ->> Git: git -C /app pull
else new install
Installer ->> Git: clone repo -> /app
end
Installer ->> Starter: execute start.ubuntu.sh
Starter ->> System: apt-get install packages, configure php-fpm socket
Starter ->> System: create/activate venv, pip install deps
Starter ->> System: mount tmpfs, copy configs/db, set permissions
Starter ->> Nginx: enable site, start php-fpm and nginx
Starter ->> App: start python service (background)
App -->> Admin: app reachable at http://<host>:20211/netalertx
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Pre-merge checks (3 passed)✅ Passed checks (3 passed)
Poem
✨ Finishing Touches
🧪 Generate unit tests
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 14
🧹 Nitpick comments (3)
install/ubuntu/install.ubuntu.sh (2)
85-86: Invoke start script via bash to avoid execute-bit surprises-"$INSTALL_DIR/install/ubuntu/start.ubuntu.sh" +bash "$INSTALL_DIR/install/ubuntu/start.ubuntu.sh"
1-2: Fail fast#!/usr/bin/env bash + +set -Eeuo pipefailinstall/ubuntu/start.ubuntu.sh (1)
213-214: Show the effective port in the banner-echo "[INSTALL] 🚀 Starting app - navigate to your <server IP>:${PORT}" +echo "[INSTALL] 🚀 Starting app - navigate to your <server IP>:${PORT:-20211}"
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
install/ubuntu/install.ubuntu.sh(1 hunks)install/ubuntu/netalertx.ubuntu.conf(1 hunks)install/ubuntu/start.ubuntu.sh(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
install/ubuntu/start.ubuntu.sh (1)
server/api_server/nettools_endpoint.py (1)
traceroute(28-72)
🪛 Shellcheck (0.10.0)
install/ubuntu/install.ubuntu.sh
[warning] 55-55: Use "${var:?}" to ensure this never expands to / .
(SC2115)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: docker_dev
🔇 Additional comments (1)
install/ubuntu/netalertx.ubuntu.conf (1)
2-2: Confirm default_server on port 20211 doesn’t conflict
Validate that no other server block listens on 20211 as the default_server on each target host.
Run on the host:nginx -T | rg -n 'listen\s+.*20211' ss -tlnp | grep ':20211'
| location ~* \.php$ { | ||
| # Set Cache-Control header to prevent caching on the first load | ||
| add_header Cache-Control "no-store"; | ||
| fastcgi_pass unix:/run/php/php8.3-fpm.sock; | ||
| include fastcgi_params; | ||
| fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; | ||
| fastcgi_param SCRIPT_NAME $fastcgi_script_name; | ||
| fastcgi_connect_timeout 75; | ||
| fastcgi_send_timeout 600; | ||
| fastcgi_read_timeout 600; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Harden PHP handling: add try_files, send X-Forwarded-Prefix to FPM, tighten regex, fix header/indent
Prevents executing non-existent scripts, makes the prefix available to the app, avoids case-insensitive .PHP execution, and tidies indentation.
- location ~* \.php$ {
+ location ~ \.php$ {
# Set Cache-Control header to prevent caching on the first load
- add_header Cache-Control "no-store";
+ add_header Cache-Control "no-store" always;
+ try_files $uri =404;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
+ fastcgi_param HTTP_X_FORWARDED_PREFIX "/netalertx";
fastcgi_connect_timeout 75;
- fastcgi_send_timeout 600;
- fastcgi_read_timeout 600;
+ fastcgi_send_timeout 600;
+ fastcgi_read_timeout 600;
}📝 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.
| location ~* \.php$ { | |
| # Set Cache-Control header to prevent caching on the first load | |
| add_header Cache-Control "no-store"; | |
| fastcgi_pass unix:/run/php/php8.3-fpm.sock; | |
| include fastcgi_params; | |
| fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; | |
| fastcgi_param SCRIPT_NAME $fastcgi_script_name; | |
| fastcgi_connect_timeout 75; | |
| fastcgi_send_timeout 600; | |
| fastcgi_read_timeout 600; | |
| } | |
| location ~ \.php$ { | |
| # Set Cache-Control header to prevent caching on the first load | |
| add_header Cache-Control "no-store" always; | |
| try_files $uri =404; | |
| fastcgi_pass unix:/run/php/php8.3-fpm.sock; | |
| include fastcgi_params; | |
| fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; | |
| fastcgi_param SCRIPT_NAME $fastcgi_script_name; | |
| fastcgi_param HTTP_X_FORWARDED_PREFIX "/netalertx"; | |
| fastcgi_connect_timeout 75; | |
| fastcgi_send_timeout 600; | |
| fastcgi_read_timeout 600; | |
| } |
🤖 Prompt for AI Agents
In install/ubuntu/netalertx.ubuntu.conf around lines 9 to 19, the PHP location
block needs hardening: change the location regex to match only lowercase ".php"
(e.g. \.php$), add a try_files directive to prevent executing non-existent
scripts (try_files $uri =404), forward the proxy prefix to PHP-FPM by adding a
fastcgi_param X-Forwarded-Prefix $http_x_forwarded_prefix (or set from
$request_uri as appropriate), ensure Cache-Control header and other directives
use consistent indentation, and keep existing fastcgi_* timeouts and
SCRIPT_FILENAME/SCRIPT_NAME fastcgi_param lines unchanged but aligned for
readability.
| chmod -R a+rwx $WEB_UI_DIR | ||
|
|
||
| echo "[INSTALL] Fixing INSTALL_DIR: ${INSTALL_DIR}" | ||
|
|
||
| chmod -R a+rw $INSTALL_PATH/log | ||
| chmod -R a+rwx $INSTALL_DIR | ||
|
|
There was a problem hiding this comment.
World-writable perms on the entire install dir are dangerous; scope to specific paths
-chmod -R a+rwx $WEB_UI_DIR
+chown -R root:www-data "$WEB_UI_DIR"
+chmod -R u=rwX,g=rX,o=rX "$WEB_UI_DIR"
@@
-chmod -R a+rw $INSTALL_PATH/log
-chmod -R a+rwx $INSTALL_DIR
+chmod -R u=rwX,g=rwX,o= "$INSTALL_PATH/log"
+chmod -R u=rwX,g=rwX,o= "${INSTALL_DIR}/api" "$INSTALL_PATH/config" "$INSTALL_PATH/db"📝 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.
| chmod -R a+rwx $WEB_UI_DIR | |
| echo "[INSTALL] Fixing INSTALL_DIR: ${INSTALL_DIR}" | |
| chmod -R a+rw $INSTALL_PATH/log | |
| chmod -R a+rwx $INSTALL_DIR | |
| # tighten down permissions on the web UI | |
| chown -R root:www-data "$WEB_UI_DIR" | |
| chmod -R u=rwX,g=rX,o=rX "$WEB_UI_DIR" | |
| echo "[INSTALL] Fixing INSTALL_DIR: ${INSTALL_DIR}" | |
| # only log and specific service directories need write access | |
| chmod -R u=rwX,g=rwX,o= "$INSTALL_PATH/log" | |
| chmod -R u=rwX,g=rwX,o= "${INSTALL_DIR}/api" "$INSTALL_PATH/config" "$INSTALL_PATH/db" |
🤖 Prompt for AI Agents
In install/ubuntu/start.ubuntu.sh around lines 165-171, the script makes the
entire install directory world-writable (chmod -R a+rwx $WEB_UI_DIR and chmod -R
a+rwx $INSTALL_DIR and chmod -R a+rw $INSTALL_PATH/log) which is dangerous;
instead restrict permissions to only the specific paths that actually need write
access (e.g., the web UI assets and the log directory), set ownership to the
service user/group (chown service_user:service_group <paths>), and apply
restrictive modes (e.g., 750/770 or 640/660 as appropriate) or group-write only
(g+rw) rather than a+rwx/a+rw; update the three chmod lines to target those
specific subdirectories with safe modes and ensure ownership is set before
changing perms.
| cp --update=none "${INSTALL_PATH}/back/$CONF_FILE" "${INSTALL_PATH}/config/$CONF_FILE" | ||
| cp --update=none "${INSTALL_PATH}/back/$DB_FILE" "$FILEDB" | ||
|
|
There was a problem hiding this comment.
cp option is invalid; ensure dirs exist and use -n to avoid overwrites
-cp --update=none "${INSTALL_PATH}/back/$CONF_FILE" "${INSTALL_PATH}/config/$CONF_FILE"
-cp --update=none "${INSTALL_PATH}/back/$DB_FILE" "$FILEDB"
+mkdir -p "${INSTALL_PATH}/config" "${INSTALL_PATH}/db"
+cp -n "${INSTALL_PATH}/back/$CONF_FILE" "${INSTALL_PATH}/config/$CONF_FILE"
+cp -n "${INSTALL_PATH}/back/$DB_FILE" "$FILEDB"📝 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.
| cp --update=none "${INSTALL_PATH}/back/$CONF_FILE" "${INSTALL_PATH}/config/$CONF_FILE" | |
| cp --update=none "${INSTALL_PATH}/back/$DB_FILE" "$FILEDB" | |
| # ensure target directories exist | |
| mkdir -p "${INSTALL_PATH}/config" "${INSTALL_PATH}/db" | |
| # copy without overwriting existing files | |
| cp -n "${INSTALL_PATH}/back/$CONF_FILE" "${INSTALL_PATH}/config/$CONF_FILE" | |
| cp -n "${INSTALL_PATH}/back/$DB_FILE" "$FILEDB" |
🤖 Prompt for AI Agents
In install/ubuntu/start.ubuntu.sh around lines 187-189, the cp commands use an
invalid option (--update=none) and do not ensure target directories exist;
replace --update=none with a supported no-overwrite flag such as -n (or
--no-clobber) and before copying ensure the destination directories exist (mkdir
-p for "${INSTALL_PATH}/config" and the directory containing "$FILEDB"); keep
the existing variable quoting and semantics so files are not overwritten and
copies succeed reliably.
There was a problem hiding this comment.
Copy option not invalid, in fact using -n will generate warnings with ubuntu.
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check cp command options and test both --update=none and -n flags
echo "=== Testing cp command options ==="
# Check cp version and available options
cp --help | grep -E "(update|no-clobber)"
echo -e "\n=== Testing --update=none option ==="
# Test --update=none option
mkdir -p test_dir/source test_dir/dest
echo "source content" > test_dir/source/testfile.txt
echo "dest content" > test_dir/dest/testfile.txt
# Test --update=none
cp --update=none test_dir/source/testfile.txt test_dir/dest/testfile.txt 2>&1
echo "Exit code for --update=none: $?"
cat test_dir/dest/testfile.txt
echo -e "\n=== Testing -n option ==="
# Reset files
echo "source content new" > test_dir/source/testfile.txt
echo "dest content original" > test_dir/dest/testfile.txt
# Test -n option
cp -n test_dir/source/testfile.txt test_dir/dest/testfile.txt 2>&1
echo "Exit code for -n: $?"
cat test_dir/dest/testfile.txt
# Clean up
rm -rf test_dir
echo -e "\n=== Checking Ubuntu version ==="
lsb_release -a 2>/dev/null || cat /etc/os-release
Length of output: 499
@ingoratsdorf Thank you for the feedback! I've tested both options on Ubuntu, and the results show that --update=none is actually invalid:
Test Results:
cp --update=noneproduces the error:cp: option '--update' doesn't allow an argumentcp -nworks correctly without any warnings (exit code 0)
The cp help output shows:
-n, --no-clobber- do not overwrite an existing file-u, --update- copy only when the SOURCE file is newer (no arguments accepted)
The --update option exists but doesn't accept the =none argument. The correct approach is indeed to use -n (or --no-clobber) to prevent overwriting existing files, which is exactly what your script intends to do.
My original suggestion stands - the current code will fail with the invalid --update=none option.
✏️ Learnings added
Learnt from: ingoratsdorf
PR: jokob-sk/NetAlertX#1166
File: install/ubuntu/start.ubuntu.sh:187-189
Timestamp: 2025-09-09T21:10:26.416Z
Learning: In Ubuntu systems, the cp command's --update option does not accept arguments like "=none". The correct way to prevent overwriting existing files is to use -n or --no-clobber flags. The --update=none syntax is invalid and will cause cp to fail with an error.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
|
Thanks a lot for the PR @ingoratsdorf 🙏 otherwise, let me know once this PR is good to merge if you want to address the coderabbit comments first - thanks a lot |
|
Oh, we will probably need to update the docs as well. |
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
install/ubuntu/install.ubuntu.sh (1)
49-60: Make “wipe and re-clone” safe; fix SC2115 and remove hard-coded /app in pkill
Current block risks destructive rm -rf and misses installs not in /app.- if [ "$confirmation" == "install" ]; then - if [ -n "$INSTALL_DIR" ] && [ "$INSTALL_DIR" != "" ]; then - echo "Removing existing installation..." - service nginx stop 2>/dev/null - pkill -f "python /app/server" 2>/dev/null - umount "$INSTALL_DIR/api" 2>/dev/null - umount "$INSTALL_DIR/front" 2>/dev/null - rm -rf "$INSTALL_DIR/" - git clone https://github.com/jokob-sk/NetAlertX "$INSTALL_DIR/" - else - echo "INSTALL_DIR is not set or is root. Aborting for safety." - exit 1 - fi + if [ "$confirmation" == "install" ]; then + # Safety checks + if [ -z "${INSTALL_DIR:-}" ] || [ "$INSTALL_DIR" = "/" ] || [ "$INSTALL_DIR" = "." ]; then + echo "Invalid or unsafe INSTALL_DIR='$INSTALL_DIR'. Aborting." + exit 1 + fi + echo "Removing existing installation..." + service nginx stop 2>/dev/null || true + pkill -f "python ${INSTALL_DIR}/server" 2>/dev/null || true + if command -v mountpoint >/dev/null 2>&1; then + mountpoint -q "$INSTALL_DIR/api" && umount "$INSTALL_DIR/api" || true + mountpoint -q "$INSTALL_DIR/front" && umount "$INSTALL_DIR/front" || true + else + umount "$INSTALL_DIR/api" 2>/dev/null || true + umount "$INSTALL_DIR/front" 2>/dev/null || true + fi + rm -rf -- "${INSTALL_DIR:?}/" + git clone https://github.com/jokob-sk/NetAlertX "$INSTALL_DIR/"
🧹 Nitpick comments (6)
install/ubuntu/install.ubuntu.sh (6)
1-2: Enable strict mode for safer installs
Use bash strict mode to fail fast on errors and undefined vars.#!/usr/bin/env bash +set -euo pipefail +IFS=$'\n\t'
15-17: Make INSTALL_DIR configurable (honor env override)
Avoid hard-coding; allow users/CI to set INSTALL_DIR.-# Set environment variables -INSTALL_DIR=/app # Specify the installation directory here +# Set environment variables +# Allow override via environment: e.g. `INSTALL_DIR=/opt/netalertx sudo -E ./install.ubuntu.sh` +INSTALL_DIR="${INSTALL_DIR:-/app}" # Default install dir
25-33: Run apt in noninteractive mode to avoid prompts
Prevents hangs on TTY-less runs and speeds up installs.echo "Updating packages" echo "-----------------" -apt-get update +export DEBIAN_FRONTEND=noninteractive +apt-get update -y echo "Making sure sudo is installed" -apt-get install sudo -y +apt-get install -y sudo # Install Git echo "Installing Git" -apt-get install -y git +apt-get install -y git
62-66: Consistency: tolerate missing nginx and ensure cd failure doesn’t proceed
Minor robustness tweaks.- service nginx stop 2>/dev/null - pkill -f "python ${INSTALL_DIR}/server" 2>/dev/null - cd "$INSTALL_DIR" || { echo "Failed to change directory to $INSTALL_DIR"; exit 1; } + service nginx stop 2>/dev/null || true + pkill -f "python ${INSTALL_DIR}/server" 2>/dev/null || true + cd "$INSTALL_DIR" || { echo "Failed to change directory to $INSTALL_DIR"; exit 1; }
85-86: Optionally replace shell with start script
Not required, but exec avoids an extra shell process.-"$INSTALL_DIR/install/ubuntu/start.ubuntu.sh" +exec "$INSTALL_DIR/install/ubuntu/start.ubuntu.sh"
51-55: Refine shell commands and address ShellCheck warnings
- Change
read -p "Enter your choice: " confirmationto
read -r -p "Enter your choice: " confirmation
to preserve backslashes (SC2162).- Update
rm -rf "$INSTALL_DIR/"to
rm -rf "${INSTALL_DIR:?}/"
to guard against an emptyINSTALL_DIR(SC2115).- Optionally, wrap the nginx stop and unmounts in checks—e.g.:
to reduce noise when errors are already redirected to /dev/null.if systemctl is-active --quiet nginx; then systemctl stop nginx fi if mountpoint -q "$INSTALL_DIR/api"; then umount "$INSTALL_DIR/api" fi
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
install/ubuntu/install.ubuntu.sh(1 hunks)install/ubuntu/start.ubuntu.sh(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- install/ubuntu/start.ubuntu.sh
🧰 Additional context used
🪛 Shellcheck (0.10.0)
install/ubuntu/install.ubuntu.sh
[warning] 55-55: Use "${var:?}" to ensure this never expands to / .
(SC2115)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: docker_dev
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
I used your Debian installer as base, but had to fix a few things for Ubuntu. Added a few things for robustness and a few convenience things like choice between delete install dir or just run an update or just nothing and start. Especially the whole Nginx startup, links, config files created a lot of issues when anything old was there. Should all work now, I ran it a few times with all sorts of scenarios. |
Fixes typo in start.ubuntu.sh Redirects output of python server to /dev/null to avoid I/O errors if started from SSH for example
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (7)
install/ubuntu/install.ubuntu.sh (7)
1-2: Harden script execution.Enable strict mode for safer failures.
#!/usr/bin/env bash - +set -euo pipefail +IFS=$'\n\t'
16-16: Allow INSTALL_DIR override via env.Keep default /app but let users change it without editing the file.
-INSTALL_DIR=/app # Specify the installation directory here +: "${INSTALL_DIR:=/app}" # Default install directory; override via env
53-58: Simplify nginx stop logic and ignore benign failures.Current list-units grep can mislead; just try stopping with fallback.
- # Stop nginx if running - if command -v systemctl >/dev/null 2>&1 && systemctl list-units --type=service | grep -q nginx; then - systemctl stop nginx 2>/dev/null - elif command -v service >/dev/null 2>&1; then - service nginx stop 2>/dev/null - fi + # Stop nginx if available (ignore if not installed) + if command -v systemctl >/dev/null 2>&1; then + systemctl stop nginx 2>/dev/null || true + elif command -v service >/dev/null 2>&1; then + service nginx stop 2>/dev/null || true + fi
61-61: Tighten process termination.Use a consistent, defensive pattern; add -- and a broader match to cover both spaces and args.
- pkill -f "python.*${INSTALL_DIR}/server" 2>/dev/null + pkill -f -- "python.*${INSTALL_DIR}/server" 2>/dev/null @@ - pkill -f "python ${INSTALL_DIR}/server" 2>/dev/null + pkill -f -- "python.*${INSTALL_DIR}/server" 2>/dev/nullAlso applies to: 83-83
105-105: Invoke start script via bash to avoid exec-bit pitfalls.Prevents failures if the file isn’t executable.
-"$INSTALL_DIR/install/ubuntu/start.ubuntu.sh" +bash "$INSTALL_DIR/install/ubuntu/start.ubuntu.sh"
28-30: Installing sudo while already root is unnecessary.Harmless but can be skipped to speed up runs.
-echo "Making sure sudo is installed" -apt-get install sudo -y +# sudo is not needed when running as root; skip install to save time +# apt-get install -y sudo
35-47: Non-interactive option hint.Consider a non-interactive mode (e.g., CONFIRMATION env/cmd flag) for automation.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
install/ubuntu/install.ubuntu.sh(1 hunks)install/ubuntu/netalertx.ubuntu.conf(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- install/ubuntu/netalertx.ubuntu.conf
🧰 Additional context used
🪛 Shellcheck (0.10.0)
install/ubuntu/install.ubuntu.sh
[warning] 68-68: Use "${var:?}" to ensure this never expands to /* .
(SC2115)
[error] 92-92: Parsing stopped here. Is this keyword correctly matched up?
(SC1089)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: docker_dev
| #!/usr/bin/env bash | ||
|
|
||
| # 🛑 Important: This is only used for the bare-metal install 🛑 | ||
| # Update /install/start.ubuntu.sh in most cases is preferred | ||
|
|
||
| echo "---------------------------------------------------------" | ||
| echo "[INSTALL] Starting NetAlertX installation for Ubuntu" | ||
| echo "---------------------------------------------------------" | ||
| echo | ||
| echo "This script will install NetAlertX on your Ubuntu system." | ||
| echo "It will clone the repository, set up necessary files, and start the application." | ||
| echo "Please ensure you have a stable internet connection." | ||
| echo "---------------------------------------------------------" | ||
|
|
||
| # Set environment variables | ||
| INSTALL_DIR=/app # Specify the installation directory here | ||
|
|
||
| # Check if script is run as root | ||
| if [[ $EUID -ne 0 ]]; then | ||
| echo "This script must be run as root. Please use 'sudo'." | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Prepare the environment | ||
| echo "Updating packages" | ||
| echo "-----------------" | ||
| apt-get update | ||
| echo "Making sure sudo is installed" | ||
| apt-get install sudo -y | ||
|
|
||
| # Install Git | ||
| echo "Installing Git" | ||
| apt-get install -y git | ||
|
|
||
| # Clean the directory, ask for confirmation | ||
| if [ -d "$INSTALL_DIR" ]; then | ||
| echo "The installation directory exists. Removing it to ensure a clean install." | ||
| echo "Are you sure you want to continue? This will delete all existing files in $INSTALL_DIR." | ||
| echo "Type:" | ||
| echo " - 'install' to continue" | ||
| echo " - 'update' to just update from GIT" | ||
| echo " - 'start' to do nothing, leave install as-is" | ||
| if [ "$1" == "install" ] || [ "$1" == "update" ] || [ "$1" == "start" ]; then | ||
| confirmation=$1 | ||
| else | ||
| read -p "Enter your choice: " confirmation | ||
| fi | ||
| if [ "$confirmation" == "install" ]; then | ||
| # Ensure INSTALL_DIR is safe to wipe | ||
| if [ -n "$INSTALL_DIR" ] && [ "$INSTALL_DIR" != "" ] && [ "$INSTALL_DIR" != "/" ] && [ "$INSTALL_DIR" != "." ] && [ -d "$INSTALL_DIR" ]; then | ||
| echo "Removing existing installation..." | ||
|
|
||
| # Stop nginx if running | ||
| if command -v systemctl >/dev/null 2>&1 && systemctl list-units --type=service | grep -q nginx; then | ||
| systemctl stop nginx 2>/dev/null | ||
| elif command -v service >/dev/null 2>&1; then | ||
| service nginx stop 2>/dev/null | ||
| fi | ||
|
|
||
| # Kill running NetAlertX server processes in this INSTALL_DIR | ||
| pkill -f "python.*${INSTALL_DIR}/server" 2>/dev/null | ||
|
|
||
| # Unmount only if mountpoints exist | ||
| mountpoint -q "$INSTALL_DIR/api" && umount "$INSTALL_DIR/api" 2>/dev/null | ||
| mountpoint -q "$INSTALL_DIR/front" && umount "$INSTALL_DIR/front" 2>/dev/null | ||
|
|
||
| # Remove all contents safely | ||
| rm -rf -- "$INSTALL_DIR"/* "$INSTALL_DIR"/.[!.]* "$INSTALL_DIR"/..?* 2>/dev/null | ||
|
|
||
| # Re-clone repository | ||
| git clone https://github.com/jokob-sk/NetAlertX "$INSTALL_DIR/" | ||
| else | ||
| echo "INSTALL_DIR is not set, is root, or is invalid. Aborting for safety." | ||
| exit 1 | ||
| fi | ||
| else | ||
| echo "INSTALL_DIR is not set or is root. Aborting for safety." | ||
| exit 1 | ||
| fi | ||
| elif [ "$confirmation" == "update" ]; then | ||
| echo "Updating the existing installation..." | ||
| service nginx stop 2>/dev/null | ||
| pkill -f "python ${INSTALL_DIR}/server" 2>/dev/null | ||
| cd "$INSTALL_DIR" || { echo "Failed to change directory to $INSTALL_DIR"; exit 1; } | ||
| git pull | ||
| elif [ "$confirmation" == "start" ]; then | ||
| echo "Continuing without changes." | ||
| else | ||
| echo "Installation aborted." | ||
| exit 1 | ||
| fi | ||
| else | ||
| git clone https://github.com/jokob-sk/NetAlertX "$INSTALL_DIR/" | ||
| fi | ||
|
|
||
| # Check for buildtimestamp.txt existence, otherwise create it | ||
| if [ ! -f "$INSTALL_DIR/front/buildtimestamp.txt" ]; then | ||
| date +%s > "$INSTALL_DIR/front/buildtimestamp.txt" | ||
| fi | ||
|
|
||
| # Start NetAlertX | ||
|
|
||
| # This is where we setup the virtual environment and install dependencies | ||
| cd "$INSTALL_DIR/install/ubuntu" || { echo "Failed to change directory to $INSTALL_DIR/install/ubuntu"; exit 1; } | ||
| "$INSTALL_DIR/install/ubuntu/start.ubuntu.sh" |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Quick validation script to confirm fixes (syntax + risky patterns).
Run this to catch syntax errors and remaining risky wipes.
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Bash syntax check
bash -n install/ubuntu/install.ubuntu.sh && echo "Syntax OK"
# 2) Flag unsafe rm patterns
rg -nP 'rm\s+-rf\s+--\s+"\$INSTALL_DIR"/\*' install/ubuntu/install.ubuntu.sh || echo "No unsafe rm -rf globs found"
# 3) Ensure pkill matches INSTALL_DIR and not hard-coded /app
rg -n 'pkill -f' install/ubuntu/install.ubuntu.shLength of output: 344
🏁 Script executed:
#!/bin/bash
nl -ba install/ubuntu/install.ubuntu.sh | sed -n '1,120p'Length of output: 40
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="install/ubuntu/install.ubuntu.sh"
if [ -f "$FILE" ]; then
echo "Printing first 150 lines of $FILE with line numbers:"
cat -n "$FILE" | sed -n '1,150p'
else
echo "Error: $FILE not found"
exit 1
fiLength of output: 4689
Fix mismatched conditionals in install/ubuntu/install.ubuntu.sh
Syntax check fails at line 92 due to an orphaned else—the confirmation branches (install/update/start) are split across two if blocks and extra fi/else statements. Collapse them into a single if … elif … elif … else … fi structure (lines 48–91) so that each elif and else pairs correctly with the opening if.
🧰 Tools
🪛 Shellcheck (0.10.0)
[warning] 68-68: Use "${var:?}" to ensure this never expands to /* .
(SC2115)
[error] 92-92: Parsing stopped here. Is this keyword correctly matched up?
(SC1089)
| if [ "$confirmation" == "install" ]; then | ||
| # Ensure INSTALL_DIR is safe to wipe | ||
| if [ -n "$INSTALL_DIR" ] && [ "$INSTALL_DIR" != "" ] && [ "$INSTALL_DIR" != "/" ] && [ "$INSTALL_DIR" != "." ] && [ -d "$INSTALL_DIR" ]; then | ||
| echo "Removing existing installation..." | ||
|
|
||
| # Stop nginx if running | ||
| if command -v systemctl >/dev/null 2>&1 && systemctl list-units --type=service | grep -q nginx; then | ||
| systemctl stop nginx 2>/dev/null | ||
| elif command -v service >/dev/null 2>&1; then | ||
| service nginx stop 2>/dev/null | ||
| fi | ||
|
|
||
| # Kill running NetAlertX server processes in this INSTALL_DIR | ||
| pkill -f "python.*${INSTALL_DIR}/server" 2>/dev/null | ||
|
|
||
| # Unmount only if mountpoints exist | ||
| mountpoint -q "$INSTALL_DIR/api" && umount "$INSTALL_DIR/api" 2>/dev/null | ||
| mountpoint -q "$INSTALL_DIR/front" && umount "$INSTALL_DIR/front" 2>/dev/null | ||
|
|
||
| # Remove all contents safely | ||
| rm -rf -- "$INSTALL_DIR"/* "$INSTALL_DIR"/.[!.]* "$INSTALL_DIR"/..?* 2>/dev/null | ||
|
|
||
| # Re-clone repository | ||
| git clone https://github.com/jokob-sk/NetAlertX "$INSTALL_DIR/" | ||
| else | ||
| echo "INSTALL_DIR is not set, is root, or is invalid. Aborting for safety." | ||
| exit 1 | ||
| fi | ||
| else | ||
| echo "INSTALL_DIR is not set or is root. Aborting for safety." | ||
| exit 1 | ||
| fi | ||
| elif [ "$confirmation" == "update" ]; then | ||
| echo "Updating the existing installation..." | ||
| service nginx stop 2>/dev/null | ||
| pkill -f "python ${INSTALL_DIR}/server" 2>/dev/null | ||
| cd "$INSTALL_DIR" || { echo "Failed to change directory to $INSTALL_DIR"; exit 1; } | ||
| git pull | ||
| elif [ "$confirmation" == "start" ]; then | ||
| echo "Continuing without changes." | ||
| else | ||
| echo "Installation aborted." | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
Fix unmatched else/elif causing parse error (SC1089).
Restructure the branch to a single if/elif/else chain.
- if [ "$confirmation" == "install" ]; then
+ if [ "$confirmation" = "install" ]; then
# Ensure INSTALL_DIR is safe to wipe
if [ -n "$INSTALL_DIR" ] && [ "$INSTALL_DIR" != "" ] && [ "$INSTALL_DIR" != "/" ] && [ "$INSTALL_DIR" != "." ] && [ -d "$INSTALL_DIR" ]; then
echo "Removing existing installation..."
@@
# Re-clone repository
git clone https://github.com/jokob-sk/NetAlertX "$INSTALL_DIR/"
else
- echo "INSTALL_DIR is not set, is root, or is invalid. Aborting for safety."
- exit 1
- fi
- else
- echo "INSTALL_DIR is not set or is root. Aborting for safety."
- exit 1
- fi
- elif [ "$confirmation" == "update" ]; then
+ echo "INSTALL_DIR is not set, is root (/), dot (.), or invalid. Aborting for safety."
+ exit 1
+ fi
+ elif [ "$confirmation" = "update" ]; then
echo "Updating the existing installation..."
service nginx stop 2>/dev/null
- pkill -f "python ${INSTALL_DIR}/server" 2>/dev/null
+ pkill -f "python ${INSTALL_DIR}/server" 2>/dev/null
cd "$INSTALL_DIR" || { echo "Failed to change directory to $INSTALL_DIR"; exit 1; }
git pull
- elif [ "$confirmation" == "start" ]; then
+ elif [ "$confirmation" = "start" ]; then
echo "Continuing without changes."
else
echo "Installation aborted."
exit 1
fi📝 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.
| if [ "$confirmation" == "install" ]; then | |
| # Ensure INSTALL_DIR is safe to wipe | |
| if [ -n "$INSTALL_DIR" ] && [ "$INSTALL_DIR" != "" ] && [ "$INSTALL_DIR" != "/" ] && [ "$INSTALL_DIR" != "." ] && [ -d "$INSTALL_DIR" ]; then | |
| echo "Removing existing installation..." | |
| # Stop nginx if running | |
| if command -v systemctl >/dev/null 2>&1 && systemctl list-units --type=service | grep -q nginx; then | |
| systemctl stop nginx 2>/dev/null | |
| elif command -v service >/dev/null 2>&1; then | |
| service nginx stop 2>/dev/null | |
| fi | |
| # Kill running NetAlertX server processes in this INSTALL_DIR | |
| pkill -f "python.*${INSTALL_DIR}/server" 2>/dev/null | |
| # Unmount only if mountpoints exist | |
| mountpoint -q "$INSTALL_DIR/api" && umount "$INSTALL_DIR/api" 2>/dev/null | |
| mountpoint -q "$INSTALL_DIR/front" && umount "$INSTALL_DIR/front" 2>/dev/null | |
| # Remove all contents safely | |
| rm -rf -- "$INSTALL_DIR"/* "$INSTALL_DIR"/.[!.]* "$INSTALL_DIR"/..?* 2>/dev/null | |
| # Re-clone repository | |
| git clone https://github.com/jokob-sk/NetAlertX "$INSTALL_DIR/" | |
| else | |
| echo "INSTALL_DIR is not set, is root, or is invalid. Aborting for safety." | |
| exit 1 | |
| fi | |
| else | |
| echo "INSTALL_DIR is not set or is root. Aborting for safety." | |
| exit 1 | |
| fi | |
| elif [ "$confirmation" == "update" ]; then | |
| echo "Updating the existing installation..." | |
| service nginx stop 2>/dev/null | |
| pkill -f "python ${INSTALL_DIR}/server" 2>/dev/null | |
| cd "$INSTALL_DIR" || { echo "Failed to change directory to $INSTALL_DIR"; exit 1; } | |
| git pull | |
| elif [ "$confirmation" == "start" ]; then | |
| echo "Continuing without changes." | |
| else | |
| echo "Installation aborted." | |
| exit 1 | |
| fi | |
| if [ "$confirmation" = "install" ]; then | |
| # Ensure INSTALL_DIR is safe to wipe | |
| if [ -n "$INSTALL_DIR" ] && [ "$INSTALL_DIR" != "" ] && [ "$INSTALL_DIR" != "/" ] && [ "$INSTALL_DIR" != "." ] && [ -d "$INSTALL_DIR" ]; then | |
| echo "Removing existing installation..." | |
| # Stop nginx if running | |
| if command -v systemctl >/dev/null 2>&1 && systemctl list-units --type=service | grep -q nginx; then | |
| systemctl stop nginx 2>/dev/null | |
| elif command -v service >/dev/null 2>&1; then | |
| service nginx stop 2>/dev/null | |
| fi | |
| # Kill running NetAlertX server processes in this INSTALL_DIR | |
| pkill -f "python.*${INSTALL_DIR}/server" 2>/dev/null | |
| # Unmount only if mountpoints exist | |
| mountpoint -q "$INSTALL_DIR/api" && umount "$INSTALL_DIR/api" 2>/dev/null | |
| mountpoint -q "$INSTALL_DIR/front" && umount "$INSTALL_DIR/front" 2>/dev/null | |
| # Remove all contents safely | |
| rm -rf -- "$INSTALL_DIR"/* "$INSTALL_DIR"/.[!.]* "$INSTALL_DIR"/..?* 2>/dev/null | |
| # Re-clone repository | |
| git clone https://github.com/jokob-sk/NetAlertX "$INSTALL_DIR/" | |
| else | |
| echo "INSTALL_DIR is not set, is root (/), dot (.), or invalid. Aborting for safety." | |
| exit 1 | |
| fi | |
| elif [ "$confirmation" = "update" ]; then | |
| echo "Updating the existing installation..." | |
| service nginx stop 2>/dev/null | |
| pkill -f "python ${INSTALL_DIR}/server" 2>/dev/null | |
| cd "$INSTALL_DIR" || { echo "Failed to change directory to $INSTALL_DIR"; exit 1; } | |
| git pull | |
| elif [ "$confirmation" = "start" ]; then | |
| echo "Continuing without changes." | |
| else | |
| echo "Installation aborted." | |
| exit 1 | |
| fi |
🧰 Tools
🪛 Shellcheck (0.10.0)
[warning] 68-68: Use "${var:?}" to ensure this never expands to /* .
(SC2115)
🤖 Prompt for AI Agents
In install/ubuntu/install.ubuntu.sh around lines 48-91 the if/else nesting is
mismatched (extra else/fi) causing a shell parse error; refactor into a single
if/elif/else chain by removing the redundant nested else/fi pair, keep the
safety check for INSTALL_DIR as the first branch (and its corresponding fi),
then have elif branches for "update" and "start" and a final else for abort;
ensure each conditional uses a matching fi and that indentation and control flow
are consistent so the script parses correctly.
| # Remove all contents safely | ||
| rm -rf -- "$INSTALL_DIR"/* "$INSTALL_DIR"/.[!.]* "$INSTALL_DIR"/..?* 2>/dev/null | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
Make wipe step safe; eliminate SC2115 risk.
Avoid globbing that could expand to /*; delete children via find with ${var:?}.
- # Remove all contents safely
- rm -rf -- "$INSTALL_DIR"/* "$INSTALL_DIR"/.[!.]* "$INSTALL_DIR"/..?* 2>/dev/null
+ # Remove all contents safely
+ find "${INSTALL_DIR:?}" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} + 2>/dev/null📝 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.
| # Remove all contents safely | |
| rm -rf -- "$INSTALL_DIR"/* "$INSTALL_DIR"/.[!.]* "$INSTALL_DIR"/..?* 2>/dev/null | |
| # Remove all contents safely | |
| find "${INSTALL_DIR:?}" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} + 2>/dev/null |
🧰 Tools
🪛 Shellcheck (0.10.0)
[warning] 68-68: Use "${var:?}" to ensure this never expands to /* .
(SC2115)
🤖 Prompt for AI Agents
In install/ubuntu/install.ubuntu.sh around lines 67 to 69, the current rm -rf
with multiple globs is unsafe and triggers SC2115; replace it with a find-based
deletion that uses the parameter expansion check ${INSTALL_DIR:?} and removes
only the directory's children (e.g., use find "$INSTALL_DIR" -mindepth 1
-maxdepth 1 and -exec rm -rf -- {} + or -delete) so you never expand to /* and
you fail fast if INSTALL_DIR is empty or unset.
| # Check for buildtimestamp.txt existence, otherwise create it | ||
| if [ ! -f "$INSTALL_DIR/front/buildtimestamp.txt" ]; then | ||
| date +%s > "$INSTALL_DIR/front/buildtimestamp.txt" | ||
| fi |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Ensure front directory exists before writing timestamp.
Guard against missing front/ on fresh clone errors.
You can verify with a quick check:
🏁 Script executed:
#!/bin/bash
set -e
test -d "$INSTALL_DIR/front" || echo "Warning: $INSTALL_DIR/front missing before timestamp write"Length of output: 46
Ensure the front directory exists before writing the timestamp
Add a directory-creation step to prevent write failures on fresh clones.
Insert before line 96 in install/ubuntu/install.ubuntu.sh:
+ mkdir -p "$INSTALL_DIR/front"
# Check for buildtimestamp.txt existence, otherwise create it
if [ ! -f "$INSTALL_DIR/front/buildtimestamp.txt" ]; then
date +%s > "$INSTALL_DIR/front/buildtimestamp.txt"
fi📝 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.
| # Check for buildtimestamp.txt existence, otherwise create it | |
| if [ ! -f "$INSTALL_DIR/front/buildtimestamp.txt" ]; then | |
| date +%s > "$INSTALL_DIR/front/buildtimestamp.txt" | |
| fi | |
| mkdir -p "$INSTALL_DIR/front" | |
| # Check for buildtimestamp.txt existence, otherwise create it | |
| if [ ! -f "$INSTALL_DIR/front/buildtimestamp.txt" ]; then | |
| date +%s > "$INSTALL_DIR/front/buildtimestamp.txt" | |
| fi |
🤖 Prompt for AI Agents
In install/ubuntu/install.ubuntu.sh around lines 96 to 99, the script writes
buildtimestamp.txt into $INSTALL_DIR/front without ensuring that the front
directory exists; add a step to create the directory before the file check
(e.g., run mkdir -p "$INSTALL_DIR/front" or equivalent using the same
$INSTALL_DIR variable) so the subsequent date > ... command cannot fail on fresh
clones.
|
Updated, checked a few times. |
|
Great! 🎊Can you please update the docs too or do you want to submit a separate pr? |
|
@jokob-sk re the docs, I'll update over the next few days if that's ok. Baby steps :-) |
Adds bare metal installer for ubuntu. Tested with version 24.04. You may want to or have to change the PHPVERSION variable in the start script for other versions
Summary by CodeRabbit