mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-06 17:15:38 -08:00
Set container parameters
This commit is contained in:
12
.devcontainer/scripts/confirm-docker-prune.sh
Executable file
12
.devcontainer/scripts/confirm-docker-prune.sh
Executable 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
|
||||
@@ -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
|
||||
|
||||
24
.github/copilot-instructions.md
vendored
24
.github/copilot-instructions.md
vendored
@@ -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 ad‑hoc 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
2
.vscode/tasks.json
vendored
@@ -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",
|
||||
|
||||
103
Dockerfile
103
Dockerfile
@@ -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" ]
|
||||
|
||||
@@ -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 && \
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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}"
|
||||
|
||||
@@ -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."
|
||||
@@ -3,6 +3,9 @@
|
||||
set -u
|
||||
|
||||
bash /services/capcheck.sh
|
||||
bash /services/ramdisk-check.sh
|
||||
|
||||
|
||||
|
||||
SERVICES=""
|
||||
FAILED_NAME=""
|
||||
|
||||
@@ -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;
|
||||
|
||||
32
install/production-filesystem/services/ramdisk-check.sh
Normal file
32
install/production-filesystem/services/ramdisk-check.sh
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
33
requirements.txt
Normal 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
|
||||
Reference in New Issue
Block a user