I will walk you through setting up automated deployment for your Laravel application using GitHub Actions. We’ll cover everything from setting up your server to configuring GitHub Actions.

Prerequisites:

Before we begin, ensure you have:

Step 1: Generate SSH Keys

First, we need to generate SSH keys for secure communication between GitHub Actions and your server.

Note: Do not set a passphrase while generating the SSH key for automation purposes. Ensure the private key is stored securely as a GitHub secret to prevent unauthorized access.

# On your local machine
ssh-keygen -t rsa -b 4096 -C "[email protected]"

This will create:

  • Private key: ~/.ssh/id_rsa
  • Public key: ~/.ssh/id_rsa.pub

Copy the public key content (id_rsa.pub) to your server:

# On your server, add it to authorized_keys
nano ~/.ssh/authorized_keys

Step 2: Configure GitHub Secrets

Add the following secrets to your GitHub repository (Settings > Secrets and variables > Actions):

  1. SERVER_IP: Your server’s IP address
  2. SERVER_SSH_USER: SSH username (usually root or ubuntu)
  3. SERVER_SSH_KEY: The contents of your private key file (~/.ssh/id_rsa)
  4. SERVER_PATH: Your Laravel project path (e.g., /var/www/html)

Step 3: Create GitHub Actions Workflow

Create .github/workflows/deploy.yml in your repository with the deployment script.

name: Deploy to Server with Maintenance Mode

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:

    - name: Checkout
      uses: actions/checkout@v2

    - name: Remove Old Files
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SERVER_IP }}
        username: ${{ secrets.SERVER_SSH_USER }}
        key: ${{ secrets.SERVER_SSH_KEY }}
        script: |
          cd ${{ secrets.SERVER_PATH }}
          find . -mindepth 1 -not -name 'phpmyadmin' -not -name '.env' -not -name 'storage' -exec rm -rf {} +

    - name: Deploy to Server
      uses: easingthemes/[email protected]
      env:
        SSH_PRIVATE_KEY: ${{ secrets.SERVER_SSH_KEY }}
        REMOTE_HOST: ${{ secrets.SERVER_IP }}
        REMOTE_USER: ${{ secrets.SERVER_SSH_USER }}
        TARGET: ${{ secrets.SERVER_PATH }}
        EXCLUDE: "/storage"

    - name: Run Essential Commands
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SERVER_IP }}
        username: ${{ secrets.SERVER_SSH_USER }}
        key: ${{ secrets.SERVER_SSH_KEY }}
        script: |
          cd ${{ secrets.SERVER_PATH }}

          export COMPOSER_ALLOW_SUPERUSER=1; composer install --no-dev --optimize-autoloader

          php artisan config:cache
          php artisan migrate --force
          php artisan route:cache
          php artisan view:cache
          php artisan event:cache
          php artisan queue:restart

          npm ci
          npm run build

          touch /var/www/html/storage/logs/laravel.log

          chown -R www-data:www-data ${{ secrets.SERVER_PATH }}

          systemctl restart nginx
          systemctl restart php8.3-fpm

          php artisan optimize:clear

    - name: Verify Deployment
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SERVER_IP }}
        username: ${{ secrets.SERVER_SSH_USER }}
        key: ${{ secrets.SERVER_SSH_KEY }}
        script: |
          cd ${{ secrets.SERVER_PATH }}
          if php artisan --version; then
            echo "Deployment successful"
          else
            echo "Deployment failed"
            exit 1
          fi

Remember to replace placeholder values (your-domain.com, [email protected]) with your actual values.

If you found this article helpful, feel free to share it with others in the Laravel community. Happy coding!

Categorized in:

Laravel,

Tagged in: