Merge branch 'next' into feat/deployment-token
This commit is contained in:
@@ -69,7 +69,7 @@ button[isHighlighted]:not(:disabled) {
|
||||
}
|
||||
|
||||
h1 {
|
||||
@apply text-2xl font-bold dark:text-white;
|
||||
@apply text-3xl font-bold dark:text-white;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@@ -124,6 +124,10 @@ tr td:first-child {
|
||||
@apply pl-4 pr-3 font-bold sm:pl-6;
|
||||
}
|
||||
|
||||
section {
|
||||
@apply mb-12;
|
||||
}
|
||||
|
||||
.alert-success {
|
||||
@apply flex items-center gap-2 text-success;
|
||||
}
|
||||
@@ -217,7 +221,7 @@ tr td:first-child {
|
||||
}
|
||||
|
||||
.box {
|
||||
@apply relative flex lg:flex-row flex-col p-2 transition-colors cursor-pointer min-h-[4rem] dark:bg-coolgray-100 bg-white border text-black dark:text-white hover:text-black border-neutral-200 dark:border-black hover:bg-neutral-100 dark:hover:bg-coollabs-100 dark:hover:text-white hover:no-underline;
|
||||
@apply relative flex lg:flex-row flex-col p-2 transition-colors cursor-pointer min-h-[4rem] dark:bg-coolgray-100 shadow bg-white border text-black dark:text-white hover:text-black border-neutral-200 dark:border-black hover:bg-neutral-100 dark:hover:bg-coollabs-100 dark:hover:text-white hover:no-underline;
|
||||
}
|
||||
|
||||
.box-boarding {
|
||||
|
||||
@@ -15,10 +15,7 @@
|
||||
'w-full' => $fullWidth,
|
||||
])>
|
||||
@if (!$hideLabel)
|
||||
<label @class([
|
||||
"flex gap-4 px-0 min-w-fit label",
|
||||
'opacity-40' => $disabled,
|
||||
])>
|
||||
<label @class(['flex gap-4 px-0 min-w-fit label', 'opacity-40' => $disabled])>
|
||||
<span class="flex gap-2">
|
||||
@if ($label)
|
||||
{!! $label !!}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@props([
|
||||
'title' => 'Are you sure?',
|
||||
'isErrorButton' => false,
|
||||
'isHighlightedButton' => false,
|
||||
'buttonTitle' => 'Confirm Action',
|
||||
'buttonFullWidth' => false,
|
||||
'customButton' => null,
|
||||
@@ -143,6 +144,16 @@
|
||||
{{ $buttonTitle }}
|
||||
</x-forms.button>
|
||||
@endif
|
||||
@elseif($isHighlightedButton)
|
||||
@if ($buttonFullWidth)
|
||||
<x-forms.button @click="modalOpen=true" class="flex gap-2 w-full" isHighlighted wire:target>
|
||||
{{ $buttonTitle }}
|
||||
</x-forms.button>
|
||||
@else
|
||||
<x-forms.button @click="modalOpen=true" class="flex gap-2" isHighlighted wire:target>
|
||||
{{ $buttonTitle }}
|
||||
</x-forms.button>
|
||||
@endif
|
||||
@else
|
||||
@if ($buttonFullWidth)
|
||||
<x-forms.button @click="modalOpen=true" class="flex gap-2 w-full" wire:target>
|
||||
@@ -291,8 +302,7 @@
|
||||
</x-forms.button>
|
||||
@endif
|
||||
<x-forms.button
|
||||
x-bind:disabled="!disableTwoStepConfirmation && confirmWithText && userConfirmationText !==
|
||||
confirmationText"
|
||||
x-bind:disabled="!disableTwoStepConfirmation && confirmWithText && userConfirmationText !== confirmationText"
|
||||
class="w-auto" isError
|
||||
@click="
|
||||
if (dispatchEvent) {
|
||||
@@ -319,16 +329,19 @@
|
||||
<p>Please enter your password to confirm this destructive action.</p>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 mb-4">
|
||||
<label for="password-confirm"
|
||||
@php
|
||||
$passwordConfirm = Str::uuid();
|
||||
@endphp
|
||||
<label for="password-confirm-{{ $passwordConfirm }}"
|
||||
class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
Your Password
|
||||
</label>
|
||||
<form @submit.prevent @keydown.enter.prevent>
|
||||
<input type="password" id="password-confirm" x-model="password"
|
||||
class="w-full input" placeholder="Enter your password">
|
||||
<form @submit.prevent="false" @keydown.enter.prevent>
|
||||
<input type="text" name="username" autocomplete="username" value="{{ auth()->user()->email }}" style="display: none;">
|
||||
<input type="password" id="password-confirm-{{ $passwordConfirm }}" x-model="password"
|
||||
class="w-full input" placeholder="Enter your password" autocomplete="current-password">
|
||||
</form>
|
||||
<p x-show="passwordError" x-text="passwordError" class="mt-1 text-sm text-red-500">
|
||||
</p>
|
||||
<p x-show="passwordError" x-text="passwordError" class="mt-1 text-sm text-red-500"></p>
|
||||
@error('password')
|
||||
<p class="mt-1 text-sm text-red-500">{{ $message }}</p>
|
||||
@enderror
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
'title' => 'Are you sure?',
|
||||
'buttonTitle' => 'Open Modal',
|
||||
'isErrorButton' => false,
|
||||
'isHighlightedButton' => false,
|
||||
'disabled' => false,
|
||||
'action' => 'delete',
|
||||
'content' => null,
|
||||
@@ -18,6 +19,8 @@
|
||||
<x-forms.button isError disabled>{{ $buttonTitle }}</x-forms.button>
|
||||
@elseif ($isErrorButton)
|
||||
<x-forms.button isError @click="modalOpen=true">{{ $buttonTitle }}</x-forms.button>
|
||||
@elseif ($isHighlightedButton)
|
||||
<x-forms.button isHighlighted @click="modalOpen=true">{{ $buttonTitle }}</x-forms.button>
|
||||
@else
|
||||
<x-forms.button @click="modalOpen=true">{{ $buttonTitle }}</x-forms.button>
|
||||
@endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<nav class="flex flex-col flex-1 bg-white border-r dark:border-coolgray-200 dark:bg-base" x-data="{
|
||||
<nav class="flex flex-col flex-1 px-2 bg-white border-r dark:border-coolgray-200 dark:bg-base" x-data="{
|
||||
switchWidth() {
|
||||
if (this.full === 'full') {
|
||||
localStorage.setItem('pageWidth', 'center');
|
||||
@@ -46,7 +46,7 @@
|
||||
}
|
||||
}
|
||||
}">
|
||||
<div class="flex pt-6 pb-4 pl-3">
|
||||
<div class="flex pt-6 pb-4 pl-2">
|
||||
<div class="flex flex-col w-full">
|
||||
<div class="text-2xl font-bold tracking-wide dark:text-white">Coolify</div>
|
||||
<x-version />
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<nav class="flex items-center gap-6 overflow-x-scroll sm:overflow-x-hidden scrollbar min-h-10 whitespace-nowrap">
|
||||
<a class="{{ request()->routeIs('server.show') ? 'dark:text-white' : '' }}"
|
||||
href="{{ route('server.show', [
|
||||
'server_uuid' => data_get($parameters, 'server_uuid'),
|
||||
'server_uuid' => data_get($server, 'uuid'),
|
||||
]) }}">
|
||||
<button>Configuration</button>
|
||||
</a>
|
||||
@@ -28,20 +28,20 @@
|
||||
@if (!$server->isSwarmWorker() && !$server->settings->is_build_server)
|
||||
<a class="{{ request()->routeIs('server.proxy') ? 'dark:text-white' : '' }}"
|
||||
href="{{ route('server.proxy', [
|
||||
'server_uuid' => data_get($parameters, 'server_uuid'),
|
||||
'server_uuid' => data_get($server, 'uuid'),
|
||||
]) }}">
|
||||
<button>Proxy</button>
|
||||
</a>
|
||||
@endif
|
||||
<a class="{{ request()->routeIs('server.resources') ? 'dark:text-white' : '' }}"
|
||||
href="{{ route('server.resources', [
|
||||
'server_uuid' => data_get($parameters, 'server_uuid'),
|
||||
'server_uuid' => data_get($server, 'uuid'),
|
||||
]) }}">
|
||||
<button>Resources</button>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('server.command') ? 'dark:text-white' : '' }}"
|
||||
href="{{ route('server.command', [
|
||||
'server_uuid' => data_get($parameters, 'server_uuid'),
|
||||
'server_uuid' => data_get($server, 'uuid'),
|
||||
]) }}">
|
||||
<button>Terminal</button>
|
||||
</a>
|
||||
|
||||
16
resources/views/components/server/sidebar-proxy.blade.php
Normal file
16
resources/views/components/server/sidebar-proxy.blade.php
Normal file
@@ -0,0 +1,16 @@
|
||||
@if ($server->proxySet())
|
||||
<div class="flex flex-col items-start gap-2 min-w-fit">
|
||||
<a class="{{ request()->routeIs('server.proxy') ? 'menu-item menu-item-active' : 'menu-item' }}"
|
||||
href="{{ route('server.proxy', $parameters) }}">
|
||||
<button>Configuration</button>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('server.proxy.dynamic-confs') ? 'menu-item menu-item-active' : 'menu-item' }}"
|
||||
href="{{ route('server.proxy.dynamic-confs', $parameters) }}">
|
||||
<button>Dynamic Configurations</button>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('server.proxy.logs') ? 'menu-item menu-item-active' : 'menu-item' }}"
|
||||
href="{{ route('server.proxy.logs', $parameters) }}">
|
||||
<button>Logs</button>
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
@@ -1,16 +1,29 @@
|
||||
@if ($server->proxySet())
|
||||
<div class="flex flex-col items-start gap-2 min-w-fit">
|
||||
<a class="{{ request()->routeIs('server.proxy') ? 'menu-item menu-item-active' : 'menu-item' }}"
|
||||
href="{{ route('server.proxy', $parameters) }}">
|
||||
<button>Configuration</button>
|
||||
<div class="flex flex-col items-start gap-2 min-w-fit">
|
||||
<a class="menu-item {{ $activeMenu === 'general' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.show', ['server_uuid' => $server->uuid]) }}" wire:navigate>General</a>
|
||||
@if ($server->isFunctional())
|
||||
<a class="menu-item {{ $activeMenu === 'advanced' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.advanced', ['server_uuid' => $server->uuid]) }}" wire:navigate>Advanced
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('server.proxy.dynamic-confs') ? 'menu-item menu-item-active' : 'menu-item' }}"
|
||||
href="{{ route('server.proxy.dynamic-confs', $parameters) }}">
|
||||
<button>Dynamic Configurations</button>
|
||||
@endif
|
||||
<a class="menu-item {{ $activeMenu === 'private-key' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.private-key', ['server_uuid' => $server->uuid]) }}" wire:navigate>Private Key
|
||||
</a>
|
||||
@if ($server->isFunctional())
|
||||
<a class="menu-item {{ $activeMenu === 'cloudflare-tunnels' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.cloudflare-tunnels', ['server_uuid' => $server->uuid]) }}" wire:navigate>Cloudflare
|
||||
Tunnels</a>
|
||||
<a class="menu-item {{ $activeMenu === 'destinations' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.destinations', ['server_uuid' => $server->uuid]) }}" wire:navigate>Destinations
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('server.proxy.logs') ? 'menu-item menu-item-active' : 'menu-item' }}"
|
||||
href="{{ route('server.proxy.logs', $parameters) }}">
|
||||
<button>Logs</button>
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
<a class="menu-item {{ $activeMenu === 'log-drains' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.log-drains', ['server_uuid' => $server->uuid]) }}" wire:navigate>Log
|
||||
Drains</a>
|
||||
<a class="menu-item {{ $activeMenu === 'metrics' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.charts', ['server_uuid' => $server->uuid]) }}">Metrics</a>
|
||||
@endif
|
||||
@if (!$server->isLocalhost())
|
||||
<a class="menu-item {{ $activeMenu === 'danger' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('server.delete', ['server_uuid' => $server->uuid]) }}" wire:navigate>Danger</a>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="relative z-50 lg:hidden" :class="open ? 'block' : 'hidden'" role="dialog" aria-modal="true">
|
||||
<div class="fixed inset-0 bg-black/80"></div>
|
||||
<div class="fixed inset-0 flex">
|
||||
<div class="relative flex flex-1 w-full mr-16 max-w-48 ">
|
||||
<div class="relative flex flex-1 w-full mr-16 max-w-56 ">
|
||||
<div class="absolute top-0 flex justify-center w-16 pt-5 left-full">
|
||||
<button type="button" class="-m-2.5 p-2.5" x-on:click="open = !open">
|
||||
<span class="sr-only">Close sidebar</span>
|
||||
@@ -29,14 +29,14 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col pb-2 overflow-y-auto min-w-48 dark:bg-coolgray-100 gap-y-5 scrollbar">
|
||||
<div class="flex flex-col pb-2 overflow-y-auto min-w-56 dark:bg-coolgray-100 gap-y-5 scrollbar">
|
||||
<x-navbar />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:w-48 lg:flex-col">
|
||||
<div class="hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:w-56 lg:flex-col">
|
||||
<div class="flex flex-col overflow-y-auto grow gap-y-5 scrollbar">
|
||||
<x-navbar />
|
||||
</div>
|
||||
@@ -52,7 +52,7 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<main class="lg:pl-48">
|
||||
<main class="lg:pl-56">
|
||||
<div class="p-4 sm:px-6 lg:px-8 lg:py-6">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
|
||||
@@ -18,155 +18,163 @@
|
||||
subscription is activated.<br> Please be patient.
|
||||
</div>
|
||||
@endif
|
||||
<h3 class="pb-4">Projects</h3>
|
||||
@if ($projects->count() > 0)
|
||||
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
||||
@foreach ($projects as $project)
|
||||
<div class="gap-2 border border-transparent cursor-pointer box group"
|
||||
onclick="gotoProject('{{ $project->uuid }}','{{ $project->default_environment }}')">
|
||||
<div class="flex flex-1 mx-6">
|
||||
<div class="flex flex-col justify-center flex-1">
|
||||
<div class="box-title">{{ $project->name }}</div>
|
||||
<div class="box-description">
|
||||
{{ $project->description }}
|
||||
|
||||
<section>
|
||||
<h3 class="pb-2">Projects</h3>
|
||||
@if ($projects->count() > 0)
|
||||
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
||||
@foreach ($projects as $project)
|
||||
<div class="gap-2 border border-transparent cursor-pointer box group"
|
||||
onclick="gotoProject('{{ $project->uuid }}','{{ $project->default_environment }}')">
|
||||
<div class="flex flex-1 mx-6">
|
||||
<div class="flex flex-col justify-center flex-1">
|
||||
<div class="box-title">{{ $project->name }}</div>
|
||||
<div class="box-description">
|
||||
{{ $project->description }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-center gap-2 text-xs font-bold">
|
||||
<a class="hover:underline"
|
||||
href="{{ route('project.resource.create', ['project_uuid' => $project->uuid, 'environment_name' => data_get($project, 'default_environment', 'production')]) }}">
|
||||
<span class="p-2 font-bold">+ Add Resource</span>
|
||||
</a>
|
||||
<a class="hover:underline"
|
||||
href="{{ route('project.edit', ['project_uuid' => $project->uuid]) }}">
|
||||
Settings
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-center gap-2 text-xs font-bold">
|
||||
<a class="hover:underline"
|
||||
href="{{ route('project.resource.create', ['project_uuid' => $project->uuid, 'environment_name' => data_get($project, 'default_environment', 'production')]) }}">
|
||||
<span class="p-2 font-bold">+ Add Resource</span>
|
||||
</a>
|
||||
<a class="hover:underline"
|
||||
href="{{ route('project.edit', ['project_uuid' => $project->uuid]) }}">
|
||||
Settings
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class='font-bold dark:text-warning'>No projects found.</div>
|
||||
<div class="flex items-center gap-1">
|
||||
<x-modal-input buttonTitle="Add" title="New Project">
|
||||
<livewire:project.add-empty />
|
||||
</x-modal-input> your first project or
|
||||
go to the <a class="underline dark:text-white" href="{{ route('onboarding') }}">onboarding</a> page.
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<h3 class="py-4">Servers</h3>
|
||||
@if ($servers->count() > 0)
|
||||
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
||||
@foreach ($servers as $server)
|
||||
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
|
||||
@class([
|
||||
'gap-2 border cursor-pointer box group',
|
||||
'border-transparent' => $server->settings->is_reachable,
|
||||
'border-red-500' => !$server->settings->is_reachable,
|
||||
])>
|
||||
<div class="flex flex-col justify-center mx-6">
|
||||
<div class="box-title">
|
||||
{{ $server->name }}
|
||||
</div>
|
||||
<div class="box-description">
|
||||
{{ $server->description }}</div>
|
||||
<div class="flex gap-1 text-xs text-error">
|
||||
@if (!$server->settings->is_reachable)
|
||||
Not reachable
|
||||
@endif
|
||||
@if (!$server->settings->is_reachable && !$server->settings->is_usable)
|
||||
&
|
||||
@endif
|
||||
@if (!$server->settings->is_usable)
|
||||
Not usable by Coolify
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1"></div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
@if ($private_keys->count() === 0)
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class='font-bold dark:text-warning'>No private keys found.</div>
|
||||
<div class="flex items-center gap-1">Before you can add your server, first <x-modal-input
|
||||
buttonTitle="add" title="New Private Key">
|
||||
<livewire:security.private-key.create from="server" />
|
||||
</x-modal-input> a private key
|
||||
or
|
||||
go to the <a class="underline dark:text-white" href="{{ route('onboarding') }}">onboarding</a>
|
||||
page.
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class='font-bold dark:text-warning'>No servers found.</div>
|
||||
<div class='font-bold dark:text-warning'>No projects found.</div>
|
||||
<div class="flex items-center gap-1">
|
||||
<x-modal-input buttonTitle="Add" title="New Server" :closeOutside="false">
|
||||
<livewire:server.create />
|
||||
</x-modal-input> your first server
|
||||
or
|
||||
go to the <a class="underline dark:text-white" href="{{ route('onboarding') }}">onboarding</a>
|
||||
page.
|
||||
<x-modal-input buttonTitle="Add" title="New Project">
|
||||
<livewire:project.add-empty />
|
||||
</x-modal-input> your first project or
|
||||
go to the <a class="underline dark:text-white" href="{{ route('onboarding') }}">onboarding</a> page.
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
@if ($servers->count() > 0 && $projects->count() > 0)
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="py-4">Deployments</h3>
|
||||
@if (count($deployments_per_server) > 0)
|
||||
<x-loading />
|
||||
@endif
|
||||
<x-modal-confirmation
|
||||
title="Confirm Cleanup Queues?"
|
||||
buttonTitle="Cleanup Queues"
|
||||
isErrorButton
|
||||
submitAction="cleanup_queue"
|
||||
:actions="['All running Deployment Queues will be cleaned up.']"
|
||||
:confirmWithText="false"
|
||||
:confirmWithPassword="false"
|
||||
step2ButtonText="Permanently Cleanup Deployment Queues"
|
||||
:dispatchEvent="true"
|
||||
dispatchEventType="success"
|
||||
dispatchEventMessage="Deployment Queues cleanup started."
|
||||
/>
|
||||
</div>
|
||||
<div wire:poll.3000ms="get_deployments" class="grid grid-cols-1">
|
||||
@forelse ($deployments_per_server as $server_name => $deployments)
|
||||
<h4 class="py-4">{{ $server_name }}</h4>
|
||||
<div class="grid grid-cols-1 gap-2 lg:grid-cols-3">
|
||||
@foreach ($deployments as $deployment)
|
||||
<a href="{{ data_get($deployment, 'deployment_url') }}" @class([
|
||||
'gap-2 cursor-pointer box group border-l-2 border-dotted',
|
||||
'dark:border-coolgray-300' => data_get($deployment, 'status') === 'queued',
|
||||
'border-yellow-500' => data_get($deployment, 'status') === 'in_progress',
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3 class="pb-2">Servers</h3>
|
||||
@if ($servers->count() > 0)
|
||||
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
||||
@foreach ($servers as $server)
|
||||
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
|
||||
@class([
|
||||
'gap-2 border cursor-pointer box group',
|
||||
'border-transparent' => $server->settings->is_reachable,
|
||||
'border-red-500' => !$server->settings->is_reachable,
|
||||
])>
|
||||
<div class="flex flex-col justify-center mx-6">
|
||||
<div class="box-title">
|
||||
{{ data_get($deployment, 'application_name') }}
|
||||
</div>
|
||||
@if (data_get($deployment, 'pull_request_id') !== 0)
|
||||
<div class="box-description">
|
||||
PR #{{ data_get($deployment, 'pull_request_id') }}
|
||||
</div>
|
||||
@endif
|
||||
<div class="box-description">
|
||||
{{ str(data_get($deployment, 'status'))->headline() }}
|
||||
</div>
|
||||
<div class="flex flex-col justify-center mx-6">
|
||||
<div class="box-title">
|
||||
{{ $server->name }}
|
||||
</div>
|
||||
<div class="flex-1"></div>
|
||||
</a>
|
||||
@endforeach
|
||||
<div class="box-description">
|
||||
{{ $server->description }}</div>
|
||||
<div class="flex gap-1 text-xs text-error">
|
||||
@if (!$server->settings->is_reachable)
|
||||
Not reachable
|
||||
@endif
|
||||
@if (!$server->settings->is_reachable && !$server->settings->is_usable)
|
||||
&
|
||||
@endif
|
||||
@if (!$server->settings->is_usable)
|
||||
Not usable by Coolify
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1"></div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
@if ($private_keys->count() === 0)
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class='font-bold dark:text-warning'>No private keys found.</div>
|
||||
<div class="flex items-center gap-1">Before you can add your server, first <x-modal-input
|
||||
buttonTitle="add" title="New Private Key">
|
||||
<livewire:security.private-key.create from="server" />
|
||||
</x-modal-input> a private key
|
||||
or
|
||||
go to the <a class="underline dark:text-white" href="{{ route('onboarding') }}">onboarding</a>
|
||||
page.
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<div>No deployments running.</div>
|
||||
@endforelse
|
||||
</div>
|
||||
@else
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class='font-bold dark:text-warning'>No servers found.</div>
|
||||
<div class="flex items-center gap-1">
|
||||
<x-modal-input buttonTitle="Add" title="New Server" :closeOutside="false">
|
||||
<livewire:server.create />
|
||||
</x-modal-input> your first server
|
||||
or
|
||||
go to the <a class="underline dark:text-white" href="{{ route('onboarding') }}">onboarding</a>
|
||||
page.
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</section>
|
||||
|
||||
@if ($servers->count() > 0 && $projects->count() > 0)
|
||||
<section>
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="pb-2">Deployments</h3>
|
||||
@if (count($deployments_per_server) > 0)
|
||||
<x-loading />
|
||||
@endif
|
||||
<x-modal-confirmation
|
||||
title="Confirm Cleanup Queues?"
|
||||
buttonTitle="Cleanup Queues"
|
||||
isErrorButton
|
||||
submitAction="cleanup_queue"
|
||||
:actions="['All running Deployment Queues will be cleaned up.']"
|
||||
:confirmWithText="false"
|
||||
:confirmWithPassword="false"
|
||||
step2ButtonText="Permanently Cleanup Deployment Queues"
|
||||
:dispatchEvent="true"
|
||||
dispatchEventType="success"
|
||||
dispatchEventMessage="Deployment Queues cleanup started."
|
||||
/>
|
||||
</div>
|
||||
<div wire:poll.3000ms="get_deployments" class="grid grid-cols-1">
|
||||
@forelse ($deployments_per_server as $server_name => $deployments)
|
||||
<h4 class="pb-2">{{ $server_name }}</h4>
|
||||
<div class="grid grid-cols-1 gap-2 lg:grid-cols-3">
|
||||
@foreach ($deployments as $deployment)
|
||||
<a href="{{ data_get($deployment, 'deployment_url') }}" @class([
|
||||
'gap-2 cursor-pointer box group border-l-2 border-dotted',
|
||||
'dark:border-coolgray-300' => data_get($deployment, 'status') === 'queued',
|
||||
'border-yellow-500' => data_get($deployment, 'status') === 'in_progress',
|
||||
])>
|
||||
<div class="flex flex-col justify-center mx-6">
|
||||
<div class="box-title">
|
||||
{{ data_get($deployment, 'application_name') }}
|
||||
</div>
|
||||
@if (data_get($deployment, 'pull_request_id') !== 0)
|
||||
<div class="box-description">
|
||||
PR #{{ data_get($deployment, 'pull_request_id') }}
|
||||
</div>
|
||||
@endif
|
||||
<div class="box-description">
|
||||
{{ str(data_get($deployment, 'status'))->headline() }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1"></div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@empty
|
||||
<div>No deployments running.</div>
|
||||
@endforelse
|
||||
</div>
|
||||
</section>
|
||||
@endif
|
||||
|
||||
|
||||
|
||||
@@ -20,11 +20,12 @@
|
||||
<x-forms.checkbox instantSave id="team.telegram_enabled" label="Enabled" />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input type="password"
|
||||
helper="Get it from the <a class='inline-block underline dark:text-white' href='https://t.me/botfather' target='_blank'>BotFather Bot</a> on Telegram."
|
||||
|
||||
<x-forms.input type="password" autocomplete="new-password"
|
||||
helper="Get it from the <a class='inline-block underline dark:text-white' href='https://t.me/botfather' target='_blank'>BotFather Bot</a> on Telegram."
|
||||
required id="team.telegram_token" label="Token" />
|
||||
<x-forms.input helper="Recommended to add your bot to a group chat and add its Chat ID here." required
|
||||
id="team.telegram_chat_id" label="Chat ID" />
|
||||
id="team.telegram_chat_id" label="Chat ID" />
|
||||
</div>
|
||||
@if (data_get($team, 'telegram_enabled'))
|
||||
<h2 class="mt-4">Subscribe to events</h2>
|
||||
|
||||
@@ -1,92 +1,97 @@
|
||||
<form wire:submit='submit'>
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>Advanced</h2>
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
<x-modal-confirmation title="Confirm Docker Cleanup?" buttonTitle="Trigger Manual Cleanup"
|
||||
submitAction="manualCleanup" :actions="[
|
||||
'Permanently deletes all stopped containers managed by Coolify (as containers are non-persistent, no data will be lost)',
|
||||
'Permanently deletes all unused images',
|
||||
'Clears build cache',
|
||||
'Removes old versions of the Coolify helper image',
|
||||
'Optionally permanently deletes all unused volumes (if enabled in advanced options).',
|
||||
'Optionally permanently deletes all unused networks (if enabled in advanced options).',
|
||||
]" :confirmWithText="false" :confirmWithPassword="false"
|
||||
step2ButtonText="Trigger Docker Cleanup" />
|
||||
</div>
|
||||
<div>Advanced configuration for your server.</div>
|
||||
</div>
|
||||
<div>
|
||||
<x-server.navbar :server="$server" />
|
||||
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'general' }" class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar :server="$server" activeMenu="advanced" />
|
||||
<form wire:submit='submit' class="w-full">
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>Advanced</h2>
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
<x-modal-confirmation title="Confirm Docker Cleanup?" buttonTitle="Trigger Manual Cleanup"
|
||||
isHighlightedButton submitAction="manualCleanup" :actions="[
|
||||
'Permanently deletes all stopped containers managed by Coolify (as containers are non-persistent, no data will be lost)',
|
||||
'Permanently deletes all unused images',
|
||||
'Clears build cache',
|
||||
'Removes old versions of the Coolify helper image',
|
||||
'Optionally permanently deletes all unused volumes (if enabled in advanced options).',
|
||||
'Optionally permanently deletes all unused networks (if enabled in advanced options).',
|
||||
]" :confirmWithText="false"
|
||||
:confirmWithPassword="false" step2ButtonText="Trigger Docker Cleanup" />
|
||||
</div>
|
||||
<div>Advanced configuration for your server.</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap pt-4">
|
||||
<x-forms.input id="server.settings.server_disk_usage_notification_threshold"
|
||||
label="Server disk usage notification threshold (%)" required
|
||||
helper="If the server disk usage exceeds this threshold, Coolify will send a notification to the team members." />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<h3>Docker Cleanup</h3>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-4">
|
||||
@if ($server->settings->force_docker_cleanup)
|
||||
<x-forms.input placeholder="*/10 * * * *" id="server.settings.docker_cleanup_frequency"
|
||||
label="Docker cleanup frequency" required
|
||||
helper="Cron expression for Docker Cleanup.<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every night at midnight." />
|
||||
@else
|
||||
<x-forms.input id="server.settings.docker_cleanup_threshold" label="Docker cleanup threshold (%)"
|
||||
required
|
||||
helper="The Docker cleanup tasks will run when the disk usage exceeds this threshold." />
|
||||
@endif
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox
|
||||
helper="Enabling Force Docker Cleanup or manually triggering a cleanup will perform the following actions:
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap pt-4">
|
||||
<x-forms.input id="serverDiskUsageNotificationThreshold"
|
||||
label="Server disk usage notification threshold (%)" required
|
||||
helper="If the server disk usage exceeds this threshold, Coolify will send a notification to the team members." />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<h3>Docker Cleanup</h3>
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-4">
|
||||
@if ($forceDockerCleanup)
|
||||
<x-forms.input placeholder="*/10 * * * *" id="dockerCleanupFrequency"
|
||||
label="Docker cleanup frequency" required
|
||||
helper="Cron expression for Docker Cleanup.<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every night at midnight." />
|
||||
@else
|
||||
<x-forms.input id="dockerCleanupThreshold" label="Docker cleanup threshold (%)" required
|
||||
helper="The Docker cleanup tasks will run when the disk usage exceeds this threshold." />
|
||||
@endif
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox
|
||||
helper="Enabling Force Docker Cleanup or manually triggering a cleanup will perform the following actions:
|
||||
<ul class='list-disc pl-4 mt-2'>
|
||||
<li>Removes stopped containers manged by Coolify (as containers are none persistent, no data will be lost).</li>
|
||||
<li>Removes stopped containers managed by Coolify (as containers are none persistent, no data will be lost).</li>
|
||||
<li>Deletes unused images.</li>
|
||||
<li>Clears build cache.</li>
|
||||
<li>Removes old versions of the Coolify helper image.</li>
|
||||
<li>Optionally delete unused volumes (if enabled in advanced options).</li>
|
||||
<li>Optionally remove unused networks (if enabled in advanced options).</li>
|
||||
</ul>"
|
||||
instantSave id="server.settings.force_docker_cleanup" label="Force Docker Cleanup" />
|
||||
</div>
|
||||
instantSave id="forceDockerCleanup" label="Force Docker Cleanup" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-2">
|
||||
<span class="dark:text-warning font-bold">Warning: Enable these
|
||||
options only if you fully understand their implications and
|
||||
consequences!</span><br>Improper use will result in data loss and could cause
|
||||
functional issues.
|
||||
</p>
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox instantSave id="server.settings.delete_unused_volumes" label="Delete Unused Volumes"
|
||||
helper="This option will remove all unused Docker volumes during cleanup.<br><br><strong>Warning: Data form stopped containers will be lost!</strong><br><br>Consequences include:<br>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mb-2">
|
||||
<span class="dark:text-warning font-bold">Warning: Enable these
|
||||
options only if you fully understand their implications and
|
||||
consequences!</span><br>Improper use will result in data loss and could cause
|
||||
functional issues.
|
||||
</p>
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox instantSave id="deleteUnusedVolumes" label="Delete Unused Volumes"
|
||||
helper="This option will remove all unused Docker volumes during cleanup.<br><br><strong>Warning: Data form stopped containers will be lost!</strong><br><br>Consequences include:<br>
|
||||
<ul class='list-disc pl-4 mt-2'>
|
||||
<li>Volumes not attached to running containers will be deleted and data will be permanently lost (stopped containers are affected).</li>
|
||||
<li>Data from stopped containers volumes will be permanently lost.</li>
|
||||
<li>No way to recover deleted volume data.</li>
|
||||
</ul>" />
|
||||
<x-forms.checkbox instantSave id="server.settings.delete_unused_networks" label="Delete Unused Networks"
|
||||
helper="This option will remove all unused Docker networks during cleanup.<br><br><strong>Warning: Functionality may be lost and containers may not be able to communicate with each other!</strong><br><br>Consequences include:<br>
|
||||
<x-forms.checkbox instantSave id="deleteUnusedNetworks" label="Delete Unused Networks"
|
||||
helper="This option will remove all unused Docker networks during cleanup.<br><br><strong>Warning: Functionality may be lost and containers may not be able to communicate with each other!</strong><br><br>Consequences include:<br>
|
||||
<ul class='list-disc pl-4 mt-2'>
|
||||
<li>Networks not attached to running containers will be permanently deleted (stopped containers are affected).</li>
|
||||
<li>Custom networks for stopped containers will be permanently deleted.</li>
|
||||
<li>Functionality may be lost and containers may not be able to communicate with each other.</li>
|
||||
</ul>" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<h3>Builds</h3>
|
||||
<div>Customize the build process.</div>
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap pt-4">
|
||||
<x-forms.input id="server.settings.concurrent_builds" label="Number of concurrent builds" required
|
||||
helper="You can specify the number of simultaneous build processes/deployments that should run concurrently." />
|
||||
<x-forms.input id="server.settings.dynamic_timeout" label="Deployment timeout (seconds)" required
|
||||
helper="You can define the maximum duration for a deployment to run before timing it out." />
|
||||
<div class="flex flex-col">
|
||||
<h3>Builds</h3>
|
||||
<div>Customize the build process.</div>
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap pt-4">
|
||||
<x-forms.input id="concurrentBuilds" label="Number of concurrent builds" required
|
||||
helper="You can specify the number of simultaneous build processes/deployments that should run concurrently." />
|
||||
<x-forms.input id="dynamicTimeout" label="Deployment timeout (seconds)" required
|
||||
helper="You can define the maximum duration for a deployment to run before timing it out." />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -1,240 +1,253 @@
|
||||
<div @if ($poll) wire:poll.5000ms='pollData' @endif x-init="$wire.loadData()">
|
||||
<x-forms.select label="Interval" wire:change="setInterval" id="interval">
|
||||
<option value="5">5 minutes (live)</option>
|
||||
<option value="10">10 minutes (live)</option>
|
||||
<option value="30">30 minutes</option>
|
||||
<option value="60">1 hour</option>
|
||||
<option value="720">12 hours</option>
|
||||
<option value="10080">1 week</option>
|
||||
<option value="43200">30 days</option>
|
||||
</x-forms.select>
|
||||
<h4 class="pt-4">CPU (%)</h4>
|
||||
<div wire:ignore id="{!! $chartId !!}-cpu"></div>
|
||||
<div>
|
||||
<x-slot:title>
|
||||
{{ data_get_str($server, 'name')->limit(10) }} > Server Destinations | Coolify
|
||||
</x-slot>
|
||||
<x-server.navbar :server="$server" />
|
||||
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar :server="$server" activeMenu="metrics" />
|
||||
<div class="w-full">
|
||||
<h2>Metrics</h2>
|
||||
<div class="pb-4">Basic metrics for your container.</div>
|
||||
<div @if ($poll) wire:poll.5000ms='pollData' @endif x-init="$wire.loadData()">
|
||||
<x-forms.select label="Interval" wire:change="setInterval" id="interval">
|
||||
<option value="5">5 minutes (live)</option>
|
||||
<option value="10">10 minutes (live)</option>
|
||||
<option value="30">30 minutes</option>
|
||||
<option value="60">1 hour</option>
|
||||
<option value="720">12 hours</option>
|
||||
<option value="10080">1 week</option>
|
||||
<option value="43200">30 days</option>
|
||||
</x-forms.select>
|
||||
<h4 class="pt-4">CPU (%)</h4>
|
||||
<div wire:ignore id="{!! $chartId !!}-cpu"></div>
|
||||
|
||||
<script>
|
||||
checkTheme();
|
||||
const optionsServerCpu = {
|
||||
stroke: {
|
||||
curve: 'straight',
|
||||
},
|
||||
chart: {
|
||||
height: '150px',
|
||||
id: '{!! $chartId !!}-cpu',
|
||||
type: 'area',
|
||||
toolbar: {
|
||||
show: true,
|
||||
tools: {
|
||||
download: false,
|
||||
selection: false,
|
||||
zoom: true,
|
||||
zoomin: false,
|
||||
zoomout: false,
|
||||
pan: false,
|
||||
reset: true
|
||||
},
|
||||
},
|
||||
animations: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false,
|
||||
offsetY: -10,
|
||||
style: {
|
||||
colors: ['#FCD452'],
|
||||
},
|
||||
background: {
|
||||
enabled: false,
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
show: true,
|
||||
borderColor: '',
|
||||
},
|
||||
colors: [baseColor],
|
||||
xaxis: {
|
||||
type: 'datetime',
|
||||
},
|
||||
series: [{
|
||||
name: 'CPU %',
|
||||
data: []
|
||||
}],
|
||||
noData: {
|
||||
text: 'Loading...',
|
||||
style: {
|
||||
color: textColor,
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
marker: {
|
||||
show: false,
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
const serverCpuChart = new ApexCharts(document.getElementById(`{!! $chartId !!}-cpu`),
|
||||
optionsServerCpu);
|
||||
serverCpuChart.render();
|
||||
document.addEventListener('livewire:init', () => {
|
||||
Livewire.on('refreshChartData-{!! $chartId !!}-cpu', (chartData) => {
|
||||
checkTheme();
|
||||
serverCpuChart.updateOptions({
|
||||
series: [{
|
||||
data: chartData[0].seriesData,
|
||||
}],
|
||||
colors: [baseColor],
|
||||
xaxis: {
|
||||
type: 'datetime',
|
||||
labels: {
|
||||
show: true,
|
||||
style: {
|
||||
colors: textColor,
|
||||
}
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
show: true,
|
||||
labels: {
|
||||
show: true,
|
||||
style: {
|
||||
colors: textColor,
|
||||
}
|
||||
}
|
||||
},
|
||||
noData: {
|
||||
text: 'Loading...',
|
||||
style: {
|
||||
color: textColor,
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<h4>Memory (%)</h4>
|
||||
<div wire:ignore id="{!! $chartId !!}-memory"></div>
|
||||
|
||||
<script>
|
||||
checkTheme();
|
||||
const optionsServerMemory = {
|
||||
stroke: {
|
||||
curve: 'straight',
|
||||
},
|
||||
chart: {
|
||||
height: '150px',
|
||||
id: '{!! $chartId !!}-memory',
|
||||
type: 'area',
|
||||
toolbar: {
|
||||
show: true,
|
||||
tools: {
|
||||
download: false,
|
||||
selection: false,
|
||||
zoom: true,
|
||||
zoomin: false,
|
||||
zoomout: false,
|
||||
pan: false,
|
||||
reset: true
|
||||
},
|
||||
},
|
||||
animations: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false,
|
||||
offsetY: -10,
|
||||
style: {
|
||||
colors: ['#FCD452'],
|
||||
},
|
||||
background: {
|
||||
enabled: false,
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
show: true,
|
||||
borderColor: '',
|
||||
},
|
||||
colors: [baseColor],
|
||||
xaxis: {
|
||||
type: 'datetime',
|
||||
labels: {
|
||||
show: true,
|
||||
style: {
|
||||
colors: textColor,
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
name: "Memory (%)",
|
||||
data: []
|
||||
}],
|
||||
noData: {
|
||||
text: 'Loading...',
|
||||
style: {
|
||||
color: textColor,
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
marker: {
|
||||
show: false,
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
const serverMemoryChart = new ApexCharts(document.getElementById(`{!! $chartId !!}-memory`),
|
||||
optionsServerMemory);
|
||||
serverMemoryChart.render();
|
||||
document.addEventListener('livewire:init', () => {
|
||||
Livewire.on('refreshChartData-{!! $chartId !!}-memory', (chartData) => {
|
||||
<script>
|
||||
checkTheme();
|
||||
serverMemoryChart.updateOptions({
|
||||
series: [{
|
||||
data: chartData[0].seriesData,
|
||||
}],
|
||||
const optionsServerCpu = {
|
||||
stroke: {
|
||||
curve: 'straight',
|
||||
},
|
||||
chart: {
|
||||
height: '150px',
|
||||
id: '{!! $chartId !!}-cpu',
|
||||
type: 'area',
|
||||
toolbar: {
|
||||
show: true,
|
||||
tools: {
|
||||
download: false,
|
||||
selection: false,
|
||||
zoom: true,
|
||||
zoomin: false,
|
||||
zoomout: false,
|
||||
pan: false,
|
||||
reset: true
|
||||
},
|
||||
},
|
||||
animations: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false,
|
||||
offsetY: -10,
|
||||
style: {
|
||||
colors: ['#FCD452'],
|
||||
},
|
||||
background: {
|
||||
enabled: false,
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
show: true,
|
||||
borderColor: '',
|
||||
},
|
||||
colors: [baseColor],
|
||||
xaxis: {
|
||||
type: 'datetime',
|
||||
labels: {
|
||||
show: true,
|
||||
style: {
|
||||
colors: textColor,
|
||||
}
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
min: 0,
|
||||
show: true,
|
||||
labels: {
|
||||
show: true,
|
||||
style: {
|
||||
colors: textColor,
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
name: 'CPU %',
|
||||
data: []
|
||||
}],
|
||||
noData: {
|
||||
text: 'Loading...',
|
||||
style: {
|
||||
color: textColor,
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
marker: {
|
||||
show: false,
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
const serverCpuChart = new ApexCharts(document.getElementById(`{!! $chartId !!}-cpu`),
|
||||
optionsServerCpu);
|
||||
serverCpuChart.render();
|
||||
document.addEventListener('livewire:init', () => {
|
||||
Livewire.on('refreshChartData-{!! $chartId !!}-cpu', (chartData) => {
|
||||
checkTheme();
|
||||
serverCpuChart.updateOptions({
|
||||
series: [{
|
||||
data: chartData[0].seriesData,
|
||||
}],
|
||||
colors: [baseColor],
|
||||
xaxis: {
|
||||
type: 'datetime',
|
||||
labels: {
|
||||
show: true,
|
||||
style: {
|
||||
colors: textColor,
|
||||
}
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
show: true,
|
||||
labels: {
|
||||
show: true,
|
||||
style: {
|
||||
colors: textColor,
|
||||
}
|
||||
}
|
||||
},
|
||||
noData: {
|
||||
text: 'Loading...',
|
||||
style: {
|
||||
color: textColor,
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<h4>Memory (%)</h4>
|
||||
<div wire:ignore id="{!! $chartId !!}-memory"></div>
|
||||
|
||||
<script>
|
||||
checkTheme();
|
||||
const optionsServerMemory = {
|
||||
stroke: {
|
||||
curve: 'straight',
|
||||
},
|
||||
chart: {
|
||||
height: '150px',
|
||||
id: '{!! $chartId !!}-memory',
|
||||
type: 'area',
|
||||
toolbar: {
|
||||
show: true,
|
||||
tools: {
|
||||
download: false,
|
||||
selection: false,
|
||||
zoom: true,
|
||||
zoomin: false,
|
||||
zoomout: false,
|
||||
pan: false,
|
||||
reset: true
|
||||
},
|
||||
},
|
||||
animations: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false,
|
||||
offsetY: -10,
|
||||
style: {
|
||||
colors: ['#FCD452'],
|
||||
},
|
||||
background: {
|
||||
enabled: false,
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
show: true,
|
||||
borderColor: '',
|
||||
},
|
||||
colors: [baseColor],
|
||||
xaxis: {
|
||||
type: 'datetime',
|
||||
labels: {
|
||||
show: true,
|
||||
style: {
|
||||
colors: textColor,
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
name: "Memory (%)",
|
||||
data: []
|
||||
}],
|
||||
noData: {
|
||||
text: 'Loading...',
|
||||
style: {
|
||||
color: textColor,
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
marker: {
|
||||
show: false,
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
const serverMemoryChart = new ApexCharts(document.getElementById(`{!! $chartId !!}-memory`),
|
||||
optionsServerMemory);
|
||||
serverMemoryChart.render();
|
||||
document.addEventListener('livewire:init', () => {
|
||||
Livewire.on('refreshChartData-{!! $chartId !!}-memory', (chartData) => {
|
||||
checkTheme();
|
||||
serverMemoryChart.updateOptions({
|
||||
series: [{
|
||||
data: chartData[0].seriesData,
|
||||
}],
|
||||
colors: [baseColor],
|
||||
xaxis: {
|
||||
type: 'datetime',
|
||||
labels: {
|
||||
show: true,
|
||||
style: {
|
||||
colors: textColor,
|
||||
}
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
min: 0,
|
||||
show: true,
|
||||
labels: {
|
||||
show: true,
|
||||
style: {
|
||||
colors: textColor,
|
||||
}
|
||||
}
|
||||
},
|
||||
noData: {
|
||||
text: 'Loading...',
|
||||
style: {
|
||||
color: textColor,
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,42 +1,54 @@
|
||||
<div>
|
||||
<div class="flex gap-1 items-center">
|
||||
<h2>Cloudflare Tunnels</h2>
|
||||
<x-helper class="inline-flex"
|
||||
helper="If you are using Cloudflare Tunnels, enable this. It will proxy all SSH requests to your server through Cloudflare.<br> You then can close your server's SSH port in the firewall of your hosting provider.<br><span class='dark:text-warning'>If you choose manual configuration, Coolify does not install or set up Cloudflare (cloudflared) on your server.</span>" />
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 pt-6">
|
||||
@if ($server->settings->is_cloudflare_tunnel)
|
||||
<div class="w-64">
|
||||
<x-forms.checkbox instantSave id="server.settings.is_cloudflare_tunnel"
|
||||
label="Enabled" />
|
||||
</div>
|
||||
@elseif (!$server->isFunctional())
|
||||
<div
|
||||
class="p-4 mb-4 w-full text-sm text-yellow-800 bg-yellow-100 rounded dark:bg-yellow-900 dark:text-yellow-300">
|
||||
To <span class="font-semibold">automatically</span> configure Cloudflare Tunnels, please
|
||||
validate your server first.</span> Then you will need a Cloudflare token and an SSH
|
||||
domain configured.
|
||||
<br />
|
||||
To <span class="font-semibold">manually</span> configure Cloudflare Tunnels, please
|
||||
click <span wire:click="manualCloudflareConfig"
|
||||
class="underline cursor-pointer">here</span>, then you should validate the server.
|
||||
<br /><br />
|
||||
For more information, please read our <a
|
||||
href="https://coolify.io/docs/knowledge-base/cloudflare/tunnels/" target="_blank"
|
||||
class="font-medium underline hover:text-yellow-600 dark:hover:text-yellow-200">documentation</a>.
|
||||
</div>
|
||||
@endif
|
||||
@if (!$server->settings->is_cloudflare_tunnel && $server->isFunctional())
|
||||
<x-modal-input buttonTitle="Automated Configuration" title="Cloudflare Tunnels"
|
||||
class="w-full" :closeOutside="false">
|
||||
<livewire:server.configure-cloudflare-tunnels :server_id="$server->id" />
|
||||
</x-modal-input>
|
||||
@endif
|
||||
@if ($server->isFunctional() && !$server->settings->is_cloudflare_tunnel)
|
||||
<div wire:click="manualCloudflareConfig" class="w-full underline cursor-pointer">
|
||||
I have configured Cloudflare Tunnels manually
|
||||
</div>
|
||||
@endif
|
||||
<x-slot:title>
|
||||
{{ data_get_str($server, 'name')->limit(10) }} > Cloudflare Tunnels | Coolify
|
||||
</x-slot>
|
||||
<x-server.navbar :server="$server" />
|
||||
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar :server="$server" activeMenu="cloudflare-tunnels" />
|
||||
<div class="w-full">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex gap-1 items-center">
|
||||
<h2>Cloudflare Tunnels</h2>
|
||||
<x-helper class="inline-flex"
|
||||
helper="If you are using Cloudflare Tunnels, enable this. It will proxy all SSH requests to your server through Cloudflare.<br> You then can close your server's SSH port in the firewall of your hosting provider.<br><span class='dark:text-warning'>If you choose manual configuration, Coolify does not install or set up Cloudflare (cloudflared) on your server.</span>" />
|
||||
</div>
|
||||
<div>Secure your servers with Cloudflare Tunnels</div>
|
||||
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 pt-6">
|
||||
@if ($isCloudflareTunnelsEnabled)
|
||||
<div class="w-64">
|
||||
<x-forms.checkbox instantSave id="isCloudflareTunnelsEnabled" label="Enabled" />
|
||||
</div>
|
||||
@elseif (!$server->isFunctional())
|
||||
<div
|
||||
class="p-4 mb-4 w-full text-sm text-yellow-800 bg-yellow-100 rounded dark:bg-yellow-900 dark:text-yellow-300">
|
||||
To <span class="font-semibold">automatically</span> configure Cloudflare Tunnels, please
|
||||
validate your server first.</span> Then you will need a Cloudflare token and an SSH
|
||||
domain configured.
|
||||
<br />
|
||||
To <span class="font-semibold">manually</span> configure Cloudflare Tunnels, please
|
||||
click <span wire:click="manualCloudflareConfig" class="underline cursor-pointer">here</span>,
|
||||
then you should validate the server.
|
||||
<br /><br />
|
||||
For more information, please read our <a
|
||||
href="https://coolify.io/docs/knowledge-base/cloudflare/tunnels/" target="_blank"
|
||||
class="font-medium underline hover:text-yellow-600 dark:hover:text-yellow-200">documentation</a>.
|
||||
</div>
|
||||
@endif
|
||||
@if (!$isCloudflareTunnelsEnabled && $server->isFunctional())
|
||||
<h4>Configuration</h4>
|
||||
<div class="flex gap-2">
|
||||
<x-modal-input buttonTitle="Automated" title="Cloudflare Tunnels" :closeOutside="false"
|
||||
isHighlightedButton>
|
||||
<livewire:server.configure-cloudflare-tunnels :server_id="$server->id" />
|
||||
</x-modal-input>
|
||||
<x-forms.button wire:click="manualCloudflareConfig" class="w-20">
|
||||
Manual
|
||||
</x-forms.button>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,22 +1,31 @@
|
||||
<div>
|
||||
@if ($server->id !== 0)
|
||||
<h2>Danger Zone</h2>
|
||||
<div class="">Woah. I hope you know what are you doing.</div>
|
||||
<h4 class="pt-4">Delete Server</h4>
|
||||
<div class="pb-4">This will remove this server from Coolify. Beware! There is no coming
|
||||
back!
|
||||
<x-slot:title>
|
||||
{{ data_get_str($server, 'name')->limit(10) }} > Delete Server | Coolify
|
||||
</x-slot>
|
||||
<x-server.navbar :server="$server" />
|
||||
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar :server="$server" activeMenu="danger" />
|
||||
<div class="w-full">
|
||||
@if ($server->id !== 0)
|
||||
<h2>Danger Zone</h2>
|
||||
<div class="">Woah. I hope you know what are you doing.</div>
|
||||
<h4 class="pt-4">Delete Server</h4>
|
||||
<div class="pb-4">This will remove this server from Coolify. Beware! There is no coming
|
||||
back!
|
||||
</div>
|
||||
@if ($server->definedResources()->count() > 0)
|
||||
<div class="pb-2 text-red-500">You need to delete all resources before deleting this server.</div>
|
||||
<x-modal-confirmation title="Confirm Server Deletion?" isErrorButton buttonTitle="Delete"
|
||||
submitAction="delete" :actions="['This server will be permanently deleted.']" confirmationText="{{ $server->name }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Server Name below"
|
||||
shortConfirmationLabel="Server Name" step3ButtonText="Permanently Delete" />
|
||||
@else
|
||||
<x-modal-confirmation title="Confirm Server Deletion?" isErrorButton buttonTitle="Delete"
|
||||
submitAction="delete" :actions="['This server will be permanently deleted.']" confirmationText="{{ $server->name }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Server Name below"
|
||||
shortConfirmationLabel="Server Name" step3ButtonText="Permanently Delete" />
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
@if ($server->definedResources()->count() > 0)
|
||||
<div class="pb-2 text-red-500">You need to delete all resources before deleting this server.</div>
|
||||
<x-modal-confirmation title="Confirm Server Deletion?" isErrorButton buttonTitle="Delete" submitAction="delete"
|
||||
:actions="['This server will be permanently deleted.']" confirmationText="{{ $server->name }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Server Name below"
|
||||
shortConfirmationLabel="Server Name" step3ButtonText="Permanently Delete" />
|
||||
@else
|
||||
<x-modal-confirmation title="Confirm Server Deletion?" isErrorButton buttonTitle="Delete"
|
||||
submitAction="delete" :actions="['This server will be permanently deleted.']" confirmationText="{{ $server->name }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Server Name below"
|
||||
shortConfirmationLabel="Server Name" step3ButtonText="Permanently Delete" />
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,48 @@
|
||||
<x-slot:title>
|
||||
{{ data_get_str($server, 'name')->limit(10) }} > Server Destinations | Coolify
|
||||
</x-slot>
|
||||
{{-- <x-server.navbar :server="$server" :parameters="$parameters" /> --}}
|
||||
<livewire:destination.show :server="$server" />
|
||||
<x-server.navbar :server="$server" />
|
||||
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar :server="$server" activeMenu="destinations" />
|
||||
<div class="w-full">
|
||||
@if ($server->isFunctional())
|
||||
<div class="flex items-end gap-2">
|
||||
<h2>Destinations</h2>
|
||||
<x-modal-input buttonTitle="+ Add" title="New Destination">
|
||||
<livewire:destination.new.docker :server_id="$server->id" />
|
||||
</x-modal-input>
|
||||
<x-forms.button isHighlighted wire:click='scan'>Scan for Destinations</x-forms.button>
|
||||
</div>
|
||||
<div>Destinations are used to segregate resources by network.</div>
|
||||
<h4 class="pt-4 pb-2">Available Destinations</h4>
|
||||
<div class="flex gap-2">
|
||||
@foreach ($server->standaloneDockers as $docker)
|
||||
<a href="{{ route('destination.show', ['destination_uuid' => data_get($docker, 'uuid')]) }}">
|
||||
<x-forms.button>{{ data_get($docker, 'network') }} </x-forms.button>
|
||||
</a>
|
||||
@endforeach
|
||||
@foreach ($server->swarmDockers as $docker)
|
||||
<a href="{{ route('destination.show', ['destination_uuid' => data_get($docker, 'uuid')]) }}">
|
||||
<x-forms.button>{{ data_get($docker, 'network') }} </x-forms.button>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@if ($networks->count() > 0)
|
||||
<div class="pt-2">
|
||||
<h3 class="pb-4">Found Destinations</h3>
|
||||
<div class="flex flex-wrap gap-2 ">
|
||||
@foreach ($networks as $network)
|
||||
<div class="min-w-fit">
|
||||
<x-forms.button wire:click="add('{{ data_get($network, 'Name') }}')">Add
|
||||
{{ data_get($network, 'Name') }}</x-forms.button>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<div>Server is not validated. Validate first.</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,120 +1,118 @@
|
||||
<div>
|
||||
<x-slot:title>
|
||||
{{ data_get_str($server, 'name')->limit(10) }} > Server LogDrains | Coolify
|
||||
{{ data_get_str($server, 'name')->limit(10) }} > Server Log Drains | Coolify
|
||||
</x-slot>
|
||||
{{-- <x-server.navbar :server="$server" :parameters="$parameters" /> --}}
|
||||
@if ($server->isFunctional())
|
||||
<h2>Log Drains</h2>
|
||||
<div class="pb-4">Sends service logs to 3rd party tools.</div>
|
||||
<div class="flex flex-col gap-4 pt-4">
|
||||
<div class="p-4 border dark:border-coolgray-300">
|
||||
<form wire:submit='submit("newrelic")' class="flex flex-col">
|
||||
<h3>New Relic</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("newrelic")'
|
||||
id="server.settings.is_logdrain_newrelic_enabled" label="Enabled" />
|
||||
</div>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
@if ($server->isLogDrainEnabled())
|
||||
<x-forms.input disabled type="password" required
|
||||
id="server.settings.logdrain_newrelic_license_key" label="License Key" />
|
||||
<x-forms.input disabled required id="server.settings.logdrain_newrelic_base_uri"
|
||||
placeholder="https://log-api.eu.newrelic.com/log/v1"
|
||||
helper="For EU use: https://log-api.eu.newrelic.com/log/v1<br>For US use: https://log-api.newrelic.com/log/v1"
|
||||
label="Endpoint" />
|
||||
<x-server.navbar :server="$server" />
|
||||
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar :server="$server" activeMenu="log-drains" />
|
||||
<div class="w-full">
|
||||
@if ($server->isFunctional())
|
||||
<div class="flex gap-2 items-center">
|
||||
<h2>Log Drains</h2>
|
||||
<x-loading wire:target="instantSave" wire:loading.delay />
|
||||
</div>
|
||||
<div class="">Sends service logs to 3rd party tools.</div>
|
||||
<div class="flex flex-col gap-4 pt-4">
|
||||
<div class="p-4 border dark:border-coolgray-300">
|
||||
<form wire:submit='submit("newrelic")' class="flex flex-col">
|
||||
<h3>New Relic</h3>
|
||||
<div class="w-32">
|
||||
@if ($isLogDrainAxiomEnabled || $isLogDrainCustomEnabled)
|
||||
<x-forms.checkbox disabled id="isLogDrainNewRelicEnabled" label="Enabled" />
|
||||
@else
|
||||
<x-forms.checkbox instantSave id="isLogDrainNewRelicEnabled" label="Enabled" />
|
||||
@endif
|
||||
</div>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
@if ($server->isLogDrainEnabled())
|
||||
<x-forms.input disabled type="password" required id="logDrainNewRelicLicenseKey"
|
||||
label="License Key" />
|
||||
<x-forms.input disabled required id="logDrainNewRelicBaseUri"
|
||||
placeholder="https://log-api.eu.newrelic.com/log/v1"
|
||||
helper="For EU use: https://log-api.eu.newrelic.com/log/v1<br>For US use: https://log-api.newrelic.com/log/v1"
|
||||
label="Endpoint" />
|
||||
@else
|
||||
<x-forms.input type="password" required id="logDrainNewRelicLicenseKey"
|
||||
label="License Key" />
|
||||
<x-forms.input required id="logDrainNewRelicBaseUri"
|
||||
placeholder="https://log-api.eu.newrelic.com/log/v1"
|
||||
helper="For EU use: https://log-api.eu.newrelic.com/log/v1<br>For US use: https://log-api.newrelic.com/log/v1"
|
||||
label="Endpoint" />
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<h3>Axiom</h3>
|
||||
<div class="w-32">
|
||||
@if ($isLogDrainNewRelicEnabled || $isLogDrainCustomEnabled)
|
||||
<x-forms.checkbox disabled id="isLogDrainAxiomEnabled" label="Enabled" />
|
||||
@else
|
||||
<x-forms.input type="password" required
|
||||
id="server.settings.logdrain_newrelic_license_key" label="License Key" />
|
||||
<x-forms.input required id="server.settings.logdrain_newrelic_base_uri"
|
||||
placeholder="https://log-api.eu.newrelic.com/log/v1"
|
||||
helper="For EU use: https://log-api.eu.newrelic.com/log/v1<br>For US use: https://log-api.newrelic.com/log/v1"
|
||||
label="Endpoint" />
|
||||
<x-forms.checkbox instantSave id="isLogDrainAxiomEnabled" label="Enabled" />
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<h3>Axiom</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("axiom")' id="server.settings.is_logdrain_axiom_enabled"
|
||||
label="Enabled" />
|
||||
</div>
|
||||
<form wire:submit='submit("axiom")' class="flex flex-col">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
@if ($server->isLogDrainEnabled())
|
||||
<x-forms.input disabled type="password" required
|
||||
id="server.settings.logdrain_axiom_api_key" label="API Key" />
|
||||
<x-forms.input disabled required id="server.settings.logdrain_axiom_dataset_name"
|
||||
label="Dataset Name" />
|
||||
<form wire:submit='submit("axiom")' class="flex flex-col">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
@if ($server->isLogDrainEnabled())
|
||||
<x-forms.input disabled type="password" required id="logDrainAxiomApiKey"
|
||||
label="API Key" />
|
||||
<x-forms.input disabled required id="logDrainAxiomDatasetName"
|
||||
label="Dataset Name" />
|
||||
@else
|
||||
<x-forms.input type="password" required id="logDrainAxiomApiKey"
|
||||
label="API Key" />
|
||||
<x-forms.input required id="logDrainAxiomDatasetName" label="Dataset Name" />
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
<h3>Custom FluentBit</h3>
|
||||
<div class="w-32">
|
||||
@if ($isLogDrainNewRelicEnabled || $isLogDrainAxiomEnabled)
|
||||
<x-forms.checkbox disabled id="isLogDrainCustomEnabled" label="Enabled" />
|
||||
@else
|
||||
<x-forms.input type="password" required id="server.settings.logdrain_axiom_api_key"
|
||||
label="API Key" />
|
||||
<x-forms.input required id="server.settings.logdrain_axiom_dataset_name"
|
||||
label="Dataset Name" />
|
||||
<x-forms.checkbox instantSave id="isLogDrainCustomEnabled" label="Enabled" />
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
{{-- <h3>Highlight.io</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("highlight")'
|
||||
id="server.settings.is_logdrain_highlight_enabled" label="Enabled" />
|
||||
</div>
|
||||
<form wire:submit='submit("highlight")' class="flex flex-col">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
<x-forms.input type="password" required id="server.settings.logdrain_highlight_project_id"
|
||||
label="Project Id" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form> --}}
|
||||
<h3>Custom FluentBit configuration</h3>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave='instantSave("custom")'
|
||||
id="server.settings.is_logdrain_custom_enabled" label="Enabled" />
|
||||
</div>
|
||||
<form wire:submit='submit("custom")' class="flex flex-col">
|
||||
<div class="flex flex-col gap-4">
|
||||
@if ($server->isLogDrainEnabled())
|
||||
<x-forms.textarea disabled rows="6" required
|
||||
id="server.settings.logdrain_custom_config" label="Custom FluentBit Configuration" />
|
||||
<x-forms.textarea disabled id="server.settings.logdrain_custom_config_parser"
|
||||
label="Custom Parser Configuration" />
|
||||
@else
|
||||
<x-forms.textarea rows="6" required id="server.settings.logdrain_custom_config"
|
||||
label="Custom FluentBit Configuration" />
|
||||
<x-forms.textarea id="server.settings.logdrain_custom_config_parser"
|
||||
label="Custom Parser Configuration" />
|
||||
@endif
|
||||
<form wire:submit='submit("custom")' class="flex flex-col">
|
||||
<div class="flex flex-col gap-4">
|
||||
@if ($server->isLogDrainEnabled())
|
||||
<x-forms.textarea disabled rows="6" required id="logDrainCustomConfig"
|
||||
label="Custom FluentBit Configuration" />
|
||||
<x-forms.textarea disabled id="logDrainCustomConfigParser"
|
||||
label="Custom Parser Configuration" />
|
||||
@else
|
||||
<x-forms.textarea rows="6" required id="logDrainCustomConfig"
|
||||
label="Custom FluentBit Configuration" />
|
||||
<x-forms.textarea id="logDrainCustomConfigParser"
|
||||
label="Custom Parser Configuration" />
|
||||
@endif
|
||||
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<div class="flex justify-end gap-4 pt-6">
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div>Server is not validated. Validate first.</div>
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
<div>Server is not validated. Validate first.</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,43 @@
|
||||
<div>
|
||||
<x-slot:title>
|
||||
Server Connection | Coolify
|
||||
{{ data_get_str($server, 'name')->limit(10) }} > Server Connection | Coolify
|
||||
</x-slot>
|
||||
<livewire:server.show-private-key :server="$server" :privateKeys="$privateKeys" />
|
||||
<x-server.navbar :server="$server" />
|
||||
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar :server="$server" activeMenu="private-key" />
|
||||
<div class="w-full">
|
||||
<div class="flex items-end gap-2">
|
||||
<h2>Private Key</h2>
|
||||
<x-modal-input buttonTitle="+ Add" title="New Private Key">
|
||||
<livewire:security.private-key.create />
|
||||
</x-modal-input>
|
||||
<x-forms.button isHighlighted wire:click.prevent='checkConnection'>
|
||||
Check connection
|
||||
</x-forms.button>
|
||||
</div>
|
||||
<div class="pb-4">Change your server's private key.</div>
|
||||
<div class="grid xl:grid-cols-2 grid-cols-1 gap-2">
|
||||
@forelse ($privateKeys as $private_key)
|
||||
<div
|
||||
class="box-without-bg justify-between dark:bg-coolgray-100 bg-white items-center flex flex-col gap-2">
|
||||
<div class="flex flex-col w-full">
|
||||
<div class="box-title">{{ $private_key->name }}</div>
|
||||
<div class="box-description">{{ $private_key->description }}</div>
|
||||
</div>
|
||||
@if (data_get($server, 'privateKey.uuid') !== $private_key->uuid)
|
||||
<x-forms.button class="w-full" wire:click='setPrivateKey({{ $private_key->id }})'>
|
||||
Use this key
|
||||
</x-forms.button>
|
||||
@else
|
||||
<x-forms.button class="w-full" disabled>
|
||||
Currently used
|
||||
</x-forms.button>
|
||||
@endif
|
||||
</div>
|
||||
@empty
|
||||
<div>No private keys found. </div>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</x-slot>
|
||||
<x-server.navbar :server="$server" :parameters="$parameters" />
|
||||
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar :server="$server" :parameters="$parameters" />
|
||||
<x-server.sidebar-proxy :server="$server" :parameters="$parameters" />
|
||||
<div class="w-full">
|
||||
@if ($server->isFunctional())
|
||||
<div class="flex gap-2">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</x-slot>
|
||||
<x-server.navbar :server="$server" :parameters="$parameters" />
|
||||
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar :server="$server" :parameters="$parameters" />
|
||||
<x-server.sidebar-proxy :server="$server" :parameters="$parameters" />
|
||||
<div class="w-full">
|
||||
<h2 class="pb-4">Logs</h2>
|
||||
<livewire:project.shared.get-logs :server="$server" container="coolify-proxy" />
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<x-server.navbar :server="$server" :parameters="$parameters" />
|
||||
@if ($server->isFunctional())
|
||||
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar :server="$server" :parameters="$parameters" />
|
||||
<x-server.sidebar-proxy :server="$server" :parameters="$parameters" />
|
||||
<div class="w-full">
|
||||
<livewire:server.proxy :server="$server" />
|
||||
</div>
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
<div>
|
||||
<div class="flex items-end gap-2">
|
||||
<h2>Private Key</h2>
|
||||
<x-modal-input buttonTitle="+ Add" title="New Private Key">
|
||||
<livewire:security.private-key.create />
|
||||
</x-modal-input>
|
||||
<x-forms.button wire:click.prevent='checkConnection'>
|
||||
Check connection
|
||||
</x-forms.button>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="pb-4">Change your server's private key.</div>
|
||||
</div>
|
||||
<div class="grid xl:grid-cols-2 grid-cols-1 gap-2">
|
||||
@forelse ($privateKeys as $private_key)
|
||||
<div class="box-without-bg justify-between dark:bg-coolgray-100 bg-white items-center flex flex-col gap-2">
|
||||
<div class="flex flex-col w-full">
|
||||
<div class="box-title">{{ $private_key->name }}</div>
|
||||
<div class="box-description">{{ $private_key->description }}</div>
|
||||
</div>
|
||||
@if (data_get($server, 'privateKey.uuid') !== $private_key->uuid)
|
||||
<x-forms.button class="w-full" wire:click='setPrivateKey({{ $private_key->id }})'>
|
||||
Use this key
|
||||
</x-forms.button>
|
||||
@else
|
||||
<x-forms.button class="w-full" disabled>
|
||||
Currently used
|
||||
</x-forms.button>
|
||||
@endif
|
||||
</div>
|
||||
@empty
|
||||
<div>No private keys found. </div>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
@@ -2,71 +2,237 @@
|
||||
<x-slot:title>
|
||||
{{ data_get_str($server, 'name')->limit(10) }} > Server Configurations | Coolify
|
||||
</x-slot>
|
||||
<x-server.navbar :server="$server" :parameters="$parameters" />
|
||||
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'general' }" class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<div class="flex flex-col items-start gap-2 min-w-fit">
|
||||
<a class="menu-item" :class="activeTab === 'general' && 'menu-item-active'"
|
||||
@click.prevent="activeTab = 'general'; window.location.hash = 'general'" href="#">General</a>
|
||||
@if ($server->isFunctional())
|
||||
<a class="menu-item" :class="activeTab === 'advanced' && 'menu-item-active'"
|
||||
@click.prevent="activeTab = 'advanced'; window.location.hash = 'advanced'" href="#">Advanced
|
||||
</a>
|
||||
@endif
|
||||
<a class="menu-item" :class="activeTab === 'private-key' && 'menu-item-active'"
|
||||
@click.prevent="activeTab = 'private-key'; window.location.hash = 'private-key'" href="#">Private
|
||||
Key</a>
|
||||
@if ($server->isFunctional())
|
||||
<a class="menu-item" :class="activeTab === 'cloudflare-tunnels' && 'menu-item-active'"
|
||||
@click.prevent="activeTab = 'cloudflare-tunnels'; window.location.hash = 'cloudflare-tunnels'"
|
||||
href="#">Cloudflare Tunnels</a>
|
||||
<a class="menu-item" :class="activeTab === 'destinations' && 'menu-item-active'"
|
||||
@click.prevent="activeTab = 'destinations'; window.location.hash = 'destinations'"
|
||||
href="#">Destinations</a>
|
||||
<a class="menu-item" :class="activeTab === 'log-drains' && 'menu-item-active'"
|
||||
@click.prevent="activeTab = 'log-drains'; window.location.hash = 'log-drains'" href="#">Log
|
||||
Drains</a>
|
||||
<a class="menu-item" :class="activeTab === 'metrics' && 'menu-item-active'"
|
||||
@click.prevent="activeTab = 'metrics'; window.location.hash = 'metrics'" href="#">Metrics</a>
|
||||
@endif
|
||||
@if (!$server->isLocalhost())
|
||||
<a class="menu-item" :class="activeTab === 'danger' && 'menu-item-active'"
|
||||
@click.prevent="activeTab = 'danger'; window.location.hash = 'danger'" href="#">Danger</a>
|
||||
@endif
|
||||
</div>
|
||||
<x-server.navbar :server="$server" />
|
||||
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-server.sidebar :server="$server" activeMenu="general" />
|
||||
<div class="w-full">
|
||||
<div x-cloak x-show="activeTab === 'general'" class="h-full">
|
||||
<livewire:server.form :server="$server" />
|
||||
</div>
|
||||
<div x-cloak x-show="activeTab === 'advanced'" class="h-full">
|
||||
<livewire:server.advanced :server="$server" />
|
||||
</div>
|
||||
<div x-cloak x-show="activeTab === 'private-key'" class="h-full">
|
||||
<livewire:server.private-key.show :server="$server" />
|
||||
</div>
|
||||
<div x-cloak x-show="activeTab === 'cloudflare-tunnels'" class="h-full">
|
||||
<livewire:server.cloudflare-tunnels :server="$server" />
|
||||
</div>
|
||||
<div x-cloak x-show="activeTab === 'destinations'" class="h-full">
|
||||
<livewire:server.destination.show :server="$server" />
|
||||
</div>
|
||||
<div x-cloak x-show="activeTab === 'log-drains'" class="h-full">
|
||||
<livewire:server.log-drains :server="$server" />
|
||||
</div>
|
||||
<div x-cloak x-show="activeTab === 'metrics'" class="h-full">
|
||||
@if ($server->isFunctional() && $server->isMetricsEnabled())
|
||||
<h2>Metrics</h2>
|
||||
<div class="pb-4">Basic metrics for your container.</div>
|
||||
<div>
|
||||
<livewire:server.charts :server="$server" />
|
||||
</div>
|
||||
@else
|
||||
No metrics available.
|
||||
@endif
|
||||
</div>
|
||||
@if (!$server->isLocalhost())
|
||||
<div x-cloak x-show="activeTab === 'danger'" class="h-full">
|
||||
<livewire:server.delete :server="$server" />
|
||||
<form wire:submit.prevent='submit' class="flex flex-col">
|
||||
<div class="flex gap-2">
|
||||
<h2>General</h2>
|
||||
@if ($server->id === 0)
|
||||
<x-modal-confirmation title="Confirm Server Settings Change?" buttonTitle="Save"
|
||||
submitAction="submit" :actions="[
|
||||
'If you missconfigure the server, you could lose a lot of functionalities of Coolify.',
|
||||
]" :confirmWithText="false" :confirmWithPassword="false"
|
||||
step2ButtonText="Save" />
|
||||
@else
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
@if ($server->isFunctional())
|
||||
<x-slide-over closeWithX fullScreen>
|
||||
<x-slot:title>Validate & configure</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:server.validate-and-install :server="$server" ask />
|
||||
</x-slot:content>
|
||||
<x-forms.button @click="slideOverOpen=true" wire:click.prevent='validateServer'
|
||||
isHighlighted>
|
||||
Revalidate server
|
||||
</x-forms.button>
|
||||
</x-slide-over>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
@if ($server->isFunctional())
|
||||
Server is reachable and validated.
|
||||
@else
|
||||
You can't use this server until it is validated.
|
||||
@endif
|
||||
@if ((!$isReachable || !$isUsable) && $server->id !== 0)
|
||||
<x-slide-over closeWithX fullScreen>
|
||||
<x-slot:title>Validate & configure</x-slot:title>
|
||||
<x-slot:content>
|
||||
<livewire:server.validate-and-install :server="$server" />
|
||||
</x-slot:content>
|
||||
<x-forms.button @click="slideOverOpen=true"
|
||||
class="mt-8 mb-4 w-full font-bold box-without-bg bg-coollabs hover:bg-coollabs-100"
|
||||
wire:click.prevent='validateServer' isHighlighted>
|
||||
Validate Server & Install Docker Engine
|
||||
</x-forms.button>
|
||||
</x-slide-over>
|
||||
@if ($server->validation_logs)
|
||||
<h4>Previous Validation Logs</h4>
|
||||
<div class="pb-8">
|
||||
{!! $server->validation_logs !!}
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
@if ((!$isReachable || !$isUsable) && $server->id === 0)
|
||||
<x-forms.button class="mt-8 mb-4 font-bold box-without-bg bg-coollabs hover:bg-coollabs-100"
|
||||
wire:click.prevent='checkLocalhostConnection' isHighlighted>
|
||||
Validate Server
|
||||
</x-forms.button>
|
||||
@endif
|
||||
@if ($server->isForceDisabled() && isCloud())
|
||||
<div class="pt-4 font-bold text-red-500">The system has disabled the server because you have
|
||||
exceeded the
|
||||
number of servers for which you have paid.</div>
|
||||
@endif
|
||||
<div class="flex flex-col gap-2 pt-4">
|
||||
<div class="flex flex-col gap-2 w-full lg:flex-row">
|
||||
<x-forms.input id="name" label="Name" required />
|
||||
<x-forms.input id="description" label="Description" />
|
||||
@if (!$isSwarmWorker && !$isBuildServer)
|
||||
<x-forms.input placeholder="https://example.com" id="wildcard_domain"
|
||||
label="Wildcard Domain"
|
||||
helper='A wildcard domain allows you to receive a randomly generated domain for your new applications. <br><br>For instance, if you set "https://example.com" as your wildcard domain, your applications will receive domains like "https://randomId.example.com".' />
|
||||
@endif
|
||||
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 w-full lg:flex-row">
|
||||
<x-forms.input type="password" id="ip" label="IP Address/Domain"
|
||||
helper="An IP Address (127.0.0.1) or domain (example.com). Make sure there is no protocol like http(s):// so you provide a FQDN not a URL."
|
||||
required />
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="user" label="User" required />
|
||||
<x-forms.input type="number" id="port" label="Port" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full" x-data="{
|
||||
open: false,
|
||||
search: '{{ $serverTimezone ?: '' }}',
|
||||
timezones: @js($timezones),
|
||||
placeholder: '{{ $serverTimezone ? 'Search timezone...' : 'Select Server Timezone' }}',
|
||||
init() {
|
||||
this.$watch('search', value => {
|
||||
if (value === '') {
|
||||
this.open = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
}">
|
||||
<div class="flex items-center mb-1">
|
||||
<label for="serverTimezone">Server
|
||||
Timezone</label>
|
||||
<x-helper class="ml-2"
|
||||
helper="Server's timezone. This is used for backups, cron jobs, etc." />
|
||||
</div>
|
||||
<div class="relative">
|
||||
<div class="inline-flex relative items-center w-64">
|
||||
<input autocomplete="off"
|
||||
wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300'
|
||||
wire:dirty.class="dark:focus:ring-warning dark:ring-warning" x-model="search"
|
||||
@focus="open = true" @click.away="open = false" @input="open = true"
|
||||
class="w-full input" :placeholder="placeholder"
|
||||
wire:model.debounce.300ms="serverTimezone">
|
||||
<svg class="absolute right-0 mr-2 w-4 h-4" xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
||||
@click="open = true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="M8.25 15L12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9" />
|
||||
</svg>
|
||||
</div>
|
||||
<div x-show="open"
|
||||
class="overflow-auto overflow-x-hidden absolute z-50 mt-1 w-64 max-h-60 bg-white rounded-md border shadow-lg dark:bg-coolgray-100 dark:border-coolgray-200 scrollbar">
|
||||
<template
|
||||
x-for="timezone in timezones.filter(tz => tz.toLowerCase().includes(search.toLowerCase()))"
|
||||
:key="timezone">
|
||||
<div @click="search = timezone; open = false; $wire.set('server.settings.server_timezone', timezone)"
|
||||
class="px-4 py-2 text-gray-800 cursor-pointer hover:bg-gray-100 dark:hover:bg-coolgray-300 dark:text-gray-200"
|
||||
x-text="timezone"></div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-full">
|
||||
@if (!$server->isLocalhost())
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox instantSave id="isBuildServer" label="Use it as a build server?" />
|
||||
</div>
|
||||
|
||||
@if (!$server->isBuildServer() && !$server->settings->is_cloudflare_tunnel)
|
||||
<h3 class="pt-6">Swarm <span class="text-xs text-neutral-500">(experimental)</span>
|
||||
</h3>
|
||||
<div class="pb-4">Read the docs <a class='underline dark:text-white'
|
||||
href='https://coolify.io/docs/knowledge-base/docker/swarm'
|
||||
target='_blank'>here</a>.
|
||||
</div>
|
||||
<div class="w-96">
|
||||
@if ($server->settings->is_swarm_worker)
|
||||
<x-forms.checkbox disabled instantSave type="checkbox" id="isSwarmManager"
|
||||
helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>."
|
||||
label="Is it a Swarm Manager?" />
|
||||
@else
|
||||
<x-forms.checkbox instantSave type="checkbox" id="isSwarmManager"
|
||||
helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>."
|
||||
label="Is it a Swarm Manager?" />
|
||||
@endif
|
||||
|
||||
@if ($server->settings->is_swarm_manager)
|
||||
<x-forms.checkbox disabled instantSave type="checkbox" id="isSwarmWorker"
|
||||
helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>."
|
||||
label="Is it a Swarm Worker?" />
|
||||
@else
|
||||
<x-forms.checkbox instantSave type="checkbox" id="isSwarmWorker"
|
||||
helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>."
|
||||
label="Is it a Swarm Worker?" />
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@if ($server->isFunctional() && !$server->isSwarm() && !$server->isBuildServer())
|
||||
<form wire:submit.prevent='submit'>
|
||||
<div class="flex gap-2 items-center pt-4 pb-2">
|
||||
<h3>Sentinel</h3>
|
||||
@if ($server->isSentinelEnabled())
|
||||
<div class="flex gap-2 items-center">
|
||||
@if ($server->isSentinelLive())
|
||||
<x-status.running status="In sync" noLoading title="{{ $sentinelUpdatedAt }}" />
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
<x-forms.button wire:click='restartSentinel'>Restart</x-forms.button>
|
||||
@else
|
||||
<x-status.stopped status="Out of sync" noLoading
|
||||
title="{{ $sentinelUpdatedAt }}" />
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
<x-forms.button wire:click='restartSentinel'>Sync</x-forms.button>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex gap-2">Experimental feature <x-helper
|
||||
helper="Sentinel reports your server's & container's health and collects metrics." />
|
||||
</div>
|
||||
<div class="w-64">
|
||||
<x-forms.checkbox wire:model.live="isSentinelEnabled" label="Enable Sentinel" />
|
||||
@if ($server->isSentinelEnabled())
|
||||
<x-forms.checkbox id="isSentinelDebugEnabled" label="Enable Sentinel Debug"
|
||||
instantSave />
|
||||
<x-forms.checkbox instantSave id="isMetricsEnabled" label="Enable Metrics" />
|
||||
@else
|
||||
<x-forms.checkbox id="isSentinelDebugEnabled" label="Enable Sentinel Debug" disabled
|
||||
instantSave />
|
||||
<x-forms.checkbox instantSave disabled id="isMetricsEnabled" label="Enable Metrics" />
|
||||
label="Enable Metrics" />
|
||||
@endif
|
||||
</div>
|
||||
@if ($server->isSentinelEnabled())
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap items-end">
|
||||
<x-forms.input type="password" id="sentinelToken" label="Sentinel token" required
|
||||
helper="Token for Sentinel." />
|
||||
<x-forms.button wire:click="regenerateSentinelToken">Regenerate</x-forms.button>
|
||||
</div>
|
||||
|
||||
<x-forms.input id="sentinelCustomUrl" required label="Coolify URL"
|
||||
helper="URL to your Coolify instance. If it is empty that means you do not have a FQDN set for your Coolify instance." />
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap">
|
||||
<x-forms.input id="sentinelMetricsRefreshRateSeconds"
|
||||
label="Metrics rate (seconds)" required
|
||||
helper="The interval for gathering metrics. Lower means more disk space will be used." />
|
||||
<x-forms.input id="sentinelMetricsHistoryDays" label="Metrics history (days)"
|
||||
required helper="How many days should the metrics data should be reserved." />
|
||||
<x-forms.input id="sentinelPushIntervalSeconds" label="Push interval (seconds)"
|
||||
required
|
||||
helper="How many seconds should the metrics data should be pushed to the collector." />
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -36,7 +36,8 @@
|
||||
</div>
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
<x-forms.input id="settings.smtp_username" label="SMTP Username" />
|
||||
<x-forms.input id="settings.smtp_password" type="password" label="SMTP Password" />
|
||||
<x-forms.input id="settings.smtp_password" type="password" label="SMTP Password"
|
||||
autocomplete="new-password" />
|
||||
<x-forms.input id="settings.smtp_timeout" helper="Timeout value for sending emails."
|
||||
label="Timeout" />
|
||||
</div>
|
||||
@@ -57,7 +58,7 @@
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||
<x-forms.input type="password" id="settings.resend_api_key" placeholder="API key" required
|
||||
label="Host" />
|
||||
label="Host" autocomplete="new-password" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<x-forms.input id="oauth_settings_map.{{ $oauth_setting->provider }}.client_id"
|
||||
label="Client ID" />
|
||||
<x-forms.input id="oauth_settings_map.{{ $oauth_setting->provider }}.client_secret"
|
||||
type="password" label="Client Secret" />
|
||||
type="password" label="Client Secret" autocomplete="new-password" />
|
||||
<x-forms.input id="oauth_settings_map.{{ $oauth_setting->provider }}.redirect_uri"
|
||||
label="Redirect URI" />
|
||||
@if ($oauth_setting->provider == 'azure')
|
||||
|
||||
@@ -14,21 +14,18 @@
|
||||
:class="selected === 'yearly' ? 'dark:bg-coollabs-100 bg-warning dark:text-white' : ''">
|
||||
<input type="radio" x-on:click="selected = 'yearly'" name="frequency" value="annually"
|
||||
class="sr-only">
|
||||
<span>Annually <span class="text-xs dark:text-warning text-coollabs">(save ~20%)</span
|
||||
></span>
|
||||
<span>Annually <span class="text-xs dark:text-warning text-coollabs">(save ~20%)</span></span>
|
||||
</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="flow-root mt-12">
|
||||
{{-- <div class="pb-10 text-xl text-center">For the detailed list of features, please visit our landing page: <a
|
||||
class="font-bold underline dark:text-white" href="https://coolify.io">coolify.io</a></div> --}}
|
||||
<div
|
||||
class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-neutral-200 dark:divide-coolgray-500 isolate gap-y-16 sm:mx-auto lg:-mx-8 lg:mt-0 lg:max-w-none lg:grid-cols-1 lg:divide-x lg:divide-y-0 xl:-mx-4">
|
||||
<div class="pt-16 lg:px-8 lg:pt-0 xl:px-14">
|
||||
<h3 id="tier-dynamic" class="text-4xl font-semibold leading-7 dark:text-white">Pay-as-you-go</h3>
|
||||
<p class="mt-4 text-sm leading-6 dark:text-neutral-400">
|
||||
Dynamic pricing based on the number of servers you connect.
|
||||
</p>
|
||||
</p>
|
||||
<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 dark:text-white">$5</span>
|
||||
@@ -43,43 +40,38 @@
|
||||
<p class="flex items-baseline mb-4 gap-x-1">
|
||||
<span x-show="selected === 'monthly'" x-cloak>
|
||||
<span class="text-base font-semibold tracking-tight dark:text-white">$3</span>
|
||||
<span class="text-sm font-semibold leading-6 "> per additional servers <span class="font-normal dark:text-white">billed monthly (+VAT)</span></span>
|
||||
<span class="text-sm font-semibold leading-6 "> per additional servers <span
|
||||
class="font-normal dark:text-white">billed monthly (+VAT)</span></span>
|
||||
</span>
|
||||
|
||||
<span x-show="selected === 'yearly'" x-cloak>
|
||||
<span class="text-base font-semibold tracking-tight dark:text-white">$2.7</span>
|
||||
<span class="text-sm font-semibold leading-6 "> per additional servers <span class="font-normal dark:text-white">billed annually (+VAT)</span></span>
|
||||
<span class="text-sm font-semibold leading-6 "> per additional servers <span
|
||||
class="font-normal dark:text-white">billed annually (+VAT)</span></span>
|
||||
</span>
|
||||
</p>
|
||||
<div class="flex items-center pt-6">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="flex-none w-8 h-8 mr-3 text-warning"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 256 256"
|
||||
><path
|
||||
d="M236.8,188.09,149.35,36.22h0a24.76,24.76,0,0,0-42.7,0L19.2,188.09a23.51,23.51,0,0,0,0,23.72A24.35,24.35,0,0,0,40.55,224h174.9a24.35,24.35,0,0,0,21.33-12.19A23.51,23.51,0,0,0,236.8,188.09ZM222.93,203.8a8.5,8.5,0,0,1-7.48,4.2H40.55a8.5,8.5,0,0,1-7.48-4.2,7.59,7.59,0,0,1,0-7.72L120.52,44.21a8.75,8.75,0,0,1,15,0l87.45,151.87A7.59,7.59,0,0,1,222.93,203.8ZM120,144V104a8,8,0,0,1,16,0v40a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,180Z"
|
||||
></path></svg
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="flex-none w-8 h-8 mr-3 text-warning"
|
||||
fill="currentColor" viewBox="0 0 256 256">
|
||||
<path
|
||||
d="M236.8,188.09,149.35,36.22h0a24.76,24.76,0,0,0-42.7,0L19.2,188.09a23.51,23.51,0,0,0,0,23.72A24.35,24.35,0,0,0,40.55,224h174.9a24.35,24.35,0,0,0,21.33-12.19A23.51,23.51,0,0,0,236.8,188.09ZM222.93,203.8a8.5,8.5,0,0,1-7.48,4.2H40.55a8.5,8.5,0,0,1-7.48-4.2,7.59,7.59,0,0,1,0-7.72L120.52,44.21a8.75,8.75,0,0,1,15,0l87.45,151.87A7.59,7.59,0,0,1,222.93,203.8ZM120,144V104a8,8,0,0,1,16,0v40a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,180Z">
|
||||
</path>
|
||||
</svg>
|
||||
|
||||
<div class="flex flex-col text-sm dark:text-white">
|
||||
<div>
|
||||
You need to bring your own servers from any cloud provider (such as <a
|
||||
class="underline"
|
||||
href="https://coolify.io/hetzner"
|
||||
target="_blank">Hetzner</a
|
||||
>, DigitalOcean, AWS, etc.)
|
||||
</div>
|
||||
<div>
|
||||
(You can connect your RPi, old laptop, or any other device that runs
|
||||
the <a
|
||||
class="underline"
|
||||
href="https://coolify.io/docs/installation#supported-operating-systems"
|
||||
target="_blank">supported operating systems</a
|
||||
>.)
|
||||
</div>
|
||||
<div>
|
||||
You need to bring your own servers from any cloud provider (such as <a class="underline"
|
||||
href="https://coolify.io/hetzner" target="_blank">Hetzner</a>, DigitalOcean, AWS,
|
||||
etc.)
|
||||
</div>
|
||||
<div>
|
||||
(You can connect your RPi, old laptop, or any other device that runs
|
||||
the <a class="underline"
|
||||
href="https://coolify.io/docs/installation#supported-operating-systems"
|
||||
target="_blank">supported operating systems</a>.)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<x-forms.button x-show="selected === 'monthly'" x-cloak aria-describedby="tier-basic"
|
||||
class="w-full h-10 buyme" wire:click="subscribeStripe('dynamic-monthly')">
|
||||
Subscribe
|
||||
@@ -90,120 +82,72 @@
|
||||
</x-forms.button>
|
||||
<ul role="list" class="mt-8 space-y-3 text-sm leading-6 dark:text-neutral-400">
|
||||
<li class="flex">
|
||||
<svg
|
||||
class="flex-none w-5 h-6 mr-3 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>
|
||||
Connect
|
||||
<span class="px-1 font-bold dark:text-white">unlimited</span> servers
|
||||
<svg class="flex-none w-5 h-6 mr-3 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>
|
||||
Connect
|
||||
<span class="px-1 font-bold dark:text-white">unlimited</span> servers
|
||||
</li>
|
||||
<li class="flex">
|
||||
<svg
|
||||
class="flex-none w-5 h-6 mr-3 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>
|
||||
Deploy
|
||||
<span class="px-1 font-bold dark:text-white">unlimited</span> applications per server
|
||||
<svg class="flex-none w-5 h-6 mr-3 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>
|
||||
Deploy
|
||||
<span class="px-1 font-bold dark:text-white">unlimited</span> applications per server
|
||||
</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>
|
||||
Free email notifications
|
||||
<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>
|
||||
Free email notifications
|
||||
</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>
|
||||
Support by email
|
||||
<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>
|
||||
Support by email
|
||||
</li>
|
||||
<li class="flex font-bold dark:text-white gap-x-3">
|
||||
<svg
|
||||
width="512"
|
||||
height="512"
|
||||
class="flex-none w-5 h-6 text-green-500"
|
||||
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
|
||||
<svg width="512" height="512" class="flex-none w-5 h-6 text-green-500"
|
||||
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>
|
||||
<li class="flex dark:text-white gap-x-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="flex-none w-5 h-6 text-green-500"
|
||||
viewBox="0 0 256 256"
|
||||
><rect width="256" height="256" fill="none" /><polyline
|
||||
points="32 136 72 136 88 112 120 160 136 136 160 136"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/><path
|
||||
d="M24,104c0-.67,0-1.33,0-2A54,54,0,0,1,78,48c22.59,0,41.94,12.31,50,32,8.06-19.69,27.41-32,50-32a54,54,0,0,1,54,54c0,66-104,122-104,122s-42-22.6-72.58-56"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="16"
|
||||
/></svg
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="flex-none w-5 h-6 text-green-500"
|
||||
viewBox="0 0 256 256">
|
||||
<rect width="256" height="256" fill="none" />
|
||||
<polyline points="32 136 72 136 88 112 120 160 136 136 160 136" fill="none"
|
||||
stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="16" />
|
||||
<path
|
||||
d="M24,104c0-.67,0-1.33,0-2A54,54,0,0,1,78,48c22.59,0,41.94,12.31,50,32,8.06-19.69,27.41-32,50-32a54,54,0,0,1,54,54c0,66-104,122-104,122s-42-22.6-72.58-56"
|
||||
fill="none" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="16" />
|
||||
</svg>
|
||||
|
||||
Do you require official support for your self-hosted instance?<a
|
||||
class="underline"
|
||||
href="https://coolify.io/docs/contact">Contact Us</a
|
||||
>
|
||||
Do you require official support for your self-hosted instance?<a class="underline"
|
||||
href="https://coolify.io/docs/contact">Contact Us</a>
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user