DEV Community

Vigoss Luke
Vigoss Luke

Posted on • Originally published at hermesdocker.com

Deploying Hermes WebUI with Docker — The 8 Errors I Hit and How to Fix Them

Deploying Hermes WebUI with Docker — The 8 Errors I Hit and How to Fix Them

I needed a web UI for the Hermes Agent. Docker Compose looked simple. Eight errors later, I had a working deployment — and a collection of scars I'm about to save you from.

What's Hermes WebUI?

Hermes WebUI is a self-hosted web interface for the Hermes Agent — an open-source AI agent framework with 140K+ GitHub stars and 2.9 trillion daily tokens served through OpenRouter. It's the browser-based dashboard you need to chat with your agent, manage conversations, and monitor usage, all from a Docker container.

The 5-Minute Happy Path

Before we dive into the errors, here's what should happen:

git clone https://github.com/Jakeshadow/hermes-webui-docker-examples.git
cd hermes-webui-docker-examples/single-container
# Create a .env file with your API keys (see .env.example)
docker compose up -d
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:3000, and you're chatting with your Hermes Agent. This actually works for most people on Linux. But if you're on macOS, RHEL, or doing anything slightly custom — buckle up.

Error #1: UID/GID Mismatch (The Silent Killer)

Symptoms: Container starts fine. You mount a volume for persistent data. The container can't write to it — permission denied, or worse, it writes but you can't see the files on your host.

Root cause: The Docker container runs as user UID 1000 (standard Linux user). macOS users run as UID 501. Linux users might be UID 1000, but their GID could be anything. When the container writes files with UID 1000, your host user can't read them.

The fix — set WANTED_UID and WANTED_GID in your .env file:

# .env
WANTED_UID=501
WANTED_GID=20
Enter fullscreen mode Exit fullscreen mode

On macOS, check your UID/GID:

id -u   # usually 501
id -g   # usually 20
Enter fullscreen mode Exit fullscreen mode

On Linux:

id -u   # usually 1000
id -g   # usually 1000
Enter fullscreen mode Exit fullscreen mode

The entrypoint script picks up these variables and creates a matching user inside the container. No more permission whack-a-mole.

Error #2: Empty Mounted Directories

Symptoms: You mount ./data:/app/data, the container starts, but ./data on your host stays empty even though the app seems to be running fine.

Root cause: Docker volume mounts work in one direction at container creation. If you mount an empty host directory to a non-empty container path, the empty host directory wins — it overlays and hides whatever was in the container.

The fix: Pre-create the expected directory structure on the host first, or let the entrypoint script handle initialization after the mount. With Hermes WebUI, the companion repo includes a scripts/init-data.sh that handles this. Run it once:

./scripts/init-data.sh
docker compose up -d
Enter fullscreen mode Exit fullscreen mode

For a deep dive on Docker volume mounting behavior, check out the detail page on hermesdocker.com.

Error #3: docker_mount_cwd_to_workspace Permission Errors

Symptoms: You're using the three-container production setup, and the workspace mount throws errors like Permission denied: /workspace. The gateway container can't access files that clearly exist on the host.

Root cause: This one is a double-whammy. First, the UID/GID issue from Error #1 applies here too. Second, the Docker socket proxy doesn't inherit the right file permissions when the mount crosses container boundaries in the three-container setup.

The fix: Make sure .env has matching UID/GID across all containers, not just the web UI. In the three-container setup:

# Applies to webui, gateway, AND hermes-agent containers
WANTED_UID=1000
WANTED_GID=1000
Enter fullscreen mode Exit fullscreen mode

Then rebuild:

docker compose down
docker compose up -d --build
Enter fullscreen mode Exit fullscreen mode

Error #4: SELinux on RHEL/Fedora

Symptoms: Everything looks right, but the container can't access any mounted volumes. Logs show avc: denied messages.

Root cause: SELinux labels on the host directory block container access.

The fix — add :Z to your volume mounts in docker-compose.yml:

volumes:
  - ./data:/app/data:Z
  - ./workspace:/workspace:Z
Enter fullscreen mode Exit fullscreen mode

The :Z flag tells Docker to relabel the directory for container access. Use :z if multiple containers share the same volume, :Z if it's exclusive to one container.

Why I Chose This Over Open WebUI

I compared Hermes WebUI with Open WebUI before committing. The short version: Open WebUI is feature-rich but heavy — it bundles RAG, document parsing, and a web search engine into one container. Hermes WebUI is focused: it does the agent chat interface and does it well, with three deployment modes that scale from a single Docker command to a production-grade multi-container setup.

The three modes matter:

  • Single-container: One docker compose up -d, perfect for testing
  • Dual-container: Separates the web UI from the gateway for cleaner isolation
  • Three-container: Full production setup with isolated gateway, agent runtime, and web UI

If you want the full comparison breakdown, there's a dedicated page on Hermes WebUI vs Open WebUI.

The Takeaway

Docker makes deployment look deceptively simple — until you hit a permission error at 11 PM. The eight errors I hit all boil down to three root causes: user ID mismatches between host and container, volume mount directionality, and SELinux on enterprise distros. Fix those three and you're golden.

All the working Docker Compose files (single, dual, and three-container modes) are in the GitHub companion repo. Clone it, set your .env, and skip the debugging I already did for you.

Happy deploying.

Top comments (0)