如何在Laravel 5.5中动态设置SSH密钥?
Great question! Storing SSH keys in your database and using them dynamically without writing to disk is totally feasible—here are a couple of solid approaches to implement this in Laravel:
1. Use phpseclib (Recommended: No File I/O Required)
phpseclib is a pure-PHP SSH library that lets you pass in private key content directly as a string, no file path needed. This is perfect for your use case since it skips disk operations entirely.
First, install the package:
composer require phpseclib/phpseclib
Then, create a method or service class to fetch your server details and key from the database, then establish the connection:
use phpseclib3\Net\SSH2; use phpseclib3\Crypt\RSA; use App\Models\Server; // Adjust this to your actual Server model use Exception; // Fetch server and its stored private key from the database $server = Server::findOrFail($targetServerId); $privateKeyString = $server->ssh_private_key; // Make sure this includes the full key (-----BEGIN RSA PRIVATE KEY----- and footer) // Load the key from the string $privateKey = RSA::load($privateKeyString); // Initialize SSH connection $ssh = new SSH2($server->host); if (!$ssh->login($server->username, $privateKey)) { throw new Exception('Failed to authenticate with SSH key'); } // Run your commands $commandOutput = $ssh->exec('ls -la'); echo $commandOutput;
This approach has minimal overhead since it works directly with the key string from your database—no file writes, no disk delays.
2. Extend Laravel's Remote Component (With Memory-Based Temp Files)
If you prefer using Laravel's familiar SSH facade (note: the Remote component was moved out of core in Laravel 5.1, so you'll need the laravelcollective/remote package), you can use a memory-based temporary file to avoid disk I/O.
First, install the package:
composer require laravelcollective/remote
Then, implement the dynamic connection:
use Illuminate\Support\Facades\Config; use Collective\Remote\RemoteFacade as SSH; use App\Models\Server; // Fetch server data from DB $server = Server::findOrFail($targetServerId); $privateKeyString = $server->ssh_private_key; // Create a temp file in RAM (uses /dev/shm on Linux, which is a RAM filesystem) $tempKeyPath = '/dev/shm/ssh_key_' . uniqid(); file_put_contents($tempKeyPath, $privateKeyString); chmod($tempKeyPath, 0600); // SSH requires private keys to have strict 600 permissions // Dynamically add a new SSH connection config Config::set('remote.connections.' . $server->id, [ 'host' => $server->host, 'username' => $server->username, 'key' => $tempKeyPath, ]); // Execute commands using the dynamic connection SSH::connection($server->id)->run(['ls -la'], function($line) { echo $line . PHP_EOL; }); // Clean up the temp file immediately after use unlink($tempKeyPath);
The /dev/shm path ensures the temp file lives in RAM, so writes/reads are nearly instant with no disk overhead. For Windows environments, you can use sys_get_temp_dir() instead, though it won't be RAM-based—still better than persistent disk files.
Critical Extra Tip
Always encrypt your private keys in the database! Never store plain-text keys. Use Laravel's built-in encryption to secure them:
- Store:
Crypt::encryptString($rawPrivateKey) - Retrieve:
Crypt::decryptString($encryptedKeyFromDb)
This adds a critical layer of security if your database ever gets compromised.
内容的提问来源于stack exchange,提问作者Adarsh Sojitra

