Say you’ve got a pipeline for building a new image, but you’d like to also make sure the Docker host redeploys the app whenever it gets updated. (I’m not going to go into how to actually do that (yet?) but this will cover at least being able to SSH and run an arbitrary command.)
Host setup
Create a service account user:
sudo useradd -r -c "Gitlab Deployment User" -s $(which bash) -m gitlab-deployGenerate a keypair:
sudo -u gitlab-deploy ssh-keygen -t ed25519base64 encode the private key:
sudo -u gitlab-deploy bash -c 'cat ~/.ssh/id_ed25519 | base64 -w0'Copy the output and add it as a masked Gitlab CI variable called SSH_PRIVATE_KEY_B64.
It needs to be base64 encoded because Gitlab refuses to mask variables containing whitespace. 🙄
copy/append the public key to ~/.ssh/authorized_keys so the account can log in with the key:
sudo -u gitlab-deploy bash -c 'cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys'
sudo -u gitlab-deploy bash -c 'chmod 600 ~/.ssh/authorized_keys'From another machine, capture the public keys of the remote host:
ssh-keyscan -H remote-host.example.comCopy the output and save it as a file type Gitlab CI variable called “SSH_KNOWN_HOSTS”.
Gitlab setup
In addition to the SSH_PRIVATE_KEY_B64 and SSH_KNOWN_HOSTS CI variables, also create one called SSH_USER_HOST which contains something like gitlab-deploy@remote-host.example.com.
Then use a job like this:
deploy-job:
stage: deploy
image: alpine:latest
before_script:
- apk update && apk add openssh-client
- mkdir -p ~/.ssh
- eval $(ssh-agent -s)
- echo $SSH_PRIVATE_KEY_B64 | base64 -d | tr -d '\r' | ssh-add -
- cp $SSH_KNOWN_HOSTS ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
- ssh $SSH_USER_HOST echo "Hello from \$HOSTNAME"