Kloudle
academy

Deploying web applications with GitHub Actions

Riyaz Walikar
#githubactions#cloudsecurity
Feature image

Who is this article for?

This article is focused on people who are interested in, first of all, automation of deployments, and secondly, for people who want to learn more about GitHub Actions. The article is intended to serve both, complete beginners who are venturing into their first foray into automated deployments, and the seasoned veterans of industry who know how to exit Vim and are curious about this (relatively) shiny, new deployment tool - GitHub Actions.

What are GitHub Actions?

Virtually all of us are familiar with GitHub, the platform that provides storage for version-controlled software repositories. GitHub now also provides a compute service, called GitHub Actions, to perform operations such as packaging, deployment on GitHub itself instead of first fetching code into another tool/platform, and then working on it.

GitHub Actions consists of a YAML file that contains all the instructions that are to be executed on the repository along with some other meta-information like which operating system to run the steps on, which secrets to use, and so forth. GitHub Actions is really useful, not only because they allow you to write the required processing/packaging steps for the code right along with the code itself, but also because it is free! Well, somewhat. Most other cloud providers that give either finite amount of credits (ahem! GCP ahem!) or have a time limit associated with free-tier resources (not taking any names like AWS). GitHub Actions, on the other hand, has a free-tier with it’s quota refreshing every month. This is incredibly useful for someone, for example, that only wants to package their software and not rent a server to accomplish a fairly simple task.

Deploying Application with GitHub Actions

Okay, enough talk, let’s start using GitHub Actions now! In the upcoming sections, we will deploy a simple web application to a server every time a new commit is made to the mas… Oops! I mean main branch!

Prerequisites

Before we begin, there are a few things that are required to be set up:

  1. A GitHub account (this really should not come as a surprise)
  2. A server (to serve the web application that will be deployed)

Setting up the repository

Let’s start setting up our repository both, locally and on GitHub.

  1. Log into your GitHub Account by navigating to https://github.com/login (on a side note, enable 2-factor authentication for your account if you have not already!)

  2. Click on the “New” button to create a new repository

    create a new repository

  3. Next, fill the details such as the repository name, description and it’s always a good idea to have a README.md for your repositories, and click on the “Create repository” button

    Create repository

  4. On the repository page, click on the “Code” dropdown and copy the Git URL for the repo, HTTPS or SSH, whichever one works for you.

    repository page code dropdown

  5. Now in a terminal window clone the repository locally by running the following command:

    git clone

    git clone

  6. Now we can open the repository/folder with the code editor of our choice. I have used VSCode for this example.

  7. Let’s add a single index.html file so we have something to serve as our web application.

<!DOCTYPE html>

<html>

     <head>

           <title>Kloudle Academy</title>

     </head>

           <body>

                 <p>Welcome to Kloudle Academy!</p>

           </body>

</html>
  1. This is how the files in the repository look now:

    repository files

Adding secrets to GitHub Secrets

To be able to SSH into the server we want to deploy our web app to, we need an SSH key. Keep in mind, we also need to avoid committing the key to the repository as anyone with access to the repository will also have access to the key. A lot of meaningful workflows would need some kind of credentials to perform their actions - Pushing code to a server, fetching files from S3, uploading a scan report somewhere, etc. We can use GitHub secrets to add these secrets to our repository without having to commit them.

To add a secret to the repository, in our case the SSH Private key, perform the following steps:

  1. Navigate to the repository’s settings page, click on the “Secrets” menu and then the “New repository secret” button.

    GitHub Secrets

  2. Then give the secret a name (I prefer using all caps with underscores so it’s easy to identify secrets in the workflow), the secret value and click on the “Create secret” button.

    Create GitHub secret

Note: There are two kinds of secrets in GitHub - repository and organization. The difference between the two is that repository secrets are only available to the repository they are added for, while organization secrets are available to all repositories in the organization. Organization secrets are great to store credentials that are used by multiple repositories, it makes it much more convenient to rotate and revoke them if required. A quick factoid - if a secret is added with the same name to both, a repository and the organization, GitHub Actions will give precedence to the repository secrets and use it instead of the organization secret.

Enabling GitHub Actions

Before we can run our workflows on GitHub Actions, we need to enable our repositories for it. To enable Actions for the repository,

