- A great YouTube video on overview on SSH
- SSH Essentials: Working with SSH Servers, Clients, and Keys
- https://smallstep.com/blog/ssh-agent-explained/
- https://gist.github.com/ryuheechul/494f4e6f08eaca34ef00ab8b238eca2a#ssh-server
RemoteCommand tmux a # as something other than default shell
RequestTTY force # as our (remote) command require TTY
# equivalent to `ssh [host] -t 'tmux a'
also see Eleven SSH Tricks
Compression yes
Agent forwarding is kind of a must so that the end client's pubkey is used
ForwardAgent yes
Also make sure to run ssh-add -k # or ssh-add [keyname]
to add keys to agent or check with ssh-add -l
to see if it's listed.
Otherwise it will not be picked up. And you might see an error meesage below.
**sign_and_send_pubkey: signing failed: agent refused operation** # (it might print your key name here too)
An additional config stanza like below could add automatically.
AddKeysToAgent yes
But I experienced that some system don't (like Blink Shell at the moment) so make sure to verify keys added by seeing the key at the result of ssh-add -l
.
Sometimes a server has its own local agent running and connect it via a config like below
host *
IdentityAgent some/socket/file
But this will ignore $SSH_AUTH_SOCK
and (this is so not obvious as ssh-add -l
will still show the one from $SSH_AUTH_SOCK
but that's what it is...).
There is a workaround to this though by only setting IdentityAgent
when it's a direct connect (achieved by looking at the presence of $SSH_TTY
).
Match host * exec "test -z $SSH_TTY"
IdentityAgent some/socket/file
Now $SSH_AUTH_SOCK
will be honored with the config above.
There is a thread on this information - https://1password.community/discussion/comment/662319/#Comment_662319.
- https://github.com/maxgoedjen/secretive/blob/main/FAQ.md#how-do-i-tell-ssh-to-use-a-specific-key
- maxgoedjen/secretive#127 (comment)
- maxgoedjen/secretive#92 (comment)
- maxgoedjen/secretive#156 (comment)
- maxgoedjen/secretive#117 (comment)
Enter Keychain, https://www.funtoo.org/OpenSSH_Key_Management,_Part_2
https://esc.sh/blog/ssh-agent-windows10-wsl2/ or
# maybe in your .bashrc or .zshrc
eval $(keychain [--quiet] --eval --agents ssh [id_rsa])
assuming
pbcopy
&pbpaste
is what is used for clipboard on both systems
ssh remote-host pbpaste | pbcopy
pbpaste | ssh remote-host pbcopy
not strictly related to above, but I enjoyed reading this article, https://andrewbrookins.com/technology/synchronizing-the-ios-clipboard-with-a-remote-server-using-command-line-tools/ and hopefully iPad gets to have macOS one day, lol.
Even beyond simply accessing it, sharing clipboard is also possible via something called X11 forwaring.
A nice explanation is at https://askubuntu.com/a/305681.
# client side at ./ssh/config
Host [host]
ForwardX11 yes # make sure this is on
# server side at /etc/ssh/sshd_config
X11Forwarding yes # make sure this is on - this might be blocked by default on macOS host
# When an error occur like this
# ```
# Remote: No xauth program; cannot forward
# X11 forwarding request failed on channel 0
# ```
# and the host is macOS and xquartz is installed, this should help with error above
XAuthLocation /opt/X11/bin/xauth # or the path what `which xauth` returns
Restart the sshd on macOS after editing
# applying edited /etc/ssh/sshd_config requires restarting sshd
sudo launchctl stop com.openssh.sshd && sudo launchctl start com.openssh.sshd
serving SSH via tailscale seems to have an issue with X11Forwarding, tailscale/tailscale#5160
[an update on above] I discovered an workaround! - tailscale/tailscale#5160 (comment)
On macOS, there is no X11 server by default but it can be installed
I would install it by one of these ways:
nix-env -iA nixpkgs.xquartz
brew install --cask xquartz
Another important thing is that we need to know how to use clipboard on linux and that information can be found at https://ostechnix.com/access-clipboard-contents-using-xclip-and-xsel-in-linux/.
I prefer to use xsel
over xclip
.
And having xsel
is enough to make these two plugins work:
I also would make an alias to help my muscle memory used to macOS.
# bring `pbcopy` and `pbpaste` to linux
alias pbcopy='xsel -i -b'
alias pbpaste='xsel -o -b'
Now things copied inside ssh and vice versa!
If you are in a "abnormal" situation that simple ForwardX11 yes
doesn't work (i. e. WSL with WSLg), the solution below might work.
# below is equivalent to `ssh -R 6020:/tmp/.X11-unix/X0 [host]` if it was used as CLI
Host [host]
RemoteForward 6020 /tmp/.X11-unix/X0 # basically can be used in place of `ForwardX11 yes`
# ^ ^
# | |
# | |
# as a TCP port on remote host |
# (6020) |
# as a Unix Domain Socket on the SSH client host
# (/tmp/.X11-unix/X0)
# which your xorg server (possibly WSLg) is lisetning to
# and the remote host side would need to `export DISPLAY=':20'`
# so that X11 client will use `localhost:6020` for X11 channel
# where is +6000 coming from?
# > `man 1 xorg | grep 6000`
# what exactly the values like these `:0` or `:20` mean?
# > `man 7 X` and search `DISPLAY NAMES`
# > to see how these resolves to which protocols (i.e. TCP or Unix Domain Socket)
# also read links below to understand more about why it works and why it might not work for some situations
- TIL - X11 FORWARDING IN WSLG
- X11 Forwarding using an SSH Reverse Tunnel
- How do X clients know that they will need to connect to TCP port 6000+?
But this can fail with the message below (depends on your SSH client side setup):
# from remote side
$ printenv DISPLAY
:20
$ xsel -o -b
Authorization required, but no authorization protocol specified
xsel: Can't open display: (null)
: Socket is not connected
# from ssh client (NixOS + Gnome + XWayland)
$ printenv XAUTHORITY # does this have anything to do with it?
/run/user/1000/.mutter-Xwaylandauth.ABCXYZ
# yes it's probably due to a mismatch between $DISPLAY and $XAUTHORITY
# run `xauth list` to debug
But... nested X would make it work althrough how useful would that be is up to you
Let's say a host is macOS and guest is a Linux VM running via UTM (and there is an agent syncing clipboard).
And with whatever reason, on the host side, there is no X server (XQuartz) are running or just ForwardX11
doesn't work.
In this case, the SSH client connection (from the host) can "pretend" that it is running directly from the guest GUI by setting $XAUTHORITY
.
Get the value by running printenv DISPLAY XAUTHORITY
from the terminal within the guest directly.
And export DISPLAY and XAUTHORITY within the client connection.
# an example (that values from the above step)
export DISPLAY=:0
export XAUTHORITY=/run/user/1000/.mutter-Xwaylandauth.XYZABC
Actually there is a better way to get these value less manually via
systemctl systemctl --user show-environment
. e.g. https://github.com/ryuheechul/dotfiles/commit/1f4329b603646e24048a232aeedf43e026a614bc
With this particular "workaround", unlike the usual usage, we are using the X server is at the remote host (VM guest in this case) not at the SSH client (Host macOS machine)
- application (e.g. poetry, pip) that excpect the keyring auth will prompt in the original virtual console which is hard to know unless you are looking the original virtual console via for example UTM window.
- possibly you can get hint on this by running a command with verbose log option like
-v, -vv, -vvv
if command supports it
- possibly you can get hint on this by running a command with verbose log option like
Few readings regarding above:
- https://goteleport.com/blog/x11-forwarding/
- https://forums.opensuse.org/t/authorization-required-but-no-authorization-protocol-specified/167149/15
Using after initial installation may require reboot (let me know if not)
xeyes
command to see if it's working (and it should run the app if it wasn't)
A timing could be little tricky that when it actually start working.
Check to see if xsel
(or xclip
if you prefer) is installed on the host system.
But bascially, when you run printenv DISPLAY
, you should see something like below.
# on the client side - in this case, macOS
$ printenv DISPLAY
/private/tmp/com.apple.launchd.xYzAbCde/org.xquartz:0
# on the ssh host side - in this case, linux
$ printenv DISPLAY
localhost:10.0
The selection should be CLIPBOARD not PRIMARY nor SECONDARY.
These should work
xclip [-i] [-o] -s clipboard
xclip [-i] [-o] -s c
xsel [-i] [-o] --clipboard
xsel [-i] [-o] -b
but not these:
xclip [-i] [-o]
xsel [-i] [-o]
via X11 forwarding, xeyes
works but not xsel -ib
from the remote machine? (xse -ob
works when it's copied from the client)
# `xsel -ib` could fail silently, which happens with `xsel -ob`, too.
# let's see the verbose messages
$ xsel -obvvv
xsel: Window id: 0xc00001 (unmapped)
xsel: Timestamp: 30457450
xsel: Maximum request size: 4000 bytes
xsel: Conversion refused
xsel: Conversion refused
# conversion refused... why?
$ echo 'please copy me' | xsel -ibvvv
xsel: Window id: 0x1c00001 (unmapped)
xsel: Timestamp: 30561631
xsel: Maximum request size: 4000 bytes
xsel: opened logfile /home/[user]/.cache/xsel.log
# ok let's follow the log file and then try `xsel -ib`
$ tail -f ~/.cache/xsel.log
xsel: BadAccess (attempt to access private resource denied): Resource temporarily unavailable
Turns out adding one more option like below worked
# ~/.ssh/config
Host [host]
ForwardX11 yes # not just this one but the line below
ForwardX11Trusted yes # but it doesn't seem to be always necessary (depends on your client machine, I guess)
# for example, I didn't need `ForwardX11Trusted yes` on macOS + XQuartz but with NixOS + XWayland
# I don't know why exactly yet, but I assume the X server configuration on (my) NixOS configuration has a tighter control.
pbcopy
and pbpaste
seems not work out of the box to forwarded X11 on the host side. (when it is on the client side it works)
xsel [-i] [-o] -b
still works though
Even after running XQaurtz on the host side and make sure it syncs clipboards. My speculation is that it's because even if it syncs, it syncs with the host X11 not the client's which makes sense to me.
I'm looking for an way to mitigate this as this could be annoying that plugins that I use automatically select pbcopy|paste
when they exist.
I invented a workaround that uses these wrapper scripts:
- https://github.com/ryuheechul/dotfiles/blob/master/bin/local/pbcopy
- https://github.com/ryuheechul/dotfiles/blob/master/bin/local/pbpaste
They worked as I hoped for my use cases!
And now these plugins works on macOS host.
Just make sure those scripts are exported to $PATH
.
But this might break the sync between macOS clipboard and xsel -b
. I'm looking into it. I'm fine with the workaround for now.
TODO: add information about reverse sshfs: