Skip to main content

Lucoles LTDA

Full Stack Developer, Acquia Certified Drupal 10 and Drupal 7, ITIL, PSM

this CI/CD guide will make it easier to go live from your GitHub repository to your webhost leveraging SSH keys and automated GitHub Actions with built-in security

Image
a 3D blue guy is in a server room, holding a metal pipe out of which semitransparent zeroes and ones in shades of green and red are pouring onto a computer screen with code.
Caption
that's not exactly what we'll be doing, but it's close.

ah, the good ol' days of webdesign, when all it took was a few images, some HTML tables, a Geocities account and an FTP connection to own a piece of virtual estate.

nowadays however, with tech making everything easier, it's not that simple anymore.

last year I chose to move from Hostgator to Hostinger after 15+ years of service — we're not old, we're classic — and the main thing I was looking for was a more future-proof way to go about publishing my website(s).

so while life was happening, I took my time to look up how best to leverage GitHub and Hostinger and build a simple CI/CD pipeline to update code locally, push it, and have the changes delivered, no muss no fuss, to my website.

and now you'll be able to follow along and get a similar result for yourself! although this approach was put together with the aforementioned services in mind, with a little bit of tinkering you should be able to make it work with any combination of web hosting plan and developer platform you choose — provided you can SSH into your web host and run Terminal commands.

so without further ado, let's roll up our sleeves and get busy!

1. generate SSH Key in Hostinger

Image
screenshot of the Hostinger Main menu, with the "Dashboard" button, to the right of "example.com", highlighted. the button has a light purple set of rounded rectanges as its icon. to the left, "Websites list" is selected.
Caption
examples galore.

on the Main menu, under Websites list, click on Dashboard to the right of the desired domain.

Image
screenshot of the "Git" section of the Hostinger Menu, with the "Generate SSH key" button, under "Private Git Repository", highlighted. the button has a light green background. to the left, "Git" is selected among several options under "Advanced".

then go to Advanced > GIT and click on Generate SSH key. this is good for any Hostinger deployment, regardless of repository.

Image
screenshot of the "Git" section of the Hostinger Menu, with a the title "Private Git Repository" and an uneditable textarea showing a "lorem ipsum" block of text where a random string of letters and numbers usually sits. under it there's a "Copy" button with light purple line icon and text against a white background, and a "Remove SSH Key" in white against a magenta background.
Caption
huh. the key is exactly an entire paragraph of Lorem Ipsum. what are the odds?

2. add the public Hostinger SSH Key to GitHub

Image
portion of a screenshot showing the options "Try Enterprise", "Feature preview", and "Settings". the latter is highlighted by mouseover.

on GitHub, click on your profile pic then go to Settings > SSH and GPG keys.

Image
screenshot of the "SSH and GPG keys" under "Settings". there are three SSH keys at the center, each with a sci-fi reference in its title. at the top right-hand corner, a button is highlighted with "New SSH key" in white against a light green background. to the left, several options are visible, with "SSH and GPG keys" selected under "Access".
Caption
it's been a while since any of those keys was used.

click on New SSH key, paste the contents of the public key generated in Hostinger, and save it as HOSTINGER_SSH_PUBLIC.

3. retrieve the Hostinger server's SSH host key

on Terminal, run:

$ ssh-keyscan -H -p your_hostinger_port your_hostinger_server_ip_or_domain

you can fetch that info from the following screen:

Image
screenshot of the "SSH Access" section of the Hostinger Menu, with a highlited table showing access information under "SSH details": IP, port, username, and password.