Navigate to the repository’s settings tab, select the “Action” menu item and ensure that the “Allow select actions” option is chosen along with only the “Allow actions created by GitHub” checkbox and click the “Save” button.

Enabling GitHub Actions

While any of the annotated options mentioned in the above screenshot would have worked, they have different levels of permissions on which sources in the Actions Marketplace we trust to run actions from:

  1. “Allow all actions” permissions is overly permissive, it allows any actions from the marketplace to be run as part of our workflows irrespective of who the author is.
  2. “Allow local actions only” allows only the actions that are defined in the repository to run, but these local workflows can no longer use pre-built actions from the marketplace.
  3. “Allow select actions” allows local actions as well as actions that were created by GitHub and/or Verified creators to run as part of our workflows. This is the option I recommend to use, to avoid accidentally using an unsafe action from the marketplace.

Writing the Workflow file

Now that we have all permissions and secrets in place, let’s write the workflow file that would deploy our variant of the Kloudle Academy website.

  1. Create the following directories inside the repository

    cd /path/to/repo

    mkdir -p .github/workflows

mkdir workflows

  1. Now with the code editor of your choice, add a new YAML file called server-deployment.yml and paste the following content in the file (note that this is not the complete configuration, we will get to it soon)

name: "Server Deployment"

on:

	push:

  		branches: [main]

jobs:

	deployment:

  	runs-on: ubuntu-latest

    steps:

    - uses: actions/checkout@v2

    - name: Say Hello!

    run: echo "Hello there!"

A quick primer on the different sections present in the workflow:

  1. Let’s commit all the files we have added and push to GitHub to see our workflow’s execution
git add .

git commit -m "Adding index.html and workflow file"

git push origin main

commit workflow files

  1. Next, navigate to the GitHub repository, go to the Actions tab and click on “Server Deployment” workflow and then click on the commit message to see execution details for the workflow

github actions

  1. Next click on the “deployment” job and now we can see our workflow’s output

workflow’s output

  1. Before moving ahead, let’s see how our current app deployment looks like

app deployment through github actions

  1. Now we know how to add commands to the workflow and how to check it’s execution, with that let’s add the deployment steps to copy our HTML file
name: "Server Deployment"

on:

	push:

  	branches: [main]

jobs:

	deployment:

	runs-on: ubuntu-latest


	steps:

	- uses: actions/checkout@v2

	- name: Say Hello!

	run: echo "Hello there!"



	- name: Deploy code to Server

	env:

		SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}

	run: |

		echo $SSH_KEY | base64 -d > ssh-key

    chmod 400 ssh-key

    	ssh -i ssh-key -o StrictHostKeyChecking=no ubuntu@3.145.1.14 "cd /home/ubuntu/sample-app-deployment-with-github-actions && GIT_SSH_COMMAND='ssh -i /home/ubuntu/.ssh/ssh-key' git pull origin main"

‍ 8. Optionally, add a few changes to our _index.html _file so we can see our changes once deployed

  1. We will repeat Step 3 to commit and push all updates to GitHub with the new commit message “Deploying changes!”

    commit and push all updates to GitHub

  2. Repeating steps 4 and 5 for the latest build, shows us a successful deployment (ignore the build number in this image)

successful deployment

  1. And lastly, let’s check our cutting edge website

website deployed with github actions

Conclusions

GitHub Actions is an amazing service that can be utilised to perform almost all kinds of operations on our code and repositories - packaging, deployment, etc. Although it does require buying a plan to unlock its full potential, the refreshing quota system present in the free-tier is a boon and is good for most individual projects. We took a look at an example where we deploy one static page to a server, but there could be other complex scenarios as well such as building a docker image and then deploying it to AWS’ Elastic Container Service, or GCP’s Cloud Run.

The idea of this blog is to provide building blocks with a brief introduction about GitHub Actions and workflows and enable the readers to start writing their own workflows. Some scenarios may require troubleshooting but once we get the hang of it, GitHub Actions becomes yet another tool in our DevOps tool belt.


This article is brought to you by Kloudle Academy, a free e-resource compilation, created and curated by Kloudle. Kloudle is a cloud security management platform that uses the power of automation and simplifies human requirements in cloud security. If you wish to give your feedback on this article, you can write to us here.

← Back to Academy