In this guide, you’ll learn how to build a simple, secure, and automated deployment pipeline for your Laravel application using GitHub Actions and SSH. This setup will automatically deploy your app to a Linux server every time you push updates to a specific Git branch.
Whether you’re just getting started with CI/CD or want to streamline your team’s workflow, this step-by-step guide is designed to walk you through the process clearly and confidently.
What You’ll Need
Before we begin, make sure you have:
- A Linux server you can SSH into.
- Your Laravel app code hosted on GitHub.
- Some Docker experience (since our deploy script uses Docker).
Step 1: Create an SSH Key to Let GitHub Talk to Your Server
Before we jump into creating SSH keys, let’s quickly understand what they are.
What Are Public and Private Keys?
SSH uses a key pair for secure communication:
- The public key is like a lock. You place it on the server you want to access.
- The private key is like the key that opens that lock. You keep this on your local machine (or in GitHub Secret vault).
Only someone with the private key can connect to the server where the public key is installed. This allows passwordless and secure logins, which is perfect for automation.
- The public key (
.pub
file) goes on your server in~/.ssh/authorized_keys
. - The private key is added to your GitHub repository's secrets as
SSH_KEY
.
Now, let’s create that key pair.
Imagine your server is your home. You want GitHub to have a spare key so it can enter without ringing the bell (or typing a password).
Here’s how to give GitHub that key:
- Open your terminal and run:
ssh-keygen -t ed25519 -C "deploy-laravel-app-with-github-actions"
- Hit Enter to accept the default location.
- When it asks for a passphrase, just press Enter again (we want this to be automatic).
-
Find your keys:
- Private key:
~/.ssh/id_ed25519
- Public key:
~/.ssh/id_ed25519.pub
- Private key:
Add the public key to your server so it trusts GitHub:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your.server.ip
Replace user and your.server.ip with your server’s SSH username and IP address.
- Copy the private key content so we can use it in GitHub Actions:
cat ~/.ssh/id_ed25519
Step 2: Add Secrets in GitHub
GitHub needs to know how to log in to your server. So let’s give it all the details safely using Secrets.
In your GitHub repo, go to Settings > Secrets > Actions, then add:
Name | What to Put There |
---|---|
HOST |
Your server's IP address or domain name |
USERNAME |
The SSH username (like ubuntu ) |
SSH_KEY |
Paste your private key here (from last step) |
SSH_PORT |
Usually 22 unless you changed it |
APP_PATH |
The full path to your app on the server |
Step 3: Write a Simple Deploy Script
This is a short script that tells your server what to do when it's time to deploy. Save it as .scripts/deploy.sh
in your project:
#!/bin/bash
set -e
echo "🚀 Starting deployment..."
cd ..
# Put app in maintenance mode
(docker-compose exec app php artisan down) || true
# Install PHP dependencies
docker-compose exec app composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader
# Clear and rebuild cache
docker-compose exec app php artisan clear-compiled
docker-compose exec app php artisan optimize:clear
# Run migrations
docker-compose exec app php artisan migrate --force
# Bring app back online
docker-compose exec app php artisan up
echo "✅ Deployment finished!"
Note: Change app
to whatever your Laravel container is named if it’s different.
Step 4: Let GitHub Deploy Automatically
Now for the magic. Create a file in your project at:
.github/workflows/deploy.yml
Paste this in:
name: Deploy to Server
on:
push:
branches:
- develop
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: SSH into server and deploy
uses: appleboy/ssh-action@v1.2.0
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
script: |
set -e
cd ${{ secrets.APP_PATH }}
git config --local url."https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/".insteadOf "https://github.com/"
git fetch origin
git reset --hard origin/develop
git config --local --remove-section url."https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/"
bash .scripts/deploy.sh
Here’s what’s happening:
- GitHub waits for a push to the
develop
branch. - It connects to your server.
- It pulls the latest code.
- It runs your
deploy.sh
script.
Breaking Down the script
Section
Let’s go over what’s happening in the script
part of the SSH step:
script: |
set -e
cd ${{ secrets.APP_PATH }}
git config --local url."https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/".insteadOf "https://github.com/"
git fetch origin
git reset --hard origin/develop
git config --local --remove-section url."https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/"
bash .scripts/deploy.sh
-
set -e
: Stops the script immediately if any command fails. -
cd ${{ secrets.APP_PATH }}
: Navigates to your Laravel app folder on the server. - The
git config
commands:- Temporarily override GitHub URLs to use the built-in
GITHUB_TOKEN
so your server can fetch private repos. - This is useful when your Laravel project is private or depends on private packages.
- Temporarily override GitHub URLs to use the built-in
-
git fetch origin
: Pulls the latest code from the remote repository. -
git reset --hard origin/develop
: Replaces local code with the latest from thedevelop
branch. (helpful if you made some changes on the server, like a quick fix or debugging, so you can reset it to the latest code) -
git config --local --remove-section
: Cleans up the temporary GitHub auth config. (as theGITHUB_TOKEN
is only useed for this deployment, and will expires after the action runs) -
bash .scripts/deploy.sh
: Finally runs your deployment script.
Note: You don’t need to manually add GITHUB_TOKEN
in your GitHub Secrets — it’s automatically provided by GitHub Actions at runtime.
Step 5: Test It!
Now try it out:
- Push any change to your
develop
branch. - Go to your GitHub repo → Actions tab.
- Watch the magic happen! If it works, your Laravel app gets updated on the server instantly.
You now have a secure, automated CI/CD pipeline using GitHub Actions to deploy your Laravel app to a remote Linux server using SSH.
In the next article, we'll take things a step further by adding features like code quality checks, automated testing, and send notifications to enhance your CI/CD pipeline. Stay tuned!
Top comments (0)