Skip to content

Commit

Permalink
fix: if mux conn fails, still use it without mux + save priv key with…
Browse files Browse the repository at this point in the history
… better logic
  • Loading branch information
andrasbacsai committed Nov 22, 2024
1 parent 9dd982b commit 8215389
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 22 deletions.
34 changes: 16 additions & 18 deletions app/Helpers/SshMultiplexingHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,16 @@ public static function serverSshConfiguration(Server $server)
];
}

public static function ensureMultiplexedConnection(Server $server)
public static function ensureMultiplexedConnection(Server $server): bool
{
if (! self::isMultiplexingEnabled()) {
return;
return false;
}

$sshConfig = self::serverSshConfiguration($server);
$muxSocket = $sshConfig['muxFilename'];
$sshKeyLocation = $sshConfig['sshKeyLocation'];

self::validateSshKey($sshKeyLocation);
self::validateSshKey($server->privateKey);

$checkCommand = "ssh -O check -o ControlPath=$muxSocket ";
if (data_get($server, 'settings.is_cloudflare_tunnel')) {
Expand All @@ -41,16 +40,17 @@ public static function ensureMultiplexedConnection(Server $server)
$process = Process::run($checkCommand);

if ($process->exitCode() !== 0) {
self::establishNewMultiplexedConnection($server);
return self::establishNewMultiplexedConnection($server);
}

return true;
}

public static function establishNewMultiplexedConnection(Server $server)
public static function establishNewMultiplexedConnection(Server $server): bool
{
$sshConfig = self::serverSshConfiguration($server);
$sshKeyLocation = $sshConfig['sshKeyLocation'];
$muxSocket = $sshConfig['muxFilename'];

$connectionTimeout = config('constants.ssh.connection_timeout');
$serverInterval = config('constants.ssh.server_interval');
$muxPersistTime = config('constants.ssh.mux_persist_time');
Expand All @@ -60,15 +60,14 @@ public static function establishNewMultiplexedConnection(Server $server)
if (data_get($server, 'settings.is_cloudflare_tunnel')) {
$establishCommand .= ' -o ProxyCommand="cloudflared access ssh --hostname %h" ';
}

$establishCommand .= self::getCommonSshOptions($server, $sshKeyLocation, $connectionTimeout, $serverInterval);
$establishCommand .= "{$server->user}@{$server->ip}";

$establishProcess = Process::run($establishCommand);

if ($establishProcess->exitCode() !== 0) {
throw new \RuntimeException('Failed to establish multiplexed connection: '.$establishProcess->errorOutput());
return false;
}

return true;
}

public static function removeMuxFile(Server $server)
Expand Down Expand Up @@ -97,9 +96,8 @@ public static function generateScpCommand(Server $server, string $source, string
if ($server->isIpv6()) {
$scp_command .= '-6 ';
}
if (self::isMultiplexingEnabled()) {
if (self::isMultiplexingEnabled() && self::ensureMultiplexedConnection($server)) {
$scp_command .= "-o ControlMaster=auto -o ControlPath=$muxSocket -o ControlPersist={$muxPersistTime} ";
self::ensureMultiplexedConnection($server);
}

if (data_get($server, 'settings.is_cloudflare_tunnel')) {
Expand Down Expand Up @@ -127,9 +125,8 @@ public static function generateSshCommand(Server $server, string $command)

$ssh_command = "timeout $timeout ssh ";

if (self::isMultiplexingEnabled()) {
if (self::isMultiplexingEnabled() && self::ensureMultiplexedConnection($server)) {
$ssh_command .= "-o ControlMaster=auto -o ControlPath=$muxSocket -o ControlPersist={$muxPersistTime} ";
self::ensureMultiplexedConnection($server);
}

if (data_get($server, 'settings.is_cloudflare_tunnel')) {
Expand All @@ -154,13 +151,14 @@ private static function isMultiplexingEnabled(): bool
return config('constants.ssh.mux_enabled') && ! config('constants.coolify.is_windows_docker_desktop');
}

private static function validateSshKey(string $sshKeyLocation): void
private static function validateSshKey(PrivateKey $privateKey): void
{
$checkKeyCommand = "ls $sshKeyLocation 2>/dev/null";
$keyLocation = $privateKey->getKeyLocation();
$checkKeyCommand = "ls $keyLocation 2>/dev/null";
$keyCheckProcess = Process::run($checkKeyCommand);

if ($keyCheckProcess->exitCode() !== 0) {
throw new \RuntimeException("SSH key file not accessible: $sshKeyLocation");
$privateKey->storeInFileSystem();
}
}

Expand Down
4 changes: 0 additions & 4 deletions app/Models/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -1059,10 +1059,6 @@ public function validateConnection(bool $isManualCheck = true, bool $justCheckin
return ['uptime' => false, 'error' => 'Server skipped.'];
}
try {
// Make sure the private key is stored
if ($this->privateKey) {
$this->privateKey->storeInFileSystem();
}
instant_remote_process(['ls /'], $this);
if ($this->settings->is_reachable === false) {
$this->settings->is_reachable = true;
Expand Down

0 comments on commit 8215389

Please sign in to comment.