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

Ssh Laravel Package

spatie/ssh

spatie/ssh is a lightweight PHP package for running commands over an SSH connection. Execute commands synchronously or asynchronously, run multiple commands, choose a custom port, and inspect results via Symfony's Process.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. spatie/ssh is a deliberately thin wrapper: it shells out to the host's ssh/scp binaries via Symfony Process and hands the Process object back to you. There is no PHP SSH protocol implementation, no ext-ssh2/libssh dependency, no daemon, and no service provider semantics beyond a facade. For a TPM this is the key architectural decision point: you inherit everything the local OpenSSH client gives you (~/.ssh/config conventions, known_hosts, jump hosts, agent auth, multiplexing) and you inherit everything the local OpenSSH client requires of you (binaries present, writable paths, correct POSIX shell availability on the target). It fits deployment runbooks, scheduled maintenance jobs, remote artisan invocation, and small-fleet orchestration from a Laravel app or CI runner. It does not fit interactive sessions, sustained high-volume transfers, or anything needing SFTP semantics, port forwarding, or structured protocol-level error handling.

Integration feasibility. composer require spatie/ssh, then Ssh::create('user', 'host')->execute('...'). A developer can be productive in under an hour. The real cost sits outside the package: SSH key material and its distribution, known_hosts management, host inventory, and command construction hygiene. Verify whether the facade alias is auto-discovered or must be registered manually, and confirm the transitive symfony/process constraint overlaps with the Symfony version your Laravel release pins.

Technical risk.

  • Command injection surface. Commands are strings concatenated into a shell invocation. There is no structured argument API. Any user-, tenant-, or config-derived value interpolated into a command is a live injection risk. Escaping discipline must be an enforced internal standard, not a code-review hope.
  • Credential handling. Password auth (added in 1.13.0) requires sshpass on the local host and passes the secret on a command line, where it is visible in process listings. Treat password auth as unsupported and mandate key-based auth.
  • Silent failure. The README explicitly states password auth "will silently fail" without sshpass. A tooling layer that can fail without throwing is a category of risk, not a bug. Every call site needs an isSuccessful() check plus output capture fed into logging.
  • Exit-code fidelity. Default command transport pipes into bash on the target; Windows targets historically reported success regardless of outcome until 1.13.2's onWindows(). Cross-platform fleets need explicit opt-in and verification.
  • Multi-command semantics. The array form of execute() is documented but its failure semantics (does command 2 run after command 1 fails?) are not stated. Must be validated in a spike before it is relied on for sequencing.
  • Supply chain. MIT, actively maintained, 13 minor releases, PHP 8.4 and Symfony 8 support already landed. Zero declared dependents is a double-edged signal: negligible transitive-conflict risk, but also little evidence of the package being exercised by downstream projects other than its own Pest suite.
  • Single-maintainer concentration. Spatie-authored, community PRs, no commercial SLA for this package. MIT means forkable, but plan for stewardship rather than assume it.

Key questions.

  1. Linux-only fleet, or are Windows targets in scope (forcing onWindows() and its recent, less-exercised code path)?
  2. Key-based auth only, and where do keys live on the app host — filesystem, secret manager, SSH agent socket?
  3. What is the fan-out and command volume per minute, and are we blocking a web request or dispatching to a queue?
  4. Do we need file transfer beyond scp semantics (rsync, resume, large directories)?
  5. Who owns known_hosts and jump-host configuration, and is disableStrictHostKeyChecking() banned by policy?
  6. Is this replacing Laravel Envoy (from which this code derives), raw exec('ssh ...'), or phpseclib?

Integration Approach

Stack fit. Composer-installable, Laravel-native ergonomics, no runtime services. It lives naturally inside queued jobs, artisan commands, and schedule:run. It is a poor fit for a synchronous HTTP path where a slow remote host becomes a slow user request. Container images must be updated to include openssh-client (and sshpass only if the risky path is ever enabled); slim PHP base images routinely omit both.

