diff --git a/app/Livewire/Boarding/Index.php b/app/Livewire/Boarding/Index.php
index 430470fa0..ac2b9213b 100644
--- a/app/Livewire/Boarding/Index.php
+++ b/app/Livewire/Boarding/Index.php
@@ -16,14 +16,18 @@ class Index extends Component
{
protected $listeners = ['refreshBoardingIndex' => 'validateServer'];
+ #[\Livewire\Attributes\Url(as: 'step', history: true)]
public string $currentState = 'welcome';
+ #[\Livewire\Attributes\Url(keep: true)]
public ?string $selectedServerType = null;
public ?Collection $privateKeys = null;
+ #[\Livewire\Attributes\Url(keep: true)]
public ?int $selectedExistingPrivateKey = null;
+ #[\Livewire\Attributes\Url(keep: true)]
public ?string $privateKeyType = null;
public ?string $privateKey = null;
@@ -38,6 +42,7 @@ class Index extends Component
public ?Collection $servers = null;
+ #[\Livewire\Attributes\Url(keep: true)]
public ?int $selectedExistingServer = null;
public ?string $remoteServerName = null;
@@ -58,6 +63,7 @@ class Index extends Component
public Collection $projects;
+ #[\Livewire\Attributes\Url(keep: true)]
public ?int $selectedProject = null;
public ?Project $createdProject = null;
@@ -79,17 +85,68 @@ public function mount()
$this->minDockerVersion = str(config('constants.docker.minimum_required_version'))->before('.');
$this->privateKeyName = generate_random_name();
$this->remoteServerName = generate_random_name();
- if (isDev()) {
- $this->privateKey = '-----BEGIN OPENSSH PRIVATE KEY-----
-b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
-QyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevAAAAJi/QySHv0Mk
-hwAAAAtzc2gtZWQyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevA
-AAAECBQw4jg1WRT2IGHMncCiZhURCts2s24HoDS0thHnnRKVuGmoeGq/pojrsyP1pszcNV
-uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
------END OPENSSH PRIVATE KEY-----';
- $this->privateKeyDescription = 'Created by Coolify';
- $this->remoteServerDescription = 'Created by Coolify';
- $this->remoteServerHost = 'coolify-testing-host';
+
+ // Initialize collections to avoid null errors
+ if ($this->privateKeys === null) {
+ $this->privateKeys = collect();
+ }
+ if ($this->servers === null) {
+ $this->servers = collect();
+ }
+ if (! isset($this->projects)) {
+ $this->projects = collect();
+ }
+
+ // Restore state when coming from URL with query params
+ if ($this->selectedServerType === 'localhost' && $this->selectedExistingServer === 0) {
+ $this->createdServer = Server::find(0);
+ if ($this->createdServer) {
+ $this->serverPublicKey = $this->createdServer->privateKey->getPublicKey();
+ }
+ }
+
+ if ($this->selectedServerType === 'remote') {
+ if ($this->privateKeys->isEmpty()) {
+ $this->privateKeys = PrivateKey::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get();
+ }
+ if ($this->servers->isEmpty()) {
+ $this->servers = Server::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get();
+ }
+
+ if ($this->selectedExistingServer) {
+ $this->createdServer = Server::find($this->selectedExistingServer);
+ if ($this->createdServer) {
+ $this->serverPublicKey = $this->createdServer->privateKey->getPublicKey();
+ $this->updateServerDetails();
+ }
+ }
+
+ if ($this->selectedExistingPrivateKey) {
+ $this->createdPrivateKey = PrivateKey::where('team_id', currentTeam()->id)
+ ->where('id', $this->selectedExistingPrivateKey)
+ ->first();
+ if ($this->createdPrivateKey) {
+ $this->privateKey = $this->createdPrivateKey->private_key;
+ $this->publicKey = $this->createdPrivateKey->getPublicKey();
+ }
+ }
+
+ // Auto-regenerate key pair for "Generate with Coolify" mode on page refresh
+ if ($this->privateKeyType === 'create' && empty($this->privateKey)) {
+ $this->createNewPrivateKey();
+ }
+ }
+
+ if ($this->selectedProject) {
+ $this->createdProject = Project::find($this->selectedProject);
+ if (! $this->createdProject) {
+ $this->projects = Project::ownedByCurrentTeam(['name'])->get();
+ }
+ }
+
+ // Load projects when on create-project state (for page refresh)
+ if ($this->currentState === 'create-project' && $this->projects->isEmpty()) {
+ $this->projects = Project::ownedByCurrentTeam(['name'])->get();
}
}
@@ -129,41 +186,16 @@ public function setServerType(string $type)
return $this->validateServer('localhost');
} elseif ($this->selectedServerType === 'remote') {
- if (isDev()) {
- $this->privateKeys = PrivateKey::ownedByCurrentTeam(['name'])->get();
- } else {
- $this->privateKeys = PrivateKey::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get();
- }
+ $this->privateKeys = PrivateKey::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get();
+ // Auto-select first key if available for better UX
if ($this->privateKeys->count() > 0) {
$this->selectedExistingPrivateKey = $this->privateKeys->first()->id;
}
- $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;
- }
+ // Onboarding always creates new servers, skip existing server selection
$this->currentState = 'private-key';
}
}
- public function selectExistingServer()
- {
- $this->createdServer = Server::find($this->selectedExistingServer);
- if (! $this->createdServer) {
- $this->dispatch('error', 'Server is not found.');
- $this->currentState = 'private-key';
-
- return;
- }
- $this->selectedExistingPrivateKey = $this->createdServer->privateKey->id;
- $this->serverPublicKey = $this->createdServer->privateKey->getPublicKey();
- $this->updateServerDetails();
- $this->currentState = 'validate-server';
- }
-
private function updateServerDetails()
{
if ($this->createdServer) {
@@ -181,7 +213,7 @@ public function getProxyType()
public function selectExistingPrivateKey()
{
if (is_null($this->selectedExistingPrivateKey)) {
- $this->restartBoarding();
+ $this->dispatch('error', 'Please select a private key.');
return;
}
@@ -202,6 +234,9 @@ public function setPrivateKey(string $type)
$this->privateKeyType = $type;
if ($type === 'create') {
$this->createNewPrivateKey();
+ } else {
+ $this->privateKey = null;
+ $this->publicKey = null;
}
$this->currentState = 'create-private-key';
}
diff --git a/resources/views/components/boarding-progress.blade.php b/resources/views/components/boarding-progress.blade.php
new file mode 100644
index 000000000..dec34abac
--- /dev/null
+++ b/resources/views/components/boarding-progress.blade.php
@@ -0,0 +1,47 @@
+@props(['currentStep' => 1, 'totalSteps' => 3])
+
+
+
+ @for ($i = 1; $i <= $totalSteps; $i++)
+
+
+
+ @if ($i < $currentStep)
+
+
+
+ @else
+
+ {{ $i }}
+
+ @endif
+
+
+ @if ($i === 1)
+ Server
+ @elseif ($i === 2)
+ Connection
+ @elseif ($i === 3)
+ Complete
+ @endif
+
+
+ @if ($i < $totalSteps)
+
+
+ @endif
+
+ @endfor
+
+
diff --git a/resources/views/components/boarding-step.blade.php b/resources/views/components/boarding-step.blade.php
index d963e55f0..716987baf 100644
--- a/resources/views/components/boarding-step.blade.php
+++ b/resources/views/components/boarding-step.blade.php
@@ -1,25 +1,29 @@
-
-
-
{{ $title }}
-
+
+
+
+
{{ $title }}
@isset($question)
-
+
{{ $question }}
-
+
@endisset
+
+ @if ($actions)
+
+ {{ $actions }}
+
+ @endif
- @if ($actions)
-
- {{ $actions }}
+
+ @isset($explanation)
+
+
+ Technical Details
+
+
+ {{ $explanation }}
+
- @endif
+ @endisset
- @isset($explanation)
-
-
Explanation
-
- {{ $explanation }}
-
-
- @endisset
diff --git a/resources/views/layouts/boarding.blade.php b/resources/views/layouts/boarding.blade.php
index 67c1cc998..e0b5f49a3 100644
--- a/resources/views/layouts/boarding.blade.php
+++ b/resources/views/layouts/boarding.blade.php
@@ -1,6 +1,6 @@
@extends('layouts.base')
@section('body')
-
+
{{ $slot }}
@parent
diff --git a/resources/views/livewire/boarding/index.blade.php b/resources/views/livewire/boarding/index.blade.php
index 68b328b30..faee9883b 100644
--- a/resources/views/livewire/boarding/index.blade.php
+++ b/resources/views/livewire/boarding/index.blade.php
@@ -1,400 +1,737 @@
@php use App\Enums\ProxyTypes; @endphp
Onboarding | Coolify
-
-
-
- @if ($currentState === 'welcome')
-
Welcome to Coolify
-
Let me help you set up the basics.
-
- Get
- Started
-
-
- @elseif ($currentState === 'explanation')
-
-
- Coolify is an all-in-one application to automate tasks on your servers, deploy applications with
- Git
- integrations, deploy databases and services, monitor these resources with notifications and
- alerts
- without vendor lock-in.
- Coolify Home .
-
-
-
-
-
-
- You don't need to manage your servers anymore.
- Coolify does
- it for you.
-
-
- All configurations are stored on your servers, so
- everything works without a connection to Coolify (except integrations and automations).
-
-
- You can get notified on your favourite platforms
- (Discord,
- Telegram, Email, etc.) when something goes wrong, or an action is needed from your side.
-
-
-
- Next
-
-
-
- @elseif ($currentState === 'select-server-type')
-
-
- Do you want to deploy your resources to your
-
- or to a
- ?
-
-
- Localhost
-
-
- Remote Server
-
-
- @if (!$serverReachable)
-
-
Server is not reachable
-
Please check the connection details below and correct them if they are
- incorrect.
-
-
-
-
-
-
- Non-root user is experimental:
- docs
-
-
-
-
-
-
If the connection details are correct, please ensure:
-
- The correct public key is in your ~/.ssh/authorized_keys
- file for the specified user
- Or skip the boarding process and manually add a new private key to Coolify and
- the server
-
-
-
-
- For more help, check this documentation .
-
-
-
-
-
- Check Again
-
-
- @endif
-
-
- 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.
-
- is the server where Coolify is running on. It is not
- recommended to use one server
- for everything.
-
-
- is a server reachable through SSH. It can be hosted
- at home, or from any cloud
- provider.
-
-
-
- @elseif ($currentState === 'private-key')
-
-
- Do you have your own SSH Private Key?
-
-
- Yes
-
- No (create one for me)
-
- @if (count($privateKeys) > 0)
-
- @endif
-
-
- SSH Keys are used to connect to a remote server through a secure shell, called SSH.
- You can use your own ssh private key, or you can let Coolify to create one for you.
- In both ways, you need to add the public version of your ssh private key to the remote
- server's
- ~/.ssh/authorized_keys file.
-
-
-
- @elseif ($currentState === 'select-existing-server')
-
-
- There are already servers available for your Team. Do you want to use one of them?
-
-
-
-
- No
- (create one for me)
-
-
-
-
-
+
+
+
+ @if ($currentState === 'welcome')
+
+
+
Welcome to Coolify
+
+ Connect your first server and start deploying in minutes
+
- @if (!$serverReachable)
-
-
Server is not reachable
-
Please check the connection details below and correct them if they are
- incorrect.
-
-
+
+
+ What You'll Set Up
+
+
+
+
-
-
- Non-root user is experimental:
- docs
-
+
Server Connection
+
Connect via SSH to deploy your resources
+
-
-
-
If the connection details are correct, please ensure:
-
- The correct public key is in your ~/.ssh/authorized_keys
- file for the specified user
- Or skip the boarding process and manually add a new private key to Coolify and
- the server
-
-
-
-
- For more help, check this documentation .
-
-
-
-
-
- Check again
-
-
- @endif
-
-
- Private Keys are used to connect to a remote server through a secure shell, called SSH.
- You can use your own private key, or you can let Coolify to create one for you.
- In both ways, you need to add the public version of your private key to the remote server's
- ~/.ssh/authorized_keys file.
-
-
-
- @elseif ($currentState === 'create-private-key')
-
-
- Please let me know your key details.
-
-
-
-
-
- Private Keys are used to connect to a remote server through a secure shell, called SSH.
- You can use your own private key, or you can let Coolify to create one for you.
- In both ways, you need to add the public version of your private key to the remote server's
- ~/.ssh/authorized_keys file.
-
-
-
- @elseif ($currentState === 'create-server')
-
-
- Please let me know your server details.
-
-
-