PHPackages                             dennenboom/harvest - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [DevOps &amp; Deployment](/categories/devops)
4. /
5. dennenboom/harvest

ActiveLibrary[DevOps &amp; Deployment](/categories/devops)

dennenboom/harvest
==================

Simple deployment automation tool for Laravel applications

v2.0.0(4mo ago)0255MITPHPPHP ^8.1

Since May 23Pushed 3mo ago1 watchersCompare

[ Source](https://github.com/ben-dennenboom/harvest)[ Packagist](https://packagist.org/packages/dennenboom/harvest)[ RSS](/packages/dennenboom-harvest/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (3)Versions (3)Used By (0)

Harvest
=======

[](#harvest)

A simple deployment automation tool for Laravel applications, inspired by Laravel Envoy. Harvest helps you automate deployment scenarios by executing a series of commands on remote servers via SSH.

Features
--------

[](#features)

- Simple deployment automation
- SSH-based remote execution
- Optional confirmation prompts
- Variable placeholders for dynamic deployments
- Sudo password handling
- Shell context switching support
- SSH jump host (proxy) support
- Easy configuration
- Docker-friendly

Installation
------------

[](#installation)

Install via Composer:

```
composer require dennenboom/harvest
```

The package will auto-register itself via Laravel's package discovery.

Configuration
-------------

[](#configuration)

Publish the configuration file:

```
php artisan vendor:publish --tag=harvest-config
```

This will create a `config/harvest.php` file. Configure your deployment environments:

```
return [
    'deployments' => [
        'uat' => [
            // The SSH command used to connect to the server
            'ssh_command' => 'ssh user@host -p2121',

            // Prompt for confirmation before executing actions
            'ask_confirmation' => true,

            // Actions to execute on the remote server
            'actions' => [
                'cd /var/www/my-app',
                'git pull origin main',
                'composer install --no-dev --optimize-autoloader',
                'php artisan migrate --force',
                'php artisan config:cache',
            ],
        ],

        'production' => [
            'ssh_command' => 'ssh user@production-host',
            'ask_confirmation' => true,
            'actions' => [
                'cd /var/www/my-app',
                'git pull origin main',
                'composer install --no-dev --optimize-autoloader',
                'php artisan migrate --force',
            ],
        ],
    ],
];
```

SSH Setup
---------

[](#ssh-setup)

**Docker: Mount SSH keys**

```
# docker-compose.yml
services:
  app:
    volumes:
      - ~/.ssh:/root/.ssh:ro
```

Usage
-----

[](#usage)

Deploy to a specific environment:

```
php artisan harvest:deploy uat
```

Skip confirmation prompt:

```
php artisan harvest:deploy uat --no-confirm
```

Pass variables via command line:

```
php artisan harvest:deploy production --var=version=v1.57.3
```

Pass multiple variables:

```
php artisan harvest:deploy production --var=version=v1.57.3 --var=branch=main
```

SSH Authentication
------------------

[](#ssh-authentication)

Harvest executes SSH commands directly, so authentication is handled by your SSH configuration. This means:

- Your SSH keys should be set up and configured outside of Harvest
- Use `ssh-agent` to manage your keys
- Configure SSH aliases in your `~/.ssh/config` for easier management

Example SSH config (`~/.ssh/config`):

```
Host uat-server
    HostName uat.example.com
    User deployer
    Port 2121
    IdentityFile ~/.ssh/deploy_key

```

Then in your Harvest config:

```
'uat' => [
    'ssh_command' => 'ssh uat-server',
    // ...
],
```

Docker Considerations
---------------------

[](#docker-considerations)

If your Laravel application runs inside Docker containers, you have several options for SSH key management:

### Option 1: SSH Agent Forwarding (Recommended)

[](#option-1-ssh-agent-forwarding-recommended)

Mount your SSH agent socket into the container:

```
# docker-compose.yml
services:
  app:
    volumes:
      - $SSH_AUTH_SOCK:/ssh-agent
    environment:
      - SSH_AUTH_SOCK=/ssh-agent
```

Then run:

```
docker-compose exec app php artisan harvest:deploy uat
```

### Option 2: Mount SSH Keys as Volume

[](#option-2-mount-ssh-keys-as-volume)

Mount your SSH directory (ensure proper permissions):

```
# docker-compose.yml
services:
  app:
    volumes:
      - ~/.ssh:/root/.ssh:ro
```

**Warning**: Be careful with this approach and never commit SSH keys to your repository.

### Option 3: Run Harvest Outside Docker

[](#option-3-run-harvest-outside-docker)

Since Harvest only orchestrates SSH commands, you can run it from your host machine:

```
# On your host machine
php artisan harvest:deploy uat
```

### Option 4: Use Environment Variables for SSH Config

[](#option-4-use-environment-variables-for-ssh-config)

You can set SSH connection details via environment variables:

```
# .env (DO NOT COMMIT)
HARVEST_UAT_SSH=ssh user@host -p2121
```

Then in your config:

```
'uat' => [
    'ssh_command' => env('HARVEST_UAT_SSH', 'ssh user@host'),
    // ...
],
```

How It Works
------------

[](#how-it-works)

1. Harvest reads your deployment configuration from `config/harvest.php`
2. It connects to the remote server using the configured SSH command
3. Each action is executed sequentially on the remote server
4. If any action fails, deployment stops immediately
5. Success/failure status is reported back to you

Advanced Features
-----------------

[](#advanced-features)

### Variable Placeholders

[](#variable-placeholders)

Use dynamic variables in your deployment actions. Perfect for version tagging, branch selection, or any dynamic value.

**Configuration:**

```
'production' => [
    'ssh_command' => 'ssh deployer@prod.example.com',
    'ask_confirmation' => true,
    'variables' => [
        'version' => 'Enter version tag to deploy (e.g., v1.57.3)',
        'branch' => [
            'prompt' => 'Enter branch name',
            'default' => 'main',
        ],
    ],
    'actions' => [
        'cd /var/www/app',
        'git fetch --all --tags',
        'git checkout {version}',
        'composer install --no-dev --optimize-autoloader',
    ],
],
```

**Usage:**

```
# Will prompt for version
php artisan harvest:deploy production

# Pass version via command line
php artisan harvest:deploy production --var=version=v1.57.3
```

### Sudo Password Handling

[](#sudo-password-handling)

Harvest automatically detects when your deployment requires sudo password and prompts you securely.

**Auto-detection:** Harvest detects `sudo -S` or `sudo -s` commands automatically.

**Manual configuration:** Set `needs_sudo_password` to `true` to force password prompt.

```
'staging' => [
    'ssh_command' => 'ssh user@staging.example.com',
    'needs_sudo_password' => true,  // Force password prompt
    'actions' => [
        'sudo systemctl restart nginx',
        'sudo supervisorctl restart all',
    ],
],
```

### Shell Context Switching

[](#shell-context-switching)

Harvest intelligently handles shell switching commands like `sudo -u user -s /bin/bash`. When detected, all subsequent commands run in that user's context.

**Example:**

```
'staging' => [
    'ssh_command' => 'ssh -J proxy@jump.example.com user@target.example.com',
    'ask_confirmation' => true,
    'actions' => [
        'sudo -S -u apache -s /bin/bash',  // Switch to apache user
        'cd /srv/www/app',                 // Runs as apache
        'git pull origin dev',             // Runs as apache
        'composer install',                // Runs as apache
        'php artisan migrate --force',     // Runs as apache
    ],
],
```

When you run this deployment, Harvest will:

1. Prompt for sudo password (auto-detected from `sudo -S`)
2. Connect via SSH jump host (proxy)
3. Switch to apache user
4. Execute remaining commands in apache user context

Configuration Options
---------------------

[](#configuration-options)

### Per-Environment Settings

[](#per-environment-settings)

- `ssh_command` (required): The SSH command to connect to the server
- `ask_confirmation` (optional, default: `false`): Whether to prompt for confirmation before deployment
- `actions` (required): Array of commands to execute on the remote server
- `variables` (optional): Define variables for use in actions with `{varname}` placeholders
- `needs_sudo_password` (optional): Force sudo password prompt (auto-detected when using `sudo -S` or `sudo -s`)

Examples
--------

[](#examples)

### Simple Deployment

[](#simple-deployment)

```
'dev' => [
    'ssh_command' => 'ssh deployer@dev.example.com',
    'ask_confirmation' => false,
    'actions' => [
        'cd /var/www/app',
        'git pull',
        'composer install',
    ],
],
```

### Production with Confirmation

[](#production-with-confirmation)

```
'production' => [
    'ssh_command' => 'ssh deployer@prod.example.com',
    'ask_confirmation' => true,
    'actions' => [
        'cd /var/www/app',
        'git pull origin main',
        'composer install --no-dev --optimize-autoloader',
        'php artisan down',
        'php artisan migrate --force',
        'php artisan config:cache',
        'php artisan route:cache',
        'php artisan view:cache',
        'php artisan queue:restart',
        'php artisan up',
    ],
],
```

### Multiple Servers

[](#multiple-servers)

```
'staging' => [
    'ssh_command' => 'ssh deployer@staging.example.com',
    'actions' => ['cd /var/www/app', 'git pull'],
],
'production-web' => [
    'ssh_command' => 'ssh deployer@web1.example.com',
    'actions' => ['cd /var/www/app', 'git pull'],
],
'production-worker' => [
    'ssh_command' => 'ssh deployer@worker1.example.com',
    'actions' => ['cd /var/www/app', 'git pull', 'supervisorctl restart all'],
],
```

License
-------

[](#license)

MIT License. See [LICENSE](LICENSE) for details.

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance76

Regular maintenance activity

Popularity15

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~216 days

Total

2

Last Release

143d ago

Major Versions

v1.0.0 → v2.0.02025-12-26

### Community

Maintainers

![](https://www.gravatar.com/avatar/41297789aa5bcd259d68233a2438e2b3338e43b1b24b717f6d44fabfb955d7bc?d=identicon)[ben-dennenboom](/maintainers/ben-dennenboom)

---

Top Contributors

[![ayoubezzini](https://avatars.githubusercontent.com/u/105205174?v=4)](https://github.com/ayoubezzini "ayoubezzini (9 commits)")

### Embed Badge

![Health badge](/badges/dennenboom-harvest/health.svg)

```
[![Health](https://phpackages.com/badges/dennenboom-harvest/health.svg)](https://phpackages.com/packages/dennenboom-harvest)
```

###  Alternatives

[laravel/dusk

Laravel Dusk provides simple end-to-end testing and browser automation.

1.9k36.7M259](/packages/laravel-dusk)[sammyjo20/lasso

Lasso - Asset wrangling for Laravel made simple.

355347.9k](/packages/sammyjo20-lasso)[spatie/laravel-health

Monitor the health of a Laravel application

86910.0M83](/packages/spatie-laravel-health)[wnx/laravel-stats

Get insights about your Laravel Project

1.8k1.8M7](/packages/wnx-laravel-stats)[laravel-zero/framework

The Laravel Zero Framework.

3371.4M369](/packages/laravel-zero-framework)[spatie/laravel-export

Create a static site bundle from a Laravel app

646127.9k5](/packages/spatie-laravel-export)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
