Skip to content

Instantly share code, notes, and snippets.

@dominosaurs
Last active January 28, 2026 14:44
Show Gist options
  • Select an option

  • Save dominosaurs/cd35f20f65970d3f37ce5ef85a1cd284 to your computer and use it in GitHub Desktop.

Select an option

Save dominosaurs/cd35f20f65970d3f37ce5ef85a1cd284 to your computer and use it in GitHub Desktop.

My Laravel Envoy Deployment Script

This gist provides a minimal Laravel deployment setup using Composer as the single entry point, with Envoy treated as a setup-time dependency.

The deployment flow is intentionally simple: build the frontend locally, deploy only the final frontend assets, then update and optimize the Laravel backend on the production server.

This keeps the deployment model explicit, predictable, and infrastructure-light while remaining flexible enough for both local and automated deployments.

Usage

  • composer production:deploy builds the frontend locally and runs the full deployment pipeline

  • composer production:clear-cache clears and rebuilds laravel caches on the production server

Important

  • Envoy is an SSH automation tool, essentially a sugar-coated SSH client wrapper.
  • Envoy is never executed on the target server. All commands run from the local machine (or runner) and are executed remotely over SSH.
  • Ensure the machine running Envoy (local computer or CI runner) has SSH access explicitly allowed on the destination server.
  • This setup works equally well for CI/CD pipelines, as long as the runner has SSH credentials and network access to the server.
  • Please consult the official Laravel Envoy documentation first to avoid incorrect assumptions or unsafe usage.

Installation

1. Install Envoy

Envoy is required only during setup and execution of deployment commands on your local machine.

composer require --dev laravel/envoy

2. Configure Environment Variables

Add the required deployment variables to your .env file:

ENVOY_SSH_HOST=your-server-host
ENVOY_SSH_PORT=22
ENVOY_PROJECT_ROOT_PATH=/var/www/your-project

3. Composer Integration

Instead of running build and Envoy commands manually, Composer is used as the single interface for production operations:

{
  "scripts": {
    "production:clear-cache": "envoy run clear_cache",
    "production:deploy": [
      "npm run build",
      "envoy run deploy"
    ]
    
    // ....
  }
}

4. Create Envoy.blade.php

Create an Envoy.blade.php file at the root of your project and define the deployment workflow:

@setup
    include __DIR__.'/vendor/autoload.php';

    Dotenv\Dotenv::createImmutable(__DIR__)
        ->safeLoad();

    // Configuration
    $serverHost = $_ENV['ENVOY_SSH_HOST'];
    $serverPort = $_ENV['ENVOY_SSH_PORT'];
    $projectPath = $_ENV['ENVOY_PROJECT_ROOT_PATH'];

    if (in_array(null, [$serverHost, $serverPort, $projectPath])) {
        throw new Exception(
            'You must set ENVOY_SSH_HOST, ENVOY_SSH_PORT, and ENVOY_PROJECT_ROOT_PATH'
        );
    }

    $localBuildPath = 'public/build/dist.zip';
    $remoteTempPath = '~/tmp/dist.zip';
    $remoteBuildPath = $projectPath . '/public/build';
@endsetup

@servers([
    'production' => "$serverHost -p $serverPort",
    'localhost' => '127.0.0.1',
])

@story('deploy')
    upload_frontend_build
    deploy_frontend_assets
    update_backend_codebase
    install_dependencies
    optimize_application
    restart_queues
@endstory

@task('upload_frontend_build', ['on' => 'localhost'])
    scp -P {{ $serverPort }} {{ $localBuildPath }} {{ $serverHost }}:{{ $remoteTempPath }}
@endtask

@task('deploy_frontend_assets', ['on' => 'production'])
    rm -rf {{ $remoteBuildPath }}
    mkdir -p {{ $remoteBuildPath }}
    unzip -o {{ $remoteTempPath }} -d {{ $remoteBuildPath }}
    rm {{ $remoteTempPath }}
@endtask

@task('update_backend_codebase', ['on' => 'production'])
    cd {{ $projectPath }}
    git pull origin HEAD
@endtask

@task('install_dependencies', ['on' => 'production'])
    cd {{ $projectPath }}
    composer install --no-dev --optimize-autoloader
@endtask

@task('clear_cache', ['on' => 'production'])
    cd {{ $projectPath }}
    php artisan cache:clear
    php artisan optimize:clear
    php artisan optimize
@endtask

@task('optimize_application', ['on' => 'production'])
    cd {{ $projectPath }}
    php artisan optimize
@endtask

@task('restart_queues', ['on' => 'production'])
    cd {{ $projectPath }}
    php artisan queue:restart
@endtask
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment