Codex リモートログイン手順(最新版・実戦対応フルガイド)

に公開

Codex リモートログイン手順(最新版・実戦対応フルガイド)

目的:ヘッドレスなリモートサーバー(例:golgi)上で codex login を安定して成功させる。
本書は仕組み・標準手順・エラーの切り分け・掃除コマンド・応用例まで現場でそのまま使える形でまとめています。


0. TL;DR(最短経路)

前提:手元にブラウザあり。リモートは golgi。JumpHost は ~/.ssh/config で設定済み。

別ターミナルA(ローカル)

ssh -fN -o ExitOnForwardFailure=yes \
  -L 127.0.0.1:1455:127.0.0.1:1455 golgi

別ターミナルB(リモート)

ssh golgi
codex login

ターミナルに出る URL をローカルのブラウザで開く。
ダメなときは URL 中の localhost127.0.0.1 に置換して開き直す。

これで終わるのが通常。詰まったら以下の切り分けへ。


1. 仕組み(なぜトンネルが要るのか)

  • codex loginhttp://localhost:1455一時的な認証受け口(小さなHTTPサーバ)を立てる。

  • ブラウザは手元(ローカル)codexリモートで動くため、そのままだとコールバックがローカルに落ちて終わり。リモートの codex には届かない。

  • そこで SSH ローカルフォワード(ssh -L を使って、

    • ローカル127.0.0.1:1455 へのアクセス ⇒ トンネル経由リモート127.0.0.1:1455 に橋渡しする。
  • こうすると、ローカルのブラウザでコールバックを開くだけで、リモートの codex に到達してログイン完了。

localhost だと環境により ::1(IPv6)へ行くことがある。127.0.0.1(IPv4)を強制すると安定。


2. 役割と用語

  • ローカル:あなたのPC(例:yt@yt-Z490-S01)。ブラウザがある側。SSHクライアント側。
  • リモート:サーバ(例:golgi)。codex login を実行して1455で待つ側
  • トンネルssh -L 127.0.0.1:1455:127.0.0.1:1455 <host> によるローカル→リモートの転送路。

3. 標準手順(再現性重視)

3.1 前提の確認

  • sshgolgi に入れること(JumpHost は ~/.ssh/configProxyJump 設定済みでOK)。
  • ブラウザはローカルにある。

3.2 実行順序

(1) トンネルを張る(ローカル)

ssh -fN -o ExitOnForwardFailure=yes \
  -L 127.0.0.1:1455:127.0.0.1:1455 golgi
  • -fN:バックグラウンド・コマンド実行なし。
  • ExitOnForwardFailure=yes:ポート競合などで即失敗してくれる(成功/失敗が分かりやすい)。

(2) 1455 の LISTEN を確認(ローカル)

ss -lptn 'sport = :1455'
# 例) users:(('ssh',pid=12345,fd=4)) と出ればOK(ローカルの ssh が LISTEN)

(3) リモートで codex login を実行

ssh golgi
codex login
# 端末に出た長い URL をローカルのブラウザで開く
# うまくいかなければ URL の localhost → 127.0.0.1 に置換

(4) 完了後

  • 使い終えたらトンネルを閉じる:
pkill -f 'ssh -N -L .*1455:127.0.0.1:1455' || true

4. エラーの「場所」を即断する(一次切り分け)

どこで出た? エラーメッセージ例 よくある原因 見るべき場所
ローカルで ssh -L bind [127.0.0.1]:1455: Address already in use / cannot listen to port: 1455 ローカル1455が既に誰かに占有(既存の ssh -L、ローカル codex 等) ローカルで ss/lsof
リモートで codex login Error logging in: Port 127.0.0.1:1455 is already in use リモート1455codex/sshd -R/残骸が占有 リモートで ss/lsof
ブラウザ認証後も終わらない (無反応) コールバックがリモートに届いていない(トンネル未張り/宛先違い/IPv6) トンネル確認、URLの 127.0.0.1 強制

まず どちら側の 1455 が詰まってるかを切り分けると、対処は一瞬で決まります。


5. トラブルシュート(実コマンド集)

5.1 ローカル側 1455 が埋まっている

症状ssh -L 実行時に Address already in use など。

ローカルで実行

# だれが掴んでいる?
ss -lptn 'sport = :1455' || true
lsof -iTCP:1455 -sTCP:LISTEN -n -P || true
pgrep -af 'ssh -N -L .*1455:127.0.0.1:1455|codex' || true

# 掴んでいる ssh/codex を落とす
pkill -f 'ssh -N -L .*1455:127.0.0.1:1455' || true
pkill -f '^codex .*login' || true

# root が掴んでいそうなら確認して PID 指定で kill
sudo lsof -iTCP:1455 -sTCP:LISTEN -n -P
# → 表示された PID を sudo kill <PID>

再試行

ssh -fN -o ExitOnForwardFailure=yes \
  -L 127.0.0.1:1455:127.0.0.1:1455 golgi
ss -lptn 'sport = :1455'

既存トンネルが目的のホスト向けなら、わざわざ落とさず“そのまま使う”のも手です。例:ps -p <PID> -o pid,etimes,cmd で宛先が golgi か確認。


5.2 リモート側 1455 が埋まっている

症状codex login 側で Port 127.0.0.1:1455 is already in use

リモート(golgi)で実行

ss -lptn 'sport = :1455'
sudo lsof -iTCP:1455 -sTCP:LISTEN -n -P
ps -ef | egrep 'ssh.* -R .*1455|codex|app-server' | grep -v egrep

# 安全速攻で掃除(誰が掴んでいても落とす)
sudo fuser -k 1455/tcp
for p in $(sudo lsof -tiTCP:1455 -sTCP:LISTEN); do
  sudo kill -TERM "$p" || true; sleep 1; sudo kill -KILL "$p" || true
done

# 解放確認
ss -lptn 'sport = :1455' || true
sudo lsof -iTCP:1455 -sTCP:LISTEN -n -P || true

# 改めて
codex login

よくある犯人

  • 以前の codex login停止(Stopped)状態でポート保持。
  • 昔打った **ssh -R 127.0.0.1:1455:...(リバースフォワード)**の残骸。

5.3 宛先ホストの取り違え(ケーススタディ)

現象:ローカル 1455 は既に ssh が LISTEN しているが、そのトンネルの宛先が gvelox。本来は golgi に通したい。

対処(ローカル)

# どこ向きのトンネル?
ps -p <PID> -o pid,etimes,cmd --cols=200
cat /proc/<PID>/cmdline | tr '\0' ' '

# 宛先が違うなら落として作り直し
kill <PID> || true; sleep 1; kill -9 <PID> || true
ssh -fN -o ExitOnForwardFailure=yes -L 127.0.0.1:1455:127.0.0.1:1455 golgi

5.4 localhost でこける

現象:ブラウザで認証したのに codex が完了しない。
原因localhost::1(IPv6)へ解決されトンネルに乗らないことがある。

対処:認証URLの localhost127.0.0.1 に置換して開く。


5.5 二重起動の罠

  • 既にローカルにトンネルがあるのに、さらに ssh -L を起動すると**Address already in use**。
  • 解決:既存トンネルを使うか、一旦落としてから張り直す。

5.6 JumpHost / 多段 SSH(必要なとき)

# 一発指定(ローカルで)
ssh -fN -o ExitOnForwardFailure=yes \
  -J bastion \
  -L 127.0.0.1:1455:127.0.0.1:1455 golgi

~/.ssh/configProxyJump bastion を書いておけば -J 省略可。


5.7 tmux/screen や systemd/autossh の影響

  • バックグラウンド化されたトンネルが無自覚に生き続けることがある。pkill -f 'ssh -N -L .*1455:127.0.0.1:1455' で掃除。
  • autossh や systemd ユーザーサービスで自動復活していると、落としても再起動する。ps -o pid,ppid,cmd --forest -p <PID> で親プロセスを確認。

6. 疎通確認&デバッグ

ローカル

ss -lptn 'sport = :1455'

リモート(golgi)

ss -lptn 'sport = :1455'

トンネル越しの到達可否(ローカルから)

# リモートに 1455 のHTTPサーバ(codex)が立っていれば 200/302/404 等が返る
curl -i http://127.0.0.1:1455/ || true

7. 応用編

7.1 逆方向(リモートにブラウザ、ローカルに callback)

# ローカルで実行:リバースフォワード
ssh -N -R 127.0.0.1:1455:127.0.0.1:1455 golgi

7.2 ブラウザ→コピー→curl(GUIなしでも完了させる)

  1. リモートで codex login を実行し、URL を取得。
  2. ローカルで URL を開いて認証。
  3. ブラウザが開こうとする http://localhost:1455/auth/callback?... を丸ごとコピー
  4. リモートで:
curl -iL "http://localhost:1455/auth/callback?code=...&state=..."

これでトンネルなしでも完了できる(非常用)。


8. ワンライナー&エイリアス

一撃ログイン(標準)

# ターミナルA(ローカル)
ssh -fN -o ExitOnForwardFailure=yes -L 127.0.0.1:1455:127.0.0.1:1455 golgi
# ターミナルB(リモート)
ssh golgi && codex login

残骸掃除(ローカル)

( ss -lptn 'sport = :1455' || true ); \
( lsof -iTCP:1455 -sTCP:LISTEN -n -P || true ); \
( pkill -f 'ssh -N -L .*1455:127.0.0.1:1455' || true ); \
( pkill -f '^codex .*login' || true )

残骸掃除(リモート)

sudo fuser -k 1455/tcp; \
for p in $(sudo lsof -tiTCP:1455 -sTCP:LISTEN); do
  sudo kill -TERM "$p" || true; sleep 1; sudo kill -KILL "$p" || true;
done

9. セキュリティ注意

  • バインドは 127.0.0.1 限定0.0.0.0 で外部に晒さない)。
  • 認可URL(code, state 等を含む)は第三者と共有しない
  • 終了後はトンネルを閉じる(pkill -f ...)。

