Hermes-WebUI on WSL2: A Practical Guide to Deployment and LAN Access

Core Question This Article Answers

How do you correctly deploy Hermes-WebUI in a WSL2 environment and make it reliably accessible over a local area network?

This is not a simple “how to run a web app” problem. It is a layered system issue involving:

  • Application layer: whether Hermes-WebUI starts correctly
  • Runtime layer: whether WSL2 exposes the service properly
  • Network layer: whether LAN devices can actually reach it

Most failures happen at the network layer, not at application startup.


1. System Thinking: The “Backstage Theater” Model

Why WSL2 + WebUI behaves like a multi-layer production system

To understand this setup intuitively, imagine a theater production with three separated zones:

  • Backstage (WSL2) → where the application runs
  • Control room (Windows host) → manages routing and port exposure
  • Audience (LAN devices) → consumes the service

Mapping of responsibilities

Layer Analogy Real function
WSL2 Backstage Hermes-WebUI runtime environment
Windows Control room Network forwarding and port management
LAN devices Audience External clients accessing the UI

A common misunderstanding is:

“If the backend is running, the audience can automatically see it.”

In reality:

  • The backend may be running in WSL2
  • Windows may not expose the port
  • The LAN still cannot access the service

2. Architecture of Hermes-WebUI in WSL2

Core runtime structure

From the actual startup logs, the system is split into four major components:

repo root   : /mnt/f/WSL/hermes-webui
agent dir   : /root/.hermes/hermes-agent
python      : /root/.hermes/hermes-agent/venv/bin/python
state dir   : /root/.hermes/webui
workspace   : /root/.hermes/webui/workspace
host:port   : 0.0.0.0:8787
config file : /root/.hermes/config.yaml

2.1 Repository Layer (Source Code)

Location:

/mnt/f/WSL/hermes-webui

Characteristics:

  • Shared between Windows and WSL2
  • Slight IO overhead due to cross-filesystem access
  • Easy to manage and edit from Windows tools

2.2 Isolated Python Agent Environment

Location:

/root/.hermes/hermes-agent/venv/bin/python

This is a self-managed virtual environment.

Purpose:

  • Dependency isolation
  • Version consistency
  • Prevent system Python contamination

2.3 Runtime State Directory

Location:

/root/.hermes/webui

This is the operational memory layer of Hermes-WebUI.

It typically stores:

  • Session state
  • Cache
  • Workspace metadata
  • Runtime context

2.4 Network Entry Point

0.0.0.0:8787

This is the critical requirement for LAN accessibility.


3. Startup Behavior Analysis: Why “Failed” Still Means “Running”

Core Question

Why does the system sometimes report startup failure while the service is actually working?

Example log:

ERROR: Web UI did not become healthy

But later:

/health status 200
Hermes Web UI listening on http://0.0.0.0:8787

Actual startup sequence

Step 1: Server starts

✔ Process is launched successfully

Step 2: Bootstrap health check begins

⚠ Timeout window is relatively short

Step 3: Health endpoint responds correctly

/health returns 200

Step 4: Bootstrap misinterprets timing

⚠ Reports failure due to timeout


Key insight

This is not a system failure. It is a monitoring mismatch problem.

The service is alive, but the bootstrap observer reacts too early.

This pattern is common in distributed systems where:

  • services start asynchronously
  • health checks lag behind runtime readiness

4. Why WSL2 Blocks Direct LAN Access

Core Question

Why can’t WSL2 services be directly accessed from other devices on the same network?

WSL2 operates on a NAT-based virtual network:

LAN Device
   ↓
Windows Host IP
   ↓
WSL2 NAT Layer
   ↓
Hermes-WebUI Service

Even if you bind:

0.0.0.0:8787

This only ensures:

  • Internal WSL accessibility
  • Partial Windows localhost forwarding

It does NOT guarantee:

  • Mobile device access
  • External LAN visibility

5. Production-Grade LAN Access Setup

Goal

Make Hermes-WebUI accessible from any device on the LAN.


Step 1: Bind service to all interfaces

HERMES_WEBUI_HOST=0.0.0.0 HERMES_WEBUI_PORT=8787 ./start.sh

This ensures the service is not restricted to localhost.


Step 2: Verify service is listening

lsof -i :8787

Expected result:

LISTEN 0.0.0.0:8787

Step 3: Retrieve WSL IP (for diagnostics)

ip addr | grep inet

Example:

172.29.xx.xx

Step 4: Windows port forwarding (critical step)

Run in Administrator CMD:

netsh interface portproxy add v4tov4 listenport=8787 listenaddress=0.0.0.0 connectport=8787 connectaddress=127.0.0.1

This bridges WSL2 and Windows networking.


Step 5: Open firewall access

netsh advfirewall firewall add rule name="hermes-webui" dir=in action=allow protocol=TCP localport=8787

Without this, LAN devices cannot connect.


Step 6: Access from LAN devices

http://<Windows-IP>:8787

Example:

http://192.168.1.23:8787

6. Security Considerations

Core Question

Why does Hermes-WebUI warn about missing password protection?

Log:

WARNING: Binding to 0.0.0.0 with NO PASSWORD SET

Security implication

When exposed to LAN:

  • Any device can access the UI
  • File system access may be exposed
  • Agent execution capability may be available

Recommended mitigation

Set a password:

export HERMES_WEBUI_PASSWORD=your_password

Or configure it in config.yaml.


7. Three-Stage Problem Reframing Model

Stage 1: Perceived issue

“I cannot access the WebUI from other devices.”

Stage 2: Actual issue

WSL2 networking isolation + missing port forwarding.

Stage 3: Root cause

Confusion between:

  • service execution layer
  • network exposure layer

Practical Summary Checklist

  • Always bind to 0.0.0.0
  • WSL2 is NAT-isolated by default
  • Windows port forwarding is required
  • Firewall rules must be configured
  • Bootstrap “failure” may be a false negative

One-Page Summary

  • Start service:

    HERMES_WEBUI_HOST=0.0.0.0 ./start.sh
    
  • Access locally:

    http://localhost:8787
    
  • LAN access:

    http://Windows-IP:8787
    
  • Required infrastructure:

    • WSL2 NAT awareness
    • Windows portproxy
    • Firewall configuration
  • Common misconception:
    “Bootstrap error means failure” → often false


FAQ

Q1: Why does bootstrap show failure while the UI works?
Because the health check times out before full initialization completes.

Q2: Can WSL2 services be accessed directly from LAN?
Not by default. Port forwarding is required.

Q3: Why must we use 0.0.0.0 binding?
To allow external interface exposure beyond localhost.

Q4: Why can’t mobile devices access the service?
Because Windows does not forward WSL2 ports automatically.

Q5: Can I change port 8787?
Yes, but all forwarding rules must be updated accordingly.

Q6: Is exposing 0.0.0.0 safe?
No. It requires password protection.

Q7: Why does localhost work on Windows but not LAN?
Because WSL2 integrates localhost forwarding only for host machine access.

Q8: What is the most stable deployment approach?
Docker or tunneling solutions like Tailscale to avoid NAT complexity.