spatie/laravel-remote
Run Laravel Artisan commands on remote servers over SSH. Configure one or more hosts (default host, user, port, path, optional private key) and execute tasks like cache clears via php artisan remote ..., with optional confirmation prompts.
Installation:
composer require spatie/laravel-remote
php artisan vendor:publish --tag="remote-config"
Publish the config file to customize remote server connections.
Define Remote Servers:
Edit config/remote.php to define your remote servers under the servers key:
'servers' => [
'production' => [
'host' => 'user@your-server.com',
'port' => 22,
'key' => '/path/to/private/key',
'options' => [
'-o', 'StrictHostKeyChecking=no',
],
],
],
First Use Case: Execute an Artisan command on a remote server:
php artisan remote:run production cache:clear
This runs cache:clear on the production server.
config/remote.php – Define and manage remote servers.remote:run – Execute a single command.remote:queue – Queue a command for later execution.remote:queue:run – Run queued commands.Direct Command Execution:
Use remote:run for immediate, one-off tasks:
php artisan remote:run production migrate
Queued Commands: Schedule commands for later execution (e.g., during off-peak hours):
php artisan remote:queue production optimize:clear
php artisan remote:queue:run production
Environment-Specific Workflows:
Define servers in remote.php with environment-specific configurations (e.g., staging, production):
'servers' => [
'staging' => [
'host' => 'user@staging.example.com',
'key' => storage_path('keys/staging_key'),
],
'production' => [
'host' => 'user@prod.example.com',
'key' => storage_path('keys/prod_key'),
],
],
Run commands dynamically:
php artisan remote:run staging deploy:prepare
Integration with Deployment Scripts:
Use remote:run in deployment pipelines (e.g., Laravel Forge, Deployer) to trigger post-deploy tasks:
php artisan remote:run production queue:restart
php artisan remote:run production supervisor:restart
Custom Artisan Commands:
Extend the package by creating custom commands that leverage Remote:
use Spatie\Remote\Remote;
class MyCustomCommand extends Command
{
protected $signature = 'my:remote-task {server}';
public function handle()
{
Remote::run($this->argument('server'), 'my:custom-command');
}
}
Zero-Downtime Deployments:
php artisan remote:queue production migrate --force
php artisan remote:queue production cache:clear
php artisan remote:queue:run production
Monitoring and Maintenance:
php artisan remote:queue production queue:prune --hours=1
Multi-Server Coordination:
php artisan remote:run production queue:restart
php artisan remote:run staging queue:restart
SSH Key Management:
storage/app/keys/ or a secrets manager).'key' => env('REMOTE_SSH_KEY_PATH'),
Error Handling:
Remote::run() in try-catch blocks to handle failures gracefully:
try {
Remote::run('production', 'my:command');
} catch (\Exception $e) {
Log::error("Remote command failed: {$e->getMessage()}");
}
Logging:
php artisan remote:run production --verbose migrate
Remote::run('production', 'my:command', function ($output) {
Log::info($output);
});
Environment Variables:
php artisan remote:run production my:command --env=production
Artisan Command Options:
php artisan remote:run production migrate --force --seed
SSH Key Permissions:
chmod 600 for private keys). Failing this will result in connection errors.StrictHostKeyChecking:
Host key verification failed, add -o StrictHostKeyChecking=no to the options array in the config. Use cautiously in production.Command Timeouts:
screen/tmux for persistent sessions:
'options' => [
'-o', 'ConnectTimeout=30',
'-o', 'ServerAliveInterval=60',
],
Command Output Buffering:
--verbose or callback functions to stream output in real-time:
Remote::run('production', 'my:command', function ($output) {
echo $output;
});
Dependency Conflicts:
Queued Command Order:
remote:queue:run --force to bypass order for critical tasks.SSH Debugging:
-vvv to the options array:
'options' => [
'-vvv',
],
Command Output:
php artisan remote:run production my:command > remote_output.log 2>&1
Dry Runs:
php artisan remote:test production
Logging:
APP_DEBUG=true) to log remote command interactions.Dynamic Server Configuration:
'servers' => [
'production' => [
'host' => env('REMOTE_PROD_HOST', 'default@example.com'),
],
],
Default Server:
'default_server' => 'production',
php artisan remote:run cache:clear
Key Paths:
'key' => '/home/user/.ssh/production_key',
Custom Remote Adapters:
RemoteAdapter.Pre/Post Command Hooks:
Remote facade or creating a decorator:
Remote::extend(function ($remote) {
$remote->before(function () {
Log::info('Running pre-command hooks');
});
return $remote;
});
Command Validation:
if (!Remote::serverExists('production')) {
throw new \Exception('Server not configured');
}
Parallel Execution:
parallel helper to run commands on multiple servers concurrently:
parallel([
'production' => fn() => Remote::run('production', 'queue:restart'),
'staging' => fn() => Remote::run('staging', 'queue:restart'),
]);
Webhooks for Queued Commands:
RemoteQueue class:
RemoteQueue::addListener('production', function ($result) {
How can I help you explore Laravel packages today?