Fix: Onboarding fails if SSH server uses other port than 22 and other onboarding improvements
This commit is contained in:
Andras Bacsai
2024-09-11 10:22:32 +02:00
committed by GitHub
3 changed files with 216 additions and 141 deletions

View File

@@ -73,6 +73,8 @@ class Index extends Component
}
$this->privateKeyName = generate_random_name();
$this->remoteServerName = generate_random_name();
$this->remoteServerPort = $this->remoteServerPort;
$this->remoteServerUser = $this->remoteServerUser;
if (isDev()) {
$this->privateKey = '-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
@@ -154,6 +156,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
$this->servers = Server::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get();
if ($this->servers->count() > 0) {
$this->selectedExistingServer = $this->servers->first()->id;
$this->updateServerDetails();
$this->currentState = 'select-existing-server';
return;
@@ -173,9 +176,18 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
}
$this->selectedExistingPrivateKey = $this->createdServer->privateKey->id;
$this->serverPublicKey = $this->createdServer->privateKey->publicKey();
$this->updateServerDetails();
$this->currentState = 'validate-server';
}
private function updateServerDetails()
{
if ($this->createdServer) {
$this->remoteServerPort = $this->createdServer->port;
$this->remoteServerUser = $this->createdServer->user;
}
}
public function getProxyType()
{
// Set Default Proxy Type
@@ -235,11 +247,12 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
public function saveServer()
{
$this->validate([
'remoteServerName' => 'required',
'remoteServerHost' => 'required',
'remoteServerName' => 'required|string',
'remoteServerHost' => 'required|string',
'remoteServerPort' => 'required|integer',
'remoteServerUser' => 'required',
'remoteServerUser' => 'required|string',
]);
$this->privateKey = formatPrivateKey($this->privateKey);
$foundServer = Server::whereIp($this->remoteServerHost)->first();
if ($foundServer) {
@@ -269,7 +282,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
public function validateServer()
{
try {
config()->set('coolify.mux_enabled', false);
config()->set('coolify.mux_enabled', true);
// EC2 does not have `uptime` command, lol
instant_remote_process(['ls /'], $this->createdServer, true);
@@ -277,9 +290,13 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
$this->createdServer->settings()->update([
'is_reachable' => true,
]);
$this->serverReachable = true;
} catch (\Throwable $e) {
$this->serverReachable = false;
$this->createdServer->delete();
$this->createdServer->settings()->update([
'is_reachable' => false,
]);
return handleError(error: $e, livewire: $this);
}
@@ -296,6 +313,9 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
]);
$this->getProxyType();
} catch (\Throwable $e) {
$this->createdServer->settings()->update([
'is_usable' => false,
]);
return handleError(error: $e, livewire: $this);
}
}
@@ -349,6 +369,21 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
);
}
public function saveAndValidateServer()
{
$this->validate([
'remoteServerPort' => 'required|integer|min:1|max:65535',
'remoteServerUser' => 'required|string',
]);
$this->createdServer->update([
'port' => $this->remoteServerPort,
'user' => $this->remoteServerUser,
'timezone' => 'UTC',
]);
$this->validateServer();
}
private function createNewPrivateKey()
{
$this->privateKeyName = generate_random_name();

View File

@@ -112,6 +112,16 @@ class Server extends BaseModel
'proxy',
];
protected $fillable = [
'name',
'ip',
'port',
'user',
'description',
'private_key_id',
'team_id',
];
protected $guarded = [];
public static function isReachable()

View File

