feat(webui): add browser terminal interface via ttyd
Adds a webui service to docker-compose that wraps Claude Code in ttyd, serving a browser-accessible terminal on port 7681. The webui reuses Dockerfile.claude (ttyd added to apt deps) with a dedicated entrypoint script that enforces WEBUI_PASSWORD before starting. Network isolation is identical to the CLI container: claude-internal only, all egress via the proxy allowlist. claude.sh gains web and web-stop commands.
This commit is contained in:
parent
c01102b641
commit
9b8562b746
7 changed files with 209 additions and 92 deletions
31
CLAUDE.md
31
CLAUDE.md
|
|
@ -8,35 +8,40 @@ This file provides context and guidance for working with this project.
|
|||
|
||||
## Architecture
|
||||
|
||||
Two containers managed by Docker Compose:
|
||||
Three containers managed by Docker Compose:
|
||||
|
||||
- **`claude`** — Claude Code CLI, non-root (UID 1000), isolated to an internal-only Docker network
|
||||
- **`webui`** — Claude Code as a browser terminal (ttyd on port 7681), same image as `claude`, non-root (UID 1000), same network isolation, basic auth required
|
||||
- **`proxy`** — Squid forward proxy, non-root (UID 13), bridges the internal network to the internet with an egress allowlist
|
||||
|
||||
Key Docker network property: `claude-internal` has `internal: true`, meaning Docker adds no default gateway. The `claude` container physically cannot reach the internet without going through the `proxy` container.
|
||||
Key Docker network property: `claude-internal` has `internal: true`, meaning Docker adds no default gateway. The `claude` and `webui` containers physically cannot reach the internet without going through the `proxy` container.
|
||||
|
||||
The `webui` service reuses `Dockerfile.claude`. Its entrypoint (`webui-entrypoint.sh`) starts `ttyd --credential user:pass claude` instead of `claude` directly.
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
docker-claude/
|
||||
├── claude.sh # Control script: start / stop / run / update / logs / status / shell
|
||||
├── docker-compose.yml # Service definitions and network topology
|
||||
├── Dockerfile.claude # Claude Code container (node:20-slim, UID 1000)
|
||||
├── Dockerfile.proxy # Squid proxy sidecar (ubuntu:22.04, UID 13)
|
||||
├── claude.sh # Control script: start/stop/run/web/web-stop/update/logs/status/shell
|
||||
├── docker-compose.yml # Service definitions and network topology
|
||||
├── Dockerfile.claude # Claude Code + ttyd container (node:20-slim, UID 1000)
|
||||
├── Dockerfile.proxy # Squid proxy sidecar (ubuntu:22.04, UID 13)
|
||||
├── webui-entrypoint.sh # Entrypoint for webui service: starts ttyd wrapping claude
|
||||
├── proxy/
|
||||
│ └── squid.conf # Squid ACL config — egress allowlist lives here
|
||||
├── .env.example # Template for ANTHROPIC_API_KEY
|
||||
├── .gitignore # Excludes .env and logs
|
||||
├── .dockerignore # Keeps .env out of build context
|
||||
└── README.md # User documentation
|
||||
│ └── squid.conf # Squid ACL config — egress allowlist lives here
|
||||
├── .env.example # Template for ANTHROPIC_API_KEY, WEBUI_PASSWORD, etc.
|
||||
├── .gitignore # Excludes .env and logs
|
||||
├── .dockerignore # Keeps .env out of build context
|
||||
└── README.md # User documentation
|
||||
```
|
||||
|
||||
## Development Workflow
|
||||
|
||||
```bash
|
||||
chmod +x claude.sh
|
||||
cp .env.example .env # set ANTHROPIC_API_KEY
|
||||
./claude.sh start # build + start proxy + launch Claude interactively
|
||||
cp .env.example .env # set ANTHROPIC_API_KEY (and WEBUI_PASSWORD for web mode)
|
||||
./claude.sh start # build + start proxy + launch Claude interactively (CLI)
|
||||
./claude.sh web # build + start proxy + webui (browser terminal on :7681)
|
||||
./claude.sh update # rebuild images (no cache) after upstream updates
|
||||
```
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue