NixOS + home-manager configs, mirrored from GitLab SaaS.
gitlab.com/andreijiroh-dev/nixops-config
nix-flake
nixos
home-manager
nixpkgs
nix-flakes
1#!/usr/bin/env bash
2# shellcheck disable=SC2034
3# SPDX-License-Identifier: MPL-2.0
4# Reliably detect and switch between SSH agents like keychain, yubikey-agent, 1Password, etc.
5
6if [[ $DEBUG != "" ]]; then
7 set -x
8fi
9
10logOps() {
11 PREFIX=$3
12
13 if [[ $PREFIX != "" ]]; then
14 LOGOPS_PREFIX="[ssh-agent-loader::$PREFIX]"
15 else
16 LOGOPS_PREFIX="[ssh-agent-loader]"
17 fi
18
19 if [[ $1 == "debug" ]]; then
20 [[ $DEBUG != "" ]] && echo "[ssh-agent-loader] debug: $2"
21 elif [[ $1 == "warn" ]]; then
22 echo "$LOGOPS_PREFIX warning: $2"
23 elif [[ $1 == "error" ]]; then
24 echo "$LOGOPS_PREFIX error: $2"
25 else
26 [[ $SSH_AGENT_LOADER_SLIENT != "1" ]] && echo "$LOGOPS_PREFIX $2"
27 fi
28}
29
30# Workaround in cases where XDG_RUNTIME_DIR is undefined on login
31if [[ -z "${XDG_RUNTIME_DIR}" ]]; then
32 logOps warn "XDG_RUNTIME_DIR is possibly undefined, see https://github.com/swaywm/sway/issues/7202"
33 logOps warn "for context and https://wiki.archlinux.org/title/XDG_Base_Directory for docs"
34 logOps warn "Temporarily using '/run/user/$(id -u)' for XDG_RUNTIME_DIR in 3s..."
35 sleep 3
36 XDG_RUNTIME_DIR="/run/user/$(id -u)"
37 export XDG_RUNTIME_DIR
38fi
39
40# do feature detection if keychain is installed
41if command -v keychain >> /dev/null; then
42 FF_KEYCHAIN=1
43else
44 FF_KEYCHAIN=0
45fi
46
47try_keychain_ssh_agent() {
48 if [[ $FF_KEYCHAIN == "1" ]]; then
49 logOps info "attempting to use keychain for SSH agents" keychain
50 if [[ "$SSH_AGENT_LOADER_SLIENT" == "" ]]; then
51 eval "$(keychain --eval --ssh-spawn-gpg --ssh-allow-gpg)"
52 else
53 eval "$(keychain --eval --ssh-spawn-gpg --ssh-allow-gpg --quiet)"
54 fi
55 else
56 logOps warn "keychain is not in PATH yet" keychain
57 return 1
58 fi
59}
60
61# Ripped off NixOS-generated set-environment on my laptop for yubikey-agent setup
62try_yubikey_agent() {
63 YUBIKEY_AGENT_AUTH_SOCK="${XDG_RUNTIME_DIR}/yubikey-agent/yubikey-agent.sock"
64 if [[ -f "${YUBIKEY_AGENT_AUTH_SOCK}" ]]; then
65 logOps info "attempting to use Yubikey SSH agent" yubikey-agent
66 if ! SSH_AUTH_SOCK=${YUBIKEY_AGENT_AUTH_SOCK} ssh-add -l >> /dev/null 2>&1; then
67 logOps warn "something went wrong while checking for Yubikey SSH agent availability" yubikey-agent
68 logOps warn "is your Yubikey plugged in properly?" yubikey-agent
69 return 1
70 fi
71 else
72 logOps error "Yubikey SSH agent seems to be not available on this host" yubikey-agent
73 return 1
74 fi
75}
76
77try_1password_ssh_agent() {
78 OP_SSH_AUTH_SOCK="$HOME/.1password/agent.sock"
79 if [[ ! -S "$OP_SSH_AUTH_SOCK" ]]; then
80 logOps warn "1Password SSH agent isn't enabled or desktop app isn't installed yet" 1password
81 return 1
82 fi
83
84 logOps info "attempting to use 1Password SSH agent" 1password
85 if ! SSH_AUTH_SOCK=$OP_SSH_AUTH_SOCK ssh-add -l >> /dev/null 2>&1; then
86 logOps warn "something went wrong while checking for 1Password SSH agent availability" 1password
87 logOps warn "unlock the desktop app first or enable SSH agent from settings" 1password
88 return 1
89 fi
90 export SSH_AUTH_SOCK=$OP_SSH_AUTH_SOCK FF_USE_OP_CLI_PLUGINS=true
91 unset OP_SSH_AUTH_SOCK
92}
93
94ssh-agent-loader() {
95 if [[ $1 == "" || $1 == "auto" ]]; then
96 if [[ $SSH_CONNECTION != "" ]] && [[ $VSCODE_IPC_HOOK_CLI != "" ]]; then
97 logOps info "automatic detection is disabled while you're in a VS Code Remote SSH/Tunnels session"
98 logOps info "to enable SSH agent, please manually invoke the shell function with desired agent"
99 return
100 fi
101
102 export OLD_SSH_AUTH_SOCK="$SSH_AUTH_SOCK"
103
104 unset SSH_AGENT_PID SSH_AUTH_SOCK
105 if try_1password_ssh_agent; then
106 return
107 elif try_keychain_ssh_agent; then
108 return
109 elif try_yubikey_agent; then
110 return
111 else
112 logOps error "SSH agent seems to be failed to load at the moment"
113 logOps error "try again later by manually invoking the shell function"
114 return 1
115 fi
116 elif [[ $1 == "1passowrd" || $1 == "op" ]]; then
117 unset SSH_AGENT_PID SSH_AUTH_SOCK
118 try_1password_ssh_agent
119 elif [[ $1 == "keychain" ]]; then
120 try_keychain_ssh_agent
121 elif [[ $1 == "yubikey" ]]; then
122 try_yubikey_agent
123 else
124 echo "Usage: ssh-agent-loader [auto|[1password|op|1p]|keychain|yubikey]"
125 return 1
126 fi
127}
128
129# Avoid source loops on subsequent file resourcing.
130if [[ -z "$SSH_AGENT_LOADED" ]]; then
131 # automatically detect things as we source this
132 [[ "$FF_SKIP_AUTO_SSH_AGENT_LOADER" == "" ]] && ssh-agent-loader auto
133 export SSH_AGENT_LOADED=1
134fi
135
136if [[ $DEBUG == "1" ]]; then
137 set +x
138fi