Migration path. From Envoy: near-identical mental model, since the Ssh class derives from Envoy's own code — porting runbooks is largely mechanical, but Envoy's @task/@story orchestration must be replaced with your own layer. From raw exec('ssh ...'): strictly better, since you gain Process output, exit codes, timeouts, and onOutput streaming. Away from DivineOmega/php-ssh-connection or phpseclib: not a drop-in; you lose in-process SFTP and structured error handling and gain external-binary dependency. To keep the exit door open, wrap the package behind an internal interface (e.g. RemoteHost::run(string $command): CommandResult) — this is cheap now and expensive later.

Compatibility. Confirm PHP floor and Symfony Process constraint against your Laravel version. SSH multiplexing requires a writable control-path directory that persists across invocations — acceptable on a stable VM, problematic in ephemeral containers where stale control sockets accumulate or the path disappears between jobs. IPv6 support and jump hosts are present but should be smoke-tested in your specific network topology.

Sequencing.

  1. Spike (1–2 days). Scratch host, key auth, verify array-command failure semantics, timeout behavior, and output streaming.
  2. Guardrails before features. Build the adapter interface, a command-escaping helper, a host inventory config, and a logging/audit decorator. Do not let call sites touch Ssh::create() directly.
  3. Add policy wrappers. Mandatory timeouts, success-check enforcement, retry policy for idempotent reads, and a hard block on password auth and disableStrictHostKeyChecking().
  4. Integrate one workflow end to end — preferably a scheduled read-only task — and measure latency and failure rate under real network conditions.
  5. CI harness. Stand up a disposable SSH container in the pipeline so integration tests exercise the real binary path, mirroring the package's own Pest approach.
  6. Expand scope to write operations and then deployment automation, with rollback runbooks defined per workflow.

Operational Impact

Maintenance. Small surface area (essentially one class) means low maintenance, but you own the wrapper, the escaping rules, and the host inventory. Pin with caret constraints and review the changelog on every bump — recent history is dominated by Symfony-version churn and exit-code fixes rather than feature creep. Budget a recurring half-day per quarter for dependency hygiene; near-zero for the package, most of it for the Symfony constraint.

Support. Community OSS with no SLA. Security reports go to [email protected]; nothing else is contractual. Assign a named internal owner and a documented fork procedure. Do not place this on a path where an unfixed upstream bug blocks revenue.

Scaling. Each execute() is a blocking process spawn plus a TCP handshake — roughly linear cost per host. Enabling multiplexing changes that calculus meaningfully for repeated calls to the same host and should be the default once the control-path lifetime problem is solved per worker. For fan-out beyond a handful of hosts, use executeAsync() plus wait() with a bounded concurrency, or better, one queued job per host so Laravel's queue concurrency and retry semantics apply. Large outputs buffer in memory inside Process — stream via onOutput and cap retention rather than getOutput() on verbose commands.

Failure modes to design for.

  • Missing sshpass/openssh-client → failure without exception; add a startup health check.
  • Host key mismatch or rotation → hard connection failure; own a known_hosts refresh runbook.
  • Network partition or hung remote command → timeout is the only circuit breaker; set it on every call, not just the risky ones.
  • Partial execution of multi-command arrays → remote state left half-applied; insist on idempotent, re-runnable commands and explicit compensation steps.
  • Stale multiplexing control sockets → intermittent connection errors that look like network flakiness; scope control paths per worker and clear them on deploy.
  • Windows targets reporting false success → verify exit-code behavior if any Windows host enters scope.
  • Secrets leaking via process arguments if password auth is ever used → treat as a policy violation, not a config option.

Ramp-up. One to two days for a mid-level Laravel developer to be productive; one to two weeks to build and validate the guardrails (escaping, inventory, audit logging, retry and timeout policy, CI harness). The adoption cost is not learning the API — it is accepting that a shell-out tool transfers all operational responsibility for connectivity, credentials, and command safety onto your team. For internal ops tooling at modest scale, that trade is favorable and reversible. For a customer-facing or high-blast-radius path, gate it behind the adapter interface and a documented exit to phpseclib or an agent-based configuration management system.

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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator