Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

forward_env does not update environment variables upon reattach #111

Open
isaksamsten opened this issue Aug 1, 2024 · 9 comments
Open

Comments

@isaksamsten
Copy link

Hi!

I'm trying to get shpool to forward a few environment variables that are set by my terminal emulator (KITTY_LISTEN_ON). Every time I reconnect to my server, the value of this variable changes and allows me to control aspects of kitty from the remote shell (I use it to smoothly swap between kitty panes and neovim splits).

If I set forward_env in the configuration, everything works as expected until I have to reconnect to the server and the value of the environment variable is changed. This change is not reflected when I reattach to the shpool session so the variable has the value it had upon first attach.

Would it be possible to make environment variables forwarded by forward_env update every time one attaches to the session?

Thanks for a great piece of software!

Best,
Isak

@ethanpailes
Copy link
Contributor

Unfortunately, updating environment variables from outside the shell process is a pretty hard problem. I've spent a decent amount of effort trying to get something working using LD_PRELOAD and a shim .so file that injects a little service for updating environment variables (https://github.com/shell-pool/subprocess-inject-env). This actually works, except that a lot of shells (at least zsh and fish but possibly more) cache environment variables, so even when you update the environment variable in their process the update is not visible from within the shell. This means there is no general solution for updating environment variables in the shells that shpool creates.

We do have some special support for the magic SSH_AUTH_SOCK value in order to get some stuff like security keys to work from within a shpool session across reattaches. That environment variable contains a socket path, and shpool creates a symlink at $XDG_RUNTIME_DIR/shpool/sessions/<session-name>/ssh-auth-sock.socket pointing to the actual path, then on reattach it just updates the symlink. This avoids having to update the env var dynamically, but ensures that it always points to a valid socket. If KITTY_LISTEN_ON behaves simillarly, there is a chance we could do something simillar. What is the typical value of KITTY_LISTEN_ON?

@isaksamsten
Copy link
Author

isaksamsten commented Aug 2, 2024

Thanks for the detailed response!

The typical value of KITTY_LISTEN_ON is something similar to tcp:localhost:34332 and allows kitty to communicate with the local machine (somehow). It also sets KITTY_WINDOW_ID and KITTY_PUBLIC_KEY that I think are also used in the same way. Could the ssh-auth-socket solution be generalized for a configuration option similar to forward_env that takes a list of environment variables with the same magic support?

@ethanpailes
Copy link
Contributor

It sounds like rather than a unix socket, KITTY_LISTEN_ON uses a local tcp port, so the mechanism would have to be different. What we might be able to do is have shpool spawn a tcp proxy server on some port, re-write KITTY_LISTEN_ON to point to the port shpool itself is listening on, then have the proxy server re-target on reattach.

I'm a little leary of adding kitty-specific support though. Maybe what we need to do is allow users to put a config entry like

[[tcp_forward]]
pattern = "tcp:localhost:(\d+)"
env_var = "KITTY_LISTEN_ON"

then make this a generic capability, possibly with a default setting for kitty.

What are the values of KITTY_WINDOW_ID and KITTY_PUBLIC_KEY? If those aren't forwardable, this might not be worth it.

@ethanpailes
Copy link
Contributor

ethanpailes commented Aug 2, 2024

It might also be better to approach this from a different angle and allow a little more manual intervention than shpool usually tries to require. You could make a script called refreshenv like

#!/bin/sh

source $XDG_RUNTIME_DIR/shpool/sessions/$SHPOOL_SESSION_NAME/target-env

and then instead of doing shpool attach -f <session-name> do env > $XDG_RUNTIME_DIR/shpool/sessions/<session-name>/target-env && shpool attach -f <session-name>. We could potentially teach shpool attach to automatically populated the target-env file based on forward_env to make this a little easier. Then after an attach, just run source refreshenv

The advantage of this approach is that it is a full solution that doesn't require us to continually implement application specific hacks to deal with every weird thing that kitty does (and it does seem to be mostly kitty causing these sorts of problems).

@isaksamsten
Copy link
Author

I think your last suggestion is definitely the best solution! It would be great if this could be automated somehow for forwarded envs!

thanks for your support!

@Aetf
Copy link
Contributor

Aetf commented Aug 21, 2024

Some prior art in tmux using update-environment and show-environment: https://babushk.in/posts/renew-environment-tmux.html

The idea is when attaching, env vars specified in update-environment setting are updated by tmux in its own env vars copy from the client. Then in the shell, define some hook to read from show-environment when reattaching.

It's largely the same as dumping the env to a file, which needs to be transferred from client host to server host anyway.

@jeroen-dhollander
Copy link

I'm running into the same situation with X forwarding - when re-attaching from a new SSH connection the DISPLAY variable changes but the copy inside the shpool session remains the old (at this point broken) value.

@ethanpailes
Copy link
Contributor

I'm somewhat tempted to integrate https://github.com/shell-pool/subprocess-inject-env with shpool even though it only works for bash and then add an auto-dumping mechanism for the env vars in the shpool runtime directory for people using fancier shells.

@tkapias
Copy link

tkapias commented Sep 27, 2024

Finding a better way to forward important parts of env would be nice, but in the meantime I think that you should at least document forward_env in config.md.

I just asked liquid prompt (adaptative prompt) to add shpool detection in its features, but just after I saw that actually you need to force forward a few variables if you want to keep many features from missing.

Also you could comment with some advices, examples:

  • ~/.config/shpool/config.toml:
forward_env = ["DISPLAY", "KITTY_PUBLIC_KEY", "KITTY_WINDOW_ID", "SSH_AGENT_PID", "SSH_CLIENT", "SSH2_CLIENT", "SSH_CONNECTION", "SSH_TTY", "TERM", "TERM_PROGRAM", "TERMINFO", "WINDOWID"]
  • ~/.bashrc:

To keep the same variables when you sudo -i to root or another user (sudoi -u username) with bash.

alias sudoi='sudo -i --preserve-env=DISPLAY,KITTY_PUBLIC_KEY,KITTY_WINDOW_ID,SHPOOL_SESSION_NAME,SSH_AGENT_PID,SSH_CLIENT,SSH2_CLIENT2,SSH_CONNECTION,SSH_TTY,TERM,TERM_PROGRAM,TERMINFO,WINDOWID'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants