Compare commits

...

74 Commits

Author SHA1 Message Date
jokob-sk
a98bac331d MERGE: resolve conflicts
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-10 10:11:34 +11:00
jokob-sk
9f6086e5cf BE: better error message
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-10 09:27:13 +11:00
Adam Outler
c5a1f19567 Attempt to kick off coderabbit
Removed unnecessary blank lines in the nginx configuration template.
2025-11-09 16:56:47 -05:00
jokob-sk
6d70a8a71d BE: /logs endpoint, comments resolution, github template
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-10 07:58:21 +11:00
Adam Outler
4161261c43 Remove unused files 2025-11-09 17:38:31 +00:00
Adam Outler
179821a527 fix workspace 2025-11-09 17:34:31 +00:00
Adam Outler
2028b1a6e3 Merge remote-tracking branch 'origin/main' into data_and_tmp_standardization 2025-11-09 17:14:11 +00:00
Adam Outler
5b871865db /data and /tmp standarization 2025-11-09 17:03:25 +00:00
Ettore Atalan
76bcec335d Translated using Weblate (German)
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Currently translated at 81.4% (621 of 762 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2025-11-09 15:51:16 +00:00
jokob-sk
8483a741b4 BE: LangStrings /graphql + /logs endpoint, utils chores
Some checks failed
docker / docker_dev (push) Has been cancelled
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-09 18:50:16 +11:00
jokob-sk
68c8e16828 PLG: cleanup
Some checks failed
docker / docker_dev (push) Has been cancelled
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-08 22:08:20 +11:00
jokob-sk
76150b2ca7 BE: github actions + dev version
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-08 22:02:55 +11:00
jokob-sk
5cf8a25bae BE: timestamp work name changes #1251
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-08 22:01:04 +11:00
Jokob @NetAlertX
593aa16f17 Merge pull request #1278 from alexhk/patch-1
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Fix typo in Baseline Docker Compose - DOCKER_COMPOSE.md
2025-11-08 21:03:17 +11:00
alexhk
af9793c2ed Update DOCKER_COMPOSE.md
Assuming this was a typo
2025-11-08 09:12:21 +01:00
jokob-sk
552d2a8286 DOCS: plugin docs
Some checks failed
docker / docker_dev (push) Has been cancelled
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-08 14:16:17 +11:00
jokob-sk
7822b11d51 BE: plugins changed data detection
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-08 14:15:45 +11:00
jokob-sk
cbe5a4a732 BE: version added to app_state
Some checks failed
docker / docker_dev (push) Has been cancelled
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-06 22:08:19 +11:00
jokob-sk
58de31d0ea BE: prod workflow + docs
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-06 21:35:05 +11:00
jokob-sk
5c06dc68c6 DOCS: link fix
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-06 21:20:28 +11:00
jokob-sk
44d65cca96 BE: version file
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-06 21:12:13 +11:00
Pavel Borecki
71e0d13bef Translated using Weblate (Czech)
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Currently translated at 8.2% (63 of 762 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/cs/
2025-11-06 10:51:14 +01:00
jokob-sk
30269a6a73 DOCS: link fix
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-06 20:47:54 +11:00
jokob-sk
6374219e05 BE: github actions + dev version
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-06 20:47:28 +11:00
jokob-sk
6e745fc6d1 DOCS: fix
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-06 08:14:13 +11:00
jokob-sk
85aa04c490 TEST: fix
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-06 08:14:00 +11:00
jokob-sk
1fd8d97d56 BE: chore datetime_utils
Some checks failed
docker / docker_dev (push) Has been cancelled
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-05 16:42:42 +11:00
jokob-sk
286d5555d2 BE: chore datetime_utils
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-05 16:14:03 +11:00
jokob-sk
57096a9258 FE: handling non-existent logs
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-05 16:13:28 +11:00
jokob-sk
c08eb1dbba BE: chore datetime_utils
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-05 16:08:04 +11:00
jokob-sk
746f1a8922 DOCS: decription fix and --exclude-broadcast documentation
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-05 15:26:57 +11:00
jokob-sk
0845b7f445 BE: name resolution did not apply regex cleanup
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-05 15:25:53 +11:00
Blueberry
a6fffe06b7 Translated using Weblate (Russian)
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Currently translated at 100.0% (762 of 762 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-11-04 21:51:12 +00:00
jokob-sk
ea8cea16c5 TEST: cleanup
Some checks failed
docker / docker_dev (push) Has been cancelled
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-04 20:01:27 +11:00
jokob-sk
5452b7287b BE/PLG: TZ timestamp work #1251
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-04 19:52:19 +11:00
jokob-sk
80d7ef7f24 BE/PLG: TZ timestamp work #1251
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-04 19:46:50 +11:00
jokob-sk
dc4da5b4c9 BE/PLG: TZ timestamp work #1251
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-04 19:44:30 +11:00
jokob-sk
59477e7b38 BE/PLG: TZ timestamp work #1251
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-04 19:24:13 +11:00
Jokob @NetAlertX
6dd7251c84 BE/PLG: TZ timestamp work #1251
Some checks failed
docker / docker_dev (push) Has been cancelled
2025-11-04 07:06:19 +00:00
jokob-sk
c52e44f90c BE/PLG: TZ timestamp work #1251
Some checks failed
docker / docker_dev (push) Has been cancelled
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-04 08:10:50 +11:00
Jokob @NetAlertX
db18ca76b4 Merge pull request #1272 from jokob-sk/main
Some checks failed
docker / docker_dev (push) Has been cancelled
sync
2025-11-03 10:22:35 +11:00
jokob-sk
288427c939 BE/PLG: TZ timestamp work #1251
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-03 10:19:39 +11:00
jokob-sk
90a07c61eb Merge branch 'main' of https://github.com/jokob-sk/NetAlertX
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-11-03 08:14:26 +11:00
jokob-sk
13341e35c9 PLG: ARPSCAN prevent duplicates across subnets
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-03 08:14:15 +11:00
jokob-sk
4c92a941a8 BE: TZ timestamp work #1251
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-03 08:12:00 +11:00
Jokob @NetAlertX
4cec88aaad Merge pull request #1269 from jokob-sk/main
Some checks failed
docker / docker_dev (push) Has been cancelled
sync
2025-11-02 22:21:19 +11:00
Jokob @NetAlertX
031d810566 Merge branch next_release into main
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-11-02 22:20:13 +11:00
jokob-sk
b806f84946 BE: invlaid return #1251
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-02 22:16:28 +11:00
jokob-sk
7c90c2e93c BE: spinner + timestamp work #1251
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-02 22:12:30 +11:00
Jokob @NetAlertX
cb69990734 Merge pull request #1268 from adamoutler/synology-fix
Fix permissions on Synology
2025-11-02 21:48:27 +11:00
Adam Outler
7037cf1bc6 fxi permissions on synology inherited 2025-11-02 10:26:21 +00:00
Jokob @NetAlertX
71646e1645 Merge pull request #1263 from adamoutler/FEAT--Make-Errors-More-Helpful
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Feat: make errors more helpful
2025-11-02 13:49:39 +11:00
Adam Outler
dde542c484 make /services/scripts executable by default 2025-11-02 00:12:50 +00:00
Adam Outler
23a0fac973 Address Coderabbit issue 2025-11-01 23:54:54 +00:00
Adam Outler
db5381db14 Update test/docker_tests/test_docker_compose_scenarios.py
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-11-01 15:12:54 -04:00
Adam Outler
f1fbc47508 coderabbit required fix 2025-11-01 19:04:31 +00:00
Adam Outler
2a9d352322 Update test/docker_tests/configurations/test_all_docker_composes.sh
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-11-01 14:57:57 -04:00
Adam Outler
51aa3d4a2e coderabbit 2025-11-01 18:53:07 +00:00
Adam Outler
70373b1fbd Address coderabbit-discoverd issues 2025-11-01 18:18:32 +00:00
jokob-sk
e7ed9e0896 BE: logging fix and comments why eve_PendingAlertEmail not cleared
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-11-01 17:58:22 +11:00
Adam Outler
79887f0bd7 Merge branch 'jokob-sk:main' into FEAT--Make-Errors-More-Helpful 2025-10-31 23:59:45 -04:00
Adam Outler
a6bc96d2dd Corrections on testing and behaviors 2025-11-01 03:57:52 +00:00
Adam Outler
8edef9e852 All errors have documentation links 2025-10-31 22:24:31 +00:00
Adam Outler
1e63cec37c Revise tests. Use docker-compose.yml where possible 2025-10-31 22:24:08 +00:00
jokob-sk
ff96d38339 DOCS:old docker installation guide
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-10-31 22:10:02 +11:00
Hosted Weblate
b89917ca3e Merge branch 'origin/main' into Weblate. 2025-10-31 11:55:36 +01:00
jokob-sk
daea3a2cd7 DOCS: WARNING use dockerhub docs
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
2025-10-31 21:55:15 +11:00
jokob-sk
b86f636b12 Revert "DOCS: clearer local_path instructions"
This reverts commit dfc64fd85f.
2025-10-31 21:46:59 +11:00
jokob-sk
0b08995223 Revert "DOCS: install refactor work"
This reverts commit fe69972caa.
2025-10-31 21:46:25 +11:00
Hosted Weblate
f42186b616 Merge branch 'origin/main' into Weblate. 2025-10-31 11:10:55 +01:00
jeet moh
bc9fb6bcde Translated using Weblate (Persian (fa_FA))
Currently translated at 0.1% (1 of 762 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fa_FA/
2025-10-31 11:06:33 +01:00
Adam Outler
d29700acf8 New mount test structure. 2025-10-31 00:07:34 +00:00
Adam Outler
b89a44d0ec Improve startup checks 2025-10-30 21:05:24 +00:00
Adam Outler
8cb1836777 Move all check- scripts to /entrypoint.d/ for better organization 2025-10-30 20:18:08 +00:00
308 changed files with 12603 additions and 5886 deletions

View File

@@ -46,14 +46,16 @@ ARG INSTALL_DIR=/app
# NetAlertX app directories
ENV NETALERTX_APP=${INSTALL_DIR}
ENV NETALERTX_CONFIG=${NETALERTX_APP}/config
ENV NETALERTX_DATA=/data
ENV NETALERTX_CONFIG=${NETALERTX_DATA}/config
ENV NETALERTX_FRONT=${NETALERTX_APP}/front
ENV NETALERTX_PLUGINS=${NETALERTX_FRONT}/plugins
ENV NETALERTX_SERVER=${NETALERTX_APP}/server
ENV NETALERTX_API=${NETALERTX_APP}/api
ENV NETALERTX_DB=${NETALERTX_APP}/db
ENV NETALERTX_API=/tmp/api
ENV NETALERTX_DB=${NETALERTX_DATA}/db
ENV NETALERTX_DB_FILE=${NETALERTX_DB}/app.db
ENV NETALERTX_BACK=${NETALERTX_APP}/back
ENV NETALERTX_LOG=${NETALERTX_APP}/log
ENV NETALERTX_LOG=/tmp/log
ENV NETALERTX_PLUGINS_LOG=${NETALERTX_LOG}/plugins
ENV NETALERTX_CONFIG_FILE=${NETALERTX_CONFIG}/app.conf
@@ -70,31 +72,35 @@ ENV LOG_EXECUTION_QUEUE=${NETALERTX_LOG}/execution_queue.log
ENV LOG_REPORT_OUTPUT_JSON=${NETALERTX_LOG}/report_output.json
ENV LOG_STDOUT=${NETALERTX_LOG}/stdout.log
ENV LOG_CROND=${NETALERTX_LOG}/crond.log
ENV LOG_NGINX_ERROR=${NETALERTX_LOG}/nginx-error.log
# System Services configuration files
ENV ENTRYPOINT_CHECKS=/entrypoint.d
ENV SYSTEM_SERVICES=/services
ENV SYSTEM_SERVICES_SCRIPTS=${SYSTEM_SERVICES}/scripts
ENV SYSTEM_SERVICES_CONFIG=${SYSTEM_SERVICES}/config
ENV SYSTEM_NGINX_CONFIG=${SYSTEM_SERVICES_CONFIG}/nginx
ENV SYSTEM_NGINX_CONFIG_FILE=${SYSTEM_NGINX_CONFIG}/nginx.conf
ENV SYSTEM_SERVICES_ACTIVE_CONFIG=/tmp/nginx/active-config
ENV SYSTEM_SERVICES_PHP_FOLDER=${SYSTEM_SERVICES_CONFIG}/php
ENV SYSTEM_SERVICES_PHP_FPM_D=${SYSTEM_SERVICES_PHP_FOLDER}/php-fpm.d
ENV SYSTEM_SERVICES_CROND=${SYSTEM_SERVICES_CONFIG}/crond
ENV SYSTEM_SERVICES_RUN=${SYSTEM_SERVICES}/run
ENV SYSTEM_SERVICES_RUN=/tmp/run
ENV SYSTEM_SERVICES_RUN_TMP=${SYSTEM_SERVICES_RUN}/tmp
ENV SYSTEM_SERVICES_RUN_LOG=${SYSTEM_SERVICES_RUN}/logs
ENV PHP_FPM_CONFIG_FILE=${SYSTEM_SERVICES_PHP_FOLDER}/php-fpm.conf
ENV READ_ONLY_FOLDERS="${NETALERTX_BACK} ${NETALERTX_FRONT} ${NETALERTX_SERVER} ${SYSTEM_SERVICES} \
${SYSTEM_SERVICES_CONFIG}"
ENV READ_WRITE_FOLDERS="${NETALERTX_CONFIG} ${NETALERTX_DB} ${NETALERTX_API} ${NETALERTX_LOG} \
${NETALERTX_PLUGINS_LOG} ${SYSTEM_SERVICES_RUN} ${SYSTEM_SERVICES_RUN_TMP} \
${SYSTEM_SERVICES_RUN_LOG}"
${SYSTEM_SERVICES_CONFIG} ${ENTRYPOINT_CHECKS}"
ENV READ_WRITE_FOLDERS="${NETALERTX_DATA} ${NETALERTX_CONFIG} ${NETALERTX_DB} ${NETALERTX_API} \
${NETALERTX_LOG} ${NETALERTX_PLUGINS_LOG} ${SYSTEM_SERVICES_RUN} \
${SYSTEM_SERVICES_RUN_TMP} ${SYSTEM_SERVICES_RUN_LOG} \
${SYSTEM_SERVICES_ACTIVE_CONFIG}"
#Python environment
ENV PYTHONUNBUFFERED=1
ENV VIRTUAL_ENV=/opt/venv
ENV VIRTUAL_ENV_BIN=/opt/venv/bin
ENV PYTHONPATH=${NETALERTX_APP}:${NETALERTX_SERVER}:${VIRTUAL_ENV}/lib/python3.12/site-packages
ENV PYTHONPATH=${NETALERTX_APP}:${NETALERTX_SERVER}:${NETALERTX_PLUGINS}:${VIRTUAL_ENV}/lib/python3.12/site-packages
ENV PATH="${SYSTEM_SERVICES}:${VIRTUAL_ENV_BIN}:$PATH"
# App Environment
@@ -102,7 +108,7 @@ ENV LISTEN_ADDR=0.0.0.0
ENV PORT=20211
ENV NETALERTX_DEBUG=0
ENV VENDORSPATH=/app/back/ieee-oui.txt
ENV VENDORSPATH_NEWEST=/services/run/tmp/ieee-oui.txt
ENV VENDORSPATH_NEWEST=${SYSTEM_SERVICES_RUN_TMP}/ieee-oui.txt
ENV ENVIRONMENT=alpine
ENV READ_ONLY_USER=readonly READ_ONLY_GROUP=readonly
ENV NETALERTX_USER=netalertx NETALERTX_GROUP=netalertx
@@ -126,8 +132,9 @@ COPY --chown=${NETALERTX_USER}:${NETALERTX_GROUP} install/production-filesystem/
COPY --chown=${NETALERTX_USER}:${NETALERTX_GROUP} --chmod=755 back ${NETALERTX_BACK}
COPY --chown=${NETALERTX_USER}:${NETALERTX_GROUP} --chmod=755 front ${NETALERTX_FRONT}
COPY --chown=${NETALERTX_USER}:${NETALERTX_GROUP} --chmod=755 server ${NETALERTX_SERVER}
RUN install -d -o ${NETALERTX_USER} -g ${NETALERTX_GROUP} -m 755 ${NETALERTX_API} \
${NETALERTX_LOG} ${SYSTEM_SERVICES_RUN_TMP} ${SYSTEM_SERVICES_RUN_LOG} && \
# Create required folders with correct ownership and permissions
RUN install -d -o ${NETALERTX_USER} -g ${NETALERTX_GROUP} -m 700 ${READ_WRITE_FOLDERS} && \
sh -c "find ${NETALERTX_APP} -type f \( -name '*.sh' -o -name 'speedtest-cli' \) \
-exec chmod 750 {} \;"
@@ -184,7 +191,7 @@ RUN chown -R ${READ_ONLY_USER}:${READ_ONLY_GROUP} ${READ_ONLY_FOLDERS} && \
chmod -R 600 ${READ_WRITE_FOLDERS} && \
find ${READ_WRITE_FOLDERS} -type d -exec chmod 700 {} + && \
chown ${READ_ONLY_USER}:${READ_ONLY_GROUP} /entrypoint.sh /opt /opt/venv && \
chmod 005 /entrypoint.sh ${SYSTEM_SERVICES}/*.sh /app /opt /opt/venv && \
chmod 005 /entrypoint.sh ${SYSTEM_SERVICES}/*.sh ${SYSTEM_SERVICES_SCRIPTS}/* ${ENTRYPOINT_CHECKS}/* /app /opt /opt/venv && \
for dir in ${READ_WRITE_FOLDERS}; do \
install -d -o ${NETALERTX_USER} -g ${NETALERTX_GROUP} -m 700 "$dir"; \
done && \
@@ -209,11 +216,14 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
# .devcontainer/scripts/generate-configs.sh
# The generator appends this stage to produce .devcontainer/Dockerfile.
# Prefer to place dev-only setup here; use setup.sh only for runtime fixes.
# Permissions in devcontainer should be of a brutalist nature. They will be
# Open and wide to avoid permission issues during development allowing max
# flexibility.
FROM runner AS netalertx-devcontainer
ENV INSTALL_DIR=/app
ENV PYTHONPATH=/workspaces/NetAlertX/test:/workspaces/NetAlertX/server:/app:/app/server:/opt/venv/lib/python3.12/site-packages:/usr/lib/python3.12/site-packages
ENV PYTHONPATH=${PYTHONPATH}:/workspaces/NetAlertX/test:/workspaces/NetAlertX/server:/usr/lib/python3.12/site-packages
ENV PATH=/services:${PATH}
ENV PHP_INI_SCAN_DIR=/services/config/php/conf.d:/etc/php83/conf.d
ENV LISTEN_ADDR=0.0.0.0
@@ -224,16 +234,28 @@ COPY .devcontainer/resources/devcontainer-overlay/ /
USER root
# 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 fish shfmt github-cli py3-yaml py3-docker-py docker-cli docker-cli-buildx \
pytest-cov zsh alpine-zsh-config shfmt github-cli py3-yaml py3-docker-py docker-cli docker-cli-buildx \
docker-cli-compose
RUN install -d -o netalertx -g netalertx -m 755 /services/php/modules && \
cp -a /usr/lib/php83/modules/. /services/php/modules/ && \
echo "${NETALERTX_USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
RUN mkdir /workspaces && \
install -d -o netalertx -g netalertx -m 777 /services/run/logs && \
install -d -o netalertx -g netalertx -m 777 /app/run/tmp/client_body && \
sed -i -e 's|:/app:|:/workspaces:|' /etc/passwd && \
ENV SHELL=/bin/zsh
RUN mkdir -p /workspaces && \
install -d -m 777 /data /data/config /data/db && \
install -d -m 777 /tmp/log /tmp/log/plugins /tmp/api /tmp/run /tmp/nginx && \
install -d -m 777 /tmp/nginx/active-config /tmp/nginx/client_body /tmp/nginx/config && \
install -d -m 777 /tmp/nginx/fastcgi /tmp/nginx/proxy /tmp/nginx/scgi /tmp/nginx/uwsgi && \
install -d -m 777 /tmp/run/tmp /tmp/run/logs && \
chmod 777 /workspaces && \
chown -R netalertx:netalertx /data && \
chmod 666 /data/config/app.conf /data/db/app.db && \
chmod 1777 /tmp && \
install -d -o root -g root -m 1777 /tmp/.X11-unix && \
mkdir -p /home/netalertx && \
chown netalertx:netalertx /home/netalertx && \
sed -i -e 's#/app:#/workspaces:#' /etc/passwd && \
find /opt/venv -type d -exec chmod o+rwx {} \;
USER netalertx

View File

@@ -0,0 +1,37 @@
{
"folders": [
{
"name": "NetAlertX Source",
"path": "/workspaces/NetAlertX"
},
{
"name": "💾 NetAlertX Data",
"path": "/data"
},
{
"name": "🔍 Active NetAlertX log",
"path": "/tmp/log"
},
{
"name": "🌐 Active NetAlertX nginx",
"path": "/tmp/nginx"
},
{
"name": "📊 Active NetAlertX api",
"path": "/tmp/api"
},
{
"name": "⚙️ Active NetAlertX run",
"path": "/tmp/run"
}
],
"settings": {
"terminal.integrated.suggest.enabled": true,
"terminal.integrated.defaultProfile.linux": "zsh",
"terminal.integrated.profiles.linux": {
"zsh": {
"path": "/usr/bin/fish"
}
}
}
}

View File

@@ -19,6 +19,17 @@ Common workflows (F1->Tasks: Run Task)
- 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)".
Production Container Evaulation
1. F1 → Tasks: Shutdown services ([Dev Container] Stop Frontend & Backend Services)
2. F1 → Tasks: Docker system and build prune ([Any] Docker system and build Prune)
3. F1 → Remote: Close Unused Forwarded Ports (VS Code command)
4. F1 → Tasks: Build & Launch Production (Build & Launch Prodcution Docker
5. visit http://localhost:20211
Unit tests
1. F1 → Tasks: Rebuild test container ([Any] Build Unit Test Docker image)
2. F1 → Test: Run all tests
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.

View File

@@ -0,0 +1,26 @@
# NetAlertX Multi-Folder Workspace
This repository uses a multi-folder workspace configuration to provide easy access to runtime directories.
## Opening the Multi-Folder Workspace
After the devcontainer builds, open the workspace file to access all folders:
1. **File****Open Workspace from File**
2. Select `NetAlertX.code-workspace`
Or use Command Palette (Ctrl+Shift+P / Cmd+Shift+P):
- Type: `Workspaces: Open Workspace from File`
- Select `NetAlertX.code-workspace`
## Workspace Folders
The workspace includes:
- **NetAlertX** - Main source code
- **/tmp** - Runtime temporary files
- **/tmp/api** - API response cache (JSON files)
- **/tmp/log** - Application and plugin logs
## Testing Configuration
Pytest is configured to only discover tests in the main `test/` directory, not in `/tmp` folders.

View File

@@ -2,6 +2,8 @@
"name": "NetAlertX DevContainer",
"remoteUser": "netalertx",
"workspaceFolder": "/workspaces/NetAlertX",
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/NetAlertX,type=bind,consistency=cached",
"onCreateCommand": "mkdir -p /tmp/api /tmp/log",
"build": {
"dockerfile": "./Dockerfile", // Dockerfile generated by script
"context": "../", // Context is the root of the repository
@@ -44,7 +46,8 @@
},
"postCreateCommand": {
"Install Pip Requirements": "/opt/venv/bin/pip3 install pytest docker debugpy"
"Install Pip Requirements": "/opt/venv/bin/pip3 install pytest docker debugpy",
"Workspace Instructions": "printf '\n\n<> DevContainer Ready!\n\n📁 To access /tmp folders in the workspace:\n File → Open Workspace from File → NetAlertX.code-workspace\n\n📖 See .devcontainer/WORKSPACE.md for details\n\n'"
},
"postStartCommand": {
"Start Environment":"${containerWorkspaceFolder}/.devcontainer/scripts/setup.sh",
@@ -70,15 +73,25 @@
"esbenp.prettier-vscode",
"eamodio.gitlens",
"alexcvzz.vscode-sqlite",
"yzhang.markdown-all-in-one",
"mkhl.shfmt"
"mkhl.shfmt",
"charliermarsh.ruff",
"ms-python.flake8"
],
"settings": {
"terminal.integrated.cwd": "${containerWorkspaceFolder}",
"terminal.integrated.profiles.linux": {
"zsh": {
"path": "/bin/zsh",
"args": ["-l"]
}
},
"terminal.integrated.defaultProfile.linux": "zsh",
// Python testing configuration
"python.testing.pytestEnabled": true,
"python.testing.unittestEnabled": false,
"python.testing.pytestArgs": ["test"],
"python.testing.cwd": "${containerWorkspaceFolder}",
// Make sure we discover tests and import server correctly
"python.analysis.extraPaths": [
"/workspaces/NetAlertX",

View File

@@ -3,11 +3,14 @@
# .devcontainer/scripts/generate-configs.sh
# The generator appends this stage to produce .devcontainer/Dockerfile.
# Prefer to place dev-only setup here; use setup.sh only for runtime fixes.
# Permissions in devcontainer should be of a brutalist nature. They will be
# Open and wide to avoid permission issues during development allowing max
# flexibility.
FROM runner AS netalertx-devcontainer
ENV INSTALL_DIR=/app
ENV PYTHONPATH=/workspaces/NetAlertX/test:/workspaces/NetAlertX/server:/app:/app/server:/opt/venv/lib/python3.12/site-packages:/usr/lib/python3.12/site-packages
ENV PYTHONPATH=${PYTHONPATH}:/workspaces/NetAlertX/test:/workspaces/NetAlertX/server:/usr/lib/python3.12/site-packages
ENV PATH=/services:${PATH}
ENV PHP_INI_SCAN_DIR=/services/config/php/conf.d:/etc/php83/conf.d
ENV LISTEN_ADDR=0.0.0.0
@@ -18,16 +21,28 @@ COPY .devcontainer/resources/devcontainer-overlay/ /
USER root
# 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 fish shfmt github-cli py3-yaml py3-docker-py docker-cli docker-cli-buildx \
pytest-cov zsh alpine-zsh-config shfmt github-cli py3-yaml py3-docker-py docker-cli docker-cli-buildx \
docker-cli-compose
RUN install -d -o netalertx -g netalertx -m 755 /services/php/modules && \
cp -a /usr/lib/php83/modules/. /services/php/modules/ && \
echo "${NETALERTX_USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
RUN mkdir /workspaces && \
install -d -o netalertx -g netalertx -m 777 /services/run/logs && \
install -d -o netalertx -g netalertx -m 777 /app/run/tmp/client_body && \
sed -i -e 's|:/app:|:/workspaces:|' /etc/passwd && \
ENV SHELL=/bin/zsh
RUN mkdir -p /workspaces && \
install -d -m 777 /data /data/config /data/db && \
install -d -m 777 /tmp/log /tmp/log/plugins /tmp/api /tmp/run /tmp/nginx && \
install -d -m 777 /tmp/nginx/active-config /tmp/nginx/client_body /tmp/nginx/config && \
install -d -m 777 /tmp/nginx/fastcgi /tmp/nginx/proxy /tmp/nginx/scgi /tmp/nginx/uwsgi && \
install -d -m 777 /tmp/run/tmp /tmp/run/logs && \
chmod 777 /workspaces && \
chown -R netalertx:netalertx /data && \
chmod 666 /data/config/app.conf /data/db/app.db && \
chmod 1777 /tmp && \
install -d -o root -g root -m 1777 /tmp/.X11-unix && \
mkdir -p /home/netalertx && \
chown netalertx:netalertx /home/netalertx && \
sed -i -e 's#/app:#/workspaces:#' /etc/passwd && \
find /opt/venv -type d -exec chmod o+rwx {} \;
USER netalertx

View File

@@ -8,7 +8,9 @@ worker_processes auto;
pcre_jit on;
# Configures default error logger.
error_log /app/log/nginx-error.log warn;
error_log /tmp/log/nginx-error.log warn;
pid /tmp/run/nginx.pid;
events {
# The maximum number of simultaneous connections that can be opened by
@@ -17,13 +19,12 @@ events {
}
http {
# Mapping of temp paths for various nginx modules.
client_body_temp_path /services/run/tmp/client_body;
proxy_temp_path /services/run/tmp/proxy;
fastcgi_temp_path /services/run/tmp/fastcgi;
uwsgi_temp_path /services/run/tmp/uwsgi;
scgi_temp_path /services/run/tmp/scgi;
client_body_temp_path /tmp/nginx/client_body;
proxy_temp_path /tmp/nginx/proxy;
fastcgi_temp_path /tmp/nginx/fastcgi;
uwsgi_temp_path /tmp/nginx/uwsgi;
scgi_temp_path /tmp/nginx/scgi;
# Includes mapping of file name extensions to MIME types of responses
# and defines the default type.
@@ -89,7 +90,7 @@ http {
'"$http_user_agent" "$http_x_forwarded_for"';
# Sets the path, format, and configuration for a buffered log write.
access_log /app/log/nginx-access.log main;
access_log /tmp/log/nginx-access.log main;
# Virtual host config
@@ -100,11 +101,10 @@ http {
index index.php;
add_header X-Forwarded-Prefix "/app" always;
location ~* \.php$ {
# Set Cache-Control header to prevent caching on the first load
add_header Cache-Control "no-store";
fastcgi_pass unix:/services/run/php.sock;
fastcgi_pass unix:/tmp/run/php.sock;
include /services/config/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;

View File

@@ -0,0 +1,47 @@
# NetAlertX devcontainer zsh configuration
# Keep this lightweight and deterministic so shells behave consistently.
export PATH="$HOME/.local/bin:$PATH"
export EDITOR=vim
export SHELL=/bin/zsh
# Start inside the workspace if it exists
if [ -d "/workspaces/NetAlertX" ]; then
cd /workspaces/NetAlertX
fi
# Enable basic completion and prompt helpers
autoload -Uz compinit promptinit colors
colors
compinit -u
promptinit
# Friendly prompt with virtualenv awareness
setopt PROMPT_SUBST
_venv_segment() {
if [ -n "$VIRTUAL_ENV" ]; then
printf '(%s) ' "${VIRTUAL_ENV:t}"
fi
}
PROMPT='%F{green}$(_venv_segment)%f%F{cyan}%n@%m%f %F{yellow}%~%f %# '
RPROMPT='%F{magenta}$(git rev-parse --abbrev-ref HEAD 2>/dev/null)%f'
# Sensible defaults
setopt autocd
setopt correct
setopt extendedglob
HISTFILE="$HOME/.zsh_history"
HISTSIZE=5000
SAVEHIST=5000
alias ll='ls -alF'
alias la='ls -A'
alias gs='git status -sb'
alias gp='git pull --ff-only'
# Ensure pyenv/virtualenv activate hooks adjust the prompt cleanly
if [ -f "$HOME/.zshrc.local" ]; then
source "$HOME/.zshrc.local"
fi

View File

@@ -1,7 +1,11 @@
#!/bin/bash
set -euo pipefail
read -r -p "Are you sure you want to destroy your host docker containers and images? Type YES to continue: " reply
if [[ -n "${CONFIRM_PRUNE:-}" && "${CONFIRM_PRUNE}" == "YES" ]]; then
reply="YES"
else
read -r -p "Are you sure you want to destroy your host docker containers and images? Type YES to continue: " reply
fi
if [[ "${reply}" == "YES" ]]; then
docker system prune -af

View File

@@ -1,184 +1,110 @@
#!/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 CROND_BIN="/usr/sbin/crond -f"
# NetAlertX Devcontainer Setup Script
#
# This script forcefully resets all runtime state for a single-user devcontainer.
# It is intentionally idempotent: every run wipes and recreates all relevant folders,
# symlinks, and files, so the environment is always fresh and predictable.
#
# - No conditional logic: everything is (re)created, overwritten, or reset unconditionally.
# - No security hardening: this is for disposable, local dev use only.
# - No checks for existing files, mounts, or processes—just do the work.
#
# If you add new runtime files or folders, add them to the creation/reset section below.
#
# Do not add if-then logic or error handling for missing/existing files. Simplicity is the goal.
export ALWAYS_FRESH_INSTALL=false
export INSTALL_DIR=/app
export LOGS_LOCATION=/app/logs
export CONF_FILE="app.conf"
export DB_FILE="app.db"
export FULL_FILEDB_PATH="${INSTALL_DIR}/db/${DB_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"
SOURCE_DIR=${SOURCE_DIR:-/workspaces/NetAlertX}
PY_SITE_PACKAGES="${VIRTUAL_ENV:-/opt/venv}/lib/python3.12/site-packages"
SOURCE_SERVICES_DIR="${SOURCE_DIR}/install/production-filesystem/services"
LOG_FILES=(
LOG_APP
LOG_APP_FRONT
LOG_STDOUT
LOG_STDERR
LOG_EXECUTION_QUEUE
LOG_APP_PHP_ERRORS
LOG_IP_CHANGES
LOG_CROND
LOG_REPORT_OUTPUT_TXT
LOG_REPORT_OUTPUT_HTML
LOG_REPORT_OUTPUT_JSON
LOG_DB_IS_LOCKED
LOG_NGINX_ERROR
)
ensure_docker_socket_access() {
local socket="/var/run/docker.sock"
if [ ! -S "${socket}" ]; then
echo "docker socket not present; skipping docker group configuration"
return
fi
sudo chmod 666 /var/run/docker.sock 2>/dev/null || true
sudo chown "$(id -u)":"$(id -g)" /workspaces
sudo chmod 755 /workspaces
local sock_gid
sock_gid=$(stat -c '%g' "${socket}" 2>/dev/null || true)
if [ -z "${sock_gid}" ]; then
echo "unable to determine docker socket gid; skipping docker group configuration"
return
fi
killall php-fpm83 nginx crond python3 2>/dev/null || true
local group_entry=""
if command -v getent >/dev/null 2>&1; then
group_entry=$(getent group "${sock_gid}" 2>/dev/null || true)
else
group_entry=$(grep -E ":${sock_gid}:" /etc/group 2>/dev/null || true)
fi
# Mount ramdisks for volatile data
sudo mount -t tmpfs -o size=100m,mode=0777 tmpfs /tmp/log 2>/dev/null || true
sudo mount -t tmpfs -o size=50m,mode=0777 tmpfs /tmp/api 2>/dev/null || true
sudo mount -t tmpfs -o size=50m,mode=0777 tmpfs /tmp/run 2>/dev/null || true
sudo mount -t tmpfs -o size=50m,mode=0777 tmpfs /tmp/nginx 2>/dev/null || true
local group_name=""
if [ -n "${group_entry}" ]; then
group_name=$(echo "${group_entry}" | cut -d: -f1)
else
group_name="docker-host"
sudo addgroup -g "${sock_gid}" "${group_name}" 2>/dev/null || group_name=$(grep -E ":${sock_gid}:" /etc/group | head -n1 | cut -d: -f1)
fi
if [ -z "${group_name}" ]; then
echo "failed to resolve group for docker socket gid ${sock_gid}; skipping docker group configuration"
return
fi
if ! id -nG netalertx | tr ' ' '\n' | grep -qx "${group_name}"; then
sudo addgroup netalertx "${group_name}" 2>/dev/null || true
fi
}
main() {
echo "=== NetAlertX Development Container Setup ==="
killall php-fpm83 nginx crond python3 2>/dev/null
sleep 1
echo "Setting up ${SOURCE_DIR}..."
ensure_docker_socket_access
sudo chown $(id -u):$(id -g) /workspaces
sudo chmod 755 /workspaces
configure_source
echo "--- Starting Development Services ---"
configure_php
start_services
}
isRamDisk() {
if [ -z "$1" ] || [ ! -d "$1" ]; then
echo "Usage: isRamDisk <directory>" >&2
return 2
fi
local fstype
fstype=$(df -T "$1" | awk 'NR==2 {print $2}')
if [ "$fstype" = "tmpfs" ] || [ "$fstype" = "ramfs" ]; then
return 0 # Success (is a ramdisk)
else
return 1 # Failure (is not a ramdisk)
fi
}
# Setup source directory
configure_source() {
echo "[1/4] Configuring System..."
echo " -> Setting up /services permissions"
sudo chown -R netalertx /services
echo "[2/4] Configuring Source..."
echo " -> Cleaning up previous instances"
test -e ${NETALERTX_LOG} && sudo umount "${NETALERTX_LOG}" 2>/dev/null || true
test -e ${NETALERTX_API} && sudo umount "${NETALERTX_API}" 2>/dev/null || true
test -e ${NETALERTX_APP} && sudo rm -Rf ${NETALERTX_APP}/
echo " -> Linking source to ${NETALERTX_APP}"
sudo ln -s ${SOURCE_DIR}/ ${NETALERTX_APP}
echo " -> Mounting ramdisks for /log and /api"
mkdir -p ${NETALERTX_LOG} ${NETALERTX_API}
sudo mount -o uid=$(id -u netalertx),gid=$(id -g netalertx),mode=775 -t tmpfs -o size=256M tmpfs "${NETALERTX_LOG}"
sudo mount -o uid=$(id -u netalertx),gid=$(id -g netalertx),mode=775 -t tmpfs -o size=256M tmpfs "${NETALERTX_API}"
mkdir -p ${NETALERTX_PLUGINS_LOG}
touch ${NETALERTX_PLUGINS_LOG}/.dockerignore ${NETALERTX_API}/.dockerignore
# tmpfs mounts configured with netalertx ownership and 775 permissions above
touch /app/log/nginx_error.log
echo " -> Empty log"|tee ${INSTALL_DIR}/log/app.log \
${INSTALL_DIR}/log/app_front.log \
${INSTALL_DIR}/log/stdout.log
touch ${INSTALL_DIR}/log/stderr.log \
${INSTALL_DIR}/log/execution_queue.log
echo 0 > ${INSTALL_DIR}/log/db_is_locked.log
for f in ${INSTALL_DIR}/log/*.log; do
sudo chown netalertx:www-data $f
sudo chmod 664 $f
echo "" > $f
done
mkdir -p /app/log/plugins
sudo chown -R netalertx:www-data ${INSTALL_DIR}
while ps ax | grep -v grep | grep python3 > /dev/null; do
killall python3 &>/dev/null
sleep 0.2
done
sudo chmod 777 /opt/venv/lib/python3.12/site-packages/ && \
sudo chmod 005 /opt/venv/lib/python3.12/site-packages/
sudo chmod 666 /var/run/docker.sock
echo " -> Updating build timestamp"
date +%s > ${NETALERTX_FRONT}/buildtimestamp.txt
}
# configure_php: configure PHP-FPM and enable dev debug options
configure_php() {
echo "[3/4] Configuring PHP-FPM..."
sudo chown -R netalertx:netalertx ${SYSTEM_SERVICES_RUN} 2>/dev/null || true
}
# start_services: start crond, PHP-FPM, nginx and the application
start_services() {
echo "[4/4] Starting services"
sudo chmod +x /entrypoint.sh
setsid bash /entrypoint.sh&
sleep 1
}
sudo chmod 755 /app/
echo "Development $(git rev-parse --short=8 HEAD)"| sudo tee /app/.VERSION
# Run the main function
main
# create a services readme file
echo "This folder is auto-generated by the container and devcontainer setup.sh script." > /services/README.md
echo "Any changes here will be lost on rebuild. To make permanent changes, edit files in .devcontainer or production filesystem and rebuild the container." >> /services/README.md
echo "Only make temporary/test changes in this folder, then perform a rebuild to reset." >> /services/README.md
sudo chmod 777 /tmp/log /tmp/api /tmp/run /tmp/nginx
sudo rm -rf "${SYSTEM_NGINX_CONFIG}/conf.active"
sudo ln -s "${SYSTEM_SERVICES_ACTIVE_CONFIG}" "${SYSTEM_NGINX_CONFIG}/conf.active"
sudo rm -rf /entrypoint.d
sudo ln -s "${SOURCE_DIR}/install/production-filesystem/entrypoint.d" /entrypoint.d
sudo rm -rf "${NETALERTX_APP}"
sudo ln -s "${SOURCE_DIR}/" "${NETALERTX_APP}"
for dir in "${NETALERTX_DATA}" "${NETALERTX_CONFIG}" "${NETALERTX_DB}"; do
sudo install -d -m 777 "${dir}"
done
for dir in \
"${SYSTEM_SERVICES_RUN_LOG}" \
"${SYSTEM_SERVICES_ACTIVE_CONFIG}" \
"${NETALERTX_PLUGINS_LOG}" \
"/tmp/nginx/client_body" \
"/tmp/nginx/proxy" \
"/tmp/nginx/fastcgi" \
"/tmp/nginx/uwsgi" \
"/tmp/nginx/scgi"; do
sudo install -d -m 777 "${dir}"
done
# Create nginx temp subdirs with permissions
sudo mkdir -p "${SYSTEM_SERVICES_RUN_TMP}/client_body" "${SYSTEM_SERVICES_RUN_TMP}/proxy" "${SYSTEM_SERVICES_RUN_TMP}/fastcgi" "${SYSTEM_SERVICES_RUN_TMP}/uwsgi" "${SYSTEM_SERVICES_RUN_TMP}/scgi"
sudo chmod -R 777 "${SYSTEM_SERVICES_RUN_TMP}"
for var in "${LOG_FILES[@]}"; do
path=${!var}
dir=$(dirname "${path}")
sudo install -d -m 777 "${dir}"
touch "${path}"
done
printf '0\n' | sudo tee "${LOG_DB_IS_LOCKED}" >/dev/null
sudo chmod 777 "${LOG_DB_IS_LOCKED}"
sudo pkill -f python3 2>/dev/null || true
sudo chmod 777 "${PY_SITE_PACKAGES}" "${NETALERTX_DATA}" "${NETALERTX_DATA}"/* 2>/dev/null || true
sudo chmod 005 "${PY_SITE_PACKAGES}" 2>/dev/null || true
sudo chown -R "${NETALERTX_USER}:${NETALERTX_GROUP}" "${NETALERTX_APP}"
date +%s | sudo tee "${NETALERTX_FRONT}/buildtimestamp.txt" >/dev/null
sudo chmod 755 "${NETALERTX_APP}"
sudo chmod +x /entrypoint.sh
setsid bash /entrypoint.sh &
sleep 1
echo "Development $(git rev-parse --short=8 HEAD)" | sudo tee "${NETALERTX_APP}/.VERSION" >/dev/null

View File

@@ -1,4 +1,5 @@
.dockerignore
**/.dockerignore
.env
.git
.github

3
.flake8 Normal file
View File

@@ -0,0 +1,3 @@
[flake8]
max-line-length = 180
ignore = E221,E222,E251,E203

View File

@@ -46,7 +46,7 @@ body:
attributes:
label: app.conf
description: |
Paste your `app.conf` (remove personal info)
Paste relevant `app.conf`settings (remove sensitive info)
render: python
validations:
required: false
@@ -70,6 +70,13 @@ body:
- Bare-metal (community only support - Check Discord)
validations:
required: true
- type: checkboxes
attributes:
label: Debug or Trace enabled
description: I confirm I set `LOG_LEVEL` to `debug` or `trace`
options:
- label: I have read and followed the steps in the wiki link above and provided the required debug logs and the log section covers the time when the issue occurs.
required: true
- type: textarea
attributes:
label: app.log
@@ -78,13 +85,14 @@ body:
***Generally speaking, all bug reports should have logs provided.***
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
Additionally, any additional info? Screenshots? References? Anything that will give us more context about the issue you are encountering!
You can use `tail -100 /app/log/app.log` in the container if you have trouble getting to the log files.
You can use `tail -100 /app/log/app.log` in the container if you have trouble getting to the log files or send them to netalertx@gmail.com with the issue number.
validations:
required: false
- type: checkboxes
- type: textarea
attributes:
label: Debug enabled
description: I confirm I enabled `debug`
options:
- label: I have read and followed the steps in the wiki link above and provided the required debug logs and the log section covers the time when the issue occurs.
required: true
label: Docker Logs
description: |
You can retrieve the logs from Portainer -> Containers -> your NetAlertX container -> Logs or by running `sudo docker logs netalertx`.
validations:
required: true

View File

@@ -18,7 +18,7 @@ Backend loop phases (see `server/__main__.py` and `server/plugin.py`): `once`, `
## Plugin patterns that matter
- Manifest lives at `front/plugins/<code_name>/config.json`; `code_name` == folder, `unique_prefix` drives settings and filenames (e.g., `ARPSCAN`).
- Control via settings: `<PREF>_RUN` (phase), `<PREF>_RUN_SCHD` (cron-like), `<PREF>_CMD` (script path), `<PREF>_RUN_TIMEOUT`, `<PREF>_WATCH` (diff columns).
- Data contract: scripts write `/app/log/plugins/last_result.<PREF>.log` (pipedelimited: 9 required cols + optional 4). Use `front/plugins/plugin_helper.py`s `Plugin_Objects` to sanitize text and normalize MACs, then `write_result_file()`.
- Data contract: scripts write `/tmp/log/plugins/last_result.<PREF>.log` (pipedelimited: 9 required cols + optional 4). Use `front/plugins/plugin_helper.py`s `Plugin_Objects` to sanitize text and normalize MACs, then `write_result_file()`.
- Device import: define `database_column_definitions` when creating/updating devices; watched fields trigger notifications.
### Standard Plugin Formats
@@ -30,6 +30,7 @@ Backend loop phases (see `server/__main__.py` and `server/plugin.py`): `once`, `
* other: Miscellaneous plugins. Runs at various times. Data source: self / Template.
### Plugin logging & outputs
- Always check relevant logs first.
- Use logging as shown in other plugins.
- Collect results with `Plugin_Objects.add_object(...)` during processing and call `plugin_objects.write_result_file()` exactly once at the end of the script.
- Prefer to log a brief summary before writing (e.g., total objects added) to aid troubleshooting; keep logs concise at `info` level and use `verbose` or `debug` for extra context.
@@ -42,22 +43,32 @@ Backend loop phases (see `server/__main__.py` and `server/plugin.py`): `once`, `
## Conventions & helpers to reuse
- Settings: add/modify via `ccd()` in `server/initialise.py` or perplugin manifest. Never hardcode ports or secrets; use `get_setting_value()`.
- Logging: use `logger.mylog(level, [message])`; levels: none/minimal/verbose/debug/trace.
- Time/MAC/strings: `helper.py` (`timeNowTZ`, `normalize_mac`, sanitizers). Validate MACs before DB writes.
- Time/MAC/strings: `helper.py` (`timeNowDB`, `normalize_mac`, sanitizers). Validate MACs before DB writes.
- DB helpers: prefer `server/db/db_helper.py` functions (e.g., `get_table_json`, device condition helpers) over raw SQL in new paths.
## Dev workflow (devcontainer)
- **Devcontainer philosophy: brutal simplicity.** One user, everything writable, completely idempotent. No permission checks, no conditional logic, no sudo needed. If something doesn't work, tear down the wall and rebuild - don't patch. We unit test permissions in the hardened build.
- **Permissions:** Never `chmod` or `chown` during operations. Everything is already writable. If you need permissions, the devcontainer setup is broken - fix `.devcontainer/scripts/setup.sh` or `.devcontainer/resources/devcontainer-Dockerfile` instead.
- **Files & Paths:** Use environment variables (`NETALERTX_DB`, `NETALERTX_LOG`, etc.) everywhere. `/data` for persistent config/db, `/tmp` for runtime logs/api/nginx state. Never hardcode `/data/db` or relative paths.
- **Database reset:** Use the `[Dev Container] Wipe and Regenerate Database` task. Kills backend, deletes `/data/{db,config}/*`, runs first-time setup scripts. Clean slate, no questions.
- Services: use tasks to (re)start backend and nginx/PHP-FPM. Backend runs with debugpy on 5678; attach a Python debugger if needed.
- Run a plugin manually: `python3 front/plugins/<code_name>/script.py` (ensure `sys.path` includes `/app/front/plugins` and `/app/server` like the template).
- Testing: pytest available via Alpine packages. Tests live in `test/`; app code is under `server/`. PYTHONPATH is preconfigured to include workspace and `/opt/venv` sitepackages.
- **Subprocess calls:** ALWAYS set explicit timeouts. Default to 60s minimum unless plugin config specifies otherwise. Nested subprocess calls (e.g., plugins calling external tools) need their own timeout - outer plugin timeout won't save you.
## What “done right” looks like
- When adding a plugin, start from `front/plugins/__template`, implement with `plugin_helper`, define manifest settings, and wire phase via `<PREF>_RUN`. Verify logs in `/app/log/plugins/` and data in `api/*.json`.
- When adding a plugin, start from `front/plugins/__template`, implement with `plugin_helper`, define manifest settings, and wire phase via `<PREF>_RUN`. Verify logs in `/tmp/log/plugins/` and data in `api/*.json`.
- When introducing new config, define it once (core `ccd()` or plugin manifest) and read it via helpers everywhere.
- When exposing new server functionality, add endpoints in `server/api_server/*` and keep authorization consistent; update UI by reading/writing JSON cache rather than bypassing the pipeline.
## Useful references
- Docs: `docs/PLUGINS_DEV.md`, `docs/SETTINGS_SYSTEM.md`, `docs/API_*.md`, `docs/DEBUG_*.md`
- Logs: backend `/app/log/app.log`, plugin logs under `/app/log/plugins/`, nginx/php logs under `/var/log/*`
- Logs: All logs are under `/tmp/log/`. Plugin logs are very shortly under `/tmp/log/plugins/` until picked up by the server.
- plugin logs: `/tmp/log/app.log`
- backend logs: `/tmp/log/stdout.log` and `/tmp/log/stderr.log`
- frontend commands logs: `/tmp/log/app_front.log`
- php errors: `/tmp/log/app.php_errors.log`
- nginx logs: `/tmp/log/nginx-access.log` and `/tmp/log/nginx-error.log`
## Assistant expectations:
- Be concise, opinionated, and biased toward security and simplicity.

View File

@@ -10,7 +10,7 @@ on:
branches:
- next_release
jobs:
jobs:
docker_dev:
runs-on: ubuntu-latest
timeout-minutes: 30
@@ -19,7 +19,8 @@ jobs:
packages: write
if: >
contains(github.event.head_commit.message, 'PUSHPROD') != 'True' &&
github.repository == 'jokob-sk/NetAlertX'
github.repository == 'jokob-sk/NetAlertX'
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -30,26 +31,36 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# --- Generate timestamped dev version
- name: Generate timestamp version
id: timestamp
run: |
ts=$(date -u +'%Y%m%d-%H%M%S')
echo "version=dev-${ts}" >> $GITHUB_OUTPUT
echo "Generated version: dev-${ts}"
- name: Set up dynamic build ARGs
id: getargs
id: getargs
run: echo "version=$(cat ./stable/VERSION)" >> $GITHUB_OUTPUT
- name: Get release version
id: get_version
run: echo "version=Dev" >> $GITHUB_OUTPUT
# --- Write the timestamped version to .VERSION file
- name: Create .VERSION file
run: echo "${{ steps.get_version.outputs.version }}" >> .VERSION
run: echo "${{ steps.timestamp.outputs.version }}" > .VERSION
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/jokob-sk/netalertx-dev
jokobsk/netalertx-dev
tags: |
type=raw,value=latest
type=raw,value=${{ steps.timestamp.outputs.version }}
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}

View File

@@ -6,7 +6,6 @@
# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.
name: Publish Docker image
on:
@@ -14,6 +13,7 @@ on:
types: [published]
tags:
- '*.[1-9]+[0-9]?.[1-9]+*'
jobs:
docker:
runs-on: ubuntu-latest
@@ -21,6 +21,7 @@ jobs:
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v3
@@ -31,42 +32,39 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set up dynamic build ARGs
id: getargs
run: echo "version=$(cat ./stable/VERSION)" >> $GITHUB_OUTPUT
# --- Get release version from tag
- name: Get release version
id: get_version
run: echo "::set-output name=version::${GITHUB_REF#refs/tags/}"
run: echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
# --- Write version to .VERSION file
- name: Create .VERSION file
run: echo "${{ steps.get_version.outputs.version }}" >> .VERSION
run: echo "${{ steps.get_version.outputs.version }}" > .VERSION
# --- Generate Docker metadata and tags
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
# list of Docker images to use as base name for tags
images: |
ghcr.io/jokob-sk/netalertx
jokobsk/netalertx
# generate Docker tags based on the following events/attributes
jokobsk/netalertx
tags: |
type=semver,pattern={{version}},value=${{ inputs.version }}
type=semver,pattern={{major}}.{{minor}},value=${{ inputs.version }}
type=semver,pattern={{major}},value=${{ inputs.version }}
type=semver,pattern={{version}},value=${{ steps.get_version.outputs.version }}
type=semver,pattern={{major}}.{{minor}},value=${{ steps.get_version.outputs.version }}
type=semver,pattern={{major}},value=${{ steps.get_version.outputs.version }}
type=ref,event=branch,suffix=-{{ sha }}
type=ref,event=pr
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }}
- name: Log in to Github Container registry
- name: Log in to Github Container Registry (GHCR)
uses: docker/login-action@v3
with:
registry: ghcr.io
username: jokob-sk
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DockerHub
- name: Log in to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
@@ -81,6 +79,5 @@ jobs:
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# # ⚠ disable cache if build is failing to download debian packages
# cache-from: type=registry,ref=ghcr.io/jokob-sk/netalertx:buildcache
# cache-to: type=registry,ref=ghcr.io/jokob-sk/netalertx:buildcache,mode=max

View File

@@ -43,7 +43,7 @@ jobs:
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/jokob-sk/netalertx-dev-rewrite

37
.gitignore vendored
View File

@@ -5,13 +5,12 @@
.gitconfig
.*CommandMarker
deviceid
.VERSION
# Sensitive data
.DS_Store
.cache
nohup.out
config/*
.ash_history
.VERSION
config/pialert.conf
config/app.conf
db/*
@@ -24,35 +23,23 @@ front/api/*
/api/*
**/plugins/**/*.log
**/plugins/cloud_services/*
**/%40eaDir/
**/@eaDir/
__pycache__/
*.py[cod]
*$py.class
**/last_result.log
**/script.log
**/pialert.conf_bak
**/pialert.db_bak
.*.swp
# future stuff
front/img/cloud_services/*
**/cloud_services.php
**/cloud_services.js
front/css/cloud_services.css
# OS junk
Thumbs.db
ehthumbs.db
Desktop.ini
**/%40eaDir/
**/@eaDir/
*/%40eaDir/
*/@eaDir/
.DS_Store
.*.swp
# Python junk
venv/
.env/
__pycache__/
*.py[cod]
*$py.class
# Build artifacts (if you ever package anything)
dist/
build/
docker-compose.yml.ffsb42
.env.omada.ffsb42

View File

@@ -1,23 +0,0 @@
import sys, importlib
mods = [
'json', 'simplejson',
'httplib', 'http.client',
'urllib2', 'urllib.request',
'Queue', 'queue',
'cStringIO', 'StringIO', 'io',
'md5', 'hashlib',
'ssl'
]
print('PYTHON_EXE:' + sys.executable)
print('PYTHON_VER:' + sys.version.replace('\n', ' '))
for m in mods:
try:
mod = importlib.import_module(m)
ver = getattr(mod, '__version__', None)
if ver is None:
# try common attributes
ver = getattr(mod, 'version', None)
info = (' version=' + str(ver)) if ver is not None else ''
print('OK %s%s' % (m, info))
except Exception as e:
print('MISSING %s %s: %s' % (m, e.__class__.__name__, e))

8
.vscode/launch.json vendored
View File

@@ -29,6 +29,14 @@
"pathMappings": {
"/app": "${workspaceFolder}"
}
},
{
"name": "Python: Current File",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true
}
]
}

18
.vscode/settings.json vendored
View File

@@ -11,13 +11,23 @@
// Let the Python extension invoke pytest via the interpreter; avoid hardcoded paths
// Removed python.testing.pytestPath and legacy pytest.command overrides
"terminal.integrated.defaultProfile.linux": "fish",
"terminal.integrated.defaultProfile.linux": "zsh",
"terminal.integrated.profiles.linux": {
"fish": {
"path": "/usr/bin/fish"
"zsh": {
"path": "/bin/zsh"
}
}
,
// Fallback for older VS Code versions or schema validators that don't accept custom profiles
"terminal.integrated.shell.linux": "/usr/bin/fish"
"terminal.integrated.shell.linux": "/usr/bin/zsh"
,
"python.linting.flake8Enabled": true,
"python.linting.enabled": true,
"python.linting.flake8Args": [
"--config=.flake8"
],
"python.formatting.provider": "black",
"python.formatting.blackArgs": [
"--line-length=180"
]
}

93
.vscode/tasks.json vendored
View File

@@ -1,16 +1,27 @@
{
"version": "2.0.0",
"inputs": [
{
"id": "confirmPrune",
"type": "promptString",
"description": "DANGER! Type YES to confirm pruning all unused Docker resources. This will destroy containers, images, volumes, and networks!",
"default": ""
}
],
"tasks": [
{
"label": "[Any POSIX] Generate Devcontainer Configs",
"type": "shell",
"command": ".devcontainer/scripts/generate-configs.sh",
"detail": "Generates devcontainer configs from the template. This must be run after changes to devcontainer to combine/merge them into the final config used by VS Code. Note- this has no bearing on the production or test image.",
"presentation": {
"echo": true,
"reveal": "always",
"panel": "shared",
"showReuseMessage": false
"showReuseMessage": false,
"group": "POSIX Tasks"
},
"problemMatcher": [],
"group": {
"kind": "build",
@@ -24,12 +35,19 @@
{
"label": "[Any] Docker system and build Prune",
"type": "shell",
"command": ".devcontainer/scripts/confirm-docker-prune.sh",
"command": ".devcontainer/scripts/confirm-docker-prune.sh",
"detail": "DANGER! Prunes all unused Docker resources (images, containers, volumes, networks). Any stopped container will be wiped and data will be lost. Use with caution.",
"options": {
"env": {
"CONFIRM_PRUNE": "${input:confirmPrune}"
}
},
"presentation": {
"echo": true,
"reveal": "always",
"panel": "shared",
"showReuseMessage": false
"showReuseMessage": false,
"group": "Any"
},
"problemMatcher": [],
"group": {
@@ -45,6 +63,7 @@
"label": "[Dev Container] Re-Run Startup Script",
"type": "shell",
"command": "./isDevContainer.sh || exit 1;/workspaces/NetAlertX/.devcontainer/scripts/setup.sh",
"detail": "The startup script runs directly after the container is started. It reprovisions permissions, links folders, and performs other setup tasks. Run this if you have made changes to the setup script or need to reprovision the container.",
"options": {
"cwd": "/workspaces/NetAlertX/.devcontainer/scripts"
},
@@ -65,6 +84,7 @@
"label": "[Dev Container] Start Backend (Python)",
"type": "shell",
"command": "./isDevContainer.sh || exit 1; /services/start-backend.sh",
"detail": "Restarts the NetAlertX backend (Python) service in the dev container. This may take 5 seconds to be completely ready.",
"options": {
"cwd": "/workspaces/NetAlertX/.devcontainer/scripts"
},
@@ -73,7 +93,8 @@
"reveal": "always",
"panel": "shared",
"showReuseMessage": false,
"clear": false
"clear": false,
"group": "Devcontainer"
},
"problemMatcher": [],
"icon": {
@@ -85,6 +106,7 @@
"label": "[Dev Container] Start CronD (Scheduler)",
"type": "shell",
"command": "./isDevContainer.sh || exit 1; /services/start-crond.sh",
"detail": "Stops and restarts the crond service.",
"options": {
"cwd": "/workspaces/NetAlertX/.devcontainer/scripts"
},
@@ -93,7 +115,8 @@
"reveal": "always",
"panel": "shared",
"showReuseMessage": false,
"clear": false
"clear": false,
"group": "Devcontainer"
},
"problemMatcher": [],
"icon": {
@@ -105,6 +128,7 @@
"label": "[Dev Container] Start Frontend (nginx and PHP-FPM)",
"type": "shell",
"command": "./isDevContainer.sh || exit 1; /services/start-php-fpm.sh & /services/start-nginx.sh &",
"detail": "Stops and restarts the NetAlertX frontend services (nginx and PHP-FPM) in the dev container. This launches almost instantly.",
"options": {
"cwd": "/workspaces/NetAlertX/.devcontainer/scripts"
@@ -114,7 +138,8 @@
"reveal": "always",
"panel": "shared",
"showReuseMessage": false,
"clear": false
"clear": false,
"group": "Devcontainer"
},
"problemMatcher": [],
"icon": {
@@ -126,6 +151,7 @@
"label": "[Dev Container] Stop Frontend & Backend Services",
"type": "shell",
"command": "./isDevContainer.sh || exit 1; pkill -f 'php-fpm83|nginx|crond|python3' || true",
"detail": "Stops all NetAlertX services running in the dev container.",
"options": {
"cwd": "/workspaces/NetAlertX/.devcontainer/scripts"
},
@@ -133,7 +159,8 @@
"echo": true,
"reveal": "always",
"panel": "shared",
"showReuseMessage": false
"showReuseMessage": false,
"group": "Devcontainer"
},
"problemMatcher": [],
"icon": {
@@ -142,29 +169,55 @@
}
},
{
"label": "[Dev Container] List NetAlertX Ports",
"label": "[Any] Build Unit Test Docker image",
"type": "shell",
"command": "list-ports.sh",
"options": {
"cwd": "/workspaces/NetAlertX/.devcontainer/scripts"
},
"command": "docker buildx build -t netalertx-test . && echo '🧪 Unit Test Docker image built: netalertx-test'",
"detail": "This must be run after changes to the container. Unit testing will not register changes until after this image is rebuilt. It takes about 30 seconds to build unless changes to the venv stage are made. venv takes 90s alone.",
"presentation": {
"echo": true,
"reveal": "always",
"panel": "shared",
"showReuseMessage": false
"showReuseMessage": false,
"group": "Any"
},
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": false
},
"icon": {
"id": "beaker",
"color": "terminal.ansiBlue"
}
},
{
"label": "[Dev Container] Wipe and Regenerate Database",
"type": "shell",
"command": "killall 'python3' || true && sleep 1 && rm -rf /data/db/* /data/config/* && bash /entrypoint.d/15-first-run-config.sh && bash /entrypoint.d/20-first-run-db.sh && echo '✅ Database and config wiped and regenerated'",
"detail": "Wipes devcontainer db and config. Provides a fresh start in devcontainer, run this task, then run the Rerun Startup Task",
"options": {},
"presentation": {
"echo": true,
"reveal": "always",
"panel": "shared",
"showReuseMessage": false,
"group": "Devcontainer"
},
"problemMatcher": [],
"icon": {
"id": "output",
"color": "terminal.ansiBlue"
"id": "database",
"color": "terminal.ansiRed"
}
}
,
},
{
"label": "[Any] Build Unit Test Docker image",
"label": "Build & Launch Prodcution Docker Container",
"type": "shell",
"command": "docker buildx build -t netalertx-test . && echo '🧪 Unit Test Docker image built: netalertx-test'",
"command": "docker compose up -d --build --force-recreate",
"detail": "Before launching, ensure VSCode Ports are closed and services are stopped. Tasks: Stop Frontend & Backend Services & Remote: Close Unused Forwarded Ports to ensure proper operation of the new container.",
"options": {
"cwd": "/workspaces/NetAlertX"
},
"presentation": {
"echo": true,
"reveal": "always",
@@ -177,7 +230,7 @@
"isDefault": false
},
"icon": {
"id": "beaker",
"id": "package",
"color": "terminal.ansiBlue"
}
}

View File

@@ -43,14 +43,16 @@ ARG INSTALL_DIR=/app
# NetAlertX app directories
ENV NETALERTX_APP=${INSTALL_DIR}
ENV NETALERTX_CONFIG=${NETALERTX_APP}/config
ENV NETALERTX_DATA=/data
ENV NETALERTX_CONFIG=${NETALERTX_DATA}/config
ENV NETALERTX_FRONT=${NETALERTX_APP}/front
ENV NETALERTX_PLUGINS=${NETALERTX_FRONT}/plugins
ENV NETALERTX_SERVER=${NETALERTX_APP}/server
ENV NETALERTX_API=${NETALERTX_APP}/api
ENV NETALERTX_DB=${NETALERTX_APP}/db
ENV NETALERTX_API=/tmp/api
ENV NETALERTX_DB=${NETALERTX_DATA}/db
ENV NETALERTX_DB_FILE=${NETALERTX_DB}/app.db
ENV NETALERTX_BACK=${NETALERTX_APP}/back
ENV NETALERTX_LOG=${NETALERTX_APP}/log
ENV NETALERTX_LOG=/tmp/log
ENV NETALERTX_PLUGINS_LOG=${NETALERTX_LOG}/plugins
ENV NETALERTX_CONFIG_FILE=${NETALERTX_CONFIG}/app.conf
@@ -67,31 +69,35 @@ ENV LOG_EXECUTION_QUEUE=${NETALERTX_LOG}/execution_queue.log
ENV LOG_REPORT_OUTPUT_JSON=${NETALERTX_LOG}/report_output.json
ENV LOG_STDOUT=${NETALERTX_LOG}/stdout.log
ENV LOG_CROND=${NETALERTX_LOG}/crond.log
ENV LOG_NGINX_ERROR=${NETALERTX_LOG}/nginx-error.log
# System Services configuration files
ENV ENTRYPOINT_CHECKS=/entrypoint.d
ENV SYSTEM_SERVICES=/services
ENV SYSTEM_SERVICES_SCRIPTS=${SYSTEM_SERVICES}/scripts
ENV SYSTEM_SERVICES_CONFIG=${SYSTEM_SERVICES}/config
ENV SYSTEM_NGINX_CONFIG=${SYSTEM_SERVICES_CONFIG}/nginx
ENV SYSTEM_NGINX_CONFIG_FILE=${SYSTEM_NGINX_CONFIG}/nginx.conf
ENV SYSTEM_SERVICES_ACTIVE_CONFIG=/tmp/nginx/active-config
ENV SYSTEM_SERVICES_PHP_FOLDER=${SYSTEM_SERVICES_CONFIG}/php
ENV SYSTEM_SERVICES_PHP_FPM_D=${SYSTEM_SERVICES_PHP_FOLDER}/php-fpm.d
ENV SYSTEM_SERVICES_CROND=${SYSTEM_SERVICES_CONFIG}/crond
ENV SYSTEM_SERVICES_RUN=${SYSTEM_SERVICES}/run
ENV SYSTEM_SERVICES_RUN=/tmp/run
ENV SYSTEM_SERVICES_RUN_TMP=${SYSTEM_SERVICES_RUN}/tmp
ENV SYSTEM_SERVICES_RUN_LOG=${SYSTEM_SERVICES_RUN}/logs
ENV PHP_FPM_CONFIG_FILE=${SYSTEM_SERVICES_PHP_FOLDER}/php-fpm.conf
ENV READ_ONLY_FOLDERS="${NETALERTX_BACK} ${NETALERTX_FRONT} ${NETALERTX_SERVER} ${SYSTEM_SERVICES} \
${SYSTEM_SERVICES_CONFIG}"
ENV READ_WRITE_FOLDERS="${NETALERTX_CONFIG} ${NETALERTX_DB} ${NETALERTX_API} ${NETALERTX_LOG} \
${NETALERTX_PLUGINS_LOG} ${SYSTEM_SERVICES_RUN} ${SYSTEM_SERVICES_RUN_TMP} \
${SYSTEM_SERVICES_RUN_LOG}"
${SYSTEM_SERVICES_CONFIG} ${ENTRYPOINT_CHECKS}"
ENV READ_WRITE_FOLDERS="${NETALERTX_DATA} ${NETALERTX_CONFIG} ${NETALERTX_DB} ${NETALERTX_API} \
${NETALERTX_LOG} ${NETALERTX_PLUGINS_LOG} ${SYSTEM_SERVICES_RUN} \
${SYSTEM_SERVICES_RUN_TMP} ${SYSTEM_SERVICES_RUN_LOG} \
${SYSTEM_SERVICES_ACTIVE_CONFIG}"
#Python environment
ENV PYTHONUNBUFFERED=1
ENV VIRTUAL_ENV=/opt/venv
ENV VIRTUAL_ENV_BIN=/opt/venv/bin
ENV PYTHONPATH=${NETALERTX_APP}:${NETALERTX_SERVER}:${VIRTUAL_ENV}/lib/python3.12/site-packages
ENV PYTHONPATH=${NETALERTX_APP}:${NETALERTX_SERVER}:${NETALERTX_PLUGINS}:${VIRTUAL_ENV}/lib/python3.12/site-packages
ENV PATH="${SYSTEM_SERVICES}:${VIRTUAL_ENV_BIN}:$PATH"
# App Environment
@@ -99,7 +105,7 @@ ENV LISTEN_ADDR=0.0.0.0
ENV PORT=20211
ENV NETALERTX_DEBUG=0
ENV VENDORSPATH=/app/back/ieee-oui.txt
ENV VENDORSPATH_NEWEST=/services/run/tmp/ieee-oui.txt
ENV VENDORSPATH_NEWEST=${SYSTEM_SERVICES_RUN_TMP}/ieee-oui.txt
ENV ENVIRONMENT=alpine
ENV READ_ONLY_USER=readonly READ_ONLY_GROUP=readonly
ENV NETALERTX_USER=netalertx NETALERTX_GROUP=netalertx
@@ -123,11 +129,15 @@ COPY --chown=${NETALERTX_USER}:${NETALERTX_GROUP} install/production-filesystem/
COPY --chown=${NETALERTX_USER}:${NETALERTX_GROUP} --chmod=755 back ${NETALERTX_BACK}
COPY --chown=${NETALERTX_USER}:${NETALERTX_GROUP} --chmod=755 front ${NETALERTX_FRONT}
COPY --chown=${NETALERTX_USER}:${NETALERTX_GROUP} --chmod=755 server ${NETALERTX_SERVER}
RUN install -d -o ${NETALERTX_USER} -g ${NETALERTX_GROUP} -m 755 ${NETALERTX_API} \
${NETALERTX_LOG} ${SYSTEM_SERVICES_RUN_TMP} ${SYSTEM_SERVICES_RUN_LOG} && \
# Create required folders with correct ownership and permissions
RUN install -d -o ${NETALERTX_USER} -g ${NETALERTX_GROUP} -m 700 ${READ_WRITE_FOLDERS} && \
sh -c "find ${NETALERTX_APP} -type f \( -name '*.sh' -o -name 'speedtest-cli' \) \
-exec chmod 750 {} \;"
# Copy version information into the image
COPY --chown=${NETALERTX_USER}:${NETALERTX_GROUP} .VERSION ${NETALERTX_APP}/.VERSION
# Copy the virtualenv from the builder stage
COPY --from=builder --chown=20212:20212 ${VIRTUAL_ENV} ${VIRTUAL_ENV}
@@ -181,7 +191,7 @@ RUN chown -R ${READ_ONLY_USER}:${READ_ONLY_GROUP} ${READ_ONLY_FOLDERS} && \
chmod -R 600 ${READ_WRITE_FOLDERS} && \
find ${READ_WRITE_FOLDERS} -type d -exec chmod 700 {} + && \
chown ${READ_ONLY_USER}:${READ_ONLY_GROUP} /entrypoint.sh /opt /opt/venv && \
chmod 005 /entrypoint.sh ${SYSTEM_SERVICES}/*.sh /app /opt /opt/venv && \
chmod 005 /entrypoint.sh ${SYSTEM_SERVICES}/*.sh ${SYSTEM_SERVICES_SCRIPTS}/* ${ENTRYPOINT_CHECKS}/* /app /opt /opt/venv && \
for dir in ${READ_WRITE_FOLDERS}; do \
install -d -o ${NETALERTX_USER} -g ${NETALERTX_GROUP} -m 700 "$dir"; \
done && \

View File

@@ -49,14 +49,15 @@ FROM debian:bookworm-slim
# NetAlertX app directories
ENV INSTALL_DIR=/app
ENV NETALERTX_APP=${INSTALL_DIR}
ENV NETALERTX_CONFIG=${NETALERTX_APP}/config
ENV NETALERTX_DATA=/data
ENV NETALERTX_CONFIG=${NETALERTX_DATA}/config
ENV NETALERTX_FRONT=${NETALERTX_APP}/front
ENV NETALERTX_SERVER=${NETALERTX_APP}/server
ENV NETALERTX_API=${NETALERTX_APP}/api
ENV NETALERTX_DB=${NETALERTX_APP}/db
ENV NETALERTX_API=/tmp/api
ENV NETALERTX_DB=${NETALERTX_DATA}/db
ENV NETALERTX_DB_FILE=${NETALERTX_DB}/app.db
ENV NETALERTX_BACK=${NETALERTX_APP}/back
ENV NETALERTX_LOG=${NETALERTX_APP}/log
ENV NETALERTX_LOG=/tmp/log
ENV NETALERTX_PLUGINS_LOG=${NETALERTX_LOG}/plugins
# NetAlertX log files
@@ -72,17 +73,19 @@ ENV LOG_EXECUTION_QUEUE=${NETALERTX_LOG}/execution_queue.log
ENV LOG_REPORT_OUTPUT_JSON=${NETALERTX_LOG}/report_output.json
ENV LOG_STDOUT=${NETALERTX_LOG}/stdout.log
ENV LOG_CROND=${NETALERTX_LOG}/crond.log
ENV LOG_NGINX_ERROR=${NETALERTX_LOG}/nginx-error.log
# System Services configuration files
ENV SYSTEM_SERVICES=/services
ENV SYSTEM_SERVICES_CONFIG=${SYSTEM_SERVICES}/config
ENV SYSTEM_NGINIX_CONFIG=${SYSTEM_SERVICES_CONFIG}/nginx
ENV SYSTEM_NGINX_CONFIG_FILE=${SYSTEM_NGINIX_CONFIG}/nginx.conf
ENV SYSTEM_SERVICES_ACTIVE_CONFIG=/tmp/nginx/active-config
ENV NETALERTX_CONFIG_FILE=${NETALERTX_CONFIG}/app.conf
ENV SYSTEM_SERVICES_PHP_FOLDER=${SYSTEM_SERVICES_CONFIG}/php
ENV SYSTEM_SERVICES_PHP_FPM_D=${SYSTEM_SERVICES_PHP_FOLDER}/php-fpm.d
ENV SYSTEM_SERVICES_CROND=${SYSTEM_SERVICES_CONFIG}/crond
ENV SYSTEM_SERVICES_RUN=${SYSTEM_SERVICES}/run
ENV SYSTEM_SERVICES_RUN=/tmp/run
ENV SYSTEM_SERVICES_RUN_TMP=${SYSTEM_SERVICES_RUN}/tmp
ENV SYSTEM_SERVICES_RUN_LOG=${SYSTEM_SERVICES_RUN}/logs
ENV PHP_FPM_CONFIG_FILE=${SYSTEM_SERVICES_PHP_FOLDER}/php-fpm.conf
@@ -94,7 +97,7 @@ ENV VIRTUAL_ENV=/opt/venv
ENV VIRTUAL_ENV_BIN=/opt/venv/bin
ENV PATH="${VIRTUAL_ENV}/bin:${PATH}:/services"
ENV VENDORSPATH=/app/back/ieee-oui.txt
ENV VENDORSPATH_NEWEST=/services/run/tmp/ieee-oui.txt
ENV VENDORSPATH_NEWEST=${SYSTEM_SERVICES_RUN_TMP}/ieee-oui.txt
# App Environment

View File

@@ -6,7 +6,7 @@
# NetAlertX - Network, presence scanner and alert framework
Get visibility of what's going on on your WIFI/LAN network and enable presence detection of important devices. Schedule scans for devices, port changes and get alerts if unknown devices or changes are found. Write your own [Plugin](https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md#readme) with auto-generated UI and in-build notification system. Build out and easily maintain your network source of truth (NSoT).
Get visibility of what's going on on your WIFI/LAN network and enable presence detection of important devices. Schedule scans for devices, port changes and get alerts if unknown devices or changes are found. Write your own [Plugin](https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md#readme) with auto-generated UI and in-build notification system. Build out and easily maintain your network source of truth (NSoT) and device inventory.
## 📋 Table of Contents
@@ -33,13 +33,13 @@ Get visibility of what's going on on your WIFI/LAN network and enable presence d
## 🚀 Quick Start
To launch NetAlertX in seconds, replace `local_path` with the absolute path on your system that contains your `config` and `db` folders, then run::
Start NetAlertX in seconds with Docker:
```bash
docker run -d --rm --network=host \
-v local_path/config:/app/config \
-v local_path/db:/app/db \
--mount type=tmpfs,target=/app/api \
-v local_path/config:/data/config \
-v local_path/db:/data/db \
--mount type=tmpfs,target=/tmp/api \
-e PUID=200 -e PGID=300 \
-e TZ=Europe/Berlin \
-e PORT=20211 \
@@ -61,7 +61,7 @@ For Home Assistant users: [Click here to add NetAlertX](https://my.home-assistan
For other install methods, check the [installation docs](#-documentation)
| [📑 Docker guide](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md) | [🚀 Releases](https://github.com/jokob-sk/NetAlertX/releases) | [📚 Docs](https://jokob-sk.github.io/NetAlertX/) | [🔌 Plugins](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md) | [🤖 Ask AI](https://gurubase.io/g/netalertx)
| [📑 Docker guide](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_INSTALLATION.md) | [🚀 Releases](https://github.com/jokob-sk/NetAlertX/releases) | [📚 Docs](https://jokob-sk.github.io/NetAlertX/) | [🔌 Plugins](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md) | [🤖 Ask AI](https://gurubase.io/g/netalertx)
|----------------------| ----------------------| ----------------------| ----------------------| ----------------------|
![showcase][showcase]
@@ -103,7 +103,7 @@ The [workflows module](https://github.com/jokob-sk/NetAlertX/blob/main/docs/WORK
Supported browsers: Chrome, Firefox
- [[Installation] Docker](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md)
- [[Installation] Docker](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_INSTALLATION.md)
- [[Installation] Home Assistant](https://github.com/alexbelgium/hassio-addons/tree/master/netalertx)
- [[Installation] Bare metal](https://github.com/jokob-sk/NetAlertX/blob/main/docs/HW_INSTALL.md)
- [[Installation] Unraid App](https://unraid.net/community/apps)
@@ -140,7 +140,7 @@ A: No. All scans and data remain local, unless you set up cloud-based notificati
A: Yes! You can install it bare-metal. See the [bare metal installation guide](https://github.com/jokob-sk/NetAlertX/blob/main/docs/HW_INSTALL.md).
**Q: Where is the data stored?**
A: In the `/config` and `/db` folders, mapped in Docker. Back up these folders regularly.
A: In the `/data/config` and `/data/db` folders. Back up these folders regularly.
## 🐞 Known Issues

1
api Symbolic link
View File

@@ -0,0 +1 @@
/tmp/api

2
db/.gitignore vendored
View File

@@ -1,2 +0,0 @@
*
!.gitignore

View File

@@ -17,53 +17,38 @@ services:
volumes:
- type: volume # Persistent Docker-managed Named Volume for storage of config files
source: netalertx_config # the default name of the volume is netalertx_config
target: /app/config # inside the container mounted to /app/config
- type: volume # Persistent Docker-managed Named Volume for storage
source: netalertx_data # the default name of the volume is netalertx_data
target: /data # consolidated configuration and database storage
read_only: false # writable volume
# Example custom local folder called /home/user/netalertx_config
# Example custom local folder called /home/user/netalertx_data
# - type: bind
# source: /home/user/netalertx_config
# target: /app/config
# source: /home/user/netalertx_data
# target: /data
# read_only: false
# ... or use the alternative format
# - /home/user/netalertx_config:/app/config:rw
- type: volume
source: netalertx_db
target: /app/db
read_only: false
# - /home/user/netalertx_data:/data:rw
- type: bind # Bind mount for timezone consistency
source: /etc/localtime
target: /etc/localtime
read_only: true
# Use a custom Enterprise-configured nginx config for ldap or other settings
# - /custom-enterprise.conf:/services/config/nginx/conf.active/netalertx.conf:ro
# Use a custom Enterprise-configured nginx config for ldap or other settings
# - /custom-enterprise.conf:/tmp/nginx/active-config/netalertx.conf:ro
# Test your plugin on the production container
# - /path/on/host:/app/front/plugins/custom
# Retain logs - comment out tmpfs /app/log if you want to retain logs between container restarts
# - /path/on/host/log:/app/log
# Retain logs - comment out tmpfs /tmp/log if you want to retain logs between container restarts
# - /path/on/host/log:/tmp/log
# Tempfs mounts for writable directories in a read-only container and improve system performance
# All mounts have noexec,nosuid,nodev for security purposes no devices, no suid/sgid and no execution of binaries
# async where possible for performance, sync where required for correctness
# tmpfs mounts for writable directories in a read-only container and improve system performance
# All writes now live under /tmp/* subdirectories which are created dynamically by entrypoint.d scripts
# uid=20211 and gid=20211 is the netalertx user inside the container
# mode=1700 gives rwx------ permissions to the netalertx user only
tmpfs:
# Speed up logging. This can be commented out to retain logs between container restarts
- "/app/log:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# Speed up API access as frontend/backend API is very chatty
- "/app/api:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,sync,noatime,nodiratime"
# Required for customization of the nginx listen addr/port without rebuilding the container
- "/services/config/nginx/conf.active:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# /services/config/nginx/conf.d is required for nginx and php to start
- "/services/run:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# /tmp is required by php for session save this should be reworked to /services/run/tmp
- "/tmp:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
environment:
LISTEN_ADDR: ${LISTEN_ADDR:-0.0.0.0} # Listen for connections on all interfaces
@@ -86,6 +71,5 @@ services:
# Always restart the container unless explicitly stopped
restart: unless-stopped
volumes: # Persistent volumes for configuration and database storage
netalertx_config: # Configuration files
netalertx_db: # Database files
volumes: # Persistent volume for configuration and database storage
netalertx_data:

View File

@@ -64,8 +64,9 @@ http://<server>:<GRAPHQL_PORT>/
* [Metrics](API_METRICS.md) Prometheus metrics and per-device status
* [Network Tools](API_NETTOOLS.md) Utilities like Wake-on-LAN, traceroute, nslookup, nmap, and internet info
* [Online History](API_ONLINEHISTORY.md) Online/offline device records
* [GraphQL](API_GRAPHQL.md) Advanced queries and filtering
* [GraphQL](API_GRAPHQL.md) Advanced queries and filtering for Devices, Settings and Language Strings
* [Sync](API_SYNC.md) Synchronization between multiple NetAlertX instances
* [Logs](API_LOGS.md) Purging of logs and adding to the event execution queue for user triggered events
* [DB query](API_DBQUERY.md) (⚠ Internal) - Low level database access - use other endpoints if possible
See [Testing](API_TESTS.md) for example requests and usage.

View File

@@ -1,9 +1,10 @@
# GraphQL API Endpoint
GraphQL queries are **read-optimized for speed**. Data may be slightly out of date until the file system cache refreshes. The GraphQL endpoints allows you to access the following objects:
GraphQL queries are **read-optimized for speed**. Data may be slightly out of date until the file system cache refreshes. The GraphQL endpoints allow you to access the following objects:
- Devices
- Settings
* Devices
* Settings
* Language Strings (LangStrings)
## Endpoints
@@ -190,11 +191,74 @@ curl 'http://host:GRAPHQL_PORT/graphql' \
}
```
---
## LangStrings Query
The **LangStrings query** provides access to localized strings. Supports filtering by `langCode` and `langStringKey`. If the requested string is missing or empty, you can optionally fallback to `en_us`.
### Sample Query
```graphql
query GetLangStrings {
langStrings(langCode: "de_de", langStringKey: "settings_other_scanners") {
langStrings {
langCode
langStringKey
langStringText
}
count
}
}
```
### Query Parameters
| Parameter | Type | Description |
| ---------------- | ------- | ---------------------------------------------------------------------------------------- |
| `langCode` | String | Optional language code (e.g., `en_us`, `de_de`). If omitted, all languages are returned. |
| `langStringKey` | String | Optional string key to retrieve a specific entry. |
| `fallback_to_en` | Boolean | Optional (default `true`). If `true`, empty or missing strings fallback to `en_us`. |
### `curl` Example
```sh
curl 'http://host:GRAPHQL_PORT/graphql' \
-X POST \
-H 'Authorization: Bearer API_TOKEN' \
-H 'Content-Type: application/json' \
--data '{
"query": "query GetLangStrings { langStrings(langCode: \"de_de\", langStringKey: \"settings_other_scanners\") { langStrings { langCode langStringKey langStringText } count } }"
}'
```
### Sample Response
```json
{
"data": {
"langStrings": {
"count": 1,
"langStrings": [
{
"langCode": "de_de",
"langStringKey": "settings_other_scanners",
"langStringText": "Other, non-device scanner plugins that are currently enabled." // falls back to en_us if empty
}
]
}
}
}
```
---
## Notes
* Device and settings queries can be combined in one request since GraphQL supports batching.
* Device, settings, and LangStrings queries can be combined in **one request** since GraphQL supports batching.
* The `fallback_to_en` feature ensures UI always has a value even if a translation is missing.
* Data is **cached in memory** per JSON file; changes to language or plugin files will only refresh after the cache detects a file modification.
* The `setOverriddenByEnv` flag helps identify setting values that are locked at container runtime.
* The schema is **read-only** — updates must be performed through other APIs or configuration management. See the other [API](API.md) endpoints for details.

179
docs/API_LOGS.md Normal file
View File

@@ -0,0 +1,179 @@
# Logs API Endpoints
Manage or purge application log files stored under `/app/log` and manage the execution queue. These endpoints are primarily used for maintenance tasks such as clearing accumulated logs or adding system actions without restarting the container.
Only specific, pre-approved log files can be purged for security and stability reasons.
---
## Delete (Purge) a Log File
* **DELETE** `/logs?file=<log_file>` → Purge the contents of an allowed log file.
**Query Parameter:**
* `file` → The name of the log file to purge (e.g., `app.log`, `stdout.log`)
**Allowed Files:**
```
app.log
app_front.log
IP_changes.log
stdout.log
stderr.log
app.php_errors.log
execution_queue.log
db_is_locked.log
```
**Authorization:**
Requires a valid API token in the `Authorization` header.
---
### `curl` Example (Success)
```sh
curl -X DELETE 'http://<server_ip>:<GRAPHQL_PORT>/logs?file=app.log' \
-H 'Authorization: Bearer <API_TOKEN>' \
-H 'Accept: application/json'
```
**Response:**
```json
{
"success": true,
"message": "[clean_log] File app.log purged successfully"
}
```
---
### `curl` Example (Not Allowed)
```sh
curl -X DELETE 'http://<server_ip>:<GRAPHQL_PORT>/logs?file=not_allowed.log' \
-H 'Authorization: Bearer <API_TOKEN>' \
-H 'Accept: application/json'
```
**Response:**
```json
{
"success": false,
"message": "[clean_log] File not_allowed.log is not allowed to be purged"
}
```
---
### `curl` Example (Unauthorized)
```sh
curl -X DELETE 'http://<server_ip>:<GRAPHQL_PORT>/logs?file=app.log' \
-H 'Accept: application/json'
```
**Response:**
```json
{
"error": "Forbidden"
}
```
---
## Add an Action to the Execution Queue
* **POST** `/logs/add-to-execution-queue` → Add a system action to the execution queue.
**Request Body (JSON):**
```json
{
"action": "update_api|devices"
}
```
**Authorization:**
Requires a valid API token in the `Authorization` header.
---
### `curl` Example (Success)
The below will update the API cache for Devices
```sh
curl -X POST 'http://<server_ip>:<GRAPHQL_PORT>/logs/add-to-execution-queue' \
-H 'Authorization: Bearer <API_TOKEN>' \
-H 'Content-Type: application/json' \
--data '{"action": "update_api|devices"}'
```
**Response:**
```json
{
"success": true,
"message": "[UserEventsQueueInstance] Action \"update_api|devices\" added to the execution queue."
}
```
---
### `curl` Example (Missing Parameter)
```sh
curl -X POST 'http://<server_ip>:<GRAPHQL_PORT>/logs/add-to-execution-queue' \
-H 'Authorization: Bearer <API_TOKEN>' \
-H 'Content-Type: application/json' \
--data '{}'
```
**Response:**
```json
{
"success": false,
"message": "Missing parameters",
"error": "Missing required 'action' field in JSON body"
}
```
---
### `curl` Example (Unauthorized)
```sh
curl -X POST 'http://<server_ip>:<GRAPHQL_PORT>/logs/add-to-execution-queue' \
-H 'Content-Type: application/json' \
--data '{"action": "update_api|devices"}'
```
**Response:**
```json
{
"error": "Forbidden"
}
```
---
## Notes
* Only predefined files in `/app/log` can be purged — arbitrary paths are **not permitted**.
* When a log file is purged:
* Its content is replaced with a short marker text: `"File manually purged"`.
* A backend log entry is created via `mylog()`.
* A frontend notification is generated via `write_notification()`.
* Execution queue actions are appended to `execution_queue.log` and can be processed asynchronously by background tasks or workflows.
* Unauthorized or invalid attempts are safely logged and rejected.
* For advanced log retrieval, analysis, or structured querying, use the frontend log viewer.
* Always ensure that sensitive or production logs are handled carefully — purging cannot be undone.

View File

@@ -141,7 +141,7 @@ The endpoints are updated when objects in the API endpoints are changed.
### Location of the endpoints
In the container, these files are located under the `/app/api/` folder. You can access them via the `/php/server/query_json.php?file=user_notifications.json` endpoint.
In the container, these files are located under the API directory (default: `/tmp/api/`, configurable via `NETALERTX_API` environment variable). You can access them via the `/php/server/query_json.php?file=user_notifications.json` endpoint.
### Available endpoints
@@ -332,7 +332,7 @@ Grafana template sample: [Download json](./samples/API/Grafana_Dashboard.json)
## API Endpoint: /log files
This API endpoint retrieves files from the `/app/log` folder.
This API endpoint retrieves files from the `/tmp/log` folder.
- Endpoint URL: `php/server/query_logs.php?file=<file name>`
- Host: `same as front end (web ui)`
@@ -357,7 +357,7 @@ This API endpoint retrieves files from the `/app/log` folder.
## API Endpoint: /config files
To retrieve files from the `/app/config` folder.
To retrieve files from the `/data/config` folder.
- Endpoint URL: `php/server/query_config.php?file=<file name>`
- Host: `same as front end (web ui)`

View File

@@ -1,7 +1,7 @@
# Backing Things Up
> [!NOTE]
> To back up 99% of your configuration, back up at least the `/app/config` folder.
> To back up 99% of your configuration, back up at least the `/data/config` folder.
> Database definitions can change between releases, so the safest method is to restore backups using the **same app version** they were taken from, then upgrade incrementally.
---
@@ -25,7 +25,7 @@ Understanding where your data is stored helps you plan your backup strategy.
### Core Configuration
Stored in `/app/config/app.conf`.
Stored in `/data/config/app.conf`.
This includes settings for:
* Notifications
@@ -37,7 +37,7 @@ This includes settings for:
### Device Data
Stored in `/app/config/devices_<timestamp>.csv` or `/app/config/devices.csv`, created by the [CSV Backup `CSVBCKP` Plugin](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/csv_backup).
Stored in `/data/config/devices_<timestamp>.csv` or `/data/config/devices.csv`, created by the [CSV Backup `CSVBCKP` Plugin](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/csv_backup).
Contains:
* Device names, icons, and categories
@@ -46,7 +46,7 @@ Contains:
### Historical Data
Stored in `/app/db/app.db` (see [Database Overview](./DATABASE.md)).
Stored in `/data/db/app.db` (see [Database Overview](./DATABASE.md)).
Contains:
* Plugin data and historical entries
@@ -77,13 +77,13 @@ You can also download the `app.conf` and `devices.csv` files from the **Maintena
### 💾 What to Back Up
* `/app/db/app.db` (uncorrupted)
* `/app/config/app.conf`
* `/app/config/workflows.json`
* `/data/db/app.db` (uncorrupted)
* `/data/config/app.conf`
* `/data/config/workflows.json`
### 📥 How to Restore
Map these files into your container as described in the [Setup documentation](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md#docker-paths).
Map these files into your container as described in the [Setup documentation](./DOCKER_INSTALLATION.md).
---
@@ -93,14 +93,14 @@ Map these files into your container as described in the [Setup documentation](ht
### 💾 What to Back Up
* `/app/config/app.conf`
* `/app/config/workflows.json`
* `/app/config/devices_<timestamp>.csv` (rename to `devices.csv` during restore)
* `/data/config/app.conf`
* `/data/config/workflows.json`
* `/data/config/devices_<timestamp>.csv` (rename to `devices.csv` during restore)
### 📥 How to Restore
1. Copy `app.conf` and `workflows.json` into `/app/config/`
2. Rename and place `devices_<timestamp>.csv``/app/config/devices.csv`
1. Copy `app.conf` and `workflows.json` into `/data/config/`
2. Rename and place `devices_<timestamp>.csv``/data/config/devices.csv`
3. Restore via the **Maintenance** section under *Devices → Bulk Editing*
This recovers nearly all configuration, workflows, and device metadata.
@@ -157,6 +157,6 @@ For users running NetAlertX via Docker, you can back up or restore directly from
## Summary
* Back up `/app/config` for configuration and devices; `/app/db` for history
* Back up `/data/config` for configuration and devices; `/data/db` for history
* Keep regular backups, especially before upgrades
* For Docker setups, use the lightweight `alpine`-based backup method for consistency and portability

View File

@@ -14,9 +14,9 @@ The app uses the MAC address as an unique identifier for devices. If a new MAC i
Make sure you [File permissions](./FILE_PERMISSIONS.md) are set correctly.
* If facing issues (AJAX errors, can't write to DB, empty screen, etc,) make sure permissions are set correctly, and check the logs under `/app/log`.
* To solve permission issues you can try setting the owner and group of the `app.db` by executing the following on the host system: `docker exec netalertx chown -R www-data:www-data /app/db/app.db`.
* If still facing issues, try to map the app.db file (⚠ not folder) to `:/app/db/app.db` (see [docker-compose Examples](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md#-docker-composeyml-examples) for details)
* If facing issues (AJAX errors, can't write to DB, empty screen, etc,) make sure permissions are set correctly, and check the logs under `/tmp/log`.
* To solve permission issues you can try setting the owner and group of the `app.db` by executing the following on the host system: `docker exec netalertx chown -R www-data:www-data /data/db/app.db`.
* If still facing issues, try to map the app.db file (⚠ not folder) to `:/data/db/app.db` (see [docker-compose Examples](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md#-docker-composeyml-examples) for details)
### Container restarts / crashes
@@ -49,7 +49,7 @@ Make sure that the subnet and interface in `SCAN_SUBNETS` are correct. If your d
### Losing my settings and devices after an update
If you lose your devices and/or settings after an update that means you don't have the `/app/db` and `/app/config` folders mapped to a permanent storage. That means every time you update these folders are re-created. Make sure you have the [volumes specified correctly](./DOCKER_COMPOSE.md) in your `docker-compose.yml` or run command.
If you lose your devices and/or settings after an update that means you don't have the `/data/db` and `/data/config` folders mapped to a permanent storage. That means every time you update these folders are re-created. Make sure you have the [volumes specified correctly](./DOCKER_COMPOSE.md) in your `docker-compose.yml` or run command.
### The application is slow

View File

@@ -27,7 +27,7 @@ Sometimes, the UI might not be accessible. In that case, you can access the logs
3. **Check the PHP application error log:**
```bash
cat /app/log/app.php_errors.log
cat /tmp/log/app.php_errors.log
```
These logs will help identify syntax issues, fatal errors, or startup problems when the UI fails to load properly.

View File

@@ -14,8 +14,8 @@ Start the container via the **terminal** with a command similar to this one:
```bash
docker run --rm --network=host \
-v local/path/netalertx/config:/app/config \
-v local/path/netalertx/db:/app/db \
-v local/path/netalertx/config:/data/config \
-v local/path/netalertx/db:/data/db \
-e TZ=Europe/Berlin \
-e PORT=20211 \
ghcr.io/jokob-sk/netalertx:latest

View File

@@ -1,5 +1,10 @@
# NetAlertX and Docker Compose
> [!WARNING]
> ⚠️ **Important:** The documentation has been recently updated and some instructions may have changed.
> If you are using the currently live production image, please follow the instructions on [Docker Hub](https://hub.docker.com/r/jokobsk/netalertx) for building and running the container.
> These docs reflect the latest development version and may differ from the production image.
Great care is taken to ensure NetAlertX meets the needs of everyone while being flexible enough for anyone. This document outlines how you can configure your docker-compose. There are many settings, so we recommend using the Baseline Docker Compose as-is, or modifying it for your system.Good care is taken to ensure NetAlertX meets the needs of everyone while being flexible enough for anyone. This document outlines how you can configure your docker-compose. There are many settings, so we recommend using the Baseline Docker Compose as-is, or modifying it for your system.
> [!NOTE]
@@ -26,61 +31,46 @@ services:
- NET_BIND_SERVICE # Required to bind to privileged ports (nbtscan)
volumes:
- type: volume # Persistent Docker-managed Named Volume for storage of config files
source: netalertx_config # the default name of the volume is netalertx_config
target: /app/config # inside the container mounted to /app/config
read_only: false # writable volume
# Example custom local folder called /home/user/netalertx_config
# - type: bind
# source: /home/user/netalertx_config
# target: /app/config
# read_only: false
# ... or use the alternative format
# - /home/user/netalertx_config:/app/config:rw
- type: volume # NetAlertX Database partiton
source: netalertx_db
target: /app/db
- type: volume # Persistent Docker-managed named volume for config + database
source: netalertx_data
target: /data # `/data/config` and `/data/db` live inside this mount
read_only: false
- type: volume # Future proof mount. During the migration to a
source: netalertx_data # future version, app and db will be migrated to
target: /data # the /data partition. This will reduce the
read_only: false # overhead and pain in the upcoming migration.
# Example custom local folder called /home/user/netalertx_data
# - type: bind
# source: /home/user/netalertx_data
# target: /data
# read_only: false
# ... or use the alternative format
# - /home/user/netalertx_data:/data:rw
- type: bind # Bind mount for timezone consistency
source: /etc/localtime
source: /etc/localtime # Alternatively add environment TZ: America/New York
target: /etc/localtime
read_only: true
# Mount your DHCP server file into NetAlertX for a plugin to access
# - path/on/host/to/dhcp.file:/resources/dhcp.file
# Retain logs - comment out tmpfs /app/log if you want to retain logs between container restarts
# - /path/on/host/log:/app/log
# Tempfs mounts for writable directories in a read-only container and improve system performance
# All mounts have noexec,nosuid,nodev for security purposes no devices, no suid/sgid and no execution of binaries
# async where possible for performance, sync where required for correctness
# tmpfs mount consolidates writable state for a read-only container and improves performance
# uid=20211 and gid=20211 is the netalertx user inside the container
# mode=1700 gives rwx------ permissions to the netalertx user only
# mode=1700 grants rwx------ permissions to the netalertx user only
tmpfs:
# Speed up logging. This can be commented out to retain logs between container restarts
- "/app/log:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# Speed up API access as frontend/backend API is very chatty
- "/app/api:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,sync,noatime,nodiratime"
# Required for customization of the nginx listen addr/port without rebuilding the container
- "/services/config/nginx/conf.active:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# /services/config/nginx/conf.d is required for nginx and php to start
- "/services/run:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# /tmp is required by php for session save this should be reworked to /services/run/tmp
- "/tmp:uid=2Key-Value Pairs: 20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# Comment out to retain logs between container restarts - this has a server performance impact.
- "/tmp:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# Retain logs - comment out tmpfs /tmp if you want to retain logs between container restarts
# Please note if you remove the /tmp mount, you must create and maintain sub-folder mounts.
# - /path/on/host/log:/tmp/log
# - "/tmp/api:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# - "/tmp/nginx:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# - "/tmp/run:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
environment:
LISTEN_ADDR: ${LISTEN_ADDR:-0.0.0.0} # Listen for connections on all interfaces
PORT: ${PORT:-20211} # Application port
GRAPHQL_PORT: ${GRAPHQL_PORT:-20212} # GraphQL API port (passed into APP_CONF_OVERRIDE at runtime)
NETALERTX_DEBUG: ${NETALERTX_DEBUG:-0} # 0=kill all services and restart if any dies. 1 keeps running dead services.
# NETALERTX_DEBUG: ${NETALERTX_DEBUG:-0} # 0=kill all services and restart if any dies. 1 keeps running dead services.
# Resource limits to prevent resource exhaustion
mem_limit: 2048m # Maximum memory usage
@@ -96,10 +86,8 @@ services:
# Always restart the container unless explicitly stopped
restart: unless-stopped
volumes: # Persistent volumes for configuration and database storage
netalertx_config: # Configuration files
netalertx_db: # Database files
netalertx_data: # For future config/db upgrade
volumes: # Persistent volume for configuration and database storage
netalertx_data:
```
Run or re-run it:
@@ -158,8 +146,8 @@ However, if you prefer to have direct, file-level access to your configuration f
```yaml
...
volumes:
- netalertx_config:/app/config:rw #short-form volume (no /path is a short volume)
- netalertx_db:/app/db:rw
- netalertx_config:/data/config:rw #short-form volume (no /path is a short volume)
- netalertx_db:/data/db:rw
...
```
@@ -169,14 +157,14 @@ Make sure to replace `/home/adam/netalertx-files` with your actual path. The for
```yaml
...
volumes:
# - netalertx_config:/app/config:rw
# - netalertx_db:/app/db:rw
- /home/adam/netalertx-files/config:/app/config:rw
- /home/adam/netalertx-files/db:/app/db:rw
# - netalertx_config:/data/config:rw
# - netalertx_db:/data/db:rw
- /home/adam/netalertx-files/config:/data/config:rw
- /home/adam/netalertx-files/db:/data/db:rw
...
```
Now, any files created by NetAlertX in `/app/config` will appear in your `/home/adam/netalertx-files/config` folder.
Now, any files created by NetAlertX in `/data/config` will appear in your `/home/adam/netalertx-files/config` folder.
This same method works for mounting other things, like custom plugins or enterprise NGINX files, as shown in the commented-out examples in the baseline file.
@@ -243,4 +231,4 @@ networks:
outside:
external:
name: "host"
```
```

View File

@@ -6,7 +6,7 @@
# NetAlertX - Network scanner & notification framework
| [📑 Docker guide](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md) | [🚀 Releases](https://github.com/jokob-sk/NetAlertX/releases) | [📚 Docs](https://jokob-sk.github.io/NetAlertX/) | [🔌 Plugins](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md) | [🤖 Ask AI](https://gurubase.io/g/netalertx)
| [📑 Docker guide](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_INSTALLATION.md) | [🚀 Releases](https://github.com/jokob-sk/NetAlertX/releases) | [📚 Docs](https://jokob-sk.github.io/NetAlertX/) | [🔌 Plugins](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md) | [🤖 Ask AI](https://gurubase.io/g/netalertx)
|----------------------| ----------------------| ----------------------| ----------------------| ----------------------|
<a href="https://raw.githubusercontent.com/jokob-sk/NetAlertX/main/docs/img/GENERAL/github_social_image.jpg" target="_blank">
@@ -25,9 +25,9 @@ Head to [https://netalertx.com/](https://netalertx.com/) for more gifs and scree
```yaml
docker run -d --rm --network=host \
-v local_path/config:/app/config \
-v local_path/db:/app/db \
--mount type=tmpfs,target=/app/api \
-v local_path/config:/data/config \
-v local_path/db:/data/db \
--mount type=tmpfs,target=/tmp/api \
-e PUID=200 -e PGID=300 \
-e TZ=Europe/Berlin \
-e PORT=20211 \
@@ -58,10 +58,10 @@ See alternative [docked-compose examples](https://github.com/jokob-sk/NetAlertX/
| Required | Path | Description |
| :------------- | :------------- | :-------------|
| ✅ | `:/app/config` | Folder which will contain the `app.conf` & `devices.csv` ([read about devices.csv](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEVICES_BULK_EDITING.md)) files |
| ✅ | `:/app/db` | Folder which will contain the `app.db` database file |
| | `:/app/log` | Logs folder useful for debugging if you have issues setting up the container |
| | `:/app/api` | A simple [API endpoint](https://github.com/jokob-sk/NetAlertX/blob/main/docs/API.md) containing static (but regularly updated) json and other files. |
| ✅ | `:/data/config` | Folder which will contain the `app.conf` & `devices.csv` ([read about devices.csv](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEVICES_BULK_EDITING.md)) files |
| ✅ | `:/data/db` | Folder which will contain the `app.db` database file |
| | `:/tmp/log` | Logs folder useful for debugging if you have issues setting up the container |
| | `:/tmp/api` | A simple [API endpoint](https://github.com/jokob-sk/NetAlertX/blob/main/docs/API.md) containing static (but regularly updated) json and other files. Path configurable via `NETALERTX_API` environment variable. |
| | `:/app/front/plugins/<plugin>/ignore_plugin` | Map a file `ignore_plugin` to ignore a plugin. Plugins can be soft-disabled via settings. More in the [Plugin docs](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md). |
| | `:/etc/resolv.conf` | Use a custom `resolv.conf` file for [better name resolution](https://github.com/jokob-sk/NetAlertX/blob/main/docs/REVERSE_DNS.md). |
@@ -70,7 +70,7 @@ See alternative [docked-compose examples](https://github.com/jokob-sk/NetAlertX/
### Initial setup
- If unavailable, the app generates a default `app.conf` and `app.db` file on the first run.
- The preferred way is to manage the configuration via the Settings section in the UI, if UI is inaccessible you can modify [app.conf](https://github.com/jokob-sk/NetAlertX/tree/main/back) in the `/app/config/` folder directly
- The preferred way is to manage the configuration via the Settings section in the UI, if UI is inaccessible you can modify [app.conf](https://github.com/jokob-sk/NetAlertX/tree/main/back) in the `/data/config/` folder directly
#### Setting up scanners

View File

@@ -1,5 +1,10 @@
# The NetAlertX Container Operator's Guide
> [!WARNING]
> ⚠️ **Important:** The documentation has been recently updated and some instructions may have changed.
> If you are using the currently live production image, please follow the instructions on [Docker Hub](https://hub.docker.com/r/jokobsk/netalertx) for building and running the container.
> These docs reflect the latest development version and may differ from the production image.
This guide assumes you are starting with the official `docker-compose.yml` file provided with the project. We strongly recommend you start with or migrate to this file as your baseline and modify it to suit your specific needs (e.g., changing file paths). While there are many ways to configure NetAlertX, the default file is designed to meet the mandatory security baseline with layer-2 networking capabilities while operating securely and without startup warnings.
This guide provides direct, concise solutions for common NetAlertX administrative tasks. It is structured to help you identify a problem, implement the solution, and understand the details.
@@ -46,13 +51,13 @@ You want to edit your `app.conf` and other configuration files directly from you
volumes:
# - type: volume
# source: netalertx_config
# target: /app/config
# target: /data/config
# read_only: false
...
# Example custom local folder called /data/netalertx_config
- type: bind
source: /data/netalertx_config
target: /app/config
target: /data/config
read_only: false
...
```
@@ -65,7 +70,7 @@ You want to edit your `app.conf` and other configuration files directly from you
### About This Method
This replaces the Docker-managed volume with a "bind mount." This is a direct mapping between a folder on your host computer (`/data/netalertx_config`) and a folder inside the container (`/app/config`), allowing you to edit the files directly.
This replaces the Docker-managed volume with a "bind mount." This is a direct mapping between a folder on your host computer (`/data/netalertx_config`) and a folder inside the container (`/data/config`), allowing you to edit the files directly.
---
@@ -92,13 +97,13 @@ You are currently using a local folder (bind mount) for your configuration (e.g.
volumes:
- type: volume
source: netalertx_config
target: /app/config
target: /data/config
read_only: false
...
# Example custom local folder called /data/netalertx_config
# - type: bind
# source: /data/netalertx_config
# target: /app/config
# target: /data/config
# read_only: false
...
```
@@ -144,7 +149,7 @@ You need to override the default Nginx configuration to add features like LDAP,
```yaml
...
# Use a custom Enterprise-configured nginx config for ldap or other settings
- /data/my-netalertx.conf:/services/config/nginx/conf.active/netalertx.conf:ro
- /data/my-netalertx.conf:/tmp/nginx/active-config/netalertx.conf:ro
...
```
4. Restart the container:

View File

@@ -45,18 +45,18 @@ services:
restart: unless-stopped
volumes:
- ${APP_FOLDER}/netalertx/config:/app/config
- ${APP_FOLDER}/netalertx/db:/app/db
- ${APP_FOLDER}/netalertx/config:/data/config
- ${APP_FOLDER}/netalertx/db:/data/db
# Optional: logs (useful for debugging setup issues, comment out for performance)
- ${APP_FOLDER}/netalertx/log:/app/log
- ${APP_FOLDER}/netalertx/log:/tmp/log
# API storage options:
# (Option 1) tmpfs (default, best performance)
- type: tmpfs
target: /app/api
target: /tmp/api
# (Option 2) bind mount (useful for debugging)
# - ${APP_FOLDER}/netalertx/api:/app/api
# - ${APP_FOLDER}/netalertx/api:/tmp/api
environment:
- TZ=${TZ}

View File

@@ -44,9 +44,9 @@ services:
ports:
- 20211:20211
volumes:
- /mnt/YOUR_SERVER/netalertx/config:/app/config:rw
- /mnt/YOUR_SERVER/netalertx/db:/netalertx/app/db:rw
- /mnt/YOUR_SERVER/netalertx/logs:/netalertx/app/log:rw
- /mnt/YOUR_SERVER/netalertx/config:/data/config:rw
- /mnt/YOUR_SERVER/netalertx/db:/netalertx/data/db:rw
- /mnt/YOUR_SERVER/netalertx/logs:/netalertx/tmp/log:rw
environment:
- TZ=Europe/London
- PORT=20211

View File

@@ -11,13 +11,15 @@ NetAlertX requires certain paths to be writable at runtime. These paths should b
| Path | Purpose | Notes |
| ------------------------------------ | ----------------------------------- | ------------------------------------------------------ |
| `/app/config` | Application configuration | Persistent volume recommended |
| `/app/db` | Database files | Persistent volume recommended |
| `/app/log` | Logs | Can be `tmpfs` for speed or host volume to retain logs |
| `/app/api` | API cache | Use `tmpfs` for faster access |
| `/services/config/nginx/conf.active` | Active nginx configuration override | `tmpfs` recommended or customized file mounted |
| `/services/run` | Runtime directories for nginx & PHP | `tmpfs` required |
| `/tmp` | PHP session save directory | `tmpfs` required |
| `/data/config` | Application configuration | Persistent volume recommended |
| `/data/db` | Database files | Persistent volume recommended |
| `/tmp/log` | Logs | Lives under `/tmp`; optional host bind to retain logs |
| `/tmp/api` | API cache | Subdirectory of `/tmp` |
| `/tmp/nginx/active-config` | Active nginx configuration override | Mount `/tmp` (or override specific file) |
| `/tmp/run` | Runtime directories for nginx & PHP | Subdirectory of `/tmp` |
| `/tmp` | PHP session save directory | Backed by `tmpfs` for runtime writes |
> Mounting `/tmp` as `tmpfs` automatically covers all of its subdirectories (`log`, `api`, `run`, `nginx/active-config`, etc.).
> All these paths will have **UID 20211 / GID 20211** inside the container. Files on the host will appear owned by `20211:20211`.
@@ -33,8 +35,8 @@ Sometimes, permission issues arise if your existing host directories were create
```bash
docker run -it --rm --name netalertx --user "0" \
-v local/path/config:/app/config \
-v local/path/db:/app/db \
-v local/path/config:/data/config \
-v local/path/db:/data/db \
ghcr.io/jokob-sk/netalertx:latest
```
@@ -60,16 +62,12 @@ services:
- NET_BIND_SERVICE
restart: unless-stopped
volumes:
- local/path/config:/app/config
- local/path/db:/app/db
- local/path/config:/data/config
- local/path/db:/data/db
environment:
- TZ=Europe/Berlin
- PORT=20211
tmpfs:
- "/app/log:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
- "/app/api:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,sync,noatime,nodiratime"
- "/services/config/nginx/conf.active:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
- "/services/run:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
tmpfs:
- "/tmp:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
```

View File

@@ -4,10 +4,10 @@
NetAlertX can be installed several ways. The best supported option is Docker, followed by a supervised Home Assistant instance, as an Unraid app, and lastly, on bare metal.
- [[Installation] Docker (recommended)](./INSTALLATION_DOCKER.md)
- [[Installation] Docker (recommended)](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_INSTALLATION.md)
- [[Installation] Home Assistant](https://github.com/alexbelgium/hassio-addons/tree/master/netalertx)
- [[Installation] Unraid App](https://unraid.net/community/apps)
- [[Installation] Bare metal (experimental - looking for maintainers)](./HW_INSTALL.md)
- [[Installation] Bare metal (experimental - looking for maintainers)](https://github.com/jokob-sk/NetAlertX/blob/main/docs/HW_INSTALL.md)
## Help

View File

@@ -9,7 +9,7 @@ NetAlertX comes with several logs that help to identify application issues. Thes
You can find most of the logs exposed in the UI under _Maintenance -> Logs_.
If the UI is inaccessible, you can access them under `/app/log`.
If the UI is inaccessible, you can access them under `/tmp/log`.
![Logs](./img/LOGGING/maintenance_logs.png)
@@ -52,18 +52,18 @@ The default logs are erased every time the container restarts because they are s
2. Edit your `docker-compose.yml` file:
* **Comment out** the `/app/log` line under the `tmpfs:` section.
* **Comment out** the `/tmp/log` line under the `tmpfs:` section.
* **Uncomment** the "Retain logs" line under the `volumes:` section and set your desired host path.
```yaml
...
tmpfs:
# - "/app/log:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# - "/tmp/log:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
...
volumes:
...
# Retain logs - comment out tmpfs /app/log if you want to retain logs between container restarts
- /home/adam/netalertx_logs:/app/log
# Retain logs - comment out tmpfs /tmp/log if you want to retain logs between container restarts
- /home/adam/netalertx_logs:/tmp/log
...
```
3. Restart the container:
@@ -72,4 +72,4 @@ The default logs are erased every time the container restarts because they are s
docker-compose up -d
```
This change stops Docker from mounting a temporary in-memory volume at `/app/log`. Instead, it "bind mounts" a persistent folder from your host computer (e.g., `/data/netalertx_logs`) to that *same location* inside the container.
This change stops Docker from mounting a temporary in-memory volume at `/tmp/log`. Instead, it "bind mounts" a persistent folder from your host computer (e.g., `/data/netalertx_logs`) to that *same location* inside the container.

View File

@@ -1,5 +1,11 @@
# Migration
> [!WARNING]
> ⚠️ **Important:** The documentation has been recently updated and some instructions may have changed.
> If you are using the currently live production image, please follow the instructions on [Docker Hub](https://hub.docker.com/r/jokobsk/netalertx) for building and running the container.
> These docs reflect the latest development version and may differ from the production image.
When upgrading from older versions of NetAlertX (or PiAlert by jokob-sk), follow the migration steps below to ensure your data and configuration are properly transferred.
> [!TIP]
@@ -37,7 +43,7 @@ A banner message will appear at the top of the web UI reminding you to update yo
> [!TIP]
> If you have trouble accessing past backups, config or database files you can copy them into the newly mapped directories, for example by running this command in the container: `cp -r /app/config /home/pi/pialert/config/old_backup_files`. This should create a folder in the `config` directory called `old_backup_files` containing all the files in that location. Another approach is to map the old location and the new one at the same time to copy things over.
> If you have trouble accessing past backups, config or database files you can copy them into the newly mapped directories, for example by running this command in the container: `cp -r /data/config /home/pi/pialert/config/old_backup_files`. This should create a folder in the `config` directory called `old_backup_files` containing all the files in that location. Another approach is to map the old location and the new one at the same time to copy things over.
#### New Docker mount locations
@@ -45,8 +51,8 @@ The internal application path in the container has changed from `/home/pi/pialer
| Old mount point | New mount point |
|----------------------|---------------|
| `/home/pi/pialert/config` | `/app/config` |
| `/home/pi/pialert/db` | `/app/db` |
| `/home/pi/pialert/config` | `/data/config` |
| `/home/pi/pialert/db` | `/data/db` |
If you were mounting files directly, please note the file names have changed:
@@ -98,10 +104,10 @@ services:
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config:/app/config # 🆕 This has changed
- local/path/db:/app/db # 🆕 This has changed
- local/path/config:/data/config # 🆕 This has changed
- local/path/db:/data/db # 🆕 This has changed
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/app/log # 🆕 This has changed
- local/path/logs:/tmp/log # 🆕 This has changed
environment:
- TZ=Europe/Berlin
- PORT=20211
@@ -144,10 +150,10 @@ services:
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config/app.conf:/app/config/app.conf # 🆕 This has changed
- local/path/db/app.db:/app/db/app.db # 🆕 This has changed
- local/path/config/app.conf:/data/config/app.conf # 🆕 This has changed
- local/path/db/app.db:/data/db/app.db # 🆕 This has changed
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/app/log # 🆕 This has changed
- local/path/logs:/tmp/log # 🆕 This has changed
environment:
- TZ=Europe/Berlin
- PORT=20211
@@ -184,10 +190,10 @@ services:
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config:/app/config
- local/path/db:/app/db
- local/path/config:/data/config
- local/path/db:/data/db
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/app/log
- local/path/logs:/tmp/log
environment:
- TZ=Europe/Berlin
- PORT=20211
@@ -201,10 +207,10 @@ services:
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config:/app/config
- local/path/db:/app/db
- local/path/config:/data/config
- local/path/db:/data/db
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/app/log
- local/path/logs:/tmp/log
environment:
- TZ=Europe/Berlin
- PORT=20211
@@ -228,10 +234,10 @@ services:
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config:/app/config
- local/path/db:/app/db
- local/path/config:/data/config
- local/path/db:/data/db
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/app/log
- local/path/logs:/tmp/log
environment:
- TZ=Europe/Berlin
- PORT=20211
@@ -247,8 +253,8 @@ services:
```sh
docker run -it --rm --name netalertx --user "0" \
-v local/path/config:/app/config \
-v local/path/db:/app/db \
-v local/path/config:/data/config \
-v local/path/db:/data/db \
ghcr.io/jokob-sk/netalertx:latest
```
@@ -267,24 +273,16 @@ services:
- NET_BIND_SERVICE # 🆕 New line
restart: unless-stopped
volumes:
- local/path/config:/app/config
- local/path/db:/app/db
- local/path/config:/data/config
- local/path/db:/data/db
# (optional) useful for debugging if you have issues setting up the container
#- local/path/logs:/app/log
#- local/path/logs:/tmp/log
environment:
- TZ=Europe/Berlin
- PORT=20211
# 🆕 New "tmpfs" section START 🔽
tmpfs:
# Speed up logging. This can be commented out to retain logs between container restarts
- "/app/log:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# Speed up API access as frontend/backend API is very chatty
- "/app/api:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,sync,noatime,nodiratime"
# Required for customization of the nginx listen addr/port without rebuilding the container
- "/services/config/nginx/conf.active:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# /services/config/nginx/conf.d is required for nginx and php to start
- "/services/run:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# /tmp is required by php for session save this should be reworked to /services/run/tmp
tmpfs:
# All writable runtime state resides under /tmp; comment out to persist logs between restarts
- "/tmp:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# 🆕 New "tmpfs" section END 🔼
```

View File

@@ -44,14 +44,19 @@ In Notification Processing settings, you can specify blanket rules. These allow
1. Notify on (`NTFPRCS_INCLUDED_SECTIONS`) allows you to specify which events trigger notifications. Usual setups will have `new_devices`, `down_devices`, and possibly `down_reconnected` set. Including `plugin` (dependenton the Plugin `<plugin>_WATCH` and `<plugin>_REPORT_ON` settings) and `events` (dependent on the on-device **Alert Events** setting) might be too noisy for most setups. More info in the [NTFPRCS plugin](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/notification_processing/README.md) on what events these selections include.
2. Alert down after (`NTFPRCS_alert_down_time`) is useful if you want to wait for some time before the system sends out a down notification for a device. This is related to the on-device **Alert down** setting and only devices with this checked will trigger a down notification.
3. A filter to allow you to set device-specific exceptions to New devices being added to the app.
4. A filter to allow you to set device-specific exceptions to generated Events.
## Ignoring devices 🔕
You can filter out unwanted notifications globally. This could be because of a misbehaving device (GoogleNest/GoogleHub (See also [ARPSAN docs and the `--exclude-broadcast` flag](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/arp_scan#ip-flipping-on-google-nest-devices))) which flips between IP addresses, or because you want to ignore new device notifications of a certain pattern.
1. Events Filter (`NTFPRCS_event_condition`) - Filter out Events from notifications.
2. New Devices Filter (`NTFPRCS_new_dev_condition`) - Filter out New Devices from notifications, but log and keep a new device in the system.
## Ignoring devices 💻
![Ignoring new devices](./img/NOTIFICATIONS/NEWDEV_ignores.png)
You can completely ignore detected devices globally. This could be because your instance detects docker containers, you want to ignore devices from a specific manufacturer via MAC rules or you want to ignore devices on a specific IP range.
1. Ignored MACs (`NEWDEV_ignored_MACs`) - List of MACs to ignore.
2. Ignored IPs (`NEWDEV_ignored_IPs`) - List of IPs to ignore.
2. Ignored IPs (`NEWDEV_ignored_IPs`) - List of IPs to ignore.

View File

@@ -62,7 +62,7 @@ For example, the **ICMP plugin** allows you to specify a regular expression to s
## Storing Temporary Files in Memory
On systems with slower I/O speeds, you can optimize performance by storing temporary files in memory. This primarily applies to the `/app/api` and `/app/log` folders.
On systems with slower I/O speeds, you can optimize performance by storing temporary files in memory. This primarily applies to the API directory (default: `/tmp/api`, configurable via `NETALERTX_API`) and `/tmp/log` folders.
Using `tmpfs` reduces disk writes and improves performance. However, it should be **disabled** if persistent logs or API data storage are required.
@@ -80,15 +80,15 @@ services:
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config:/app/config
- local/path/db:/app/db
- local/path/config:/data/config
- local/path/db:/data/db
# (Optional) Useful for debugging setup issues
- local/path/logs:/app/log
- local/path/logs:/tmp/log
# (API: OPTION 1) Store temporary files in memory (recommended for performance)
- type: tmpfs # ◀ 🔺
target: /app/api # ◀ 🔺
target: /tmp/api # ◀ 🔺
# (API: OPTION 2) Store API data on disk (useful for debugging)
# - local/path/api:/app/api
# - local/path/api:/tmp/api
environment:
- TZ=Europe/Berlin
- PORT=20211

View File

@@ -1,146 +1,192 @@
## config.json Lifecycle in NetAlertX
# Plugins Implementation Details
This document describes on a high level how `config.json` is read, processed, and used by the NetAlertX core and plugins. It also outlines the plugin output contract and the main plugin types.
Plugins provide data to the NetAlertX core, which processes it to detect changes, discover new devices, raise alerts, and apply heuristics.
> [!NOTE]
> For a deep-dive on the specific configuration options and sections of the `config.json` plugin manifest, consult the [Plugins Development Guide](PLUGINS_DEV.md).
---
## Overview: Plugin Data Flow
1. Each plugin runs on a defined schedule.
2. Aligning all plugin schedules is recommended so they execute in the same loop.
3. During execution, all plugins write their collected data into the **`CurrentScan`** table.
4. After all plugins complete, the `CurrentScan` table is evaluated to detect **new devices**, **changes**, and **triggers**.
Although plugins run independently, they contribute to the shared `CurrentScan` table.
To inspect its contents, set `LOG_LEVEL=trace` and check for the log section:
```
================ CurrentScan table content ================
```
---
## `config.json` Lifecycle
This section outlines how each plugins `config.json` manifest is read, validated, and used by the core and plugins.
It also describes plugin output expectations and the main plugin categories.
> [!TIP]
> For detailed schema and examples, see the [Plugin Development Guide](PLUGINS_DEV.md).
---
### 1. Loading
* On startup, the app core loads `config.json` for each plugin.
* The `config.json` represents a plugin manifest, that contains metadata and runtime settings.
* On startup, the core loads `config.json` for each plugin.
* The file acts as a **plugin manifest**, defining metadata, runtime configuration, and database mappings.
---
### 2. Validation
* The core checks that each required settings key (such as `RUN`) for a plugin exists.
* Invalid or missing values may be replaced with defaults, or the plugin may be disabled.
* The core validates required keys (for example, `RUN`).
* Missing or invalid entries may be replaced with defaults or cause the plugin to be disabled.
---
### 3. Preparation
* The plugins settings (paths, commands, parameters) are prepared.
* Database mappings (`mapped_to_table`, `database_column_definitions`) for data ingestion into the core app are parsed.
* Plugin parameters (paths, commands, and options) are prepared for execution.
* Database mappings (`mapped_to_table`, `database_column_definitions`) are parsed to define how data integrates with the main app.
---
### 4. Execution
* Plugins can be run at different core app execution points, such as on schedule, once on start, after a notification, etc.
* At runtime, the scheduler triggers plugins according to their `interval`.
* The plugin executes its command or script.
* Plugins may run:
* On a fixed schedule.
* Once at startup.
* After a notification or other trigger.
* The scheduler executes plugins according to their `interval`.
---
### 5. Parsing
* Plugin output is expected in **pipe (`|`)-delimited format**.
* The core parses lines into fields, matching the **plugin interface contract**.
* Plugin output must be **pipe-delimited (`|`)**.
* The core parses each output line following the **Plugin Interface Contract**, splitting and mapping fields accordingly.
---
### 6. Mapping
* Each parsed field is moved into the `Plugins_` database tables and can be mapped into a configured database table.
* Controlled by `database_column_definitions` and `mapped_to_table`.
* Example: `Object_PrimaryID → Devices.MAC`.
* Parsed fields are inserted into the plugins `Plugins_*` table.
* Data can be mapped into other tables (e.g., `Devices`, `CurrentScan`) as defined by:
* `database_column_definitions`
* `mapped_to_table`
**Example:** `Object_PrimaryID → devMAC`
---
### 6a. Plugin Output Contract
Each plugin must output results in the **plugin interface contract format**, pipe (`|`)-delimited values, in the column order described under [Plugin Interface Contract](PLUGINS_DEV.md)
All plugins must follow the **Plugin Interface Contract** defined in `PLUGINS_DEV.md`.
Output values are pipe-delimited in a fixed order.
#### IDs
#### Identifiers
* `Object_PrimaryID` and `Object_SecondaryID` identify the record (e.g. `MAC|IP`).
* `Object_PrimaryID` and `Object_SecondaryID` uniquely identify records (for example, `MAC|IP`).
#### **Watched values (`Watched_Value14`)**
#### Watched Values (`Watched_Value14`)
* Used by the core to detect changes between runs.
* Changes here can trigger **notifications**.
* Used by the core to detect changes between runs.
* Changes in these fields can trigger notifications.
#### **Extra value (`Extra`)**
#### Extra Field (`Extra`)
* Optional, extra field.
* Stored in the database but **not used for alerts**.
* Optional additional value.
* Stored in the database but not used for alerts.
#### **Helper values (`Helper_Value13`)**
#### Helper Values (`Helper_Value13`)
* Added for cases where more than IDs + watched + extra are needed.
* Can be made visible in the UI.
* Stored in the database but **not used for alerts**.
* Optional auxiliary data (for display or plugin logic).
* Stored but not alert-triggering.
#### **Mapping matters**
#### Mapping
* While the plugin output is free-form, the `database_column_definitions` and `mapped_to_table` settings in `config.json` determine the **target columns and data types** in NetAlertX.
* While the output format is flexible, the plugins manifest determines the destination and type of each field.
---
### 7. Persistence
* Data is upserted into the database.
* Conflicts are resolved using `Object_PrimaryID` + `Object_SecondaryID`.
* Parsed data is **upserted** into the database.
* Conflicts are resolved using the combined key: `Object_PrimaryID + Object_SecondaryID`.
---
### 8. Plugin Types and Expected Outputs
## Plugin Categories
Beyond the `data_source` setting, plugins fall into functional categories. Each has its own input requirements and output expectations:
Plugins fall into several functional categories depending on their purpose and expected outputs.
#### **Device discovery plugins**
### 1. Device Discovery Plugins
* **Inputs:** `N/A`, subnet, or API for discovery service, or similar.
* **Outputs:** At minimum `MAC` and `IP` that results in a new or updated device records in the `Devices` table.
* **Mapping:** Must be mapped to the `CurrentScan` table via `database_column_definitions` and `data_filters`.
* **Examples:** ARP-scan, NMAP device discovery (e.g., `ARPSCAN`, `NMAPDEV`).
#### **Device-data enrichment plugins**
* **Inputs:** Device identifier (usually `MAC`, `IP`).
* **Outputs:** Additional data for that device (e.g. open ports).
* **Mapping:** Controlled via `database_column_definitions` and `data_filters`.
* **Examples:** Ports, MQTT messages (e.g., `NMAP`, `MQTT`)
#### **Name resolver plugins**
* **Inputs:** Device identifiers (MAC, IP, or hostname).
* **Outputs:** Updated `devName` and `devFQDN` fields.
* **Mapping:** Not expected.
* **Note:** Currently requires **core app modification** to add new plugins, not fully driven by the plugins `config.json`.
* **Examples:** Avahiscan (e.g., `NBTSCAN`, `NSLOOKUP`).
#### **Generic plugins**
* **Inputs:** Whatever the script or query provides.
* **Outputs:** Data shown only in **Integrations → Plugins**, not tied to devices.
* **Mapping:** Not expected.
* **Examples:** External monitoring data (e.g., `INTRSPD`)
#### **Configuration-only plugins**
* **Inputs/Outputs:** None at runtime.
* **Mapping:** Not expected.
* **Examples:** Used to provide additional settings or execute scripts (e.g., `MAINT`, `CSVBCKP`).
* **Inputs:** None, subnet, or discovery API.
* **Outputs:** `MAC` and `IP` for new or updated device records in `Devices`.
* **Mapping:** Required usually into `CurrentScan`.
* **Examples:** `ARPSCAN`, `NMAPDEV`.
---
### 9. Post-Processing
### 2. Device Data Enrichment Plugins
* Notifications are generated if watched values change.
* UI is updated with new or updated records.
* All values that are configured to be shown in teh UI appear in the Plugins section.
* **Inputs:** Device identifiers (`MAC`, `IP`).
* **Outputs:** Additional metadata (for example, open ports or sensors).
* **Mapping:** Controlled via manifest definitions.
* **Examples:** `NMAP`, `MQTT`.
---
### 10. Summary
### 3. Name Resolver Plugins
The lifecycle of `config.json` entries is:
* **Inputs:** Device identifiers (`MAC`, `IP`, hostname`).
* **Outputs:** Updated `devName` and `devFQDN`.
* **Mapping:** Typically none.
* **Note:** Adding new resolvers currently requires a core change.
* **Examples:** `NBTSCAN`, `NSLOOKUP`.
---
### 4. Generic Plugins
* **Inputs:** Custom, based on the plugin logic or script.
* **Outputs:** Data displayed under **Integrations → Plugins** only.
* **Mapping:** Not required.
* **Examples:** `INTRSPD`, custom monitoring scripts.
---
### 5. Configuration-Only Plugins
* **Inputs/Outputs:** None at runtime.
* **Purpose:** Used for configuration or maintenance tasks.
* **Examples:** `MAINT`, `CSVBCKP`.
---
## Post-Processing
After persistence:
* The core generates notifications for any watched value changes.
* The UI updates with new or modified data.
* Plugins with UI-enabled data display under **Integrations → Plugins**.
---
## Summary
The lifecycle of a plugin configuration is:
**Load → Validate → Prepare → Execute → Parse → Map → Persist → Post-process**
Plugins must follow the **output contract**, and their category (discovery, specific, resolver, generic, config-only) defines what inputs they require and what outputs are expected.
Each plugin must:
* Follow the **output contract**.
* Declare its type and expected output structure.
* Define mappings and watched values clearly in `config.json`.

View File

@@ -13,7 +13,7 @@ There is also an in-app Help / FAQ section that should be answering frequently a
#### 🐳 Docker (Fully supported)
- The main installation method is as a [docker container - follow these instructions here](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md).
- The main installation method is as a [docker container - follow these instructions here](./DOCKER_INSTALLATION.md).
#### 💻 Bare-metal / On-server (Experimental/community supported 🧪)

View File

@@ -42,9 +42,9 @@ services:
image: "ghcr.io/jokob-sk/netalertx:latest"
restart: unless-stopped
volumes:
- /home/netalertx/config:/app/config
- /home/netalertx/db:/app/db
- /home/netalertx/log:/app/log
- /home/netalertx/config:/data/config
- /home/netalertx/db:/data/db
- /home/netalertx/log:/tmp/log
environment:
- TZ=Europe/Berlin
- PORT=20211
@@ -68,9 +68,9 @@ services:
image: "ghcr.io/jokob-sk/netalertx:latest"
restart: unless-stopped
volumes:
- ./config/app.conf:/app/config/app.conf
- ./db:/app/db
- ./log:/app/log
- ./config/app.conf:/data/config/app.conf
- ./db:/data/db
- ./log:/tmp/log
- ./config/resolv.conf:/etc/resolv.conf # Mapping the /resolv.conf file for better name resolution
environment:
- TZ=Europe/Berlin

View File

@@ -499,8 +499,8 @@ Mapping the updated file (on the local filesystem at `/appl/docker/netalertx/def
```bash
docker run -d --rm --network=host \
--name=netalertx \
-v /appl/docker/netalertx/config:/app/config \
-v /appl/docker/netalertx/db:/app/db \
-v /appl/docker/netalertx/config:/data/config \
-v /appl/docker/netalertx/db:/data/db \
-v /appl/docker/netalertx/default:/etc/nginx/sites-available/default \
-e TZ=Europe/Amsterdam \
-e PORT=20211 \

View File

@@ -48,7 +48,7 @@ Heres a breakdown of the defensive layers you get, right out of the box using
**Methodology:** All writable locations are treated as untrusted, temporary, and non-executable by default.
* **In-Memory Volatile Storage:** The `docker-compose.yml` configuration maps all temporary directories (e.g., `/app/log`, `/app/api`, `/tmp`) to in-memory `tmpfs` filesystems. They do not exist on the host's disk.
* **In-Memory Volatile Storage:** The `docker-compose.yml` configuration maps all temporary directories (e.g., `/tmp/log`, `/tmp/api`, `/tmp`) to in-memory `tmpfs` filesystems. They do not exist on the host's disk.
* **Volatile Data:** Because these locations exist only in RAM, their contents are **instantly and irrevocably erased** when the container is stopped. This provides a "self-cleaning" mechanism that purges any attacker-dropped files or payloads on every single restart.

View File

@@ -40,10 +40,10 @@ services:
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config:/app/config
- local/path/db:/app/db
- local/path/config:/data/config
- local/path/db:/data/db
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/app/log
- local/path/logs:/tmp/log
environment:
- TZ=Europe/Berlin
- PORT=20211
@@ -57,10 +57,10 @@ services:
```yaml
volumes:
- /volume1/app_storage/netalertx/config:/app/config
- /volume1/app_storage/netalertx/db:/app/db
- /volume1/app_storage/netalertx/config:/data/config
- /volume1/app_storage/netalertx/db:/data/db
# (optional) useful for debugging if you have issues setting up the container
# - local/path/logs:/app/log <- commented out with # ⚠
# - local/path/logs:/tmp/log <- commented out with # ⚠
```
![Adjusting docker-compose](./img/SYNOLOGY/08_Adjust_docker_compose_volumes.png)

View File

@@ -15,7 +15,7 @@ The **Web UI** is served by an **nginx** server, while the **API backend** runs
APP_CONF_OVERRIDE={"GRAPHQL_PORT":"20212"}
```
For more information, check the [Docker installation guide](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md).
For more information, check the [Docker installation guide](./DOCKER_INSTALLATION.md).
## Possible issues and troubleshooting
@@ -62,11 +62,11 @@ In the container execute and investigate:
`cat /var/log/nginx/error.log`
`cat /app/log/app.php_errors.log`
`cat /tmp/log/app.php_errors.log`
### 8. Make sure permissions are correct
> [!TIP]
> You can try to start the container without mapping the `/app/config` and `/app/db` dirs and if the UI shows up then the issue is most likely related to your file system permissions or file ownership.
> You can try to start the container without mapping the `/data/config` and `/data/db` dirs and if the UI shows up then the issue is most likely related to your file system permissions or file ownership.
Please read the [Permissions troubleshooting guide](./FILE_PERMISSIONS.md) and provide a screesnhot of the permissions and ownership in the `/app/db` and `app/config` directories.
Please read the [Permissions troubleshooting guide](./FILE_PERMISSIONS.md) and provide a screesnhot of the permissions and ownership in the `/data/db` and `app/config` directories.

View File

@@ -0,0 +1,32 @@
# Excessive Capabilities
## Issue Description
Excessive Linux capabilities are detected beyond the necessary NET_ADMIN, NET_BIND_SERVICE, and NET_RAW. This may indicate overly permissive container configuration.
## Security Ramifications
While the detected capabilities might not directly harm operation, running with more privileges than necessary increases the attack surface. If the container is compromised, additional capabilities could allow broader system access or privilege escalation.
## Why You're Seeing This Issue
This occurs when your Docker configuration grants more capabilities than required for network monitoring. The application only needs specific network-related capabilities for proper function.
## How to Correct the Issue
Limit capabilities to only those required:
- In docker-compose.yml, specify only needed caps:
```yaml
cap_add:
- NET_RAW
- NET_ADMIN
- NET_BIND_SERVICE
```
- Remove any unnecessary `--cap-add` or `--privileged` flags from docker run commands
## Additional Resources
Docker Compose setup can be complex. We recommend starting with the default docker-compose.yml as a base and modifying it incrementally.
For detailed Docker Compose configuration guidance, see: [DOCKER_COMPOSE.md](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_COMPOSE.md)

View File

@@ -0,0 +1,27 @@
# File Permission Issues
## Issue Description
NetAlertX cannot read from or write to critical configuration and database files. This prevents the application from saving data, logs, or configuration changes.
## Security Ramifications
Incorrect file permissions can expose sensitive configuration data or database contents to unauthorized access. Network monitoring tools handle sensitive information about devices on your network, and improper permissions could lead to information disclosure.
## Why You're Seeing This Issue
This occurs when the mounted volumes for configuration and database files don't have proper ownership or permissions set for the netalertx user (UID 20211). The container expects these files to be accessible by the service account, not root or other users.
## How to Correct the Issue
Fix permissions on the host system for the mounted directories:
- Ensure the config and database directories are owned by the netalertx user: `chown -R 20211:20211 /path/to/config /path/to/db`
- Set appropriate permissions: `chmod -R 755 /path/to/config /path/to/db` for directories, `chmod 644` for files
- Alternatively, restart the container with root privileges temporarily to allow automatic permission fixing, then switch back to the default user
## Additional Resources
Docker Compose setup can be complex. We recommend starting with the default docker-compose.yml as a base and modifying it incrementally.
For detailed Docker Compose configuration guidance, see: [DOCKER_COMPOSE.md](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_COMPOSE.md)

View File

@@ -0,0 +1,28 @@
# Incorrect Container User
## Issue Description
NetAlertX is running as UID:GID other than the expected 20211:20211. This bypasses hardened permissions, file ownership, and runtime isolation safeguards.
## Security Ramifications
The application is designed with security hardening that depends on running under a dedicated, non-privileged service account. Using a different user account can silently fail future upgrades and removes crucial isolation between the container and host system.
## Why You're Seeing This Issue
This occurs when you override the container's default user with custom `user:` directives in docker-compose.yml or `--user` flags in docker run commands. The container expects to run as the netalertx user for proper security isolation.
## How to Correct the Issue
Restore the container to the default user:
- Remove any `user:` overrides from docker-compose.yml
- Avoid `--user` flags in docker run commands
- Allow the container to run with its default UID:GID 20211:20211
- Recreate the container so volume ownership is reset automatically
## Additional Resources
Docker Compose setup can be complex. We recommend starting with the default docker-compose.yml as a base and modifying it incrementally.
For detailed Docker Compose configuration guidance, see: [DOCKER_COMPOSE.md](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_COMPOSE.md)

View File

@@ -0,0 +1,32 @@
# Missing Network Capabilities
## Issue Description
Raw network capabilities (NET_RAW, NET_ADMIN, NET_BIND_SERVICE) are missing. Tools that rely on these capabilities (e.g., nmap -sS, arp-scan, nbtscan) will not function.
## Security Ramifications
Network scanning and monitoring requires low-level network access that these capabilities provide. Without them, the application cannot perform essential functions like ARP scanning, port scanning, or passive network discovery, severely limiting its effectiveness.
## Why You're Seeing This Issue
This occurs when the container doesn't have the necessary Linux capabilities granted. Docker containers run with limited capabilities by default, and network monitoring tools need elevated network privileges.
## How to Correct the Issue
Add the required capabilities to your container:
- In docker-compose.yml:
```yaml
cap_add:
- NET_RAW
- NET_ADMIN
- NET_BIND_SERVICE
```
- For docker run: `--cap-add=NET_RAW --cap-add=NET_ADMIN --cap-add=NET_BIND_SERVICE`
## Additional Resources
Docker Compose setup can be complex. We recommend starting with the default docker-compose.yml as a base and modifying it incrementally.
For detailed Docker Compose configuration guidance, see: [DOCKER_COMPOSE.md](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_COMPOSE.md)

View File

@@ -0,0 +1,36 @@
# Mount Configuration Issues
## Issue Description
NetAlertX has detected configuration issues with your Docker volume mounts. These may include write permission problems, data loss risks, or performance concerns marked with ❌ in the table.
## Security Ramifications
Improper mount configurations can lead to data loss, performance degradation, or security vulnerabilities. For persistent data (database and configuration), using non-persistent storage like tmpfs can result in complete data loss on container restart. For temporary data, using persistent storage may unnecessarily expose sensitive logs or cache data.
## Why You're Seeing This Issue
This occurs when your Docker Compose or run configuration doesn't properly map host directories to container paths, or when the mounted volumes have incorrect permissions. The application requires specific paths to be writable for operation, and some paths should use persistent storage while others should be temporary.
## How to Correct the Issue
Review and correct your volume mounts in docker-compose.yml:
- Ensure `${NETALERTX_DB}` and `${NETALERTX_CONFIG}` use persistent host directories
- Ensure `${NETALERTX_API}`, `${NETALERTX_LOG}` have appropriate permissions
- Avoid mounting sensitive paths to non-persistent filesystems like tmpfs for critical data
- Use bind mounts with proper ownership (netalertx user: 20211:20211)
Example volume configuration:
```yaml
volumes:
- ./data/db:/data/db
- ./data/config:/data/config
- ./data/log:/tmp/log
```
## Additional Resources
Docker Compose setup can be complex. We recommend starting with the default docker-compose.yml as a base and modifying it incrementally.
For detailed Docker Compose configuration guidance, see: [DOCKER_COMPOSE.md](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_COMPOSE.md)

View File

@@ -0,0 +1,27 @@
# Network Mode Configuration
## Issue Description
NetAlertX is not running with `--network=host`. Bridge networking blocks passive discovery (ARP, NBNS, mDNS) and active scanning accuracy.
## Security Ramifications
Host networking is required for comprehensive network monitoring. Bridge mode isolates the container from raw network access needed for ARP scanning, passive discovery protocols, and accurate device detection. Without host networking, the application cannot fully monitor your network.
## Why You're Seeing This Issue
This occurs when your Docker configuration uses bridge networking instead of host networking. Network monitoring requires direct access to the host's network interfaces to perform passive discovery and active scanning.
## How to Correct the Issue
Enable host networking mode:
- In docker-compose.yml, add: `network_mode: host`
- For docker run, use: `--network=host`
- Ensure the container has required capabilities: `--cap-add=NET_RAW --cap-add=NET_ADMIN --cap-add=NET_BIND_SERVICE`
## Additional Resources
Docker Compose setup can be complex. We recommend starting with the default docker-compose.yml as a base and modifying it incrementally.
For detailed Docker Compose configuration guidance, see: [DOCKER_COMPOSE.md](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_COMPOSE.md)

View File

@@ -0,0 +1,36 @@
# Nginx Configuration Mount Issues
## Issue Description
You've configured a custom port for NetAlertX, but the required nginx configuration mount is missing or not writable. Without this mount, the container cannot apply your port changes and will fall back to the default port 20211.
## Security Ramifications
Running in read-only mode (as recommended) prevents the container from modifying its own nginx configuration. Without a writable mount, custom port configurations cannot be applied, potentially exposing the service on unintended ports or requiring fallback to defaults.
## Why You're Seeing This Issue
This occurs when you set a custom PORT environment variable (other than 20211) but haven't provided a writable mount for nginx configuration. The container needs to write custom nginx config files when running in read-only mode.
## How to Correct the Issue
If you want to use a custom port, create a bind mount for the nginx configuration:
- Create a directory on your host: `mkdir -p /path/to/nginx-config`
- Add to your docker-compose.yml:
```yaml
volumes:
- /path/to/nginx-config:/tmp/nginx/active-config
environment:
- PORT=your_custom_port
```
- Ensure it's owned by the netalertx user: `chown -R 20211:20211 /path/to/nginx-config`
- Set permissions: `chmod -R 700 /path/to/nginx-config`
If you don't need a custom port, simply omit the PORT environment variable and the container will use 20211 by default.
## Additional Resources
Docker Compose setup can be complex. We recommend starting with the default docker-compose.yml as a base and modifying it incrementally.
For detailed Docker Compose configuration guidance, see: [DOCKER_COMPOSE.md](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_COMPOSE.md)

View File

@@ -0,0 +1,86 @@
# Port Conflicts
## Issue Description
The configured application port (default 20211) or GraphQL API port (default 20212) is already in use by another service. This commonly occurs when you already have another NetAlertX instance running.
## Security Ramifications
Port conflicts prevent the application from starting properly, leaving network monitoring services unavailable. Running multiple instances on the same ports can also create configuration confusion and potential security issues if services are inadvertently exposed.
## Why You're Seeing This Issue
This error typically occurs when:
- **You already have NetAlertX running** - Another Docker container or devcontainer instance is using the default ports 20211 and 20212
- **Port conflicts with other services** - Other applications on your system are using these ports
- **Configuration error** - Both PORT and GRAPHQL_PORT environment variables are set to the same value
## How to Correct the Issue
### Check for Existing NetAlertX Instances
First, check if you already have NetAlertX running:
```bash
# Check for running NetAlertX containers
docker ps | grep netalertx
# Check for devcontainer processes
ps aux | grep netalertx
# Check what services are using the ports
netstat -tlnp | grep :20211
netstat -tlnp | grep :20212
```
### Stop Conflicting Instances
If you find another NetAlertX instance:
```bash
# Stop specific container
docker stop <container_name>
# Stop all NetAlertX containers
docker stop $(docker ps -q --filter ancestor=jokob-sk/netalertx)
# Stop devcontainer services
# Use VS Code command palette: "Dev Containers: Rebuild Container"
```
### Configure Different Ports
If you need multiple instances, configure unique ports:
```yaml
environment:
- PORT=20211 # Main application port
- GRAPHQL_PORT=20212 # GraphQL API port
```
For a second instance, use different ports:
```yaml
environment:
- PORT=20213 # Different main port
- GRAPHQL_PORT=20214 # Different API port
```
### Alternative: Use Different Container Names
When running multiple instances, use unique container names:
```yaml
services:
netalertx-primary:
# ... existing config
netalertx-secondary:
# ... config with different ports
```
## Additional Resources
Docker Compose setup can be complex. We recommend starting with the default docker-compose.yml as a base and modifying it incrementally.
For detailed Docker Compose configuration guidance, see: [DOCKER_COMPOSE.md](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_COMPOSE.md)

View File

@@ -0,0 +1,27 @@
# Read-Only Filesystem Mode
## Issue Description
The container is running as read-write instead of read-only mode. This reduces the security hardening of the appliance.
## Security Ramifications
Read-only root filesystem is a security best practice that prevents malicious modifications to the container's filesystem. Running read-write allows potential attackers to modify system files or persist malware within the container.
## Why You're Seeing This Issue
This occurs when the Docker configuration doesn't mount the root filesystem as read-only. The application is designed as a security appliance that should prevent filesystem modifications.
## How to Correct the Issue
Enable read-only mode:
- In docker-compose.yml, add: `read_only: true`
- For docker run, use: `--read-only`
- Ensure necessary directories are mounted as writable volumes (tmp, logs, etc.)
## Additional Resources
Docker Compose setup can be complex. We recommend starting with the default docker-compose.yml as a base and modifying it incrementally.
For detailed Docker Compose configuration guidance, see: [DOCKER_COMPOSE.md](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_COMPOSE.md)

View File

@@ -0,0 +1,29 @@
# Running as Root User
## Issue Description
NetAlertX has detected that the container is running with root privileges (UID 0). This configuration bypasses all built-in security hardening measures designed to protect your system.
## Security Ramifications
Running security-critical applications like network monitoring tools as root grants unrestricted access to your host system. A successful compromise here could jeopardize your entire infrastructure, including other containers, host services, and potentially your network.
## Why You're Seeing This Issue
This typically occurs when you've explicitly overridden the container's default user in your Docker configuration, such as using `user: root` or `--user 0:0` in docker-compose.yml or docker run commands. The application is designed to run under a dedicated, non-privileged service account for security.
## How to Correct the Issue
Switch to the dedicated 'netalertx' user by removing any custom user directives:
- Remove `user:` entries from your docker-compose.yml
- Avoid `--user` flags in docker run commands
- Ensure the container runs with the default UID 20211:20211
After making these changes, restart the container. The application will automatically adjust ownership of required directories.
## Additional Resources
Docker Compose setup can be complex. We recommend starting with the default docker-compose.yml as a base and modifying it incrementally.
For detailed Docker Compose configuration guidance, see: [DOCKER_COMPOSE.md](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DOCKER_COMPOSE.md)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -21,7 +21,7 @@ The app can be installed different ways, with the best support of the docker-bas
NetAlertX is fully supported in Docker environments, allowing for easy setup and configuration. Follow the official guide to get started:
- [Docker Installation Guide](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md)
- [Docker Installation Guide](./DOCKER_INSTALLATION.md)
This guide will take you through the process of setting up NetAlertX using Docker Compose or standalone Docker commands.

View File

@@ -15,9 +15,22 @@
<?php
require 'php/templates/header.php';
// check permissions
$dbPath = "../db/app.db";
$confPath = "../config/app.conf";
// Use environment-aware paths with fallback to legacy locations
$dbFolderPath = rtrim(getenv('NETALERTX_DB') ?: '/data/db', '/');
$configFolderPath = rtrim(getenv('NETALERTX_CONFIG') ?: '/data/config', '/');
$dbPath = $dbFolderPath . '/app.db';
$confPath = $configFolderPath . '/app.conf';
// Fallback to legacy paths if new locations don't exist
if (!file_exists($dbPath) && file_exists('../db/app.db')) {
$dbPath = '../db/app.db';
}
if (!file_exists($confPath) && file_exists('../config/app.conf')) {
$confPath = '../config/app.conf';
}
checkPermissions([$dbPath, $confPath]);
?>

View File

@@ -17,11 +17,12 @@
// Size and last mod of DB ------------------------------------------------------
$nax_db = str_replace('front', 'db', getcwd()).'/app.db';
$nax_wal = str_replace('front', 'db', getcwd()).'/app.db-wal';
$nax_db_size = number_format((filesize($nax_db) / 1000000),2,",",".") . ' MB';
$nax_wal_size = number_format((filesize($nax_wal) / 1000000),2,",",".") . ' MB';
$nax_db_mod = date ("F d Y H:i:s", filemtime($nax_db));
$dbBasePath = rtrim(getenv('NETALERTX_DB') ?: '/data/db', '/');
$nax_db = $dbBasePath . '/app.db';
$nax_wal = $dbBasePath . '/app.db-wal';
$nax_db_size = file_exists($nax_db) ? number_format((filesize($nax_db) / 1000000),2,",",".") . ' MB' : '0 MB';
$nax_wal_size = file_exists($nax_wal) ? number_format((filesize($nax_wal) / 1000000),2,",",".") . ' MB' : '0 MB';
$nax_db_mod = file_exists($nax_db) ? date ("F d Y H:i:s", filemtime($nax_db)) : 'N/A';
// Table sizes -----------------------------------------------------------------
@@ -334,7 +335,7 @@ $db->close();
var emptyArr = ['undefined', "", undefined, null];
var selectedTab = 'tab_DBTools_id';
initializeTabs();
// initializeTabs() is called in window.onload
// -----------------------------------------------------------
// delete devices with emty macs
@@ -704,7 +705,7 @@ function renderLogs(customData) {
window.onload = function asyncFooter() {
renderLogs();
// initializeTabs();
initializeTabs();
try {
$("#lastCommit").append('<a href="https://github.com/jokob-sk/NetAlertX/commits" target="_blank"><img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/jokob-sk/netalertx/main?logo=github"></a>');

View File

@@ -2,30 +2,60 @@
require '../server/init.php';
$logBasePath = rtrim(getenv('NETALERTX_LOG') ?: '/tmp/log', '/');
function resolveLogPath($path)
{
global $logBasePath;
if ($path === null || $path === '') {
return $path;
}
$placeholder = '__NETALERTX_LOG__';
if (strpos($path, $placeholder) === 0) {
return $logBasePath . substr($path, strlen($placeholder));
}
return $path;
}
//------------------------------------------------------------------------------
// check if authenticated
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
// Function to render the log area component
function renderLogArea($params) {
global $logBasePath;
$fileName = isset($params['fileName']) ? $params['fileName'] : '';
$filePath = isset($params['filePath']) ? $params['filePath'] : '';
$textAreaCssClass = isset($params['textAreaCssClass']) ? $params['textAreaCssClass'] : '';
$buttons = isset($params['buttons']) ? $params['buttons'] : [];
$content = "";
$fileSize = 0;
if (filesize($filePath) > 2000000) {
$filePath = resolveLogPath($filePath);
if (!is_file($filePath)) {
$content = "";
$fileSizeMb = 0.0;
} elseif (filesize($filePath) > 2000000) {
$content = file_get_contents($filePath, false, null, -2000000);
$fileSizeMb = filesize($filePath) / 1000000;
} else {
$content = file_get_contents($filePath);
$fileSizeMb = filesize($filePath) / 1000000;
}
// Prepare the download button HTML if filePath starts with /app
// Prepare the download button HTML if filePath resides under the active log base path
$downloadButtonHtml = '';
if (strpos($filePath, '/app') === 0) {
$logPrefix = $logBasePath . '/';
if ($logPrefix !== '/' && strpos($filePath, $logPrefix) === 0) {
$downloadName = basename($filePath);
$downloadButtonHtml = '
<span class="span-padding">
<a href="' . htmlspecialchars(str_replace('/app/log/', '/php/server/query_logs.php?file=', $filePath)) . '" target="_blank">
<a href="' . htmlspecialchars('/php/server/query_logs.php?file=' . rawurlencode($downloadName)) . '" target="_blank">
<i class="fa fa-download"></i>
</a>
</span>';
@@ -34,13 +64,7 @@ function renderLogArea($params) {
// Prepare buttons HTML
$buttonsHtml = '';
$totalButtons = count($buttons);
if ($totalButtons > 0) {
$colClass = 12 / $totalButtons;
// Use $colClass in your HTML generation or further logic
} else {
// Handle case where $buttons array is empty
$colClass = 12;
}
$colClass = $totalButtons > 0 ? (12 / $totalButtons) : 12;
foreach ($buttons as $button) {
$labelStringCode = isset($button['labelStringCode']) ? $button['labelStringCode'] : '';
@@ -52,8 +76,7 @@ function renderLogArea($params) {
</div>';
}
// Render the log area HTML
// Render HTML
$html = '
<div class="log-area box box-solid box-primary">
<div class="row logs-row col-sm-12 col-xs-12">
@@ -63,7 +86,7 @@ function renderLogArea($params) {
</div>
<div class="row logs-row">
<div class="log-file col-sm-6 col-xs-12">' . htmlspecialchars($filePath) . '
<div class="logs-size">' . number_format((filesize($filePath) / 1000000), 2, ",", ".") . ' MB'
<div class="logs-size">' . number_format($fileSizeMb, 2, ",", ".") . ' MB'
. $downloadButtonHtml .
'</div>
</div>

View File

@@ -10,8 +10,8 @@
"event": "askRestartBackend()"
}
],
"fileName": "app.log",
"filePath": "/app/log/app.log",
"fileName": "app.log",
"filePath": "__NETALERTX_LOG__/app.log",
"textAreaCssClass": "logs"
},
@@ -22,8 +22,8 @@
"event": "logManage('app_front.log', 'cleanLog')"
}
],
"fileName": "app_front.log",
"filePath": "/app/log/app_front.log",
"fileName": "app_front.log",
"filePath": "__NETALERTX_LOG__/app_front.log",
"textAreaCssClass": "logs logs-small"
},
{
@@ -33,8 +33,8 @@
"event": "logManage('app.php_errors.log', 'cleanLog')"
}
],
"fileName": "app.php_errors.log",
"filePath": "/app/log/app.php_errors.log",
"fileName": "app.php_errors.log",
"filePath": "__NETALERTX_LOG__/app.php_errors.log",
"textAreaCssClass": "logs logs-small"
},
{
@@ -44,15 +44,19 @@
"event": "logManage('execution_queue.log', 'cleanLog')"
}
],
"fileName": "execution_queue.log",
"filePath": "/app/log/execution_queue.log",
"fileName": "execution_queue.log",
"filePath": "__NETALERTX_LOG__/execution_queue.log",
"textAreaCssClass": "logs logs-small"
},
{
"buttons": [
{
"labelStringCode": "Maint_PurgeLog",
"event": "logManage('nginx-error.log', 'cleanLog')"
}
],
"fileName": "nginx/error.log",
"filePath": "/var/log/nginx/error.log",
"fileName": "nginx-error.log",
"filePath": "__NETALERTX_LOG__/nginx-error.log",
"textAreaCssClass": "logs logs-small"
},
{
@@ -62,8 +66,8 @@
"event": "logManage('db_is_locked.log', 'cleanLog')"
}
],
"fileName": "db_is_locked.log",
"filePath": "/app/log/db_is_locked.log",
"fileName": "db_is_locked.log",
"filePath": "__NETALERTX_LOG__/db_is_locked.log",
"textAreaCssClass": "logs logs-small"
},
{
@@ -73,8 +77,8 @@
"event": "logManage('stdout.log', 'cleanLog')"
}
],
"fileName": "stdout.log",
"filePath": "/app/log/stdout.log",
"fileName": "stdout.log",
"filePath": "__NETALERTX_LOG__/stdout.log",
"textAreaCssClass": "logs logs-small"
},
{
@@ -84,8 +88,30 @@
"event": "logManage('stderr.log', 'cleanLog')"
}
],
"fileName": "stderr.log",
"filePath": "/app/log/stderr.log",
"fileName": "stderr.log",
"filePath": "__NETALERTX_LOG__/stderr.log",
"textAreaCssClass": "logs logs-small"
},
{
"buttons": [
{
"labelStringCode": "Maint_PurgeLog",
"event": "logManage('IP_changes.log', 'cleanLog')"
}
],
"fileName": "IP_changes.log",
"filePath": "__NETALERTX_LOG__/IP_changes.log",
"textAreaCssClass": "logs logs-small"
},
{
"buttons": [
{
"labelStringCode": "Maint_PurgeLog",
"event": "logManage('crond.log', 'cleanLog')"
}
],
"fileName": "crond.log",
"filePath": "__NETALERTX_LOG__/crond.log",
"textAreaCssClass": "logs logs-small"
}
]

View File

@@ -13,8 +13,35 @@
// $DBFILE = dirname(__FILE__).'/../../../db/app.db';
// $DBFILE_LOCKED_FILE = dirname(__FILE__).'/../../../log/db_is_locked.log';
$scriptDir = realpath(dirname(__FILE__)); // Resolves symlinks to the actual physical path
$DBFILE = $scriptDir . '/../../../db/app.db';
$DBFILE_LOCKED_FILE = $scriptDir . '/../../../log/db_is_locked.log';
$legacyDbPath = $scriptDir . '/../../../db/app.db';
$legacyLogDir = $scriptDir . '/../../../log';
$dbFolderPath = rtrim(getenv('NETALERTX_DB') ?: '/data/db', '/');
$logFolderPath = rtrim(getenv('NETALERTX_LOG') ?: '/tmp/log', '/');
// Fallback to legacy layout if the new location is missing but the legacy file still exists
if (!is_dir($dbFolderPath) && file_exists($legacyDbPath)) {
$dbFolderPath = dirname($legacyDbPath);
}
if (!is_dir($dbFolderPath)) {
@mkdir($dbFolderPath, 0775, true);
}
$DBFILE = rtrim($dbFolderPath, '/') . '/app.db';
if (!file_exists($DBFILE) && file_exists($legacyDbPath)) {
$DBFILE = $legacyDbPath;
}
if (!is_dir($logFolderPath) && is_dir($legacyLogDir)) {
$logFolderPath = $legacyLogDir;
}
if (!is_dir($logFolderPath)) {
@mkdir($logFolderPath, 0775, true);
}
$DBFILE_LOCKED_FILE = rtrim($logFolderPath, '/') . '/db_is_locked.log';
//------------------------------------------------------------------------------
@@ -39,8 +66,10 @@ function SQLite3_connect($trytoreconnect = true, $retryCount = 0) {
if (!file_exists($DBFILE)) {
die("Database file not found: $DBFILE");
}
if (!file_exists(dirname($DBFILE_LOCKED_FILE))) {
die("Log directory not found: " . dirname($DBFILE_LOCKED_FILE));
$lockDir = dirname($DBFILE_LOCKED_FILE);
if (!is_dir($lockDir) && !@mkdir($lockDir, 0775, true)) {
die("Log directory not found and could not be created: $lockDir");
}
@@ -130,6 +159,7 @@ class CustomDatabaseWrapper {
$message = 'Error executing query (attempts: ' . $attempts . '), query: ' . $query;
// write_notification($message);
error_log("Query failed after {$this->maxRetries} attempts: " . $this->sqlite->lastErrorMsg());
return false;
}
public function query_log_add($query)
@@ -187,7 +217,7 @@ function OpenDB($DBPath = null) {
if (strlen($DBFILE) == 0) {
$message = 'Database not available';
echo '<script>alert('.$message.')</script>';
echo '<script>alert("'.$message.'")</script>';
write_notification($message);
die('<div style="padding-left:150px">'.$message.'</div>');
@@ -197,7 +227,7 @@ function OpenDB($DBPath = null) {
$db = new CustomDatabaseWrapper($DBFILE);
} catch (Exception $e) {
$message = "Error connecting to the database";
echo '<script>alert('.$message.'": ' . $e->getMessage() . '")</script>';
echo '<script>alert("'.$message.': '.$e->getMessage().'")</script>';
write_notification($message);
die('<div style="padding-left:150px">'.$message.'</div>');
}

View File

@@ -1,5 +1,6 @@
<?php
ini_set('error_log', '../../log/app.php_errors.log'); // initializing the app.php_errors.log file for the maintenance section
$logPath = rtrim(getenv('NETALERTX_LOG') ?: '/tmp/log', '/') . '/app.php_errors.log';
ini_set('error_log', $logPath); // initializing the app.php_errors.log file for the maintenance section
require dirname(__FILE__).'/../templates/globals.php';
require dirname(__FILE__).'/db.php';
require dirname(__FILE__).'/util.php';

View File

@@ -18,7 +18,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
// Check if file parameter is provided
if ($file) {
// Define the folder where files are located
$filePath = "/app/config/" . basename($file);
$configRoot = getenv('NETALERTX_CONFIG') ?: '/data/config';
$filePath = rtrim($configRoot, '/') . "/" . basename($file);
// Check if the file exists and is readable
if (file_exists($filePath) && is_readable($filePath)) {

View File

@@ -11,6 +11,8 @@ require dirname(__FILE__).'/../server/init.php';
//------------------------------------------------------------------------------
// Handle incoming requests
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$configRoot = getenv('NETALERTX_CONFIG') ?: '/data/config';
$apiRoot = getenv('NETALERTX_API') ?: '/tmp/api';
// Get query string parameter ?file=settings_table.json
$file = isset($_GET['file']) ? $_GET['file'] : null;
@@ -19,10 +21,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
// Define the folder where files are located
if ($file == "workflows.json")
{
$filePath = "/app/config/" . basename($file);
$filePath = rtrim($configRoot, '/') . "/" . basename($file);
} else
{
$filePath = "/app/api/" . basename($file);
$filePath = rtrim($apiRoot, '/') . "/" . basename($file);
}
// Check if the file exists
@@ -59,7 +61,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
}
$file = $_GET['file'];
$filePath = "/app/config/" . basename($file);
$configRoot = getenv('NETALERTX_CONFIG') ?: '/data/config';
$filePath = rtrim($configRoot, '/') . "/" . basename($file);
// Save new workflows.json (replace existing content)
if (file_put_contents($filePath, json_encode($decodedData, JSON_PRETTY_PRINT))) {

View File

@@ -16,8 +16,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
// Check if file parameter is provided
if ($file) {
// Define the folder where files are located
$filePath = "/app/log/" . basename($file);
// Define the folder where files are located
$logBasePath = rtrim(getenv('NETALERTX_LOG') ?: '/tmp/log', '/');
$filePath = $logBasePath . '/' . basename($file);
// Check if the file exists
if (file_exists($filePath)) {

View File

@@ -11,6 +11,7 @@
require dirname(__FILE__).'/../templates/globals.php';
require dirname(__FILE__).'/../templates/skinUI.php';
//------------------------------------------------------------------------------
// check if authenticated
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
@@ -176,7 +177,10 @@ function checkPermissions($files)
}
// ----------------------------------------------------------------------------------------
// 🔺----- API ENDPOINTS SUPERSEDED -----🔺
// check server/api_server/api_server_start.py for equivalents
// equivalent: /messaging/in-app/write
// 🔺----- API ENDPOINTS SUPERSEDED -----🔺
function displayMessage($message, $logAlert = FALSE, $logConsole = TRUE, $logFile = TRUE, $logEcho = FALSE)
{
global $logFolderPath, $log_file, $timestamp;
@@ -234,7 +238,10 @@ function displayMessage($message, $logAlert = FALSE, $logConsole = TRUE, $logFil
}
// 🔺----- API ENDPOINTS SUPERSEDED -----🔺
// check server/api_server/api_server_start.py for equivalents
// equivalent: /logs/add-to-execution-queue
// 🔺----- API ENDPOINTS SUPERSEDED -----🔺
// ----------------------------------------------------------------------------------------
// Adds an action to perform into the execution_queue.log file
function addToExecutionQueue($action)
@@ -257,13 +264,17 @@ function addToExecutionQueue($action)
// ----------------------------------------------------------------------------------------
// 🔺----- API ENDPOINTS SUPERSEDED -----🔺
// check server/api_server/api_server_start.py for equivalents
// equivalent: /logs DELETE
// 🔺----- API ENDPOINTS SUPERSEDED -----🔺
function cleanLog($logFile)
{
global $logFolderPath, $timestamp;
$path = "";
$allowedFiles = ['app.log', 'app_front.log', 'IP_changes.log', 'stdout.log', 'stderr.log', 'app.php_errors.log', 'execution_queue.log', 'db_is_locked.log'];
$allowedFiles = ['app.log', 'app_front.log', 'IP_changes.log', 'stdout.log', 'stderr.log', 'app.php_errors.log', 'execution_queue.log', 'db_is_locked.log', 'nginx-error.log', 'crond.log'];
if(in_array($logFile, $allowedFiles))
{
@@ -312,7 +323,7 @@ function saveSettings()
$txt = $txt."#-----------------AUTOGENERATED FILE-----------------#\n";
$txt = $txt."# #\n";
$txt = $txt."# Generated: ".$timestamp." #\n";
$txt = $txt."# Generated: ".$timestamp." #\n";
$txt = $txt."# #\n";
$txt = $txt."# Config file for the LAN intruder detection app: #\n";
$txt = $txt."# https://github.com/jokob-sk/NetAlertX #\n";
@@ -321,7 +332,12 @@ function saveSettings()
// collect all groups
$decodedSettings = json_decode($SETTINGS, true);
$decodedSettings = json_decode((string)$SETTINGS, true);
if ($decodedSettings === null) {
echo "Error: Invalid JSON in settings data.";
return;
}
foreach ($decodedSettings as $setting) {
if( in_array($setting[0] , $groups) == false) {
@@ -418,6 +434,10 @@ function saveSettings()
}
// -------------------------------------------------------------------------------------------
// 🔺----- API ENDPOINTS SUPERSEDED -----🔺
// check server/api_server/api_server_start.py for equivalents
// equivalent: /graphql LangStrings endpoint
// 🔺----- API ENDPOINTS SUPERSEDED -----🔺
function getString ($setKey, $default) {
$result = lang($setKey);
@@ -430,9 +450,14 @@ function getString ($setKey, $default) {
return $default;
}
// -------------------------------------------------------------------------------------------
// 🔺----- API ENDPOINTS SUPERSEDED -----🔺
// check server/api_server/api_server_start.py for equivalents
// equivalent: /settings/<key>
// 🔺----- API ENDPOINTS SUPERSEDED -----🔺
function getSettingValue($setKey) {
// Define the JSON endpoint URL
$url = dirname(__FILE__).'/../../../api/table_settings.json';
// Define the JSON endpoint URL
$apiRoot = rtrim(getenv('NETALERTX_API') ?: '/tmp/api', '/');
$url = $apiRoot . '/table_settings.json';
// Fetch the JSON data
$json = file_get_contents($url);

View File

@@ -7,6 +7,11 @@
require dirname(__FILE__).'/../templates/globals.php';
function get_notification_store_path(): string {
$apiRoot = getenv('NETALERTX_API') ?: '/tmp/api';
return rtrim($apiRoot, '/') . '/user_notifications.json';
}
//------------------------------------------------------------------------------
// check if authenticated
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
@@ -69,7 +74,7 @@ function generate_guid() {
// ----------------------------------------------------------------------------------------
// Logs a notification in in-app notification system
function write_notification($content, $level = "interrupt") {
$NOTIFICATION_API_FILE = '/app/api/user_notifications.json';
$NOTIFICATION_API_FILE = get_notification_store_path();
// Generate GUID
$guid = generate_guid();
@@ -102,7 +107,7 @@ function write_notification($content, $level = "interrupt") {
// ----------------------------------------------------------------------------------------
// Removes a notification based on GUID
function remove_notification($guid) {
$NOTIFICATION_API_FILE = '/app/api/user_notifications.json';
$NOTIFICATION_API_FILE = get_notification_store_path();
// Read existing notifications
$notifications = json_decode(file_get_contents($NOTIFICATION_API_FILE), true);
@@ -119,7 +124,7 @@ function remove_notification($guid) {
// ----------------------------------------------------------------------------------------
// Deletes all notifications
function notifications_clear() {
$NOTIFICATION_API_FILE = '/app/api/user_notifications.json';
$NOTIFICATION_API_FILE = get_notification_store_path();
// Clear notifications by writing an empty array to the file
file_put_contents($NOTIFICATION_API_FILE, json_encode(array()));
@@ -128,7 +133,7 @@ function notifications_clear() {
// ----------------------------------------------------------------------------------------
// Mark a notification read based on GUID
function mark_notification_as_read($guid) {
$NOTIFICATION_API_FILE = '/app/api/user_notifications.json';
$NOTIFICATION_API_FILE = get_notification_store_path();
$max_attempts = 3;
$attempts = 0;
@@ -177,7 +182,7 @@ function notifications_mark_all_read() {
// ----------------------------------------------------------------------------------------
function get_unread_notifications() {
$NOTIFICATION_API_FILE = '/app/api/user_notifications.json';
$NOTIFICATION_API_FILE = get_notification_store_path();
// Read existing notifications
if (file_exists($NOTIFICATION_API_FILE) && is_readable($NOTIFICATION_API_FILE)) {

View File

@@ -15,7 +15,19 @@ if (isset($_SESSION["login"]) && $_SESSION["login"] == 1) {
// Check if a valid cookie is present
$CookieSaveLoginName = "NetAlertX_SaveLogin";
$config_file = "../../../config/app.conf"; // depends on where this file is called from
// Use environment-aware config path
$configFolderPath = rtrim(getenv('NETALERTX_CONFIG') ?: '/data/config', '/');
$config_file = $configFolderPath . '/app.conf';
// Fallback to legacy path if new location doesn't exist
if (!file_exists($config_file)) {
$legacyPath = "../../../config/app.conf";
if (file_exists($legacyPath)) {
$config_file = $legacyPath;
}
}
$config_file_lines = file($config_file);
$config_file_lines = array_values(preg_grep('/^SETPWD_password.*=/', $config_file_lines));
$password_line = explode("'", $config_file_lines[0]);

View File

@@ -4,8 +4,8 @@
// ## Global constants and TimeZone processing
// ######################################################################
$configFolderPath = "/app/config/";
$logFolderPath = "/app/log/";
$configFolderPath = rtrim(getenv('NETALERTX_CONFIG') ?: '/data/config', '/') . '/';
$logFolderPath = rtrim(getenv('NETALERTX_LOG') ?: '/tmp/log', '/') . '/';
$config_file = "app.conf";
$workflows_file = "workflows.json";

View File

@@ -674,7 +674,7 @@
"Systeminfo_System_Uptime": "Uptime:",
"Systeminfo_This_Client": "Aquest Client",
"Systeminfo_USB_Devices": "Dispositius USB",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ S'han detectat punts muntatge antics. Ves a <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">aquesta guia</a> per migrar les noves <code>/app/config</code> i <code>/app/db</code> carpetes i al <code>netalertx</code> contenidor.",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ S'han detectat punts muntatge antics. Ves a <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">aquesta guia</a> per migrar les noves <code>/data/config</code> i <code>/data/db</code> carpetes i al <code>netalertx</code> contenidor.",
"TIMEZONE_description": "Fus horari per mostrar les estadístiques correctament. <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\" rel=\"nofollow\">aquí</a>.",
"TIMEZONE_name": "Fus horari",
"UI_DEV_SECTIONS_description": "Seleccioneu quins elements de la interfície d'usuari per ocultar a les pàgines de dispositius.",

16
front/php/templates/language/cs_cz.json Executable file → Normal file
View File

@@ -9,7 +9,7 @@
"About_Exit": "Odhlásit",
"About_Title": "Scanner síťové bezpečnosti a framework pro upozornění",
"AppEvents_AppEventProcessed": "Zpracováno",
"AppEvents_DateTimeCreated": "Objeveno",
"AppEvents_DateTimeCreated": "Zaznamenáno",
"AppEvents_Extra": "Extra",
"AppEvents_GUID": "",
"AppEvents_Helper1": "",
@@ -25,8 +25,8 @@
"AppEvents_ObjectStatus": "",
"AppEvents_ObjectStatusColumn": "",
"AppEvents_ObjectType": "",
"AppEvents_Plugin": "",
"AppEvents_Type": "",
"AppEvents_Plugin": "Zásuvný modul",
"AppEvents_Type": "Typ",
"BackDevDetail_Actions_Ask_Run": "",
"BackDevDetail_Actions_Not_Registered": "",
"BackDevDetail_Actions_Title_Run": "Spustit akci",
@@ -74,7 +74,7 @@
"DevDetail_DisplayFields_Title": "",
"DevDetail_EveandAl_AlertAllEvents": "",
"DevDetail_EveandAl_AlertDown": "",
"DevDetail_EveandAl_Archived": "",
"DevDetail_EveandAl_Archived": "Archivováno",
"DevDetail_EveandAl_NewDevice": "",
"DevDetail_EveandAl_NewDevice_Tooltip": "",
"DevDetail_EveandAl_RandomMAC": "",
@@ -85,10 +85,10 @@
"DevDetail_EveandAl_Title": "",
"DevDetail_Events_CheckBox": "",
"DevDetail_GoToNetworkNode": "",
"DevDetail_Icon": "",
"DevDetail_Icon": "Ikona",
"DevDetail_Icon_Descr": "",
"DevDetail_Loading": "",
"DevDetail_MainInfo_Comments": "",
"DevDetail_Loading": "Načítání…",
"DevDetail_MainInfo_Comments": "Komentáře",
"DevDetail_MainInfo_Favorite": "",
"DevDetail_MainInfo_Group": "",
"DevDetail_MainInfo_Location": "",
@@ -761,4 +761,4 @@
"settings_system_label": "",
"settings_update_item_warning": "",
"test_event_tooltip": ""
}
}

4
front/php/templates/language/de_de.json Executable file → Normal file
View File

@@ -9,7 +9,7 @@
"About_Exit": "Abmelden",
"About_Title": "Netzwerksicherheitsscanner und Benachrichtigungsframework",
"AppEvents_AppEventProcessed": "Verarbeitet",
"AppEvents_DateTimeCreated": "Entdeckt am",
"AppEvents_DateTimeCreated": "Protokolliert",
"AppEvents_Extra": "Extra",
"AppEvents_GUID": "Anwendungsereignis-GUID",
"AppEvents_Helper1": "Helfer 1",
@@ -834,4 +834,4 @@
"settings_system_label": "System",
"settings_update_item_warning": "",
"test_event_tooltip": "Speichere die Änderungen, bevor Sie die Einstellungen testen."
}
}

View File

@@ -674,7 +674,7 @@
"Systeminfo_System_Uptime": "Uptime:",
"Systeminfo_This_Client": "This Client",
"Systeminfo_USB_Devices": "USB devices",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Old mount locations detected. Follow <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">this guide</a> to migrate to the new <code>/app/config</code> and <code>/app/db</code> folders and the <code>netalertx</code> container.",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Old mount locations detected. Follow <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">this guide</a> to migrate to the new <code>/data/config</code> and <code>/data/db</code> folders and the <code>netalertx</code> container.",
"TIMEZONE_description": "Time zone to display stats correctly. Find your time zone <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\" rel=\"nofollow\">here</a>.",
"TIMEZONE_name": "Time zone",
"UI_DEV_SECTIONS_description": "Select which UI elements to hide in the devices pages.",

View File

@@ -734,7 +734,7 @@
"Systeminfo_System_Uptime": "Tiempo de actividad:",
"Systeminfo_This_Client": "Este cliente",
"Systeminfo_USB_Devices": "Dispositivos USB",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Ubicaciones de montaje antiguas detectadas. Siga <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">esta guía</a> para migrar a las nuevas carpetas <code>/app/config</code> y <code>/app/db</code> y el contenedor <code>netalertx</code>.",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Ubicaciones de montaje antiguas detectadas. Siga <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">esta guía</a> para migrar a las nuevas carpetas <code>/data/config</code> y <code>/data/db</code> y el contenedor <code>netalertx</code>.",
"TIMEZONE_description": "La zona horaria para mostrar las estadísticas correctamente. Encuentra tu zona horaria <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\" rel=\"nofollow\">aquí</a>.",
"TIMEZONE_name": "Zona horaria",
"UI_DEV_SECTIONS_description": "Seleccione los elementos de la interfaz de usuario que desea ocultar en las páginas de dispositivos.",

4
front/php/templates/language/fa_fa.json Executable file → Normal file
View File

@@ -1,6 +1,6 @@
{
"API_CUSTOM_SQL_description": "",
"API_CUSTOM_SQL_name": "",
"API_CUSTOM_SQL_name": "مقصده سفارشی",
"API_TOKEN_description": "",
"API_TOKEN_name": "",
"API_display_name": "",
@@ -761,4 +761,4 @@
"settings_system_label": "",
"settings_update_item_warning": "",
"test_event_tooltip": ""
}
}

View File

@@ -674,7 +674,7 @@
"Systeminfo_System_Uptime": "Durée d'activité:",
"Systeminfo_This_Client": "Ce client",
"Systeminfo_USB_Devices": "Appareils USB",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Emplacement de point de montage obsolète détecté. Suivez <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">ce guide</a> pour migrer vers les nouveaux dossiers <code>/app/config</code> and <code>/app/db</code> et le container <code>netalertx</code>.",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Emplacement de point de montage obsolète détecté. Suivez <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">ce guide</a> pour migrer vers les nouveaux dossiers <code>/data/config</code> and <code>/data/db</code> et le container <code>netalertx</code>.",
"TIMEZONE_description": "Fuseau horaire pour afficher correctement les statistiques. Trouvez votre fuseau horaire <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\" rel=\"nofollow\">ici</a>.",
"TIMEZONE_name": "Fuseau horaire",
"UI_DEV_SECTIONS_description": "Slecetionnez quels éléments de l'interface graphique masquer dans les pages des appareils.",

View File

@@ -674,7 +674,7 @@
"Systeminfo_System_Uptime": "Tempo di attività:",
"Systeminfo_This_Client": "Questo client",
"Systeminfo_USB_Devices": "Dispositivi USB",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Rilevate vecchie posizioni di montaggio. Segui <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">questa guida</a> per migrare alle nuove cartelle <code> /app/config</code> e <code>/app/db</code> e al contenitore <code>netalertx</code>.",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Rilevate vecchie posizioni di montaggio. Segui <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">questa guida</a> per migrare alle nuove cartelle <code> /data/config</code> e <code>/data/db</code> e al contenitore <code>netalertx</code>.",
"TIMEZONE_description": "Fuso orario per visualizzare correttamente le statistiche. Trova il tuo fuso orario <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\" rel=\"nofollow\">qui</a>.",
"TIMEZONE_name": "Fuso orario",
"UI_DEV_SECTIONS_description": "Seleziona quali elementi della UI nascondere nella pagina dei dispositivi.",

View File

@@ -674,7 +674,7 @@
"Systeminfo_System_Uptime": "Oppetid:",
"Systeminfo_This_Client": "Denne klienten",
"Systeminfo_USB_Devices": "USB-enheter",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Eldre Mount-lokasjoner oppdaget. Følg <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">denne guiden</a> for å migrere til den nye <code>/app/config</code> og <code>/app/db </code> mappene og <code>netalertx</code> containeren.",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Eldre Mount-lokasjoner oppdaget. Følg <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">denne guiden</a> for å migrere til den nye <code>/data/config</code> og <code>/data/db </code> mappene og <code>netalertx</code> containeren.",
"TIMEZONE_description": "Tidssone for å vise statistikk riktig. Finn din tidssone <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\" rel=\"nofollow\">her</a>.",
"TIMEZONE_name": "Tidssone",
"UI_DEV_SECTIONS_description": "Velg hvilke UI -elementer du vil skjule på enhetssiden.",

View File

@@ -674,7 +674,7 @@
"Systeminfo_System_Uptime": "Czas pracy:",
"Systeminfo_This_Client": "Ten klient",
"Systeminfo_USB_Devices": "Urządzenia USB",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Wykryto stare lokalizacje montowania. Skorzystaj z <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">tego przewodnika</a>, aby przeprowadzić migrację do nowych folderów <code>/app/config</code> i <code>/app/db</code> oraz kontenera <code>netalertx</code>.",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Wykryto stare lokalizacje montowania. Skorzystaj z <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">tego przewodnika</a>, aby przeprowadzić migrację do nowych folderów <code>/data/config</code> i <code>/data/db</code> oraz kontenera <code>netalertx</code>.",
"TIMEZONE_description": "Ustaw strefę czasową, aby statystyki były wyświetlane poprawnie. Znajdź swoją strefę czasową <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\" rel=\"nofollow\">tutaj</a>.",
"TIMEZONE_name": "Strefa czasowa",
"UI_DEV_SECTIONS_description": "Wybierz elementy interfejsu użytkownika (UI), które chcesz ukryć na stronach Urządzeń.",

14
front/php/templates/language/ru_ru.json Executable file → Normal file
View File

@@ -1,8 +1,8 @@
{
"API_CUSTOM_SQL_description": "Вы можете указать собственный SQL-запрос, который будет генерировать файл JSON, а затем предоставлять его через конечную точку файла <a href=\"/php/server/query_json.php?file=table_custom_endpoint.json\" target=\"_blank\"><code>table_custom_endpoint.json</code></a>.",
"API_CUSTOM_SQL_name": "Пользовательская конечная точка",
"API_TOKEN_description": "API-токен для безопасной связи. Сгенерируйте его или введите любое значение. Он передается в заголовке запроса и используется в плагине <code>SYNC</code>, сервере GraphQL и других конечных точках API. Вы можете использовать конечные точки API для создания пользовательских интеграций, как описано в <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/API.md\" target=\"_blank\">документации по API</a>.",
"API_TOKEN_name": "API токен",
"API_TOKEN_description": "API-токен для безопасной связи. Сгенерируйте его или введите любое значение. Он передаётся в заголовке запроса и используется в плагине <code>SYNC</code>, сервере GraphQL и других конечных точках API. Вы можете использовать конечные точки API для создания пользовательских интеграций, как описано в <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/API.md\" target=\"_blank\">документации по API</a>.",
"API_TOKEN_name": "API-токен",
"API_display_name": "API",
"API_icon": "<i class=\"fa fa-arrow-down-up-across-line\"></i>",
"About_Design": "Разработан для:",
@@ -57,8 +57,8 @@
"BackDevices_Restore_CopError": "Исходную базу данных сохранить не удалось.",
"BackDevices_Restore_Failed": "Восстановление не удалось. Пожалуйста, восстановите резервную копию вручную.",
"BackDevices_Restore_okay": "Восстановление выполнено успешно.",
"BackDevices_darkmode_disabled": "Темный режим отключен",
"BackDevices_darkmode_enabled": "Темный режим включен",
"BackDevices_darkmode_disabled": "Тёмный режим отключён",
"BackDevices_darkmode_enabled": "Тёмный режим включен",
"CLEAR_NEW_FLAG_description": "Если этот параметр включен (<code>0</code> отключен), устройства, помеченные как <b>Новое устройство</b>, станут неотмеченными, если лимит времени, указанный в часах, превышает время их <b>первой сессии</b>.",
"CLEAR_NEW_FLAG_name": "Удалить новый флаг",
"CustProps_cant_remove": "Невозможно удалить, необходимо хотя бы одно свойство.",
@@ -127,7 +127,7 @@
"DevDetail_Run_Actions_Tooltip": "Выполнить действие на текущем устройстве из раскрывающегося списка.",
"DevDetail_SessionInfo_FirstSession": "Первый сеанс",
"DevDetail_SessionInfo_LastIP": "Последний IP",
"DevDetail_SessionInfo_LastSession": "Последний оффлайн",
"DevDetail_SessionInfo_LastSession": "Посл. не в сети",
"DevDetail_SessionInfo_StaticIP": "Статический IP",
"DevDetail_SessionInfo_Status": "Статус",
"DevDetail_SessionInfo_Title": "Информация о сеансе",
@@ -674,7 +674,7 @@
"Systeminfo_System_Uptime": "Время работы:",
"Systeminfo_This_Client": "Этот клиент",
"Systeminfo_USB_Devices": "USB-устройства",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Обнаружены устаревшие местоположения. Следуйте этому руководству <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\"></a>, чтобы перейти на новые <code>/app/config</code> и <code>/app/db</code> папки и контейнер <code>netalertx</code>.",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Обнаружены устаревшие местоположения. Следуйте этому руководству <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\"></a>, чтобы перейти на новые <code>/data/config</code> и <code>/data/db</code> папки и контейнер <code>netalertx</code>.",
"TIMEZONE_description": "Часовой пояс для корректного отображения статистики. Найдите свой часовой пояс <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\" rel=\"nofollow\">здесь</a>.",
"TIMEZONE_name": "Часовой пояс",
"UI_DEV_SECTIONS_description": "Выберите, какие элементы интерфейса нужно скрыть на страницах «Устройства».",
@@ -761,4 +761,4 @@
"settings_system_label": "Система",
"settings_update_item_warning": "Обновить значение ниже. Будьте осторожны, следуя предыдущему формату. <b>Проверка не выполняется.</b>",
"test_event_tooltip": "Сначала сохраните изменения, прежде чем проверять настройки."
}
}

Some files were not shown because too many files have changed in this diff Show More