docs(github-auth): document headless gh auth login --with-token hang + hosts.yml fallback
On keyring-less headless Linux (VPS, containers, no dbus session), 'gh auth login --with-token' can block indefinitely waiting on a secret-service keyring -- even with --insecure-storage, with no output. Hit live on a headless x86_64 VPS (gh 2.97.0): the documented device flow succeeded up to the token, then --with-token hung twice. - Add a timeout guard to the device-flow polling loop so the hang is detected instead of silently stalling the login. - Document the proven fallback: write ~/.config/gh/hosts.yml directly (chmod 600) and run 'gh auth setup-git' -- both read the file store without touching the keyring.
This commit is contained in:
@@ -195,7 +195,10 @@ while true; do
|
||||
case "$POLL" in
|
||||
*access_token*)
|
||||
# Never echo the token; pipe it straight into gh.
|
||||
echo "$POLL" | sed 's/.*"access_token":"\([^"]*\)".*/\1/' | gh auth login --with-token
|
||||
# timeout guards the headless-keyring hang (see pitfall below) —
|
||||
# on exit 124, fall back to writing ~/.config/gh/hosts.yml directly.
|
||||
echo "$POLL" | sed 's/.*"access_token":"\([^"]*\)".*/\1/' | timeout 20 gh auth login --with-token \
|
||||
|| { echo "WITH_TOKEN_HUNG_OR_FAILED — use the hosts.yml fallback below"; exit 1; }
|
||||
gh auth setup-git
|
||||
gh auth status
|
||||
echo "LOGIN_COMPLETE"; break ;;
|
||||
@@ -210,6 +213,29 @@ done
|
||||
|
||||
Note: on Windows winget installs, gh lands at `/c/Program Files/GitHub CLI` — add it to PATH in the same shell: `export PATH="$PATH:/c/Program Files/GitHub CLI"`.
|
||||
|
||||
> **PITFALL (headless Linux): `gh auth login --with-token` can hang forever.**
|
||||
> On keyring-less/headless boxes (VPS, containers, no dbus session), gh's
|
||||
> credential storage may block indefinitely waiting on a secret-service
|
||||
> keyring — even with `--insecure-storage`, and with no output. If the
|
||||
> command doesn't return within ~20s (wrap it in `timeout 20 …` to detect
|
||||
> this), skip gh's login machinery and write the credential store directly:
|
||||
>
|
||||
> ```bash
|
||||
> # $TOKEN = the access token from the device flow above (never echo it)
|
||||
> mkdir -p ~/.config/gh
|
||||
> LOGIN=$(curl -s -H "Authorization: token $TOKEN" https://api.github.com/user \
|
||||
> | sed 's/.*"login": *"\([^"]*\)".*/\1/')
|
||||
> printf 'github.com:\n users:\n %s:\n oauth_token: %s\n git_protocol: https\n oauth_token: %s\n user: %s\n' \
|
||||
> "$LOGIN" "$TOKEN" "$TOKEN" "$LOGIN" > ~/.config/gh/hosts.yml
|
||||
> chmod 600 ~/.config/gh/hosts.yml
|
||||
> gh auth status # reads hosts.yml directly — verifies without the keyring
|
||||
> gh auth setup-git # wires the git credential helper (does not hang)
|
||||
> ```
|
||||
>
|
||||
> `gh auth status` and `setup-git` read the file store without touching the
|
||||
> keyring, so they work immediately. Proven on a headless x86_64 VPS
|
||||
> (gh 2.97.0, Aug 2026) after `--with-token` hung twice.
|
||||
|
||||
### Token-Based Login (Headless / SSH Servers)
|
||||
|
||||
```bash
|
||||
@@ -219,6 +245,8 @@ echo "<THEIR_TOKEN>" | gh auth login --with-token
|
||||
gh auth setup-git
|
||||
```
|
||||
|
||||
If `--with-token` hangs here, use the hosts.yml fallback from the pitfall above.
|
||||
|
||||
### Verify
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user