Set container parameters

This commit is contained in:
Adam Outler
2025-10-12 15:05:20 -04:00
parent be73e3a7f5
commit 1be91559d2
16 changed files with 301 additions and 182 deletions

View File

@@ -0,0 +1,12 @@
#!/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 [[ "${reply}" == "YES" ]]; then
docker system prune -af
docker builder prune -af
else
echo "Aborted."
exit 1
fi

View File

@@ -78,7 +78,7 @@ configure_source() {
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}/.git-placeholder ${NETALERTX_API}/.git-placeholder
touch ${NETALERTX_PLUGINS_LOG}/.dockerignore ${NETALERTX_API}/.dockerignore
# tmpfs mounts configured with netalertx ownership and 775 permissions above
touch /app/log/nginx_error.log

View File

@@ -1,6 +1,7 @@
This is NetAlertX — network monitoring & alerting.
# NetAlertX AI Assistant Instructions
This is NetAlertX — network monitoring & alerting. NetAlertX provides Network inventory, awareness, insight, categorization, intruder and presence detection. This is a heavily community driven project, welcoming of all contributions.
Purpose: Guide AI assistants to follow NetAlertX architecture, conventions, and safety practices. Be concise, opinionated, and prefer existing helpers/settings over new code or hardcoded values.
You are to expected to be concise, opinionated, and biased toward security and simplicity.
## Architecture (what runs where)
- Backend (Python): main loop + GraphQL/REST endpoints orchestrate scans, plugins, workflows, notifications, and JSON export.
@@ -29,9 +30,9 @@ 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 log via `mylog()` like other plugins do (no `print()`). Example: `mylog('verbose', [f'[{pluginName}] In script'])`.
- 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 `verbose` level unless debugging.
- 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.
- Do not write adhoc files for results; the only consumable output is `last_result.<PREF>.log` generated by `Plugin_Objects`.
## API/Endpoints quick map
@@ -58,5 +59,16 @@ Backend loop phases (see `server/__main__.py` and `server/plugin.py`): `once`, `
- 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/*`
Assistant expectations
- Reference concrete files/paths. Use existing helpers/settings. Keep changes idempotent and safe. Offer a quick validation step (log line, API hit, or JSON export) for anything you add.
## Assistant expectations:
- Be concise, opinionated, and biased toward security and simplicity.
- Reference concrete files/paths/environmental variables.
- Use existing helpers/settings.
- Offer a quick validation step (log line, API hit, or JSON export) for anything you add.
- Be blunt about risks and when you offer suggestions ensure they're also blunt,
- Ask for confirmation before making changes that run code or change multiple files.
- Make statements actionable and specific; propose exact edits.
- Request confirmation before applying changes that affect more than a single, clearly scoped line or file.
- Ask the user to debug something for an actionable value if you're unsure.
- Be sure to offer choices when appropriate.
- Always understand the intent of the user's request and undo/redo as needed.
- Above all, use the simplest possible code that meets the need so it can be easily audited and maintained.

2
.vscode/tasks.json vendored
View File

