Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Remote Laravel Package

phanan/remote

Run Artisan commands on remote servers over SSH directly from your local Laravel app. Configure connections, then execute and inspect them as if they were local—handy for deployment, maintenance, and managing multiple environments. No extra tooling required.

View on GitHub
Deep Wiki
Context7

Getting Started

phanan/remote is a thin Laravel 5 wrapper around phpseclib that gives you a Remote facade for SFTP transfers and SSH command execution. It is deliberately small — one connection abstraction, a handful of file operations — so it fits best as a plumbing dependency inside deploy scripts, sync commands, and queue jobs rather than as a first-class filesystem driver.

Install it and wire it up:

composer require phanan/remote
php artisan vendor:publish --provider="Phanan\Remote\RemoteServiceProvider"

On Laravel 5.5+ the provider is auto-discovered. On 5.0–5.4 register Phanan\Remote\RemoteServiceProvider in config/app.php and add the Remote alias pointing at the package's facade class. Then edit the published config/remote.php with host, port, username, password (or key path), root directory, and timeout.

Look first at two files in vendor/phanan/remote: the facade (it lists every public method and its exact signature) and the main service class (it shows how phpseclib's SFTP and SSH2 objects are constructed and cached). Reading those two files takes five minutes and removes all guesswork about the API.

The canonical first use case: a php artisan remote:push command that uploads a locally built asset directory to a staging server.

Remote::connect();
Remote::put(base_path('public/build'), '/var/www/app/public/build');
Remote::disconnect();

Implementation Patterns

Treat it as a transport layer, not a filesystem. The natural pattern is to keep Laravel's Storage disk for local work, then push the finished artifact over the remote connection. Generate the file locally, verify it, then put() it. This keeps your code testable — you can fake the local disk and only the final transfer touches the network.

Centralize the connection lifecycle. Open and close explicitly around a batch of operations rather than relying on lazy connection:

Remote::connect();
try {
    foreach ($files as $local => $remote) {
        Remote::put($local, $remote);
    }
    Remote::run('cd /var/www/app && php artisan cache:clear');
} finally {
    Remote::disconnect();
}

This matters in queue workers, where the process outlives a single job and a stale handle will bite you on the next job.

Wrap it in a dedicated service class. Don't sprinkle Remote:: calls through controllers. A RemoteDeployer or RemoteSync class with push(), pull(), exists(), and run() methods gives you one place to swap in a fake for tests and one place to add retry logic.

Use SSH execution for post-transfer steps. The real value in day-to-day work is the combination: upload a release archive, then run tar -xzf and composer install --no-dev over SSH in the same session. That turns a two-step manual deploy into one command.

Pull remote artifacts for debugging. get() on /var/log/app/error.log or a remote storage directory into storage/app/remote/ is a genuinely useful debugging pattern when you have no shell access to the box. Schedule it as a command if you need periodic log collection.

Layer multiple named connections if the config supports it. If you deploy to staging and production, keep separate config entries and pass the connection name to connect(). Verify in the source whether the package supports named connections or a single global config — if it is single-connection, hold two config arrays in your own service class rather than mutating the package config at runtime.

Gotchas and Tips

The package is archived. No bug fixes, no PHP 8.x or Laravel 9+ compatibility work. Pin the version in composer.json, and if you are starting fresh, use Laravel's native SFTP filesystem driver or league/flysystem-sftp-v3 instead — you get the full Storage API, better error handling, and active maintenance. Choose phanan/remote only if you are already on Laravel 5 and need SSH command execution alongside transfers.

Config caching will silently ignore your edits. If you run php artisan config:cache in deployment, changes to config/remote.php won't take effect until you re-cache. This is the single most common "why isn't it connecting to the new host" cause.

Long-running processes hold stale connections. Queue workers and Octane-style runtimes keep the phpseclib handle alive across jobs. Always disconnect() in a finally block, or reconnect at the top of each job. Remote servers and firewalls will drop idle connections and the next call fails cryptically.

Path resolution depends on the configured root. A leading slash may mean "absolute on the server" or "relative to the configured root directory" depending on how the wrapper joins paths. Test with a known path and confirm with exists() before relying on it in a batch operation.

Errors are not always exceptions. Some methods return booleans, others may throw phpseclib exceptions. Wrap calls defensively and check return values rather than assuming an exception will surface. Log the failing path — phpseclib's own messages are terse.

Large files and timeouts. The default timeout in the config is likely too short for a multi-hundred-megabyte upload. Raise it, and consider chunking or using a tarball over SSH for anything substantial rather than moving many small files individually.

phpseclib version sensitivity. The package's composer constraint pins an older phpseclib. If another dependency wants a newer major version, you get a conflict. Check composer why phpseclib/phpseclib before adding anything else that does SSH.

Extension point if you need to fork. The service provider binds a single connection class; subclass it and rebind in your own provider to add retries, logging, or connection pooling. That is a cleaner path than patching vendor/.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings