Important
PRE-RELEASE BETA
Real-time log viewer for Apache, Nginx, NPM, system logs and Fail2ban
README en Français | Installation | Plugins | Configuration | Documentation
LogviewR — real-time log viewer for Apache, Nginx, NPM, system logs and Fail2ban.
- 🚀 Real-time via WebSocket
- 🔍 Filters: level, date, IP, HTTP method…
- 📊 Statistics and dashboards per plugin
- 🔐 JWT auth, role management
- 🐳 Docker-ready
🖥️ Host System — Linux/Unix system logs
- Syslog, auth, kernel, daemon, mail, custom logs
- Automatic Docker environment detection
- RFC 3164 / RFC 5424 support
- Configurable base path (
/var/logor/host/logsin Docker)
🌐 Apache — Apache HTTP Server logs
- Access logs (Combined, Common, VHost) + Error logs
- IP, timestamp, HTTP method, status code, referer, user-agent extraction
- Editable default regex,
.gzsupport
🚀 Nginx — Nginx logs
- Access logs (Combined, Common, Main, Extended) + Error logs
- Timestamp parsing with timezone handling
- Fail2ban and ELK compatible regex,
.gzsupport
🔄 Nginx Proxy Manager (NPM) — NPM logs
- 5 supported formats with automatic detection
- Fields: cache, upstream status, gzip ratio, subdomains
.gzsupport
🛡️ Fail2ban — jail monitoring and banned IPs
Tabs: Jails · Filters · Actions · IP Tracker · Map · Ban Manager · Stats · IPTables · IPSet · NFTables · Config · Audit
Requirements: fail2ban installed and active on the host. Host setup required — see Installation Step 2.
To verify: Administration → Plugins → Fail2ban → Diagnostic.
Firewall tabs in Docker (IPTables · IPSet · NFTables)
These tabs require two cumulative conditions — neither alone is sufficient:
| Condition | Role |
|---|---|
network_mode: host |
Shares host network namespace — container sees host iptables/ipset/nft rules |
cap_add: NET_ADMIN |
Linux capability required by the kernel for netfilter read/write |
⚠️ Three incompatibilities to know:
network_mode: hostis incompatible withports:— removeports:and usePORT=7500inenvironment:insteadsecurity_opt: no-new-privileges:trueis incompatible with firewall tabs —sudocannot elevate with this flag, breaking iptables/ipset/nft commands- To change the listen port: set
PORT=8080in.envand point your reverse proxy to127.0.0.1:8080
docker-compose.yml configuration with Firewall tabs enabled:
services:
logviewr:
image: ghcr.io/erreur32/logviewr:latest
container_name: logviewr
restart: unless-stopped
# no ports: — incompatible with network_mode: host
network_mode: host
cap_add:
- NET_ADMIN # required for netfilter (iptables/ipset/nft)
# no security_opt: no-new-privileges — incompatible with sudo (breaks firewall tabs)
environment:
JWT_SECRET: ${JWT_SECRET}
PORT: ${PORT:-7500} # direct listen port — change here + update reverse proxy
HOST_IP: ${HOST_IP:-}
group_add:
- "${ADM_GID:-4}"
- "${FAIL2BAN_GID:-}"
volumes:
- ./data:/app/data
- /var/run/fail2ban/fail2ban.sock:/var/run/fail2ban/fail2ban.sock
- /:/host:ro # :ro = more secure; disables Fail2ban VACUUM (see note below)
- /proc:/host/proc:ro
- /sys:/host/sys:ro
# Optional: enable Fail2ban SQLite VACUUM (long-form bind required — short-form does not override :ro)
# - type: bind
# source: /var/lib/fail2ban
# target: /host/var/lib/fail2ban
# bind:
# propagation: shared
# Optional: enable Fail2ban config file editing from the UI (jail.local / fail2ban.local)
# Run once: curl -fsSL https://raw.githubusercontent.com/Erreur32/LogviewR/main/scripts/setup-fail2ban-access.sh | sudo bash
# - type: bind
# source: /etc/fail2ban
# target: /host/etc/fail2ban
# bind:
# propagation: shared
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:7500/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sWithout these options, IPTables/IPSet/NFTables tabs will show a Permission denied or no new privileges error.
Step 1 — Create .env
echo "JWT_SECRET=$(openssl rand -base64 32)" > .envStep 2 — Fail2ban host setup (one-time — required only if using the Fail2ban plugin)
curl -fsSL https://raw.githubusercontent.com/Erreur32/LogviewR/main/scripts/setup-fail2ban-access.sh | sudo bashRun this before
docker compose up, directly on the Docker host (not inside the container). Creates thefail2bangroup, installs a systemd drop-in to persist socket permissions across reboots, and sets SQLite read access. One-time only — survives reboots and fail2ban restarts automatically. Re-run only if you reinstall fail2ban on the host.
Step 3 — Create docker-compose.yml
Download the production file directly:
wget -O docker-compose.yml https://raw.githubusercontent.com/Erreur32/LogviewR/main/docker-compose.ymlOr copy the standard / firewall mode config from the Configuration section below.
Step 4 — Start
docker compose up -dDashboard available at http://your-ip:7500
| Variable | Description | Default | Required |
|---|---|---|---|
JWT_SECRET |
Secret used to sign JWT tokens | — | ✅ Yes |
DASHBOARD_PORT |
Dashboard port (bridge mode with ports:) |
7500 |
No |
PORT |
Direct listen port (network_mode: host mode) |
3000 |
No |
HOST_IP |
Host machine IP address | Auto-detect | No |
CONFIG_FILE_PATH |
Path to external configuration file | /app/config/logviewr.conf |
No |
ADM_GID |
GID of the adm group on the host (system logs) |
4 |
No |
HOST_ROOT_PATH |
Host root path mounted in the container | /host |
No |
Standard mode (without Firewall tabs):
services:
logviewr:
image: ghcr.io/erreur32/logviewr:latest
container_name: logviewr
restart: unless-stopped
ports:
- "${DASHBOARD_PORT:-7500}:3000"
environment:
JWT_SECRET: ${JWT_SECRET}
DASHBOARD_PORT: ${DASHBOARD_PORT:-7500}
HOST_IP: ${HOST_IP:-}
group_add:
- "${ADM_GID:-4}" # adm group — system log read access
volumes:
- ./data:/app/data
- /var/run/fail2ban/fail2ban.sock:/var/run/fail2ban/fail2ban.sock
- /:/host:ro # :ro = more secure; disables Fail2ban VACUUM (see note below)
- /proc:/host/proc:ro
- /sys:/host/sys:ro
# Optional: enable Fail2ban SQLite VACUUM (long-form bind required — short-form does not override :ro)
# - type: bind
# source: /var/lib/fail2ban
# target: /host/var/lib/fail2ban
# bind:
# propagation: shared
# Optional: enable Fail2ban config file editing from the UI (jail.local / fail2ban.local)
# Run once: curl -fsSL https://raw.githubusercontent.com/Erreur32/LogviewR/main/scripts/setup-fail2ban-access.sh | sudo bash
# - type: bind
# source: /etc/fail2ban
# target: /host/etc/fail2ban
# bind:
# propagation: shared
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sFirewall mode (IPTables · IPSet · NFTables tabs enabled) — replace ports: with network_mode: host:
services:
logviewr:
image: ghcr.io/erreur32/logviewr:latest
container_name: logviewr
restart: unless-stopped
# ⚠️ no ports: — incompatible with network_mode: host
network_mode: host
cap_add:
- NET_ADMIN
environment:
JWT_SECRET: ${JWT_SECRET}
PORT: 7500 # direct listen port (replaces ports: mapping)
HOST_IP: ${HOST_IP:-}
group_add:
- "${ADM_GID:-4}"
volumes:
- ./data:/app/data
- /var/run/fail2ban/fail2ban.sock:/var/run/fail2ban/fail2ban.sock
- /:/host:ro # :ro = more secure; disables Fail2ban VACUUM (see note below)
- /proc:/host/proc:ro
- /sys:/host/sys:ro
# Optional: enable Fail2ban SQLite VACUUM (long-form bind required — short-form does not override :ro)
# - type: bind
# source: /var/lib/fail2ban
# target: /host/var/lib/fail2ban
# bind:
# propagation: shared
# Optional: enable Fail2ban config file editing from the UI (jail.local / fail2ban.local)
# Run once: curl -fsSL https://raw.githubusercontent.com/Erreur32/LogviewR/main/scripts/setup-fail2ban-access.sh | sudo bash
# - type: bind
# source: /etc/fail2ban
# target: /host/etc/fail2ban
# bind:
# propagation: shared
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:7500/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sFail2ban optional rw mounts: The
:roflag prevents the container from writing to the host filesystem — recommended for security. Two features require a dedicated rw bind mount (both use the same long-form syntax withpropagation: shared):
Feature Uncomment source:SQLite VACUUM (Fail2ban Config tab) /var/lib/fail2banConfig file editing from the UI ( jail.local/fail2ban.local)/etc/fail2banA simple short-form mount (e.g.
- /etc/fail2ban:/host/etc/fail2ban) does not work — Docker cannot override a:roparent mount with a short-form rw entry. The long-form syntax withpropagation: sharedis required. It takes precedence over/:/host:rofor that path only.For config file editing, also run the setup script once on the host to grant group-write access:
curl -fsSL https://raw.githubusercontent.com/Erreur32/LogviewR/main/scripts/setup-fail2ban-access.sh | sudo bash
Changing the port: only modify PORT: 7500 → PORT: 8080 (or any other), then point your reverse proxy to that port.
Reverse proxy (Nginx Proxy Manager, Caddy, Traefik…) with network_mode: host:
The container listens directly on the host — the reverse proxy connects via 127.0.0.1:
# Nginx Proxy Manager
Forward Hostname : 127.0.0.1
Forward Port : 7500 ← must match PORT=
# Manual Nginx
location / {
proxy_pass http://127.0.0.1:7500;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
# Caddy
reverse_proxy 127.0.0.1:7500
The complete file with all comments is in
docker-compose.ymlat the project root.
The Host System plugin requires access to files owned by root:adm (permissions 640).
The container automatically adds node to the adm group (GID 4).
If your system uses a different GID:
getent group adm | cut -d: -f3 # check the GID on the host
echo "ADM_GID=your_gid" >> .envFiles with restrictive permissions (600)
Some files (/var/log/php8.0-fpm.log, /var/log/rkhunter.log) are owned by root:root 600.
Solution:
sudo chgrp adm /var/log/php8.0-fpm.log* && sudo chmod 640 /var/log/php8.0-fpm.log*- Parser guides — supported formats and regex
- NPM Parser Help — NPM formats
- Nginx Parser Help — Nginx formats
- Host-system integration audit — error/warning scan
Contributions are welcome!
This project is licensed under the MIT License. See LICENSE.
Made with ❤️ for system administrators and developers
Issues | Discussions | Wiki