SSHKit & Remote Execution
Relevant source files
The following files were used as context for generating this wiki page:
Kamal leverages SSHKit as its core engine for executing commands across remote servers. It serves as Layer 0 in the application architecture, providing the infrastructure for remote task orchestration, connection pooling, and parallel execution. Kamal extends and patches SSHKit to tailor its behavior for container-based deployments, ensuring robustness during multi-host operations.
Sources: CLAUDE.md:34-40, README.md:1-5
Architecture and Integration
The remote execution system is integrated into Kamal through the Kamal::Commander and Kamal::Cli::Base classes. The Commander acts as a singleton that manages target resolution and configures SSHKit global settings, while Cli::Base includes the SSHKit::DSL to provide command execution methods like on and execute to all CLI subcommands.
The diagram shows how Kamal's CLI components interact with the orchestration and execution layers to drive remote commands.
Sources: lib/kamal/commander.rb:1-20, lib/kamal/cli/base.rb:1-10, CLAUDE.md:34-40
Configuration and Connection Management
SSHKit configuration is handled lazily by the Kamal::Commander using values derived from the Kamal::Configuration object. This includes setting up connection pooling, concurrency limits, and SSH-specific options like users, ports, and proxy jumps.
SSH Options
Kamal supports a wide range of SSH configurations to accommodate different infrastructure setups, including jump proxies and identity management.
| Configuration Key | Type | Description |
|---|---|---|
user | String | Remote SSH user (defaults to root) |
port | Integer | SSH port (defaults to 22) |
proxy | String/Object | Jump host or ProxyCommand configuration |
pool_idle_timeout | Integer | Seconds to keep idle connections alive in the pool |
max_concurrent_starts | Integer | Max number of concurrent connection attempts |
Sources: lib/kamal/commander.rb:108-118, lib/kamal/configuration.rb:250-265, test/configuration/ssh_test.rb:22-50
Connection Lifecycle
Before any remote execution occurs, Kamal ensures a connection is established and potentially runs a pre-connect hook. The Commander tracks the connection state via the connected attribute.
This sequence illustrates the connection gatekeeping performed before executing remote blocks.
Sources: lib/kamal/cli/base.rb:229-239, lib/kamal/commander.rb:7-15
SSHKit Extensions and Patches
Kamal prepends custom modules to SSHKit runners to modify default behaviors that are suboptimal for its deployment model. These patches are located in lib/kamal/sshkit_with_ext.rb.
Parallel Execution (CompleteAll)
The standard SSHKit parallel runner aborts all remaining tasks if a single host fails. Kamal patches SSHKit::Runner::Parallel with a CompleteAll module. This ensures that an execution block attempts to run on every target host regardless of individual failures, which is critical for maintaining consistency across a fleet.
Group Execution (NoTrailingWait)
Kamal patches SSHKit::Runner::Group to remove the trailing wait interval after the final group of hosts has finished. This optimizes deployment speed, especially when rolling through small groups of servers.
Sources: lib/kamal/sshkit_with_ext.rb:1-20, test/sshkit_patch_drift_test.rb:1-15
Execution Primitives
Remote commands are typically constructed using the Kamal::Commands::Base primitives and executed via the on scope.
Command Execution Flow
- Target Selection: The
Commanderfilters hosts based on roles or specific CLI flags (--hosts,--roles). - Command Building: Logic in
Kamal::Commands::*builds an array of shell tokens. - Execution Scope: The CLI uses
on(hosts) { execute(...) }. - Logging: SSHKit output is formatted and broadcasted via
Kamal::Output::FormatterandActiveSupport::BroadcastLogger.
Sources: lib/kamal/commander.rb:120-134, lib/kamal/commands/base.rb:5-25, lib/kamal/cli/base.rb:229-231
SSH Command construction
def run_over_ssh(*command, host:)
"ssh#{ssh_config_args}#{ssh_proxy_args}#{ssh_keys_args} -t #{config.ssh.user}@#{host} -p #{config.ssh.port} '#{command.join(" ").gsub("'", "'\\\\''")}'"
end
Sources: lib/kamal/commands/base.rb:21-23
Summary
The SSHKit integration in Kamal provides a robust, parallelized execution layer that manages remote lifecycle events. By extending the base runners, Kamal ensures that deployments are resilient to single-host failures and optimized for speed, while maintaining flexible configuration for complex SSH environments.
Sources: lib/kamal/sshkit_with_ext.rb, lib/kamal/commander.rb, CLAUDE.md