@@ -24,7 +24,7 @@
{
"label": "[Any] Docker system and build Prune",
"type": "shell",
"command": "docker system prune -af && docker builder prune -af",
"command": ".devcontainer/scripts/confirm-docker-prune.sh",
"presentation": {
"echo": true,
"reveal": "always",

View File

@@ -6,12 +6,13 @@ ENV PYTHONUNBUFFERED=1
ENV PATH="/opt/venv/bin:$PATH"
# Install build dependencies
COPY requirements.txt /tmp/requirements.txt
RUN apk add --no-cache bash shadow python3 python3-dev gcc musl-dev libffi-dev openssl-dev git \
&& python -m venv /opt/venv
RUN pip install -r /tmp/requirements.txt
RUN pip install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask flask-cors unifi-sm-api tplink-omada-client wakeonlan pycryptodome requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython librouteros yattag zeroconf simplejson future six urllib3 httplib2 git+https://github.com/foreign-sub/aiofreepybox.git
# From this point on the Venv is owned by root without any read/write/execute permissions for root or group.
# This makes it easy to copy into hardened stage without worrying about permissions and keeps image size small
RUN chmod -R u-rwx,g-rwx /opt
# second stage is the main runtime stage with just the minimum required to run the application
@@ -20,8 +21,6 @@ FROM alpine:3.22 AS runner
ARG INSTALL_DIR=/app
ENV PATH="/opt/venv/bin:/usr/bin:/sbin:/bin:$PATH"
# NetAlertX app directories
ENV NETALERTX_APP=${INSTALL_DIR}
ENV NETALERTX_CONFIG=${NETALERTX_APP}/config
@@ -33,6 +32,7 @@ ENV NETALERTX_DB_FILE=${NETALERTX_DB}/app.db
ENV NETALERTX_BACK=${NETALERTX_APP}/back
ENV NETALERTX_LOG=${NETALERTX_APP}/log
ENV NETALERTX_PLUGINS_LOG=${NETALERTX_LOG}/plugins
ENV NETALERTX_CONFIG_FILE=${NETALERTX_CONFIG}/app.conf
# NetAlertX log files
ENV LOG_IP_CHANGES=${NETALERTX_LOG}/IP_changes.log
@@ -53,7 +53,6 @@ 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 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
@@ -61,12 +60,18 @@ ENV SYSTEM_SERVICES_RUN=${SYSTEM_SERVICES}/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} /opt /opt/venv"
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}"
#Python environment
ENV PYTHONPATH=${NETALERTX_SERVER}
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 PATH="${SYSTEM_SERVICES}:${VIRTUAL_ENV_BIN}:$PATH"
# App Environment
ENV LISTEN_ADDR=0.0.0.0
@@ -74,8 +79,12 @@ ENV PORT=20211
ENV NETALERTX_DEBUG=0
ENV VENDORSPATH=/app/back/ieee-oui.txt
ENV VENDORSPATH_NEWEST=/services/run/tmp/ieee-oui.txt
ENV PATH="${VIRTUAL_ENV}/bin:${PATH}"
ENV PYTHONPATHPATH="${NETALERTX_APP}:${VIRTUAL_ENV}/bin:${PATH}"
ENV ENVIRONMENT=alpine
ENV READ_ONLY_USER=readonly READ_ONLY_GROUP=readonly
ENV NETALERTX_USER=netalertx NETALERTX_GROUP=netalertx
RUN apk add --no-cache bash mtr libbsd zip lsblk sudo tzdata curl arp-scan iproute2 \
iproute2-ss nmap nmap-scripts traceroute nbtscan net-tools net-snmp-tools bind-tools awake \
@@ -83,40 +92,43 @@ RUN apk add --no-cache bash mtr libbsd zip lsblk sudo tzdata curl arp-scan iprou
envsubst nginx sudo shadow && \
rm -Rf /var/cache/apk/* && \
rm -Rf /etc/nginx && \
addgroup -g 20211 netalertx && \
adduser -u 20211 -D -h ${NETALERTX_APP} -G netalertx netalertx && \
addgroup -g 20211 ${NETALERTX_GROUP} && \
adduser -u 20211 -D -h ${NETALERTX_APP} -G ${NETALERTX_GROUP} ${NETALERTX_USER} && \
apk del shadow
# Install application, copy files, set permissions
COPY --from=builder --chown=20212:20212 ${VIRTUAL_ENV} ${VIRTUAL_ENV}}
COPY --from=builder /usr/sbin/usermod /usr/sbin/groupmod /usr/sbin/
COPY --chown=netalertx:netalertx install/production-filesystem/ /
COPY --chown=netalertx:netalertx --chmod=755 back ${NETALERTX_BACK}
COPY --chown=netalertx:netalertx --chmod=755 front ${NETALERTX_FRONT}
COPY --chown=netalertx:netalertx --chmod=755 server ${NETALERTX_SERVER}
RUN install -d -o netalertx -g netalertx -m 755 ${NETALERTX_API} \
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} && \
sh -c "find ${NETALERTX_APP} -type f \( -name '*.sh' -o -name 'speedtest-cli' \) \
-exec chmod 750 {} \;"
# Copy the virtualenv from the builder stage
COPY --from=builder --chown=20212:20212 ${VIRTUAL_ENV} ${VIRTUAL_ENV}
#initialize each service with the dockerfiles/init-*.sh scripts, once.
RUN apk add libcap && \
setcap cap_net_raw,cap_net_admin+eip /usr/bin/nmap && \
setcap cap_net_raw,cap_net_admin+eip /usr/bin/arp-scan && \
setcap cap_net_raw,cap_net_admin+eip /usr/bin/traceroute && \
setcap cap_net_raw,cap_net_admin+eip ${VIRTUAL_ENV_BIN}scapy && \
setcap cap_net_raw,cap_net_admin+eip ${VIRTUAL_ENV_BIN}/scapy && \
/bin/sh /build/init-nginx.sh && \
/bin/sh /build/init-php-fpm.sh && \
/bin/sh /build/init-crond.sh && \
/bin/sh /build/init-backend.sh && \
chmod 755 ${SYSTEM_SERVICES}/update_vendors.sh ${SYSTEM_SERVICES}/cron_script.sh && \
rm -rf /build && \
apk del libcap
# set netalertx to allow sudoers for any command, no password
RUN echo "netalertx ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
RUN echo "${NETALERTX_USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
ENTRYPOINT ["/bin/sh","-c","sleep infinity"]
@@ -125,45 +137,42 @@ ENTRYPOINT ["/bin/sh","-c","sleep infinity"]
# This stage is separate from Runner stage so that devcontainer can use the Runner stage.
FROM runner AS hardened
# create readonly user and group with no shell access.
# Create readonly user and group with no shell access.
# Readonly user marks folders that are created by NetAlertX, but should not be modified.
RUN addgroup -g 20212 readonly && \
adduser -u 20212 -G readonly -D -h /app readonly && \
usermod -s /sbin/nologin readonly
# AI may claim this is stupid, but it's actually least possible permissions as
# read-only user cannot login, cannot sudo, has no write permission, and cannot even
# read the files it owns. The read-only user is ownership-as-a-lock hardening pattern.
RUN addgroup -g 20212 ${READ_ONLY_GROUP} && \
adduser -u 20212 -G ${READ_ONLY_GROUP} -D -h /app ${READ_ONLY_USER}
# reduce permissions to minimum necessary for all NetAlertX files and folders
# Permissions 005 and 004 are not typos, they enable read-only.
RUN chown -R ${READ_ONLY_USER}:${READ_ONLY_GROUP} ${READ_ONLY_FOLDERS} && \
chmod -R 004 ${READ_ONLY_FOLDERS} && \
find ${READ_ONLY_FOLDERS} -type d -exec chmod 005 {} + && \
install -d -o ${NETALERTX_USER} -g ${NETALERTX_GROUP} -m 700 ${READ_WRITE_FOLDERS} && \
chown -R ${NETALERTX_USER}:${NETALERTX_GROUP} ${READ_WRITE_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 && \
chmod 005 /entrypoint.sh ${SYSTEM_SERVICES}/*.sh
RUN chown -R readonly:readonly ${NETALERTX_BACK} ${NETALERTX_FRONT} ${NETALERTX_SERVER} ${SYSTEM_SERVICES} ${SYSTEM_SERVICES} && \
chmod -R 004 ${NETALERTX_BACK} ${NETALERTX_FRONT} ${NETALERTX_SERVER} && \
find ${NETALERTX_BACK} ${NETALERTX_FRONT} ${NETALERTX_SERVER} -type d -exec chmod 005 {} + && \
chmod -R 005 ${SYSTEM_SERVICES} ${SYSTEM_SERVICES}/* && \
chown -R netalertx:netalertx ${NETALERTX_CONFIG} ${NETALERTX_DB} ${NETALERTX_API} ${NETALERTX_LOG} && \
chmod -R 600 ${NETALERTX_CONFIG} ${NETALERTX_DB} ${NETALERTX_API} ${NETALERTX_LOG} && \
chmod 700 ${NETALERTX_CONFIG} ${NETALERTX_DB} ${NETALERTX_API} ${NETALERTX_LOG} ${NETALERTX_PLUGINS_LOG} ${SYSTEM_SERVICES_RUN_TMP} && \
chown readonly:readonly /entrypoint.sh && \
install -d -o netalertx -g netalertx -m 700 ${SYSTEM_SERVICES_RUN} ${SYSTEM_SERVICES_RUN_TMP} ${SYSTEM_SERVICES_RUN_LOG} && \
chmod 005 /entrypoint.sh ${SYSTEM_SERVICES}/update_vendors.sh ${SYSTEM_SERVICES}/cron_script.sh ${SYSTEM_SERVICES}/speedtest-cli
#
# remove sudo and alpine installers pacakges
# remove sudoers, sudo, alpine installers pacakges, and all users and groups except
# readonly and netalertx
RUN apk del sudo apk-tools && \
rm -rf /var/cache/apk/*
# remove all users and groups except readonly and netalertx & remove all sudoers
RUN rm -Rf /etc/sudoers.d/* /etc/shadow /etc/gshadow /etc/sudoers \
/lib/apk /lib/firmware /lib/modules-load.d /lib/sysctl.d /mnt /home/ /root \
rm -rf /var/cache/apk/* && \
rm -Rf /etc/sudoers.d/* /etc/shadow /etc/gshadow /etc/sudoers \
/lib/apk /lib/firmware /lib/modules-load.d /lib/sysctl.d /mnt /home/ /root \
/srv /media && \
sed -i -n -e '/^readonly:/p' -e '/^netalertx:/p' /etc/passwd && \
sed -i -n -e '/^readonly:/p' -e '/^netalertx:/p' /etc/group && \
sed -i "/^\(${READ_ONLY_USER}\|${NETALERTX_USER}\):/!d" /etc/passwd && \
sed -i "/^\(${READ_ONLY_GROUP}\|${NETALERTX_GROUP}\):/!d" /etc/group && \
echo -ne '#!/bin/sh\n"$@"\n' > /usr/bin/sudo && chmod +x /usr/bin/sudo
USER netalertx
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD /services/healthcheck.sh
#ENTRYPOINT [ "/bin/sh" ]
ENTRYPOINT [ "/bin/sh", "/entrypoint.sh" ]

View File

@@ -1,7 +1,46 @@
# Warning - use of this unhardened image is not recommended for production use.
# This image is provided for backward compatibility, development and testing purposes only.
# For production use, please use the hardened image built with Alpine. This image attempts to
# treat a container as an operating system, which is an anti-pattern and a common source of
# security issues.
#
# The default Dockerfile/docker-compose image contains the following security improvements
# over the Debian image:
# - read-only filesystem
# - no sudo access
# - least possible permissions on all files and folders
# - no shell access for non-privileged users
# - no unnecessary packages or services
# - reduced capabilities
# - tmpfs for writable folders
# - healthcheck
# - no package managers
# - no compilers or build tools
# - no systemd, uses lightweight init system
# - no persistent storage except for config and db volumes
# - minimal image size due to segmented build stages
# - minimal base image (Alpine Linux)
# - minimal python environment (venv, no pip)
# - minimal stripped web server
# - minimal stripped php environment
# - minimal services (nginx, php-fpm, crond, no unnecessary services or service managers)
# - minimal users and groups (netalertx and readonly only, no others)
# - minimal permissions (read-only for most files and folders, write-only for necessary folders)
# - minimal capabilities (NET_ADMIN and NET_RAW only, no others)
# - minimal environment variables (only necessary ones, no others)
# - minimal entrypoint (only necessary commands, no others)
# - Uses the same base image as the development environmnment (Alpine Linux)
# - Uses the same services as the development environment (nginx, php-fpm, crond)
# - Uses the same environment variables as the development environment (only necessary ones, no others)
# - Uses the same file and folder structure as the development environment (only necessary ones, no others)
# NetAlertX is designed to be run as an unattended network security monitoring appliance, which means it
# should be able to operate without human intervention. Overall, the hardened image is designed to be as
# secure as possible while still being functional and is recommended because you cannot attack a surface
# that isn't there.
FROM debian:bookworm-slim
#TZ=Europe/London
# NetAlertX app directories
@@ -74,11 +113,11 @@ ENV USER_GID=1000
# add root and www-data to pi group so they can r/w files and db
RUN groupadd --gid "${USER_GID}" "${USER}" && \
useradd \
--uid ${USER_ID} \
--gid ${USER_GID} \
--create-home \
--shell /bin/bash \
${USER} && \
--uid ${USER_ID} \
--gid ${USER_GID} \
--create-home \
--shell /bin/bash \
${USER} && \
usermod -a -G ${USER_GID} root && \
usermod -a -G ${USER_GID} www-data
@@ -97,10 +136,10 @@ RUN apt update && apt-get install -y \
# (Ondřej Surý maintains php packages for debian. This is temp until debian includes php-fpm in their
# repos. Likely it will be in Debian Trixie.). This keeps the image up-to-date with the alpine version.
RUN apt-get install -y --no-install-recommends \
apt-transport-https \
ca-certificates \
lsb-release \
wget && \
apt-transport-https \
ca-certificates \
lsb-release \
wget && \
wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg && \
echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list && \
apt-get update && \
@@ -109,7 +148,7 @@ RUN apt-get install -y --no-install-recommends \
# Setup virtual python environment and use pip3 to install packages
RUN python3 -m venv ${VIRTUAL_ENV} && \
/bin/bash -c "source ${VIRTUAL_ENV_BIN}/activate && update-alternatives --install /usr/bin/python python /usr/bin/python3 10 && pip3 install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask flask-cors unifi-sm-api tplink-omada-client wakeonlan pycryptodome requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython librouteros yattag "
/bin/bash -c "source ${VIRTUAL_ENV_BIN}/activate && update-alternatives --install /usr/bin/python python /usr/bin/python3 10 && pip3 install -r ${INSTALL_DIR}/requirements.txt"
# Configure php-fpm
RUN chmod -R 755 /services && \

View File

@@ -1,39 +1,41 @@
version: '3.8'
services:
netalertx:
network_mode: host # Use host networking for ARP scanning and other services
build:
context: .
dockerfile: Dockerfile
context: . # Build context is the current directory
dockerfile: Dockerfile # Specify the Dockerfile to use
image: netalertx:latest
container_name: netalertx_internal
read_only: true
container_name: netalertx # The name when you docker contiainer ls
read_only: true # Make the container filesystem read-only
# cap_drop: # Drop all capabilities for enhanced security
# - ALL
cap_add: # Add only the necessary capabilities
- NET_ADMIN # Required for ARP scanning
- NET_RAW # Required for raw socket operations
security_opt: # Security options for the container
- no-new-privileges:true # Prevent privilege escalation
- seccomp:unconfined # Use unconfined seccomp profile (adjust as needed)
volumes:
- netalertx_config:/app/config
- netalertx_db:/app/db
- /etc/localtime:/etc/localtime:ro
tmpfs:
- /etc/nginx/conf.d
- /var/cache/nginx
- /var/run
- /app/log
- /tmp
networks:
- netalertx_net
- "/app/api:uid=20211,gid=20211,mode=700"
- "/app/log:uid=20211,gid=20211,mode=700"
- "/services/config/nginx/conf.active:uid=20211,gid=20211,mode=700"
- "/services/run:uid=20211,gid=20211,mode=700"
- "/tmp:mode=700"
environment:
- NETALERTX_MODE=hardened
- GRAPHQL_PORT=25378
NETALERTX_MODE: hardened
PORT: 20211
GRAPHQL_PORT: 25378
ALWAYS_FRESH_INSTALL: false
restart: unless-stopped
proxy:
image: nginx:alpine
container_name: netalertx_proxy
ports:
- "20211:25377"
- "20212:25378"
networks:
- netalertx_net
depends_on:
- netalertx
restart: unless-stopped
networks:
netalertx_net:
volumes:
netalertx_config:
netalertx_db:

View File

@@ -1,82 +1,43 @@
services:
netalertx:
privileged: true
network_mode: host # Use host networking for ARP scanning and other services
build:
dockerfile: Dockerfile
context: .
cache_from:
- type=registry,ref=docker.io/jokob-sk/netalertx:buildcache
container_name: netalertx
network_mode: host
# restart: unless-stopped
context: . # Build context is the current directory
dockerfile: Dockerfile # Specify the Dockerfile to use
image: netalertx:latest
container_name: netalertx # The name when you docker contiainer ls
read_only: true # Make the container filesystem read-only
cap_drop: # Drop all capabilities for enhanced security
- ALL
cap_add: # Add only the necessary capabilities
- NET_ADMIN # Required for ARP scanning
- NET_RAW # Required for raw socket operations
security_opt: # Security options for the container
- no-new-privileges:true # Prevent privilege escalation
- seccomp:unconfined # Use unconfined seccomp profile (adjust as needed)
volumes:
# - ${APP_DATA_LOCATION}/netalertx_dev/config:/app/config
- ${APP_DATA_LOCATION}/netalertx/config:/app/config
# - ${APP_DATA_LOCATION}/netalertx_dev/db:/app/db
- ${APP_DATA_LOCATION}/netalertx/db:/app/db
# (optional) useful for debugging if you have issues setting up the container
- ${APP_DATA_LOCATION}/netalertx/log:/app/log
# (API: OPTION 1) use for performance
- type: tmpfs
target: /app/api
# (API: OPTION 2) use when debugging issues
# - ${DEV_LOCATION}/api:/app/api
# ---------------------------------------------------------------------------
# DELETE START anyone trying to use this file: comment out / delete BELOW lines, they are only for development purposes
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/dhcp1.leases:/mnt/dhcp1.leases # test data for DCPLSS plugin
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/dhcp2.leases:/mnt/dhcp2.leases # test data for DCPLSS plugin
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/pihole_dhcp_full.leases:/etc/pihole/dhcp.leases # test data for DCPLSS plugin
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/pihole_dhcp_2.leases:/etc/pihole/dhcp2.leases # test data for DCPLSS plugin
- ${APP_DATA_LOCATION}/pihole/etc-pihole/pihole-FTL.db:/etc/pihole/pihole-FTL.db # test data for PIHOLE plugin
- ${DEV_LOCATION}/mkdocs.yml:/app/mkdocs.yml
- ${DEV_LOCATION}/docs:/app/docs
- ${DEV_LOCATION}/server:/app/server
- ${DEV_LOCATION}/test:/app/test
- ${DEV_LOCATION}/dockerfiles:/app/dockerfiles
# - ${APP_DATA_LOCATION}/netalertx/php.ini:/etc/php/8.2/fpm/php.ini
- ${DEV_LOCATION}/install:/app/install
- ${DEV_LOCATION}/front/css:/app/front/css
- ${DEV_LOCATION}/front/img:/app/front/img
- ${DEV_LOCATION}/back/update_vendors.sh:/app/back/update_vendors.sh
- ${DEV_LOCATION}/front/lib:/app/front/lib
- ${DEV_LOCATION}/front/js:/app/front/js
- ${DEV_LOCATION}/front/php:/app/front/php
- ${DEV_LOCATION}/front/deviceDetails.php:/app/front/deviceDetails.php
- ${DEV_LOCATION}/front/deviceDetailsEdit.php:/app/front/deviceDetailsEdit.php
- ${DEV_LOCATION}/front/userNotifications.php:/app/front/userNotifications.php
- ${DEV_LOCATION}/front/deviceDetailsTools.php:/app/front/deviceDetailsTools.php
- ${DEV_LOCATION}/front/deviceDetailsPresence.php:/app/front/deviceDetailsPresence.php
- ${DEV_LOCATION}/front/deviceDetailsSessions.php:/app/front/deviceDetailsSessions.php
- ${DEV_LOCATION}/front/deviceDetailsEvents.php:/app/front/deviceDetailsEvents.php
- ${DEV_LOCATION}/front/devices.php:/app/front/devices.php
- ${DEV_LOCATION}/front/events.php:/app/front/events.php
- ${DEV_LOCATION}/front/plugins.php:/app/front/plugins.php
- ${DEV_LOCATION}/front/pluginsCore.php:/app/front/pluginsCore.php
- ${DEV_LOCATION}/front/index.php:/app/front/index.php
- ${DEV_LOCATION}/front/initCheck.php:/app/front/initCheck.php
- ${DEV_LOCATION}/front/maintenance.php:/app/front/maintenance.php
- ${DEV_LOCATION}/front/network.php:/app/front/network.php
- ${DEV_LOCATION}/front/presence.php:/app/front/presence.php
- ${DEV_LOCATION}/front/settings.php:/app/front/settings.php
- ${DEV_LOCATION}/front/systeminfo.php:/app/front/systeminfo.php
- ${DEV_LOCATION}/front/systeminfoNetwork.php:/app/front/systeminfoNetwork.php
- ${DEV_LOCATION}/front/systeminfoServer.php:/app/front/systeminfoServer.php
- ${DEV_LOCATION}/front/systeminfoStorage.php:/app/front/systeminfoStorage.php
- ${DEV_LOCATION}/front/cloud_services.php:/app/front/cloud_services.php
- ${DEV_LOCATION}/front/report.php:/app/front/report.php
- ${DEV_LOCATION}/front/workflows.php:/app/front/workflows.php
- ${DEV_LOCATION}/front/workflowsCore.php:/app/front/workflowsCore.php
- ${DEV_LOCATION}/front/appEvents.php:/app/front/appEvents.php
- ${DEV_LOCATION}/front/appEventsCore.php:/app/front/appEventsCore.php
- ${DEV_LOCATION}/front/multiEditCore.php:/app/front/multiEditCore.php
- ${DEV_LOCATION}/front/plugins:/app/front/plugins
# DELETE END anyone trying to use this file: comment out / delete ABOVE lines, they are only for development purposes
# ---------------------------------------------------------------------------
environment:
# - APP_CONF_OVERRIDE={"SCAN_SUBNETS":"['192.168.1.0/24 --interface=eth1']","GRAPHQL_PORT":"20223","UI_theme":"Light"}
- TZ=${TZ}
- PORT=${PORT}
# ❗ DANGER ZONE BELOW - Setting ALWAYS_FRESH_INSTALL=true will delete the content of the /db & /config folders
- ALWAYS_FRESH_INSTALL=${ALWAYS_FRESH_INSTALL}
# - LOADED_PLUGINS=["DHCPLSS","PIHOLE","ASUSWRT","FREEBOX"]
- netalertx_config:/app/config # Store your NetAlertX config
- netalertx_db:/app/db # Store your NetAlertX devices and settings
- /etc/localtime:/etc/localtime:ro # Use your system clock inside the container (read-only)
#- /path/on/host:/app/front/plugins/custom # Test your plugin on the production container
# Tempfs mounts for writable directories in a read-only container and improve system performance
# by providing a clean R/W filesystem each container start and reducing disk I/O.
tmpfs:
- "/app/api:uid=20211,gid=20211,mode=700"
- "/app/log:uid=20211,gid=20211,mode=700"
- "/services/config/nginx/conf.active:uid=20211,gid=20211,mode=700"
- "/services/run:uid=20211,gid=20211,mode=700"
environment:
LISTEN_ADDR: 0.0.0.0
PORT: 20211
GRAPHQL_PORT: 20212
NETALERTX_MODE: hardened
ALWAYS_FRESH_INSTALL: false
NETALERTX_DEBUG: 0
restart: unless-stopped
volumes:
netalertx_config:
netalertx_db:

View File

@@ -6,6 +6,15 @@ echo "---------------------------------------------------------"
# ❗ IMPORTANT - if you modify this file modify the root Dockerfile as well ❗
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
REQUIREMENTS_FILE="${REPO_ROOT}/requirements.txt"
if [[ ! -f "${REQUIREMENTS_FILE}" ]]; then
echo "requirements.txt not found at ${REQUIREMENTS_FILE}. Please ensure the repository root is available." >&2
exit 1
fi
# Check if script is run as root
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root. Please use 'sudo'."
@@ -30,4 +39,4 @@ source /opt/venv/bin/activate
update-alternatives --install /usr/bin/python python /usr/bin/python3 10
# install packages thru pip3
pip3 install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask flask-cors unifi-sm-api tplink-omada-client wakeonlan pycryptodome requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython librouteros yattag git+https://github.com/foreign-sub/aiofreepybox.git
pip3 install -r "${REQUIREMENTS_FILE}"

View File

@@ -1,4 +1,4 @@
#!/bin/bash
echo "Initializing nginx..."
install -d -o netalertx -g netalertx -m 700 /app/run/tmp/client_body;
install -d -o netalertx -g netalertx -m 700 ${SYSTEM_SERVICES_RUN_TMP}/client_body;
echo "nginx initialized."

View File

@@ -3,6 +3,9 @@
set -u
bash /services/capcheck.sh
bash /services/ramdisk-check.sh
SERVICES=""
FAILED_NAME=""

View File

@@ -107,7 +107,7 @@ http {
# Set Cache-Control header to prevent caching on the first load
add_header Cache-Control "no-store";
fastcgi_pass unix:/services/run/php.sock;
include fastcgi_params;
include /services/config/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_connect_timeout 75;

View File

@@ -0,0 +1,32 @@
#!/bin/sh
# ramdisk-check.sh - Verify critical paths are backed by ramdisk and warn on fallback storage.
warn_if_not_ramdisk() {
path="$1"
if cat /proc/mounts| grep ${path} | grep -qE 'tmpfs|ramfs'; then
return 0
fi
cat >&2 <<EOF
⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
ATTENTION: ${path} is not on a ramdisk.
Mount this folder inside the container as tmpfs or ramfs.
NetAlertX expects this location to live in memory for fast reads and writes.
Running it on disk will severely degrade performance for every user.
Fix: Please mount ${path} as tmpfs/ramfs.
eg. --mount type=tmpfs,destination=${path}
Restart the container after adding the ramdisk mount.
⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
EOF
exit 1
}
warn_if_not_ramdisk "${NETALERTX_API}"
warn_if_not_ramdisk "${NETALERTX_LOG}"
if [ ! -f "${SYSTEM_NGINIX_CONFIG}/conf.active" ]; then
echo "Note: Using default listen address ${LISTEN_ADDR}:${PORT} (no ${SYSTEM_NGINIX_CONFIG}/conf.active override)."
fi

View File

@@ -1,4 +1,5 @@
#!/bin/bash
#! /bin/sh
set -euo pipefail
LOG_DIR=${NETALERTX_APP}
@@ -34,10 +35,10 @@ done
TEMP_CONFIG_FILE=$(mktemp "${TMP_DIR}/netalertx.conf.XXXXXX")
if envsubst '${LISTEN_ADDR} ${PORT}' < "${SYSTEM_NGINX_CONFIG_TEMPLATE}" > "${TEMP_CONFIG_FILE}" 2>/dev/null; then
mv "${TEMP_CONFIG_FILE}" "${SYSTEM_NGINX_CONFIG_FILE}"
mv "${TEMP_CONFIG_FILE}" "${SYSTEM_NGINX_CONFIG_FILE}" 2>/dev/null || true
else
echo "Note: Unable to write to ${SYSTEM_NGINX_CONFIG_FILE}. Using default configuration."
rm -f "${TEMP_CONFIG_FILE}"
rm -f "${TEMP_CONFIG_FILE}" 2>/dev/null || true
fi
trap cleanup EXIT

View File

@@ -15,6 +15,7 @@ echo "---------------------------------------------------------"
INSTALL_DIR=/app
INSTALL_SYSTEM_NAME=ubuntu24
INSTALLER_DIR=${INSTALL_DIR}/install/$INSTALL_SYSTEM_NAME
REQUIREMENTS_FILE=${INSTALL_DIR}/requirements.txt
CONF_FILE=app.conf
DB_FILE=app.db
NGINX_CONF_FILE=netalertx.conf
@@ -153,7 +154,12 @@ echo
python3 -m venv "${VENV_DIR}"
source "${VENV_DIR}/bin/activate"
pip3 install -r "${INSTALLER_DIR}/requirements.txt" || {
if [[ ! -f "${REQUIREMENTS_FILE}" ]]; then
echo "[INSTALL] requirements.txt not found at ${REQUIREMENTS_FILE}"
exit 1
fi
pip3 install -r "${REQUIREMENTS_FILE}" || {
echo "[INSTALL] Failed to install Python dependencies"
exit 1
}

33
requirements.txt Normal file
View File

@@ -0,0 +1,33 @@
openwrt-luci-rpc
asusrouter
asyncio
aiohttp
graphene
flask
flask-cors
unifi-sm-api
tplink-omada-client
wakeonlan
pycryptodome
requests
paho-mqtt
scapy
cron-converter
pytz
json2table
dhcp-leases
pyunifi
speedtest-cli
chardet
python-nmap
dnspython
librouteros
yattag
zeroconf
simplejson
future
six
urllib3
httplib2
gunicorn
git+https://github.com/foreign-sub/aiofreepybox.git