mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 01:26:11 -08:00
feat: setup devcontainer
This commit is contained in:
112
.devcontainer/Dockerfile
Executable file
112
.devcontainer/Dockerfile
Executable file
@@ -0,0 +1,112 @@
|
||||
# DO NOT MODIFY THIS FILE DIRECTLY. IT IS AUTO-GENERATED BY .devcontainer/scripts/generate-dockerfile.sh
|
||||
|
||||
# ---/Dockerfile---
|
||||
FROM alpine:3.22 AS builder
|
||||
|
||||
ARG INSTALL_DIR=/app
|
||||
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
# Install build dependencies
|
||||
RUN apk add --no-cache bash shadow python3 python3-dev gcc musl-dev libffi-dev openssl-dev git \
|
||||
&& python -m venv /opt/venv
|
||||
|
||||
# Enable venv
|
||||
ENV PATH="/opt/venv/bin:$PATH"
|
||||
|
||||
|
||||
RUN pip install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask flask-cors unifi-sm-api tplink-omada-client wakeonlan pycryptodome requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython librouteros yattag git+https://github.com/foreign-sub/aiofreepybox.git
|
||||
|
||||
# Append Iliadbox certificate to aiofreepybox
|
||||
|
||||
# second stage
|
||||
FROM alpine:3.22 AS runner
|
||||
|
||||
ARG INSTALL_DIR=/app
|
||||
|
||||
COPY --from=builder /opt/venv /opt/venv
|
||||
COPY --from=builder /usr/sbin/usermod /usr/sbin/groupmod /usr/sbin/
|
||||
|
||||
# Enable venv
|
||||
ENV PATH="/opt/venv/bin:$PATH"
|
||||
|
||||
# default port and listen address
|
||||
ENV PORT=20211 LISTEN_ADDR=0.0.0.0
|
||||
|
||||
# needed for s6-overlay
|
||||
ENV S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0
|
||||
|
||||
# ❗ IMPORTANT - if you modify this file modify the /install/install_dependecies.sh file as well ❗
|
||||
|
||||
RUN apk update --no-cache \
|
||||
&& apk add --no-cache bash libbsd zip lsblk gettext-envsubst sudo mtr tzdata s6-overlay \
|
||||
&& apk add --no-cache curl arp-scan iproute2 iproute2-ss nmap nmap-scripts traceroute nbtscan avahi avahi-tools openrc dbus net-tools net-snmp-tools bind-tools awake ca-certificates \
|
||||
&& apk add --no-cache sqlite php83 php83-fpm php83-cgi php83-curl php83-sqlite3 php83-session \
|
||||
&& apk add --no-cache python3 nginx \
|
||||
&& ln -s /usr/bin/awake /usr/bin/wakeonlan \
|
||||
&& rm -f /etc/nginx/http.d/default.conf
|
||||
|
||||
|
||||
# Add crontab file
|
||||
COPY --chmod=600 --chown=root:root install/crontab /etc/crontabs/root
|
||||
|
||||
# Start all required services
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=2 \
|
||||
CMD curl -sf -o /dev/null ${LISTEN_ADDR}:${PORT}/php/server/query_json.php?file=app_state.json
|
||||
|
||||
ENTRYPOINT ["/init"]
|
||||
|
||||
# ---/resources/devcontainer-Dockerfile---
|
||||
|
||||
# Devcontainer build stage (do not build directly)
|
||||
# This file is combined with the root /Dockerfile by
|
||||
# .devcontainer/scripts/generate-dockerfile.sh
|
||||
# The generator appends this stage to produce .devcontainer/Dockerfile.
|
||||
# Prefer to place dev-only setup here; use setup.sh only for runtime fixes.
|
||||
|
||||
FROM runner AS devcontainer
|
||||
ENV INSTALL_DIR=/app
|
||||
ENV PYTHONPATH=/workspaces/NetAlertX/test:/workspaces/NetAlertX/server:/app:/app/server:/opt/venv/lib/python3.12/site-packages
|
||||
|
||||
# Install common tools, create user, and set up sudo
|
||||
RUN apk add --no-cache git nano vim jq php83-pecl-xdebug py3-pip nodejs sudo gpgconf pytest pytest-cov && \
|
||||
adduser -D -s /bin/sh netalertx && \
|
||||
addgroup netalertx nginx && \
|
||||
addgroup netalertx www-data && \
|
||||
echo "netalertx ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/90-netalertx && \
|
||||
chmod 440 /etc/sudoers.d/90-netalertx
|
||||
# Install debugpy in the virtualenv if present, otherwise into system python3
|
||||
RUN /bin/sh -c '(/opt/venv/bin/python3 -m pip install --no-cache-dir debugpy) || (python3 -m pip install --no-cache-dir debugpy) || true'
|
||||
# setup nginx
|
||||
COPY .devcontainer/resources/netalertx-devcontainer.conf /etc/nginx/http.d/netalert-frontend.conf
|
||||
RUN set -e; \
|
||||
chown netalertx:nginx /etc/nginx/http.d/netalert-frontend.conf; \
|
||||
install -d -o netalertx -g www-data -m 775 /app; \
|
||||
install -d -o netalertx -g www-data -m 755 /run/nginx; \
|
||||
install -d -o netalertx -g www-data -m 755 /var/lib/nginx/logs; \
|
||||
rm -f /var/lib/nginx/logs/* || true; \
|
||||
for f in error access; do : > /var/lib/nginx/logs/$f.log; done; \
|
||||
install -d -o netalertx -g www-data -m 777 /run/php; \
|
||||
install -d -o netalertx -g www-data -m 775 /var/log/php; \
|
||||
chown -R netalertx:www-data /etc/nginx/http.d; \
|
||||
chmod -R 775 /etc/nginx/http.d; \
|
||||
chown -R netalertx:www-data /var/lib/nginx; \
|
||||
chmod -R 755 /var/lib/nginx && \
|
||||
chown -R netalertx:www-data /var/log/nginx/ && \
|
||||
sed -i '/^user /d' /etc/nginx/nginx.conf; \
|
||||
sed -i 's|^error_log .*|error_log /dev/stderr warn;|' /etc/nginx/nginx.conf; \
|
||||
sed -i 's|^access_log .*|access_log /dev/stdout main;|' /etc/nginx/nginx.conf; \
|
||||
sed -i 's|error_log .*|error_log /dev/stderr warn;|g' /etc/nginx/http.d/*.conf 2>/dev/null || true; \
|
||||
sed -i 's|access_log .*|access_log /dev/stdout main;|g' /etc/nginx/http.d/*.conf 2>/dev/null || true; \
|
||||
mkdir -p /run/openrc; \
|
||||
chown netalertx:nginx /run/openrc/; \
|
||||
rm -Rf /run/openrc/*;
|
||||
|
||||
# setup pytest
|
||||
RUN sudo /opt/venv/bin/python -m pip install -U pytest pytest-cov
|
||||
|
||||
WORKDIR /workspaces/NetAlertX
|
||||
|
||||
|
||||
ENTRYPOINT ["/bin/sh","-c","sleep infinity"]
|
||||
30
.devcontainer/README.md
Normal file
30
.devcontainer/README.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# NetAlertX Devcontainer Notes
|
||||
|
||||
This devcontainer replicates the production container as closely as practical, with a few development-oriented differences.
|
||||
|
||||
Key behavior
|
||||
- No init process: Services are managed by shell scripts using killall, setsid, and nohup. Startup and restarts are script-driven rather than supervised by an init system.
|
||||
- Autogenerated Dockerfile: The effective devcontainer Dockerfile is generated on demand by `.devcontainer/scripts/generate-dockerfile.sh`. It combines the root `Dockerfile` (with certain COPY instructions removed) and an extra "devcontainer" stage from `.devcontainer/resources/devcontainer-Dockerfile`. When you change the resource Dockerfile, re-run the generator to refresh `.devcontainer/Dockerfile`.
|
||||
- Where to put setup: Prefer baking setup into `.devcontainer/resources/devcontainer-Dockerfile`. Use `.devcontainer/scripts/setup.sh` only for steps that must happen at container start (e.g., cleaning up nginx/php ownership, creating directories, touching runtime files) or depend on runtime paths.
|
||||
|
||||
Debugging (F5)
|
||||
The Frontend and backend run in debug mode always. You can attach your debugger at any time.
|
||||
- Python Backend Debug: Attach - The backend runs with a debugger on port 5678. Set breakpoints in the code and press F5 to begin triggering them.
|
||||
- PHP Frontend (XDebug) Xdebug listens on 9003. Start listening and use an Xdebug extension in your browser to debug PHP.
|
||||
|
||||
Common workflows (F1->Tasks: Run Task)
|
||||
- Regenerate the devcontainer Dockerfile: Run the VS Code task "Generate Dockerfile" or execute `.devcontainer/scripts/generate-dockerfile.sh`. The result is `.devcontainer/Dockerfile`.
|
||||
- Re-run startup provisioning: Use the task "Re-Run Startup Script" to execute `.devcontainer/scripts/setup.sh` in the container.
|
||||
- Start services:
|
||||
- Backend (GraphQL/Flask): `.devcontainer/scripts/restart-backend.sh` starts it under debugpy and logs to `/app/log/app.log`
|
||||
- Frontend (nginx + PHP-FPM): Started via setup.sh; can be restarted by the task "Start Frontend (nginx and PHP-FPM)".
|
||||
|
||||
Testing
|
||||
- pytest is installed via Alpine packages (py3-pytest, py3-pytest-cov).
|
||||
- PYTHONPATH includes workspace and venv site-packages so tests can import `server/*` modules and third-party libs.
|
||||
- Run tests via VS Code Pytest Runner or `pytest -q` from the workspace root.
|
||||
|
||||
Conventions
|
||||
- Don’t edit `.devcontainer/Dockerfile` directly; edit `.devcontainer/resources/devcontainer-Dockerfile` and regenerate.
|
||||
- Keep setup in the resource Dockerfile when possible; reserve `setup.sh` for runtime fixes.
|
||||
- Avoid hardcoding ports/secrets; prefer existing settings and helpers (see `.github/copilot-instructions.md`).
|
||||
75
.devcontainer/devcontainer.json
Executable file
75
.devcontainer/devcontainer.json
Executable file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"name": "NetAlertX DevContainer",
|
||||
"remoteUser": "netalertx",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": "..",
|
||||
"target": "devcontainer"
|
||||
},
|
||||
"workspaceFolder": "/workspaces/NetAlertX",
|
||||
|
||||
"runArgs": [
|
||||
"--privileged",
|
||||
"--cap-add=NET_ADMIN",
|
||||
"--cap-add=NET_RAW",
|
||||
// Ensure containers can resolve host.docker.internal to the host (required on Linux)
|
||||
"--add-host=host.docker.internal:host-gateway"
|
||||
],
|
||||
|
||||
"postStartCommand": "${containerWorkspaceFolder}/.devcontainer/scripts/setup.sh",
|
||||
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-python.python",
|
||||
"ms-azuretools.vscode-docker",
|
||||
"felixfbecker.php-debug",
|
||||
"bmewburn.vscode-intelephense-client",
|
||||
"xdebug.php-debug",
|
||||
"ms-python.vscode-pylance",
|
||||
"pamaron.pytest-runner",
|
||||
"coderabbit.coderabbit-vscode",
|
||||
"ms-python.black-formatter"
|
||||
]
|
||||
,
|
||||
"settings": {
|
||||
"terminal.integrated.cwd": "${containerWorkspaceFolder}",
|
||||
// Python testing configuration
|
||||
"python.testing.pytestEnabled": true,
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestArgs": [
|
||||
"test"
|
||||
],
|
||||
// Make sure we discover tests and import server correctly
|
||||
"python.analysis.extraPaths": [
|
||||
"/workspaces/NetAlertX",
|
||||
"/workspaces/NetAlertX/server",
|
||||
"/app",
|
||||
"/app/server"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"forwardPorts": [5678, 9000, 9003, 20211, 20212],
|
||||
|
||||
"portsAttributes": {
|
||||
"20211": {
|
||||
"label": "Frontend:Nginx+PHP"
|
||||
},
|
||||
"20212": {
|
||||
"label": "Backend:GraphQL"
|
||||
},
|
||||
"9003": {
|
||||
"label": "PHP Debug:Xdebug"
|
||||
},
|
||||
"9000": {
|
||||
"label": "PHP-FPM:FastCGI"
|
||||
},
|
||||
"5678": {
|
||||
"label": "Python Debug:debugpy"
|
||||
}
|
||||
},
|
||||
|
||||
// Optional: ensures compose services are stopped when you close the window
|
||||
"shutdownAction": "stopContainer"
|
||||
}
|
||||
8
.devcontainer/resources/99-xdebug.ini
Normal file
8
.devcontainer/resources/99-xdebug.ini
Normal file
@@ -0,0 +1,8 @@
|
||||
zend_extension="xdebug.so"
|
||||
[xdebug]
|
||||
xdebug.mode=develop,debug
|
||||
xdebug.log_level=0
|
||||
xdebug.client_host=host.docker.internal
|
||||
xdebug.client_port=9003
|
||||
xdebug.start_with_request=yes
|
||||
xdebug.discover_client_host=1
|
||||
51
.devcontainer/resources/devcontainer-Dockerfile
Normal file
51
.devcontainer/resources/devcontainer-Dockerfile
Normal file
@@ -0,0 +1,51 @@
|
||||
# Devcontainer build stage (do not build directly)
|
||||
# This file is combined with the root /Dockerfile by
|
||||
# .devcontainer/scripts/generate-dockerfile.sh
|
||||
# The generator appends this stage to produce .devcontainer/Dockerfile.
|
||||
# Prefer to place dev-only setup here; use setup.sh only for runtime fixes.
|
||||
|
||||
FROM runner AS devcontainer
|
||||
ENV INSTALL_DIR=/app
|
||||
ENV PYTHONPATH=/workspaces/NetAlertX/test:/workspaces/NetAlertX/server:/app:/app/server:/opt/venv/lib/python3.12/site-packages
|
||||
|
||||
# Install common tools, create user, and set up sudo
|
||||
RUN apk add --no-cache git nano vim jq php83-pecl-xdebug py3-pip nodejs sudo gpgconf pytest pytest-cov && \
|
||||
adduser -D -s /bin/sh netalertx && \
|
||||
addgroup netalertx nginx && \
|
||||
addgroup netalertx www-data && \
|
||||
echo "netalertx ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/90-netalertx && \
|
||||
chmod 440 /etc/sudoers.d/90-netalertx
|
||||
# Install debugpy in the virtualenv if present, otherwise into system python3
|
||||
RUN /bin/sh -c '(/opt/venv/bin/python3 -m pip install --no-cache-dir debugpy) || (python3 -m pip install --no-cache-dir debugpy) || true'
|
||||
# setup nginx
|
||||
COPY .devcontainer/resources/netalertx-devcontainer.conf /etc/nginx/http.d/netalert-frontend.conf
|
||||
RUN set -e; \
|
||||
chown netalertx:nginx /etc/nginx/http.d/netalert-frontend.conf; \
|
||||
install -d -o netalertx -g www-data -m 775 /app; \
|
||||
install -d -o netalertx -g www-data -m 755 /run/nginx; \
|
||||
install -d -o netalertx -g www-data -m 755 /var/lib/nginx/logs; \
|
||||
rm -f /var/lib/nginx/logs/* || true; \
|
||||
for f in error access; do : > /var/lib/nginx/logs/$f.log; done; \
|
||||
install -d -o netalertx -g www-data -m 777 /run/php; \
|
||||
install -d -o netalertx -g www-data -m 775 /var/log/php; \
|
||||
chown -R netalertx:www-data /etc/nginx/http.d; \
|
||||
chmod -R 775 /etc/nginx/http.d; \
|
||||
chown -R netalertx:www-data /var/lib/nginx; \
|
||||
chmod -R 755 /var/lib/nginx && \
|
||||
chown -R netalertx:www-data /var/log/nginx/ && \
|
||||
sed -i '/^user /d' /etc/nginx/nginx.conf; \
|
||||
sed -i 's|^error_log .*|error_log /dev/stderr warn;|' /etc/nginx/nginx.conf; \
|
||||
sed -i 's|^access_log .*|access_log /dev/stdout main;|' /etc/nginx/nginx.conf; \
|
||||
sed -i 's|error_log .*|error_log /dev/stderr warn;|g' /etc/nginx/http.d/*.conf 2>/dev/null || true; \
|
||||
sed -i 's|access_log .*|access_log /dev/stdout main;|g' /etc/nginx/http.d/*.conf 2>/dev/null || true; \
|
||||
mkdir -p /run/openrc; \
|
||||
chown netalertx:nginx /run/openrc/; \
|
||||
rm -Rf /run/openrc/*;
|
||||
|
||||
# setup pytest
|
||||
RUN sudo /opt/venv/bin/python -m pip install -U pytest pytest-cov
|
||||
|
||||
WORKDIR /workspaces/NetAlertX
|
||||
|
||||
|
||||
ENTRYPOINT ["/bin/sh","-c","sleep infinity"]
|
||||
26
.devcontainer/resources/netalertx-devcontainer.conf
Normal file
26
.devcontainer/resources/netalertx-devcontainer.conf
Normal file
@@ -0,0 +1,26 @@
|
||||
log_format netalertx '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
access_log /var/log/nginx/access.log netalertx flush=1s;
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
|
||||
server {
|
||||
listen 20211 default_server;
|
||||
root /app/front;
|
||||
index index.php;
|
||||
|
||||
add_header X-Forwarded-Prefix "/netalertx" always;
|
||||
proxy_set_header X-Forwarded-Prefix "/netalertx";
|
||||
|
||||
location ~* \.php$ {
|
||||
add_header Cache-Control "no-store";
|
||||
fastcgi_pass 127.0.0.1:9000;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
||||
fastcgi_param PHP_VALUE "xdebug.remote_enable=1";
|
||||
fastcgi_connect_timeout 75;
|
||||
fastcgi_send_timeout 600;
|
||||
fastcgi_read_timeout 600;
|
||||
}
|
||||
}
|
||||
38
.devcontainer/scripts/generate-dockerfile.sh
Executable file
38
.devcontainer/scripts/generate-dockerfile.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Generator for .devcontainer/Dockerfile
|
||||
# Combines the root /Dockerfile (with some COPY lines removed) and
|
||||
# the dev-only stage in .devcontainer/resources/devcontainer-Dockerfile.
|
||||
# Run this script after modifying the resource Dockerfile to refresh
|
||||
# the final .devcontainer/Dockerfile used by the devcontainer.
|
||||
|
||||
# Make a copy of the original Dockerfile to the .devcontainer folder
|
||||
# but remove the COPY . ${INSTALL_DIR}/ command from it. This avoids
|
||||
# overwriting /app (which uses symlinks to the workspace) and preserves
|
||||
# debugging capabilities inside the devcontainer.
|
||||
|
||||
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
|
||||
DEVCONTAINER_DIR="${SCRIPT_DIR%/scripts}"
|
||||
ROOT_DIR="${DEVCONTAINER_DIR%/.devcontainer}"
|
||||
|
||||
OUT_FILE="${DEVCONTAINER_DIR}/Dockerfile"
|
||||
|
||||
echo "# DO NOT MODIFY THIS FILE DIRECTLY. IT IS AUTO-GENERATED BY .devcontainer/scripts/generate-dockerfile.sh" > "$OUT_FILE"
|
||||
echo "" >> "$OUT_FILE"
|
||||
echo "# ---/Dockerfile---" >> "$OUT_FILE"
|
||||
|
||||
sed '/${INSTALL_DIR}/d' "${ROOT_DIR}/Dockerfile" >> "$OUT_FILE"
|
||||
|
||||
# sed the line https://github.com/foreign-sub/aiofreepybox.git \\ to remove trailing backslash
|
||||
sed -i '/aiofreepybox.git/ s/ \\$//' "$OUT_FILE"
|
||||
|
||||
# don't cat the file, just copy it in because it doesn't exist at build time
|
||||
sed -i 's|^ RUN cat ${INSTALL_DIR}/install/freebox_certificate.pem >> /opt/venv/lib/python3.12/site-packages/aiofreepybox/freebox_certificates.pem$| COPY install/freebox_certificate.pem /opt/venv/lib/python3.12/site-packages/aiofreepybox/freebox_certificates.pem |' "$OUT_FILE"
|
||||
|
||||
echo "" >> "$OUT_FILE"
|
||||
echo "# ---/resources/devcontainer-Dockerfile---" >> "$OUT_FILE"
|
||||
echo "" >> "$OUT_FILE"
|
||||
|
||||
cat "${DEVCONTAINER_DIR}/resources/devcontainer-Dockerfile" >> "$OUT_FILE"
|
||||
|
||||
echo "Generated $OUT_FILE using root dir $ROOT_DIR" >&2
|
||||
24
.devcontainer/scripts/restart-backend.sh
Executable file
24
.devcontainer/scripts/restart-backend.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
# Start (or restart) the NetAlertX Python backend under debugpy in background.
|
||||
# This script is invoked by the VS Code task "Restart GraphQL".
|
||||
# It exists to avoid complex inline command chains that were being mangled by the task runner.
|
||||
|
||||
set -e
|
||||
|
||||
LOG_DIR=/app/log
|
||||
APP_DIR=/app/server
|
||||
PY=python3
|
||||
PORT_DEBUG=5678
|
||||
|
||||
# Kill any prior debug/run instances
|
||||
sudo killall python3 2>/dev/null || true
|
||||
sleep 2
|
||||
|
||||
|
||||
cd "$APP_DIR"
|
||||
|
||||
# Launch using absolute module path for clarity; rely on cwd for local imports
|
||||
setsid nohup ${PY} -m debugpy --listen 0.0.0.0:${PORT_DEBUG} /app/server/__main__.py >/dev/null 2>&1 &
|
||||
PID=$!
|
||||
sleep 2
|
||||
|
||||
13
.devcontainer/scripts/run-tests.sh
Executable file
13
.devcontainer/scripts/run-tests.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
# shellcheck shell=sh
|
||||
# Simple helper to run pytest inside the devcontainer with correct paths
|
||||
set -eu
|
||||
|
||||
# Ensure we run from the workspace root
|
||||
cd /workspaces/NetAlertX
|
||||
|
||||
# Make sure PYTHONPATH includes server and workspace
|
||||
export PYTHONPATH="/workspaces/NetAlertX:/workspaces/NetAlertX/server:/app:/app/server:${PYTHONPATH:-}"
|
||||
|
||||
# Default to running the full test suite under /workspaces/NetAlertX/test
|
||||
pytest -q --maxfail=1 --disable-warnings test "$@"
|
||||
191
.devcontainer/scripts/setup.sh
Executable file
191
.devcontainer/scripts/setup.sh
Executable file
@@ -0,0 +1,191 @@
|
||||
#! /bin/bash
|
||||
# Runtime setup for devcontainer (executed after container starts).
|
||||
# Prefer building setup into resources/devcontainer-Dockerfile when possible.
|
||||
# Use this script for runtime-only adjustments (permissions, sockets, ownership,
|
||||
# and services managed without init) that are difficult at build time.
|
||||
id
|
||||
|
||||
# Define variables (paths, ports, environment)
|
||||
|
||||
export APP_DIR="/app"
|
||||
export APP_COMMAND="/workspaces/NetAlertX/.devcontainer/scripts/restart-backend.sh"
|
||||
export PHP_FPM_BIN="/usr/sbin/php-fpm83"
|
||||
export NGINX_BIN="/usr/sbin/nginx"
|
||||
export CROND_BIN="/usr/sbin/crond -f"
|
||||
|
||||
|
||||
export ALWAYS_FRESH_INSTALL=false
|
||||
export INSTALL_DIR=/app
|
||||
export APP_DATA_LOCATION=/app/config
|
||||
export APP_CONFIG_LOCATION=/app/config
|
||||
export LOGS_LOCATION=/app/logs
|
||||
export CONF_FILE="app.conf"
|
||||
export NGINX_CONF_FILE=netalertx.conf
|
||||
export DB_FILE="app.db"
|
||||
export FULL_FILEDB_PATH="${INSTALL_DIR}/db/${DB_FILE}"
|
||||
export NGINX_CONFIG_FILE="/etc/nginx/http.d/${NGINX_CONF_FILE}"
|
||||
export OUI_FILE="/usr/share/arp-scan/ieee-oui.txt" # Define the path to ieee-oui.txt and ieee-iab.txt
|
||||
export TZ=Europe/Paris
|
||||
export PORT=20211
|
||||
export SOURCE_DIR="/workspaces/NetAlertX"
|
||||
|
||||
|
||||
|
||||
main() {
|
||||
echo "=== NetAlertX Development Container Setup ==="
|
||||
echo "Setting up ${SOURCE_DIR}..."
|
||||
configure_source
|
||||
|
||||
echo "--- Starting Development Services ---"
|
||||
configure_php
|
||||
|
||||
|
||||
start_services
|
||||
}
|
||||
|
||||
# safe_link: create a symlink from source to target, removing existing target if necessary
|
||||
# bypassing the default behavior of symlinking the directory into the target directory if it is a directory
|
||||
safe_link() {
|
||||
# usage: safe_link <source> <target>
|
||||
local src="$1"
|
||||
local dst="$2"
|
||||
|
||||
# Ensure parent directory exists
|
||||
install -d -m 775 "$(dirname "$dst")" >/dev/null 2>&1 || true
|
||||
|
||||
# If target exists, remove it without dereferencing symlinks
|
||||
if [ -L "$dst" ] || [ -e "$dst" ]; then
|
||||
rm -rf "$dst"
|
||||
fi
|
||||
|
||||
# Create link; -n prevents deref, -f replaces if somehow still exists
|
||||
ln -sfn "$src" "$dst"
|
||||
}
|
||||
|
||||
# Setup source directory
|
||||
configure_source() {
|
||||
echo "[1/3] Configuring Source..."
|
||||
echo " -> Linking source to ${INSTALL_DIR}"
|
||||
echo "Dev">${INSTALL_DIR}/.VERSION
|
||||
safe_link ${SOURCE_DIR}/api ${INSTALL_DIR}/api
|
||||
safe_link ${SOURCE_DIR}/back ${INSTALL_DIR}/back
|
||||
if [ ! -f "${INSTALL_DIR}/config/app.conf" ]; then
|
||||
rm -Rf ${INSTALL_DIR}/config
|
||||
install -d -o netalertx -g www-data -m 750 ${INSTALL_DIR}/config
|
||||
cp -R ${SOURCE_DIR}/config/* ${INSTALL_DIR}/config/
|
||||
fi
|
||||
|
||||
safe_link "${SOURCE_DIR}/db" "${INSTALL_DIR}/db"
|
||||
safe_link "${SOURCE_DIR}/docs" "${INSTALL_DIR}/docs"
|
||||
safe_link "${SOURCE_DIR}/front" "${INSTALL_DIR}/front"
|
||||
safe_link "${SOURCE_DIR}/install" "${INSTALL_DIR}/install"
|
||||
safe_link "${SOURCE_DIR}/scripts" "${INSTALL_DIR}/scripts"
|
||||
safe_link "${SOURCE_DIR}/server" "${INSTALL_DIR}/server"
|
||||
safe_link "${SOURCE_DIR}/test" "${INSTALL_DIR}/test"
|
||||
safe_link "${SOURCE_DIR}/mkdocs.yml" "${INSTALL_DIR}/mkdocs.yml"
|
||||
|
||||
echo " -> Copying static files to ${INSTALL_DIR}"
|
||||
cp -R ${SOURCE_DIR}/CODE_OF_CONDUCT.md ${INSTALL_DIR}/
|
||||
cp -R ${SOURCE_DIR}/dockerfiles ${INSTALL_DIR}/dockerfiles
|
||||
sudo cp -na "${INSTALL_DIR}/back/${CONF_FILE}" "${INSTALL_DIR}/config/${CONF_FILE}"
|
||||
sudo cp -na "${INSTALL_DIR}/back/${DB_FILE}" "${FULL_FILEDB_PATH}"
|
||||
if [ -e "${INSTALL_DIR}/api/user_notifications.json" ]; then
|
||||
echo " -> Removing existing user_notifications.json"
|
||||
sudo rm "${INSTALL_DIR}"/api/user_notifications.json
|
||||
fi
|
||||
|
||||
echo " -> Setting ownership and permissions"
|
||||
sudo find ${INSTALL_DIR}/ -type d -exec chmod 775 {} \;
|
||||
sudo find ${INSTALL_DIR}/ -type f -exec chmod 664 {} \;
|
||||
sudo date +%s > "${INSTALL_DIR}/front/buildtimestamp.txt"
|
||||
sudo chmod 640 "${INSTALL_DIR}/config/${CONF_FILE}" || true
|
||||
|
||||
echo " -> Setting up log directory"
|
||||
sudo rm -Rf ${INSTALL_DIR}/log
|
||||
install -d -o netalertx -g www-data -m 777 ${INSTALL_DIR}/log
|
||||
install -d -o netalertx -g www-data -m 777 ${INSTALL_DIR}/log/plugins
|
||||
|
||||
echo " -> Empty log"|tee ${INSTALL_DIR}/log/app.log \
|
||||
${INSTALL_DIR}/log/app_front.log \
|
||||
${INSTALL_DIR}/log/app_front.log \
|
||||
${INSTALL_DIR}/log/execution_queue.log \
|
||||
${INSTALL_DIR}/log/db_is_locked.log \
|
||||
${INSTALL_DIR}/log/stdout.log \
|
||||
${INSTALL_DIR}/log/stderr.log \
|
||||
/var/log/nginx/error.log
|
||||
date +%s > /app/front/buildtimestamp.txt
|
||||
|
||||
killall python &>/dev/null
|
||||
sleep 1
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
# start_services: start crond, PHP-FPM, nginx and the application
|
||||
start_services() {
|
||||
echo "[3/3] Starting services..."
|
||||
|
||||
killall nohup &>/dev/null || true
|
||||
|
||||
killall php-fpm83 &>/dev/null || true
|
||||
killall crond &>/dev/null || true
|
||||
# Give the OS a moment to release the php-fpm socket
|
||||
sleep 0.3
|
||||
echo " -> Starting CronD"
|
||||
setsid nohup $CROND_BIN &>/dev/null &
|
||||
|
||||
echo " -> Starting PHP-FPM"
|
||||
setsid nohup $PHP_FPM_BIN &>/dev/null &
|
||||
|
||||
sudo killall nginx &>/dev/null || true
|
||||
# Wait for the previous nginx processes to exit and for the port to free up
|
||||
tries=0
|
||||
while ss -ltn | grep -q ":${PORT}[[:space:]]" && [ $tries -lt 10 ]; do
|
||||
echo " -> Waiting for port ${PORT} to free..."
|
||||
sleep 0.2
|
||||
tries=$((tries+1))
|
||||
done
|
||||
sleep 0.2
|
||||
echo " -> Starting Nginx"
|
||||
setsid nohup $NGINX_BIN &>/dev/null &
|
||||
echo " -> Starting Backend ${APP_DIR}/server..."
|
||||
$APP_COMMAND
|
||||
sleep 2
|
||||
}
|
||||
|
||||
# configure_php: configure PHP-FPM and enable dev debug options
|
||||
configure_php() {
|
||||
echo "[2/3] Configuring PHP-FPM..."
|
||||
sudo killall php-fpm83 &>/dev/null || true
|
||||
install -d -o nginx -g www-data /run/php/ &>/dev/null
|
||||
sudo sed -i "/^;pid/c\pid = /run/php/php8.3-fpm.pid" /etc/php83/php-fpm.conf
|
||||
sudo sed -i 's|^listen = .*|listen = 127.0.0.1:9000|' /etc/php83/php-fpm.d/www.conf
|
||||
sudo sed -i 's|fastcgi_pass .*|fastcgi_pass 127.0.0.1:9000;|' /etc/nginx/http.d/*.conf
|
||||
|
||||
# find any line in php-fmp that starts with either ;error_log or error_log = and replace it with error_log = /app/log/app.php_errors.log
|
||||
sudo sed -i '/^;*error_log\s*=/c\error_log = /app/log/app.php_errors.log' /etc/php83/php-fpm.conf
|
||||
# If the line was not found, append it to the end of the file
|
||||
if ! grep -q '^error_log\s*=' /etc/php83/php-fpm.conf; then
|
||||
echo 'error_log = /app/log/app.php_errors.log' | sudo tee -a /etc/php83/php-fpm.conf
|
||||
fi
|
||||
|
||||
sudo mkdir -p /etc/php83/conf.d
|
||||
sudo cp /workspaces/NetAlertX/.devcontainer/resources/99-xdebug.ini /etc/php83/conf.d/99-xdebug.ini
|
||||
|
||||
sudo rm -R /var/log/php83 &>/dev/null || true
|
||||
install -d -o netalertx -g www-data -m 755 var/log/php83;
|
||||
|
||||
sudo chmod 644 /etc/php83/conf.d/99-xdebug.ini || true
|
||||
|
||||
}
|
||||
|
||||
# (duplicate start_services removed)
|
||||
|
||||
|
||||
|
||||
echo "$(git rev-parse --short=8 HEAD)">/app/.VERSION
|
||||
# Run the main function
|
||||
main
|
||||
|
||||
|
||||
|
||||
40
.devcontainer/scripts/stream-logs.sh
Executable file
40
.devcontainer/scripts/stream-logs.sh
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
# Stream NetAlertX logs to stdout so the Dev Containers output channel shows them.
|
||||
# This script waits briefly for the files to appear and then tails them with -F.
|
||||
|
||||
LOG_FILES="/app/log/app.log /app/log/db_is_locked.log /app/log/execution_queue.log /app/log/app_front.log /app/log/app.php_errors.log /app/log/IP_changes.log /app/stderr.log /app/stdout.log"
|
||||
|
||||
wait_for_files() {
|
||||
# Wait up to ~10s for at least one of the files to exist
|
||||
attempts=0
|
||||
while [ $attempts -lt 20 ]; do
|
||||
for f in $LOG_FILES; do
|
||||
if [ -f "$f" ]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
attempts=$((attempts+1))
|
||||
sleep 0.5
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
if wait_for_files; then
|
||||
echo "Starting log stream for:"
|
||||
for f in $LOG_FILES; do
|
||||
[ -f "$f" ] && echo " $f"
|
||||
done
|
||||
|
||||
# Use tail -F where available. If tail -F isn't supported, tail -f is used as fallback.
|
||||
# Some minimal images may have busybox tail without -F; this handles both.
|
||||
if tail --version >/dev/null 2>&1; then
|
||||
# GNU tail supports -F
|
||||
tail -n +1 -F $LOG_FILES
|
||||
else
|
||||
# Fallback to -f for busybox; will exit if files rotate or do not exist initially
|
||||
tail -n +1 -f $LOG_FILES
|
||||
fi
|
||||
else
|
||||
echo "No log files appeared after wait; exiting stream script."
|
||||
exit 0
|
||||
fi
|
||||
11
.devcontainer/xdebug-trigger.ini
Normal file
11
.devcontainer/xdebug-trigger.ini
Normal file
@@ -0,0 +1,11 @@
|
||||
zend_extension=xdebug.so
|
||||
xdebug.mode=debug
|
||||
xdebug.start_with_request=trigger
|
||||
xdebug.trigger_value=VSCODE
|
||||
xdebug.client_host=host.docker.internal
|
||||
xdebug.client_port=9003
|
||||
xdebug.log=/var/log/xdebug.log
|
||||
xdebug.log_level=7
|
||||
xdebug.idekey=VSCODE
|
||||
xdebug.discover_client_host=true
|
||||
xdebug.max_nesting_level=512
|
||||
Reference in New Issue
Block a user