DEV Community

Ali Sahin
Ali Sahin

Posted on

Deploy Laravel App to a Linux Server Using GitHub Actions

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:

  1. Open your terminal and run:
   ssh-keygen -t ed25519 -C "deploy-laravel-app-with-github-actions"
Enter fullscreen mode Exit fullscreen mode
  • Hit Enter to accept the default location.
  • When it asks for a passphrase, just press Enter again (we want this to be automatic).
  1. Find your keys:

    • Private key: ~/.ssh/id_ed25519
    • Public key: ~/.ssh/id_ed25519.pub
  2. Add the public key to your server so it trusts GitHub:

   ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your.server.ip
Enter fullscreen mode Exit fullscreen mode

Replace user and your.server.ip with your server’s SSH username and IP address.

  1. Copy the private key content so we can use it in GitHub Actions:
   cat ~/.ssh/id_ed25519
Enter fullscreen mode Exit fullscreen mode

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!"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
  • 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.
  • git fetch origin: Pulls the latest code from the remote repository.
  • git reset --hard origin/develop: Replaces local code with the latest from the develop 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 the GITHUB_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:

  1. Push any change to your develop branch.
  2. Go to your GitHub repo → Actions tab.
  3. 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)