diff --git a/.claude/handoffs/2026-09-15-222455-tank-automount.md b/.claude/handoffs/2026-09-15-222455-tank-automount.md new file mode 100644 index 0000000..31acaa9 --- /dev/null +++ b/.claude/handoffs/2026-09-15-222455-tank-automount.md @@ -0,0 +1,135 @@ +# Handoff: tank automount on the Mac (autofs + SMB) + +## Session Metadata +- Created: 2026-09-15 22:24:55 +- Project: /home/claude/bin/mac +- Branch: master +- Session duration: ~35 min + +### Recent Commits (for context) + - c1558d2 feat(tank): autofs SMB mount of tank at /Volumes/tank + - c204d99 docs: session handoff — ssh aliases + two-key split + - 2028508 feat(ssh): full homelab alias set on the Mac + separate interactive key + - 43877eb docs(checklist): kitty needs the Local Network grant — else LAN ssh = No route to host + - dc29b7a docs: session handoff — kitty titlebar fix + +## Handoff Chain + +- **Continues from**: [2026-09-15-203133-mac-ssh-aliases.md](./2026-09-15-203133-mac-ssh-aliases.md) + - Previous title: ssh aliases + two-key split (mac) +- **Supersedes**: None + +> Review the previous handoff for full context before filling this one. + +## Current State Summary + +Seth asked to "mount tank on the mac as a drive". Shipped `scripts/tank-automount.sh`: an autofs direct map (`/- auto_smb -nosuid` in `/etc/auto_master`) + root-owned 0600 `/etc/auto_smb` mounting `//Administrator@192.168.0.173/tank` (soft) at `/Volumes/tank`. Mounts on access, unmounts when idle — chosen over a Finder Login-Item mount because the laptop roams. Verified: mount works, writes land as root on tank, two consecutive all-`[skip]` reruns, wired into `run.sh`. The literal "as a drive" is NOT achievable this way: macOS marks all automounted fs `nobrowse` (confirmed in `man auto_master`), so it shows as a folder and needs a Finder Favorite (added to `docs/manual-checklist.md`). A Finder window on `/Volumes/tank` was opened on Seth's screen. Not yet verified across a reboot (FileVault means Seth must be at the lid). Committed + pushed. + +## Codebase Understanding + +### Architecture Overview + +- `run.sh` now has 3 on-Mac stages: `setup.sh` (temp NOPASSWD sudoers), `tank-automount.sh` (own `sudo -S -v` from the stdin password — needs no temp sudoers), then tank-side + `authorize-mac-key.sh` from steel141. +- tank export facts (pve173): NFS `/tank *(rw,no_root_squash,insecure)`; Samba shares `[tank]` and `[Z]` (same path, `force user = root`, users `Administrator`/`octoprint`). steel141's seth uses `//173/Z` as Administrator; vdj-rig uses NFS ro with a systemd automount — the roaming pattern this copies. +- The Mac's `seth` is uid 501, which is why NFS was rejected: writes would be an unknown uid and only 777 dirs are writable. + +### Critical Files + +| File | Purpose | Relevance | +|------|---------|-----------| +| `scripts/tank-automount.sh` | the whole feature; password on stdin | idempotent; see header comment for the three macOS gotchas | +| `/etc/auto_smb` (on the Mac) | contains the SMB password, root 0600 | never copy into the repo or `.mac-setup-backup` | +| `/etc/auto_master` (on the Mac) | direct-map line appended | pre-change copy in `~/.mac-setup-backup/auto_master-` on the Mac | +| `docs/manual-checklist.md` | new "tank" section + fixed Gitea key + samples step | Seth's next GUI actions | +| `DECISIONS.md` | autofs-vs-Finder-mount rationale; Finder mount in Deferred/Rejected | | + +### Key Patterns Discovered + +- macOS `automount -vc` does NOT create direct-map trigger dirs ("mountpoint unavailable", `getattrlist:fail:2`). `mkdir -p` first. +- No-tty sudo ticket (`sudo -S -v` over ssh) is per parent pid: `sudo` in a pipeline or as a direct child works; `$(sudo cat ...)` silently fails. Cost a false "not idempotent". +- `nobrowse` in a map's options and `nobrowse` on the resulting mount are different things (man page says so); there is no map option that makes an automount Finder-browsable. +- Secrets to on-Mac scripts go via stdin (`printf | ssh mac 'bash script'`), never argv/env in the ssh command string; URL-encoding the password also went through python3 stdin, not argv. + +## Work Completed + +### Tasks Finished + +- [x] `scripts/tank-automount.sh` written, applied, verified (mount, root write, idempotent reruns) +- [x] `run.sh` runs it after `setup.sh` +- [x] `docs/manual-checklist.md`: tank Favorite + reboot check; Gitea key -> `id_ed25519_homelab`; samples step now uses `/Volumes/tank` +- [x] DECISIONS.md + CLAUDE.md updated; committed + pushed +- [x] Finder window opened on `/Volumes/tank` for Seth + +### Files Modified + +| File | Changes | Rationale | +|------|---------|-----------| +| [no modified files detected] | | | + +### Decisions Made + +| Decision | Options Considered | Rationale | +|----------|-------------------|-----------| +| autofs (roaming-safe, folder) over Finder Login-Item mount (drive icon, hard mount) | both; a custom LaunchAgent doing `mount_smbfs` was the third (rung-7) option | laptop leaves the LAN; hard mounts beachball Finder and throw login dialogs. Icon can be revisited | +| SMB as Administrator over NFS | NFS is passwordless | uid 501 on the Mac; SMB `force user = root` matches how seth writes tank from steel141 | +| `/Volumes/tank` as the path | `~/tank`, `/tank` via synthetic.conf | reads as a drive path; persistence across reboot is the open question — fallback is synthetic.conf `/tank` (needs a reboot) | +| Password in `/etc/auto_smb` root 0600 | keychain (not honoured by automountd) | same class as steel141's `~/.smbcredentials`; never leaves the Mac | + +## Pending Work + +### Immediate Next Steps + +1. After Seth's next reboot: `ssh mac 'mount | grep auto_smb'` must show the `/Volumes/tank` trigger. If `/Volumes/tank` vanished (boot-time /Volumes cleanup), switch the map to `/tank` via `/etc/synthetic.conf` (`tank` bare line) — needs another reboot. +2. Seth: drag `/Volumes/tank` to Finder Favorites (checklist). Ask whether the folder-not-drive result is acceptable or he wants the Locations icon (then: Finder Connect-to-Server + Login Item, documented as rejected-for-now in DECISIONS). +3. Carried: `authorize-mac-key.sh` rerun for bedroom/thinkcentre/seth-pi/pinail/openclaw2; `bedroom`=root confirmation; kitty relaunch; Ableton install then `run.sh --no-tank`; audio interface test. + +### Blockers/Open Questions + +- [ ] Reboot persistence of the `/Volumes/tank` trigger dir — unverified (FileVault: needs Seth at the lid). +- [ ] Idle-unmount timing not measured (macOS default `AUTOMOUNT_TIMEOUT` in `/etc/autofs.conf`, 3600 s); fine unless Seth notices. + +### Deferred Items + +- Real drive icon under Locations (Finder mount + Login Item) — rejected for now, see DECISIONS. +- LaunchAgent-based `mount_smbfs` reconnect daemon — would give icon + roaming, but it's custom code for a problem autofs solves well enough. +- Carried: SparkFun PPP, Tailscale login, AeroSpace, `NSWindowShouldDragOnGesture`, Gitea key upload. + +## Context for Resuming Agent + +### Important Context + +`/etc/auto_smb` on the Mac holds the homelab password — never `cat` it into a transcript, never back it up into the repo or `~/.mac-setup-backup`. If tank "isn't mounting": `ls /Volumes/tank` is what triggers it (autofs is lazy); check `mount | grep tank` for the autofs trigger line first — if the trigger is missing, `automount -vc` failed (usually the dir is gone); if the trigger is there but smbfs isn't, it's network/creds (`log show --last 2m --predicate 'process == "automountd"'`). Re-running `printf '%s\n' "$HOMELAB_PASSWORD" | ssh mac 'bash ~/mac/scripts/tank-automount.sh'` is always safe. This session changed on the Mac: `/etc/auto_master` (+1 line), `/etc/auto_smb` (new), `/Volumes/tank` (dir), and opened one Finder window; nothing else. + +### Assumptions Made + +- Seth's Mac sudo password == `$HOMELAB_PASSWORD` (true: run.sh's cleanup relies on it) and the Samba `Administrator` password == the same (verified by the mount succeeding). +- Seth values roaming-safety over the drive icon (inferred from "portable" use; not confirmed — item 2 in next steps). + +### Potential Gotchas + +- The Ableton Live 12 Trial Installer DMG was mounted at `/Volumes/Ableton Live 12 Trial Installer` during this session — Seth is mid-install; don't unmount/eject volumes wholesale. +- `mount | grep tank` shows TWO lines (autofs trigger + smbfs) when mounted; only the trigger when idle. Both are normal. +- `sed -i ""` (BSD form) is what works on the Mac even with GNU sed on PATH via gnubin — check `which sed` before scripting sed there. + +## Environment State + +### Tools/Services Used + +- `ssh mac`; `/usr/sbin/automount`, `/usr/libexec/automountd`; `/usr/bin/python3` (Xcode CLT) used for URL-encoding; `gitea push`. + +### Active Processes + +- tank currently mounted at `/Volumes/tank` on the Mac (will idle-unmount). Finder window open on it. Backup launchd agent unchanged. + +### Environment Variables + +- `HOMELAB_PASSWORD` — piped on stdin to `tank-automount.sh` (and by `run.sh`); never in argv. + +## Related Resources + +- Previous handoff: `.claude/handoffs/2026-09-15-203133-mac-ssh-aliases.md` (two-key ssh design, offline hosts list). +- `man auto_master` on the Mac (nobrowse semantics); `/etc/autofs.conf` (timeouts); `~/bin/CLAUDE.md` Storage section (tank export facts, use .173 not .200). + +--- + +**Security Reminder**: Before finalizing, run `validate_handoff.py` to check for accidental secret exposure.