
OpenShell WebUI는 OpenShell CLI의 게이트웨이와 인증 정보를 재사용해 브라우저에서 샌드박스, 정책, 제안, 제공자, 워크스페이스를 관리하는 독립 커뮤니티 도구다. 별도 계정이나 데이터베이스 없이 로컬에서 실행되며, 게이트웨이 사용자에게 허용된 작업만 수행한다.
NVIDIA와 제휴·승인·지원 관계가 없는 비공식 프로젝트다. OpenShell 자체는 공식 저장소와 문서를 참고하면 된다. OpenShell CLI와 등록된 게이트웨이가 필요하며, openshell status에서 Connected 상태인지 확인해야 한다. Docker는 선택 사항이며, 로컬 샌드박스의 실시간 컨테이너 통계를 표시할 때 필요하다.
설치와 실행
가장 간단한 방법은 릴리스 바이너리를 내려받는 것이다. Linux와 macOS의 amd64, arm64용 단일 실행 파일에 UI가 포함된다. Linux 빌드는 정적 바이너리로 제공돼 어떤 배포판에서도 실행할 수 있다. 릴리스에는 SHA-256 체크섬이 담긴 checksums.txt도 포함된다.
os=$(uname -s | tr '[:upper:]' '[:lower:]') # linux or darwin
arch=$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/') # amd64 or arm64
curl -fsSL -o openshell-webui "https://github.com/shaharia-lab/openshell-webui/releases/latest/download/openshell-webui-$os-$arch"
chmod +x openshell-webui
./openshell-webui --open
실행하면 http://127.0.0.1:8787을 연다. 바이너리를 PATH에서 쓰려면 /usr/local/bin이나 ~/.local/bin으로 옮기면 된다. 릴리스 페이지에서 파일을 받을 수 있다.
- Linux x86_64:
openshell-webui-linux-amd64 - Linux arm64:
openshell-webui-linux-arm64 - macOS Apple Silicon:
openshell-webui-darwin-arm64 - macOS Intel:
openshell-webui-darwin-amd64
macOS 바이너리는 공증되지 않았다. curl로 받은 파일에는 격리 플래그가 설정되지 않지만, 브라우저로 받았다면 먼저 다음 명령으로 플래그를 지워야 한다.
xattr -d com.apple.quarantine openshell-webui
Docker 이미지는 linux/amd64와 linux/arm64용으로 제공되며 latest, X.Y, X.Y.Z 태그를 사용한다.
docker run --rm --name openshell-webui \
--network host \
--user "$(id -u):$(id -g)" \
-v ~/.config/openshell:/home/app/.config/openshell:ro \
-v openshell-webui-state:/home/app/.local/state \
ghcr.io/shaharia-lab/openshell-webui:latest
그 뒤 http://127.0.0.1:8787로 접속한다. 이미지 이름 뒤에 --read-only나 --addr 127.0.0.1:9000 같은 플래그를 붙일 수 있다. --network host가 필요한 이유는 로컬 게이트웨이가 127.0.0.1에서만 대기하기 때문이다. Docker 기본 브리지 네트워크의 컨테이너에서는 게이트웨이에 접근할 수 없다. 호스트 네트워크를 사용해도 WebUI는 루프백 주소에서만 대기한다.
--user는 WebUI를 실행한 사용자 권한으로 실행해 게이트웨이의 mTLS 키(0600)를 읽게 한다. 게이트웨이 설정 레지스트리는 읽기 전용으로 마운트하고, 두 번째 볼륨은 재시작 뒤에도 감사 로그를 보존한다. 이 이미지에는 docker CLI와 저널이 없어 개요 화면의 실시간 컨테이너 통계와 로컬 게이트웨이 로그는 제공되지 않는다. 게이트웨이를 통하는 나머지 기능은 사용할 수 있다.
소스에서 빌드하려면 Rust stable과 Bun이 필요하다.
git clone https://github.com/shaharia-lab/openshell-webui.git
cd openshell-webui
make run
make run은 필요한 도구를 확인하고, 게이트웨이에 연결할 수 없으면 systemd 사용자 유닛 또는 Homebrew 서비스를 통해 로컬 게이트웨이를 시작한다. 이어 UI를 포함한 릴리스 바이너리를 빌드하고 http://127.0.0.1:8787을 연다. make build는 실행하지 않고 bin/openshell-webui에 빌드한다.
실행 모드는 기본 쓰기 가능 모드, 읽기 전용 모드, 다른 포트 지정으로 나뉜다.
openshell-webui # read-write
openshell-webui --read-only # look, but never change anything
openshell-webui --addr 127.0.0.1:9000 # another port
소스 체크아웃에서는 같은 설정을 make run, make run ARGS=--read-only, make run ADDR=127.0.0.1:9000으로 지정할 수 있다. 공유 또는 운영 게이트웨이에서 살펴보기만 할 때는 --read-only로 시작하는 것이 권장된다. 변경 요청은 게이트웨이에 도달하기 전에 거부된다. 설정 전체는 Configuration에 정리돼 있다.
기능과 작동 방식
WebUI에서는 게이트웨이별 상태와 샌드박스 수를 확인하고, 로컬 OpenShell 컨테이너의 CPU·메모리 사용량을 볼 수 있다. 샌드박스는 이미지나 템플릿, 네트워크 규칙, 제공자, 리소스, GPU, 레이블, 환경 변수, 서비스 설정을 지정해 만들 수 있으며 시작·중지·삭제할 수 있다.
정책 화면에서는 제공자 규칙을 포함한 유효 정책을 읽고, 규칙·엔드포인트·바이너리를 추가하거나 제거할 수 있다. 정책 전체를 YAML로 편집하고 설정을 변경하는 기능도 있다. 거부된 트래픽에서 작성된 규칙 제안은 변경 사항 비교 형태로 검토·편집한 뒤 승인하거나 거부할 수 있으며, 실행을 되돌리거나 모두 승인하고 제안을 지울 수도 있다. 정책 버전 기록을 살펴보고 두 버전을 비교할 수 있다.
로그는 게이트웨이와 샌드박스에서 실시간으로 받아오며 출처·수준·시간·텍스트로 필터링하고 거부된 연결을 찾을 수 있다. 터미널에서는 샌드박스 셸을 열거나 일회성 명령을 실행한다. xterm.js와 WebSocket을 사용하며, Ctrl+C는 선택 영역 복사, Ctrl+Shift+C/V는 복사와 붙여넣기에 사용된다.
파일 기능에서는 샌드박스 파일 시스템을 탐색하고 파일이나 폴더 전체를 올리거나 내려받을 수 있다. 미리 보기, 편집, 폴더 생성, 삭제도 지원한다. 드래그 앤 드롭 업로드에서는 .git, node_modules, target, dist, .venv와 .gitignore에 일치하는 항목을 건너뛴다. 서비스 화면에서는 샌드박스의 HTTP 포트를 게이트웨이를 통해 노출하거나 제거한다.
제공자 기능은 자격 증명 관리, 교체, 만료, 자동 갱신, 샌드박스별 준비 상태 확인을 지원한다. 저장한 자격 증명은 다시 표시되지 않는다. 제공자 프로필은 CLI YAML 또는 proto JSON 형식으로 가져오고, 검사·편집·삭제할 수 있다. 재사용할 샌드박스 템플릿을 만들거나 삭제할 수 있으며 이미지, 리소스, 환경 변수, 레이블, 드라이버 설정을 담을 수 있다. 템플릿으로 샌드박스를 만들 수도 있다. 워크스페이스를 만들고 삭제하며 구성원과 역할을 관리한다. 게이트웨이 화면에서는 사용자 ID와 역할, 컴퓨트 드라이버, 확장 기능, 게이트웨이 전체 설정, 게이트웨이 로그와 WebUI 감사 로그를 확인한다.
모든 기능은 게이트웨이와 워크스페이스 또는 전체 워크스페이스 범위로 제한되고 자동 새로고침을 지원한다. 화면은 밝은 모드와 어두운 모드를 제공하며 작은 화면에도 맞춰진다. 실제 권한은 게이트웨이가 집행하므로 WebUI는 로그인한 ID가 허용받은 작업만 수행할 수 있다. 사용자 안내서는 화면별 사용법을 설명한다.
백엔드는 상류 OpenShell 프로토콜 정의를 반영해 리플렉션으로 게이트웨이를 호출한다. 동적 gRPC 코덱 하나로 모든 메서드를 처리하고, 비밀 필드는 수동 목록이 아니라 프로토 정의의 주석을 통해 찾는다. 자세한 내용은 아키텍처 문서에 있다.
인증과 보안 조건
WebUI는 CLI와 같은 게이트웨이 인증 정보를 사용한다. 각 게이트웨이 설정은 ~/.config/openshell/gateways/<name>/에서 읽는다.
- mTLS:
mtls/ca.crt,mtls/tls.crt,mtls/tls.key를 사용한다. - OIDC:
oidc_token.json을 bearer 토큰으로 보내며 호출할 때마다 다시 읽는다. 토큰은 CLI로 갱신해야 한다. - 평문 연결:
http://엔드포인트를 사용하며 인증 정보는 없다.
Cloudflare 엣지 게이트웨이는 아직 지원하지 않는다. 정책과 프로필 편집기는 CLI YAML, proto 형태 YAML, proto JSON을 받는다. 알려진 표기 차이만 변환하며 알 수 없는 필드는 오류로 처리하고, 게이트웨이도 결과를 다시 검증한다.
WebUI는 게이트웨이 키를 보유하므로 다음과 같은 보호 장치를 둔다.
127.0.0.1에서만 대기하고 알 수 없는Host헤더를 거부해 DNS 리바인딩과 LAN 접근을 막는다.- 동일 출처
Origin검사와 실행 때마다 생성하는 CSRF 토큰을 모든 쓰기 요청과 WebSocket에 적용한다. Sec-Fetch-Site를 검사해 교차 사이트 요청을 거부한다.- 게이트웨이 메서드 허용 목록(
backend/src/rpcs.rs)으로 샌드박스 토큰, supervisor, peer, 자격 증명 내보내기 RPC에 접근하지 못하게 한다. (openshell.options.v1.secret)표시가 붙은 필드는 모든 응답에서 가린다. 가려진 값을 포함해 다시 보내는 요청은 실제 비밀 정보를 마스크로 덮어쓰지 않도록 거부한다.- 모든 쓰기 작업은 메서드·대상·결과와 함께 감사 로그에 추가한다. 자격 증명과 요청 본문은 기록하지 않는다.
script-src 'self'를 적용한 엄격한 CSP를 사용하며 제3자 CDN이나 글꼴을 불러오지 않는다.--read-only에서는 터미널과 파일 업로드를 포함해 어떤 변경도 허용하지 않는다.
로그인 기능은 없다. 포트에 접근할 수 있는 사람은 게이트웨이 사용자 ID의 권한으로 동작할 수 있다. 인증 프록시를 앞에 두지 않은 채 다른 사람에게 노출하지 말아야 한다. 관련 설정은 --addr와 --allowed-host이며, 설정 문서는 리버스 프록시와 백그라운드 실행도 다룬다.
기본 대기 주소는 127.0.0.1:8787이다. 옵션은 환경 변수로도 설정할 수 있다.
--addr/OPENSHELL_UI_ADDR: 대기 주소. 기본값은127.0.0.1:8787이며 루프백 주소 사용이 권장된다.--open: 기본 브라우저에서 UI를 연다. 기본값은 꺼짐이다.--read-only/OPENSHELL_UI_READ_ONLY: 상태를 바꾸는 모든 작업을 거부한다. 기본값은 꺼짐이다.--audit-log/OPENSHELL_UI_AUDIT_LOG: 모든 쓰기를 기록하는 JSON Lines 파일 경로. 기본값은$XDG_STATE_HOME/openshell-ui/audit.jsonl이다.--gateway-log-dir/OPENSHELL_UI_GATEWAY_LOG_DIR: 로컬 게이트웨이 로그 위치. 기본값은 Homebrew 로그 디렉터리이며, 그렇지 않으면 systemd 저널을 사용한다.--allowed-host/OPENSHELL_UI_ALLOWED_HOSTS: 리버스 프록시용으로 추가 허용할Host값. 기본값은 없다.--timeout-secs/OPENSHELL_UI_TIMEOUT: 게이트웨이 호출 하나의 제한 시간. 기본값은20초다.--no-update-check/OPENSHELL_UI_NO_UPDATE_CHECK: GitHub에 최신 릴리스를 묻지 않는다. 기본값은 꺼짐이다.
사이드바에는 WebUI 버전, PATH에 있는 OpenShell CLI 버전, 저장소 링크가 표시된다. 새 릴리스 확인을 위해 백엔드는 최대 6시간에 한 번 GitHub API를 요청한다. 이 요청에는 게이트웨이 데이터가 포함되지 않으며 --no-update-check로 확인을 끌 수 있다. make를 사용할 때 주소는 ADDR, 그 밖의 플래그는 ARGS로 지정한다. DOCKER_HOST가 설정되지 않았다면 게이트웨이의 gateway.env에 있는 값을 사용해 같은 Docker 엔진에 연결한다.
예제와 개발
examples/claude-sandbox/는 OpenShell 샌드박스 안에서 Claude Code를 실행하는 예제다. Ubuntu 이미지와 claude 바이너리만 Anthropic API에 연결하도록 허용하는 정책, OAuth 토큰을 주입해 토큰이 샌드박스에 노출되지 않도록 하는 제공자 프로필을 사용한다. CLI나 WebUI로 만들 수 있으며 네트워크 송신과 제안 항목을 실시간으로 확인할 수 있다. 이미지는 ghcr.io/shaharia-lab/claude-sandbox:latest에 게시되며 main에서 예제 디렉터리가 바뀔 때마다 다시 빌드된다.
개발 명령은 다음과 같다.
make dev # backend (cargo watch) + frontend (Vite HMR) with hot reload
make backend-dev # backend only, on 127.0.0.1:8787
make frontend-dev # Vite dev server, proxies /api to the backend
make test # cargo test + vitest
make lint # rustfmt, clippy -D warnings, eslint, prettier, tsc
make build # bin/openshell-webui with the frontend embedded
make proto # refresh protos from $OPENSHELL_SRC and regenerate TS types
개발 중에는 출력된 Vite 주소(http://localhost:5173)를 연다. make proto는 OPENSHELL_SRC에 OpenShell 체크아웃이 있어야 하며, 기본 경로는 ~/Projects/OpenShell이다. 상류 커밋은 backend/proto/SOURCE_COMMIT에 기록된다. 개발자 안내서는 로컬 설정, 아키텍처, 상류 OpenShell 추적, 테스트와 단계별 조리법을 다룬다.
릴리스하려면 backend/Cargo.toml의 버전을 설정하고 cargo check를 실행해 Cargo.lock을 맞춘 뒤 변경을 병합한다. 이어 일치하는 태그를 푸시한다.
git tag v0.2.0 && git push origin v0.2.0
태그가 네 개의 바이너리와 checksums.txt가 포함된 GitHub 릴리스, 다중 플랫폼 Docker 이미지를 빌드한다. 태그와 Cargo.toml 버전이 일치하지 않으면 빌드 전에 실패한다. v0.2.0-rc.1처럼 하이픈이 들어간 태그는 사전 릴리스이며 latest를 갱신하지 않는다.
저장소는 Rust 백엔드와 React 19·TypeScript·Vite·Tailwind v4·shadcn/ui 프런트엔드, 예제로 구성된다. 백엔드는 axum, tonic, prost-reflect를 사용한다. backend/src/gateway/에는 CLI 레지스트리, 연결 풀, mTLS/OIDC, 동적 gRPC 코덱이 있고, backend/src/http/에는 경로, 보호 장치, SSE 감시, WebSocket 터미널, 파일 브라우저, 자산이 있다. backend/src/rpcs.rs는 브라우저가 호출할 수 있는 게이트웨이 메서드 허용 목록이며 backend/src/redact.rs는 proto 주석을 이용해 비밀을 가린다. backend/tests/api.rs에는 프로세스 안의 가짜 게이트웨이를 대상으로 한 HTTP 테스트가 있다. 프런트엔드는 src/api/의 형식 지정 클라이언트와 TanStack Query 훅, src/features/의 기능별 디렉터리, src/components/의 공통 UI 구성 요소, proto에서 생성한 src/gen/ 형식으로 나뉜다.
게이트웨이 메서드를 추가할 때는 backend/src/rpcs.rs의 ALLOWED에 Read 또는 Write로 등록한다. 쓰기는 감사 로그에 남고 읽기 전용 모드에서 거부된다. 이어 frontend/src/api/rpc.ts의 형식 지정 맵에 추가하고 useRpc(gw, "Method")로 호출한 뒤 make lint test를 실행한다. sandbox-token, supervisor, peer, credential-export RPC는 허용 목록에 넣지 말아야 한다. 기여자와 AI 에이전트를 위한 추가 규칙은 CLAUDE.md에 있다.
기여는 이슈를 열어 변경 내용과 이유를 설명하고, 포크와 브랜치를 만든 뒤 이슈를 연결한 PR을 제출하는 방식으로 받는다. make lint test를 통과해야 하며 보안 모델을 유지해야 한다. 보안 문제는 공개 이슈가 아니라 GitHub 보안 권고로 비공개 신고한다.
프로젝트는 MIT 라이선스이며 보증은 제공하지 않는다. backend/proto/의 NVIDIA/OpenShell 코드는 Apache License 2.0을 따르고, Rust 크레이트와 npm 패키지(xterm.js와 shadcn/ui 포함)는 각각의 라이선스를 따른다. 저장소에서 코드와 릴리스, 사용자 문서를 확인할 수 있다.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요