Merge branch 'jokob-sk:main' into FEAT--Make-Errors-More-Helpful

This commit is contained in:
Adam Outler
2025-10-31 23:59:45 -04:00
committed by GitHub
46 changed files with 1905 additions and 365 deletions

View File

@@ -1,90 +1,162 @@
# Backing things up
# Backing Things Up
> [!NOTE]
> To backup 99% of your configuration backup at least the `/app/config` folder. Please read the whole page (or at least "Scenario 2: Corrupted database") for details.
> Note that database definitions might change over time. The safest way is to restore your older backups into the **same version** of the app they were taken from and then gradually upgarde between releases to the latest version.
> To back up 99% of your configuration, back up at least the `/app/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.
There are 4 artifacts that can be used to backup the application:
---
| File | Description | Limitations |
|-----------------------|-------------------------------|-------------------------------|
| `/db/app.db` | Database file(s) | The database file might be in an uncommitted state or corrupted |
| `/config/app.conf` | Configuration file | Can be overridden with the [`APP_CONF_OVERRIDE` env variable](https://github.com/jokob-sk/NetAlertX/tree/main/dockerfiles#docker-environment-variables). |
| `/config/devices.csv` | CSV file containing device information | Doesn't contain historical data |
| `/config/workflows.json` | A JSON file containing your workflows | N/A |
## What to Back Up
There are four key artifacts you can use to back up your NetAlertX configuration:
## Backup strategies
| File | Description | Limitations |
| ------------------------ | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/db/app.db` | The application database | Might be in an uncommitted state or corrupted |
| `/config/app.conf` | Configuration file | Can be overridden using the [`APP_CONF_OVERRIDE`](https://github.com/jokob-sk/NetAlertX/tree/main/dockerfiles#docker-environment-variables) variable |
| `/config/devices.csv` | CSV file containing device data | Does not include historical data |
| `/config/workflows.json` | JSON file containing your workflows | N/A |
The safest approach to backups is to backup everything, by taking regular file system backups of the `/db` and `/config` folders (I use [Kopia](https://github.com/kopia/kopia)).
---
Arguably, the most time is spent setting up the device list, so if only one file is kept I'd recommend to have a latest backup of the `devices_<timestamp>.csv` or `devices.csv` file, followed by the `app.conf` and `workflows.json` files. You can also download `app.conf` and `devices.csv` file in the Maintenance section:
## Where the Data Lives
![Backup and Restore Section in Maintenance](./img/BACKUPS/Maintenance_Backup_Restore.png)
### Scenario 1: Full backup
End-result: Full restore
#### 💾 Source artifacts:
- `/app/db/app.db` (uncorrupted)
- `/app/config/app.conf`
- `/app/config/workflows.json`
#### 📥 Recovery:
To restore the application map the above files as described in the [Setup documentation](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md#docker-paths).
### Scenario 2: Corrupted database
End-result: Partial restore (historical data and some plugin data will be missing)
#### 💾 Source artifacts:
- `/app/config/app.conf`
- `/app/config/devices_<timestamp>.csv` or `/app/config/devices.csv`
- `/app/config/workflows.json`
#### 📥 Recovery:
Even with a corrupted database you can recover what I would argue is 99% of the configuration.
- upload the `app.conf` and `workflows.json` files into the mounted `/app/config/` folder as described in the [Setup documentation](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md#docker-paths).
- rename the `devices_<timestamp>.csv` to `devices.csv` and place it in the `/app/config` folder
- Restore the `devices.csv` backup via the [Maintenance section](./DEVICES_BULK_EDITING.md)
## Data and backup storage
To decide on a backup strategy, check where the data is stored:
Understanding where your data is stored helps you plan your backup strategy.
### Core Configuration
The core application configuration is in the `app.conf` file (See [Settings System](./SETTINGS_SYSTEM.md) for details), such as:
Stored in `/app/config/app.conf`.
This includes settings for:
- Notification settings
- Scanner settings
- Scheduled maintenance settings
- UI configuration
* Notifications
* Scanning
* Scheduled maintenance
* UI preferences
### Core Device Data
(See [Settings System](./SETTINGS_SYSTEM.md) for details.)
The core device data is backed up to the `devices_<timestamp>.csv` or `devices.csv` file via the [CSV Backup `CSVBCKP` Plugin](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/csv_backup). This file contains data, such as:
### Device Data
- Device names
- Device icons
- Device network configuration
- Device categorization
- Device custom properties 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).
Contains:
### Historical data
* Device names, icons, and categories
* Network configuration
* Custom properties
Historical data is stored in the `app.db` database (See [Database overview](./DATABASE.md) for details). This data includes:
### Historical Data
- Plugin objects
- Plugin historical entries
- History of Events, Notifications, Workflow Events
- Presence history
Stored in `/app/db/app.db` (see [Database Overview](./DATABASE.md)).
Contains:
* Plugin data and historical entries
* Event and notification history
* Device presence history
---
## Backup Strategies
The safest approach is to back up **both** the `/db` and `/config` folders regularly. Tools like [Kopia](https://github.com/kopia/kopia) make this simple and efficient.
If you can only keep a few files, prioritize:
1. The latest `devices_<timestamp>.csv` or `devices.csv`
2. `app.conf`
3. `workflows.json`
You can also download the `app.conf` and `devices.csv` files from the **Maintenance** section:
![Backup and Restore Section in Maintenance](./img/BACKUPS/Maintenance_Backup_Restore.png)
---
## Scenario 1: Full Backup and Restore
**Goal:** Full recovery of your configuration and data.
### 💾 What to Back Up
* `/app/db/app.db` (uncorrupted)
* `/app/config/app.conf`
* `/app/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).
---
## Scenario 2: Corrupted Database
**Goal:** Recover configuration and device data when the database is lost or corrupted.
### 💾 What to Back Up
* `/app/config/app.conf`
* `/app/config/workflows.json`
* `/app/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`
3. Restore via the **Maintenance** section under *Devices → Bulk Editing*
This recovers nearly all configuration, workflows, and device metadata.
---
## Docker-Based Backup and Restore
For users running NetAlertX via Docker, you can back up or restore directly from your host system — a convenient and scriptable option.
### Full Backup (File-Level)
1. **Stop the container:**
```bash
docker stop netalertx
```
2. **Create a compressed archive** of your configuration and database volumes:
```bash
docker run --rm -v local_path/config:/config -v local_path/db:/db alpine tar -cz /config /db > netalertx-backup.tar.gz
```
3. **Restart the container:**
```bash
docker start netalertx
```
### Restore from Backup
1. **Stop the container:**
```bash
docker stop netalertx
```
2. **Restore from your backup file:**
```bash
docker run --rm -i -v local_path/config:/config -v local_path/db:/db alpine tar -C / -xz < netalertx-backup.tar.gz
```
3. **Restart the container:**
```bash
docker start netalertx
```
> This approach uses a temporary, minimal `alpine` container to access Docker-managed volumes. The `tar` command creates or extracts an archive directly from your hosts filesystem, making it fast, clean, and reliable for both automation and manual recovery.
---
## Summary
* Back up `/app/config` for configuration and devices; `/app/db` for history
* Keep regular backups, especially before upgrades
* For Docker setups, use the lightweight `alpine`-based backup method for consistency and portability

82
docs/BUILDS.md Normal file
View File

@@ -0,0 +1,82 @@
# NetAlertX Builds: Choose Your Path
NetAlertX provides different installation methods for different needs. This guide helps you choose the right path for security, experimentation, or development.
## 1. Hardened Appliance (Default Production)
> [!NOTE]
> Use this image if: You want to use NetAlertX securely.
### Who is this for?
All users who want a stable, secure, "set-it-and-forget-it" appliance.
### Methodology
- Multi-stage Alpine build
- Aggressively "amputated"
- Locked down for max security
### Source
`Dockerfile (hardened target)`
## 2. "Tinkerer's" Image (Insecure VM-Style)
> [!NOTE]
> Use this image if: You want to experiment with NetAlertX.
### Who is this for?
Power users, developers, and "tinkerers" wanting a familiar "VM-like" experience.
### Methodology
- Traditional Debian build
- Includes full un-hardened OS
- Contains `apt`, `sudo`, `git`
### Source
`Dockerfile.debian`
## 3. Contributor's Devcontainer (Project Developers)
> [!NOTE]
> Use this image if: You want to develop NetAlertX itself.
### Who is this for?
Project contributors who are actively writing and debugging code for NetAlertX.
### Methodology
- Builds `FROM runner` stage
- Loaded by VS Code
- Full debug tools: `xdebug`, `pytest`
### Source
`Dockerfile (devcontainer target)`
# Visualizing the Trade-Offs
This chart compares the three builds across key attributes. A higher score means "more of" that attribute. Notice the clear trade-offs between security and development features.
![tradeoffs](./img/BUILDS/build_images_options_tradeoffs.png)
# Build Process & Origins
The final images originate from two different files and build paths. The main `Dockerfile` uses stages to create *both* the hardened and development container images.
## Official Build Path
Dockerfile -> builder (Stage 1) -> runner (Stage 2) -> hardened (Final Stage) (Production Image) + devcontainer (Final Stage) (Developer Image)
## Legacy Build Path
Dockerfile.debian -> "Tinkerer's" Image (Insecure VM-Style Image)

View File

@@ -1,203 +1,251 @@
# `docker-compose.yaml` Examples
# 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]
> The container needs to run in `network_mode:"host"`. This also means that not all functionality is supported on a Windows host as Docker for Windows doesn't support this networking option.
> The container needs to run in `network_mode:"host"` to access Layer 2 networking such as arp, nmap and others. Due to lack of support for this feature, Windows host is not a supported operating system.
### Example 1
## Baseline Docker Compose
There is one baseline for NetAlertX. That's the default security-enabled official distribution.
```yaml
services:
netalertx:
container_name: netalertx
# use the below line if you want to test the latest dev image
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: "ghcr.io/jokob-sk/netalertx:latest"
network_mode: "host"
restart: unless-stopped
#use an environmental variable to set host networking mode if needed
container_name: netalertx # The name when you docker contiainer ls
image: ghcr.io/jokob-sk/netalertx-dev:latest
network_mode: ${NETALERTX_NETWORK_MODE:-host} # Use host networking for ARP scanning and other services
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
- NET_BIND_SERVICE # Required to bind to privileged ports (nbtscan)
volumes:
- local_path/config:/app/config
- local_path/db:/app/db
# (optional) useful for debugging if you have issues setting up the container
- local_path/logs:/app/log
# (API: OPTION 1) use for performance
- type: tmpfs
target: /app/api
# (API: OPTION 2) use when debugging issues
# - local_path/api:/app/api
- 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
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.
- type: bind # Bind mount for timezone consistency
source: /etc/localtime
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
# 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=2Key-Value Pairs: 20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
environment:
- TZ=Europe/Berlin
- PORT=20211
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.
# Resource limits to prevent resource exhaustion
mem_limit: 2048m # Maximum memory usage
mem_reservation: 1024m # Soft memory limit
cpu_shares: 512 # Relative CPU weight for CPU contention scenarios
pids_limit: 512 # Limit the number of processes/threads to prevent fork bombs
logging:
driver: "json-file" # Use JSON file logging driver
options:
max-size: "10m" # Rotate log files after they reach 10MB
max-file: "3" # Keep a maximum of 3 log files
# 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
```
To run the container execute: `sudo docker-compose up -d`
Run or re-run it:
### Example 2
Example by [SeimuS](https://github.com/SeimusS).
```yaml
services:
netalertx:
container_name: NetAlertX
hostname: NetAlertX
privileged: true
# use the below line if you want to test the latest dev image
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: ghcr.io/jokob-sk/netalertx:latest
environment:
- TZ=Europe/Bratislava
restart: always
volumes:
- ./netalertx/db:/app/db
- ./netalertx/config:/app/config
network_mode: host
```sh
docker compose up --force-recreate
```
To run the container execute: `sudo docker-compose up -d`
### Customize with Environmental Variables
### Example 3
You can override the default settings by passing environmental variables to the `docker compose up` command.
`docker-compose.yml`
**Example using a single variable:**
This command runs NetAlertX on port 8080 instead of the default 20211.
```sh
PORT=8080 docker compose up
```
**Example using all available variables:**
This command demonstrates overriding all primary environmental variables: running with host networking, on port 20211, GraphQL on 20212, and listening on all IPs.
```sh
NETALERTX_NETWORK_MODE=host \
LISTEN_ADDR=0.0.0.0 \
PORT=20211 \
GRAPHQL_PORT=20212 \
NETALERTX_DEBUG=0 \
docker compose up
```
## `docker-compose.yaml` Modifications
### Modification 1: Use a Local Folder (Bind Mount)
By default, the baseline compose file uses "named volumes" (`netalertx_config`, `netalertx_db`). **This is the preferred method** because NetAlertX is designed to manage all configuration and database settings directly from its web UI. Named volumes let Docker handle this data cleanly without you needing to manage local file permissions or paths.
However, if you prefer to have direct, file-level access to your configuration for manual editing, a "bind mount" is a simple alternative. This tells Docker to use a specific folder from your computer (the "host") inside the container.
**How to make the change:**
1. Choose a location on your computer. For example, `/home/adam/netalertx-files`.
2. Create the subfolders: `mkdir -p /home/adam/netalertx-files/config` and `mkdir -p /home/adam/netalertx-files/db`.
3. Edit your `docker-compose.yml` and find the `volumes:` section (the one *inside* the `netalertx:` service).
4. Comment out (add a `#` in front) or delete the `type: volume` blocks for `netalertx_config` and `netalertx_db`.
5. Add new lines pointing to your local folders.
**Before (Using Named Volumes - Preferred):**
```yaml
...
volumes:
- netalertx_config:/app/config:rw #short-form volume (no /path is a short volume)
- netalertx_db:/app/db:rw
...
```
**After (Using a Local Folder / Bind Mount):**
Make sure to replace `/home/adam/netalertx-files` with your actual path. The format is `<path_on_your_computer>:<path_inside_container>:<options>`.
```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
...
```
Now, any files created by NetAlertX in `/app/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.
## Example Configuration Summaries
Here are the essential modifications for common alternative setups.
### Example 2: External `.env` File for Paths
This method is useful for keeping your paths and other settings separate from your main compose file, making it more portable.
**`docker-compose.yml` changes:**
```yaml
...
services:
netalertx:
container_name: netalertx
# use the below line if you want to test the latest dev image
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: "ghcr.io/jokob-sk/netalertx:latest"
network_mode: "host"
restart: unless-stopped
volumes:
- ${APP_CONFIG_LOCATION}/netalertx/config:/app/config
- ${APP_DATA_LOCATION}/netalertx/db/:/app/db/
# (optional) useful for debugging if you have issues setting up the container
- ${LOGS_LOCATION}:/app/log
# (API: OPTION 1) use for performance
- type: tmpfs
target: /app/api
# (API: OPTION 2) use when debugging issues
# - local/path/api:/app/api
environment:
- TZ=${TZ}
- TZ=${TZ}
- PORT=${PORT}
...
```
`.env` file
```yaml
#GLOBAL PATH VARIABLES
APP_DATA_LOCATION=/path/to/docker_appdata
APP_CONFIG_LOCATION=/path/to/docker_config
LOGS_LOCATION=/path/to/docker_logs
#ENVIRONMENT VARIABLES
**`.env` file contents:**
```sh
TZ=Europe/Paris
PORT=20211
#DEVELOPMENT VARIABLES
DEV_LOCATION=/path/to/local/source/code
NETALERTX_NETWORK_MODE=host
LISTEN_ADDR=0.0.0.0
PORT=20211
GRAPHQL_PORT=20212
```
To run the container execute: `sudo docker-compose --env-file /path/to/.env up`
Run with: `sudo docker-compose --env-file /path/to/.env up`
### Example 3: Docker Swarm
### Example 4: Docker swarm
This is for deploying on a Docker Swarm cluster. The key differences from the baseline are the removal of `network_mode:` from the service, and the addition of `deploy:` and `networks:` blocks at both the service and top-level.
Notice how the host network is defined in a swarm setup:
Here are the *only* changes you need to make to the baseline compose file to make it Swarm-compatible.
```yaml
services:
netalertx:
# Use the below line if you want to test the latest dev image
# image: "jokobsk/netalertx-dev:latest"
image: "ghcr.io/jokob-sk/netalertx:latest"
volumes:
- /mnt/MYSERVER/netalertx/config:/config:rw
- /mnt/MYSERVER/netalertx/db:/netalertx/db:rw
- /mnt/MYSERVER/netalertx/logs:/netalertx/front/log:rw
environment:
- TZ=Europe/London
- PORT=20211
...
# network_mode: ${NETALERTX_NETWORK_MODE:-host} # <-- DELETE THIS LINE
...
# 2. ADD a 'networks:' block INSIDE the service to connect to the external host network.
networks:
- outside
# 3. ADD a 'deploy:' block to manage the service as a swarm replica.
deploy:
mode: replicated
replicas: 1
restart_policy:
condition: on-failure
# 4. ADD a new top-level 'networks:' block at the end of the file to define 'outside' as the external 'host' network.
networks:
outside:
external:
name: "host"
```
### Example 5: same as 3 but with a top-level root directory; also works in Portainer as-is
`docker-compose.yml`
```yaml
services:
netalertx:
container_name: netalertx
# use the below line if you want to test the latest dev image instead of the stable release
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: "ghcr.io/jokob-sk/netalertx:latest"
network_mode: "host"
restart: unless-stopped
volumes:
- ${APP_FOLDER}/netalertx/config:/app/config
- ${APP_FOLDER}/netalertx/db:/app/db
# (optional) useful for debugging if you have issues setting up the container
- ${APP_FOLDER}/netalertx/log:/app/log
# (API: OPTION 1) default -> use for performance
- type: tmpfs
target: /app/api
# (API: OPTION 2) use when debugging issues
# - ${APP_FOLDER}/netalertx/api:/app/api
environment:
- TZ=${TZ}
- PORT=${PORT}
- PUID=${PUID}
- PGID=${PGID}
- LISTEN_ADDR=${LISTEN_ADDR}
```
`.env` file
```yaml
APP_FOLDER=/path/to/local/NetAlertX/location
#ENVIRONMENT VARIABLES
PUID=200
PGID=300
TZ=America/New_York
LISTEN_ADDR=0.0.0.0
PORT=20211
#GLOBAL PATH VARIABLE
# you may want to create a dedicated user and group to run the container with
# sudo groupadd -g 300 nax-g
# sudo useradd -u 200 -g 300 nax-u
# mkdir -p $APP_FOLDER/{db,config,log}
# chown -R 200:300 $APP_FOLDER
# chmod -R 775 $APP_FOLDER
# DEVELOPMENT VARIABLES
# you can create multiple env files called .env.dev1, .env.dev2 etc and use them by running:
# docker compose --env-file .env.dev1 up -d
# you can then clone multiple dev copies of NetAlertX just make sure to change the APP_FOLDER and PORT variables in each .env.devX file
```
To run the container execute: `sudo docker-compose --env-file /path/to/.env up`
```

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">

205
docs/DOCKER_MAINTENANCE.md Normal file
View File

@@ -0,0 +1,205 @@
# 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.
## Guide Contents
- Using a Local Folder for Configuration
- Migrating from a Local Folder to a Docker Volume
- Applying a Custom Nginx Configuration
- Mounting Additional Files for Plugins
> [!NOTE]
>
> Other relevant resources
> - [Fixing Permission Issues](./FILE_PERMISSIONS.md)
> - [Handling Backups](./BACKUPS.md)
> - [Accessing Application Logs](./LOGGING.md)
---
## Task: Using a Local Folder for Configuration
### Problem
You want to edit your `app.conf` and other configuration files directly from your host machine, instead of using a Docker-managed volume.
### Solution
1. Stop the container:
```bash
docker-compose down
```
2. (Optional but Recommended) Back up your data using the method in Part 1.
3. Create a local folder on your host machine (e.g., `/data/netalertx_config`).
4. Edit `docker-compose.yml`:
* **Comment out** the `netalertx_config` volume entry.
* **Uncomment** and **set the path** for the "Example custom local folder" bind mount entry.
```yaml
...
volumes:
# - type: volume
# source: netalertx_config
# target: /app/config
# read_only: false
...
# Example custom local folder called /data/netalertx_config
- type: bind
source: /data/netalertx_config
target: /app/config
read_only: false
...
```
5. (Optional) Restore your backup.
6. Restart the container:
```bash
docker-compose up -d
```
### 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.
---
## Task: Migrating from a Local Folder to a Docker Volume
### Problem
You are currently using a local folder (bind mount) for your configuration (e.g., `/data/netalertx_config`) and want to switch to the recommended Docker-managed volume (`netalertx_config`).
### Solution
1. Stop the container:
```bash
docker-compose down
```
2. Edit `docker-compose.yml`:
* **Comment out** the bind mount entry for your local folder.
* **Uncomment** the `netalertx_config` volume entry.
```yaml
...
volumes:
- type: volume
source: netalertx_config
target: /app/config
read_only: false
...
# Example custom local folder called /data/netalertx_config
# - type: bind
# source: /data/netalertx_config
# target: /app/config
# read_only: false
...
```
3. (Optional) Initialize the volume:
```bash
docker-compose up -d && docker-compose down
```
4. Run the migration command (**replace `/data/netalertx_config` with your actual path**):
```bash
docker run --rm -v netalertx_config:/config -v /data/netalertx_config:/local-config alpine \
sh -c "tar -C /local-config -c . | tar -C /config -x"
```
5. Restart the container:
```bash
docker-compose up -d
```
### About This Method
This uses a temporary `alpine` container that mounts *both* your source folder (`/local-config`) and destination volume (`/config`). The `tar ... | tar ...` command safely copies all files, including hidden ones, preserving structure.
---
## Task: Applying a Custom Nginx Configuration
### Problem
You need to override the default Nginx configuration to add features like LDAP, SSO, or custom SSL settings.
### Solution
1. Stop the container:
```bash
docker-compose down
```
2. Create your custom config file on your host (e.g., `/data/my-netalertx.conf`).
3. Edit `docker-compose.yml`:
```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
...
```
4. Restart the container:
```bash
docker-compose up -d
```
### About This Method
Dockers bind mount overlays your host file (`my-netalertx.conf`) on top of the default file inside the container. The container remains read-only, but Nginx reads your file as if it were the default.
---
## Task: Mounting Additional Files for Plugins
### Problem
A plugin (like `DHCPLSS`) needs to read a file from your host machine (e.g., `/var/lib/dhcp/dhcpd.leases`).
### Solution
1. Stop the container:
```bash
docker-compose down
```
2. Edit `docker-compose.yml` and add a new line under the `volumes:` section:
```yaml
...
volumes:
...
# Mount for DHCPLSS plugin
- /var/lib/dhcp/dhcpd.leases:/mnt/dhcpd.leases:ro
...
```
3. Restart the container:
```bash
docker-compose up -d
```
4. In the NetAlertX web UI, configure the plugin to read from:
```
/mnt/dhcpd.leases
```
### About This Method
This maps your host file to a new, read-only (`:ro`) location inside the container. The plugin can then safely read this file without exposing anything else on your host filesystem.

View File

@@ -1,23 +1,78 @@
# Managing File Permissions for NetAlertX on Nginx with Docker
# Managing File Permissions for NetAlertX on a Read-Only Container
> [!TIP]
> If you are facing permission issues, try to start the container without mapping your volumes. If that works, then the issue is permission related. You can try e.g., the following command:
> ```
> docker run -d --rm --network=host \
> -e TZ=Europe/Berlin \
> -e PUID=200 -e PGID=200 \
> -e PORT=20211 \
> ghcr.io/jokob-sk/netalertx:latest
> ```
NetAlertX runs on an Nginx web server. On Alpine Linux, Nginx operates as the `nginx` user (if PUID and GID environment variables are not specified, nginx user UID will be set to 102, and its supplementary group `www-data` ID to 82). Consequently, files accessed or written by the NetAlertX application are owned by `nginx:www-data`.
> NetAlertX runs in a **secure, read-only Alpine-based container** under a dedicated `netalertx` user (UID 20211, GID 20211). All writable paths are either mounted as **persistent volumes** or **`tmpfs` filesystems**. This ensures consistent file ownership and prevents privilege escalation.
Upon starting, NetAlertX changes nginx user UID and www-data GID to specified values (or defaults), and the ownership of files on the host system mapped to `/app/config` and `/app/db` in the container to `nginx:www-data`. This ensures that Nginx can access and write to these files. Since the user in the Docker container is mapped to a user on the host system by ID:GID, the files in `/app/config` and `/app/db` on the host system are owned by a user with the same ID and GID (defaults are ID 102 and GID 82). On different systems, this ID:GID may belong to different users, or there may not be a group with ID 82 at all.
---
Option to set specific user UID and GID can be useful for host system users needing to access these files (e.g., backup scripts).
## Writable Paths
NetAlertX requires certain paths to be writable at runtime. These paths should be mounted either as **host volumes** or **`tmpfs`** in your `docker-compose.yml` or `docker run` command:
| 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 |
> All these paths will have **UID 20211 / GID 20211** inside the container. Files on the host will appear owned by `20211:20211`.
---
## Fixing Permission Problems
Sometimes, permission issues arise if your existing host directories were created by a previous container running as root or another UID. The container will fail to start with "Permission Denied" errors.
### Solution
1. **Run the container once as root** (`--user "0"`) to allow it to correct permissions automatically:
```bash
docker run -it --rm --name netalertx --user "0" \
-v local/path/config:/app/config \
-v local/path/db:/app/db \
ghcr.io/jokob-sk/netalertx:latest
```
2. Wait for logs showing **permissions being fixed**. The container will then **hang intentionally**.
3. Press **Ctrl+C** to stop the container.
4. Start the container normally with your `docker-compose.yml` or `docker run` command.
> The container startup script detects `root` and runs `chown -R 20211:20211` on all volumes, fixing ownership for the secure `netalertx` user.
---
## Example: docker-compose.yml with `tmpfs`
```yaml
services:
netalertx:
container_name: netalertx
image: "ghcr.io/jokob-sk/netalertx"
network_mode: "host"
cap_add:
- NET_RAW
- NET_ADMIN
- NET_BIND_SERVICE
restart: unless-stopped
volumes:
- local/path/config:/app/config
- local/path/db:/app/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"
- "/tmp:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
```
> This setup ensures all writable paths are either in `tmpfs` or host-mounted, and the container never writes outside of controlled volumes.
### Permissions Table for Individual Folders
| Folder | User | User ID | Group | Group ID | Permissions | Notes |
|----------------|--------|---------|-----------|----------|-------------|---------------------------------------------------------------------|
| `/app/config` | nginx | PUID (default 102) | www-data | PGID (default 82) | rwxr-xr-x | Ensure `nginx` can read/write; other users can read if in `www-data` |
| `/app/db` | nginx | PUID (default 102) | www-data | PGID (default 82) | rwxr-xr-x | Same as above |

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/dockerfiles/README.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

@@ -1,11 +1,9 @@
# Logging
NetAlertX comes with several logs that help to identify application issues.
For plugin-specific log debugging, please read the [Debug Plugins](./DEBUG_PLUGINS.md) guide.
When debugging any issue, increase the `LOG_LEVEL` Setting as per the [Debug tips](./DEBUG_TIPS.md) documentation.
NetAlertX comes with several logs that help to identify application issues. These include nginx logs, app, or plugin logs. For plugin-specific log debugging, please read the [Debug Plugins](./DEBUG_PLUGINS.md) guide.
> [!NOTE]
> When debugging any issue, increase the `LOG_LEVEL` Setting as per the [Debug tips](./DEBUG_TIPS.md) documentation.
## Main logs
@@ -24,3 +22,54 @@ If a Plugin supplies data to the main app it's done either vie a SQL query or vi
The data is in most of the cases then displayed in the application under _Integrations -> Plugins_ (or _Device -> Plugins_ if the plugin is supplying device-specific data).
![Plugin objects](./img/LOGGING/logging_integrations_plugins.png)
## Viewing Logs on the File System
You cannot find any log files on the filesystem. The container is `read-only` and writes logs to a temporary in-memory filesystem (`tmpfs`) for security and performance. The application follows container best-practices by writing all logs to the standard output (`stdout`) and standard error (`stderr`) streams. Docker's logging driver (set in `docker-compose.yml`) captures this stream automatically, allowing you to access it with the `docker logs <image_name>` command.
* **To see all logs since the last restart:**
```bash
docker logs netalertx
```
* **To watch the logs live (live feed):**
```bash
docker logs -f netalertx
```
## Enabling Persistent File-Based Logs
The default logs are erased every time the container restarts because they are stored in temporary in-memory storage (`tmpfs`). If you need to keep a persistent, file-based log history, follow the steps below.
> [!NOTE]
> This might lead to performance degradation so this approach is only suggested when actively debugging issues. See the [Performance optimization](./PERFORMANCE.md) documentation for details.
1. Stop the container:
```bash
docker-compose down
```
2. Edit your `docker-compose.yml` file:
* **Comment out** the `/app/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"
...
volumes:
...
# Retain logs - comment out tmpfs /app/log if you want to retain logs between container restarts
- /home/adam/netalertx_logs:/app/log
...
```
3. Restart the container:
```bash
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.

View File

@@ -1,27 +1,53 @@
# Migration form PiAlert to NetAlertX
# Migration
> [!WARNING]
> Follow this guide only after you you downloaded and started a version of NetAlertX prior to v25.6.7 (e.g. `docker pull ghcr.io/jokob-sk/netalertx:25.5.24`) at least once after previously using the PiAlert image. Later versions don't support migration and devices and settings will have to migrated manually, e.g. via [CSV import](./DEVICES_BULK_EDITING.md).
> [!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.
## STEPS:
> [!TIP]
> In short: The application will auto-migrate the database, config, and all device information. A ticker message on top will be displayed until you update your docker mount points. It's always good to have a [backup strategy](./BACKUPS.md) in place.
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.
1. Backup your current config and database (optional `devices.csv` to have a backup) (See bellow tip if facing issues)
2. Stop the container
2. Update the Docker file mount locations in your `docker-compose.yml` or docker run command (See bellow **New Docker mount locations**).
3. Rename the DB and conf files to `app.db` and `app.conf` and place them in the appropriate location.
4. Start the Container
> [!TIP]
> It's always important to have a [backup strategy](./BACKUPS.md) in place.
## Migration scenarios
- You are running PiAlert (by jokob-sk)
→ [Read the 1.1 Migration from PiAlert to NetAlertX `v25.5.24`](#11-migration-from-pialert-to-netalertx-v25524)
- You are running NetAlertX (by jokob-sk) `25.5.24` or older
→ [Read the 1.2 Migration from NetAlertX `v25.5.24`](#12-migration-from-netalertx-v25524)
- You are running NetAlertX (by jokob-sk) (`v25.6.7` to `v25.10.1`)
→ [Read the 1.3 Migration from NetAlertX `v25.10.1`](#13-migration-from-netalertx-v25101)
### 1.0 Manual Migration
You can migrate data manually, for example by exporting and importing devices using the [CSV import](./DEVICES_BULK_EDITING.md) method.
### 1.1 Migration from PiAlert to NetAlertX `v25.5.24`
#### STEPS:
The application will automatically migrate the database, configuration, and all device information.
A banner message will appear at the top of the web UI reminding you to update your Docker mount points.
1. Stop the container
2. [Back up your setup](./BACKUPS.md)
3. Update the Docker file mount locations in your `docker-compose.yml` or docker run command (See below **New Docker mount locations**).
4. Rename the DB and conf files to `app.db` and `app.conf` and place them in the appropriate location.
5. Start the container
> [!TIP]
> If you have troubles 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` conatining 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 /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.
#### New Docker mount locations
### New Docker mount locations
The application installation folder in the docker container has changed from `/home/pi/pialert` to `/app`. That means the new mount points are:
The internal application path in the container has changed from `/home/pi/pialert` to `/app`. Update your volume mounts as follows:
| Old mount point | New mount point |
|----------------------|---------------|
@@ -38,16 +64,16 @@ The application installation folder in the docker container has changed from `/h
> [!NOTE]
> The application uses symlinks linking the old db and config locations to the new ones, so data loss should not occur. [Backup strategies](./BACKUPS.md) are still recommended to backup your setup.
> The application automatically creates symlinks from the old database and config locations to the new ones, so data loss should not occur. Read the [backup strategies](./BACKUPS.md) guide to backup your setup.
# Examples
#### Examples
Examples of docker files with the new mount points.
## Example 1: Mapping folders
##### Example 1: Mapping folders
### Old docker-compose.yml
###### Old docker-compose.yml
```yaml
services:
@@ -68,34 +94,32 @@ services:
- PORT=20211
```
### New docker-compose.yml
###### New docker-compose.yml
```yaml
services:
netalertx: # This has changed (🟡optional)
container_name: netalertx # This has changed (🟡optional)
# use the below line if you want to test the latest dev image
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: "ghcr.io/jokob-sk/netalertx:latest" # ⚠ This has changed (🟡optional/🔺required in future)
netalertx: # 🆕 This has changed
container_name: netalertx # 🆕 This has changed
image: "ghcr.io/jokob-sk/netalertx:25.5.24" # 🆕 This has changed
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config:/app/config # This has changed (🔺required)
- local/path/db:/app/db # This has changed (🔺required)
- local/path/config:/app/config # 🆕 This has changed
- local/path/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 (🟡optional)
- local/path/logs:/app/log # 🆕 This has changed
environment:
- TZ=Europe/Berlin
- PORT=20211
```
## Example 2: Mapping files
##### Example 2: Mapping files
> [!NOTE]
> The recommendation is to map folders as in Example 1, map files directly only when needed.
### Old docker-compose.yml
###### Old docker-compose.yml
```yaml
services:
@@ -116,23 +140,159 @@ services:
- PORT=20211
```
### New docker-compose.yml
###### New docker-compose.yml
```yaml
services:
netalertx: # This has changed (🟡optional)
container_name: netalertx # This has changed (🟡optional)
# use the below line if you want to test the latest dev image
# image: "ghcr.io/jokob-sk/netalertx-dev:latest"
image: "ghcr.io/jokob-sk/netalertx:latest" # ⚠ This has changed (🟡optional/🔺required in future)
netalertx: # 🆕 This has changed
container_name: netalertx # 🆕 This has changed
image: "ghcr.io/jokob-sk/netalertx:25.5.24" # 🆕 This has changed
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config/app.conf:/app/config/app.conf # This has changed (🔺required)
- local/path/db/app.db:/app/db/app.db # This has changed (🔺required)
- local/path/config/app.conf:/app/config/app.conf # 🆕 This has changed
- local/path/db/app.db:/app/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 (🟡optional)
- local/path/logs:/app/log # 🆕 This has changed
environment:
- TZ=Europe/Berlin
- PORT=20211
```
### 1.2 Migration from NetAlertX `v25.5.24`
Versions before `v25.10.1` require an intermediate migration through `v25.5.24` to ensure database compatibility. Skipping this step may cause compatibility issues due to database schema changes introduced after `v25.5.24`.
#### STEPS:
1. Stop the container
2. [Back up your setup](./BACKUPS.md)
3. Upgrade to `v25.5.24` by pinning the release version (See Examples below)
4. Start the container and verify everything works as expected.
5. Stop the container
6. Upgrade to `v25.10.1` by pinning the release version (See Examples below)
7. Start the container and verify everything works as expected.
#### Examples
Examples of docker files with the tagged version.
##### Example 1: Mapping folders
###### docker-compose.yml changes
```yaml
services:
netalertx:
container_name: netalertx
image: "ghcr.io/jokob-sk/netalertx:25.5.24" # 🆕 This is important
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config:/app/config
- local/path/db:/app/db
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/app/log
environment:
- TZ=Europe/Berlin
- PORT=20211
```
```yaml
services:
netalertx:
container_name: netalertx
image: "ghcr.io/jokob-sk/netalertx:25.10.1" # 🆕 This is important
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config:/app/config
- local/path/db:/app/db
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/app/log
environment:
- TZ=Europe/Berlin
- PORT=20211
```
### 1.3 Migration from NetAlertX `v25.10.1`
Starting from v25.10.1, the container uses a [more secure, read-only runtime environment](./SECURITY_FEATURES.md), which requires all writable paths (e.g., logs, API cache, temporary data) to be mounted as `tmpfs` or permanent writable volumes, with sufficient access [permissions](./FILE_PERMISSIONS.md).
#### STEPS:
1. Stop the container
2. [Back up your setup](./BACKUPS.md)
3. Upgrade to `v25.10.1` by pinning the release version (See the example below)
```yaml
services:
netalertx:
container_name: netalertx
image: "ghcr.io/jokob-sk/netalertx:25.10.1" # 🆕 This is important
network_mode: "host"
restart: unless-stopped
volumes:
- local/path/config:/app/config
- local/path/db:/app/db
# (optional) useful for debugging if you have issues setting up the container
- local/path/logs:/app/log
environment:
- TZ=Europe/Berlin
- PORT=20211
```
4. Start the container and verify everything works as expected.
5. Stop the container.
6. Perform a one-off migration to the latest `netalertx` image and `20211` user:
> [!NOTE]
> The example below assumes your `/config` and `/db` folders are stored in `local/path`.
> Replace this path with your actual configuration directory. `netalertx` is the container name, which might differ from your setup.
```sh
docker run -it --rm --name netalertx --user "0" \
-v local/path/config:/app/config \
-v local/path/db:/app/db \
ghcr.io/jokob-sk/netalertx:latest
```
7. Stop the container
8. Update the `docker-compose.yml` as per example below.
```yaml
services:
netalertx:
container_name: netalertx
image: "ghcr.io/jokob-sk/netalertx" # 🆕 This is important
network_mode: "host"
cap_add: # 🆕 New line
- NET_RAW # 🆕 New line
- NET_ADMIN # 🆕 New line
- NET_BIND_SERVICE # 🆕 New line
restart: unless-stopped
volumes:
- local/path/config:/app/config
- local/path/db:/app/db
# (optional) useful for debugging if you have issues setting up the container
#- local/path/logs:/app/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
- "/tmp:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"
# 🆕 New "tmpfs" section END 🔼
```
9. Start the container and verify everything works as expected.

View File

@@ -1,6 +1,6 @@
# Integration with PiHole
NetAlertX comes with 2 plugins suitable for integarting with your existing PiHole instace. One plugin is using a direct SQLite DB connection, the other leverages the DHCP.leases file generated by PiHole. You can combine both approaches and also supplement it with other [plugins](/docs/PLUGINS.md).
NetAlertX comes with 2 plugins suitable for integrating with your existing PiHole instance. One plugin is using a direct SQLite DB connection, the other leverages the DHCP.leases file generated by PiHole. You can combine both approaches and also supplement it with other [plugins](/docs/PLUGINS.md).
## Approach 1: `DHCPLSS` Plugin - Import devices from the PiHole DHCP leases file

85
docs/SECURITY_FEATURES.md Normal file
View File

@@ -0,0 +1,85 @@
# NetAlertX Security: A Layered Defense
Your network security monitor has the "keys to the kingdom," making it a prime target for attackers. If it gets compromised, the game is over.
NetAlertX is engineered from the ground up to prevent this. It's not just an app; it's a purpose-built **security appliance.** Its core design is built on a **zero-trust** philosophy, which is a modern way of saying we **assume a breach will happen** and plan for it. This isn't a single "lock on the door"; it's a **"defense-in-depth"** strategy, more like a medieval castle with a moat, high walls, and guards at every door.
Heres a breakdown of the defensive layers you get, right out of the box using the default configuration.
## Feature 1: The "Digital Concrete" Filesystem
**Methodology:** The core application and its system files are treated as immutable. Once built, the app's code is "set in concrete," preventing attackers from modifying it or planting malware.
* **Immutable Filesystem:** At runtime, the container's entire filesystem is set to `read_only: true`. The application code, system libraries, and all other files are literally frozen. This single control neutralizes a massive range of common attacks.
* **"Ownership-as-a-Lock" Pattern:** During the build, all system files are assigned to a special `readonly` user. This user has no login shell and no power to write to *any* files, even its own. Its a clever, defense-in-depth locking mechanism.
* **Data Segregation:** All user-specific data (like configurations and the device database) is stored completely outside the container in Docker volumes. The application is disposable; the data is persistent.
**What's this mean to you:** Even if an attacker gets in, they **cannot modify the application code or plant malware.** It's like the app is set in digital concrete.
## Feature 2: Surgical, "Keycard-Only" Access
**Methodology:** The principle of least privilege is strictly enforced. Every process gets only the absolute minimum set of permissions needed for its specific job.
* **Non-Privileged Execution:** The entire NetAlertX stack runs as a dedicated, low-power, non-root user (`netalertx`). No "god mode" privileges are available to the application.
* **Kernel-Level Capability Revocation:** The container is launched with `cap_drop: - ALL`, which tells the Linux kernel to revoke *all* "root-like" special powers.
* **Binary-Specific Privileges (setcap):** This is the "keycard" metaphor in action. After revoking all powers, the system uses `setcap` to grant specific, necessary permissions *only* to the binaries that absolutely require them (like `nmap` and `arp-scan`). This means that even if an attacker compromises the web server, they can't start scanning the network. The web server's "keycard" doesn't open the "scanning" door.
**What's this mean to you:** A security breach is **firewalled.** An attacker who gets into the web UI **does not have the "keycard"** to start scanning your network or take over the system. The breach is contained.
## Feature 3: Attack Surface "Amputation"
**Methodology:** The potential attack surface is aggressively minimized by removing every non-essential tool an attacker would want to use.
* **Package Manager Removal:** The `hardened` build stage explicitly deletes the Alpine package manager (`apk del apk-tools`). This makes it impossible for an attacker to simply `apk add` their malicious toolkit.
* **`sudo` Neutralization:** All `sudo` configurations are removed, and the `/usr/bin/sudo` command is replaced with a non-functional shim. Any attempt to escalate privileges this way will fail.
* **Build Toolchain Elimination:** The `Dockerfile` uses a multi-stage build. The initial "builder" stage, which contains all the powerful compilers (`gcc`) and development tools, is completely discarded. The final production image is lean and contains no build tools.
* **Minimal User & Group Files:** The `hardened` stage scrubs the system's `passwd` and `group` files, removing all default system users to minimize potential avenues for privilege escalation.
**What's this mean to you:** An attacker who breaks in finds themselves in an **empty room with no tools.** They have no `sudo` to get more power, no package manager to download weapons, and no compilers to build new ones.
## Feature 4: "Self-Cleaning" Writable Areas
**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.
* **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.
* **Secure Mount Flags:** These in-memory mounts are configured with the `noexec` flag. This is a critical security control: it **prohibits the execution of any binary or script** from a location that is writable.
**What's this mean to you:** Any malicious file an attacker *does* manage to drop is **written in invisible, non-permanent ink.** The file is written to RAM, not disk, so it **vaporizes the instant you restart** the container. Even worse for them, the `noexec` flag means they **can't even run the file** in the first place.
## Feature 5: Built-in Resource Guardrails
**Methodology:** The container is constrained by resource limits to function as a "good citizen" on the host system. This prevents a compromised or runaway process from consuming excessive resources, a common vector for Denial of Service (DoS) attacks.
* **Process Limiting:** The `docker-compose.yml` defines a `pids_limit: 512`. This directly mitigates "fork bomb" attacks, where a process attempts to crash the host by recursively spawning thousands of new processes.
* **Memory & CPU Limits:** The configuration file defines strict resource limits to prevent any single process from exhausting the host's available system resources.
**What's this mean to you:** NetAlertX is a "good neighbor" and **can't be used to crash your host machine.** Even if a process is compromised, it's in a digital straitjacket and **cannot** pull a "denial of service" attack by hogging all your CPU or memory.
## Feature 6: The "Pre-Flight" Self-Check
**Methodology:** Before any services start, NetAlertX runs a comprehensive "pre-flight" check to ensure its own security and configuration are sound. It's like a built-in auditor who verifies its own defenses.
* **Active Self-Diagnosis:** On every single boot, NetAlertX runs a series of startup pre-checks—and it's fast. The entire self-check process typically completes in less than a second, letting you get to the web UI in about three seconds from startup.
* **Validates Its Own Security:** These checks actively inspect the other security features. For example, `check-0-permissions.sh` validates that all the "Digital Concrete" files are locked down and all the "Self-Cleaning" areas are writable, just as they should be. It also checks that the correct `netalertx` user is running the show, not `root`.
* **Catches Misconfigurations:** This system acts as a "safety inspector" that catches misconfigurations *before* they can become security holes. If you've made a mistake in your configuration (like a bad folder permission or incorrect network mode), NetAlertX will tell you in the logs *why* it can't start, rather than just failing silently.
**What's this mean to you:** The system is **self-aware and checks its own work.** You get instant feedback if a setting is wrong, and you get peace of mind on every single boot knowing all these security layers are **active and verified,** all in about one second.
## Conclusion: Security by Default
No single security control is a silver bullet. The robust security posture of NetAlertX is achieved through **defense in depth**, layering these methodologies.
An adversary must not only gain initial access but must also find a way to write a payload to a non-executable, in-memory location, without access to any standard system tools, `sudo`, or a package manager. And they must do this while operating as an unprivileged user in a resource-limited environment where the application code is immutable and *actively checks its own integrity on every boot*.

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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB