· Alexander · GitHub  · 8 min read

GitHub Actions - Automatically Deploy Docker Updates to Cloud Hosts via SSH

Automatically deploy docker updates to your cloud hosts using GitHub Actions and SSH

Automatically deploy docker updates to your cloud hosts using GitHub Actions and SSH

This is part 3 of this series so if you haven’t completed part 1 and part 2 yet, go back if you want to follow along. In this part we will be updating our Caddy pipeline to deploy updates from Actions to a VM running in Linode’s cloud. As we are using Docker to run Caddy this will be very easy. In Part 4 we will be building a binary and pushing it to the Linode VM instead, which is slightly more complicated.

The Environment

I will be running this series as if you were running on Windows 10/11 with Visual Studio Code installed. Now this series can also be followed fairly easily if you are running Linux setup or WSL. I am also assuming you have a general understanding of the command line interface. If you need more help, leave a comment below and I will reach out!

Pre-Requisites

You should have these items completed and set up before trying to follow this post.

Setting up the VM

First we need to create a new user account on our VM so Actions is not logging in as root. To do this, first SSH into your VM as root (since we haven’t setup any other users yet) and run the following commands to create a new non-root user.

Terminal window
ssh i- /path/to/private_key root@host
Terminal window
# Create a new user called "actions" with a home directory (-m).
useradd -s /bin/bash -m -c "GitHub Actions Account" actions

After the command completes, create a password for the new account.

Terminal window
passwd actions

Follow the prompts to set a new password for the actions account. Once done, switch to the new user and verify the home directory was created properly.

Terminal window
su actions && cd ~ && ls -a -l

You should see some default hidden files that were created:

Terminal window
total 20
drwxr-xr-x 2 actions actions 4096 Jul 6 14:55 .
drwxr-xr-x 4 root root 4096 Jul 6 14:55 ..
-rw-r--r-- 1 actions actions 220 Feb 25 2020 .bash_logout
-rw-r--r-- 1 actions actions 3771 Feb 25 2020 .bashrc
-rw-r--r-- 1 actions actions 807 Feb 25 2020 .profile

Now create the .ssh directory structure for the actions user.

Terminal window
mkdir .ssh
touch .ssh/authorized_keys

Set permissions on the .ssh directory.

Terminal window
chmod 700 .ssh
chmod 600 .ssh/authorized_keys

Now Add the second key pair’s public key to the .ssh/authorized_keys file. From your PC run the following commands depending on the OS:

Windows 10/11

Terminal window
type $env.USERPROFILE\.ssh\mykey.pub | ssh actions@host "cat >> .ssh/authorized_keys"

Linux

Terminal window
ssh-copy-id -i ~/.ssh/mykey.pub actions@host

You can then test to make sure your SSH key auth is working.

Terminal window
ssh -i ~/.ssh/mykey actions@host

Make sure to update the path to the public key file and the @host to the public IP/DNS name of your VM.

Once we have verified that our user can login via SSH, we can disable password auth for the VM. Switch back to root and edit the /etc/ssh/sshd_config file.

Terminal window
su root
# `exit` can also be used
nano /etc/ssh/sshd_config

Hit CTRL+W to enter search and type PasswordAuthentication and hit Enter. Change the value from yes to no. Hit CTRL+X then y to save and close the file. Now restart the sshd service so the changes take affect.

Terminal window
systemctl restart sshd

Creating the File Structure

Now we need to setup and create the directory structure for Caddy on the Linode VM. Run the following commands to setup the directory and file structure for Caddy.

Terminal window
mkdir ~/caddy
mkdir ~/caddy/data
mkdir ~/caddy/Caddyfile
mkdir ~/caddy/docker-compose.yml

Now edit the docker-compose.yml file:

Terminal window
nano ~/caddy/docker-compose.yml

Copy the following into the docker-compose file. Make sure to change <username> to your Docker Hub username. If you used GitHub’s container repo, make sure to add ghcr.io/ in front of your username, which should be your GitHub one (e.g. ghcr.io/alexandzors/caddy).

docker-compose.yml
version: '3.6'
services:
caddy:
restart: always
logging:
driver: "json-file"
options:
max-size: "500k"
max-file: "1"
image: <username>/caddy
ports:
- 80:80
- 443:443
volumes:
- ~/caddy/config/Caddyfile:/etc/caddy/Caddyfile:ro
- ~/caddy/config:/config
- ~/caddy/data:/data

Save and close the file by hitting CTRL + X then y.

Now edit the Caddyfile and add the following content (same quick start from Caddy’s docs):

Terminal window
nano ~/caddy/config/Caddyfile
Caddyfile
#Caddyfile
yourdomain.tld
respond "Hello World"

Save and close the file by hitting CTRL + X then y. We can leave the current SSH session open as we will be needing it later.

Updating the Actions pipeline

Now that we have the VM file structure ready to go, we can update our GitHub Actions pipeline to automatically update our docker container on image updates. Navigate to our actions repository and open the actions.yml file with your favorite text editor. Now add the following lines at the end of the file:

actions.yml
[Previous YAML content...]

Once you are done editing, save the file.

Updating Actions Secrets

With our actions pipeline file updated, we need to update our secrets to match. Navigate to your repository on GitHub.com and click on the Settings tab > Secrets > Actions, then create the following secrets:

NameValue
LINODEhostpublic ip / dns name of your Linode VM
LINODEuserusername for login
LINODEkeySSH secret key (use the second pair’s secret key not the one you used to deploy the host with.)

Updating the Repository

Now that we have the secrets created we can update our repository.

Terminal window
git add .
git commit -m "set actions to update linode vm"
git push

After the push our actions pipeline will automatically kick off. To watch the log, return to the repository on GitHub and click on the Actions tab. Under “All Workflows” click on Caddy. The newest run should show up as a yellow flashing dot. Click on the item title to view the pipeline and follow the log output. When it completes we can run a curl check on our webserver to verify its running.

Terminal window
curl https://yourdomain.tld

If successful, you should get a Hello World response. If it fails, return to your SSH session and first check that Caddy is running using docker ps.

Docker 'ps' output showing Caddy running Docker ps output showing Caddy container running

If it is not, cd to the caddy directory and manually run the container.

Terminal window
cd ~/caddy
docker compose up

If it starts up with no errors, terminate the container using CTRL+C. Then double check your action’s file commands for spelling mistakes during the container running portion under the “Deploy to VM” step. As always, if you run into issues, let me know in the comments or reach out via email and I’ll gladly walk you through it! Check out part 4 where we change up the pipeline to build and release a binary version of Caddy.

Thanks to my good friend Stefan for helping proof this post series!


FTC: Some links in this post are income earning affiliate links.
Back to Blog

Comments


Related Posts

View All Posts »