SSH를 통한 OAuth/원격 호스트
일부 Hermes 제공업체(현재 xAI Grok OAuth및Spotify)는 루프백 리디렉션 OAuth 흐름을 사용합니다. 인증 서버(xAI, Spotify)는 브라우저를 http://127.0.0.1:<port>/callback로 리디렉션하므로 hermes auth... 명령으로 시작된 작은 HTTP 리스너가 인증 코드를 얻을 수 있습니다.
이는 Hermes와 브라우저가 동일한 컴퓨터에 있을 때 완벽하게 작동합니다. 그렇지 않은 순간 중단됩니다. 노트북의 브라우저는 노트북에서 127.0.0.1에 연결하려고 시도하지만 수신기는 원격 서버의 127.0.0.1에 바인딩됩니다.
수정 사항은 한 줄 SSH 로컬 전달입니다.
TL;DR
# On your local machine (laptop), in a separate terminal:
ssh -N -L 56121:127.0.0.1:56121 user@remote-host
# In your existing SSH session on the remote machine:
hermes auth add xai-oauth --no-browser
# → Hermes prints an authorize URL. Open it in a browser on your laptop.
# → Your browser redirects to 127.0.0.1:56121/callback, the tunnel forwards
# the request to the remote listener, login completes.
포트 56121은 xAI OAuth가 사용하는 포트입니다. Spotify의 경우 43827로 바꾸세요. Hermes는 Waiting for callback on... 줄에 바인딩된 정확한 포트를 인쇄합니다. 거기에서 복사하세요.
어떤 제공자에게 이것이 필요한지
| 제공자 | 루프백 포트 | 터널이 필요합니까? |
|---|---|---|
xai-oauth (Grok SuperGrok) | 56121 | 예, 헤르메스가 멀리 떨어져 있을 때 |
| 스포티파이 | 43827 | 예, 헤르메스가 멀리 떨어져 있을 때 |
anthropic (클로드 프로/맥스) | 해당사항 없음 | 아니요 - 코드 붙여넣기 흐름 |
openai-codex (ChatGPT 플러스/프로) | 해당사항 없음 | 아니요 - 장치 코드 흐름 |
minimax, nous-portal | 해당사항 없음 | 아니요 - 장치 코드 흐름 |
제공자가 테이블에 없으면 터널이 필요하지 않습니다.
리스너가 0.0.0.0만 바인딩할 수 없는 이유
xAI와 Spotify는 모두 허용 목록에 대해 redirect_uri 매개변수를 검증합니다. 둘 다 루프백 형식(http://127.0.0.1:<exact-port>/callback)이 필요합니다. 리스너를 0.0.0.0 또는 다른 포트에 바인딩하면 인증 서버가 리디렉션_uri 불일치로 인해 요청을 거부하게 됩니다. SSH 터널은 루프백 URI를 처음부터 끝까지 그대로 유지합니다.
단계별: 단일 SSH 홉
1. 로컬 머신에서 터널을 시작합니다.
# xAI Grok OAuth (port 56121)
ssh -N -L 56121:127.0.0.1:56121 user@remote-host
# Or for Spotify (port 43827)
ssh -N -L 43827:127.0.0.1:43827 user@remote-host
``-N`은 "원격 셸을 열지 말고 터널을 열어두기만 하세요"를 의미합니다. 로그인하는 동안 이 터미널을 계속 실행하세요.
### 2. 별도의 SSH 세션에서 auth 명령을 실행합니다. \{#2-in-a-separate-ssh-session-run-the-auth-command}
```bash
ssh user@remote-host
hermes auth add xai-oauth --no-browser
# or for Spotify:
# hermes auth add spotify --no-browser
Hermes는 SSH 세션을 감지하고 브라우저 자동 열기를 건너뛰고 인증 URL과 Waiting for callback on http://127.0.0.1:<port>/callback 줄을 인쇄합니다.
3. 로컬 브라우저에서 URL을 엽니다.
원격 터미널에서 인증 URL을 복사하여 노트북의 브라우저에 붙여넣습니다. 동의 화면을 승인합니다. 인증 서버가 http://127.0.0.1:<port>/callback으로 리디렉션됩니다. 브라우저가 터널에 도달하고 요청이 원격 수신기로 전달되며 Hermes는 Login successful!을 인쇄합니다.
성공 라인이 보이면 터널을 해체할 수 있습니다(첫 번째 터미널에서 Ctrl+C).
단계별: 점프박스를 통해
배스천/점프 호스트를 통해 Hermes에 연결하는 경우 SSH에 내장된 -J(ProxyJump)을 사용하세요.
ssh -N -L 56121:127.0.0.1:56121 -J jump-user@jump-host user@final-host
이는 점프 박스 자체에 루프백 포트를 배치하지 않고 점프 호스트를 통해 SSH 연결을 연결합니다. 노트북의 로컬 127.0.0.1:56121은 최종 원격 호스트의 127.0.0.1:56121을 통해 곧바로 터널링됩니다.
-J을 지원하지 않는 이전 OpenSSH의 경우 긴 형식은 다음과 같습니다.
ssh -N \
-o "ProxyCommand=ssh -W %h:%p jump-user@jump-host" \
-L 56121:127.0.0.1:56121 \
user@final-host
모쉬, tmux, SSH ControlMaster
터널은 기본 SSH 연결의 속성입니다. mosh 세션을 통해 tmux 내에서 Hermes를 실행하는 경우 mosh 로밍은 -L 전달을 전달하지 않습니다. -L 터널에 대해 별도의 일반 SSH 세션 만 엽니다. 이는 인증 흐름 동안 활성 상태를 유지해야 하는 연결입니다. 대화형 mosh/tmux 세션은 Hermes를 정상적으로 계속 실행할 수 있습니다.
ssh -o ControlMaster=auto을 사용하는 경우 다중 연결의 포트 전달은 마스터의 수명을 공유합니다. 터널이 나타나지 않으면 마스터를 다시 시작하십시오.
ssh -O exit user@remote-host
ssh -N -L 56121:127.0.0.1:56121 user@remote-host
문제 해결
bind [127.0.0.1]:56121: Address already in use
노트북의 무언가가 이미 해당 포트를 사용하고 있습니다. 이전 터널이 완전히 종료되지 않았거나 현지 헤르메스도 이를 듣고 있습니다. 범인을 찾아서 죽여라:
# macOS / Linux
lsof -iTCP:56121 -sTCP:LISTEN
kill <PID>
그런 다음 ssh -L 명령을 다시 시도하세요.
"연결을 설정할 수 없습니다. 앱에 연결할 수 없습니다." (xAI)
xAI의 승인 페이지는 127.0.0.1:<port>/callback에 대한 리디렉션이 리스너에 도달하지 못할 때 이를 표시합니다. 터널이 실행되고 있지 않거나, 포트가 잘못되었거나, 이전 실행에서 인쇄된 Hermes 포트를 사용하고 있습니다(선호하는 포트가 사용 중인 경우 포트가 자동 범프될 수 있습니다. 항상 최신 Waiting for callback on... 행을 읽으십시오).
xAI authorization timed out waiting for the local callback
위와 동일한 근본 원인 - 리디렉션이 다시 발생하지 않았습니다. 터널이 아직 활성 상태인지 확인하고(ssh -N에 출력이 표시되지 않으므로 터널을 시작한 터미널을 확인하세요) 필요한 경우 다시 시작한 후 hermes auth add xai-oauth --no-browser을 다시 실행하세요.
토큰이 잘못된 ~/.hermes에 도착했습니다.
토큰은 hermes auth add...을 실행한 Linux 사용자 아래에 작성됩니다. 게이트웨이/시스템 서비스가 다른 사용자(예: root 또는 전용 hermes 사용자)로 실행되는 경우 해당 사용자로 인증하여 토큰이 ~/.hermes/auth.json에 보관되도록 합니다. sudo -u hermes -i 또는 이와 동등한 것.