DEV Community

Nasrul Hazim Bin Mohamad
Nasrul Hazim Bin Mohamad

Posted on

Automating Code Deployment with GitHub Actions via SSH

In today's world of continuous integration and deployment, automating the process of pushing code updates to your server is crucial. One of the most popular ways to streamline this is through GitHub Actions, which allows you to create automated workflows directly from your GitHub repository.

In this blog post, I'll walk you through how to SSH into a remote server, pull the latest code from a Git repository, install dependencies, and restart services — all automated with GitHub Actions. We'll be using the GitHub Token (GITHUB_TOKEN) for authentication, which simplifies the process and improves security.

Why Use GitHub Actions for Deployment?

GitHub Actions allows you to automate a wide variety of workflows directly from your GitHub repository. Whether it's testing, building, or deploying your code, GitHub Actions provides a powerful, flexible platform to handle these tasks. For deployment, GitHub Actions can:

  • Automate server updates whenever you push changes to a specific branch.
  • Handle SSH connections and execute remote commands seamlessly.
  • Use GitHub Token for secure, token-based authentication, avoiding the need to manually input credentials.

Deployment Workflow Overview

Here’s what the GitHub Action will do:

  1. Trigger the workflow when code is pushed to the master branch.
  2. SSH into the remote server using stored credentials.
  3. Pull the latest code from GitHub using the GITHUB_TOKEN.
  4. Install dependencies if needed (e.g., with pip for Python projects).
  5. Restart services to apply changes.

Let's dive into the actual implementation!

Step-by-Step Guide

Prerequisites

Before we get started, make sure you have:

  1. A GitHub repository with the code you want to deploy.
  2. A remote server where you have SSH access and want to deploy the code (e.g., a VPS or cloud instance).
  3. The necessary credentials (username, password, and the GitHub repository token) added as GitHub Secrets.

Adding GitHub Secrets

In your GitHub repository, you’ll need to add the following secrets:

  • SERVER_USER: The SSH username to log into your server.
  • SERVER_PASSWORD: The password for SSH login (use strong passwords or, ideally, SSH keys).
  • SERVER_HOST: The IP address or domain name of your server.
  • GITHUB_TOKEN: This is automatically available for use in GitHub Actions, but you can override it if necessary.

To add these secrets:

  1. Go to your GitHub repository.
  2. Navigate to SettingsSecrets and variablesActions.
  3. Add each secret individually, ensuring you enter the correct values.

Writing the GitHub Action

Here’s the workflow file that will automate the deployment process.

name: Deploy to Server

on:
  push:
    branches:
      - master  # Trigger the action on a push to the 'master' branch

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v3

    - name: Install sshpass
      run: sudo apt-get install -y sshpass

    - name: SSH into server and deploy application
      run: |
        sshpass -p "${{ secrets.SERVER_PASSWORD }}" ssh -o StrictHostKeyChecking=no ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} << EOF
          cd /var/www/your-app

          # Set GitHub credentials using GITHUB_TOKEN
          git config --global credential.helper store
          echo "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}" > ~/.git-credentials

          # Pull the latest code from the repository
          git pull origin master

          # Install dependencies
          pip install -r /var/www/your-app/requirements.txt

          # Restart the service
          sudo systemctl stop your-app
          sudo systemctl start your-app
        EOF
Enter fullscreen mode Exit fullscreen mode

How This Works:

  1. Trigger: The workflow is triggered by any push to the master branch. You can adjust this to fit your branching model, such as using main or another branch.
  2. Install sshpass: We install sshpass, a tool that allows password-based SSH logins in non-interactive environments. This avoids having to manually input a password during deployment.
  3. SSH into the server: Using sshpass with the credentials stored in GitHub Secrets, we securely SSH into the remote server without exposing sensitive data.
  4. Pull latest code with GITHUB_TOKEN: Instead of using a username and password, we take advantage of the GitHub Token (GITHUB_TOKEN), which GitHub automatically provides during workflow execution. We store the token in ~/.git-credentials to enable Git to authenticate without user interaction.
  5. Install dependencies: After pulling the latest code, we ensure all necessary Python dependencies are installed using pip.
  6. Restart the service: Finally, we restart the relevant service to apply the changes. In this case, the your-app service is stopped and started again using systemctl.

Key Security Benefits:

  • GITHUB_TOKEN: The GITHUB_TOKEN is automatically provided by GitHub in each workflow run. It allows you to authenticate for git pull, git push, and other repository-related actions securely. It’s valid only during the workflow execution and doesn't require manual management, which reduces the risk of leaking credentials.
  • GitHub Secrets: Storing sensitive information like SSH credentials in GitHub Secrets ensures they’re encrypted and only accessible during the workflow runtime.

Why Use GITHUB_TOKEN?

Using the GITHUB_TOKEN for Git operations offers several advantages:

  • Security: You don’t have to manually store or manage Personal Access Tokens (PATs) or GitHub credentials.
  • Ease of Use: GitHub manages token rotation automatically, meaning you don’t have to worry about expired or invalid tokens.
  • Minimal Setup: The token is automatically injected into every workflow run, requiring minimal configuration.

Conclusion

By combining GitHub Actions with GITHUB_TOKEN and sshpass, you can easily automate the deployment of your code to a remote server. This approach not only simplifies the deployment process but also improves security by handling credentials properly and reducing the need for manual input.

This method is highly customizable and can be adapted to various deployment scenarios, whether you’re managing a simple project or a complex multi-service application.

Next Steps

  • Consider adding additional steps for things like database migrations or other application-specific commands.
  • Explore GitHub’s support for environment-specific secrets to handle deployments to multiple environments (e.g., staging, production).

Feel free to extend this workflow to suit your project’s needs, and happy coding! 🚀

Top comments (0)