@@ -1,16 +1,14 @@
@php use App\Enums\ProxyTypes; @endphp
<x-slot:title>
Onboarding | Coolify
</x-slot>
<section class="flex flex-col h-full lg:items-center lg:justify-center">
<div
class="flex flex-col items-center justify-center p-10 mx-2 mt-10 bg-white border rounded-lg shadow lg:p-20 dark:bg-transparent dark:border-none max-w-7xl ">
</x-slot>
<section class="flex flex-col h-full lg:items-center lg:justify-center">
<div class="flex flex-col items-center justify-center p-10 mx-2 mt-10 bg-white border rounded-lg shadow lg:p-20 dark:bg-transparent dark:border-none max-w-7xl ">
@if ($currentState === 'welcome')
<h1 class="text-3xl font-bold lg:text-5xl">Welcome to Coolify</h1>
<div class="py-6 text-center lg:text-xl">Let me help you set up the basics.</div>
<div class="flex justify-center ">
<x-forms.button class="justify-center w-64 box-boarding"
wire:click="$set('currentState','explanation')">Get
<x-forms.button class="justify-center w-64 box-boarding" wire:click="$set('currentState','explanation')">Get
Started
</x-forms.button>
</div>
@@ -28,12 +26,15 @@
<x-highlighted text="Self-hosting with superpowers!" /></span>
</x-slot:question>
<x-slot:explanation>
<p><x-highlighted text="Task automation:" /> You don't need to manage your servers anymore.
<p>
<x-highlighted text="Task automation:" /> You don't need to manage your servers anymore.
Coolify does
it for you.</p>
<p><x-highlighted text="No vendor lock-in:" /> All configurations are stored on your servers, so
<p>
<x-highlighted text="No vendor lock-in:" /> All configurations are stored on your servers, so
everything works without a connection to Coolify (except integrations and automations).</p>
<p><x-highlighted text="Monitoring:" />You can get notified on your favourite platforms
<p>
<x-highlighted text="Monitoring:" />You can get notified on your favourite platforms
(Discord,
Telegram, Email, etc.) when something goes wrong, or an action is needed from your side.</p>
</x-slot:explanation>
@@ -45,41 +46,64 @@
@elseif ($currentState === 'select-server-type')
<x-boarding-step title="Server">
<x-slot:question>
Do you want to deploy your resources to your <x-highlighted text="Localhost" />
or to a <x-highlighted text="Remote Server" />?
Do you want to deploy your resources to your
<x-highlighted text="Localhost" />
or to a
<x-highlighted text="Remote Server" />?
</x-slot:question>
<x-slot:actions>
<x-forms.button class="justify-center w-64 box-boarding" wire:target="setServerType('localhost')"
wire:click="setServerType('localhost')">Localhost
<x-forms.button class="justify-center w-64 box-boarding" wire:target="setServerType('localhost')" wire:click="setServerType('localhost')">Localhost
</x-forms.button>
<x-forms.button class="justify-center w-64 box-boarding " wire:target="setServerType('remote')"
wire:click="setServerType('remote')">Remote Server
<x-forms.button class="justify-center w-64 box-boarding " wire:target="setServerType('remote')" wire:click="setServerType('remote')">Remote Server
</x-forms.button>
@if (!$serverReachable)
Localhost is not reachable with the following public key.
<br /> <br />
Please make sure you have the correct public key in your ~/.ssh/authorized_keys file for
user or skip the boarding process and add a new private key manually to Coolify and to the
server.
<br />
Check this <a target="_blank" class="underline"
href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a> for further
help.
<x-forms.input readonly id="serverPublicKey"></x-forms.input>
<x-forms.button class="lg:w-64 box-boarding" wire:target="setServerType('localhost')"
wire:click="setServerType('localhost')">Check again
<div class="mt-6 p-4 bg-red-100 dark:bg-red-950 rounded-lg text-gray-800 dark:text-gray-200">
<h2 class="text-lg font-bold mb-2">Server is not reachable</h2>
<p class="mb-4">Please check the connection details below and correct them if they are incorrect.</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<x-forms.input placeholder="Default is 22" label="Port" id="remoteServerPort" wire:model="remoteServerPort" :value="$remoteServerPort" />
<div>
<x-forms.input placeholder="Default is root" label="User" id="remoteServerUser" wire:model="remoteServerUser" :value="$remoteServerUser" />
<p class="text-xs mt-1">
Non-root user is experimental:
<a class="font-bold underline" target="_blank" href="https://coolify.io/docs/knowledge-base/server/non-root-user">docs</a>
</p>
</div>
</div>
<div class="mb-4">
<p class="mb-2">If the connection details are correct, please ensure:</p>
<ul class="list-disc list-inside">
<li>The correct public key is in your <code class="bg-red-200 dark:bg-red-900 px-1 rounded">~/.ssh/authorized_keys</code> file for the specified user</li>
<li>Or skip the boarding process and manually add a new private key to Coolify and the server</li>
</ul>
</div>
<p class="mb-4">
For more help, check this <a target="_blank" class="underline font-semibold" href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a>.
</p>
<x-forms.input readonly id="serverPublicKey" class="mb-4" label="Current Public Key"></x-forms.input>
<x-forms.button class="w-full md:w-auto box-boarding" wire:click="saveAndValidateServer">
Check again
</x-forms.button>
</div>
@endif
</x-slot:actions>
<x-slot:explanation>
<p>Servers are the main building blocks, as they will host your applications, databases,
services, called resources. Any CPU intensive process will use the server's CPU where you
are deploying your resources.</p>
<p><x-highlighted text="Localhost" /> is the server where Coolify is running on. It is not
<p>
<x-highlighted text="Localhost" /> is the server where Coolify is running on. It is not
recommended to use one server
for everything.</p>
<p><x-highlighted text="A remote server" /> is a server reachable through SSH. It can be hosted
<p>
<x-highlighted text="A remote server" /> is a server reachable through SSH. It can be hosted
at home, or from any cloud
provider.</p>
</x-slot:explanation>
@@ -90,11 +114,9 @@
Do you have your own SSH Private Key?
</x-slot:question>
<x-slot:actions>
<x-forms.button class="justify-center lg:w-64 box-boarding" wire:target="setPrivateKey('own')"
wire:click="setPrivateKey('own')">Yes
<x-forms.button class="justify-center lg:w-64 box-boarding" wire:target="setPrivateKey('own')" wire:click="setPrivateKey('own')">Yes
</x-forms.button>
<x-forms.button class="justify-center lg:w-64 box-boarding" wire:target="setPrivateKey('create')"
wire:click="setPrivateKey('create')">No (create one for me)
<x-forms.button class="justify-center lg:w-64 box-boarding" wire:target="setPrivateKey('create')" wire:click="setPrivateKey('create')">No (create one for me)
</x-forms.button>
@if (count($privateKeys) > 0)
<form wire:submit='selectExistingPrivateKey' class="flex flex-col w-full gap-4 lg:pr-10">
@@ -125,11 +147,7 @@
<x-slot:actions>
<div class="flex flex-col gap-4">
<div>
<x-forms.button class="justify-center w-64 box-boarding" wire:click="createNewServer">No
(create
one
for
me)
<x-forms.button class="justify-center w-64 box-boarding" wire:click="createNewServer">No (create one for me)
</x-forms.button>
</div>
<div>
@@ -145,20 +163,39 @@
</div>
</div>
@if (!$serverReachable)
This server is not reachable with the following public key.
<br /> <br />
Please make sure you have the correct public key in your ~/.ssh/authorized_keys file for
user or skip the boarding process and add a new private key manually to Coolify and to the
server.
<br />
Check this <a target="_blank" class="underline"
href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a> for further
help.
<x-forms.input readonly id="serverPublicKey"></x-forms.input>
<x-forms.button class="w-64 box-boarding" wire:target="validateServer"
wire:click="validateServer">Check
again
<div class="mt-6 p-4 bg-red-100 dark:bg-red-950 rounded-lg text-gray-800 dark:text-gray-200">
<h2 class="text-lg font-bold mb-2">Server is not reachable</h2>
<p class="mb-4">Please check the connection details below and correct them if they are incorrect.</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<x-forms.input placeholder="Default is 22" label="Port" id="remoteServerPort" wire:model="remoteServerPort" :value="$remoteServerPort" />
<div>
<x-forms.input placeholder="Default is root" label="User" id="remoteServerUser" wire:model="remoteServerUser" :value="$remoteServerUser" />
<p class="text-xs mt-1">
Non-root user is experimental:
<a class="font-bold underline" target="_blank" href="https://coolify.io/docs/knowledge-base/server/non-root-user">docs</a>
</p>
</div>
</div>
<div class="mb-4">
<p class="mb-2">If the connection details are correct, please ensure:</p>
<ul class="list-disc list-inside">
<li>The correct public key is in your <code class="bg-red-200 dark:bg-red-900 px-1 rounded">~/.ssh/authorized_keys</code> file for the specified user</li>
<li>Or skip the boarding process and manually add a new private key to Coolify and the server</li>
</ul>
</div>
<p class="mb-4">
For more help, check this <a target="_blank" class="underline font-semibold" href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a>.
</p>
<x-forms.input readonly id="serverPublicKey" class="mb-4" label="Current Public Key"></x-forms.input>
<x-forms.button class="w-full md:w-auto box-boarding" wire:click="saveAndValidateServer">
Check again
</x-forms.button>
</div>
@endif
</x-slot:actions>
<x-slot:explanation>
@@ -176,12 +213,9 @@
</x-slot:question>
<x-slot:actions>
<form wire:submit='savePrivateKey' class="flex flex-col w-full gap-4 lg:pr-10">
<x-forms.input required placeholder="Choose a name for your Private Key. Could be anything."
label="Name" id="privateKeyName" />
<x-forms.input placeholder="Description, so others will know more about this."
label="Description" id="privateKeyDescription" />
<x-forms.textarea required placeholder="-----BEGIN OPENSSH PRIVATE KEY-----" label="Private Key"
id="privateKey" />
<x-forms.input required placeholder="Choose a name for your Private Key. Could be anything." label="Name" id="privateKeyName" />
<x-forms.input placeholder="Description, so others will know more about this." label="Description" id="privateKeyDescription" />
<x-forms.textarea required placeholder="-----BEGIN OPENSSH PRIVATE KEY-----" label="Private Key" id="privateKey" />
@if ($privateKeyType === 'create')
<x-forms.textarea rows="7" readonly label="Public Key" id="publicKey" />
<span class="font-bold dark:text-warning">ACTION REQUIRED: Copy the 'Public Key' to your
@@ -208,28 +242,27 @@
<x-slot:actions>
<form wire:submit='saveServer' class="flex flex-col w-full gap-4 lg:pr-10">
<div class="flex flex-col gap-2 lg:flex-row">
<x-forms.input required placeholder="Choose a name for your Server. Could be anything."
label="Name" id="remoteServerName" />
<x-forms.input placeholder="Description, so others will know more about this."
label="Description" id="remoteServerDescription" />
<x-forms.input required placeholder="Choose a name for your Server. Could be anything." label="Name" id="remoteServerName" wire:model="remoteServerName" />
<x-forms.input placeholder="Description, so others will know more about this." label="Description" id="remoteServerDescription" wire:model="remoteServerDescription" />
</div>
<div class="flex flex-col gap-2 lg:flex-row ">
<x-forms.input required placeholder="127.0.0.1" label="IP Address" id="remoteServerHost" />
<x-forms.input required placeholder="Port number of your server. Default is 22."
label="Port" id="remoteServerPort" />
<x-forms.input required placeholder="127.0.0.1" label="IP Address" id="remoteServerHost" wire:model="remoteServerHost" />
</div>
<div x-data="{ showAdvanced: false }" class="flex flex-col gap-2">
<button @click="showAdvanced = !showAdvanced" type="button" class="text-left text-sm text-gray-600 dark:text-gray-300 hover:underline">
Advanced Settings
</button>
<div x-show="showAdvanced" class="flex flex-col gap-2 lg:flex-row">
<x-forms.input placeholder="Port number of your server. Default is 22." label="Port" id="remoteServerPort" wire:model="remoteServerPort" />
<div class="w-full">
<x-forms.input required placeholder="User to connect to your server. Default is root."
label="User" id="remoteServerUser" />
<div class="text-xs dark:text-warning text-coollabs ">Non-root user is experimental: <a
class="font-bold underline" target="_blank"
href="https://coolify.io/docs/knowledge-base/server/non-root-user">docs</a>.
<x-forms.input placeholder="Default is root." label="User" id="remoteServerUser" wire:model="remoteServerUser" />
<div class="text-xs text-gray-600 dark:text-gray-300">Non-root user is experimental: <a class="font-bold underline" target="_blank" href="https://coolify.io/docs/knowledge-base/server/non-root-user">docs</a>.
</div>
</div>
</div>
</div>
<div class="lg:w-64">
<x-forms.checkbox
helper="If you are using Cloudflare Tunnels, enable this. It will proxy all ssh requests to your server through Cloudflare.<br><span class='dark:text-warning'>Coolify does not install/setup Cloudflare (cloudflared) on your server.</span>"
id="isCloudflareTunnel" label="Cloudflare Tunnel" />
<x-forms.checkbox helper="If you are using Cloudflare Tunnels, enable this. It will proxy all ssh requests to your server through Cloudflare.<br><span class='dark:text-warning'>Coolify does not install/setup Cloudflare (cloudflared) on your server.</span>" id="isCloudflareTunnel" label="Cloudflare Tunnel" wire:model="isCloudflareTunnel" />
</div>
<x-forms.button type="submit">Continue</x-forms.button>
</form>
@@ -247,8 +280,7 @@
<x-slot:content>
<livewire:server.validate-and-install :server="$this->createdServer" />
</x-slot:content>
<x-forms.button @click="slideOverOpen=true" class="w-full font-bold box-boarding lg:w-96"
wire:click.prevent='installServer' isHighlighted>
<x-forms.button @click="slideOverOpen=true" class="w-full font-bold box-boarding lg:w-96" wire:click.prevent='installServer' isHighlighted>
Let's do it!
</x-forms.button>
</x-slide-over>
@@ -257,8 +289,7 @@
<p>This will install the latest Docker Engine on your server, configure a few things to be able
to run optimal.<br><br>Minimum Docker Engine version is: 22<br><br>To manually install
Docker
Engine, check <a target="_blank" class="underline dark:text-warning"
href="https://docs.docker.com/engine/install/#server">this
Engine, check <a target="_blank" class="underline dark:text-warning" href="https://docs.docker.com/engine/install/#server">this
documentation</a>.</p>
</x-slot:explanation>
</x-boarding-step>
@@ -321,8 +352,7 @@
</div>
<x-modal-input title="How can we help?">
<x-slot:content>
<div class="w-full text-center cursor-pointer hover:underline dark:hover:text-white"
title="Send us feedback or get help!">
<div class="w-full text-center cursor-pointer hover:underline dark:hover:text-white" title="Send us feedback or get help!">
Feedback
</div>
</x-slot:content>
@@ -330,4 +360,4 @@
</x-modal-input>
</div>
</div>
</section>
</section>