Skip to content

Instantly share code, notes, and snippets.

@jhnns
Created March 20, 2025 15:02
Show Gist options
  • Save jhnns/87cc80257bf16f92841ec8d336fd8a3b to your computer and use it in GitHub Desktop.
Save jhnns/87cc80257bf16f92841ec8d336fd8a3b to your computer and use it in GitHub Desktop.
Bash script to set up an SSH tunnel (in a Github action)

Bash script to set up an SSH tunnel

Starts an SSH tunnel in the background and checks if it is usable. Can be used in a Github action e.g. in order to connect to a Postgres instance that is only reachable via SSH.

You need to set the following env variables

Variable Description
SSH_TUNNEL_HOST The hostname of the machine, e.g. example.com
SSH_TUNNEL_PORT The SSH port you want to connect to (e.g. 22 )
SSH_TUNNEL_USER The SSH user, e.g. root
SSH_TUNNEL_PRIVATE_KEY The private key you are going to use for ssh
SSH_TUNNEL_HOST_PUBLIC_KEYS Public keys of the host that will be appended to known_hosts. Necessary to prevent MITM attacks. Use ssh-keyscan $SSH_TUNNEL_HOST to get the keys.
SSH_TUNNEL_LOCAL_PORT The local port you want to open
SSH_TUNNEL_REMOTE_HOST The hostname you want to connect to from SSH_TUNNEL_HOST
SSH_TUNNEL_REMOTE_PORT The port you want to connect to at SSH_TUNNEL_REMOTE_HOST

The script is going to exit with code 0 as soon as SSH_TUNNEL_LOCAL_PORT is usable on localhost.

#!/usr/bin/env bash
set -o errexit # exit when there was a single error
set -o pipefail # fail when there was a pipe error
set -o nounset # fail when an env variable is not set
# set -x # Set for debugging
echo "Adding SSH key to the agent..."
eval "$(ssh-agent -s)"
echo "${SSH_TUNNEL_PRIVATE_KEY}" | ssh-add -
echo "Adding public key to known_hosts..."
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "$SSH_TUNNEL_HOST_PUBLIC_KEYS" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
echo "Creating SSH tunnel..."
ssh -o StrictHostKeyChecking=yes -L "$SSH_TUNNEL_LOCAL_PORT":"$SSH_TUNNEL_REMOTE_HOST":"$SSH_TUNNEL_REMOTE_PORT" -p "$SSH_TUNNEL_PORT" "$SSH_TUNNEL_USER"@"$SSH_TUNNEL_HOST" -N -f
echo "Validating SSH tunnel..."
for i in {1..5}; do
if nc -z localhost "$SSH_TUNNEL_LOCAL_PORT"; then
echo "SSH tunnel is up."
break
fi
if [ "$i" -eq 5 ]; then
echo "SSH tunnel failed to establish after 5 attempts."
exit 1
fi
echo "Attempt $i: SSH tunnel not established yet, retrying..."
sleep 2
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment