Compare commits

...

16 Commits

Author SHA1 Message Date
Andras Bacsai
b7acf99cde Merge pull request #1238 from coollabsio/next
Fixes
2023-09-18 15:31:54 +02:00
Andras Bacsai
21d52d7846 oops 2023-09-18 15:23:23 +02:00
Andras Bacsai
ab5929cc69 typo 2023-09-18 15:20:48 +02:00
Andras Bacsai
1452cdf5ad fix: send internal notifications of email errors 2023-09-18 15:19:27 +02:00
Andras Bacsai
3eb1a1f48c debug with ray 2023-09-18 15:06:37 +02:00
Andras Bacsai
5f7a97c31f debug job 2023-09-18 15:04:50 +02:00
Andras Bacsai
9cba0a6df3 fix: boarding again 2023-09-18 14:41:31 +02:00
Andras Bacsai
af57b2aa73 pricing change 2023-09-18 13:42:35 +02:00
Andras Bacsai
b9b9582601 version++ 2023-09-18 13:14:48 +02:00
Andras Bacsai
c8ba98b93d fix: try to use old docker-compose 2023-09-18 13:14:05 +02:00
Andras Bacsai
a50e1e2f0c Merge pull request #1237 from coollabsio/next
Lots of fixes
2023-09-18 13:06:43 +02:00
Andras Bacsai
1093294f06 minimum toaster 2023-09-18 13:06:02 +02:00
Andras Bacsai
c023be2348 fix: improve localhost boarding process 2023-09-18 13:01:01 +02:00
Andras Bacsai
deece51e83 fix: stop/start UI on apps and dbs 2023-09-18 12:38:11 +02:00
Andras Bacsai
e2ab569244 version++ 2023-09-18 12:30:49 +02:00
Andras Bacsai
93b202bde4 fix: convert startProxy to action 2023-09-18 12:29:50 +02:00
27 changed files with 330 additions and 409 deletions

View File

@@ -16,9 +16,12 @@ class CheckConfiguration
"cat $proxy_path/docker-compose.yml", "cat $proxy_path/docker-compose.yml",
], $server, false); ], $server, false);
if ($reset || is_null($proxy_configuration)) { if ($reset || !$proxy_configuration || is_null($proxy_configuration)) {
$proxy_configuration = Str::of(generate_default_proxy_configuration($server))->trim()->value; $proxy_configuration = Str::of(generate_default_proxy_configuration($server))->trim()->value;
} }
if (!$proxy_configuration || is_null($proxy_configuration)) {
throw new \Exception("Could not generate proxy configuration");
}
return $proxy_configuration; return $proxy_configuration;
} }
} }

View File

@@ -6,11 +6,13 @@ use App\Enums\ProxyStatus;
use App\Enums\ProxyTypes; use App\Enums\ProxyTypes;
use App\Models\Server; use App\Models\Server;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Lorisleiva\Actions\Concerns\AsAction;
use Spatie\Activitylog\Models\Activity; use Spatie\Activitylog\Models\Activity;
class StartProxy class StartProxy
{ {
public function __invoke(Server $server, bool $async = true): Activity|string use AsAction;
public function handle(Server $server, bool $async = true): Activity|string
{ {
$proxyType = data_get($server,'proxy.type'); $proxyType = data_get($server,'proxy.type');
if ($proxyType === 'none') { if ($proxyType === 'none') {
@@ -49,9 +51,9 @@ class StartProxy
"cd $proxy_path", "cd $proxy_path",
"echo '####### Creating Docker Compose file...'", "echo '####### Creating Docker Compose file...'",
"echo '####### Pulling docker image...'", "echo '####### Pulling docker image...'",
'docker compose pull', 'docker compose pull || docker-compose pull',
"echo '####### Stopping existing coolify-proxy...'", "echo '####### Stopping existing coolify-proxy...'",
"docker compose down -v --remove-orphans > /dev/null 2>&1 || true", "docker compose down -v --remove-orphans > /dev/null 2>&1 || docker-compose down -v --remove-orphans > /dev/null 2>&1 || true",
"command -v fuser >/dev/null || command -v lsof >/dev/null || echo '####### Could not kill existing processes listening on port 80 & 443. Please stop the process holding these ports...'", "command -v fuser >/dev/null || command -v lsof >/dev/null || echo '####### Could not kill existing processes listening on port 80 & 443. Please stop the process holding these ports...'",
"command -v lsof >/dev/null && lsof -nt -i:80 | xargs -r kill -9 || true", "command -v lsof >/dev/null && lsof -nt -i:80 | xargs -r kill -9 || true",
"command -v lsof >/dev/null && lsof -nt -i:443 | xargs -r kill -9 || true", "command -v lsof >/dev/null && lsof -nt -i:443 | xargs -r kill -9 || true",
@@ -61,7 +63,7 @@ class StartProxy
"systemctl disable apache2 > /dev/null 2>&1 || true", "systemctl disable apache2 > /dev/null 2>&1 || true",
"systemctl disable apache > /dev/null 2>&1 || true", "systemctl disable apache > /dev/null 2>&1 || true",
"echo '####### Starting coolify-proxy...'", "echo '####### Starting coolify-proxy...'",
'docker compose up -d --remove-orphans', 'docker compose up -d --remove-orphans || docker-compose up -d --remove-orphans',
"echo '####### Proxy installed successfully...'" "echo '####### Proxy installed successfully...'"
]; ];
if (!$async) { if (!$async) {

View File

@@ -7,7 +7,7 @@ use App\Models\StandaloneDocker;
class InstallDocker class InstallDocker
{ {
public function __invoke(Server $server, bool $instant = false) public function __invoke(Server $server)
{ {
$dockerVersion = '24.0'; $dockerVersion = '24.0';
$config = base64_encode('{ $config = base64_encode('{
@@ -55,9 +55,6 @@ class InstallDocker
"echo '####### Done!'" "echo '####### Done!'"
]; ];
} }
if ($instant) {
return instant_remote_process($command, $server);
}
return remote_process($command, $server); return remote_process($command, $server);
} }
} }

View File

@@ -17,8 +17,11 @@ class CoolifyTaskArgs extends Data
public string $type, public string $type,
public ?string $type_uuid = null, public ?string $type_uuid = null,
public ?Model $model = null, public ?Model $model = null,
public string $status = ProcessStatus::QUEUED->value, public ?string $status = null ,
public bool $ignore_errors = false, public bool $ignore_errors = false,
) { ) {
if(is_null($status)){
$this->status = ProcessStatus::QUEUED->value;
}
} }
} }

