Skip to content

Instantly share code, notes, and snippets.

@dcode
Created January 25, 2024 16:08
Show Gist options
  • Select an option

  • Save dcode/912be128174c468a2dc28f263bdb7328 to your computer and use it in GitHub Desktop.

Select an option

Save dcode/912be128174c468a2dc28f263bdb7328 to your computer and use it in GitHub Desktop.
Automatic waypipe setup for SSH remote forwarding of clipboard (via wl-copy/paste) and other Wayland clients

README

The goal of this gist is to setup waypipe to automically run locally on user login and remotely when you connect to it. In both cases, this is managed by systemd user session and assumes that is running. This took way too long to figure out, so I hope it helps someone (or me) in the future.

Instructions

Local

On your local system, copy the waypipe-client.service to the user systemd directory.

install -d 0755 ${HOME}/.config/systemd/user/
install waypipe-client.service ${HOME}/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now waypipe-client.service

Configure SSH Remote Forward by creating or amending an entry for your remote host. It should look like the ssh_config file in this gist.

Remote

On the remote system, do similarly with waypipe-server.service.

install -d 0755 ${HOME}/.config/systemd/user/
install waypipe-server.service ${HOME}/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now waypipe-server.service
# Append to ${HOME}/.ssh/config
Host my-remote
# other relevant configuration
RemoteForward ${XDG_RUNTIME_DIR}/waypipe-server.sock:${XDG_RUNTIME_DIR}/waypipe-client.sock
# ${HOME}/.config/systemd/user/waypipe-client.service
[Unit]
Description=Runs waypipe on startup to support SSH forwarding
[Service]
ExecStart=/usr/bin/waypipe --socket %t/%N.sock client
[Install]
WantedBy=default.target
# ${HOME}/.config/systemd/user/waypipe-server.service
[Unit]
Description=Runs waypipe on startup to support SSH forwarding
[Service]
Type=simple
ExecStart=/usr/bin/waypipe --socket %t/%N.sock --no-gpu --display %t/wayland-remote server -- sleep inf
[Install]
WantedBy=default.target
@b2ag
Copy link

b2ag commented Sep 26, 2025

My solution is now based on @dcode's and @zelch's.

I changed the waypipe-server.service to waypipe-server@.service with following content.

[Service]
ExecStart=waypipe --socket %t/%N.sock --unlink-socket --no-gpu --display wayland-%i server -- sleep inf
ExecStartPre=-rm '%t/wayland-%i'
ExecStopPost=-rm '%t/wayland-%i'
Restart=on-failure
Slice=session.slice

[Unit]
Description=Runs waypipe server for %I

And use waypipe-client.service almost unchanged.

Than I tagged my waypipe hosts in ~/.ssh/config but did the setup step upfront like follows. Assuming waypipe-server@.service is available on the remote host.

Host some_system
  Tag waypipe

Match Tagged waypipe,!waypipe-setup Exec "ssh -P waypipe-setup -p %p %r@%n systemctl --user start waypipe-server@%u@%L --no-block || true"
  RemoteForward ${XDG_RUNTIME_DIR}/waypipe-server@%u@%L.sock:${XDG_RUNTIME_DIR}/waypipe-client.sock
  SetEnv WAYLAND_DISPLAY=wayland-%u@%L

EDIT: Just noticed that XDG_RUNTIME_DIR locally and on the remote side could differ. That won't happen for my setups but could happen in general and is NOT handled correctly here. Sorry for that.

Thanks again to both of you! ❤️

@zelch
Copy link

zelch commented Sep 27, 2025

@b2ag I started with sleep inf, but found that after connections died or were killed I had 'sleep inf' processes hanging around on the server.

That wasn't very friendly, thus the tail | ssh host cat hack.

And ssh -O exit host does the job of killing the connection cleanly. :)

I'm going to have to play with your service, that looks pretty nice.

@b2ag
Copy link

b2ag commented Sep 27, 2025

I started with sleep inf, but found that after connections died or were killed I had 'sleep inf' processes hanging around on the server.
That wasn't very friendly, thus the tail | ssh host cat hack.

I see. In situations like that I usually did a sleep 1d or similar. Nice idea to use cat as a detection for a closed connection/stdin.

And ssh -O exit host does the job of killing the connection cleanly. :)

Understood. Not used to using exit. Stop usually worked for me 😅

I'm going to have to play with your service, that looks pretty nice.

Give it a shot!

More thoughts:

Automatically stopping the waypipe server services after use would be nice. Tracking all potential users (e.g. ssh connections) or tracking by activity would be quite hard though. A sleep 1d instead of a sleep inf would ensure the services stops, but is NOT guarantied to NOT happen in the middle of your work session the next day. Something to reset a stop timer timeout is missing here.

Also I put a || true in the exec statement to ensure it never fails because it's a hack and not really a qualifier script or something. Though if the service isn't present at the remote host, without this || true, the matching should fail, which would prevent the remote forwarding and setting of WAYLAND_DISPLAY. A desired outcome prevented by my addition I guess 🤷

Happy hacking and have a nice weekend!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment