Install
npx skillscat add ecmoce/claude-web Install via the SkillsCat registry.
SKILL.md
Claude Web Gateway
Secure web interface for Claude CLI (Opus) — exposes a minimal HTTPS endpoint on a Mac mini for remote Q&A via browser.
Overview
| Item | Detail |
|---|---|
| Goal | 외부 인터넷에서 웹 브라우저로 Claude CLI(Opus)에 질의/응답 |
| Host | Mac mini (macOS, ARM64, 유선 이더넷) |
| Model | Claude Opus 4.6 via claude CLI |
| Security | Zero-trust: TLS only, token auth, rate limit, no shell escape |
Architecture
[Browser] ──HTTPS──▶ [Reverse Proxy (Caddy)]
│
TLS termination
Token auth check
Rate limiting
│
▼
[Web Server (FastAPI)]
├─ POST /api/chat → Claude CLI 실행
├─ GET /api/history → 대화 이력
├─ GET / → SPA (웹 UI)
└─ WebSocket /ws → 스트리밍 응답
│
▼
[Claude CLI subprocess]
claude --print --model opus
stdin/stdout pipeSecurity Layers
1. Network
- Caddy reverse proxy (자동 HTTPS, Let's Encrypt)
- 포트 443만 외부 노출 (라우터 포트포워딩)
- 내부 서버는 127.0.0.1:8450 바인딩 (외부 직접 접근 불가)
2. Authentication (GitHub OAuth)
- GitHub OAuth App 로그인 (Authorization Code Flow)
- 허용 사용자:
ecmoce만 접근 가능 (ALLOWED_USERS환경변수) - 로그인 후 서버 발급 JWT 세션 토큰 (HttpOnly, Secure, SameSite=Strict)
- 미인증 요청 → GitHub 로그인 페이지로 리다이렉트
- 세션 만료: 24시간, 갱신 가능
3. Rate Limiting
- IP당 분당 10회 요청 제한
- 토큰당 시간당 60회 제한
- 429 Too Many Requests 응답
4. Input Sanitization
- 최대 입력 길이 제한 (10,000자)
- Shell injection 방지 (subprocess with list args, no shell=True)
- Claude CLI 플래그 고정 (사용자가 CLI 옵션 변경 불가)
5. Process Isolation
- Claude CLI를 별도 사용자/sandbox로 실행
- 타임아웃 300초 (무한 대기 방지)
- 동시 실행 제한 (max 3 세션)
Tech Stack
| Component | Choice | Reason |
|---|---|---|
| Web Framework | FastAPI + uvicorn | async, WebSocket 지원, 경량 |
| Reverse Proxy | Caddy | 자동 HTTPS, 설정 간단 |
| Frontend | Vanilla HTML/CSS/JS | 의존성 최소화 |
| Process | asyncio.subprocess | non-blocking CLI 실행 |
| Auth | GitHub OAuth + JWT | ecmoce만 허용, 세션 관리 |
| DDNS | Cloudflare Tunnel 또는 duckdns | 동적 IP 대응 |
File Structure
claude-web/
├── SKILL.md # 이 파일
├── README.md # 프로젝트 설명
├── server/
│ ├── main.py # FastAPI 앱
│ ├── auth.py # GitHub OAuth + JWT 세션
│ ├── claude_runner.py # Claude CLI 실행기
│ ├── rate_limit.py # 속도 제한
│ ├── config.py # 설정 (env vars)
│ └── models.py # Pydantic 스키마
├── web/
│ ├── index.html # 채팅 UI
│ ├── style.css # 스타일
│ └── app.js # 프론트엔드 로직
├── Caddyfile # 리버스 프록시 설정
├── .env.example # 환경변수 템플릿
├── requirements.txt # Python 의존성
├── Makefile # 빌드/실행 명령
└── docs/
├── setup.md # 설치 가이드
└── security.md # 보안 설계 상세Auth Flow (GitHub OAuth)
1. 사용자 → GET /
└─ 세션 없음 → 302 → GitHub OAuth authorize URL
2. GitHub → 사용자 로그인 + 권한 승인
└─ 302 → GET /auth/callback?code=xxx
3. 서버 → GitHub API로 code → access_token 교환
└─ GET https://api.github.com/user (토큰으로 사용자 정보 조회)
└─ login == "ecmoce" 확인
└─ ❌ 불일치 → 403 Forbidden ("접근 권한 없음")
└─ ✅ 일치 → JWT 생성, Set-Cookie (HttpOnly, Secure, SameSite=Strict)
└─ 302 → /
4. 이후 요청: Cookie의 JWT 검증 → 만료/무효 시 다시 1번환경변수
GITHUB_CLIENT_ID=xxx # GitHub OAuth App Client ID
GITHUB_CLIENT_SECRET=xxx # GitHub OAuth App Client Secret
ALLOWED_USERS=ecmoce # 쉼표 구분, 허용 GitHub 사용자
JWT_SECRET=xxx # JWT 서명 키 (랜덤 생성)
SESSION_TTL_HOURS=24 # 세션 유효 시간GitHub OAuth App 설정
- GitHub Settings → Developer settings → OAuth Apps → New
- Homepage URL:
https://your-domain.com - Callback URL:
https://your-domain.com/auth/callback - Scope:
read:user(최소 권한)
API Spec
GET /auth/login
GitHub OAuth 로그인 리다이렉트
GET /auth/callback
OAuth 콜백 — 토큰 교환, 사용자 검증, JWT 발급
GET /auth/logout
세션 쿠키 삭제, 로그아웃
POST /api/chat
// Request
{ "message": "질문 내용", "conversation_id": "optional-uuid" }
// Response (streaming via SSE)
{ "id": "uuid", "content": "응답 텍스트", "model": "opus", "tokens": 1234, "done": true }GET /api/history
// Response
{ "conversations": [{ "id": "uuid", "messages": [...], "created_at": "ISO8601" }] }WebSocket /ws
// Client → Server
{ "type": "message", "content": "질문" }
// Server → Client (스트리밍)
{ "type": "chunk", "content": "응답 조각..." }
{ "type": "done", "tokens": 1234 }Deployment Checklist
- Caddy 설치 및 HTTPS 인증서 설정
- 라우터에서 443 포트포워딩
- DDNS 설정 (도메인 연결)
- 환경변수 설정 (.env)
- Claude CLI 정상 동작 확인
- launchd로 서비스 등록
- 방화벽 규칙 확인 (443만 허용)
- 로그 모니터링 설정
Commands
# 개발
make dev # 로컬 개발 서버 (8450)
# 프로덕션
make setup # 의존성 설치 + Caddy 설정
make start # 서비스 시작
make stop # 서비스 중지
make token # 새 인증 토큰 생성
make logs # 로그 확인Alternatives Considered
| Option | Pros | Cons | Decision |
|---|---|---|---|
| Cloudflare Tunnel | 포트포워딩 불필요, DDoS 방어 | CF 의존, 지연 증가 | 선택 가능 옵션 |
| Tailscale | P2P, 설정 간단 | 클라이언트 설치 필요 | 모바일 불편 |
| SSH tunnel | 매우 안전 | 매번 연결 필요 | 불편 |
| 직접 노출 | 간단 | 보안 위험 | ❌ |