View File

@@ -9,7 +9,6 @@ use App\Models\Server;
use App\Models\Team; use App\Models\Team;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Livewire\Component; use Livewire\Component;
use Visus\Cuid2\Cuid2;
class Index extends Component class Index extends Component
{ {
@@ -39,6 +38,10 @@ class Index extends Component
public ?Project $createdProject = null; public ?Project $createdProject = null;
public bool $dockerInstallationStarted = false; public bool $dockerInstallationStarted = false;
public string $serverPublicKey;
public bool $serverReachable = true;
public function mount() public function mount()
{ {
$this->privateKeyName = generate_random_name(); $this->privateKeyName = generate_random_name();
@@ -66,14 +69,6 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
public function restartBoarding() public function restartBoarding()
{ {
// if ($this->selectedServerType !== 'localhost') {
// if ($this->createdServer) {
// $this->createdServer->delete();
// }
// if ($this->createdPrivateKey) {
// $this->createdPrivateKey->delete();
// }
// }
return redirect()->route('boarding'); return redirect()->route('boarding');
} }
public function skipBoarding() public function skipBoarding()
@@ -94,6 +89,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
if (!$this->createdServer) { if (!$this->createdServer) {
return $this->emit('error', 'Localhost server is not found. Something went wrong during installation. Please try to reinstall or contact support.'); return $this->emit('error', 'Localhost server is not found. Something went wrong during installation. Please try to reinstall or contact support.');
} }
$this->serverPublicKey = $this->createdServer->privateKey->publicKey();
return $this->validateServer('localhost'); return $this->validateServer('localhost');
} elseif ($this->selectedServerType === 'remote') { } elseif ($this->selectedServerType === 'remote') {
$this->privateKeys = PrivateKey::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get(); $this->privateKeys = PrivateKey::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get();
@@ -118,6 +114,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
return; return;
} }
$this->selectedExistingPrivateKey = $this->createdServer->privateKey->id; $this->selectedExistingPrivateKey = $this->createdServer->privateKey->id;
$this->serverPublicKey = $this->createdServer->privateKey->publicKey();
$this->validateServer(); $this->validateServer();
} }
public function getProxyType() public function getProxyType()
@@ -188,7 +185,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
$this->createdServer->save(); $this->createdServer->save();
$this->validateServer(); $this->validateServer();
} }
public function validateServer(?string $type = null) public function validateServer()
{ {
try { try {
$customErrorMessage = "Server is not reachable:"; $customErrorMessage = "Server is not reachable:";
@@ -196,18 +193,27 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
instant_remote_process(['uptime'], $this->createdServer, true); instant_remote_process(['uptime'], $this->createdServer, true);
$this->createdServer->settings->update([ $this->createdServer->settings()->update([
'is_reachable' => true, 'is_reachable' => true,
]); ]);
} catch (\Throwable $e) {
$this->serverReachable = false;
return handleError(error: $e, customErrorMessage: $customErrorMessage, livewire: $this);
}
try {
$dockerVersion = instant_remote_process(["docker version|head -2|grep -i version| awk '{print $2}'"], $this->createdServer, true); $dockerVersion = instant_remote_process(["docker version|head -2|grep -i version| awk '{print $2}'"], $this->createdServer, true);
$dockerVersion = checkMinimumDockerEngineVersion($dockerVersion); $dockerVersion = checkMinimumDockerEngineVersion($dockerVersion);
if (is_null($dockerVersion)) { if (is_null($dockerVersion)) {
$this->currentState = 'install-docker'; $this->currentState = 'install-docker';
throw new \Exception('Docker version is not supported or not installed.'); throw new \Exception('Docker version is not supported or not installed.');
} }
$this->dockerInstalledOrSkipped(); $this->createdServer->settings()->update([
'is_usable' => true,
]);
$this->getProxyType();
} catch (\Throwable $e) { } catch (\Throwable $e) {
$this->dockerInstallationStarted = false;
return handleError(error: $e, customErrorMessage: $customErrorMessage, livewire: $this); return handleError(error: $e, customErrorMessage: $customErrorMessage, livewire: $this);
} }
} }
@@ -219,10 +225,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
} }
public function dockerInstalledOrSkipped() public function dockerInstalledOrSkipped()
{ {
$this->createdServer->settings->update([ $this->validateServer();
'is_usable' => true,
]);
$this->getProxyType();
} }
public function selectProxy(string|null $proxyType = null) public function selectProxy(string|null $proxyType = null)
{ {

View File

@@ -68,10 +68,11 @@ class Heading extends Component
["docker rm -f {$containerName}"], ["docker rm -f {$containerName}"],
$this->application->destination->server $this->application->destination->server
); );
$this->application->status = 'stopped'; $this->application->status = 'exited';
$this->application->save(); $this->application->save();
// $this->application->environment->project->team->notify(new StatusChanged($this->application)); // $this->application->environment->project->team->notify(new StatusChanged($this->application));
} }
} }
$this->application->refresh();
} }
} }

View File

@@ -43,7 +43,7 @@ class Heading extends Component
stopPostgresProxy($this->database); stopPostgresProxy($this->database);
$this->database->is_public = false; $this->database->is_public = false;
} }
$this->database->status = 'stopped'; $this->database->status = 'exited';
$this->database->save(); $this->database->save();
$this->check_status(); $this->check_status();
// $this->database->environment->project->team->notify(new StatusChanged($this->database)); // $this->database->environment->project->team->notify(new StatusChanged($this->database));

View File

