Compare commits

...
Author SHA1 Message Date
陈大猫 91e286d64a fix(nix): publish ssh config snapshot atomically
cp truncates the destination before copying, so a concurrent ssh -F
reader can see an empty or partial config and ignore HostName,
identity, or proxy settings. Copy to a unique staging file and
rename it over the snapshot.
2026-11-09 01:30:08 +08:00
陈大猫 00fdddce05 fix(nix): always refresh ssh config snapshot for home-manager
Nix store files have normalized old mtimes, so a -nt check never
notices a newer home-manager generation after the first snapshot.
2026-11-09 01:24:47 +08:00
陈大猫 b13e545bed fix(nix): work around bwrap ssh config owner check for home-manager
Unprivileged wrapType2/bwrap maps only the caller uid, so a home-manager
~/.ssh/config symlink into the nix store appears as overflowuid 65534.
OpenSSH then rejects the default user config and the Mosh handshake
never sees MOSH CONNECT. Inject an ssh wrapper via extraPkgs that
snapshots a badly owned config and execs nixpkgs OpenSSH with -F.
2026-11-09 01:19:17 +08:00
+34
View File
@@ -2,8 +2,10 @@
appimageTools,
fetchurl,
lib,
openssh,
release ? import ./release.nix,
stdenv,
writeShellScriptBin,
}:
let
@@ -22,10 +24,42 @@ let
appimageContents = appimageTools.extractType2 {
inherit pname version src;
};
# home-manager's ~/.ssh/config is a root-owned symlink into the nix store.
# Unprivileged bwrap (wrapType2 / buildFHSEnv) maps only the caller uid, so
# that file appears as overflowuid 65534 and OpenSSH refuses the default
# user config with "Bad owner or permissions". A -F path skips that check.
# The wrapper is injected via extraPkgs so it lands on the FHS /usr/bin,
# which buildFHSEnv prepends ahead of any bind-mounted host profile PATH.
sshWrapped = writeShellScriptBin "ssh" ''
real_ssh="${openssh}/bin/ssh"
config="''${HOME}/.ssh/config"
if [ -e "$config" ]; then
owner="$(stat -c %u -L "$config" 2>/dev/null || true)"
me="$(id -u)"
if [ -n "$owner" ] && [ "$owner" != "$me" ] && [ "$owner" != 0 ]; then
cache="''${XDG_CACHE_HOME:-$HOME/.cache}/netcatty"
snap="$cache/ssh_config"
mkdir -p "$cache"
# Always refresh: nix store files have frozen old mtimes, so -nt
# never sees a newer home-manager generation after the first copy.
# Publish via a unique staging file + mv so a concurrent ssh -F
# reader never sees a truncated snapshot (cp truncates first).
snap_tmp="$snap.tmp.$$"
cp -L "$config" "$snap_tmp"
chmod 600 "$snap_tmp"
mv -f "$snap_tmp" "$snap"
exec "$real_ssh" -F "$snap" "$@"
fi
fi
exec "$real_ssh" "$@"
'';
in
appimageTools.wrapType2 {
inherit pname version src;
extraPkgs = pkgs: [ sshWrapped ];
extraInstallCommands = ''
desktopSource="$(find ${appimageContents} -maxdepth 3 -name '*.desktop' -print -quit)"
if [ -n "$desktopSource" ]; then