10. エラー辞典(クイックリファレンス)

エラー 原因 対処
bind [127.0.0.1]:1455: Address already in use ローカル 1455 が埋まっている ローカルで ss/lsof → 掴んでる ssh/codex を kill → 再トンネル
cannot listen to port: 1455 同上 同上
Error logging in: Port 127.0.0.1:1455 is already in use リモート 1455 が埋まっている リモートで fuser -k 1455/tcpcodex login 再実行
認証後も完了しない コールバックがリモートに届かない / IPv6 に流れている トンネル確認、URL を 127.0.0.1 に、または 7.2 の curl 手法
どのホストにトンネル張ってるか不明 宛先取り違え ps -p <PID> -o pid,etimes,cmd / /proc/<PID>/cmdline で確認 → 作り直し

11. まとめ

  • 原理:ブラウザの callback を SSH ローカルフォワードでローカル→リモートへ橋渡し。
  • 実践ssh -L 127.0.0.1:1455:127.0.0.1:1455 golgi → リモートで codex loginローカルのブラウザで URL を開く。
  • 詰まりポイント:1455 の占有(ローカル or リモート)、宛先ホスト取り違え、localhost vs 127.0.0.1、二重トンネル。
  • 困ったら:本書 5章の掃除コマンドとチェックリストで5分以内に復旧できます。

Discussion