it will come in handy later on, so write it down (and don't share with anyone).

that kind of information should not be hardcoded in your repository as it could be a major security risk. instead, save it as GitHub Secrets by going to the Settings tab of your repo and clicking on Secrets and variables > Actions > New repository secret.

Image
screenshot of the "Actions secrets and variables" under "Settings". there is an instruction text at the center, and a "New repository secret" button highlited, in white text against a light green background. at the top right-hand corner, a button is highlighted with "New SSH key" in white against a light green background. to the left, several options are visible, with "Secrets and variables" selected under "Actions".

add the host key you generated with ssh-keyscan to your GitHub repository secrets as HOSTINGER_KNOWN_HOST_KEY. also set up GitHub Secrets for HOSTINGER_PORT, HOSTINGER_USERNAME, and HOSTINGER_HOST.

when you set up the GitHub Secret for HOSTINGER_PASSWORD, keep in mind that's the same as your SSH password, not your account password.

a friend of a friend spent a few hours scratching his head beacause of this difference.

4. encode a private key and add it to GitHub Secrets

on terminal, SSH into Hostinger and execute:

$ ssh-keygen -t rsa -b 4096 -C "github-to-hostinger-deploy" -f github-to-hostinger
cat github-to-hostinger | base64 -w0

add the resulting key to GitHub Secrets as HOSTINGER_SSH_PRIVATE_ENCODED.

create a new file in your repo called hostinger.yml under .github/workflows/:

name: Deploy to Hostinger via SSH

on:
  push:
    branches:
      - master

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout repository
      uses: actions/checkout@v4
      with:
        fetch-depth: 0
        show-progress: true
    
    - name: Log job start
      run: echo "Starting job..."
    
    - name: Deploy via SSH
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.HOSTINGER_IP }}
        username: ${{ secrets.HOSTINGER_USERNAME }}
        password: ${{ secrets.HOSTINGER_PASSWORD }}
        key: ${{ secrets.HOSTINGER_SSH_PRIVATE_ENCODED }}
        port: ${{ secrets.HOSTINGER_PORT }}
        script: |
          # Add the manually verified host key to known_hosts
          echo "${{ secrets.HOSTINGER_KNOWN_HOST_KEY }}" >> ~/.ssh/known_hosts

          # Check if the directory is a Git repository
          if [ ! -d "/home/your_username/domains/example.com/public_html/.git" ]; then
            # If not, initialize it
            cd /home/your_username/domains/example.com/public_html/
            git init
            git remote add origin git@github.com:LucolesLTDA/luco_net_br.git
          else
            # If it is, just change to the directory
            cd /home/your_username/domains/example.com/public_html/
          fi

          # Automatically accept GitHub's host key
          ssh-keyscan -H github.com >> ~/.ssh/known_hosts

          # Pull latest changes on master branch
          git pull origin master

          # Install
          composer2 install
    
    - name: Log job completion
      run: echo "Job's done!"

this script will:

  1. only work on the master branch when changes are pushed
  2. instantiate a container to carry out the deployment
  3. log the beginning of activities
  4. ensure connection happens without any issues
  5. check for the existence of a Git repo in Hostinger
  6. initialize Git if needed
  7. connect Hostinger to GitHub
  8. pull the changes
  9. (re)install the codebase with Composer, version 2
  10. then finally log a successful execution. hooray \o/

don't forget to make the necessary adjustments in the script to reflect your server setup. commit and push this workflow to your GitHub repo, then re-run the job from GitHub Actions. you'll see the commit message as the workflow run title.

Image
screenshot of the "Deploy to Hostinger via SSH" under "Actions". there is a table at the center, with a list of two deployment jobs whose titles have been changed humorously with sci-fi references. to the left, several options are visible, with "Deploy to Hostinger via SSH" under "Actions".
Caption
it's important to honour the proper rituals.

the first line of your script (Deploy to Hostinger via SSH) is what you're looking for in this screen. underneath that line are all the deployment jobs. click on any workflow run from the list, then click on Re-run all jobs.

Image
screenshot of a deployment job with its title (humorously changed with a sci-fi reference) and the number 2 beside it. to the left, four links: "Summary", "Deploy", "Usage", and "Workflow file". at the center, information about the job: account, hash, branch, status ("Success"), and elapsed time. below, the YAML file name with "deploy" and a green circle with a dark gray tick. at the top right-hand corner, the "Re-run all jobs" button is highlited.

the first time you commit your script, it will trigger a deployment, so there will always be at least an item in this list. once that's finished, head back to Hostinger and check if the files were deployed correctly.

wrapping up

if you followed all the steps in this tutorial, your CI/CD pipeline should be working now. if you have any questions, don't hesitate to reach out to me. thanks for reading and until next time!


Originally published at https://linkedin.com on April 8, 2025.