You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ocx status prints unreachable Dashboard: http://localhost:10100/ when a hub binds a non-loopback hostname #3304
ocx status prints a dead dashboard URL (http://localhost:10100/) when a hub binds a non-loopback hostname. In this topology nothing listens on localhost:10100 — the public listener moved to the tailnet IP and the loopback data listener (10102) serves only the API — so the printed URL is unreachable. The reachable dashboard is the management ingress origin (hub.managementPublicOrigin). Misleading during remote-hub ops: it sent me hunting for a broken GUI before I realized the listener layout had moved.
Reproduction
Configure opencodex 2.40.0 with runtimeRole: hub on macOS: hostname = tailnet IP (public data-plane listener), unauthenticatedLoopbackListener on 10102, hub.managementIngress on 10101 behind tailscale serve, hub.managementPublicOrigin set.
Run:
$ ocx status
✅ Proxy: running (PID …)
Health: http://100.x.x.x:10100/healthz ok (live)
Dashboard: http://localhost:10100/ <-- nothing listens there in this shape
Observe that the printed dashboard URL cannot be opened, while hub.managementPublicOrigin works in a browser.
Version
2.40.0
Operating system
macOS 26
Provider and model
No response
Logs or error output
$ ocx status
Health: http://100.x.x.x:10100/healthz ok (live)
Dashboard: http://localhost:10100/
When runtimeRole: hub (or when hostname is non-loopback and managementIngress is enabled), print hub.managementPublicOrigin as the dashboard URL instead of http://localhost:<port>/.
Checks
I searched existing issues and documentation.
I removed secrets, tokens, account details, request credentials, and personal data.
Re-filing of #3287 (auto-closed by the issue-quality bot because the original freeform body did not follow the Bug report form — content unchanged).
설명
이 이슈는 ocx status가 찍어 주는 Dashboard 주소가 실제 리스너 배치와 안 맞는다는 버그입니다. 지금 dev(HEAD 2e74a35d4)의 src/cli/status.ts를 보면 selectListenTarget(136행)과 collectStatus live 분기(344행) 둘 다 dashboardUrl을 http://localhost:${port}/로 만듭니다. healthUrl만 probeHostname(hostname)을 쓰고, Dashboard는 항상 루프백을 가리킵니다. 허브가 테일넷 IP 같은 non-loopback에 붙거나 GUI가 hub.managementPublicOrigin 쪽으로 빠진 배치에서는 그 주소에 아무것도 안 떠서, 운영자가 깨진 화면을 찾게 됩니다. 제보의 출력(Health: http://100.x.x.x:10100/healthz vs Dashboard: http://localhost:10100/)과 코드가 한 줄로 이어집니다.
왜 지금 중요한가. 원격 허브/테일넷 배치가 늘어나면서 ocx status는 “어디를 열면 GUI가 보이는지”를 한눈에 보여 줘야 합니다. health는 이미 실제 호스트를 보고 있는데 Dashboard만 localhost로 남는 불일치는 운영 실수로 이어지기 쉽습니다. 제보 토폴로지는 hostname = 테일넷 IP, unauthenticatedLoopbackListener 10102, hub.managementIngress 10101 뒤 tailscale serve, hub.managementPublicOrigin이 있는 형태입니다. 이 배치에서 진짜 열리는 대시보드는 management origin이고, localhost:10100에는 리스너가 없습니다. 루프백만 쓰는 평범한 설치에서는 예전 주소가 맞으니, 고칠 때도 그 경로는 그대로 나와야 합니다.
Ready PR #3308이 이미 그 규칙을 한곳에 모았습니다. 새 statusDashboardUrl 헬퍼는 runtimeRole === "hub"이고 hub.managementPublicOrigin이 있으면 그 origin(끝 / 보정)을 쓰고, 없으면 probeHostname 결과를 루프백이면 localhost, 아니면 그대로 써서 http://호스트:포트/를 만듭니다. selectListenTarget의 config 타입이 runtimeRole/hub까지 넓어지고, live 분기도 같은 헬퍼를 탑니다. 테스트는 tests/cli-status-json.test.ts에 루프백 유지, 허브+managementPublicOrigin, non-loopback 호스트 세 경우를 넣었고 red-first(2 fail) → green(26 pass)입니다. 이 PR 리뷰는 이미 74/80으로 머지를 권했고, 본문에 Closes #3304가 있습니다.
설계를 이 이슈에서 다시 열 필요는 없습니다. 같은 파일 probeUncleanExitState(301행)는 비정상 종료 판별용 checkProxyHealth에 쓰는 ListenTarget이라 화면에 그대로 안 나갈 수 있습니다. Dashboard 규칙이 파일 안에 두 갈래로 남는 자국은 #3308 리뷰에서 후속으로 남겨 두었습니다. managementPublicOrigin 없이 ingress만 다른 포트인 극단 배치도 이번 이슈 본문 범위 밖입니다. types.ts/config.ts 분할과도 무관한 좁은 CLI 표시 픽스이고, 현재 dev tip(#3302 콤보 쿼터 스킵)과 파일이 겹치지 않습니다.
이 이슈는 #3287을 품질 봇이 폼 미준수로 닫은 뒤 같은 내용으로 다시 올린 것입니다. 고치는 쪽은 #3308 하나면 충분합니다. 제보에 실기 테일넷 허브 검증이 빠져 있다는 점은 PR 본문도 솔직히 적었습니다. focused 테스트가 세 레이아웃을 잠그므로, 그 한계를 이유로 이 이슈를 열린 채로 두지 마세요.
라인 136 - selectListenTarget이 Dashboard를 무조건 http://localhost:${port}/로 만든다. health는 실제 호스트를 쓰는데 Dashboard만 루프백이다
라인 344 - collectStatus live 분기도 같은 localhost 하드코딩이라, 프록시가 살아 있어도 찍히는 주소가 틀린다
라인 301 - probeUncleanExitState의 dashboardUrl도 localhost다. 표시 경로는 아니라 #3308 범위 밖·후속이다
경로 hub.managementPublicOrigin - 제보 토폴로지에서 실제로 열리는 GUI origin. #3308이 허브일 때 이 값을 쓴다
경로 #3308 - Ready PR. Closes #3304. 리뷰 74/80, 머지 권고 댓글이 이미 있다
ocx status was printing a constant rather than reading the layout. The dashboard URL is now derived from the listeners that actually exist: a hub with hub.managementPublicOrigin set reports that origin, and otherwise status reflects the real bound hostname and port. Ordinary loopback setups print exactly what they printed before.
"It sent me hunting for a broken GUI before I realized the listener layout had moved" is the part that made this worth fixing rather than documenting — a wrong URL costs more than a missing one.
One caveat: no live tailnet hub was available here, so the three layouts (loopback, hub with a management origin, non-loopback without one) are covered by focused tests rather than verified against a real remote hub. If you get a chance to run ocx status on your setup after this lands, I would be glad to hear whether the printed URL is now the reachable one.
Activity
lidge-jun commentedon Sep 2, 2026
리뷰 · 우선순위 74 / 80
설명
이 이슈는
ocx status가 찍어 주는 Dashboard 주소가 실제 리스너 배치와 안 맞는다는 버그입니다. 지금dev(HEAD2e74a35d4)의src/cli/status.ts를 보면selectListenTarget(136행)과collectStatuslive 분기(344행) 둘 다dashboardUrl을http://localhost:${port}/로 만듭니다.healthUrl만probeHostname(hostname)을 쓰고, Dashboard는 항상 루프백을 가리킵니다. 허브가 테일넷 IP 같은 non-loopback에 붙거나 GUI가hub.managementPublicOrigin쪽으로 빠진 배치에서는 그 주소에 아무것도 안 떠서, 운영자가 깨진 화면을 찾게 됩니다. 제보의 출력(Health: http://100.x.x.x:10100/healthzvsDashboard: http://localhost:10100/)과 코드가 한 줄로 이어집니다.왜 지금 중요한가. 원격 허브/테일넷 배치가 늘어나면서
ocx status는 “어디를 열면 GUI가 보이는지”를 한눈에 보여 줘야 합니다. health는 이미 실제 호스트를 보고 있는데 Dashboard만 localhost로 남는 불일치는 운영 실수로 이어지기 쉽습니다. 제보 토폴로지는hostname= 테일넷 IP,unauthenticatedLoopbackListener10102,hub.managementIngress10101 뒤tailscale serve,hub.managementPublicOrigin이 있는 형태입니다. 이 배치에서 진짜 열리는 대시보드는 management origin이고, localhost:10100에는 리스너가 없습니다. 루프백만 쓰는 평범한 설치에서는 예전 주소가 맞으니, 고칠 때도 그 경로는 그대로 나와야 합니다.Ready PR #3308이 이미 그 규칙을 한곳에 모았습니다. 새
statusDashboardUrl헬퍼는runtimeRole === "hub"이고hub.managementPublicOrigin이 있으면 그 origin(끝/보정)을 쓰고, 없으면probeHostname결과를 루프백이면localhost, 아니면 그대로 써서http://호스트:포트/를 만듭니다.selectListenTarget의 config 타입이runtimeRole/hub까지 넓어지고, live 분기도 같은 헬퍼를 탑니다. 테스트는tests/cli-status-json.test.ts에 루프백 유지, 허브+managementPublicOrigin, non-loopback 호스트 세 경우를 넣었고 red-first(2 fail) → green(26 pass)입니다. 이 PR 리뷰는 이미 74/80으로 머지를 권했고, 본문에 Closes #3304가 있습니다.설계를 이 이슈에서 다시 열 필요는 없습니다. 같은 파일
probeUncleanExitState(301행)는 비정상 종료 판별용checkProxyHealth에 쓰는ListenTarget이라 화면에 그대로 안 나갈 수 있습니다. Dashboard 규칙이 파일 안에 두 갈래로 남는 자국은 #3308 리뷰에서 후속으로 남겨 두었습니다. managementPublicOrigin 없이 ingress만 다른 포트인 극단 배치도 이번 이슈 본문 범위 밖입니다. types.ts/config.ts 분할과도 무관한 좁은 CLI 표시 픽스이고, 현재devtip(#3302 콤보 쿼터 스킵)과 파일이 겹치지 않습니다.이 이슈는 #3287을 품질 봇이 폼 미준수로 닫은 뒤 같은 내용으로 다시 올린 것입니다. 고치는 쪽은 #3308 하나면 충분합니다. 제보에 실기 테일넷 허브 검증이 빠져 있다는 점은 PR 본문도 솔직히 적었습니다. focused 테스트가 세 레이아웃을 잠그므로, 그 한계를 이유로 이 이슈를 열린 채로 두지 마세요.
라인 136 -
selectListenTarget이 Dashboard를 무조건http://localhost:${port}/로 만든다. health는 실제 호스트를 쓰는데 Dashboard만 루프백이다라인 344 -
collectStatuslive 분기도 같은 localhost 하드코딩이라, 프록시가 살아 있어도 찍히는 주소가 틀린다라인 301 -
probeUncleanExitState의dashboardUrl도 localhost다. 표시 경로는 아니라 #3308 범위 밖·후속이다경로
hub.managementPublicOrigin- 제보 토폴로지에서 실제로 열리는 GUI origin. #3308이 허브일 때 이 값을 쓴다경로 #3308 - Ready PR. Closes #3304. 리뷰 74/80, 머지 권고 댓글이 이미 있다
메인테이너의 판단이 필요한 지점
probeUncleanExitState의 localhost Dashboard를 후속 한 줄로 헬퍼에 맞출지(이번 PR에 억지로 넣지 말 것)너의 추천
#3308을 머지하고 이 이슈를 그 PR로 닫으세요. 설계를 다시 열지 마세요. 루프백 배치는 테스트로 예전 주소가 유지됩니다. unclean-exit 경로 통일은 원하면 한 줄 follow-up이면 됩니다.
이 댓글은 grok-bot이 작성했습니다
lidge-jun commentedon Sep 2, 2026
Fixed on
devin PR #3308.ocx statuswas printing a constant rather than reading the layout. The dashboard URL is now derived from the listeners that actually exist: a hub withhub.managementPublicOriginset reports that origin, and otherwise status reflects the real bound hostname and port. Ordinary loopback setups print exactly what they printed before."It sent me hunting for a broken GUI before I realized the listener layout had moved" is the part that made this worth fixing rather than documenting — a wrong URL costs more than a missing one.
One caveat: no live tailnet hub was available here, so the three layouts (loopback, hub with a management origin, non-loopback without one) are covered by focused tests rather than verified against a real remote hub. If you get a chance to run
ocx statuson your setup after this lands, I would be glad to hear whether the printed URL is now the reachable one.