OpenCode 서버 보안: opencode serve와 opencode web을 안전하게 실행하는 방법
opencode serve는 파일을 읽고 셸 명령을 실행할 수 있는 HTTP API를 노출합니다. localhost에 묶어 두고, 비밀번호를 설정하고, TLS를 추가하고, 원격으로 안전하게 접속하는 방법.
- CLI
- 0.2.17
- 프리뷰 ref
- a2c45c8
요약
opencode serve와 opencode web은 HTTP 서버를 실행하며, 그 API는 파일을 읽고, 셸 명령을 실행하고, 설정을 바꾸고, 공급자 자격 증명을 설정할 수 있습니다. 이 서버에 대한 접근은 그 머신에 대한 셸 접근과 같다고 생각하세요.
안전한 설정, 중요한 순서대로:
- 기본 호스트 이름
127.0.0.1을 유지하세요.0.0.0.0바인딩이나--mdns는 직접 관리하는 네트워크에서만 쓰세요. - 내 머신 외의 곳에서 접근할 수 있다면 반드시
OPENCODE_SERVER_PASSWORD를 설정하세요. OpenCode 문서에 따르면 이것이 없으면 서버는 보호되지 않습니다. - 트래픽이 네트워크를 건넌다면 앞단에 TLS를 두세요. 평문 HTTP 위의 Basic 인증은 경로상의 누구나 읽을 수 있는 형태로 비밀번호를 보냅니다.
- 공개 포트 대신 사설 네트워크나 터널로 접속하세요. SSH나 Tailscale 같은 것입니다.
--cors는 좁게 유지하세요. 직접 운영하는 오리진만 추가하세요.
문제
OpenCode의 클라이언트-서버 구조는 장점 중 하나입니다. TUI가 로컬 서버와 통신하므로 브라우저, IDE 플러그인, 스크립트, 다른 컴퓨터에서도 조작할 수 있습니다. 문서는 플래그 하나로 그렇게 하는 방법을 보여 줍니다.
opencode web --port 4096 --hostname 0.0.0.0집에 있는 노트북이라면 이 한 줄로 충분합니다. 하지만 카페 네트워크, 공유 사무실 LAN, 보안 그룹이 열린 클라우드 VM에서는 코딩 에이전트의 제어 API를 그 포트에 닿을 수 있는 모두에게 공개하게 됩니다. 해결책은 몇 가지 설정뿐이지만, 휴대폰을 연결하는 것만이 목표일 때는 건너뛰기 쉽습니다.
OpenCode 서버가 노출하는 것
OpenCode의 서버 문서(2026년 10월 26일 확인)에 따르면 API에는 다음이 포함됩니다.
| 엔드포인트 | 하는 일 |
|---|---|
POST /session/:id/shell | 셸 명령 실행 |
POST /session/:id/message | 에이전트에 프롬프트 전송 |
GET /file/content?path= | 파일 읽기 |
GET /find?pattern= | 파일 내용 검색 |
PATCH /config | 설정 업데이트 |
PUT /auth/:id | 공급자 자격 증명 설정 |
POST /mcp | MCP 서버 추가 |
POST /session/:id/permissions/:permissionID | 권한 요청에 응답 |
GET /doc | OpenAPI 3.1 명세 |
이것들을 호출할 수 있는 사람은 그 머신의 터미널에서 내가 할 수 있는 모든 일을 할 수 있고, 에이전트의 권한 프롬프트에 나 대신 응답할 수 있습니다. 아래 내용은 모두 이 위협 모델을 전제로 합니다.
OpenCode 서버 기본값
서버 문서에 따르면:
| 플래그 | 기본값 | 비고 |
|---|---|---|
--port | 4096 | |
--hostname | 127.0.0.1 | 루프백만 |
--mdns | false | 켜면 호스트 이름이 0.0.0.0이 되고 opencode.local을 알림 |
--cors | 없음 | 추가로 허용할 브라우저 오리진 |
기본값 자체는 안전합니다. 인수 없이 opencode를 실행하면 TUI와 무작위 포트·호스트 이름의 서버가 시작되고, TUI는 이를 백엔드로 사용합니다. 위험은 호스트 이름을 바꾸거나 mDNS를 켤 때 생깁니다.
1단계: 필요하지 않다면 OpenCode를 localhost에 두기
클라이언트가 같은 머신에만 있다면 --hostname을 아예 지정하지 마세요.
opencode serve수신 대기 상태를 확인하세요.
# Linux
ss -ltnp | grep 4096
# macOS
lsof -nP -iTCP:4096 -sTCP:LISTEN0.0.0.0:4096이나 *:4096이 아니라 127.0.0.1:4096이어야 합니다.
2단계: OpenCode 서버에 비밀번호 설정
서버는 환경 변수를 통한 HTTP Basic 인증을 지원하며, opencode serve와 opencode web 모두에 적용됩니다.
export OPENCODE_SERVER_PASSWORD="$(openssl rand -base64 32)"
opencode serve사용자 이름의 기본값은 opencode입니다. 바꾸려면 OPENCODE_SERVER_USERNAME을 설정하세요. 웹 문서에는 주의 사항이 있습니다. OPENCODE_SERVER_PASSWORD가 설정되지 않으면 서버는 보호되지 않으며, 로컬 사용에는 괜찮지만 네트워크 접근 시에는 설정해야 한다고 설명합니다.
비밀번호로 보호된 서버에 TUI를 연결하려면:
opencode attach http://10.20.30.40:4096 --password "$OPENCODE_SERVER_PASSWORD"--password의 기본값은 OPENCODE_SERVER_PASSWORD이므로, 그 셸에 변수가 설정되어 있다면 플래그를 생략할 수 있습니다.
비밀번호를 셸 기록이나 공유 저장소의 dotfiles에 남기지 마세요. 비밀번호 관리자나, 나만 읽을 수 있는 파일을 시작 시 불러오는 방법을 쓰면 됩니다.
3단계: OpenCode 서버 앞단에 TLS 추가
Basic 인증은 요청마다 자격 증명을 보내는데, 인코딩만 되고 암호화되지는 않습니다. 완전히 신뢰할 수 없는 네트워크에서 평문 HTTP를 쓰면 비밀번호가 없는 것과 같습니다. 선택지:
-
리버스 프록시. Caddy나 nginx로 HTTPS를 종료하고
127.0.0.1:4096으로 전달합니다. OpenCode 서버는 루프백에 그대로 있습니다. -
SSH 터널. 새 포트 없이 연결을 암호화합니다.
ssh -N -L 4096:127.0.0.1:4096 you@server그런 다음 내 머신에서 클라이언트를
http://127.0.0.1:4096으로 향하게 합니다. -
사설 네트워크. Tailscale이나 WireGuard는 기기 간 트래픽을 암호화합니다. 그 네트워크의 다른 기기도 포트에 닿을 수 있으므로 비밀번호와 함께 쓰세요.
터널 선택지는 Cloudflare Tunnel vs Tailscale Funnel vs ngrok에서 비교합니다. 포트를 공용 인터넷에 공개하는 것은 조심하세요. 공개 URL에 Basic 인증만 있다면 비밀번호 하나로 지키는 셸입니다.
4단계: OpenCode 포트에 접근할 수 있는 대상 제한
- 클라우드 VM에서는 보안 그룹에서 4096을 열지 마세요. SSH나 사설 네트워크로 접속하세요.
- 홈 서버에서는 라우터의 포트 포워딩에 넣지 마세요.
- mDNS를 쓸 때는
--mdns가0.0.0.0에 바인딩한다는 점을 기억하세요. 집 네트워크에서는 편리하지만 공유 Wi-Fi에는 맞지 않습니다. - 호스트 방화벽에서는 필요한 주소에서만 포트를 허용하세요.
5단계: CORS를 좁게 유지
--cors는 서버 호출이 허용되는 브라우저 오리진을 추가합니다. 추가하는 오리진 하나하나는, 서버에 닿을 수 있는 브라우저에서 스크립트가 내 에이전트와 통신할 수 있는 웹사이트입니다. 직접 운영하는 프런트엔드만 정확한 오리진으로 추가하세요.
opencode serve --cors https://app.example.com6단계: 머신에서의 피해 범위 줄이기
접근 제어를 잘 해도 서버는 내 권한으로 실행됩니다. 실수의 영향을 줄이는 습관:
- 공유 서버에서는 필요한 저장소에만 접근할 수 있고 프로덕션 자격 증명이 없는 별도 사용자로 OpenCode를 실행하세요.
- 셸 명령에 대한 권한 규칙을 엄격하게 유지하세요. 원격 클라이언트가 "허용"을 눌러도 허용하는 사람은 나입니다.
- 다 쓰면 서버를 멈추세요. 몇 주씩 실행되는
opencode serve는 상시 노출입니다.
포트를 열지 않고 휴대폰에서 OpenCode 사용하기
0.0.0.0에 바인딩하는 흔한 이유는 다른 기기에서 OpenCode를 쓰기 위해서입니다. 이는 OpenCode 서버가 루프백 외에는 수신 대기하지 않게 하면서도 할 수 있습니다.
서버를 노출하지 않고 휴대폰에서 OpenCode를 조작하고 싶다면, Happier는 Claude Code, Codex, OpenCode 등 여러 에이전트를 휴대폰, 데스크톱, 웹에서 크로스 디바이스로 실행하고 오케스트레이션할 수 있는 오픈 소스 앱입니다.
Happier가 관리하는 OpenCode 서버를 다루는 방식:
- 루프백만. Happier는 관리형 OpenCode 서버를
--hostname=127.0.0.1과 비어 있는 로컬 포트로 시작하고, 주소가 루프백인 관리형 서버만 재사용합니다. - 관리형 서버마다 비밀번호.
OPENCODE_PASSWORD나OPENCODE_SERVER_PASSWORD를 설정했다면 그것을 사용합니다. 그렇지 않으면 서버마다 하나를 생성해~/.happier/opencode/managed-servers/아래 소유자만 읽을 수 있는 상태 파일에 보관합니다. - 비밀번호는 내 머신에 남습니다. Happier 문서에 따르면 비밀번호는 환경 변수로 서버에 전달되고, Happier의 OpenCode 서버 로그에 기록되지 않으며, 원격 엔드포인트로 전송되지 않습니다.
- 원격 접근은 OpenCode 포트가 아니라 Happier를 거칩니다. 휴대폰, 데스크톱, 웹 앱은 릴레이를 통해 내 컴퓨터의 Happier 데몬과 통신합니다. 세션 내용은 기본적으로 종단간 암호화됩니다. 세션 ID와 타임스탬프 같은 메타데이터는 암호화되지 않습니다. 릴레이를 셀프 호스팅할 수도 있습니다.
OpenCode의 권한 프롬프트는 휴대폰으로 오고, 거기서 응답합니다. happier attach <session-id>는 같은 머신에서 그 세션의 OpenCode TUI를 다시 엽니다. 설정 방법은 휴대폰에서 Happier 사용하기에 있습니다. Happier는 GitHub에 공개되어 있고, 여기서 다운로드할 수 있으며, Discord도 있습니다.
문제 해결
모든 요청이 401을 반환함
클라이언트가 서버가 기대하는 비밀번호를 보내지 않고 있습니다. 클라이언트의 OPENCODE_SERVER_PASSWORD가 서버와 같은지, OPENCODE_SERVER_USERNAME을 바꿨다면 사용자 이름도 같은지 확인하세요. 일부 최신 OpenCode 릴리스는 다른 변수 이름을 읽으므로 opencode --version을 해당 릴리스의 문서와 대조하세요.
다른 머신에서 서버에 접근되면 안 되는데 접근됨
ss -ltnp나 lsof로 수신 대기 주소를 확인하세요. 0.0.0.0이나 *라면 명령이나 서비스 파일에서 --hostname 0.0.0.0 또는 --mdns를 찾아보세요.
브라우저가 사용자 지정 프런트엔드의 요청을 차단함
프런트엔드의 정확한 오리진을 --cors로 추가하세요. 와일드카드는 쓰지 마세요.
opencode attach가 SSH로 연결되지 않음
터널이 열려 있고 원격 쪽의 127.0.0.1:4096을 가리키는지 확인하세요. 원격 IP가 아니라 로컬의 http://127.0.0.1:4096에 연결하세요.
자주 묻는 질문
opencode serve는 기본적으로 안전한가요?
127.0.0.1에서 수신 대기하므로 다른 머신은 접근할 수 없습니다. 같은 머신의 프로세스는 모두 접근할 수 있습니다. OPENCODE_SERVER_PASSWORD가 없으면 인증이 없습니다.
opencode web도 같은 비밀번호를 쓰나요?
네. OpenCode 문서에 따르면 OPENCODE_SERVER_PASSWORD는 opencode serve와 opencode web 모두에 적용됩니다.
OpenCode를 인터넷에 공개할 수 있나요?
할 수는 있지만 API가 셸 명령을 실행합니다. 꼭 해야 한다면 TLS, 강력한 비밀번호, 가능하면 VPN이나 ID 인식 프록시 같은 접근 계층을 앞에 두세요.
OpenAPI 명세 엔드포인트가 위험한가요?
/doc은 API를 설명합니다. 그 자체로 접근 권한을 주지는 않지만 공격 표면을 쉽게 파악하게 해 줍니다. 나머지와 같은 비밀번호로 보호됩니다.