It is a little pain to copy files from a remote server in a GitHub action as you need to do authenticate and if your key is passphrase protected then it adds extra pain to it.
First, we should not use sensitive data directly, that’s why GitHub provide feature like secrets. So as per our requirement, we should keep our SSH private key and passphrase secret. The below code is what you are looking for.
- name: Copy Result
env:
SSH_KEY: ${{secrets.SSH_KEY}}
run: |
echo "$SSH_KEY" >> key
chmod 600 key
eval `ssh-agent -s`
{ sleep .1; echo ${{secrets.PASSPHRASE}}; } | script -q /dev/null -c 'ssh-add key'
scp -P 2710 -o StrictHostKeyChecking=no user@host:source destination
name: Denotes the name of this step.
env: Here, we set env variables which I will use in the script.
run: Statement inside this tag is run one by one inside the GitHub runner. This is where we write our logic to fetch a particular file from a remote server. Let’s see what they are.
echo "$SSH_KEY" >> key
Here we are saving our ssh private key inside a file called a key, this later will be used in scp
command because scp internally use ssh
chmod 600 key
This is an important step because the key file has very sensitive data and this should be protected. Here we are giving read and write access to the owner of the file only. Others can’t access this file.
If your ssh key is not passphrase protected, the following command will work without any problem.
scp -i key -P {port} -o StrictHostKeyChecking=no {user}@{host}:{source_path} {destination_path}
# -i takes path of private key
# -P port of ssh, by default it is 22
# -o SSH comes with lots of happens, refer man of scp.
# StrictHostKeyChecking=no when we connect to a server first time then a prompt comes are you want to store the fingerprint of this server. To bypass that check we use this command.
The main problem is we don’t want prompts because it is automated scripts. Prompts should be bypassed.
Now comes the other section, with a passphrase. The pain is of another level when you don’t know that there exists something as ssh-agent and its concept.
SSH-Agent
SSH-agent is used to remember your private keys and passphrase if the key is encrypted. SCP doesn’t take passphrase as an argument, that’s why we have to use ssh-agent so when ssh is requested from scp command ssh-agent pass the key with a passphrase for us.
eval `ssh-agent -s`
This command helps us to start the agent.
{ sleep .1; echo ${{secrets.PASSPHRASE}}; } | script -q /dev/null -c 'ssh-add key'
See this as 2 commands one { sleep .1; echo ${{secrets.PASSPHRASE}}; }
and another is script -q /dev/null -c 'ssh-add key'
check what | stands for In short, it denotes the output of the first part is served as input to the second part of the code.
So let’s see the second part script -q /dev/null -c 'ssh-add key'
Scripts record commands and their output, -q indicates to run in silent, -c indicates instead of running an interactive shell just run only this command. Now this will prompt for the passphrase to enter which will be passed by the first part of the command.
{ sleep .1; echo ${{secrets.PASSPHRASE}}; }
After running this our ssh-agent has our private key with passphrase, so now if we run following SCP command the ssh key and passphrase passed directly ssh agent
scp -i key -P {port} -o StrictHostKeyChecking=no {user}@{host}:{source_path} {destination_path}
Awesome, now you can read a file from remote server in Github Actions using ssh key.