@@ -27,7 +27,7 @@ class Deploy extends Component
SaveConfiguration::run($this->server); SaveConfiguration::run($this->server);
} }
$activity = resolve(StartProxy::class)($this->server); $activity = StartProxy::run($this->server);
$this->emit('newMonitorActivity', $activity->id); $this->emit('newMonitorActivity', $activity->id);
} catch (\Throwable $e) { } catch (\Throwable $e) {
return handleError($e); return handleError($e);

View File

@@ -89,7 +89,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
$this->is_debug_enabled = $this->application->settings->is_debug_enabled; $this->is_debug_enabled = $this->application->settings->is_debug_enabled;
$this->container_name = generateApplicationContainerName($this->application->uuid, $this->pull_request_id); $this->container_name = generateApplicationContainerName($this->application->uuid, $this->pull_request_id);
addPrivateKeyToSshAgent($this->server); savePrivateKeyToFs($this->server);
$this->saved_outputs = collect(); $this->saved_outputs = collect();
// Set preview fqdn // Set preview fqdn

View File

@@ -82,11 +82,10 @@ class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
})->first(); })->first();
if (!$foundProxyContainer) { if (!$foundProxyContainer) {
if ($this->server->isProxyShouldRun()) { if ($this->server->isProxyShouldRun()) {
resolve(StartProxy::class)($this->server, false); StartProxy::run($this->server, false);
$this->server->team->notify(new ContainerRestarted('coolify-proxy', $this->server)); $this->server->team->notify(new ContainerRestarted('coolify-proxy', $this->server));
} }
} else { } else {
ray($foundProxyContainer);
$this->server->proxy->status = data_get($foundProxyContainer, 'State.Status'); $this->server->proxy->status = data_get($foundProxyContainer, 'State.Status');
$this->server->save(); $this->server->save();
} }
@@ -198,94 +197,6 @@ class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
$url = base_url() . '/project/' . $project->uuid . "/" . $environment->name . "/database/" . $database->uuid; $url = base_url() . '/project/' . $project->uuid . "/" . $environment->name . "/database/" . $database->uuid;
$this->server->team->notify(new ContainerStopped($containerName, $this->server, $url)); $this->server->team->notify(new ContainerStopped($containerName, $this->server, $url));
} }
return;
foreach ($applications as $application) {
$uuid = data_get($application, 'uuid');
$id = data_get($application, 'id');
$foundContainer = $containers->filter(function ($value, $key) use ($id, $uuid) {
$labels = data_get($value, 'Config.Labels');
$labels = Arr::undot(format_docker_labels_to_json($labels));
$labelId = data_get($labels, 'coolify.applicationId');
if ($labelId == $id) {
return $value;
}
$isPR = Str::startsWith(data_get($value, 'Name'), "/$uuid");
$isPR = Str::contains(data_get($value, 'Name'), "-pr-");
if ($isPR) {
return false;
}
return $value;
})->first();
if ($foundContainer) {
$containerStatus = data_get($foundContainer, 'State.Status');
$databaseStatus = data_get($application, 'status');
if ($containerStatus !== $databaseStatus) {
$application->update(['status' => $containerStatus]);
}
} else {
$databaseStatus = data_get($application, 'status');
if ($databaseStatus !== 'exited') {
$application->update(['status' => 'exited']);
$name = data_get($application, 'name');
$fqdn = data_get($application, 'fqdn');
$containerName = $name ? "$name ($fqdn)" : $fqdn;
$project = data_get($application, 'environment.project');
$environment = data_get($application, 'environment');
$url = base_url() . '/project/' . $project->uuid . "/" . $environment->name . "/application/" . $application->uuid;
$this->server->team->notify(new ContainerStopped($containerName, $this->server, $url));
}
}
$previews = $application->previews;
foreach ($previews as $preview) {
$foundContainer = $containers->filter(function ($value, $key) use ($id, $uuid, $preview) {
$labels = data_get($value, 'Config.Labels');
$labels = Arr::undot(format_docker_labels_to_json($labels));
$labelId = data_get($labels, 'coolify.applicationId');
if ($labelId == "$id-pr-{$preview->id}") {
return $value;
}
return Str::startsWith(data_get($value, 'Name'), "/$uuid-pr-{$preview->id}");
})->first();
}
}
foreach ($databases as $database) {
$uuid = data_get($database, 'uuid');
$foundContainer = $containers->filter(function ($value, $key) use ($uuid) {
return Str::startsWith(data_get($value, 'Name'), "/$uuid");
})->first();
if ($foundContainer) {
$containerStatus = data_get($foundContainer, 'State.Status');
$databaseStatus = data_get($database, 'status');
if ($containerStatus !== $databaseStatus) {
$database->update(['status' => $containerStatus]);
}
} else {
$databaseStatus = data_get($database, 'status');
if ($databaseStatus !== 'exited') {
$database->update(['status' => 'exited']);
$name = data_get($database, 'name');
$containerName = $name;
$project = data_get($database, 'environment.project');
$environment = data_get($database, 'environment');
$url = base_url() . '/project/' . $project->uuid . "/" . $environment->name . "/database/" . $database->uuid;
$this->server->team->notify(new ContainerStopped($containerName, $this->server, $url));
}
}
}
// TODO Monitor other containers not managed by Coolify
} catch (\Throwable $e) { } catch (\Throwable $e) {
send_internal_notification('ContainerStatusJob failed with: ' . $e->getMessage()); send_internal_notification('ContainerStatusJob failed with: ' . $e->getMessage());
ray($e->getMessage()); ray($e->getMessage());

View File

@@ -14,7 +14,7 @@ class DeploymentFailed extends Notification implements ShouldQueue
{ {
use Queueable; use Queueable;
public $tries = 5; public $tries = 1;
public Application $application; public Application $application;
public ?ApplicationPreview $preview = null; public ?ApplicationPreview $preview = null;

View File

@@ -14,7 +14,7 @@ class DeploymentSuccess extends Notification implements ShouldQueue
{ {
use Queueable; use Queueable;
public $tries = 5; public $tries = 1;
public Application $application; public Application $application;
public ApplicationPreview|null $preview = null; public ApplicationPreview|null $preview = null;

View File

@@ -13,7 +13,7 @@ class StatusChanged extends Notification implements ShouldQueue
{ {
use Queueable; use Queueable;
public $tries = 5; public $tries = 1;
public Application $application; public Application $application;
public string $application_name; public string $application_name;

View File

@@ -6,14 +6,16 @@ use Exception;
use Illuminate\Mail\Message; use Illuminate\Mail\Message;
use Illuminate\Notifications\Notification; use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Mail;
use Log;
class EmailChannel class EmailChannel
{ {
public function send(SendsEmail $notifiable, Notification $notification): void public function send(SendsEmail $notifiable, Notification $notification): void
{ {
try {
$this->bootConfigs($notifiable); $this->bootConfigs($notifiable);
$recepients = $notifiable->getRecepients($notification); $recepients = $notifiable->getRecepients($notification);
ray($recepients);
if (count($recepients) === 0) { if (count($recepients) === 0) {
throw new Exception('No email recipients found'); throw new Exception('No email recipients found');
} }
@@ -27,6 +29,11 @@ class EmailChannel
->subject($mailMessage->subject) ->subject($mailMessage->subject)
->html((string)$mailMessage->render()) ->html((string)$mailMessage->render())
); );
} catch (Exception $e) {
ray($e->getMessage());
send_internal_notification("EmailChannel error: {$e->getMessage()}. Failed to send email to: " . implode(', ', $recepients) . " with subject: {$mailMessage->subject}");
throw $e;
}
} }
private function bootConfigs($notifiable): void private function bootConfigs($notifiable): void

View File

@@ -12,7 +12,7 @@ class ContainerRestarted extends Notification implements ShouldQueue
{ {
use Queueable; use Queueable;
public $tries = 5; public $tries = 1;
public function __construct(public string $name, public Server $server, public ?string $url = null) public function __construct(public string $name, public Server $server, public ?string $url = null)

View File

@@ -3,8 +3,6 @@
namespace App\Notifications\Database; namespace App\Notifications\Database;
use App\Models\ScheduledDatabaseBackup; use App\Models\ScheduledDatabaseBackup;
use App\Notifications\Channels\DiscordChannel;
use App\Notifications\Channels\EmailChannel;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\MailMessage;
@@ -14,7 +12,7 @@ class BackupFailed extends Notification implements ShouldQueue
{ {
use Queueable; use Queueable;
public $tries = 5; public $tries = 1;
public string $name; public string $name;
public string $frequency; public string $frequency;

View File

@@ -3,8 +3,6 @@
namespace App\Notifications\Database; namespace App\Notifications\Database;
use App\Models\ScheduledDatabaseBackup; use App\Models\ScheduledDatabaseBackup;
use App\Notifications\Channels\DiscordChannel;
use App\Notifications\Channels\EmailChannel;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\MailMessage;
@@ -14,7 +12,7 @@ class BackupSuccess extends Notification implements ShouldQueue
{ {
use Queueable; use Queueable;
public $tries = 5; public $tries = 1;
public string $name; public string $name;
public string $frequency; public string $frequency;

View File

@@ -18,12 +18,14 @@ use Spatie\Activitylog\Contracts\Activity;
function remote_process( function remote_process(
array $command, array $command,
Server $server, Server $server,
string $type = ActivityTypes::INLINE->value, ?string $type = null,
?string $type_uuid = null, ?string $type_uuid = null,
?Model $model = null, ?Model $model = null,
bool $ignore_errors = false, bool $ignore_errors = false,
): Activity { ): Activity {
if (is_null($type)) {
$type = ActivityTypes::INLINE->value;
}
$command_string = implode("\n", $command); $command_string = implode("\n", $command);
if (auth()->user()) { if (auth()->user()) {
$teams = auth()->user()->teams->pluck('id'); $teams = auth()->user()->teams->pluck('id');
@@ -53,7 +55,7 @@ function remote_process(
// } // }
// // processWithEnv()->run("echo '{$server->privateKey->private_key}' | ssh-add -d -"); // // processWithEnv()->run("echo '{$server->privateKey->private_key}' | ssh-add -d -");
// } // }
function addPrivateKeyToSshAgent(Server $server) function savePrivateKeyToFs(Server $server)
{ {
if (data_get($server, 'privateKey.private_key') === null) { if (data_get($server, 'privateKey.private_key') === null) {
throw new \Exception("Server {$server->name} does not have a private key"); throw new \Exception("Server {$server->name} does not have a private key");
@@ -70,7 +72,7 @@ function generateSshCommand(Server $server, string $command, bool $isMux = true)
{ {
$user = $server->user; $user = $server->user;
$port = $server->port; $port = $server->port;
$privateKeyLocation = addPrivateKeyToSshAgent($server); $privateKeyLocation = savePrivateKeyToFs($server);
$timeout = config('constants.ssh.command_timeout'); $timeout = config('constants.ssh.command_timeout');
$connectionTimeout = config('constants.ssh.connection_timeout'); $connectionTimeout = config('constants.ssh.connection_timeout');
$serverInterval = config('constants.ssh.server_interval'); $serverInterval = config('constants.ssh.server_interval');

View File

@@ -138,5 +138,6 @@ function allowedPathsForBoardingAccounts()
...allowedPathsForUnsubscribedAccounts(), ...allowedPathsForUnsubscribedAccounts(),
'boarding', 'boarding',
'livewire/message/boarding.index', 'livewire/message/boarding.index',
'livewire/message/activity-monitor'
]; ];
} }

View File

@@ -7,7 +7,7 @@ return [
// The release version of your application // The release version of your application
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
'release' => '4.0.0-beta.41', 'release' => '4.0.0-beta.43',
// When left empty or `null` the Laravel environment will be used // When left empty or `null` the Laravel environment will be used
'environment' => config('app.env'), 'environment' => config('app.env'),

View File

@@ -30,7 +30,7 @@ return [
* *
* Minimum: 3000 (in milliseconds) * Minimum: 3000 (in milliseconds)
*/ */
'duration' => 1500, 'duration' => 3000,
/** /**
* The horizontal position of each toast. * The horizontal position of each toast.

View File

@@ -1,3 +1,3 @@
<?php <?php
return '4.0.0-beta.41'; return '4.0.0-beta.43';

View File

@@ -1,7 +1,7 @@
@props([ @props([
'showSubscribeButtons' => true, 'showSubscribeButtons' => true,
]) ])
<div x-data="{ selected: 'yearly' }" class="w-full pb-20"> <div x-data="{ selected: 'monthly' }" class="w-full pb-20">
<div class="px-6 mx-auto lg:px-8"> <div class="px-6 mx-auto lg:px-8">
<div class="flex justify-center"> <div class="flex justify-center">
<fieldset <fieldset
@@ -24,80 +24,36 @@
<div class="py-2 text-center"><span class="font-bold text-warning">{{ config('constants.limits.trial_period') }} <div class="py-2 text-center"><span class="font-bold text-warning">{{ config('constants.limits.trial_period') }}
days trial</span> included on all plans, without credit card details.</div> days trial</span> included on all plans, without credit card details.</div>
<div x-show="selected === 'monthly'" class="flex justify-center h-10 mt-3 text-sm leading-6 "> <div x-show="selected === 'monthly'" class="flex justify-center h-10 mt-3 text-sm leading-6 ">
<div>Save <span class="font-bold text-warning">1 month</span> annually with the yearly plans. <div>Save <span class="font-bold text-warning">10%</span> annually with the yearly plans.
</div> </div>
</div> </div>
<div x-show="selected === 'yearly'" class="flex justify-center h-10 mt-3 text-sm leading-6 "> <div x-show="selected === 'yearly'" class="flex justify-center h-10 mt-3 text-sm leading-6 ">
<div> <div>
</div> </div>
</div> </div>
<div class="p-4 rounded bg-coolgray-400">
<h2 id="tier-hobby" class="flex items-start gap-4 text-4xl font-bold tracking-tight">Unlimited Trial
<x-forms.button><a class="font-bold text-white hover:no-underline"
href="https://github.com/coollabsio/coolify">Get Started</a></x-forms.button>
</h2>
<p class="mt-4 text-sm leading-6">Start self-hosting <span class="text-warning">without limits</span> with
our
OSS version. Same features as the paid version, but you have to manage by yourself.</p>
</div>
<div class="flow-root mt-12"> <div class="flow-root mt-12">
<div <div
class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-coolgray-500 isolate gap-y-16 sm:mx-auto lg:-mx-8 lg:mt-0 lg:max-w-none lg:grid-cols-4 lg:divide-x lg:divide-y-0 xl:-mx-4"> class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-coolgray-500 isolate gap-y-16 sm:mx-auto lg:-mx-8 lg:mt-0 lg:max-w-none lg:grid-cols-3 lg:divide-x lg:divide-y-0 xl:-mx-4">
<div class="px-8 pt-16 lg:pt-0">
<h3 id="tier-trial" class="text-base font-semibold leading-7 text-white">Unlimited Trial</h3>
<p class="flex items-baseline mt-6 gap-x-1">
<span x-show="selected === 'monthly'" x-cloak>
<span class="text-4xl font-bold tracking-tight text-white">Free</span>
</span>
<span x-show="selected === 'yearly'" x-cloak>
<span class="text-4xl font-bold tracking-tight text-white">Still Free </span>
</span>
</p>
<span x-show="selected === 'monthly'" x-cloak>
<span>billed monthly</span>
</span>
<span x-show="selected === 'yearly'" x-cloak>
<span>billed annually</span>
</span>
<a href="https://github.com/coollabsio/coolify" aria-describedby="tier-trial" class="buyme">Get
Started</a>
<p class="mt-10 text-sm leading-6 text-white h-[6.5rem]">Start self-hosting without limits with our
OSS
version.</p>
<ul role="list" class="space-y-3 text-sm leading-6 ">
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
aria-hidden="true">
<path fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
clip-rule="evenodd" />
</svg>
You manage everything
</li>
<li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
aria-hidden="true">
<path fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
clip-rule="evenodd" />
</svg>
Community Support
</li>
<li class="flex font-bold text-white gap-x-3">
<svg width="512" height="512" class="flex-none w-5 h-6 text-green-600"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2">
<path
d="M4 13a8 8 0 0 1 7 7a6 6 0 0 0 3-5a9 9 0 0 0 6-8a3 3 0 0 0-3-3a9 9 0 0 0-8 6a6 6 0 0 0-5 3" />
<path d="M7 14a6 6 0 0 0-3 6a6 6 0 0 0 6-3m4-8a1 1 0 1 0 2 0a1 1 0 1 0-2 0" />
</g>
</svg>
+ All upcoming features
</li>
</ul>
</div>
<div class="pt-16 lg:px-8 lg:pt-0 xl:px-14"> <div class="pt-16 lg:px-8 lg:pt-0 xl:px-14">
<h3 id="tier-basic" class="text-base font-semibold leading-7 text-white">Basic</h3> <h3 id="tier-basic" class="text-base font-semibold leading-7 text-white">Basic</h3>
<p class="flex items-baseline mt-6 gap-x-1"> <p class="flex items-baseline mt-6 gap-x-1">
<span x-show="selected === 'monthly'" x-cloak> <span x-show="selected === 'monthly'" x-cloak>
<span class="text-4xl font-bold tracking-tight text-white">$5</span> <span class="text-4xl font-bold tracking-tight text-white">$5</span>
<span class="text-sm font-semibold leading-6 ">/month</span> <span class="text-sm font-semibold leading-6 ">/month + VAT</span>
</span> </span>
<span x-show="selected === 'yearly'" x-cloak> <span x-show="selected === 'yearly'" x-cloak>
<span class="text-4xl font-bold tracking-tight text-white">$4</span> <span class="text-4xl font-bold tracking-tight text-white">$4</span>
<span class="text-sm font-semibold leading-6 ">/month</span> <span class="text-sm font-semibold leading-6 ">/month + VAT</span>
</span> </span>
</p> </p>
<span x-show="selected === 'monthly'" x-cloak> <span x-show="selected === 'monthly'" x-cloak>
@@ -139,8 +95,8 @@
<li class="flex font-bold text-white gap-x-3"> <li class="flex font-bold text-white gap-x-3">
<svg width="512" height="512" class="flex-none w-5 h-6 text-green-600" <svg width="512" height="512" class="flex-none w-5 h-6 text-green-600"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="currentColor" stroke-linecap="round" <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-linejoin="round" stroke-width="2"> stroke-width="2">
<path <path
d="M4 13a8 8 0 0 1 7 7a6 6 0 0 0 3-5a9 9 0 0 0 6-8a3 3 0 0 0-3-3a9 9 0 0 0-8 6a6 6 0 0 0-5 3" /> d="M4 13a8 8 0 0 1 7 7a6 6 0 0 0 3-5a9 9 0 0 0 6-8a3 3 0 0 0-3-3a9 9 0 0 0-8 6a6 6 0 0 0-5 3" />
<path d="M7 14a6 6 0 0 0-3 6a6 6 0 0 0 6-3m4-8a1 1 0 1 0 2 0a1 1 0 1 0-2 0" /> <path d="M7 14a6 6 0 0 0-3 6a6 6 0 0 0 6-3m4-8a1 1 0 1 0 2 0a1 1 0 1 0-2 0" />
@@ -154,12 +110,12 @@
<h3 id="tier-pro" class="text-base font-semibold leading-7 text-white">Pro</h3> <h3 id="tier-pro" class="text-base font-semibold leading-7 text-white">Pro</h3>
<p class="flex items-baseline mt-6 gap-x-1"> <p class="flex items-baseline mt-6 gap-x-1">
<span x-show="selected === 'monthly'" x-cloak> <span x-show="selected === 'monthly'" x-cloak>
<span class="text-4xl font-bold tracking-tight text-white">$29</span> <span class="text-4xl font-bold tracking-tight text-white">$30</span>
<span class="text-sm font-semibold leading-6 ">/month</span> <span class="text-sm font-semibold leading-6 ">/month + VAT</span>
</span> </span>
<span x-show="selected === 'yearly'" x-cloak> <span x-show="selected === 'yearly'" x-cloak>
<span class="text-4xl font-bold tracking-tight text-white">$26</span> <span class="text-4xl font-bold tracking-tight text-white">$27</span>
<span class="text-sm font-semibold leading-6 ">/month</span> <span class="text-sm font-semibold leading-6 ">/month + VAT</span>
</span> </span>
</p> </p>
<span x-show="selected === 'monthly'" x-cloak> <span x-show="selected === 'monthly'" x-cloak>
@@ -192,7 +148,7 @@
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
clip-rule="evenodd" /> clip-rule="evenodd" />
</svg> </svg>
Basic Support Included Email System
</li> </li>
<li class="flex gap-x-3"> <li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor" <svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
@@ -201,7 +157,7 @@
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
clip-rule="evenodd" /> clip-rule="evenodd" />
</svg> </svg>
Included Email System Email Support
</li> </li>
<li class="flex font-bold text-white gap-x-3"> <li class="flex font-bold text-white gap-x-3">
<svg width="512" height="512" class="flex-none w-5 h-6 text-green-600" <svg width="512" height="512" class="flex-none w-5 h-6 text-green-600"
@@ -221,12 +177,12 @@
<h3 id="tier-ultimate" class="text-base font-semibold leading-7 text-white">Ultimate</h3> <h3 id="tier-ultimate" class="text-base font-semibold leading-7 text-white">Ultimate</h3>
<p class="flex items-baseline mt-6 gap-x-1"> <p class="flex items-baseline mt-6 gap-x-1">
<span x-show="selected === 'monthly'" x-cloak> <span x-show="selected === 'monthly'" x-cloak>
<span class="text-4xl font-bold tracking-tight text-white">$69</span> <span class="text-4xl font-bold tracking-tight text-white">$?</span>
<span class="text-sm font-semibold leading-6 ">/month</span> <span class="text-sm font-semibold leading-6 ">/month + VAT</span>
</span> </span>
<span x-show="selected === 'yearly'" x-cloak> <span x-show="selected === 'yearly'" x-cloak>
<span class="text-4xl font-bold tracking-tight text-white">$63</span> <span class="text-4xl font-bold tracking-tight text-white">$?</span>
<span class="text-sm font-semibold leading-6 ">/month</span> <span class="text-sm font-semibold leading-6 ">/month + VAT</span>
</span> </span>
</p> </p>
<span x-show="selected === 'monthly'" x-cloak> <span x-show="selected === 'monthly'" x-cloak>
@@ -250,17 +206,9 @@
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
clip-rule="evenodd" /> clip-rule="evenodd" />
</svg> </svg>
25 servers <x-helper helper="Bring Your Own Server. All you need is n SSH connection." /> ? servers <x-helper helper="Bring Your Own Server. All you need is n SSH connection." />
</li>
<li class="flex font-bold text-white gap-x-3">
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
aria-hidden="true">
<path fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
clip-rule="evenodd" />
</svg>
Priority Support
</li> </li>
<li class="flex gap-x-3"> <li class="flex gap-x-3">
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor" <svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
aria-hidden="true"> aria-hidden="true">
@@ -270,6 +218,15 @@
</svg> </svg>
Included Email System Included Email System
</li> </li>
<li class="flex font-bold text-white gap-x-3">
<svg class="flex-none w-5 h-6 text-warning" viewBox="0 0 20 20" fill="currentColor"
aria-hidden="true">
<path fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
clip-rule="evenodd" />
</svg>
Priority (Email/Chat) Support
</li>
<li class="flex font-bold text-white gap-x-3"> <li class="flex font-bold text-white gap-x-3">
<svg width="512" height="512" class="flex-none w-5 h-6 text-green-600" <svg width="512" height="512" class="flex-none w-5 h-6 text-green-600"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
@@ -285,8 +242,13 @@
</ul> </ul>
</div> </div>
</div> </div>
<div class="pt-10">Need unlimited servers or official support for your Coolify instance? <a <div class="p-4 mt-10 rounded">
href="https://docs.coollabs.io/contact" class='text-warning'>Contact us.</a> <div class="flex items-start gap-4 text-xl tracking-tight">Need official support for
your self-hosted instance?
<x-forms.button>
<a class="font-bold text-white hover:no-underline"
href="https://docs.coollabs.io/contact">Contact Us</a>
</x-forms.button>
</div> </div>
</div> </div>
</div> </div>
@@ -297,8 +259,8 @@
<div class="flex items-center justify-center w-10 h-10 text-white rounded-lg bg-coolgray-500"> <div class="flex items-center justify-center w-10 h-10 text-white rounded-lg bg-coolgray-500">
<svg width="512" height="512" class="icon" viewBox="0 0 24 24" <svg width="512" height="512" class="icon" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" <path fill="none" stroke="currentColor" stroke-linecap="round"
stroke-width="2" stroke-linejoin="round" stroke-width="2"
d="M3 7a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v2a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3zm12 13H6a3 3 0 0 1-3-3v-2a3 3 0 0 1 3-3h12M7 8v.01M7 16v.01M20 15l-2 3h3l-2 3" /> d="M3 7a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v2a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3zm12 13H6a3 3 0 0 1-3-3v-2a3 3 0 0 1 3-3h12M7 8v.01M7 16v.01M20 15l-2 3h3l-2 3" />
</svg> </svg>
</div> </div>
@@ -339,8 +301,10 @@
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2"> stroke-width="2">
<path d="M15 11h2a2 2 0 0 1 2 2v2m0 4a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-6a2 2 0 0 1 2-2h4" /> <path
<path d="M11 16a1 1 0 1 0 2 0a1 1 0 1 0-2 0m-3-5V8m.347-3.631A4 4 0 0 1 16 6M3 3l18 18" /> d="M15 11h2a2 2 0 0 1 2 2v2m0 4a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-6a2 2 0 0 1 2-2h4" />
<path
d="M11 16a1 1 0 1 0 2 0a1 1 0 1 0-2 0m-3-5V8m.347-3.631A4 4 0 0 1 16 6M3 3l18 18" />
</g> </g>
</svg> </svg>
</div> </div>
@@ -356,8 +320,9 @@
<div> <div>
<div class="flex items-center gap-4 mb-4"> <div class="flex items-center gap-4 mb-4">
<div class="flex items-center justify-center w-10 h-10 text-white rounded-lg bg-coolgray-500"> <div class="flex items-center justify-center w-10 h-10 text-white rounded-lg bg-coolgray-500">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" stroke-width="1.5" <svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24"
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" /> <path stroke="none" d="M0 0h24v24H0z" fill="none" />
<rect x="3" y="4" width="18" height="12" rx="1" /> <rect x="3" y="4" width="18" height="12" rx="1" />
<path d="M7 20h10" /> <path d="M7 20h10" />
@@ -396,8 +361,9 @@
<div> <div>
<div class="flex items-center gap-4 mb-4"> <div class="flex items-center gap-4 mb-4">
<div class="flex items-center justify-center w-10 h-10 text-white rounded-lg bg-coolgray-500"> <div class="flex items-center justify-center w-10 h-10 text-white rounded-lg bg-coolgray-500">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" stroke-width="1.5" <svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24"
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" /> <path stroke="none" d="M0 0h24v24H0z" fill="none" />
<polyline points="5 7 10 12 5 17" /> <polyline points="5 7 10 12 5 17" />
<line x1="13" y1="17" x2="19" y2="17" /> <line x1="13" y1="17" x2="19" y2="17" />
@@ -429,7 +395,8 @@
</div> </div>
<div class="mt-1 text-base leading-7 text-gray-300"> <div class="mt-1 text-base leading-7 text-gray-300">
Git integration is default today. We support hosted (github.com, Git integration is default today. We support hosted (github.com,
gitlab.com<span class="inline-block text-warning">*</span>) or self-hosted<span class="text-warning">*</span> gitlab.com<span class="inline-block text-warning">*</span>) or self-hosted<span
class="text-warning">*</span>
(Github Enterprise, Gitlab) Git repositories. (Github Enterprise, Gitlab) Git repositories.
</div> </div>
</div> </div>
@@ -438,8 +405,8 @@
<div class="flex items-center justify-center w-10 h-10 text-white rounded-lg bg-coolgray-500"> <div class="flex items-center justify-center w-10 h-10 text-white rounded-lg bg-coolgray-500">
<svg width="512" height="512" class="icon" viewBox="0 0 24 24" <svg width="512" height="512" class="icon" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"> xmlns="http://www.w3.org/2000/svg">
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" <path fill="none" stroke="currentColor" stroke-linecap="round"
stroke-width="2" stroke-linejoin="round" stroke-width="2"
d="M10 13a2 2 0 1 0 4 0a2 2 0 0 0-4 0m-2 8v-1a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1M15 5a2 2 0 1 0 4 0a2 2 0 0 0-4 0m2 5h2a2 2 0 0 1 2 2v1M5 5a2 2 0 1 0 4 0a2 2 0 0 0-4 0m-2 8v-1a2 2 0 0 1 2-2h2" /> d="M10 13a2 2 0 1 0 4 0a2 2 0 0 0-4 0m-2 8v-1a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1M15 5a2 2 0 1 0 4 0a2 2 0 0 0-4 0m2 5h2a2 2 0 0 1 2 2v1M5 5a2 2 0 1 0 4 0a2 2 0 0 0-4 0m-2 8v-1a2 2 0 0 1 2-2h2" />
</svg> </svg>
</div> </div>

View File

@@ -1,8 +1,6 @@
@extends('layouts.base') @extends('layouts.base')
@section('body') @section('body')
<main class="min-h-screen hero"> <x-modal noSubmit modalId="installDocker">
<div class="hero-content">
<x-modal modalId="installDocker">
<x-slot:modalBody> <x-slot:modalBody>
<livewire:activity-monitor header="Docker Installation Logs" /> <livewire:activity-monitor header="Docker Installation Logs" />
</x-slot:modalBody> </x-slot:modalBody>
@@ -12,6 +10,8 @@
</x-forms.button> </x-forms.button>
</x-slot:modalSubmit> </x-slot:modalSubmit>
</x-modal> </x-modal>
<main class="min-h-screen hero">
<div class="hero-content">
{{ $slot }} {{ $slot }}
</div> </div>
</main> </main>

View File

@@ -46,9 +46,21 @@
<x-forms.button class="justify-center box" wire:target="setServerType('localhost')" <x-forms.button class="justify-center box" wire:target="setServerType('localhost')"
wire:click="setServerType('localhost')">Localhost wire:click="setServerType('localhost')">Localhost
</x-forms.button> </x-forms.button>
<x-forms.button class="justify-center box" wire:target="setServerType('remote')" <x-forms.button class="justify-center box" wire:target="setServerType('remote')"
wire:click="setServerType('remote')">Remote Server wire:click="setServerType('remote')">Remote Server
</x-forms.button> </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
'root' or skip the boarding process and add a new private key manually to Coolify and to the
server.
<x-forms.input readonly id="serverPublicKey"></x-forms.input>
<x-forms.button class="box" wire:target="setServerType('localhost')"
wire:click="setServerType('localhost')">Check again
</x-forms.button>
@endif
</x-slot:actions> </x-slot:actions>
<x-slot:explanation> <x-slot:explanation>
<p>Servers are the main building blocks, as they will host your applications, databases, <p>Servers are the main building blocks, as they will host your applications, databases,
@@ -118,6 +130,17 @@
<x-forms.button type="submit">Use this Server</x-forms.button> <x-forms.button type="submit">Use this Server</x-forms.button>
</form> </form>
</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
'root' or skip the boarding process and add a new private key manually to Coolify and to the
server.
<x-forms.input readonly id="serverPublicKey"></x-forms.input>
<x-forms.button class="box" wire:target="validateServer"
wire:click="validateServer">Check again
</x-forms.button>
@endif
</x-slot:actions> </x-slot:actions>
<x-slot:explanation> <x-slot:explanation>
<p>Private Keys are used to connect to a remote server through a secure shell, called SSH.</p> <p>Private Keys are used to connect to a remote server through a secure shell, called SSH.</p>
@@ -202,10 +225,10 @@
Could not find Docker Engine on your server. Do you want me to install it for you? Could not find Docker Engine on your server. Do you want me to install it for you?
</x-slot:question> </x-slot:question>
<x-slot:actions> <x-slot:actions>
@if ($dockerInstallationStarted)
<x-forms.button class="justify-center box" wire:click="installDocker" <x-forms.button class="justify-center box" wire:click="installDocker"
onclick="installDocker.showModal()"> onclick="installDocker.showModal()">
Let's do it!</x-forms.button> Let's do it!</x-forms.button>
@if ($dockerInstallationStarted)
<x-forms.button class="justify-center box" wire:click="dockerInstalledOrSkipped"> <x-forms.button class="justify-center box" wire:click="dockerInstalledOrSkipped">
Next</x-forms.button> Next</x-forms.button>
@endif @endif

View File

@@ -2,16 +2,19 @@
@if (config('subscription.provider') === 'stripe') @if (config('subscription.provider') === 'stripe')
<x-slot:basic> <x-slot:basic>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-basic" <x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-basic"
class="w-full h-10 buyme" wire:click="subscribeStripe('basic-monthly')"> {{$isTrial ? 'Start Trial' : 'Subscribe' }} class="w-full h-10 buyme" wire:click="subscribeStripe('basic-monthly')">
{{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button> </x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-basic" <x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-basic"
class="w-full h-10 buyme" wire:click="subscribeStripe('basic-yearly')"> {{$isTrial ? 'Start Trial' : 'Subscribe' }} class="w-full h-10 buyme" wire:click="subscribeStripe('basic-yearly')">
{{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button> </x-forms.button>
</x-slot:basic> </x-slot:basic>
<x-slot:pro> <x-slot:pro>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-pro" <x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-pro"
class="w-full h-10 buyme" wire:click="subscribeStripe('pro-monthly')"> {{$isTrial ? 'Start Trial' : 'Subscribe' }} class="w-full h-10 buyme" wire:click="subscribeStripe('pro-monthly')">
{{ $isTrial ? 'Start Trial' : 'Subscribe' }}
</x-forms.button> </x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-pro" class="w-full h-10 buyme" <x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-pro" class="w-full h-10 buyme"
@@ -20,11 +23,13 @@
</x-slot:pro> </x-slot:pro>
<x-slot:ultimate> <x-slot:ultimate>
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-ultimate" <x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-ultimate"
class="w-full h-10 buyme" wire:click="subscribeStripe('ultimate-monthly')"> {{$isTrial ? 'Start Trial' : 'Subscribe' }} class="w-full h-10 buyme"><a class="text-white hover:no-underline" href="https://docs.coollabs.io/contact" target="_blank">
Contact Us</a>
</x-forms.button> </x-forms.button>
<x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-ultimate" <x-forms.button x-show="selected === 'yearly'" x-cloak aria-describedby="tier-ultimate"
class="w-full h-10 buyme" wire:click="subscribeStripe('ultimate-yearly')"> {{$isTrial ? 'Start Trial' : 'Subscribe' }} class="w-full h-10 buyme"><a class="text-white hover:no-underline" href="https://docs.coollabs.io/contact" target="_blank">
Contact Us</a>
</x-forms.button> </x-forms.button>
</x-slot:ultimate> </x-slot:ultimate>
@endif @endif

View File

@@ -4,7 +4,7 @@
"version": "3.12.36" "version": "3.12.36"
}, },
"v4": { "v4": {
"version": "4.0.0-beta.41" "version": "4.0.0-beta.43"
} }
} }
} }