Skip to content

Node Agent ​

The agent runs on every node and does three things: reads the Xray access.log and ships connections to the panel, collects host and network metrics, and keeps a command channel open (terminal, scripts, block lists).

Without it there is no anti-abuse — the panel simply has no way to know who connects from where.

One-line install ​

The panel builds the command for you, token included:

  1. Servers → Panel nodes → the node menu → Agent token → Install agent
  2. Copy the resulting line and run it on the node:
bash
curl -fsSL --retry 3 --retry-delay 2 \
  https://raw.githubusercontent.com/Case211/remnawave-admin/main/node-agent/install.sh \
  -o /tmp/rwa-node-agent-install.sh \
  && bash /tmp/rwa-node-agent-install.sh --uuid UUID --url URL --token TOKEN

The script creates /opt/remnawave-node-agent/, downloads docker-compose.yml, writes .env and starts the container.

FlagPurposeDefault
--uuidnode UUIDrequired
--urlpanel addressrequired
--tokenagent tokenrequired
--intervalhow often to send data, seconds30
--ws-secretcommand signing key, the WEB_SECRET_KEY of the panel—
--no-commandskip the command channel—
--no-host-modedo not run commands on the host—
--dirinstall directory/opt/remnawave-node-agent

Manual install ​

Generate the token in the panel (Servers → Panel nodes → node menu → Agent token) or in the bot. It is shown once.

bash
mkdir -p /opt/remnawave-node-agent && cd /opt/remnawave-node-agent
curl -fsSLO --retry 3 --retry-delay 2 https://raw.githubusercontent.com/Case211/remnawave-admin/main/node-agent/docker-compose.yml
nano .env
docker compose up -d
ini
AGENT_NODE_UUID=fd3a2983-4f68-45eb-8652-7557d7e15f7a
AGENT_COLLECTOR_URL=https://admin.example.com
AGENT_AUTH_TOKEN=token_from_the_panel
AGENT_INTERVAL_SECONDS=30
AGENT_XRAY_LOG_PATH=/var/log/remnanode/access.log

The image comes ready-made: ghcr.io/case211/remnawave-admin-node-agent:latest.

Agent variables ​

VariableWhat it setsDefault
AGENT_NODE_UUIDnode UUID from the Remnawave panelrequired
AGENT_COLLECTOR_URLRemnawave Admin addressrequired
AGENT_AUTH_TOKENtoken of this noderequired
AGENT_INTERVAL_SECONDSbatch interval30
AGENT_LOG_PARSING_MODErealtime or pollingrealtime
AGENT_XRAY_LOG_PATHpath to access.log/var/log/remnanode/access.log
AGENT_MAX_BUFFER_SIZEconnection buffer ceiling50000
AGENT_SEND_MAX_RETRIESbatch send attempts3
AGENT_SEND_RETRY_DELAY_SECONDSpause between attempts5.0
AGENT_LOG_LEVELlog levelINFO
AGENT_COMMAND_ENABLEDcommand channel from the panelfalse
AGENT_WS_URLWebSocket address if it differs= AGENT_COLLECTOR_URL
AGENT_WS_SECRET_KEYcommand signature key—

The AGENT_NDPI_* variables are covered in Torrent detection.

Checking ​

bash
docker compose logs -f

A healthy start looks like this:

INFO: Collector API OK: https://admin.example.com/api/v2/collector/health
INFO: Log file found: /var/log/remnanode/access.log (size: X bytes)
INFO: Node Agent started: node_uuid=..., mode=realtime, interval=30s
INFO: Real-time parsing: new_lines=X accepted_lines=X connections=X

On shutdown the agent flushes what it has instead of dropping it:

INFO: Shutdown: sending remaining X accumulated connections...
INFO: Node Agent stopped

Proxy in front of the collector ​

The agent talks to /api/v2/collector/* and holds a WebSocket on /api/v2/agent/ws. Both must pass through your reverse proxy — sample configs are in Web panel and reverse proxy.

What the agent reads ​

A Remnawave log line looks like this:

2026/01/28 11:23:18.306521 from 188.170.87.33:20129 accepted tcp:accounts.google.com:443 [Sweden1 >> DIRECT] email: 154

email: 154 is a user identifier, not an address: the collector resolves it by short_uuid, email or ID. IPv4 and IPv6 are both supported. If your log format differs, the parser lives in node-agent/src/collectors/xray_log.py.

Your own servers without Xray ​

The agent also works on a server that is not a Remnawave node: the bot, the panel itself, a database. It collects CPU, memory, disk and network, keeps the command channel (terminal, scripts), and simply runs in "metrics only" mode when there is no Xray log.

  1. Servers → Fleet → Add server, enter a name and an address.
  2. Copy the install command from the response and run it on the server: it is the same command as for nodes, only the UUID is issued by the admin panel rather than by Remnawave.
  3. The server shows up in Fleet with a "Server" badge after the first agent report. Alert rules for CPU, RAM, disk and "not responding" apply to it as well.

Such servers do not appear in the Panel nodes tab or in the node counters on the dashboard, and the panel sync leaves them alone. Connectivity follows the metrics: an agent silent for more than five minutes means the server is offline. Remove it with the button in its Fleet card; stop the agent container on the server yourself afterwards.

Upgrading ​

bash
cd /opt/remnawave-node-agent
docker compose pull
docker compose up -d

If the agent was once installed as a local build (build: . in compose), move to the published image: stop the container, keep your .env, take the current docker-compose.yml from the repository and start again. Newer versions add a healthcheck, resource limits, graceful shutdown and a connectivity check at startup.

If no data arrives ​

  • The agent cannot see the log. Make sure the path in AGENT_XRAY_LOG_PATH exists inside the container and is mounted in docker-compose.yml
  • The collector does not answer. The address in AGENT_COLLECTOR_URL must be reachable from the node: curl https://admin.example.com/api/v2/collector/health
  • server rejected WebSocket connection: HTTP 404. The reverse proxy is not passing /api/v2/agent/ws, so the terminal and live node status will not work
  • Commands are rejected. AGENT_WS_SECRET_KEY on the node must match the WEB_SECRET_KEY of the panel: commands are HMAC-signed

AGPL-3.0 with a plugin exception