Skip to content

VM setup: apt-get only, fix root-owned ~/.gnupg, quieter installs, Remote Control confirmation - #30

Merged
modem7 merged 2 commits into
masterfrom
fix/vm-setup-apt-noise
Sep 26, 2026
Merged

modem7 merged 2 commits into
masterfrom
fix/vm-setup-apt-noise

Conversation

@modem7

@modem7 modem7 commented Sep 26, 2026 •

Copy link
Copy Markdown
Owner

Summary

Fixes from the first live run of claude-code-vm-setup.sh on a fresh VM, where every check passed except Remote Control.

Remote Control service never started

The journal showed the cause: claude remote-control asks a one-time Enable Remote Control? (y/n) before it will serve. Under systemd, stdin is empty, which counts as "no", so it exited 0 and systemd restarted it every minute forever. The docs confirm the answer is stored once given, but there's no documented way to pre-set it.

  • New confirm_remote_control step at the end of phase 1 (right after Claude sign-in): runs claude remote-control once in the foreground so the user sees Claude's own explanation and answers y, then presses Ctrl+C once the session URL shows (2-minute safety timeout). A no-op INT handler keeps Ctrl+C from aborting the script; timeout --foreground keeps claude able to read the terminal.
  • Skipped when the service is already active, i.e. the confirmation was given on an earlier run. When not signed in, or with no TTY, it prints the one-line manual fix instead.
  • Workspace trust moved into a shared trust_project_dir helper, applied before this step as well as when writing the service.
  • The health check spots the prompt in the service journal and names the exact fix, instead of the generic "not staying up".

Real bugs

  • Root-owned ~/.gnupg. NodeSource's setup script was run with sudo -E, which keeps HOME, so root's gpg wrote into /home/<user>/.gnupg (gpg: WARNING: unsafe ownership on homedir). That breaks the user's own gpg later. NodeSource's repo is now added directly: the armored key goes to /etc/apt/keyrings/nodesource.asc (no gpg involved), plus a nodesource.list entry and an apt pin preferring it over Ubuntu's older nodejs. The old script's nodesource.sources is replaced, so apt doesn't see two entries with different Signed-By. Preflight repairs a root-owned ~/.gnupg left by earlier runs.
  • DEBIAN_FRONTEND never reached apt. sudo resets the environment, so the script's export DEBIAN_FRONTEND=noninteractive did nothing, and a package with a debconf question could have stalled the run. All apt calls now go through apt_get(), which sets DEBIAN_FRONTEND=noninteractive NEEDRESTART_SUSPEND=1 on the sudo line itself (also passed to get.docker.com's installer).
  • WARNING: apt does not have a stable CLI interface. This came from NodeSource's script calling apt. It's gone with the script; everything uses apt-get.

Noise

  • needrestart's "Scanning processes / candidates / linux images" after every install: suppressed via NEEDRESTART_SUSPEND.
  • Chatty installers (rustup's cargo:rerun-if-env-changed… block, get.docker.com's + sh -c trace, npm install -g, pip/Playwright downloads) now run through quiet(), which captures output and shows the last 30 lines only if the command fails.

Sign-in polish

  • gh auth login --web: skips the "How would you like to authenticate?" question.
  • BROWSER=true exported once in preflight when there's no display, so gh and Claude just print their URL / device code instead of "Failed opening a web browser" (and a console browser can't take over the terminal). Replaces the Claude-only version from VM setup: catch missing AVX2 up front and stop the sign-in step hanging #29.

Test plan

  • shellcheck clean; no sudo apt-get / apt install left outside comments
  • Fresh ubuntu:24.04 container with needrestart installed, NodeSource's old setup_22.x already run, and a root-owned ~/.gnupg: zero occurrences of the apt CLI warning, "Scanning processes", "unsafe ownership", cargo:rerun, + sh -c and npm "added N packages"; nodesource.sources replaced by nodesource.list; nodejs 24.21.0-1nodesource1 from NodeSource; ~/.gnupg returned to the user (700); Playwright import OK
  • Remote Control confirmation step under a real PTY (Python pty driver, stub claude with the same y/n prompt): the answer reaches claude through the terminal; Ctrl+C stops only claude and the script continues (exit 0); the timeout path also continues; project dir trusted in ~/.claude.json
  • Real claude remote-control confirmation needs a signed-in VM; next live run

- Add NodeSource's repo directly instead of running their setup script
  (it used apt and ran gpg as root with the user's HOME); repair a
  root-owned ~/.gnupg left by earlier runs
- Route apt through apt_get() so DEBIAN_FRONTEND and needrestart's
  opt-out actually survive sudo
- Capture chatty installer output, showing it only on failure
- gh auth login --web; no-op BROWSER on headless machines
claude remote-control asks 'Enable Remote Control? (y/n)' once; under
systemd the empty stdin counts as no, so the service exited and restarted
every minute. Run it once in the foreground right after sign-in so the
user can answer, surviving the Ctrl+C that stops it, and have the health
check name this fix when the service is stuck at the prompt.
@modem7 modem7 changed the title VM setup: apt-get only, fix root-owned ~/.gnupg, quieter installs VM setup: apt-get only, fix root-owned ~/.gnupg, quieter installs, Remote Control confirmation Sep 26, 2026
@modem7
modem7 merged commit 0899ada into master Sep 26, 2026
1 check passed
@modem7
modem7 deleted the fix/vm-setup-apt-noise branch September 26, 2026 22:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant