#!/bin/bash # ssh client config. Dry run by default; pass `yes` to apply. set -euo pipefail # shellcheck source-path=SCRIPTDIR # shellcheck source=lib.sh source "$(dirname "$0")/lib.sh" "$@" # ~/.ssh/config itself is the entry point: it reads ~/.config/ssh/config-fleet # first, if another layer has linked one in, then this host's # ~/.config/ssh/config-local -- see config/ssh/entry. Only the file is linked; # ~/.ssh stays a real directory, because what else lives in it (keys, # known_hosts, control and agent sockets) is this host's own. # # Each step below is skipped, loudly, rather than forced, because link() starts # with `rm -rf`: # - a symlinked ~/.ssh. On the Macs it once pointed into iCloud Drive, a # single directory shared by two machines, so replacing a file in it on one # deleted it on the other. # - a real ~/.ssh/config holding anything but `Include ~/.config/ssh/config`, # the one line each host was given by hand on 2026-09-07, before this file # was linked. Anything else is host-specific and belongs in config-local; # move it there first. ssh_dir="$HOME/.ssh" if [[ -L "$ssh_dir" ]] then red "$ssh_dir is a symlink to $(readlink "$ssh_dir"); skipping ssh links -- make it a real local directory first" exit 0 fi if [[ -z "${is_dry_run}" && ! -d "$ssh_dir" ]] then install -d -m 700 "$ssh_dir" fi ssh_config_extra="" if [[ -f "$ssh_dir/config" && ! -L "$ssh_dir/config" ]] then ssh_config_extra="$(grep -vE '^[[:space:]]*(#|$)' "$ssh_dir/config" \ | grep -vxF 'Include ~/.config/ssh/config' || true)" fi if [[ -n "$ssh_config_extra" ]] then red "$ssh_dir/config has host-specific lines; move them to ~/.config/ssh/config-local, then re-run" else link "$config_dir/ssh/entry" "$ssh_dir/config" fi # Links this repo made while host blocks and their key pins were tracked here, # now that another layer owns them: only a dangling link in ~/.config/ssh that # points into this repo's config/ssh is removed -- never a real file, and never # a link someone else made. Compared as real paths: the link holds whatever # spelling this repo had when it was made, which on a machine whose checkout is # reached through a symlink is not this run's. ssh_repo_dir="$(realpath "$config_dir/ssh")" for stale in "$xdg_config_dir"/ssh/* do if [[ -L "$stale" && ! -e "$stale" ]] \ && [[ "$(realpath "$(dirname "$(readlink "$stale")")" 2>/dev/null)" == "$ssh_repo_dir" ]] then if [[ -n "${is_dry_run}" ]] then yellow "$stale is a dangling link into this repo and will be removed" else rm "$stale" fi fi done