Skip to main content
Back to Articles
LaravelDecember 11, 20248 min read

From Code to Production: A Guide to Automating Laravel Deployments with GitHub Actions

Learn how to build a fully automated CI/CD pipeline for Laravel using GitHub Actions, covering SSH key setup, workflow configuration, testing, and deployment to production servers.

Deploying Laravel Applications from GitHub to Your Server

We can automate Laravel deployments with a CI/CD pipeline powered by GitHub Actions. This eliminates manual uploads and SSH sessions -- tests run, assets build, and code deploys automatically on every push to main.

What is GitHub Actions?

GitHub Actions allows us to define automated workflows in a repository that respond to events like pushes or pull requests. We can use it to:

  • Automate Tests: Run the Laravel test suite on every PR or push.
  • Standardize Deployments: Execute the same deploy steps each time.
  • Boost Velocity: Ship code faster without manual intervention.

How the Pipeline Runs

The workflow file in .github/workflows/deploy.yml listens for pushes to main. On each push:

  • GitHub detects the push event.
  • Runs the defined steps: checkout, tests, build, and deploy.
  • Logs output and status for each step are available in the Actions tab.

Prerequisites

  • A Laravel application hosted in a GitHub repository.
  • A remote server (Ubuntu recommended) with SSH access.
  • PHP, Composer, and a web server (Nginx or Apache) installed on the server.

Setting Up SSH Keys

We need a deploy key so GitHub Actions can connect to our server securely.

ssh-keygen -t ed25519 -C "you@example.com"

Add the public key to the server's authorized_keys:

cat id_ed25519.pub | ssh deploy@your-server "cat >> ~/.ssh/authorized_keys"

In GitHub, navigate to Settings > Secrets & variables > Actions and create:

  • SSH_PRIVATE_KEY -- the private key contents
  • SSH_KNOWN_HOSTS -- output of ssh-keyscan your-server
  • SSH_USER -- e.g. deploy
  • SSH_HOST -- the domain or IP address

Creating the CI/CD Workflow

Create .github/workflows/deploy.yml:

name: Deploy Laravel

on:
  push:
    branches: [ "main" ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.1'
          extensions: mbstring, mysql, intl, bcmath

      - name: Install dependencies
        run: composer install --no-dev --optimize-autoloader

      - name: Run tests
        run: php artisan test

      - name: Start SSH agent
        uses: webfactory/ssh-agent@v0.5.4
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Add known hosts
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts

      - name: Deploy
        run: |
          rsync -avz --delete --exclude=".git" -e "ssh -o StrictHostKeyChecking=no" ./ \
            ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/var/www/your-project
          ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'EOF'
            cd /var/www/your-project
            composer install --no-dev --optimize-autoloader
            php artisan migrate --force
            php artisan config:cache
            php artisan route:cache
            php artisan view:cache
          EOF

Monitoring & Logs

  • Go to Actions in the GitHub repository.
  • Select the latest workflow run.
  • Expand steps to view logs and status.

Initial Server Setup

  • Ensure .env has correct production values.
  • Run php artisan key:generate if needed.
  • Set writable permissions for storage and bootstrap/cache.

Troubleshooting

  • GitHub Logs: Pinpoint step failures in the Actions tab.
  • Laravel Logs: Check storage/logs/laravel.log on the server.
  • Permissions: Verify directory permissions for the deploy user.

Enhancements

  • Slack Notifications: Add a Slack webhook step to receive deployment alerts.
  • Staging Branch: Create a separate workflow for a staging branch that deploys to a test server.
  • Database Seeding: Include php artisan db:seed for staging environments.
  • Zero-Downtime Deploys: Use tools like Envoyer or a symlink-based strategy.

By following this guide, we have a robust, automated deployment pipeline that ensures every push to main is tested, built, and deployed without manual effort.

Need help with this?

Our team handles this kind of work daily. Let us take care of your infrastructure.