@@ -27,6 +27,8 @@ class StartDatabaseProxy
|
|||||||
$server = data_get($database, 'destination.server');
|
$server = data_get($database, 'destination.server');
|
||||||
$containerName = data_get($database, 'uuid');
|
$containerName = data_get($database, 'uuid');
|
||||||
$proxyContainerName = "{$database->uuid}-proxy";
|
$proxyContainerName = "{$database->uuid}-proxy";
|
||||||
|
$isSSLEnabled = $database->enable_ssl ?? false;
|
||||||
|
|
||||||
if ($database->getMorphClass() === \App\Models\ServiceDatabase::class) {
|
if ($database->getMorphClass() === \App\Models\ServiceDatabase::class) {
|
||||||
$databaseType = $database->databaseType();
|
$databaseType = $database->databaseType();
|
||||||
$network = $database->service->uuid;
|
$network = $database->service->uuid;
|
||||||
@@ -42,6 +44,12 @@ class StartDatabaseProxy
|
|||||||
'standalone-mongodb' => 27017,
|
'standalone-mongodb' => 27017,
|
||||||
default => throw new \Exception("Unsupported database type: $databaseType"),
|
default => throw new \Exception("Unsupported database type: $databaseType"),
|
||||||
};
|
};
|
||||||
|
if ($isSSLEnabled) {
|
||||||
|
$internalPort = match ($databaseType) {
|
||||||
|
'standalone-redis', 'standalone-keydb', 'standalone-dragonfly' => 6380,
|
||||||
|
default => throw new \Exception("Unsupported database type: $databaseType"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
$configuration_dir = database_proxy_dir($database->uuid);
|
$configuration_dir = database_proxy_dir($database->uuid);
|
||||||
if (isDev()) {
|
if (isDev()) {
|
||||||
|
@@ -19,6 +19,7 @@ class StartService
|
|||||||
StopService::run(service: $service, dockerCleanup: false);
|
StopService::run(service: $service, dockerCleanup: false);
|
||||||
}
|
}
|
||||||
$service->saveComposeConfigs();
|
$service->saveComposeConfigs();
|
||||||
|
$service->isConfigurationChanged(save: true);
|
||||||
$commands[] = 'cd '.$service->workdir();
|
$commands[] = 'cd '.$service->workdir();
|
||||||
$commands[] = "echo 'Saved configuration files to {$service->workdir()}.'";
|
$commands[] = "echo 'Saved configuration files to {$service->workdir()}.'";
|
||||||
if ($pullLatestImages) {
|
if ($pullLatestImages) {
|
||||||
|
@@ -23,7 +23,7 @@ class CleanupInstanceStuffsJob implements ShouldBeEncrypted, ShouldBeUnique, Sho
|
|||||||
|
|
||||||
public function middleware(): array
|
public function middleware(): array
|
||||||
{
|
{
|
||||||
return [(new WithoutOverlapping('cleanup-instance-stuffs'))->dontRelease()];
|
return [(new WithoutOverlapping('cleanup-instance-stuffs'))->expireAfter(60)->dontRelease()];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(): void
|
public function handle(): void
|
||||||
|
@@ -31,7 +31,7 @@ class DockerCleanupJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
|
|
||||||
public function middleware(): array
|
public function middleware(): array
|
||||||
{
|
{
|
||||||
return [(new WithoutOverlapping('docker-cleanup-'.$this->server->uuid))->dontRelease()];
|
return [(new WithoutOverlapping('docker-cleanup-'.$this->server->uuid))->expireAfter(600)->dontRelease()];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct(public Server $server, public bool $manualCleanup = false) {}
|
public function __construct(public Server $server, public bool $manualCleanup = false) {}
|
||||||
|
@@ -70,7 +70,7 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
|
|
||||||
public function middleware(): array
|
public function middleware(): array
|
||||||
{
|
{
|
||||||
return [(new WithoutOverlapping('push-server-update-'.$this->server->uuid))->dontRelease()];
|
return [(new WithoutOverlapping('push-server-update-'.$this->server->uuid))->expireAfter(30)->dontRelease()];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function backoff(): int
|
public function backoff(): int
|
||||||
|
@@ -23,7 +23,7 @@ class RestartProxyJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
|
|
||||||
public function middleware(): array
|
public function middleware(): array
|
||||||
{
|
{
|
||||||
return [(new WithoutOverlapping('restart-proxy-'.$this->server->uuid))->dontRelease()];
|
return [(new WithoutOverlapping('restart-proxy-'.$this->server->uuid))->expireAfter(60)->dontRelease()];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct(public Server $server) {}
|
public function __construct(public Server $server) {}
|
||||||
|
@@ -28,7 +28,7 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
|
|
||||||
public function middleware(): array
|
public function middleware(): array
|
||||||
{
|
{
|
||||||
return [(new WithoutOverlapping('server-check-'.$this->server->uuid))->dontRelease()];
|
return [(new WithoutOverlapping('server-check-'.$this->server->uuid))->expireAfter(60)->dontRelease()];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct(public Server $server) {}
|
public function __construct(public Server $server) {}
|
||||||
|
@@ -19,11 +19,11 @@ class ServerPatchCheckJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
|
|
||||||
public $tries = 3;
|
public $tries = 3;
|
||||||
|
|
||||||
public $timeout = 600; // 10 minutes timeout
|
public $timeout = 600;
|
||||||
|
|
||||||
public function middleware(): array
|
public function middleware(): array
|
||||||
{
|
{
|
||||||
return [(new WithoutOverlapping('server-patch-check-'.$this->server->uuid))->dontRelease()];
|
return [(new WithoutOverlapping('server-patch-check-'.$this->server->uuid))->expireAfter(600)->dontRelease()];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct(public Server $server) {}
|
public function __construct(public Server $server) {}
|
||||||
|
@@ -56,7 +56,6 @@ class CloneMe extends Component
|
|||||||
$this->project_id = $this->project->id;
|
$this->project_id = $this->project->id;
|
||||||
$this->servers = currentTeam()
|
$this->servers = currentTeam()
|
||||||
->servers()
|
->servers()
|
||||||
->with('destinations')
|
|
||||||
->get()
|
->get()
|
||||||
->reject(fn ($server) => $server->isBuildServer());
|
->reject(fn ($server) => $server->isBuildServer());
|
||||||
$this->newName = str($this->project->name.'-clone-'.(string) new Cuid2)->slug();
|
$this->newName = str($this->project->name.'-clone-'.(string) new Cuid2)->slug();
|
||||||
|
@@ -63,7 +63,7 @@ class Heading extends Component
|
|||||||
$this->service->databases->each(function ($database) {
|
$this->service->databases->each(function ($database) {
|
||||||
$database->refresh();
|
$database->refresh();
|
||||||
});
|
});
|
||||||
if (is_null($this->service->config_hash) || $this->service->isConfigurationChanged()) {
|
if (is_null($this->service->config_hash)) {
|
||||||
$this->service->isConfigurationChanged(true);
|
$this->service->isConfigurationChanged(true);
|
||||||
}
|
}
|
||||||
$this->dispatch('configurationChanged');
|
$this->dispatch('configurationChanged');
|
||||||
|
@@ -170,6 +170,7 @@ class Show extends Component
|
|||||||
$this->syncData(true);
|
$this->syncData(true);
|
||||||
$this->dispatch('success', 'Environment variable updated.');
|
$this->dispatch('success', 'Environment variable updated.');
|
||||||
$this->dispatch('envsUpdated');
|
$this->dispatch('envsUpdated');
|
||||||
|
$this->dispatch('configurationChanged');
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return handleError($e);
|
return handleError($e);
|
||||||
}
|
}
|
||||||
|
@@ -68,11 +68,16 @@ class Terminal extends Component
|
|||||||
|
|
||||||
// Escape the identifier for shell usage
|
// Escape the identifier for shell usage
|
||||||
$escapedIdentifier = escapeshellarg($identifier);
|
$escapedIdentifier = escapeshellarg($identifier);
|
||||||
$command = SshMultiplexingHelper::generateSshCommand($server, "docker exec -it {$escapedIdentifier} sh -c 'PATH=\$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && if [ -f ~/.profile ]; then . ~/.profile; fi && if [ -n \"\$SHELL\" ]; then exec \$SHELL; else sh; fi'");
|
$shellCommand = 'PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && '.
|
||||||
|
'if [ -f ~/.profile ]; then . ~/.profile; fi && '.
|
||||||
|
'if [ -n "$SHELL" ] && [ -x "$SHELL" ]; then exec $SHELL; else sh; fi';
|
||||||
|
$command = SshMultiplexingHelper::generateSshCommand($server, "docker exec -it {$escapedIdentifier} sh -c '{$shellCommand}'");
|
||||||
} else {
|
} else {
|
||||||
$command = SshMultiplexingHelper::generateSshCommand($server, 'PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && if [ -f ~/.profile ]; then . ~/.profile; fi && if [ -n "$SHELL" ]; then exec $SHELL; else sh; fi');
|
$shellCommand = 'PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && '.
|
||||||
|
'if [ -f ~/.profile ]; then . ~/.profile; fi && '.
|
||||||
|
'if [ -n "$SHELL" ] && [ -x "$SHELL" ]; then exec $SHELL; else sh; fi';
|
||||||
|
$command = SshMultiplexingHelper::generateSshCommand($server, $shellCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ssh command is sent back to frontend then to websocket
|
// ssh command is sent back to frontend then to websocket
|
||||||
// this is done because the websocket connection is not available here
|
// this is done because the websocket connection is not available here
|
||||||
// a better solution would be to remove websocket on NodeJS and work with something like
|
// a better solution would be to remove websocket on NodeJS and work with something like
|
||||||
|
118
app/Livewire/Settings/Advanced.php
Normal file
118
app/Livewire/Settings/Advanced.php
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Livewire\Settings;
|
||||||
|
|
||||||
|
use App\Models\InstanceSettings;
|
||||||
|
use App\Models\Server;
|
||||||
|
use Auth;
|
||||||
|
use Hash;
|
||||||
|
use Livewire\Attributes\Validate;
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
|
class Advanced extends Component
|
||||||
|
{
|
||||||
|
#[Validate('required')]
|
||||||
|
public Server $server;
|
||||||
|
|
||||||
|
public InstanceSettings $settings;
|
||||||
|
|
||||||
|
#[Validate('boolean')]
|
||||||
|
public bool $is_registration_enabled;
|
||||||
|
|
||||||
|
#[Validate('boolean')]
|
||||||
|
public bool $do_not_track;
|
||||||
|
|
||||||
|
#[Validate('boolean')]
|
||||||
|
public bool $is_dns_validation_enabled;
|
||||||
|
|
||||||
|
#[Validate('nullable|string')]
|
||||||
|
public ?string $custom_dns_servers = null;
|
||||||
|
|
||||||
|
#[Validate('boolean')]
|
||||||
|
public bool $is_api_enabled;
|
||||||
|
|
||||||
|
#[Validate('nullable|string')]
|
||||||
|
public ?string $allowed_ips = null;
|
||||||
|
|
||||||
|
#[Validate('boolean')]
|
||||||
|
public bool $is_sponsorship_popup_enabled;
|
||||||
|
|
||||||
|
#[Validate('boolean')]
|
||||||
|
public bool $disable_two_step_confirmation;
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
if (! isInstanceAdmin()) {
|
||||||
|
return redirect()->route('dashboard');
|
||||||
|
}
|
||||||
|
$this->server = Server::findOrFail(0);
|
||||||
|
$this->settings = instanceSettings();
|
||||||
|
$this->custom_dns_servers = $this->settings->custom_dns_servers;
|
||||||
|
$this->allowed_ips = $this->settings->allowed_ips;
|
||||||
|
$this->do_not_track = $this->settings->do_not_track;
|
||||||
|
$this->is_registration_enabled = $this->settings->is_registration_enabled;
|
||||||
|
$this->is_dns_validation_enabled = $this->settings->is_dns_validation_enabled;
|
||||||
|
$this->is_api_enabled = $this->settings->is_api_enabled;
|
||||||
|
$this->disable_two_step_confirmation = $this->settings->disable_two_step_confirmation;
|
||||||
|
$this->is_sponsorship_popup_enabled = $this->settings->is_sponsorship_popup_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function submit()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->validate();
|
||||||
|
|
||||||
|
$this->custom_dns_servers = str($this->custom_dns_servers)->replaceEnd(',', '')->trim();
|
||||||
|
$this->custom_dns_servers = str($this->custom_dns_servers)->trim()->explode(',')->map(function ($dns) {
|
||||||
|
return str($dns)->trim()->lower();
|
||||||
|
})->unique()->implode(',');
|
||||||
|
|
||||||
|
$this->allowed_ips = str($this->allowed_ips)->replaceEnd(',', '')->trim();
|
||||||
|
$this->allowed_ips = str($this->allowed_ips)->trim()->explode(',')->map(function ($ip) {
|
||||||
|
return str($ip)->trim();
|
||||||
|
})->unique()->implode(',');
|
||||||
|
|
||||||
|
$this->instantSave();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function instantSave()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->settings->is_registration_enabled = $this->is_registration_enabled;
|
||||||
|
$this->settings->do_not_track = $this->do_not_track;
|
||||||
|
$this->settings->is_dns_validation_enabled = $this->is_dns_validation_enabled;
|
||||||
|
$this->settings->custom_dns_servers = $this->custom_dns_servers;
|
||||||
|
$this->settings->is_api_enabled = $this->is_api_enabled;
|
||||||
|
$this->settings->allowed_ips = $this->allowed_ips;
|
||||||
|
$this->settings->is_sponsorship_popup_enabled = $this->is_sponsorship_popup_enabled;
|
||||||
|
$this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation;
|
||||||
|
$this->settings->save();
|
||||||
|
$this->dispatch('success', 'Settings updated!');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toggleTwoStepConfirmation($password): bool
|
||||||
|
{
|
||||||
|
if (! Hash::check($password, Auth::user()->password)) {
|
||||||
|
$this->addError('password', 'The provided password is incorrect.');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation = true;
|
||||||
|
$this->settings->save();
|
||||||
|
$this->dispatch('success', 'Two step confirmation has been disabled.');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return view('livewire.settings.advanced');
|
||||||
|
}
|
||||||
|
}
|
@@ -2,11 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Livewire\Settings;
|
namespace App\Livewire\Settings;
|
||||||
|
|
||||||
use App\Jobs\CheckForUpdatesJob;
|
|
||||||
use App\Models\InstanceSettings;
|
use App\Models\InstanceSettings;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Illuminate\Support\Facades\Hash;
|
|
||||||
use Livewire\Attributes\Computed;
|
use Livewire\Attributes\Computed;
|
||||||
use Livewire\Attributes\Validate;
|
use Livewire\Attributes\Validate;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
@@ -15,10 +12,7 @@ class Index extends Component
|
|||||||
{
|
{
|
||||||
public InstanceSettings $settings;
|
public InstanceSettings $settings;
|
||||||
|
|
||||||
protected Server $server;
|
public Server $server;
|
||||||
|
|
||||||
#[Validate('boolean')]
|
|
||||||
public bool $is_auto_update_enabled;
|
|
||||||
|
|
||||||
#[Validate('nullable|string|max:255')]
|
#[Validate('nullable|string|max:255')]
|
||||||
public ?string $fqdn = null;
|
public ?string $fqdn = null;
|
||||||
@@ -29,48 +23,18 @@ class Index extends Component
|
|||||||
#[Validate('required|integer|min:1025|max:65535')]
|
#[Validate('required|integer|min:1025|max:65535')]
|
||||||
public int $public_port_max;
|
public int $public_port_max;
|
||||||
|
|
||||||
#[Validate('nullable|string')]
|
|
||||||
public ?string $custom_dns_servers = null;
|
|
||||||
|
|
||||||
#[Validate('nullable|string|max:255')]
|
#[Validate('nullable|string|max:255')]
|
||||||
public ?string $instance_name = null;
|
public ?string $instance_name = null;
|
||||||
|
|
||||||
#[Validate('nullable|string')]
|
|
||||||
public ?string $allowed_ips = null;
|
|
||||||
|
|
||||||
#[Validate('nullable|string')]
|
#[Validate('nullable|string')]
|
||||||
public ?string $public_ipv4 = null;
|
public ?string $public_ipv4 = null;
|
||||||
|
|
||||||
#[Validate('nullable|string')]
|
#[Validate('nullable|string')]
|
||||||
public ?string $public_ipv6 = null;
|
public ?string $public_ipv6 = null;
|
||||||
|
|
||||||
#[Validate('string')]
|
|
||||||
public string $auto_update_frequency;
|
|
||||||
|
|
||||||
#[Validate('string|required')]
|
|
||||||
public string $update_check_frequency;
|
|
||||||
|
|
||||||
#[Validate('required|string|timezone')]
|
#[Validate('required|string|timezone')]
|
||||||
public string $instance_timezone;
|
public string $instance_timezone;
|
||||||
|
|
||||||
#[Validate('boolean')]
|
|
||||||
public bool $do_not_track;
|
|
||||||
|
|
||||||
#[Validate('boolean')]
|
|
||||||
public bool $is_registration_enabled;
|
|
||||||
|
|
||||||
#[Validate('boolean')]
|
|
||||||
public bool $is_dns_validation_enabled;
|
|
||||||
|
|
||||||
#[Validate('boolean')]
|
|
||||||
public bool $is_api_enabled;
|
|
||||||
|
|
||||||
#[Validate('boolean')]
|
|
||||||
public bool $disable_two_step_confirmation;
|
|
||||||
|
|
||||||
#[Validate('boolean')]
|
|
||||||
public bool $is_sponsorship_popup_enabled;
|
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
return view('livewire.settings.index');
|
return view('livewire.settings.index');
|
||||||
@@ -80,27 +44,16 @@ class Index extends Component
|
|||||||
{
|
{
|
||||||
if (! isInstanceAdmin()) {
|
if (! isInstanceAdmin()) {
|
||||||
return redirect()->route('dashboard');
|
return redirect()->route('dashboard');
|
||||||
} else {
|
|
||||||
$this->settings = instanceSettings();
|
|
||||||
$this->fqdn = $this->settings->fqdn;
|
|
||||||
$this->public_port_min = $this->settings->public_port_min;
|
|
||||||
$this->public_port_max = $this->settings->public_port_max;
|
|
||||||
$this->custom_dns_servers = $this->settings->custom_dns_servers;
|
|
||||||
$this->instance_name = $this->settings->instance_name;
|
|
||||||
$this->allowed_ips = $this->settings->allowed_ips;
|
|
||||||
$this->public_ipv4 = $this->settings->public_ipv4;
|
|
||||||
$this->public_ipv6 = $this->settings->public_ipv6;
|
|
||||||
$this->do_not_track = $this->settings->do_not_track;
|
|
||||||
$this->is_auto_update_enabled = $this->settings->is_auto_update_enabled;
|
|
||||||
$this->is_registration_enabled = $this->settings->is_registration_enabled;
|
|
||||||
$this->is_dns_validation_enabled = $this->settings->is_dns_validation_enabled;
|
|
||||||
$this->is_api_enabled = $this->settings->is_api_enabled;
|
|
||||||
$this->auto_update_frequency = $this->settings->auto_update_frequency;
|
|
||||||
$this->update_check_frequency = $this->settings->update_check_frequency;
|
|
||||||
$this->instance_timezone = $this->settings->instance_timezone;
|
|
||||||
$this->disable_two_step_confirmation = $this->settings->disable_two_step_confirmation;
|
|
||||||
$this->is_sponsorship_popup_enabled = $this->settings->is_sponsorship_popup_enabled;
|
|
||||||
}
|
}
|
||||||
|
$this->settings = instanceSettings();
|
||||||
|
$this->server = Server::findOrFail(0);
|
||||||
|
$this->fqdn = $this->settings->fqdn;
|
||||||
|
$this->public_port_min = $this->settings->public_port_min;
|
||||||
|
$this->public_port_max = $this->settings->public_port_max;
|
||||||
|
$this->instance_name = $this->settings->instance_name;
|
||||||
|
$this->public_ipv4 = $this->settings->public_ipv4;
|
||||||
|
$this->public_ipv6 = $this->settings->public_ipv6;
|
||||||
|
$this->instance_timezone = $this->settings->instance_timezone;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Computed]
|
#[Computed]
|
||||||
@@ -115,30 +68,13 @@ class Index extends Component
|
|||||||
public function instantSave($isSave = true)
|
public function instantSave($isSave = true)
|
||||||
{
|
{
|
||||||
$this->validate();
|
$this->validate();
|
||||||
if ($this->settings->is_auto_update_enabled === true) {
|
|
||||||
$this->validate([
|
|
||||||
'auto_update_frequency' => ['required', 'string'],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->settings->fqdn = $this->fqdn;
|
$this->settings->fqdn = $this->fqdn;
|
||||||
$this->settings->public_port_min = $this->public_port_min;
|
$this->settings->public_port_min = $this->public_port_min;
|
||||||
$this->settings->public_port_max = $this->public_port_max;
|
$this->settings->public_port_max = $this->public_port_max;
|
||||||
$this->settings->custom_dns_servers = $this->custom_dns_servers;
|
|
||||||
$this->settings->instance_name = $this->instance_name;
|
$this->settings->instance_name = $this->instance_name;
|
||||||
$this->settings->allowed_ips = $this->allowed_ips;
|
|
||||||
$this->settings->public_ipv4 = $this->public_ipv4;
|
$this->settings->public_ipv4 = $this->public_ipv4;
|
||||||
$this->settings->public_ipv6 = $this->public_ipv6;
|
$this->settings->public_ipv6 = $this->public_ipv6;
|
||||||
$this->settings->do_not_track = $this->do_not_track;
|
|
||||||
$this->settings->is_auto_update_enabled = $this->is_auto_update_enabled;
|
|
||||||
$this->settings->is_registration_enabled = $this->is_registration_enabled;
|
|
||||||
$this->settings->is_dns_validation_enabled = $this->is_dns_validation_enabled;
|
|
||||||
$this->settings->is_api_enabled = $this->is_api_enabled;
|
|
||||||
$this->settings->auto_update_frequency = $this->auto_update_frequency;
|
|
||||||
$this->settings->update_check_frequency = $this->update_check_frequency;
|
|
||||||
$this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation;
|
|
||||||
$this->settings->instance_timezone = $this->instance_timezone;
|
$this->settings->instance_timezone = $this->instance_timezone;
|
||||||
$this->settings->is_sponsorship_popup_enabled = $this->is_sponsorship_popup_enabled;
|
|
||||||
if ($isSave) {
|
if ($isSave) {
|
||||||
$this->settings->save();
|
$this->settings->save();
|
||||||
$this->dispatch('success', 'Settings updated!');
|
$this->dispatch('success', 'Settings updated!');
|
||||||
@@ -149,7 +85,6 @@ class Index extends Component
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$error_show = false;
|
$error_show = false;
|
||||||
$this->server = Server::findOrFail(0);
|
|
||||||
$this->resetErrorBag();
|
$this->resetErrorBag();
|
||||||
|
|
||||||
if (! validate_timezone($this->instance_timezone)) {
|
if (! validate_timezone($this->instance_timezone)) {
|
||||||
@@ -166,46 +101,15 @@ class Index extends Component
|
|||||||
}
|
}
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
|
||||||
if ($this->is_auto_update_enabled && ! validate_cron_expression($this->auto_update_frequency)) {
|
if ($this->settings->is_dns_validation_enabled && $this->fqdn) {
|
||||||
$this->dispatch('error', 'Invalid Cron / Human expression for Auto Update Frequency.');
|
if (! validate_dns_entry($this->fqdn, $this->server)) {
|
||||||
if (empty($this->auto_update_frequency)) {
|
$this->dispatch('error', "Validating DNS failed.<br><br>Make sure you have added the DNS records correctly.<br><br>{$this->fqdn}->{$this->server->ip}<br><br>Check this <a target='_blank' class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/dns-configuration'>documentation</a> for further help.");
|
||||||
$this->auto_update_frequency = '0 0 * * *';
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! validate_cron_expression($this->update_check_frequency)) {
|
|
||||||
$this->dispatch('error', 'Invalid Cron / Human expression for Update Check Frequency.');
|
|
||||||
if (empty($this->update_check_frequency)) {
|
|
||||||
$this->update_check_frequency = '0 * * * *';
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->settings->is_dns_validation_enabled && $this->settings->fqdn) {
|
|
||||||
if (! validate_dns_entry($this->settings->fqdn, $this->server)) {
|
|
||||||
$this->dispatch('error', "Validating DNS failed.<br><br>Make sure you have added the DNS records correctly.<br><br>{$this->settings->fqdn}->{$this->server->ip}<br><br>Check this <a target='_blank' class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/dns-configuration'>documentation</a> for further help.");
|
|
||||||
$error_show = true;
|
$error_show = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($this->settings->fqdn) {
|
if ($this->fqdn) {
|
||||||
check_domain_usage(domain: $this->settings->fqdn);
|
check_domain_usage(domain: $this->fqdn);
|
||||||
}
|
}
|
||||||
$this->settings->custom_dns_servers = str($this->settings->custom_dns_servers)->replaceEnd(',', '')->trim();
|
|
||||||
$this->settings->custom_dns_servers = str($this->settings->custom_dns_servers)->trim()->explode(',')->map(function ($dns) {
|
|
||||||
return str($dns)->trim()->lower();
|
|
||||||
});
|
|
||||||
$this->settings->custom_dns_servers = $this->settings->custom_dns_servers->unique();
|
|
||||||
$this->settings->custom_dns_servers = $this->settings->custom_dns_servers->implode(',');
|
|
||||||
|
|
||||||
$this->settings->allowed_ips = str($this->settings->allowed_ips)->replaceEnd(',', '')->trim();
|
|
||||||
$this->settings->allowed_ips = str($this->settings->allowed_ips)->trim()->explode(',')->map(function ($ip) {
|
|
||||||
return str($ip)->trim();
|
|
||||||
});
|
|
||||||
$this->settings->allowed_ips = $this->settings->allowed_ips->unique();
|
|
||||||
$this->settings->allowed_ips = $this->settings->allowed_ips->implode(',');
|
|
||||||
|
|
||||||
$this->instantSave(isSave: false);
|
$this->instantSave(isSave: false);
|
||||||
|
|
||||||
@@ -218,31 +122,4 @@ class Index extends Component
|
|||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function checkManually()
|
|
||||||
{
|
|
||||||
CheckForUpdatesJob::dispatchSync();
|
|
||||||
$this->dispatch('updateAvailable');
|
|
||||||
$settings = instanceSettings();
|
|
||||||
if ($settings->new_version_available) {
|
|
||||||
$this->dispatch('success', 'New version available!');
|
|
||||||
} else {
|
|
||||||
$this->dispatch('success', 'No new version available.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toggleTwoStepConfirmation($password): bool
|
|
||||||
{
|
|
||||||
if (! Hash::check($password, Auth::user()->password)) {
|
|
||||||
$this->addError('password', 'The provided password is incorrect.');
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation = true;
|
|
||||||
$this->settings->save();
|
|
||||||
$this->dispatch('success', 'Two step confirmation has been disabled.');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
101
app/Livewire/Settings/Updates.php
Normal file
101
app/Livewire/Settings/Updates.php
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Livewire\Settings;
|
||||||
|
|
||||||
|
use App\Jobs\CheckForUpdatesJob;
|
||||||
|
use App\Models\InstanceSettings;
|
||||||
|
use App\Models\Server;
|
||||||
|
use Livewire\Attributes\Validate;
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
|
class Updates extends Component
|
||||||
|
{
|
||||||
|
public InstanceSettings $settings;
|
||||||
|
|
||||||
|
public Server $server;
|
||||||
|
|
||||||
|
#[Validate('string')]
|
||||||
|
public string $auto_update_frequency;
|
||||||
|
|
||||||
|
#[Validate('string|required')]
|
||||||
|
public string $update_check_frequency;
|
||||||
|
|
||||||
|
#[Validate('boolean')]
|
||||||
|
public bool $is_auto_update_enabled;
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
$this->server = Server::findOrFail(0);
|
||||||
|
|
||||||
|
$this->settings = instanceSettings();
|
||||||
|
$this->auto_update_frequency = $this->settings->auto_update_frequency;
|
||||||
|
$this->update_check_frequency = $this->settings->update_check_frequency;
|
||||||
|
$this->is_auto_update_enabled = $this->settings->is_auto_update_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function instantSave()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if ($this->settings->is_auto_update_enabled === true) {
|
||||||
|
$this->validate([
|
||||||
|
'auto_update_frequency' => ['required', 'string'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$this->settings->auto_update_frequency = $this->auto_update_frequency;
|
||||||
|
$this->settings->update_check_frequency = $this->update_check_frequency;
|
||||||
|
$this->settings->is_auto_update_enabled = $this->is_auto_update_enabled;
|
||||||
|
$this->settings->save();
|
||||||
|
$this->dispatch('success', 'Settings updated!');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function submit()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->resetErrorBag();
|
||||||
|
$this->validate();
|
||||||
|
|
||||||
|
if ($this->is_auto_update_enabled && ! validate_cron_expression($this->auto_update_frequency)) {
|
||||||
|
$this->dispatch('error', 'Invalid Cron / Human expression for Auto Update Frequency.');
|
||||||
|
if (empty($this->auto_update_frequency)) {
|
||||||
|
$this->auto_update_frequency = '0 0 * * *';
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! validate_cron_expression($this->update_check_frequency)) {
|
||||||
|
$this->dispatch('error', 'Invalid Cron / Human expression for Update Check Frequency.');
|
||||||
|
if (empty($this->update_check_frequency)) {
|
||||||
|
$this->update_check_frequency = '0 * * * *';
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->instantSave();
|
||||||
|
$this->server->setupDynamicProxyConfiguration();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkManually()
|
||||||
|
{
|
||||||
|
CheckForUpdatesJob::dispatchSync();
|
||||||
|
$this->dispatch('updateAvailable');
|
||||||
|
$settings = instanceSettings();
|
||||||
|
if ($settings->new_version_available) {
|
||||||
|
$this->dispatch('success', 'New version available!');
|
||||||
|
} else {
|
||||||
|
$this->dispatch('success', 'No new version available.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return view('livewire.settings.updates');
|
||||||
|
}
|
||||||
|
}
|
@@ -46,32 +46,31 @@ class SettingsBackup extends Component
|
|||||||
{
|
{
|
||||||
if (! isInstanceAdmin()) {
|
if (! isInstanceAdmin()) {
|
||||||
return redirect()->route('dashboard');
|
return redirect()->route('dashboard');
|
||||||
} else {
|
|
||||||
$settings = instanceSettings();
|
|
||||||
$this->server = Server::findOrFail(0);
|
|
||||||
$this->database = StandalonePostgresql::whereName('coolify-db')->first();
|
|
||||||
$s3s = S3Storage::whereTeamId(0)->get() ?? [];
|
|
||||||
if ($this->database) {
|
|
||||||
$this->uuid = $this->database->uuid;
|
|
||||||
$this->name = $this->database->name;
|
|
||||||
$this->description = $this->database->description;
|
|
||||||
$this->postgres_user = $this->database->postgres_user;
|
|
||||||
$this->postgres_password = $this->database->postgres_password;
|
|
||||||
|
|
||||||
if ($this->database->status !== 'running') {
|
|
||||||
$this->database->status = 'running';
|
|
||||||
$this->database->save();
|
|
||||||
}
|
|
||||||
$this->backup = $this->database->scheduledBackups->first();
|
|
||||||
if ($this->backup && ! $this->server->isFunctional()) {
|
|
||||||
$this->backup->enabled = false;
|
|
||||||
$this->backup->save();
|
|
||||||
}
|
|
||||||
$this->executions = $this->backup->executions;
|
|
||||||
}
|
|
||||||
$this->settings = $settings;
|
|
||||||
$this->s3s = $s3s;
|
|
||||||
}
|
}
|
||||||
|
$settings = instanceSettings();
|
||||||
|
$this->server = Server::findOrFail(0);
|
||||||
|
$this->database = StandalonePostgresql::whereName('coolify-db')->first();
|
||||||
|
$s3s = S3Storage::whereTeamId(0)->get() ?? [];
|
||||||
|
if ($this->database) {
|
||||||
|
$this->uuid = $this->database->uuid;
|
||||||
|
$this->name = $this->database->name;
|
||||||
|
$this->description = $this->database->description;
|
||||||
|
$this->postgres_user = $this->database->postgres_user;
|
||||||
|
$this->postgres_password = $this->database->postgres_password;
|
||||||
|
|
||||||
|
if ($this->database->status !== 'running') {
|
||||||
|
$this->database->status = 'running';
|
||||||
|
$this->database->save();
|
||||||
|
}
|
||||||
|
$this->backup = $this->database->scheduledBackups->first();
|
||||||
|
if ($this->backup && ! $this->server->isFunctional()) {
|
||||||
|
$this->backup->enabled = false;
|
||||||
|
$this->backup->save();
|
||||||
|
}
|
||||||
|
$this->executions = $this->backup->executions;
|
||||||
|
}
|
||||||
|
$this->settings = $settings;
|
||||||
|
$this->s3s = $s3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addCoolifyDatabase()
|
public function addCoolifyDatabase()
|
||||||
|
@@ -31,7 +31,7 @@ class Form extends Component
|
|||||||
'storage.endpoint' => 'Endpoint',
|
'storage.endpoint' => 'Endpoint',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function test_s3_connection()
|
public function testConnection()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->storage->testConnection(shouldSave: true);
|
$this->storage->testConnection(shouldSave: true);
|
||||||
@@ -45,6 +45,8 @@ class Form extends Component
|
|||||||
public function delete()
|
public function delete()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('delete', $this->storage);
|
||||||
|
|
||||||
$this->storage->delete();
|
$this->storage->delete();
|
||||||
|
|
||||||
return redirect()->route('storage.index');
|
return redirect()->route('storage.index');
|
||||||
@@ -57,7 +59,7 @@ class Form extends Component
|
|||||||
{
|
{
|
||||||
$this->validate();
|
$this->validate();
|
||||||
try {
|
try {
|
||||||
$this->test_s3_connection();
|
$this->testConnection();
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
}
|
}
|
||||||
|
@@ -887,7 +887,7 @@ $schema://$host {
|
|||||||
|
|
||||||
public function muxFilename()
|
public function muxFilename()
|
||||||
{
|
{
|
||||||
return $this->uuid;
|
return 'mux_'.$this->uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function team()
|
public function team()
|
||||||
|
66
app/Policies/S3StoragePolicy.php
Normal file
66
app/Policies/S3StoragePolicy.php
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\S3Storage;
|
||||||
|
use App\Models\Server;
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
class S3StoragePolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view any models.
|
||||||
|
*/
|
||||||
|
public function viewAny(User $user): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the model.
|
||||||
|
*/
|
||||||
|
public function view(User $user, S3Storage $storage): bool
|
||||||
|
{
|
||||||
|
return $user->teams()->where('id', $storage->team_id)->exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create models.
|
||||||
|
*/
|
||||||
|
public function create(User $user): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*/
|
||||||
|
public function update(User $user, Server $server): bool
|
||||||
|
{
|
||||||
|
return $user->teams()->get()->firstWhere('id', $server->team_id) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*/
|
||||||
|
public function delete(User $user, S3Storage $storage): bool
|
||||||
|
{
|
||||||
|
return $user->teams()->where('id', $storage->team_id)->exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can restore the model.
|
||||||
|
*/
|
||||||
|
public function restore(User $user, S3Storage $storage): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can permanently delete the model.
|
||||||
|
*/
|
||||||
|
public function forceDelete(User $user, S3Storage $storage): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'coolify' => [
|
'coolify' => [
|
||||||
'version' => '4.0.0-beta.420.1',
|
'version' => '4.0.0-beta.420.2',
|
||||||
'helper_version' => '1.0.8',
|
'helper_version' => '1.0.8',
|
||||||
'realtime_version' => '1.0.9',
|
'realtime_version' => '1.0.9',
|
||||||
'self_hosted' => env('SELF_HOSTED', true),
|
'self_hosted' => env('SELF_HOSTED', true),
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"coolify": {
|
"coolify": {
|
||||||
"v4": {
|
"v4": {
|
||||||
"version": "4.0.0-beta.420"
|
"version": "4.0.0-beta.420.2"
|
||||||
},
|
},
|
||||||
"nightly": {
|
"nightly": {
|
||||||
"version": "4.0.0-beta.421"
|
"version": "4.0.0-beta.420.3"
|
||||||
},
|
},
|
||||||
"helper": {
|
"helper": {
|
||||||
"version": "1.0.8"
|
"version": "1.0.8"
|
||||||
|
7
public/svgs/excalidraw.svg
Normal file
7
public/svgs/excalidraw.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
|
||||||
|
<rect width="1000" height="1000" rx="200" ry="200" fill="#fff" />
|
||||||
|
<svg viewBox="0 0 107 101" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2">
|
||||||
|
<path style="fill:none" d="M24 17h121v121H24z" transform="matrix(.8843 0 0 .83471 -21.223 -14.19)" />
|
||||||
|
<path d="M119.81 105.98a.549.549 0 0 0-.53-.12c-4.19-6.19-9.52-12.06-14.68-17.73l-.85-.93c0-.11-.05-.21-.12-.3a.548.548 0 0 0-.34-.2l-.17-.18-.12-.09c-.15-.32-.53-.56-.95-.35-1.58.81-3 1.97-4.4 3.04-1.87 1.43-3.7 2.92-5.42 4.52-.7.65-1.39 1.33-1.97 2.09-.28.37-.07.72.27.87-1.22 1.2-2.45 2.45-3.68 3.74-.11.12-.17.28-.16.44.01.16.09.31.22.41l2.16 1.65s.01.03.03.04c3.09 3.05 8.51 7.28 14.25 11.76.85.67 1.71 1.34 2.57 2.01.39.47.76.94 1.12 1.4.19.25.55.3.8.11.13.1.26.21.39.31a.57.57 0 0 0 .8-.1c.07-.09.1-.2.11-.31.04 0 .07.03.1.03.15 0 .31-.06.42-.18l10.18-11.12a.56.56 0 0 0-.04-.8l.01-.01Zm-29.23-3.85c.07.09.14.17.21.25 1.16.98 2.4 2.04 3.66 3.12l-5.12-3.91s-.32-.22-.52-.36c-.11-.08-.21-.16-.31-.24l-.38-.32s.07-.07.1-.11l.35-.35c1.72-1.74 4.67-4.64 6.19-6.06-1.61 1.62-4.87 6.37-4.17 7.98h-.01Zm17.53 13.81-4.22-3.22c-1.65-1.71-3.43-3.4-5.24-5.03 2.28 1.76 4.23 3.25 4.52 3.51 2.21 1.97 2.11 1.61 3.63 2.91l1.83 1.33c-.18.16-.36.33-.53.49l.01.01Zm1.06.81-.08-.06c.16-.13.33-.25.49-.38l-.4.44h-.01ZM42.24 51.45c.14.72.27 1.43.4 2.11.69 3.7 1.33 7.03 2.55 9.56l.48 1.92c.19.73.46 1.64.71 1.83 2.85 2.52 7.22 6.28 11.89 9.82.21.16.5.15.7-.01.01.02.03.03.04.04.11.1.24.15.38.15.16 0 .31-.06.42-.19 5.98-6.65 10.43-12.12 13.6-16.7.2-.25.3-.54.29-.84.2-.24.41-.48.6-.68a.558.558 0 0 0-.1-.86.578.578 0 0 0-.17-.36c-1.39-1.34-2.42-2.31-3.46-3.28-1.84-1.72-3.74-3.5-7.77-7.51-.02-.02-.05-.04-.07-.06a.555.555 0 0 0-.22-.14c-1.11-.39-3.39-.78-6.26-1.28-4.22-.72-10-1.72-15.2-3.27h-.04v-.01s-.02 0-.03.02h-.01l.04-.02s-.31.01-.37.04c-.08.04-.14.09-.19.15-.05.06-.09.12-.47.2-.38.08.08 0 .11 0h-.11v.03c.07.34.05.58.16.97-.02.1.21 1.02.24 1.11l1.83 7.26h.03Zm30.95 6.54s-.03.04-.04.05l-.64-.71c.22.21.44.42.68.66Zm-7.09 9.39s-.07.08-.1.12l-.02-.02c.04-.03.08-.07.13-.1h-.01Zm-7.07 8.47Zm3.02-28.57c.35.35 1.74 1.65 2.06 1.97-1.45-.66-5.06-2.34-6.74-2.88 1.65.29 3.93.66 4.68.91Zm-19.18-2.77c.84 1.44 1.5 6.49 2.16 11.4-.37-1.58-.69-3.12-.99-4.6-.52-2.56-1-4.85-1.67-6.88.14.01.31.03.49.05 0 .01 0 .02.02.03h-.01Zm-.29-1.21c-.23-.02-.44-.04-.62-.05-.02-.04-.03-.08-.04-.12l.66.18v-.01Zm-2.22.45v-.02.02ZM118.9 42.57c.04-.23-1.1-1.24-.74-1.26.85-.04.86-1.35 0-1.31-1.13.06-2.27.32-3.37.53-1.98.37-3.95.78-5.92 1.21-4.39.94-8.77 1.93-13.1 3.11-1.36.37-2.86.7-4.11 1.36-.42.22-.4.67-.17.95-.09.05-.18.08-.28.09-.37.07-.74.13-1.11.19a.566.566 0 0 0-.39.86c-2.32 3.1-4.96 6.44-7.82 9.95-2.81 3.21-5.73 6.63-8.72 10.14-9.41 11.06-20.08 23.6-31.9 34.64-.23.21-.24.57-.03.8.05.06.12.1.19.13-.16.15-.32.3-.48.44-.1.09-.14.2-.16.32-.08.08-.16.17-.23.25-.21.23-.2.59.03.8.23.21.59.2.8-.03.04-.04.08-.09.12-.13a.84.84 0 0 1 1.22 0c.69.74 1.34 1.44 1.95 2.09l-1.38-1.15a.57.57 0 0 0-.8.07c-.2.24-.17.6.07.8l14.82 12.43c.11.09.24.13.37.13.15 0 .29-.06.4-.17l.36-.36a.56.56 0 0 0 .63-.12c20.09-20.18 36.27-35.43 54.8-49.06.17-.12.25-.32.23-.51a.57.57 0 0 0 .48-.39c3.42-10.46 4.08-19.72 4.28-24.27 0-.03.01-.05.02-.07.02-.05.03-.1.04-.14.03-.11.05-.19.05-.19.26-.78.17-1.53-.15-2.15v.02ZM82.98 58.94c.9-1.03 1.79-2.04 2.67-3.02-5.76 7.58-15.3 19.26-28.81 33.14 9.2-10.18 18.47-20.73 26.14-30.12Zm-32.55 52.81-.03-.03c.11.02.19.04.2.04a.47.47 0 0 0-.17 0v-.01Zm6.9 6.42-.05-.04.03-.03c.02 0 .03.02.04.02 0 .02-.02.03-.03.05h.01Zm8.36-7.21 1.38-1.44c.01.01.02.03.03.05-.47.46-.94.93-1.42 1.39h.01Zm2.24-2.21c.26-.3.56-.65.87-1.02.01-.01.02-.03.04-.04 3.29-3.39 6.68-6.82 10.18-10.25.02-.02.05-.04.07-.06.86-.66 1.82-1.39 2.72-2.08-4.52 4.32-9.11 8.78-13.88 13.46v-.01Zm21.65-55.88c-1.86 2.42-3.9 5.56-5.63 8.07-5.46 7.91-23.04 27.28-23.43 27.65-2.71 2.62-10.88 10.46-16.09 15.37-.14.13-.25.24-.34.35a.794.794 0 0 1 .03-1.13c24.82-23.4 39.88-42.89 46-51.38-.13.33-.24.69-.55 1.09l.01-.02Zm16.51 7.1-.01.02c0-.02-.02-.07.01-.02Zm-.91-5.13Zm-5.89 9.45c-2.26-1.31-3.32-3.27-2.71-5.25l.19-.66c.08-.19.17-.38.28-.57.59-.98 1.49-1.85 2.52-2.36.05-.02.1-.03.15-.04a.795.795 0 0 1-.04-.43c.05-.31.25-.58.66-.58.67 0 2.75.62 3.54 1.3.24.19.47.4.68.63.3.35.74.92.96 1.33.13.06.23.62.38.91.14.46.2.93.18 1.4 0 .02 0 .02.01.03-.03.07 0 .37-.04.4-.1.72-.36 1.43-.75 2.05-.04.05-.07.11-.11.16 0 .01-.02.02-.03.04-.3.43-.65.83-1.08 1.13-1.26.89-2.73 1.16-4.2.79a6.33 6.33 0 0 1-.57-.25l-.02-.03Zm16.27-1.63c-.49 2.05-1.09 4.19-1.8 6.38-.03.08-.03.16-.03.23-.1.01-.19.05-.27.11-4.44 3.26-8.73 6.62-12.98 10.11 3.67-3.32 7.39-6.62 11.23-9.95a6.409 6.409 0 0 0 2.11-3.74l.56-3.37.03-.1c.25-.71 1.34-.4 1.17.33h-.02Z" style="fill:#6965db;fill-rule:nonzero" transform="matrix(1 0 0 1 -26.41 -29.49)" />
|
||||||
|
</svg>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.8 KiB |
@@ -42,7 +42,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@utility button {
|
@utility button {
|
||||||
@apply flex gap-2 justify-center items-center px-2 py-1 text-sm text-black normal-case rounded-sm border outline-0 cursor-pointer bg-neutral-200/50 border-neutral-300 hover:bg-neutral-300 dark:bg-coolgray-200 dark:text-white dark:hover:text-white dark:hover:bg-coolgray-500 dark:border-coolgray-300 hover:text-black disabled:cursor-not-allowed min-w-fit dark:disabled:text-neutral-600 disabled:border-none disabled:hover:bg-transparent disabled:bg-transparent disabled:text-neutral-300;
|
@apply flex gap-2 justify-center items-center px-2 py-1 text-sm text-black normal-case rounded-sm border outline-0 cursor-pointer bg-neutral-200/50 border-neutral-300 hover:bg-neutral-300 dark:bg-coolgray-200 dark:text-white dark:hover:text-white dark:hover:bg-coolgray-500 dark:border-coolgray-300 hover:text-black disabled:cursor-not-allowed min-w-fit dark:disabled:text-neutral-600 disabled:border-transparent disabled:hover:bg-transparent disabled:bg-transparent disabled:text-neutral-300;
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility alert-success {
|
@utility alert-success {
|
||||||
|
@@ -5,19 +5,19 @@
|
|||||||
<nav class="flex items-center gap-6 min-h-10 whitespace-nowrap">
|
<nav class="flex items-center gap-6 min-h-10 whitespace-nowrap">
|
||||||
<a class="{{ request()->routeIs('settings.index') ? 'dark:text-white' : '' }}"
|
<a class="{{ request()->routeIs('settings.index') ? 'dark:text-white' : '' }}"
|
||||||
href="{{ route('settings.index') }}">
|
href="{{ route('settings.index') }}">
|
||||||
<button>Configuration</button>
|
Configuration
|
||||||
</a>
|
</a>
|
||||||
<a class="{{ request()->routeIs('settings.backup') ? 'dark:text-white' : '' }}"
|
<a class="{{ request()->routeIs('settings.backup') ? 'dark:text-white' : '' }}"
|
||||||
href="{{ route('settings.backup') }}">
|
href="{{ route('settings.backup') }}">
|
||||||
<button>Backup</button>
|
Backup
|
||||||
</a>
|
</a>
|
||||||
<a class="{{ request()->routeIs('settings.email') ? 'dark:text-white' : '' }}"
|
<a class="{{ request()->routeIs('settings.email') ? 'dark:text-white' : '' }}"
|
||||||
href="{{ route('settings.email') }}">
|
href="{{ route('settings.email') }}">
|
||||||
<button>Transactional Email</button>
|
Transactional Email
|
||||||
</a>
|
</a>
|
||||||
<a class="{{ request()->routeIs('settings.oauth') ? 'dark:text-white' : '' }}"
|
<a class="{{ request()->routeIs('settings.oauth') ? 'dark:text-white' : '' }}"
|
||||||
href="{{ route('settings.oauth') }}">
|
href="{{ route('settings.oauth') }}">
|
||||||
<button>OAuth</button>
|
OAuth
|
||||||
</a>
|
</a>
|
||||||
<div class="flex-1"></div>
|
<div class="flex-1"></div>
|
||||||
</nav>
|
</nav>
|
||||||
|
8
resources/views/components/settings/sidebar.blade.php
Normal file
8
resources/views/components/settings/sidebar.blade.php
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<div class="flex flex-col items-start gap-2 min-w-fit">
|
||||||
|
<a class="menu-item {{ $activeMenu === 'general' ? 'menu-item-active' : '' }}"
|
||||||
|
href="{{ route('settings.index') }}">General</a>
|
||||||
|
<a class="menu-item {{ $activeMenu === 'advanced' ? 'menu-item-active' : '' }}"
|
||||||
|
href="{{ route('settings.advanced') }}">Advanced</a>
|
||||||
|
<a class="menu-item {{ $activeMenu === 'updates' ? 'menu-item-active' : '' }}"
|
||||||
|
href="{{ route('settings.updates') }}">Updates</a>
|
||||||
|
</div>
|
@@ -9,16 +9,16 @@
|
|||||||
<div class="navbar-main">
|
<div class="navbar-main">
|
||||||
<nav class="flex items-center gap-6 min-h-10">
|
<nav class="flex items-center gap-6 min-h-10">
|
||||||
<a class="{{ request()->routeIs('team.index') ? 'dark:text-white' : '' }}" href="{{ route('team.index') }}">
|
<a class="{{ request()->routeIs('team.index') ? 'dark:text-white' : '' }}" href="{{ route('team.index') }}">
|
||||||
<button>General</button>
|
General
|
||||||
</a>
|
</a>
|
||||||
<a class="{{ request()->routeIs('team.member.index') ? 'dark:text-white' : '' }}"
|
<a class="{{ request()->routeIs('team.member.index') ? 'dark:text-white' : '' }}"
|
||||||
href="{{ route('team.member.index') }}">
|
href="{{ route('team.member.index') }}">
|
||||||
<button>Members</button>
|
Members
|
||||||
</a>
|
</a>
|
||||||
@if (isInstanceAdmin())
|
@if (isInstanceAdmin())
|
||||||
<a class="{{ request()->routeIs('team.admin-view') ? 'dark:text-white' : '' }}"
|
<a class="{{ request()->routeIs('team.admin-view') ? 'dark:text-white' : '' }}"
|
||||||
href="{{ route('team.admin-view') }}">
|
href="{{ route('team.admin-view') }}">
|
||||||
<button>Admin View</button>
|
Admin View
|
||||||
</a>
|
</a>
|
||||||
@endif
|
@endif
|
||||||
<div class="flex-1"></div>
|
<div class="flex-1"></div>
|
||||||
|
@@ -63,12 +63,13 @@
|
|||||||
<section>
|
<section>
|
||||||
<h3 class="pb-2">Servers</h3>
|
<h3 class="pb-2">Servers</h3>
|
||||||
@if ($servers->count() > 0)
|
@if ($servers->count() > 0)
|
||||||
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
<div class="grid grid-cols-1 gap-4 xl:grid-cols-2">
|
||||||
@foreach ($servers as $server)
|
@foreach ($servers as $server)
|
||||||
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
|
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
|
||||||
@class([
|
@class([
|
||||||
'gap-2 border cursor-pointer box group',
|
'gap-2 border cursor-pointer box group',
|
||||||
'border-red-500' => !$server->settings->is_reachable,
|
'border-red-500' =>
|
||||||
|
!$server->settings->is_reachable || $server->settings->force_disabled,
|
||||||
])>
|
])>
|
||||||
<div class="flex flex-col justify-center mx-6">
|
<div class="flex flex-col justify-center mx-6">
|
||||||
<div class="box-title">
|
<div class="box-title">
|
||||||
|
@@ -11,13 +11,13 @@
|
|||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="subtitle">Network endpoints to deploy your resources.</div>
|
<div class="subtitle">Network endpoints to deploy your resources.</div>
|
||||||
<div class="grid gap-2 lg:grid-cols-1">
|
<div class="grid gap-4 lg:grid-cols-2">
|
||||||
@forelse ($servers as $server)
|
@forelse ($servers as $server)
|
||||||
@forelse ($server->destinations() as $destination)
|
@forelse ($server->destinations() as $destination)
|
||||||
@if ($destination->getMorphClass() === 'App\Models\StandaloneDocker')
|
@if ($destination->getMorphClass() === 'App\Models\StandaloneDocker')
|
||||||
<a class="box group"
|
<a class="box group"
|
||||||
href="{{ route('destination.show', ['destination_uuid' => data_get($destination, 'uuid')]) }}">
|
href="{{ route('destination.show', ['destination_uuid' => data_get($destination, 'uuid')]) }}">
|
||||||
<div class="flex flex-col mx-6">
|
<div class="flex flex-col justify-center mx-6">
|
||||||
<div class="box-title">{{ $destination->name }}</div>
|
<div class="box-title">{{ $destination->name }}</div>
|
||||||
<div class="box-description">Server: {{ $destination->server->name }}</div>
|
<div class="box-description">Server: {{ $destination->server->name }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,5 +2,5 @@
|
|||||||
<x-modal-confirmation buttonFullWidth title="Confirm Team Deletion?" buttonTitle="Delete Team" isErrorButton
|
<x-modal-confirmation buttonFullWidth title="Confirm Team Deletion?" buttonTitle="Delete Team" isErrorButton
|
||||||
submitAction="delete" :actions="['The current Team will be permanently deleted.']" confirmationText="{{ $team }}"
|
submitAction="delete" :actions="['The current Team will be permanently deleted.']" confirmationText="{{ $team }}"
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Team Name below"
|
confirmationLabel="Please confirm the execution of the actions by entering the Team Name below"
|
||||||
shortConfirmationLabel="Team Name" step3ButtonText="Permanently Delete" />
|
shortConfirmationLabel="Team Name" />
|
||||||
</div>
|
</div>
|
||||||
|
@@ -7,86 +7,101 @@
|
|||||||
<div class="subtitle ">Quickly clone all resources to a new project or environment.</div>
|
<div class="subtitle ">Quickly clone all resources to a new project or environment.</div>
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input required id="newName" label="New Name" />
|
<x-forms.input required id="newName" label="New Name" />
|
||||||
<x-forms.button isHighlighted wire:click="clone('project')" class="mt-4">Clone to a new Project</x-forms.button>
|
<h3 class="pt-8 ">Destination Server</h3>
|
||||||
<x-forms.button isHighlighted wire:click="clone('environment')" class="mt-4">Clone to a new Environment</x-forms.button>
|
<div class="pb-2">Choose the server and network to clone the resources to.</div>
|
||||||
{{--
|
<div class="flex flex-col">
|
||||||
<div class="mt-8">
|
<div class="flex flex-col">
|
||||||
<h3 class="text-lg font-bold mb-2">Clone Volume Data</h3>
|
<div class="overflow-x-auto">
|
||||||
<div class="text-sm text-gray-600 dark:text-gray-300 mb-4">
|
<div class="inline-block min-w-full">
|
||||||
Clone your volume data to the new resources volumes. This process requires a brief container downtime to ensure data consistency.
|
<div class="overflow-hidden">
|
||||||
</div>
|
<table class="min-w-full">
|
||||||
<div wire:poll>
|
<thead>
|
||||||
@if(!$cloneVolumeData)
|
<tr>
|
||||||
<div wire:key="volume-disabled">
|
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Server</th>
|
||||||
<x-modal-confirmation
|
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Network</th>
|
||||||
title="Enable Volume Data Cloning?"
|
</tr>
|
||||||
buttonTitle="Enable Volume Cloning"
|
</thead>
|
||||||
submitAction="toggleVolumeCloning(true)"
|
<tbody>
|
||||||
:actions="['This will temporarily stop all the containers to copy the volume data to the new resources to ensure data consistency.', 'The process runs in the background and may take a few minutes.']"
|
@foreach ($servers->sortBy('id') as $server)
|
||||||
:confirmWithPassword="false"
|
@foreach ($server->destinations() as $destination)
|
||||||
:confirmWithText="false"
|
<tr class="cursor-pointer hover:bg-coolgray-50 dark:hover:bg-coolgray-200"
|
||||||
/>
|
wire:click="selectServer('{{ $server->id }}', '{{ $destination->id }}')">
|
||||||
</div>
|
<td class="px-5 py-4 text-sm whitespace-nowrap dark:text-white"
|
||||||
@else
|
:class="'{{ $selectedDestination === $destination->id }}' ?
|
||||||
<div wire:key="volume-enabled" class="max-w-md">
|
'bg-coollabs text-white' : 'dark:bg-coolgray-100 bg-white'">
|
||||||
<x-forms.checkbox
|
{{ $server->name }}</td>
|
||||||
label="Clone Volume Data"
|
<td class="px-5 py-4 text-sm whitespace-nowrap dark:text-white "
|
||||||
id="cloneVolumeData"
|
:class="'{{ $selectedDestination === $destination->id }}' ?
|
||||||
wire:model="cloneVolumeData"
|
'bg-coollabs text-white' : 'dark:bg-coolgray-100 bg-white'">
|
||||||
wire:change="toggleVolumeCloning(false)"
|
{{ $destination->name }}
|
||||||
:checked="$cloneVolumeData"
|
</td>
|
||||||
helper="Volume Data will be cloned to the new resources. Containers will be temporarily stopped during the cloning process." />
|
</tr>
|
||||||
</div>
|
@endforeach
|
||||||
@endif
|
@endforeach
|
||||||
</div>
|
</tbody>
|
||||||
</div> --}}
|
</table>
|
||||||
|
</div>
|
||||||
<h3 class="pt-8 pb-2">Servers</h3>
|
|
||||||
<div>Choose the server and network to clone the resources to.</div>
|
|
||||||
<div class="flex flex-col gap-4">
|
|
||||||
@foreach ($servers->sortBy('id') as $server)
|
|
||||||
<div class="p-4">
|
|
||||||
<h4>{{ $server->name }}</h4>
|
|
||||||
<div class="pt-4 pb-2">Docker Networks</div>
|
|
||||||
<div class="grid grid-cols-1 gap-2 pb-4 lg:grid-cols-4">
|
|
||||||
@foreach ($server->destinations() as $destination)
|
|
||||||
<div class="cursor-pointer box-without-bg group"
|
|
||||||
:class="'{{ $selectedDestination === $destination->id }}' ? 'bg-coollabs text-white' : 'dark:bg-coolgray-100 bg-white'"
|
|
||||||
wire:click="selectServer('{{ $server->id }}', '{{ $destination->id }}')">
|
|
||||||
{{ $destination->name }}
|
|
||||||
</div>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3 class="pt-8 pb-2">Resources</h3>
|
<h3 class="pt-8">Resources</h3>
|
||||||
<div>These will be cloned to the new project</div>
|
<div class="pb-2">These will be cloned to the new project</div>
|
||||||
<div class="grid grid-cols-1 gap-2 pt-4 opacity-95 lg:grid-cols-2 xl:grid-cols-3">
|
<div class="flex flex-col pt-4">
|
||||||
@foreach ($environment->applications->sortBy('name') as $application)
|
<div class="flex flex-col">
|
||||||
<div class="bg-white cursor-default box-without-bg dark:bg-coolgray-100 group">
|
<div class="overflow-x-auto">
|
||||||
<div class="flex flex-col">
|
<div class="inline-block min-w-full">
|
||||||
<div class="font-bold dark:text-white">{{ $application->name }}</div>
|
<div class="overflow-hidden">
|
||||||
<div class="description">{{ $application->description }}</div>
|
<table class="min-w-full">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Name</th>
|
||||||
|
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Type</th>
|
||||||
|
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach ($environment->applications->sortBy('name') as $application)
|
||||||
|
<tr>
|
||||||
|
<td class="px-5 py-4 text-sm whitespace-nowrap font-bold dark:text-white">
|
||||||
|
{{ $application->name }}</td>
|
||||||
|
<td class="px-5 py-4 text-sm whitespace-nowrap dark:text-white">Application</td>
|
||||||
|
<td class="px-5 py-4 text-sm dark:text-white">
|
||||||
|
{{ $application->description ?: '-' }}</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
@foreach ($environment->databases()->sortBy('name') as $database)
|
||||||
|
<tr>
|
||||||
|
<td class="px-5 py-4 text-sm whitespace-nowrap font-bold dark:text-white">
|
||||||
|
{{ $database->name }}
|
||||||
|
</td>
|
||||||
|
<td class="px-5 py-4 text-sm whitespace-nowrap dark:text-white">Database</td>
|
||||||
|
<td class="px-5 py-4 text-sm dark:text-white">
|
||||||
|
{{ $database->description ?: '-' }}</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
@foreach ($environment->services->sortBy('name') as $service)
|
||||||
|
<tr>
|
||||||
|
<td class="px-5 py-4 text-sm whitespace-nowrap font-bold dark:text-white">
|
||||||
|
{{ $service->name }}
|
||||||
|
</td>
|
||||||
|
<td class="px-5 py-4 text-sm whitespace-nowrap dark:text-white">Service</td>
|
||||||
|
<td class="px-5 py-4 text-sm dark:text-white">
|
||||||
|
{{ $service->description ?: '-' }}</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
</div>
|
||||||
@foreach ($environment->databases()->sortBy('name') as $database)
|
</div>
|
||||||
<div class="bg-white cursor-default box-without-bg dark:bg-coolgray-100 group">
|
<div class="flex gap-4 pt-4 w-full">
|
||||||
<div class="flex flex-col">
|
<x-forms.button isHighlighted class="w-full" wire:click="clone('project')" :disabled="!filled($selectedDestination)">Clone to new
|
||||||
<div class="font-bold dark:text-white">{{ $database->name }}</div>
|
Project</x-forms.button>
|
||||||
<div class="description">{{ $database->description }}</div>
|
<x-forms.button isHighlighted class="w-full" wire:click="clone('environment')" :disabled="!filled($selectedDestination)">Clone to new
|
||||||
</div>
|
Environment</x-forms.button>
|
||||||
</div>
|
|
||||||
@endforeach
|
|
||||||
@foreach ($environment->services->sortBy('name') as $service)
|
|
||||||
<div class="bg-white cursor-default box-without-bg dark:bg-coolgray-100 group">
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<div class="font-bold dark:text-white">{{ $service->name }}</div>
|
|
||||||
<div class="description">{{ $service->description }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@@ -8,7 +8,8 @@
|
|||||||
@forelse($executions as $execution)
|
@forelse($executions as $execution)
|
||||||
<div wire:key="{{ data_get($execution, 'id') }}" @class([
|
<div wire:key="{{ data_get($execution, 'id') }}" @class([
|
||||||
'flex flex-col border-l-2 transition-colors p-4 bg-white dark:bg-coolgray-100 text-black dark:text-white',
|
'flex flex-col border-l-2 transition-colors p-4 bg-white dark:bg-coolgray-100 text-black dark:text-white',
|
||||||
'border-blue-500/50 border-dashed' => data_get($execution, 'status') === 'running',
|
'border-blue-500/50 border-dashed' =>
|
||||||
|
data_get($execution, 'status') === 'running',
|
||||||
'border-error' => data_get($execution, 'status') === 'failed',
|
'border-error' => data_get($execution, 'status') === 'failed',
|
||||||
'border-success' => data_get($execution, 'status') === 'success',
|
'border-success' => data_get($execution, 'status') === 'success',
|
||||||
])>
|
])>
|
||||||
@@ -20,16 +21,19 @@
|
|||||||
<div class="flex items-center gap-2 mb-2">
|
<div class="flex items-center gap-2 mb-2">
|
||||||
<span @class([
|
<span @class([
|
||||||
'px-3 py-1 rounded-md text-xs font-medium tracking-wide shadow-xs',
|
'px-3 py-1 rounded-md text-xs font-medium tracking-wide shadow-xs',
|
||||||
'bg-blue-100/80 text-blue-700 dark:bg-blue-500/20 dark:text-blue-300 dark:shadow-blue-900/5' => data_get($execution, 'status') === 'running',
|
'bg-blue-100/80 text-blue-700 dark:bg-blue-500/20 dark:text-blue-300 dark:shadow-blue-900/5' =>
|
||||||
'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-200 dark:shadow-red-900/5' => data_get($execution, 'status') === 'failed',
|
data_get($execution, 'status') === 'running',
|
||||||
'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200 dark:shadow-green-900/5' => data_get($execution, 'status') === 'success',
|
'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-200 dark:shadow-red-900/5' =>
|
||||||
|
data_get($execution, 'status') === 'failed',
|
||||||
|
'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200 dark:shadow-green-900/5' =>
|
||||||
|
data_get($execution, 'status') === 'success',
|
||||||
])>
|
])>
|
||||||
@php
|
@php
|
||||||
$statusText = match(data_get($execution, 'status')) {
|
$statusText = match (data_get($execution, 'status')) {
|
||||||
'success' => 'Success',
|
'success' => 'Success',
|
||||||
'running' => 'In Progress',
|
'running' => 'In Progress',
|
||||||
'failed' => 'Failed',
|
'failed' => 'Failed',
|
||||||
default => ucfirst(data_get($execution, 'status'))
|
default => ucfirst(data_get($execution, 'status')),
|
||||||
};
|
};
|
||||||
@endphp
|
@endphp
|
||||||
{{ $statusText }}
|
{{ $statusText }}
|
||||||
@@ -37,9 +41,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="text-gray-600 dark:text-gray-400 text-sm">
|
<div class="text-gray-600 dark:text-gray-400 text-sm">
|
||||||
Started: {{ formatDateInServerTimezone(data_get($execution, 'created_at'), $this->server()) }}
|
Started: {{ formatDateInServerTimezone(data_get($execution, 'created_at'), $this->server()) }}
|
||||||
@if(data_get($execution, 'status') !== 'running')
|
@if (data_get($execution, 'status') !== 'running')
|
||||||
<br>Ended: {{ formatDateInServerTimezone(data_get($execution, 'finished_at'), $this->server()) }}
|
<br>Ended:
|
||||||
<br>Duration: {{ calculateDuration(data_get($execution, 'created_at'), data_get($execution, 'finished_at')) }}
|
{{ formatDateInServerTimezone(data_get($execution, 'finished_at'), $this->server()) }}
|
||||||
|
<br>Duration:
|
||||||
|
{{ calculateDuration(data_get($execution, 'created_at'), data_get($execution, 'finished_at')) }}
|
||||||
<br>Finished {{ \Carbon\Carbon::parse(data_get($execution, 'finished_at'))->diffForHumans() }}
|
<br>Finished {{ \Carbon\Carbon::parse(data_get($execution, 'finished_at'))->diffForHumans() }}
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@@ -60,36 +66,60 @@
|
|||||||
</div>
|
</div>
|
||||||
<span @class([
|
<span @class([
|
||||||
'px-2 py-1 rounded-sm text-xs font-medium',
|
'px-2 py-1 rounded-sm text-xs font-medium',
|
||||||
'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200' => !data_get($execution, 'local_storage_deleted', false),
|
'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200' => !data_get(
|
||||||
'bg-gray-100 text-gray-600 dark:bg-gray-800/50 dark:text-gray-400' => data_get($execution, 'local_storage_deleted', false),
|
$execution,
|
||||||
|
'local_storage_deleted',
|
||||||
|
false),
|
||||||
|
'bg-gray-100 text-gray-600 dark:bg-gray-800/50 dark:text-gray-400' => data_get(
|
||||||
|
$execution,
|
||||||
|
'local_storage_deleted',
|
||||||
|
false),
|
||||||
])>
|
])>
|
||||||
<span class="flex items-center gap-1">
|
<span class="flex items-center gap-1">
|
||||||
@if(!data_get($execution, 'local_storage_deleted', false))
|
@if (!data_get($execution, 'local_storage_deleted', false))
|
||||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20"
|
||||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path>
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
|
clip-rule="evenodd"></path>
|
||||||
</svg>
|
</svg>
|
||||||
@else
|
@else
|
||||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20"
|
||||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"></path>
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z"
|
||||||
|
clip-rule="evenodd"></path>
|
||||||
</svg>
|
</svg>
|
||||||
@endif
|
@endif
|
||||||
Local Storage
|
Local Storage
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
@if($backup->save_s3)
|
@if ($backup->save_s3)
|
||||||
<span @class([
|
<span @class([
|
||||||
'px-2 py-1 rounded-sm text-xs font-medium',
|
'px-2 py-1 rounded-sm text-xs font-medium',
|
||||||
'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200' => !data_get($execution, 's3_storage_deleted', false),
|
'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200' => !data_get(
|
||||||
'bg-gray-100 text-gray-600 dark:bg-gray-800/50 dark:text-gray-400' => data_get($execution, 's3_storage_deleted', false),
|
$execution,
|
||||||
|
's3_storage_deleted',
|
||||||
|
false),
|
||||||
|
'bg-gray-100 text-gray-600 dark:bg-gray-800/50 dark:text-gray-400' => data_get(
|
||||||
|
$execution,
|
||||||
|
's3_storage_deleted',
|
||||||
|
false),
|
||||||
])>
|
])>
|
||||||
<span class="flex items-center gap-1">
|
<span class="flex items-center gap-1">
|
||||||
@if(!data_get($execution, 's3_storage_deleted', false))
|
@if (!data_get($execution, 's3_storage_deleted', false))
|
||||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20"
|
||||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path>
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
|
clip-rule="evenodd"></path>
|
||||||
</svg>
|
</svg>
|
||||||
@else
|
@else
|
||||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20"
|
||||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"></path>
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z"
|
||||||
|
clip-rule="evenodd"></path>
|
||||||
</svg>
|
</svg>
|
||||||
@endif
|
@endif
|
||||||
S3 Storage
|
S3 Storage
|
||||||
@@ -108,11 +138,10 @@
|
|||||||
x-on:click="download_file('{{ data_get($execution, 'id') }}')">Download</x-forms.button>
|
x-on:click="download_file('{{ data_get($execution, 'id') }}')">Download</x-forms.button>
|
||||||
@endif
|
@endif
|
||||||
<x-modal-confirmation title="Confirm Backup Deletion?" buttonTitle="Delete" isErrorButton
|
<x-modal-confirmation title="Confirm Backup Deletion?" buttonTitle="Delete" isErrorButton
|
||||||
submitAction="deleteBackup({{ data_get($execution, 'id') }})"
|
submitAction="deleteBackup({{ data_get($execution, 'id') }})" :checkboxes="$checkboxes"
|
||||||
:checkboxes="$checkboxes"
|
|
||||||
:actions="['This backup will be permanently deleted from local storage.']" confirmationText="{{ data_get($execution, 'filename') }}"
|
:actions="['This backup will be permanently deleted from local storage.']" confirmationText="{{ data_get($execution, 'filename') }}"
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Backup Filename below"
|
confirmationLabel="Please confirm the execution of the actions by entering the Backup Filename below"
|
||||||
shortConfirmationLabel="Backup Filename" step3ButtonText="Permanently Delete" />
|
shortConfirmationLabel="Backup Filename" 1 />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@empty
|
@empty
|
||||||
|
@@ -253,7 +253,8 @@
|
|||||||
@endif
|
@endif
|
||||||
@if ($current_step === 'destinations')
|
@if ($current_step === 'destinations')
|
||||||
<h2>Select a destination</h2>
|
<h2>Select a destination</h2>
|
||||||
<div>Destinations are used to segregate resources by network. If you are unsure, select the default
|
<div class="pb-4">Destinations are used to segregate resources by network. If you are unsure, select the
|
||||||
|
default
|
||||||
Standalone Docker (coolify).</div>
|
Standalone Docker (coolify).</div>
|
||||||
<div class="flex flex-col justify-center gap-4 text-left xl:flex-row xl:flex-wrap">
|
<div class="flex flex-col justify-center gap-4 text-left xl:flex-row xl:flex-wrap">
|
||||||
@if ($server->isSwarm())
|
@if ($server->isSwarm())
|
||||||
|
@@ -11,11 +11,11 @@
|
|||||||
buttonTitle="Convert to Application" submitAction="convertToApplication" :actions="['The selected resource will be converted to an application.']"
|
buttonTitle="Convert to Application" submitAction="convertToApplication" :actions="['The selected resource will be converted to an application.']"
|
||||||
confirmationText="{{ Str::headline($database->name) }}"
|
confirmationText="{{ Str::headline($database->name) }}"
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Service Database Name below"
|
confirmationLabel="Please confirm the execution of the actions by entering the Service Database Name below"
|
||||||
shortConfirmationLabel="Service Database Name" step3ButtonText="Permanently Delete" />
|
shortConfirmationLabel="Service Database Name" />
|
||||||
<x-modal-confirmation title="Confirm Service Database Deletion?" buttonTitle="Delete" isErrorButton
|
<x-modal-confirmation title="Confirm Service Database Deletion?" buttonTitle="Delete" isErrorButton
|
||||||
submitAction="delete" :actions="['The selected service database container will be stopped and permanently deleted.']" confirmationText="{{ Str::headline($database->name) }}"
|
submitAction="delete" :actions="['The selected service database container will be stopped and permanently deleted.']" confirmationText="{{ Str::headline($database->name) }}"
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Service Database Name below"
|
confirmationLabel="Please confirm the execution of the actions by entering the Service Database Name below"
|
||||||
shortConfirmationLabel="Service Database Name" step3ButtonText="Permanently Delete" />
|
shortConfirmationLabel="Service Database Name" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
]"
|
]"
|
||||||
confirmationText="{{ $fs_path }}"
|
confirmationText="{{ $fs_path }}"
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Filepath below"
|
confirmationLabel="Please confirm the execution of the actions by entering the Filepath below"
|
||||||
shortConfirmationLabel="Filepath" step3ButtonText="Permanently Delete" />
|
shortConfirmationLabel="Filepath" />
|
||||||
@else
|
@else
|
||||||
@if (!$fileStorage->is_binary)
|
@if (!$fileStorage->is_binary)
|
||||||
<x-modal-confirmation :ignoreWire="false" title="Confirm File Conversion to Directory?"
|
<x-modal-confirmation :ignoreWire="false" title="Confirm File Conversion to Directory?"
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
isErrorButton submitAction="delete" :checkboxes="$fileDeletionCheckboxes" :actions="['The selected file will be permanently deleted from the container.']"
|
isErrorButton submitAction="delete" :checkboxes="$fileDeletionCheckboxes" :actions="['The selected file will be permanently deleted from the container.']"
|
||||||
confirmationText="{{ $fs_path }}"
|
confirmationText="{{ $fs_path }}"
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Filepath below"
|
confirmationLabel="Please confirm the execution of the actions by entering the Filepath below"
|
||||||
shortConfirmationLabel="Filepath" step3ButtonText="Permanently Delete" />
|
shortConfirmationLabel="Filepath" />
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@if (!$fileStorage->is_directory)
|
@if (!$fileStorage->is_directory)
|
||||||
|
@@ -11,11 +11,11 @@
|
|||||||
buttonTitle="Convert to Database" submitAction="convertToDatabase" :actions="['The selected resource will be converted to a service database.']"
|
buttonTitle="Convert to Database" submitAction="convertToDatabase" :actions="['The selected resource will be converted to a service database.']"
|
||||||
confirmationText="{{ Str::headline($application->name) }}"
|
confirmationText="{{ Str::headline($application->name) }}"
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Service Application Name below"
|
confirmationLabel="Please confirm the execution of the actions by entering the Service Application Name below"
|
||||||
shortConfirmationLabel="Service Application Name" step3ButtonText="Permanently Delete" />
|
shortConfirmationLabel="Service Application Name" />
|
||||||
<x-modal-confirmation title="Confirm Service Application Deletion?" buttonTitle="Delete" isErrorButton
|
<x-modal-confirmation title="Confirm Service Application Deletion?" buttonTitle="Delete" isErrorButton
|
||||||
submitAction="delete" :actions="['The selected service application container will be stopped and permanently deleted.']" confirmationText="{{ Str::headline($application->name) }}"
|
submitAction="delete" :actions="['The selected service application container will be stopped and permanently deleted.']" confirmationText="{{ Str::headline($application->name) }}"
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Service Application Name below"
|
confirmationLabel="Please confirm the execution of the actions by entering the Service Application Name below"
|
||||||
shortConfirmationLabel="Service Application Name" step3ButtonText="Permanently Delete" />
|
shortConfirmationLabel="Service Application Name" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
|
@@ -7,5 +7,5 @@
|
|||||||
<x-modal-confirmation title="Confirm Resource Deletion?" buttonTitle="Delete" isErrorButton submitAction="delete"
|
<x-modal-confirmation title="Confirm Resource Deletion?" buttonTitle="Delete" isErrorButton submitAction="delete"
|
||||||
buttonTitle="Delete" :checkboxes="$checkboxes" :actions="['Permanently delete all containers of this resource.']" confirmationText="{{ $resourceName }}"
|
buttonTitle="Delete" :checkboxes="$checkboxes" :actions="['Permanently delete all containers of this resource.']" confirmationText="{{ $resourceName }}"
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Resource Name below"
|
confirmationLabel="Please confirm the execution of the actions by entering the Resource Name below"
|
||||||
shortConfirmationLabel="Resource Name" step3ButtonText="Permanently Delete" />
|
shortConfirmationLabel="Resource Name" />
|
||||||
</div>
|
</div>
|
||||||
|
@@ -70,7 +70,7 @@
|
|||||||
'This will stop the all running applications on this server and remove it as a deployment destination.',
|
'This will stop the all running applications on this server and remove it as a deployment destination.',
|
||||||
]" confirmationText="{{ data_get($destination, 'server.name') }}"
|
]" confirmationText="{{ data_get($destination, 'server.name') }}"
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Server Name below"
|
confirmationLabel="Please confirm the execution of the actions by entering the Server Name below"
|
||||||
shortConfirmationLabel="Server Name" step3ButtonText="Remove application from server" />
|
shortConfirmationLabel="Server Name" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
@@ -48,10 +48,10 @@
|
|||||||
<x-forms.checkbox instantSave id="is_build_time"
|
<x-forms.checkbox instantSave id="is_build_time"
|
||||||
helper="If you are using Docker, remember to modify the file to be ready to receive the build time args. Ex.: for docker file, add `ARG name_of_the_variable`, or dockercompose add `- 'name_of_the_variable=${name_of_the_variable}'`"
|
helper="If you are using Docker, remember to modify the file to be ready to receive the build time args. Ex.: for docker file, add `ARG name_of_the_variable`, or dockercompose add `- 'name_of_the_variable=${name_of_the_variable}'`"
|
||||||
label="Is Build Variable?" />
|
label="Is Build Variable?" />
|
||||||
|
<x-forms.checkbox instantSave id="is_multiline" label="Is Multiline?" />
|
||||||
<x-forms.checkbox instantSave id="is_literal"
|
<x-forms.checkbox instantSave id="is_literal"
|
||||||
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
|
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
|
||||||
label="Is Literal?" />
|
label="Is Literal?" />
|
||||||
<x-forms.checkbox instantSave id="is_multiline" label="Is Multiline?" />
|
|
||||||
@else
|
@else
|
||||||
@if ($is_shared)
|
@if ($is_shared)
|
||||||
<x-forms.checkbox instantSave id="is_build_time"
|
<x-forms.checkbox instantSave id="is_build_time"
|
||||||
|
@@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
@if ($type === 'server')
|
@if ($type === 'server')
|
||||||
<livewire:server.navbar :server="$servers->first()" />
|
<livewire:server.navbar :server="$servers->first()" />
|
||||||
@if ($servers->first()->isTerminalEnabled())
|
@if ($servers->first()->isTerminalEnabled() && $servers->first()->isFunctional())
|
||||||
<form class="w-full flex gap-2 items-start" wire:submit="$dispatchSelf('connectToServer')"
|
<form class="w-full flex gap-2 items-start" wire:submit="$dispatchSelf('connectToServer')"
|
||||||
wire:init="$dispatchSelf('connectToServer')">
|
wire:init="$dispatchSelf('connectToServer')">
|
||||||
<h2 class="pb-4">Terminal</h2>
|
<h2 class="pb-4">Terminal</h2>
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
<livewire:project.shared.terminal />
|
<livewire:project.shared.terminal />
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<div>Terminal access is disabled on this server.</div>
|
<div>Server is not functional or terminal access is disabled.</div>
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
@@ -60,7 +60,7 @@
|
|||||||
'If the persistent storage/volume is actvily used by a resource data will be lost.',
|
'If the persistent storage/volume is actvily used by a resource data will be lost.',
|
||||||
]" confirmationText="{{ $storage->name }}"
|
]" confirmationText="{{ $storage->name }}"
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Storage Name below"
|
confirmationLabel="Please confirm the execution of the actions by entering the Storage Name below"
|
||||||
shortConfirmationLabel="Storage Name" step3ButtonText="Permanently Delete" />
|
shortConfirmationLabel="Storage Name" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</form>
|
</form>
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
<div>
|
<div>
|
||||||
<x-security.navbar />
|
<x-security.navbar />
|
||||||
|
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<h2 class="pb-4">Private Keys</h2>
|
<h2 class="pb-4">Private Keys</h2>
|
||||||
<x-modal-input buttonTitle="+ Add" title="New Private Key">
|
<x-modal-input buttonTitle="+ Add" title="New Private Key">
|
||||||
@@ -9,18 +8,19 @@
|
|||||||
<x-modal-confirmation title="Confirm unused SSH Key Deletion?" buttonTitle="Delete unused SSH Keys" isErrorButton
|
<x-modal-confirmation title="Confirm unused SSH Key Deletion?" buttonTitle="Delete unused SSH Keys" isErrorButton
|
||||||
submitAction="cleanupUnusedKeys" :actions="['All unused SSH keys (marked with unused) are permanently deleted.']" :confirmWithText="false" :confirmWithPassword="false" />
|
submitAction="cleanupUnusedKeys" :actions="['All unused SSH keys (marked with unused) are permanently deleted.']" :confirmWithText="false" :confirmWithPassword="false" />
|
||||||
</div>
|
</div>
|
||||||
<div class="grid gap-2 lg:grid-cols-2">
|
<div class="grid gap-4 lg:grid-cols-2">
|
||||||
@forelse ($privateKeys as $key)
|
@forelse ($privateKeys as $key)
|
||||||
<a class="box group"
|
<a class="box group"
|
||||||
href="{{ route('security.private-key.show', ['private_key_uuid' => data_get($key, 'uuid')]) }}">
|
href="{{ route('security.private-key.show', ['private_key_uuid' => data_get($key, 'uuid')]) }}">
|
||||||
<div class="flex flex-col mx-6">
|
<div class="flex flex-col justify-center mx-6">
|
||||||
<div class="box-title">
|
<div class="box-title">
|
||||||
{{ data_get($key, 'name') }}
|
{{ data_get($key, 'name') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="box-description">
|
<div class="box-description">
|
||||||
{{ $key->description }}
|
{{ $key->description }}
|
||||||
@if (!$key->isInUse())
|
@if (!$key->isInUse())
|
||||||
<span class="inline-flex items-center px-2 py-0.5 rounded-sm text-xs font-medium bg-yellow-400 text-black">Unused</span>
|
<span
|
||||||
|
class="inline-flex items-center px-2 py-0.5 rounded-sm text-xs font-medium bg-yellow-400 text-black">Unused</span>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -4,56 +4,58 @@
|
|||||||
</x-slot>
|
</x-slot>
|
||||||
<x-security.navbar />
|
<x-security.navbar />
|
||||||
<div x-data="{ showPrivateKey: false }">
|
<div x-data="{ showPrivateKey: false }">
|
||||||
<form class="flex flex-col gap-2" wire:submit='changePrivateKey'>
|
<form class="flex flex-col" wire:submit='changePrivateKey'>
|
||||||
<div class="flex items-end gap-2">
|
<div class="flex items-start gap-2">
|
||||||
<h2>Private Key</h2>
|
<h2 class="pb-4">Private Key</h2>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@if (data_get($private_key, 'id') > 0)
|
@if (data_get($private_key, 'id') > 0)
|
||||||
<x-modal-confirmation
|
<x-modal-confirmation title="Confirm Private Key Deletion?" isErrorButton buttonTitle="Delete"
|
||||||
title="Confirm Private Key Deletion?"
|
submitAction="delete({{ $private_key->id }})" :actions="[
|
||||||
isErrorButton
|
'This private key will be permanently deleted.',
|
||||||
buttonTitle="Delete"
|
'All servers connected to this private key will stop working.',
|
||||||
submitAction="delete({{ $private_key->id }})"
|
'Any git app using this private key will stop working.',
|
||||||
:actions="['This private key will be permanently deleted.', 'All servers connected to this private key will stop working.', 'Any git app using this private key will stop working.']"
|
]"
|
||||||
confirmationText="{{ $private_key->name }}"
|
confirmationText="{{ $private_key->name }}"
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Private Key Name below"
|
confirmationLabel="Please confirm the execution of the actions by entering the Private Key Name below"
|
||||||
shortConfirmationLabel="Private Key Name"
|
shortConfirmationLabel="Private Key Name" :confirmWithPassword="false"
|
||||||
:confirmWithPassword="false"
|
step2ButtonText="Delete Private Key" />
|
||||||
step2ButtonText="Delete Private Key"
|
|
||||||
/>
|
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input id="private_key.name" label="Name" required />
|
<div class="flex flex-col gap-2">
|
||||||
<x-forms.input id="private_key.description" label="Description" />
|
<div class="flex gap-2">
|
||||||
<div>
|
<x-forms.input id="private_key.name" label="Name" required />
|
||||||
<div class="flex items-end gap-2 py-2 ">
|
<x-forms.input id="private_key.description" label="Description" />
|
||||||
<div class="pl-1 ">Public Key</div>
|
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input readonly id="public_key" />
|
<div>
|
||||||
<div class="flex items-end gap-2 py-2 ">
|
<div class="flex items-end gap-2 py-2 ">
|
||||||
<div class="pl-1 ">Private Key <span class='text-helper'>*</span></div>
|
<div class="pl-1">Public Key</div>
|
||||||
<div class="text-xs underline cursor-pointer dark:text-white" x-cloak x-show="!showPrivateKey"
|
|
||||||
x-on:click="showPrivateKey = true">
|
|
||||||
Edit
|
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs underline cursor-pointer dark:text-white" x-cloak x-show="showPrivateKey"
|
<x-forms.input readonly id="public_key" />
|
||||||
x-on:click="showPrivateKey = false">
|
<div class="flex items-end gap-2 py-2 ">
|
||||||
Hide
|
<div class="pl-1">Private Key <span class='text-helper'>*</span></div>
|
||||||
|
<div class="text-xs underline cursor-pointer dark:text-white" x-cloak x-show="!showPrivateKey"
|
||||||
|
x-on:click="showPrivateKey = true">
|
||||||
|
Edit
|
||||||
|
</div>
|
||||||
|
<div class="text-xs underline cursor-pointer dark:text-white" x-cloak x-show="showPrivateKey"
|
||||||
|
x-on:click="showPrivateKey = false">
|
||||||
|
Hide
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
@if (data_get($private_key, 'is_git_related'))
|
||||||
@if (data_get($private_key, 'is_git_related'))
|
<div class="w-48">
|
||||||
<div class="w-48">
|
<x-forms.checkbox id="private_key.is_git_related" disabled label="Is used by a Git App?" />
|
||||||
<x-forms.checkbox id="private_key.is_git_related" disabled label="Is used by a Git App?" />
|
</div>
|
||||||
|
@endif
|
||||||
|
<div x-cloak x-show="!showPrivateKey">
|
||||||
|
<x-forms.input allowToPeak="false" type="password" rows="10" id="private_key.private_key"
|
||||||
|
required disabled />
|
||||||
|
</div>
|
||||||
|
<div x-cloak x-show="showPrivateKey">
|
||||||
|
<x-forms.textarea rows="10" id="private_key.private_key" required />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
|
||||||
<div x-cloak x-show="!showPrivateKey">
|
|
||||||
<x-forms.input allowToPeak="false" type="password" rows="10" id="private_key.private_key"
|
|
||||||
required disabled />
|
|
||||||
</div>
|
|
||||||
<div x-cloak x-show="showPrivateKey">
|
|
||||||
<x-forms.textarea rows="10" id="private_key.private_key" required />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@@ -42,8 +42,7 @@
|
|||||||
]"
|
]"
|
||||||
confirmationText="DISABLE CLOUDFLARE TUNNEL"
|
confirmationText="DISABLE CLOUDFLARE TUNNEL"
|
||||||
confirmationLabel="Please type the confirmation text to disable Cloudflare Tunnel."
|
confirmationLabel="Please type the confirmation text to disable Cloudflare Tunnel."
|
||||||
shortConfirmationLabel="Confirmation text"
|
shortConfirmationLabel="Confirmation text" />
|
||||||
step3ButtonText="Disable Cloudflare Tunnel" />
|
|
||||||
@else
|
@else
|
||||||
<x-modal-confirmation title="Disable Cloudflare Tunnel?"
|
<x-modal-confirmation title="Disable Cloudflare Tunnel?"
|
||||||
buttonTitle="Disable Cloudflare Tunnel" isErrorButton
|
buttonTitle="Disable Cloudflare Tunnel" isErrorButton
|
||||||
@@ -55,8 +54,7 @@
|
|||||||
]"
|
]"
|
||||||
confirmationText="DISABLE CLOUDFLARE TUNNEL"
|
confirmationText="DISABLE CLOUDFLARE TUNNEL"
|
||||||
confirmationLabel="Please type the confirmation text to disable Cloudflare Tunnel."
|
confirmationLabel="Please type the confirmation text to disable Cloudflare Tunnel."
|
||||||
shortConfirmationLabel="Confirmation text"
|
shortConfirmationLabel="Confirmation text" />
|
||||||
step3ButtonText="Disable Cloudflare Tunnel" />
|
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -120,7 +118,7 @@
|
|||||||
'If you missed something, the connection will not work.',
|
'If you missed something, the connection will not work.',
|
||||||
]" confirmationText="I manually configured Cloudflare Tunnel"
|
]" confirmationText="I manually configured Cloudflare Tunnel"
|
||||||
confirmationLabel="Please type the confirmation text to confirm that you manually configured Cloudflare Tunnel."
|
confirmationLabel="Please type the confirmation text to confirm that you manually configured Cloudflare Tunnel."
|
||||||
shortConfirmationLabel="Confirmation text" step3ButtonText="Confirm" />
|
shortConfirmationLabel="Confirmation text" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
@@ -18,12 +18,12 @@
|
|||||||
<x-modal-confirmation title="Confirm Server Deletion?" isErrorButton buttonTitle="Delete"
|
<x-modal-confirmation title="Confirm Server Deletion?" isErrorButton buttonTitle="Delete"
|
||||||
submitAction="delete" :actions="['This server will be permanently deleted.']" confirmationText="{{ $server->name }}"
|
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"
|
confirmationLabel="Please confirm the execution of the actions by entering the Server Name below"
|
||||||
shortConfirmationLabel="Server Name" step3ButtonText="Permanently Delete" />
|
shortConfirmationLabel="Server Name" />
|
||||||
@else
|
@else
|
||||||
<x-modal-confirmation title="Confirm Server Deletion?" isErrorButton buttonTitle="Delete"
|
<x-modal-confirmation title="Confirm Server Deletion?" isErrorButton buttonTitle="Delete"
|
||||||
submitAction="delete" :actions="['This server will be permanently deleted.']" confirmationText="{{ $server->name }}"
|
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"
|
confirmationLabel="Please confirm the execution of the actions by entering the Server Name below"
|
||||||
shortConfirmationLabel="Server Name" step3ButtonText="Permanently Delete" />
|
shortConfirmationLabel="Server Name" />
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
@@ -9,15 +9,11 @@
|
|||||||
</x-modal-input>
|
</x-modal-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="subtitle">All your servers are here.</div>
|
<div class="subtitle">All your servers are here.</div>
|
||||||
<div class="grid gap-2 lg:grid-cols-2">
|
<div class="grid gap-4 lg:grid-cols-2">
|
||||||
@forelse ($servers as $server)
|
@forelse ($servers as $server)
|
||||||
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
|
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
|
||||||
@class([
|
@class([
|
||||||
'gap-2 border cursor-pointer box group',
|
'gap-2 border cursor-pointer box group',
|
||||||
'border-transparent' =>
|
|
||||||
$server->settings->is_reachable &&
|
|
||||||
$server->settings->is_usable &&
|
|
||||||
!$server->settings->force_disabled,
|
|
||||||
'border-red-500' =>
|
'border-red-500' =>
|
||||||
!$server->settings->is_reachable || $server->settings->force_disabled,
|
!$server->settings->is_reachable || $server->settings->force_disabled,
|
||||||
])>
|
])>
|
||||||
|
79
resources/views/livewire/settings/advanced.blade.php
Normal file
79
resources/views/livewire/settings/advanced.blade.php
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<div>
|
||||||
|
<x-slot:title>
|
||||||
|
Advanced Settings | Coolify
|
||||||
|
</x-slot>
|
||||||
|
<x-settings.navbar />
|
||||||
|
<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-settings.sidebar activeMenu="advanced" />
|
||||||
|
<form wire:submit='submit' class="flex flex-col">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<h2>Advanced</h2>
|
||||||
|
<x-forms.button type="submit">
|
||||||
|
Save
|
||||||
|
</x-forms.button>
|
||||||
|
</div>
|
||||||
|
<div class="pb-4">Advanced settings for your Coolify instance.</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-1 md:w-96">
|
||||||
|
<x-forms.checkbox instantSave id="is_registration_enabled"
|
||||||
|
helper="If enabled, users can register themselves. If disabled, only administrators can create new users."
|
||||||
|
label="Registration Allowed" />
|
||||||
|
<x-forms.checkbox instantSave id="do_not_track"
|
||||||
|
helper="If enabled, Coolify will not track any data. This is useful if you are concerned about privacy."
|
||||||
|
label="Do Not Track" />
|
||||||
|
<h4 class="pt-4">DNS Settings</h4>
|
||||||
|
<x-forms.checkbox instantSave id="is_dns_validation_enabled"
|
||||||
|
helper="If you set a custom domain, Coolify will validate the domain in your DNS provider."
|
||||||
|
label="DNS Validation" />
|
||||||
|
<x-forms.input id="custom_dns_servers" label="Custom DNS Servers"
|
||||||
|
helper="DNS servers to validate domains against. A comma separated list of DNS servers."
|
||||||
|
placeholder="1.1.1.1,8.8.8.8" />
|
||||||
|
<h4 class="pt-4">API Settings</h4>
|
||||||
|
<x-forms.checkbox instantSave id="is_api_enabled" label="API Access"
|
||||||
|
helper="If enabled, the API will be enabled. If disabled, the API will be disabled." />
|
||||||
|
<x-forms.input id="allowed_ips" label="Allowed IPs for API Access"
|
||||||
|
helper="Allowed IP lists for the API. A comma separated list of IPs. Empty means you allow from everywhere."
|
||||||
|
placeholder="1.1.1.1,8.8.8.8" />
|
||||||
|
<h4 class="pt-4">Confirmation Settings</h4>
|
||||||
|
<div class="md:w-96 pb-1">
|
||||||
|
<x-forms.checkbox instantSave id="is_sponsorship_popup_enabled" label="Show Sponsorship Popup"
|
||||||
|
helper="When enabled, sponsorship popups will be shown monthly to users. When disabled, the sponsorship popup will be permanently hidden for all users." />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col gap-1">
|
||||||
|
@if ($disable_two_step_confirmation)
|
||||||
|
<div class="md:w-96 pb-4" wire:key="two-step-confirmation-enabled">
|
||||||
|
<x-forms.checkbox instantSave id="disable_two_step_confirmation"
|
||||||
|
label="Disable Two Step Confirmation"
|
||||||
|
helper="When disabled, you will not need to confirm actions with a text and user password. This significantly reduces security and may lead to accidental deletions or unwanted changes. Use with extreme caution, especially on production servers." />
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<div class="md:w-96 pb-4 flex items-center justify-between gap-2"
|
||||||
|
wire:key="two-step-confirmation-disabled">
|
||||||
|
<label class="flex items-center gap-2">
|
||||||
|
Disable Two Step Confirmation
|
||||||
|
<x-helper
|
||||||
|
helper="When disabled, you will not need to confirm actions with a text and user password. This significantly reduces security and may lead to accidental deletions or unwanted changes. Use with extreme caution, especially on production servers.">
|
||||||
|
</x-helper>
|
||||||
|
</label>
|
||||||
|
<x-modal-confirmation title="Disable Two Step Confirmation?" buttonTitle="Disable" isErrorButton
|
||||||
|
submitAction="toggleTwoStepConfirmation" :actions="[
|
||||||
|
'Two Step confirmation will be disabled globally.',
|
||||||
|
'Disabling two step confirmation reduces security (as anyone can easily delete anything).',
|
||||||
|
'The risk of accidental actions will increase.',
|
||||||
|
]"
|
||||||
|
confirmationText="DISABLE TWO STEP CONFIRMATION"
|
||||||
|
confirmationLabel="Please type the confirmation text to disable two step confirmation."
|
||||||
|
shortConfirmationLabel="Confirmation text" />
|
||||||
|
</div>
|
||||||
|
<div class="w-full px-4 py-2 mb-4 text-white rounded-xs border-l-4 border-red-500 bg-error">
|
||||||
|
<p class="font-bold">Warning!</p>
|
||||||
|
<p>Disabling two step confirmation reduces security (as anyone can easily delete anything) and
|
||||||
|
increases
|
||||||
|
the risk of accidental actions. This is not recommended for production servers.</p>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -3,159 +3,81 @@
|
|||||||
Settings | Coolify
|
Settings | Coolify
|
||||||
</x-slot>
|
</x-slot>
|
||||||
<x-settings.navbar />
|
<x-settings.navbar />
|
||||||
<form wire:submit='submit' class="flex flex-col">
|
<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 items-center gap-2 pb-2">
|
<x-settings.sidebar activeMenu="general" />
|
||||||
<h2>Configuration</h2>
|
<form wire:submit='submit' class="flex flex-col">
|
||||||
<x-forms.button type="submit">
|
<div class="flex items-center gap-2">
|
||||||
Save
|
<h2>General</h2>
|
||||||
</x-forms.button>
|
<x-forms.button type="submit">
|
||||||
</div>
|
Save
|
||||||
<div>General configuration for your Coolify instance.</div>
|
</x-forms.button>
|
||||||
|
</div>
|
||||||
|
<div class="pb-4">General configuration for your Coolify instance.</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<h4 class="pt-6">Instance Settings</h4>
|
<div class="flex flex-wrap items-end gap-2">
|
||||||
<div class="flex flex-wrap items-end gap-2">
|
<div class="flex gap-2 md:flex-row flex-col w-full">
|
||||||
<div class="flex gap-2 md:flex-row flex-col w-full">
|
<x-forms.input id="fqdn" label="Domain"
|
||||||
<x-forms.input id="fqdn" label="Instance's Domain"
|
helper="Enter the full domain name (FQDN) of the instance, including 'https://' if you want to secure the dashboard with HTTPS. Setting this will make the dashboard accessible via this domain, secured by HTTPS, instead of just the IP address."
|
||||||
helper="Enter the full domain name (FQDN) of the instance, including 'https://' if you want to secure the dashboard with HTTPS. Setting this will make the dashboard accessible via this domain, secured by HTTPS, instead of just the IP address."
|
placeholder="https://coolify.yourdomain.com" />
|
||||||
placeholder="https://coolify.yourdomain.com" />
|
<x-forms.input id="instance_name" label="Name" placeholder="Coolify"
|
||||||
<x-forms.input id="instance_name" label="Instance's Name" placeholder="Coolify" />
|
helper="Custom name for your Coolify instance, shown in the URL." />
|
||||||
<div class="w-full" x-data="{
|
<div class="w-full" x-data="{
|
||||||
open: false,
|
open: false,
|
||||||
search: '{{ $settings->instance_timezone ?: '' }}',
|
search: '{{ $settings->instance_timezone ?: '' }}',
|
||||||
timezones: @js($this->timezones),
|
timezones: @js($this->timezones),
|
||||||
placeholder: '{{ $settings->instance_timezone ? 'Search timezone...' : 'Select Server Timezone' }}',
|
placeholder: '{{ $settings->instance_timezone ? 'Search timezone...' : 'Select Server Timezone' }}',
|
||||||
init() {
|
init() {
|
||||||
this.$watch('search', value => {
|
this.$watch('search', value => {
|
||||||
if (value === '') {
|
if (value === '') {
|
||||||
this.open = true;
|
this.open = true;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}">
|
}">
|
||||||
<div class="flex items-center mb-1">
|
<div class="flex items-center mb-1">
|
||||||
<label for="instance_timezone">Instance
|
<label for="instance_timezone">Instance
|
||||||
Timezone</label>
|
Timezone</label>
|
||||||
<x-helper class="ml-2"
|
<x-helper class="ml-2"
|
||||||
helper="Timezone for the Coolify instance. This is used for the update check and automatic update frequency." />
|
helper="Timezone for the Coolify instance. This is used for the update check and automatic update frequency." />
|
||||||
</div>
|
|
||||||
<div class="relative">
|
|
||||||
<div class="inline-flex relative items-center w-full">
|
|
||||||
<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="instance_timezone">
|
|
||||||
<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>
|
||||||
<div x-show="open"
|
<div class="relative">
|
||||||
class="overflow-auto overflow-x-hidden absolute z-50 mt-1 w-full max-h-60 bg-white rounded-md border shadow-lg dark:bg-coolgray-100 dark:border-coolgray-200 scrollbar">
|
<div class="inline-flex relative items-center w-full">
|
||||||
<template
|
<input autocomplete="off"
|
||||||
x-for="timezone in timezones.filter(tz => tz.toLowerCase().includes(search.toLowerCase()))"
|
wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300'
|
||||||
:key="timezone">
|
wire:dirty.class="dark:focus:ring-warning dark:ring-warning" x-model="search"
|
||||||
<div @click="search = timezone; open = false; $wire.set('instance_timezone', timezone); $wire.submit()"
|
@focus="open = true" @click.away="open = false" @input="open = true"
|
||||||
class="px-4 py-2 text-gray-800 cursor-pointer hover:bg-gray-100 dark:hover:bg-coolgray-300 dark:text-gray-200"
|
class="w-full input" :placeholder="placeholder" wire:model="instance_timezone">
|
||||||
x-text="timezone"></div>
|
<svg class="absolute right-0 mr-2 w-4 h-4" xmlns="http://www.w3.org/2000/svg"
|
||||||
</template>
|
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-full 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('instance_timezone', timezone); $wire.submit()"
|
||||||
|
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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex gap-2 md:flex-row flex-col w-full">
|
||||||
|
<x-forms.input id="public_ipv4" type="password" label="Instance's Public IPv4"
|
||||||
|
helper="Enter the IPv4 address of the instance.<br><br>It is useful if you have several IPv4 addresses and Coolify could not detect the correct one."
|
||||||
|
placeholder="1.2.3.4" autocomplete="new-password" />
|
||||||
|
<x-forms.input id="public_ipv6" type="password" label="Instance's Public IPv6"
|
||||||
|
helper="Enter the IPv6 address of the instance.<br><br>It is useful if you have several IPv6 addresses and Coolify could not detect the correct one."
|
||||||
|
placeholder="2001:db8::1" autocomplete="new-password" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2 md:flex-row flex-col w-full">
|
|
||||||
<x-forms.input id="public_ipv4" type="password" label="Instance's IPv4"
|
|
||||||
helper="Enter the IPv4 address of the instance.<br><br>It is useful if you have several IPv4 addresses and Coolify could not detect the correct one."
|
|
||||||
placeholder="1.2.3.4" autocomplete="new-password" />
|
|
||||||
<x-forms.input id="public_ipv6" type="password" label="Instance's IPv6"
|
|
||||||
helper="Enter the IPv6 address of the instance.<br><br>It is useful if you have several IPv6 addresses and Coolify could not detect the correct one."
|
|
||||||
placeholder="2001:db8::1" autocomplete="new-password" />
|
|
||||||
</div>
|
|
||||||
<h4 class="w-full pt-6">DNS Validation</h4>
|
|
||||||
<div class="md:w-96">
|
|
||||||
<x-forms.checkbox instantSave id="is_dns_validation_enabled" label="Enabled" />
|
|
||||||
</div>
|
|
||||||
<x-forms.input id="custom_dns_servers" label="DNS Servers"
|
|
||||||
helper="DNS servers to validate FQDNs against. A comma separated list of DNS servers."
|
|
||||||
placeholder="1.1.1.1,8.8.8.8" />
|
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
{{-- <div class="flex gap-2 ">
|
</div>
|
||||||
<x-forms.input type="number" id="public_port_min" label="Public Port Min" />
|
|
||||||
<x-forms.input type="number" id="public_port_max" label="Public Port Max" />
|
|
||||||
</div> --}}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<h4 class="pt-6">API</h4>
|
|
||||||
<div class="md:w-96 pb-2">
|
|
||||||
<x-forms.checkbox instantSave id="is_api_enabled" label="Enabled" />
|
|
||||||
</div>
|
|
||||||
<x-forms.input id="allowed_ips" label="Allowed IPs"
|
|
||||||
helper="Allowed IP lists for the API. A comma separated list of IPs. Empty means you allow from everywhere."
|
|
||||||
placeholder="1.1.1.1,8.8.8.8" />
|
|
||||||
<h4 class="pt-6">Update</h4>
|
|
||||||
<div class="text-right md:w-96 pb-4">
|
|
||||||
@if (!is_null(config('constants.coolify.autoupdate', null)))
|
|
||||||
<div class="text-right md:w-96">
|
|
||||||
<x-forms.checkbox instantSave helper="AUTOUPDATE is set in .env file, you need to modify it there."
|
|
||||||
disabled checked="{{ config('constants.coolify.autoupdate') }}" label="Auto Update Enabled" />
|
|
||||||
</div>
|
|
||||||
@else
|
|
||||||
<x-forms.checkbox instantSave id="is_auto_update_enabled" label="Auto Update Enabled" />
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<div class="flex items-end gap-2">
|
|
||||||
<x-forms.input required id="update_check_frequency" label="Update Check Frequency"
|
|
||||||
placeholder="0 * * * *"
|
|
||||||
helper="Cron expression for update check frequency (check for new Coolify versions and pull new Service Templates from CDN).<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every hour." />
|
|
||||||
<x-forms.button wire:click='checkManually'>Check Manually</x-forms.button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (is_null(config('constants.coolify.autoupdate', null)) && $is_auto_update_enabled)
|
|
||||||
<x-forms.input required id="auto_update_frequency" label="Auto Update Frequency" placeholder="0 0 * * *"
|
|
||||||
helper="Cron expression for auto update frequency (automatically update coolify).<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every day at 00:00" />
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h4 class="pt-6">Advanced</h4>
|
|
||||||
<div class="text-right md:w-96">
|
|
||||||
<x-forms.checkbox instantSave id="is_registration_enabled" label="Registration Allowed" />
|
|
||||||
<x-forms.checkbox instantSave id="do_not_track" label="Do Not Track" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h4 class="py-4">Confirmation Settings</h4>
|
|
||||||
<div class="md:w-96 ">
|
|
||||||
<x-forms.checkbox instantSave id="is_sponsorship_popup_enabled" label="Show Sponsorship Popup"
|
|
||||||
helper="When enabled, sponsorship popups will be shown monthly to users. When disabled, the sponsorship popup will be permanently hidden for all users." />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if ($disable_two_step_confirmation)
|
|
||||||
<div class="md:w-96 pb-4" wire:key="two-step-confirmation-enabled">
|
|
||||||
<x-forms.checkbox instantSave id="disable_two_step_confirmation" label="Disable Two Step Confirmation"
|
|
||||||
helper="When disabled, you will not need to confirm actions with a text and user password. This significantly reduces security and may lead to accidental deletions or unwanted changes. Use with extreme caution, especially on production servers." />
|
|
||||||
</div>
|
|
||||||
@else
|
|
||||||
<div class="md:w-96 pb-4" wire:key="two-step-confirmation-disabled">
|
|
||||||
<x-modal-confirmation title="Disable Two Step Confirmation?"
|
|
||||||
buttonTitle="Disable Two Step Confirmation" isErrorButton submitAction="toggleTwoStepConfirmation"
|
|
||||||
:actions="[
|
|
||||||
'Two Step confirmation will be disabled globally.',
|
|
||||||
'Disabling two step confirmation reduces security (as anyone can easily delete anything).',
|
|
||||||
'The risk of accidental actions will increase.',
|
|
||||||
]" confirmationText="DISABLE TWO STEP CONFIRMATION"
|
|
||||||
confirmationLabel="Please type the confirmation text to disable two step confirmation."
|
|
||||||
shortConfirmationLabel="Confirmation text" step3ButtonText="Disable Two Step Confirmation" />
|
|
||||||
</div>
|
|
||||||
<div class="w-full px-4 py-2 mb-4 text-white rounded-xs border-l-4 border-red-500 bg-error">
|
|
||||||
<p class="font-bold">Warning!</p>
|
|
||||||
<p>Disabling two step confirmation reduces security (as anyone can easily delete anything) and
|
|
||||||
increases
|
|
||||||
the risk of accidental actions. This is not recommended for production servers.</p>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
|
51
resources/views/livewire/settings/updates.blade.php
Normal file
51
resources/views/livewire/settings/updates.blade.php
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<div>
|
||||||
|
<x-slot:title>
|
||||||
|
Auto Update | Coolify
|
||||||
|
</x-slot>
|
||||||
|
<x-settings.navbar />
|
||||||
|
<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-settings.sidebar activeMenu="updates" />
|
||||||
|
<form wire:submit='submit' class="flex flex-col w-full">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<h2>Updates</h2>
|
||||||
|
<x-forms.button type="submit">
|
||||||
|
Save
|
||||||
|
</x-forms.button>
|
||||||
|
</div>
|
||||||
|
<div class="pb-4">Your instance's update settings.</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<div class="flex items-end gap-2">
|
||||||
|
<x-forms.input required id="update_check_frequency" label="Update Check Frequency"
|
||||||
|
placeholder="0 * * * *"
|
||||||
|
helper="Frequency (cron expression) to check for new Coolify versions and pull new Service Templates from CDN.<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every hour." />
|
||||||
|
<x-forms.button wire:click='checkManually'>Check Manually</x-forms.button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4 class="pt-4">Auto Update</h4>
|
||||||
|
|
||||||
|
<div class="text-right md:w-64">
|
||||||
|
@if (!is_null(config('constants.coolify.autoupdate', null)))
|
||||||
|
<div class="text-right">
|
||||||
|
<x-forms.checkbox instantSave
|
||||||
|
helper="AUTOUPDATE is set in .env file, you need to modify it there." disabled
|
||||||
|
checked="{{ config('constants.coolify.autoupdate') }}" label="Enabled" />
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<x-forms.checkbox instantSave id="is_auto_update_enabled" label="Enabled" />
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
@if (is_null(config('constants.coolify.autoupdate', null)) && $is_auto_update_enabled)
|
||||||
|
<x-forms.input required id="auto_update_frequency" label="Frequency (cron expression)"
|
||||||
|
placeholder="0 0 * * *"
|
||||||
|
helper="Frequency (cron expression) (automatically update coolify).<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every day at 00:00" />
|
||||||
|
@else
|
||||||
|
<x-forms.input required label="Frequency (cron expression)" disabled placeholder="disabled"
|
||||||
|
helper="Frequency (cron expression) (automatically update coolify).<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every day at 00:00" />
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -1,21 +1,28 @@
|
|||||||
<div>
|
<div>
|
||||||
<form class="flex flex-col gap-2 pb-6" wire:submit='submit'>
|
<form class="flex flex-col gap-2 pb-6" wire:submit='submit'>
|
||||||
<div class="flex items-start gap-2">
|
<div class="flex items-start gap-2">
|
||||||
<div class="pb-4">
|
<div class="">
|
||||||
<h1>Storage Details</h1>
|
<h1>Storage Details</h1>
|
||||||
<div class="subtitle">{{ $storage->name }}</div>
|
<div class="subtitle">{{ $storage->name }}</div>
|
||||||
@if ($storage->is_usable)
|
<div class="flex items-center gap-2 pb-4">
|
||||||
<div>Usable</div>
|
<div>Current Status:</div>
|
||||||
@else
|
@if ($storage->is_usable)
|
||||||
<div class="text-red-500">Not Usable</div>
|
<span
|
||||||
@endif
|
class="px-2 py-1 text-xs font-semibold text-green-800 bg-green-100 rounded dark:text-green-100 dark:bg-green-800">
|
||||||
|
Usable
|
||||||
|
</span>
|
||||||
|
@else
|
||||||
|
<span
|
||||||
|
class="px-2 py-1 text-xs font-semibold text-red-800 bg-red-100 rounded dark:text-red-100 dark:bg-red-800">
|
||||||
|
Not Usable
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
<x-forms.button wire:click="test_s3_connection">
|
|
||||||
Validate Connection
|
|
||||||
</x-forms.button>
|
|
||||||
<x-modal-confirmation title="Confirm Storage Deletion?" isErrorButton buttonTitle="Delete"
|
<x-modal-confirmation title="Confirm Storage Deletion?" isErrorButton buttonTitle="Delete"
|
||||||
submitAction="delete({{ $storage->id }})" :actions="[
|
submitAction="delete({{ $storage->id }})" :actions="[
|
||||||
'The selected storage location will be permanently deleted from Coolify.',
|
'The selected storage location will be permanently deleted from Coolify.',
|
||||||
@@ -37,5 +44,8 @@
|
|||||||
<x-forms.input required type="password" label="Access Key" id="storage.key" />
|
<x-forms.input required type="password" label="Access Key" id="storage.key" />
|
||||||
<x-forms.input required type="password" label="Secret Key" id="storage.secret" />
|
<x-forms.input required type="password" label="Secret Key" id="storage.secret" />
|
||||||
</div>
|
</div>
|
||||||
|
<x-forms.button class="mt-4" isHighlighted wire:click="testConnection">
|
||||||
|
Validate Connection
|
||||||
|
</x-forms.button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -9,10 +9,10 @@
|
|||||||
</x-modal-input>
|
</x-modal-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="subtitle">S3 storages for backups.</div>
|
<div class="subtitle">S3 storages for backups.</div>
|
||||||
<div class="grid gap-2 lg:grid-cols-2">
|
<div class="grid gap-4 lg:grid-cols-2">
|
||||||
@forelse ($s3 as $storage)
|
@forelse ($s3 as $storage)
|
||||||
<a href="/storages/{{ $storage->uuid }}" @class(['gap-2 border cursor-pointer box group border-transparent'])>
|
<a href="/storages/{{ $storage->uuid }}" @class(['gap-2 border cursor-pointer box group'])>
|
||||||
<div class="flex flex-col mx-6">
|
<div class="flex flex-col justify-center mx-6">
|
||||||
<div class="box-title">
|
<div class="box-title">
|
||||||
{{ $storage->name }}
|
{{ $storage->name }}
|
||||||
</div>
|
</div>
|
||||||
@@ -20,7 +20,10 @@
|
|||||||
{{ $storage->description }}
|
{{ $storage->description }}
|
||||||
</div>
|
</div>
|
||||||
@if (!$storage->is_usable)
|
@if (!$storage->is_usable)
|
||||||
<div class="text-red-500">Not Usable</div>
|
<span
|
||||||
|
class="px-2 py-1 text-xs font-semibold text-red-800 bg-red-100 rounded dark:text-red-100 dark:bg-red-800">
|
||||||
|
Not Usable
|
||||||
|
</span>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
@@ -7,8 +7,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-wrap gap-2 ">
|
<div class="flex flex-wrap gap-2 ">
|
||||||
@forelse ($tags as $oneTag)
|
@forelse ($tags as $oneTag)
|
||||||
<a :class="{{ $tag?->id == $oneTag->id }} && 'dark:bg-coollabs hover:bg-coollabs-100'"
|
<a :class="{{ $tag?->id == $oneTag->id }} && 'dark:bg-coollabs'"
|
||||||
class="w-64 box-without-bg dark:bg-coolgray-100 dark:text-white font-bold"
|
class="w-32 box-without-bg dark:bg-coolgray-100 dark:text-white font-bold dark:hover:bg-coollabs-100 flex justify-center items-center"
|
||||||
href="{{ route('tags.show', ['tagName' => $oneTag->name]) }}">{{ $oneTag->name }}</a>
|
href="{{ route('tags.show', ['tagName' => $oneTag->name]) }}">{{ $oneTag->name }}</a>
|
||||||
@empty
|
@empty
|
||||||
<div>No tags yet defined yet. Go to a resource and add a tag there.</div>
|
<div>No tags yet defined yet. Go to a resource and add a tag there.</div>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
</div>
|
</div>
|
||||||
@if (isset($tag))
|
@if (isset($tag))
|
||||||
<div>
|
<div>
|
||||||
<h3 class="py-4">Details</h3>
|
<h3 class="py-4">Tag Details</h3>
|
||||||
<div class="flex items-end gap-2 ">
|
<div class="flex items-end gap-2 ">
|
||||||
<div class="w-[500px]">
|
<div class="w-[500px]">
|
||||||
<x-forms.input readonly label="Deploy Webhook URL" id="webhook" />
|
<x-forms.input readonly label="Deploy Webhook URL" id="webhook" />
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
@if (isset($applications) && count($applications) > 0)
|
@if (isset($applications) && count($applications) > 0)
|
||||||
@foreach ($applications as $application)
|
@foreach ($applications as $application)
|
||||||
<a href="{{ $application->link() }}" class="box group">
|
<a href="{{ $application->link() }}" class="box group">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col justify-center">
|
||||||
<div class="box-title">
|
<div class="box-title">
|
||||||
{{ $application->project()->name }}/{{ $application->environment->name }}
|
{{ $application->project()->name }}/{{ $application->environment->name }}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -3,12 +3,16 @@
|
|||||||
Team Admin | Coolify
|
Team Admin | Coolify
|
||||||
</x-slot>
|
</x-slot>
|
||||||
<x-team.navbar />
|
<x-team.navbar />
|
||||||
|
<h2>Admin View</h2>
|
||||||
|
<div class="subtitle">
|
||||||
|
Manage users of this instance.
|
||||||
|
</div>
|
||||||
<form wire:submit="submitSearch" class="flex flex-col gap-2 lg:flex-row">
|
<form wire:submit="submitSearch" class="flex flex-col gap-2 lg:flex-row">
|
||||||
<x-forms.input wire:model="search" placeholder="Search for a user" />
|
<x-forms.input wire:model="search" placeholder="Search for a user" />
|
||||||
<x-forms.button type="submit">Search</x-forms.button>
|
<x-forms.button type="submit">Search</x-forms.button>
|
||||||
</form>
|
</form>
|
||||||
<h3 class="pt-4">Users</h3>
|
<h3 class="py-4">Users</h3>
|
||||||
<div class="flex flex-col gap-2 ">
|
<div class="grid grid-cols-1 gap-2 lg:grid-cols-2">
|
||||||
@forelse ($users as $user)
|
@forelse ($users as $user)
|
||||||
<div wire:key="user-{{ $user->id }}"
|
<div wire:key="user-{{ $user->id }}"
|
||||||
class="flex items-center justify-center gap-2 bg-white box-without-bg dark:bg-coolgray-100">
|
class="flex items-center justify-center gap-2 bg-white box-without-bg dark:bg-coolgray-100">
|
||||||
@@ -23,7 +27,7 @@
|
|||||||
]"
|
]"
|
||||||
confirmationText="{{ $user->name }}"
|
confirmationText="{{ $user->name }}"
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the User Name below"
|
confirmationLabel="Please confirm the execution of the actions by entering the User Name below"
|
||||||
shortConfirmationLabel="User Name" step3ButtonText="Permanently Delete" />
|
shortConfirmationLabel="User Name" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@empty
|
@empty
|
||||||
|
@@ -4,17 +4,19 @@
|
|||||||
</x-slot>
|
</x-slot>
|
||||||
<x-team.navbar />
|
<x-team.navbar />
|
||||||
|
|
||||||
<form class="flex flex-col gap-2 pb-6" wire:submit='submit'>
|
<form class="flex flex-col" wire:submit='submit'>
|
||||||
<div class="flex items-end gap-2">
|
<h2>General</h2>
|
||||||
<h2>General</h2>
|
<div class="subtitle">
|
||||||
|
Manage the general settings of this team.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-end gap-2 pb-6">
|
||||||
|
<x-forms.input id="team.name" label="Name" required />
|
||||||
|
<x-forms.input id="team.description" label="Description" />
|
||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
|
||||||
<x-forms.input id="team.name" label="Name" required />
|
|
||||||
<x-forms.input id="team.description" label="Description" />
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
@@ -4,7 +4,9 @@
|
|||||||
</x-slot>
|
</x-slot>
|
||||||
<x-team.navbar />
|
<x-team.navbar />
|
||||||
<h2>Members</h2>
|
<h2>Members</h2>
|
||||||
|
<div class="subtitle">
|
||||||
|
Manage or invite members of this team.
|
||||||
|
</div>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
@@ -38,8 +40,8 @@
|
|||||||
@else
|
@else
|
||||||
<h2>Invite New Member</h2>
|
<h2>Invite New Member</h2>
|
||||||
@if (isInstanceAdmin())
|
@if (isInstanceAdmin())
|
||||||
<div class="pb-4 text-xs dark:text-warning">You need to configure (as root team) <a href="/settings#smtp"
|
<div class="pb-4 text-xs dark:text-warning">You need to configure (as root team) <a
|
||||||
class="underline dark:text-warning">Transactional
|
href="/settings#smtp" class="underline dark:text-warning">Transactional
|
||||||
Emails</a>
|
Emails</a>
|
||||||
before
|
before
|
||||||
you can invite a
|
you can invite a
|
||||||
|
@@ -1,8 +0,0 @@
|
|||||||
<x-layout>
|
|
||||||
<x-security.navbar />
|
|
||||||
<a class="text-center hover:no-underline group" href="{{ route('security.private-key.index') }}">
|
|
||||||
<div class="dark:group-hover:text-white">
|
|
||||||
<div>Private Keys</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</x-layout>
|
|
@@ -8,25 +8,29 @@
|
|||||||
<livewire:source.github.create />
|
<livewire:source.github.create />
|
||||||
</x-modal-input>
|
</x-modal-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="subtitle ">Git sources for your applications.</div>
|
<div class="subtitle">Git sources for your applications.</div>
|
||||||
<div class="grid gap-2 lg:grid-cols-2">
|
<div class="grid gap-4 lg:grid-cols-2">
|
||||||
@forelse ($sources as $source)
|
@forelse ($sources as $source)
|
||||||
@if ($source->getMorphClass() === 'App\Models\GithubApp')
|
@if ($source->getMorphClass() === 'App\Models\GithubApp')
|
||||||
<a class="flex gap-4 text-center hover:no-underline box group"
|
<a class="flex gap-2 text-center hover:no-underline box group"
|
||||||
href="{{ route('source.github.show', ['github_app_uuid' => data_get($source, 'uuid')]) }}">
|
href="{{ route('source.github.show', ['github_app_uuid' => data_get($source, 'uuid')]) }}">
|
||||||
<x-git-icon class="dark:text-white w-9 h-9" git="{{ $source->getMorphClass() }}" />
|
{{-- <x-git-icon class="dark:text-white w-8 h-8 mt-1" git="{{ $source->getMorphClass() }}" /> --}}
|
||||||
<div class="text-left dark:group-hover:text-white">
|
<div class="text-left dark:group-hover:text-white flex flex-col justify-center mx-6">
|
||||||
<div class="box-title">{{ $source->name }}</div>
|
<div class="box-title">{{ $source->name }}</div>
|
||||||
@if (is_null($source->app_id))
|
@if (is_null($source->app_id))
|
||||||
<span class="box-description text-error! ">Configuration is not finished.</span>
|
<span class="box-description text-error! ">Configuration is not finished.</span>
|
||||||
|
@else
|
||||||
|
@if ($source->organization)
|
||||||
|
<span class="box-description">Organization: {{ $source->organization }}</span>
|
||||||
|
@endif
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
@endif
|
@endif
|
||||||
@if ($source->getMorphClass() === 'App\Models\GitlabApp')
|
{{-- @if ($source->getMorphClass() === 'App\Models\GitlabApp')
|
||||||
<a class="flex gap-4 text-center hover:no-underline box group"
|
<a class="flex gap-4 text-center hover:no-underline box group"
|
||||||
href="{{ route('source.gitlab.show', ['gitlab_app_uuid' => data_get($source, 'uuid')]) }}">
|
href="{{ route('source.gitlab.show', ['gitlab_app_uuid' => data_get($source, 'uuid')]) }}">
|
||||||
<x-git-icon class="dark:text-white w-9 h-9" git="{{ $source->getMorphClass() }}" />
|
<x-git-icon class="dark:text-white w-8 h-8" git="{{ $source->getMorphClass() }}" />
|
||||||
<div class="text-left dark:group-hover:text-white">
|
<div class="text-left dark:group-hover:text-white">
|
||||||
<div>{{ $source->name }}</div>
|
<div>{{ $source->name }}</div>
|
||||||
@if (is_null($source->app_id))
|
@if (is_null($source->app_id))
|
||||||
@@ -34,7 +38,7 @@
|
|||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
@endif
|
@endif --}}
|
||||||
@empty
|
@empty
|
||||||
<div>
|
<div>
|
||||||
<div>No sources found.</div>
|
<div>No sources found.</div>
|
||||||
|
@@ -52,7 +52,9 @@ use App\Livewire\Server\Proxy\Show as ProxyShow;
|
|||||||
use App\Livewire\Server\Resources as ResourcesShow;
|
use App\Livewire\Server\Resources as ResourcesShow;
|
||||||
use App\Livewire\Server\Security\Patches;
|
use App\Livewire\Server\Security\Patches;
|
||||||
use App\Livewire\Server\Show as ServerShow;
|
use App\Livewire\Server\Show as ServerShow;
|
||||||
|
use App\Livewire\Settings\Advanced as SettingsAdvanced;
|
||||||
use App\Livewire\Settings\Index as SettingsIndex;
|
use App\Livewire\Settings\Index as SettingsIndex;
|
||||||
|
use App\Livewire\Settings\Updates as SettingsUpdates;
|
||||||
use App\Livewire\SettingsBackup;
|
use App\Livewire\SettingsBackup;
|
||||||
use App\Livewire\SettingsEmail;
|
use App\Livewire\SettingsEmail;
|
||||||
use App\Livewire\SettingsOauth;
|
use App\Livewire\SettingsOauth;
|
||||||
@@ -105,6 +107,9 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
|||||||
Route::get('/subscription/new', SubscriptionIndex::class)->name('subscription.index');
|
Route::get('/subscription/new', SubscriptionIndex::class)->name('subscription.index');
|
||||||
|
|
||||||
Route::get('/settings', SettingsIndex::class)->name('settings.index');
|
Route::get('/settings', SettingsIndex::class)->name('settings.index');
|
||||||
|
Route::get('/settings/advanced', SettingsAdvanced::class)->name('settings.advanced');
|
||||||
|
Route::get('/settings/updates', SettingsUpdates::class)->name('settings.updates');
|
||||||
|
|
||||||
Route::get('/settings/backup', SettingsBackup::class)->name('settings.backup');
|
Route::get('/settings/backup', SettingsBackup::class)->name('settings.backup');
|
||||||
Route::get('/settings/email', SettingsEmail::class)->name('settings.email');
|
Route::get('/settings/email', SettingsEmail::class)->name('settings.email');
|
||||||
Route::get('/settings/oauth', SettingsOauth::class)->name('settings.oauth');
|
Route::get('/settings/oauth', SettingsOauth::class)->name('settings.oauth');
|
||||||
|
@@ -5,14 +5,17 @@
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
appwrite:
|
appwrite:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
container_name: appwrite
|
container_name: appwrite
|
||||||
volumes:
|
volumes:
|
||||||
- appwrite-uploads:/storage/uploads:rw
|
- appwrite-uploads:/storage/uploads:rw
|
||||||
|
- appwrite-imports:/storage/imports:rw
|
||||||
- appwrite-cache:/storage/cache:rw
|
- appwrite-cache:/storage/cache:rw
|
||||||
- appwrite-config:/storage/config:rw
|
- appwrite-config:/storage/config:rw
|
||||||
- appwrite-certificates:/storage/certificates:rw
|
- appwrite-certificates:/storage/certificates:rw
|
||||||
- appwrite-functions:/storage/functions:rw
|
- appwrite-functions:/storage/functions:rw
|
||||||
|
- appwrite-sites:/storage/sites:rw
|
||||||
|
- appwrite-builds:/storage/builds:rw
|
||||||
depends_on:
|
depends_on:
|
||||||
- appwrite-mariadb
|
- appwrite-mariadb
|
||||||
- appwrite-redis
|
- appwrite-redis
|
||||||
@@ -21,10 +24,12 @@ services:
|
|||||||
- _APP_ENV=${_APP_ENV:-production}
|
- _APP_ENV=${_APP_ENV:-production}
|
||||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||||
- _APP_LOCALE=${_APP_LOCALE:-en}
|
- _APP_LOCALE=${_APP_LOCALE:-en}
|
||||||
|
- _APP_COMPRESSION_MIN_SIZE_BYTES=${_APP_COMPRESSION_MIN_SIZE_BYTES}
|
||||||
- _APP_CONSOLE_WHITELIST_ROOT=${_APP_CONSOLE_WHITELIST_ROOT:-enabled}
|
- _APP_CONSOLE_WHITELIST_ROOT=${_APP_CONSOLE_WHITELIST_ROOT:-enabled}
|
||||||
- _APP_CONSOLE_WHITELIST_EMAILS=${_APP_CONSOLE_WHITELIST_EMAILS}
|
- _APP_CONSOLE_WHITELIST_EMAILS=${_APP_CONSOLE_WHITELIST_EMAILS}
|
||||||
|
- _APP_CONSOLE_SESSION_ALERTS=${_APP_CONSOLE_SESSION_ALERTS}
|
||||||
- _APP_CONSOLE_WHITELIST_IPS=${_APP_CONSOLE_WHITELIST_IPS}
|
- _APP_CONSOLE_WHITELIST_IPS=${_APP_CONSOLE_WHITELIST_IPS}
|
||||||
- _APP_CONSOLE_HOSTNAMES=${_APP_CONSOLE_HOSTNAMES:-localhost,appwrite.io,*.appwrite.io}
|
- _APP_CONSOLE_HOSTNAMES=${_APP_CONSOLE_HOSTNAMES}
|
||||||
- _APP_SYSTEM_EMAIL_NAME=${_APP_SYSTEM_EMAIL_NAME:-Appwrite}
|
- _APP_SYSTEM_EMAIL_NAME=${_APP_SYSTEM_EMAIL_NAME:-Appwrite}
|
||||||
- _APP_SYSTEM_EMAIL_ADDRESS=${_APP_SYSTEM_EMAIL_ADDRESS:-team@appwrite.io}
|
- _APP_SYSTEM_EMAIL_ADDRESS=${_APP_SYSTEM_EMAIL_ADDRESS:-team@appwrite.io}
|
||||||
- _APP_SYSTEM_TEAM_EMAIL=${_APP_SYSTEM_TEAM_EMAIL:-team@appwrite.io}
|
- _APP_SYSTEM_TEAM_EMAIL=${_APP_SYSTEM_TEAM_EMAIL:-team@appwrite.io}
|
||||||
@@ -33,10 +38,12 @@ services:
|
|||||||
- _APP_OPTIONS_ABUSE=${_APP_OPTIONS_ABUSE:-enabled}
|
- _APP_OPTIONS_ABUSE=${_APP_OPTIONS_ABUSE:-enabled}
|
||||||
- _APP_OPTIONS_ROUTER_PROTECTION=${_APP_OPTIONS_ROUTER_PROTECTION:-disabled}
|
- _APP_OPTIONS_ROUTER_PROTECTION=${_APP_OPTIONS_ROUTER_PROTECTION:-disabled}
|
||||||
- _APP_OPTIONS_FORCE_HTTPS=${_APP_OPTIONS_FORCE_HTTPS:-disabled}
|
- _APP_OPTIONS_FORCE_HTTPS=${_APP_OPTIONS_FORCE_HTTPS:-disabled}
|
||||||
- _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=${_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS:-disabled}
|
- _APP_OPTIONS_ROUTER_FORCE_HTTPS=${_APP_OPTIONS_ROUTER_FORCE_HTTPS:-disabled}
|
||||||
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
||||||
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
||||||
- _APP_DOMAIN_TARGET=$SERVICE_URL_APPWRITE
|
- _APP_DOMAIN_TARGET_CNAME=${_APP_DOMAIN_TARGET_CNAME:-localhost}
|
||||||
|
- _APP_DOMAIN_TARGET_AAAA=${_APP_DOMAIN_TARGET_AAAA:-::1}
|
||||||
|
- _APP_DOMAIN_TARGET_A=${_APP_DOMAIN_TARGET_A:-127.0.0.1}
|
||||||
- _APP_DOMAIN_FUNCTIONS=$SERVICE_URL_APPWRITE
|
- _APP_DOMAIN_FUNCTIONS=$SERVICE_URL_APPWRITE
|
||||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||||
@@ -63,6 +70,7 @@ services:
|
|||||||
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
||||||
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
||||||
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
||||||
|
- _APP_STORAGE_S3_ENDPOINT=${_APP_STORAGE_S3_ENDPOINT}
|
||||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
||||||
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
||||||
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
||||||
@@ -79,21 +87,26 @@ services:
|
|||||||
- _APP_STORAGE_WASABI_SECRET=${_APP_STORAGE_WASABI_SECRET}
|
- _APP_STORAGE_WASABI_SECRET=${_APP_STORAGE_WASABI_SECRET}
|
||||||
- _APP_STORAGE_WASABI_REGION=${_APP_STORAGE_WASABI_REGION:-eu-central-1}
|
- _APP_STORAGE_WASABI_REGION=${_APP_STORAGE_WASABI_REGION:-eu-central-1}
|
||||||
- _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET}
|
- _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET}
|
||||||
- _APP_FUNCTIONS_SIZE_LIMIT=${_APP_FUNCTIONS_SIZE_LIMIT:-30000000}
|
- _APP_COMPUTE_SIZE_LIMIT=${_APP_COMPUTE_SIZE_LIMIT:-30000000}
|
||||||
- _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT:-900}
|
- _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT:-900}
|
||||||
- _APP_FUNCTIONS_BUILD_TIMEOUT=${_APP_FUNCTIONS_BUILD_TIMEOUT:-900}
|
- _APP_SITES_TIMEOUT=${_APP_SITES_TIMEOUT:-900}
|
||||||
- _APP_FUNCTIONS_CPUS=${_APP_FUNCTIONS_CPUS:-0}
|
- _APP_COMPUTE_BUILD_TIMEOUT=${_APP_COMPUTE_BUILD_TIMEOUT:-900}
|
||||||
- _APP_FUNCTIONS_MEMORY=${_APP_FUNCTIONS_MEMORY:-0}
|
- _APP_COMPUTE_CPUS=${_APP_COMPUTE_CPUS:-0}
|
||||||
|
- _APP_COMPUTE_MEMORY=${_APP_COMPUTE_MEMORY:-0}
|
||||||
- _APP_FUNCTIONS_RUNTIMES=${_APP_FUNCTIONS_RUNTIMES:-node-20.0,php-8.2,python-3.11,ruby-3.2}
|
- _APP_FUNCTIONS_RUNTIMES=${_APP_FUNCTIONS_RUNTIMES:-node-20.0,php-8.2,python-3.11,ruby-3.2}
|
||||||
|
- _APP_SITES_RUNTIMES=${_APP_SITES_RUNTIMES}
|
||||||
|
- _APP_DOMAIN_SITES=${_APP_DOMAIN_SITES:-appwrite.network}
|
||||||
- _APP_EXECUTOR_SECRET=$SERVICE_PASSWORD_64_APPWRITE
|
- _APP_EXECUTOR_SECRET=$SERVICE_PASSWORD_64_APPWRITE
|
||||||
- _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST:-http://appwrite-executor/v1}
|
- _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST:-http://appwrite-executor/v1}
|
||||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||||
- _APP_MAINTENANCE_INTERVAL=${_APP_MAINTENANCE_INTERVAL:-86400}
|
- _APP_MAINTENANCE_INTERVAL=${_APP_MAINTENANCE_INTERVAL:-86400}
|
||||||
- _APP_MAINTENANCE_DELAY=${_APP_MAINTENANCE_DELAY}
|
- _APP_MAINTENANCE_DELAY=${_APP_MAINTENANCE_DELAY}
|
||||||
|
- _APP_MAINTENANCE_START_TIME=${_APP_MAINTENANCE_START_TIME}
|
||||||
- _APP_MAINTENANCE_RETENTION_EXECUTION=${_APP_MAINTENANCE_RETENTION_EXECUTION:-1209600}
|
- _APP_MAINTENANCE_RETENTION_EXECUTION=${_APP_MAINTENANCE_RETENTION_EXECUTION:-1209600}
|
||||||
- _APP_MAINTENANCE_RETENTION_CACHE=${_APP_MAINTENANCE_RETENTION_CACHE:-2592000}
|
- _APP_MAINTENANCE_RETENTION_CACHE=${_APP_MAINTENANCE_RETENTION_CACHE:-2592000}
|
||||||
- _APP_MAINTENANCE_RETENTION_ABUSE=${_APP_MAINTENANCE_RETENTION_ABUSE:-86400}
|
- _APP_MAINTENANCE_RETENTION_ABUSE=${_APP_MAINTENANCE_RETENTION_ABUSE:-86400}
|
||||||
- _APP_MAINTENANCE_RETENTION_AUDIT=${_APP_MAINTENANCE_RETENTION_AUDIT:-1209600}
|
- _APP_MAINTENANCE_RETENTION_AUDIT=${_APP_MAINTENANCE_RETENTION_AUDIT:-1209600}
|
||||||
|
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=${_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE}
|
||||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=${_APP_MAINTENANCE_RETENTION_USAGE_HOURLY:-8640000}
|
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=${_APP_MAINTENANCE_RETENTION_USAGE_HOURLY:-8640000}
|
||||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES=${_APP_MAINTENANCE_RETENTION_SCHEDULES:-86400}
|
- _APP_MAINTENANCE_RETENTION_SCHEDULES=${_APP_MAINTENANCE_RETENTION_SCHEDULES:-86400}
|
||||||
- _APP_SMS_PROVIDER=${_APP_SMS_PROVIDER}
|
- _APP_SMS_PROVIDER=${_APP_SMS_PROVIDER}
|
||||||
@@ -112,13 +125,13 @@ services:
|
|||||||
- _APP_ASSISTANT_OPENAI_API_KEY=${_APP_ASSISTANT_OPENAI_API_KEY}
|
- _APP_ASSISTANT_OPENAI_API_KEY=${_APP_ASSISTANT_OPENAI_API_KEY}
|
||||||
|
|
||||||
appwrite-console:
|
appwrite-console:
|
||||||
image: appwrite/console:5.0.12
|
image: appwrite/console:6.0.13
|
||||||
container_name: appwrite-console
|
container_name: appwrite-console
|
||||||
environment:
|
environment:
|
||||||
- SERVICE_FQDN_APPWRITE=/console
|
- SERVICE_FQDN_APPWRITE=/console
|
||||||
|
|
||||||
appwrite-realtime:
|
appwrite-realtime:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: realtime
|
entrypoint: realtime
|
||||||
container_name: appwrite-realtime
|
container_name: appwrite-realtime
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -129,6 +142,7 @@ services:
|
|||||||
- _APP_ENV=${_APP_ENV:-production}
|
- _APP_ENV=${_APP_ENV:-production}
|
||||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||||
- _APP_OPTIONS_ABUSE=${_APP_OPTIONS_ABUSE:-enabled}
|
- _APP_OPTIONS_ABUSE=${_APP_OPTIONS_ABUSE:-enabled}
|
||||||
|
- _APP_OPTIONS_ROUTER_PROTECTION=${_APP_OPTIONS_ROUTER_PROTECTION:-disabled}
|
||||||
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
||||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||||
@@ -143,7 +157,7 @@ services:
|
|||||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||||
|
|
||||||
appwrite-worker-audits:
|
appwrite-worker-audits:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: worker-audits
|
entrypoint: worker-audits
|
||||||
container_name: appwrite-worker-audits
|
container_name: appwrite-worker-audits
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -165,7 +179,7 @@ services:
|
|||||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||||
|
|
||||||
appwrite-worker-webhooks:
|
appwrite-worker-webhooks:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: worker-webhooks
|
entrypoint: worker-webhooks
|
||||||
container_name: appwrite-worker-webhooks
|
container_name: appwrite-worker-webhooks
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -189,7 +203,7 @@ services:
|
|||||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||||
|
|
||||||
appwrite-worker-deletes:
|
appwrite-worker-deletes:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: worker-deletes
|
entrypoint: worker-deletes
|
||||||
container_name: appwrite-worker-deletes
|
container_name: appwrite-worker-deletes
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -199,6 +213,7 @@ services:
|
|||||||
- appwrite-uploads:/storage/uploads:rw
|
- appwrite-uploads:/storage/uploads:rw
|
||||||
- appwrite-cache:/storage/cache:rw
|
- appwrite-cache:/storage/cache:rw
|
||||||
- appwrite-functions:/storage/functions:rw
|
- appwrite-functions:/storage/functions:rw
|
||||||
|
- appwrite-sites:/storage/sites:rw
|
||||||
- appwrite-builds:/storage/builds:rw
|
- appwrite-builds:/storage/builds:rw
|
||||||
- appwrite-certificates:/storage/certificates:rw
|
- appwrite-certificates:/storage/certificates:rw
|
||||||
environment:
|
environment:
|
||||||
@@ -215,10 +230,11 @@ services:
|
|||||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||||
- _APP_STORAGE_DEVICE=${_APP_STORAGE_DEVICE:-local}
|
- _APP_STORAGE_DEVICE=${_APP_STORAGE_DEVICE:-local}
|
||||||
- _APP_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY:-local}
|
- _APP_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY}
|
||||||
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
||||||
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
||||||
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
||||||
|
- _APP_STORAGE_S3_ENDPOINT=${_APP_STORAGE_S3_ENDPOINT}
|
||||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
||||||
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
||||||
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
||||||
@@ -240,10 +256,13 @@ services:
|
|||||||
- _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST:-http://appwrite-executor/v1}
|
- _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST:-http://appwrite-executor/v1}
|
||||||
- _APP_MAINTENANCE_RETENTION_ABUSE=${_APP_MAINTENANCE_RETENTION_ABUSE:-86400}
|
- _APP_MAINTENANCE_RETENTION_ABUSE=${_APP_MAINTENANCE_RETENTION_ABUSE:-86400}
|
||||||
- _APP_MAINTENANCE_RETENTION_AUDIT=${_APP_MAINTENANCE_RETENTION_AUDIT:-1209600}
|
- _APP_MAINTENANCE_RETENTION_AUDIT=${_APP_MAINTENANCE_RETENTION_AUDIT:-1209600}
|
||||||
|
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=${_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE}
|
||||||
- _APP_MAINTENANCE_RETENTION_EXECUTION=${_APP_MAINTENANCE_RETENTION_EXECUTION:-1209600}
|
- _APP_MAINTENANCE_RETENTION_EXECUTION=${_APP_MAINTENANCE_RETENTION_EXECUTION:-1209600}
|
||||||
|
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS=${_APP_SYSTEM_SECURITY_EMAIL_ADDRESS}
|
||||||
|
- _APP_EMAIL_CERTIFICATES=${_APP_EMAIL_CERTIFICATES}
|
||||||
|
|
||||||
appwrite-worker-databases:
|
appwrite-worker-databases:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: worker-databases
|
entrypoint: worker-databases
|
||||||
container_name: appwrite-worker-databases
|
container_name: appwrite-worker-databases
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -265,7 +284,7 @@ services:
|
|||||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||||
|
|
||||||
appwrite-worker-builds:
|
appwrite-worker-builds:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: worker-builds
|
entrypoint: worker-builds
|
||||||
container_name: appwrite-worker-builds
|
container_name: appwrite-worker-builds
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -273,7 +292,9 @@ services:
|
|||||||
- appwrite-mariadb
|
- appwrite-mariadb
|
||||||
volumes:
|
volumes:
|
||||||
- appwrite-functions:/storage/functions:rw
|
- appwrite-functions:/storage/functions:rw
|
||||||
|
- appwrite-sites:/storage/sites:rw
|
||||||
- appwrite-builds:/storage/builds:rw
|
- appwrite-builds:/storage/builds:rw
|
||||||
|
- appwrite-uploads:/storage/uploads:rw
|
||||||
environment:
|
environment:
|
||||||
- _APP_ENV=${_APP_ENV:-production}
|
- _APP_ENV=${_APP_ENV:-production}
|
||||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||||
@@ -294,18 +315,20 @@ services:
|
|||||||
- _APP_VCS_GITHUB_PRIVATE_KEY=${_APP_VCS_GITHUB_PRIVATE_KEY}
|
- _APP_VCS_GITHUB_PRIVATE_KEY=${_APP_VCS_GITHUB_PRIVATE_KEY}
|
||||||
- _APP_VCS_GITHUB_APP_ID=${_APP_VCS_GITHUB_APP_ID}
|
- _APP_VCS_GITHUB_APP_ID=${_APP_VCS_GITHUB_APP_ID}
|
||||||
- _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT:-900}
|
- _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT:-900}
|
||||||
- _APP_FUNCTIONS_BUILD_TIMEOUT=${_APP_FUNCTIONS_BUILD_TIMEOUT:-900}
|
- _APP_SITES_TIMEOUT=${_APP_SITES_TIMEOUT:-900}
|
||||||
- _APP_FUNCTIONS_CPUS=${_APP_FUNCTIONS_CPUS:-0}
|
- _APP_COMPUTE_BUILD_TIMEOUT=${_APP_COMPUTE_BUILD_TIMEOUT:-900}
|
||||||
- _APP_FUNCTIONS_MEMORY=${_APP_FUNCTIONS_MEMORY:-0}
|
- _APP_COMPUTE_CPUS=${_APP_COMPUTE_CPUS:-0}
|
||||||
- _APP_FUNCTIONS_SIZE_LIMIT=${_APP_FUNCTIONS_SIZE_LIMIT:-30000000}
|
- _APP_COMPUTE_MEMORY=${_APP_COMPUTE_MEMORY:-0}
|
||||||
|
- _APP_COMPUTE_SIZE_LIMIT=${_APP_COMPUTE_SIZE_LIMIT:-30000000}
|
||||||
- _APP_OPTIONS_FORCE_HTTPS=${_APP_OPTIONS_FORCE_HTTPS:-disabled}
|
- _APP_OPTIONS_FORCE_HTTPS=${_APP_OPTIONS_FORCE_HTTPS:-disabled}
|
||||||
- _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=${_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS:-disabled}
|
- _APP_OPTIONS_ROUTER_FORCE_HTTPS=${_APP_OPTIONS_ROUTER_FORCE_HTTPS:-disabled}
|
||||||
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
||||||
- _APP_STORAGE_DEVICE=${_APP_STORAGE_DEVICE:-local}
|
- _APP_STORAGE_DEVICE=${_APP_STORAGE_DEVICE:-local}
|
||||||
- _APP_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY:-local}
|
- _APP_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY}
|
||||||
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
||||||
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
||||||
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
||||||
|
- _APP_STORAGE_S3_ENDPOINT=${_APP_STORAGE_S3_ENDPOINT}
|
||||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
||||||
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
||||||
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
||||||
@@ -322,9 +345,10 @@ services:
|
|||||||
- _APP_STORAGE_WASABI_SECRET=${_APP_STORAGE_WASABI_SECRET}
|
- _APP_STORAGE_WASABI_SECRET=${_APP_STORAGE_WASABI_SECRET}
|
||||||
- _APP_STORAGE_WASABI_REGION=${_APP_STORAGE_WASABI_REGION:-eu-central-1}
|
- _APP_STORAGE_WASABI_REGION=${_APP_STORAGE_WASABI_REGION:-eu-central-1}
|
||||||
- _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET}
|
- _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET}
|
||||||
|
- _APP_DOMAIN_SITES=${_APP_DOMAIN_SITES}
|
||||||
|
|
||||||
appwrite-worker-certificates:
|
appwrite-worker-certificates:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: worker-certificates
|
entrypoint: worker-certificates
|
||||||
container_name: appwrite-worker-certificates
|
container_name: appwrite-worker-certificates
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -338,10 +362,11 @@ services:
|
|||||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||||
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
||||||
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
||||||
- _APP_DOMAIN_TARGET=$SERVICE_URL_APPWRITE
|
- _APP_DOMAIN_TARGET_CNAME=${_APP_DOMAIN_TARGET_CNAME}
|
||||||
|
- _APP_DOMAIN_TARGET_AAAA=${_APP_DOMAIN_TARGET_AAAA}
|
||||||
|
- _APP_DOMAIN_TARGET_A=${_APP_DOMAIN_TARGET_A}
|
||||||
- _APP_DOMAIN_FUNCTIONS=$SERVICE_URL_APPWRITE
|
- _APP_DOMAIN_FUNCTIONS=$SERVICE_URL_APPWRITE
|
||||||
- _APP_EMAIL_CERTIFICATES=${_APP_EMAIL_CERTIFICATES:-enabled}
|
- _APP_EMAIL_CERTIFICATES=${_APP_EMAIL_CERTIFICATES:-enabled}
|
||||||
- _APP_EMAIL_SECURITY=${_APP_EMAIL_SECURITY:-certs@appwrite.io}
|
|
||||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||||
@@ -354,7 +379,7 @@ services:
|
|||||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||||
|
|
||||||
appwrite-worker-functions:
|
appwrite-worker-functions:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: worker-functions
|
entrypoint: worker-functions
|
||||||
container_name: appwrite-worker-functions
|
container_name: appwrite-worker-functions
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -377,9 +402,10 @@ services:
|
|||||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||||
- _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT:-900}
|
- _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT:-900}
|
||||||
- _APP_FUNCTIONS_BUILD_TIMEOUT=${_APP_FUNCTIONS_BUILD_TIMEOUT:-900}
|
- _APP_SITES_TIMEOUT=${_APP_SITES_TIMEOUT:-900}
|
||||||
- _APP_FUNCTIONS_CPUS=${_APP_FUNCTIONS_CPUS:-0}
|
- _APP_COMPUTE_BUILD_TIMEOUT=${_APP_COMPUTE_BUILD_TIMEOUT:-900}
|
||||||
- _APP_FUNCTIONS_MEMORY=${_APP_FUNCTIONS_MEMORY:-0}
|
- _APP_COMPUTE_CPUS=${_APP_COMPUTE_CPUS:-0}
|
||||||
|
- _APP_COMPUTE_MEMORY=${_APP_COMPUTE_MEMORY:-0}
|
||||||
- _APP_EXECUTOR_SECRET=$SERVICE_PASSWORD_64_APPWRITE
|
- _APP_EXECUTOR_SECRET=$SERVICE_PASSWORD_64_APPWRITE
|
||||||
- _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST:-http://appwrite-executor/v1}
|
- _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST:-http://appwrite-executor/v1}
|
||||||
- _APP_USAGE_STATS=${_APP_USAGE_STATS:-enabled}
|
- _APP_USAGE_STATS=${_APP_USAGE_STATS:-enabled}
|
||||||
@@ -388,7 +414,7 @@ services:
|
|||||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||||
|
|
||||||
appwrite-worker-mails:
|
appwrite-worker-mails:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: worker-mails
|
entrypoint: worker-mails
|
||||||
container_name: appwrite-worker-mails
|
container_name: appwrite-worker-mails
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -415,9 +441,10 @@ services:
|
|||||||
- _APP_SMTP_PASSWORD=${_APP_SMTP_PASSWORD}
|
- _APP_SMTP_PASSWORD=${_APP_SMTP_PASSWORD}
|
||||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||||
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
||||||
|
- _APP_OPTIONS_FORCE_HTTPS=${_APP_OPTIONS_FORCE_HTTPS:-disabled}
|
||||||
|
|
||||||
appwrite-worker-messaging:
|
appwrite-worker-messaging:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: worker-messaging
|
entrypoint: worker-messaging
|
||||||
container_name: appwrite-worker-messaging
|
container_name: appwrite-worker-messaging
|
||||||
volumes:
|
volumes:
|
||||||
@@ -445,6 +472,7 @@ services:
|
|||||||
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
||||||
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
||||||
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
||||||
|
- _APP_STORAGE_S3_ENDPOINT=${_APP_STORAGE_S3_ENDPOINT}
|
||||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
||||||
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
||||||
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
||||||
@@ -463,9 +491,11 @@ services:
|
|||||||
- _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET}
|
- _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET}
|
||||||
|
|
||||||
appwrite-worker-migrations:
|
appwrite-worker-migrations:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: worker-migrations
|
entrypoint: worker-migrations
|
||||||
container_name: appwrite-worker-migrations
|
container_name: appwrite-worker-migrations
|
||||||
|
volumes:
|
||||||
|
- appwrite-imports:/storage/imports:rw
|
||||||
depends_on:
|
depends_on:
|
||||||
- appwrite-mariadb
|
- appwrite-mariadb
|
||||||
environment:
|
environment:
|
||||||
@@ -473,7 +503,9 @@ services:
|
|||||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||||
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
||||||
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
||||||
- _APP_DOMAIN_TARGET=$SERVICE_URL_APPWRITE
|
- _APP_DOMAIN_TARGET_CNAME=${_APP_DOMAIN_TARGET_CNAME}
|
||||||
|
- _APP_DOMAIN_TARGET_AAAA=${_APP_DOMAIN_TARGET_AAAA}
|
||||||
|
- _APP_DOMAIN_TARGET_A=${_APP_DOMAIN_TARGET_A}
|
||||||
- _APP_EMAIL_SECURITY=${_APP_EMAIL_SECURITY:-certs@appwrite.io}
|
- _APP_EMAIL_SECURITY=${_APP_EMAIL_SECURITY:-certs@appwrite.io}
|
||||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||||
@@ -489,7 +521,7 @@ services:
|
|||||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=${_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET}
|
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=${_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET}
|
||||||
|
|
||||||
appwrite-task-maintenance:
|
appwrite-task-maintenance:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: maintenance
|
entrypoint: maintenance
|
||||||
container_name: appwrite-task-maintenance
|
container_name: appwrite-task-maintenance
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -498,7 +530,9 @@ services:
|
|||||||
- _APP_ENV=${_APP_ENV:-production}
|
- _APP_ENV=${_APP_ENV:-production}
|
||||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||||
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
||||||
- _APP_DOMAIN_TARGET=$SERVICE_URL_APPWRITE
|
- _APP_DOMAIN_TARGET_CNAME=${_APP_DOMAIN_TARGET_CNAME}
|
||||||
|
- _APP_DOMAIN_TARGET_AAAA=${_APP_DOMAIN_TARGET_AAAA}
|
||||||
|
- _APP_DOMAIN_TARGET_A=${_APP_DOMAIN_TARGET_A}
|
||||||
- _APP_DOMAIN_FUNCTIONS=$SERVICE_URL_APPWRITE
|
- _APP_DOMAIN_FUNCTIONS=$SERVICE_URL_APPWRITE
|
||||||
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
||||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||||
@@ -515,14 +549,14 @@ services:
|
|||||||
- _APP_MAINTENANCE_RETENTION_CACHE=${_APP_MAINTENANCE_RETENTION_CACHE:-2592000}
|
- _APP_MAINTENANCE_RETENTION_CACHE=${_APP_MAINTENANCE_RETENTION_CACHE:-2592000}
|
||||||
- _APP_MAINTENANCE_RETENTION_ABUSE=${_APP_MAINTENANCE_RETENTION_ABUSE:-86400}
|
- _APP_MAINTENANCE_RETENTION_ABUSE=${_APP_MAINTENANCE_RETENTION_ABUSE:-86400}
|
||||||
- _APP_MAINTENANCE_RETENTION_AUDIT=${_APP_MAINTENANCE_RETENTION_AUDIT:-1209600}
|
- _APP_MAINTENANCE_RETENTION_AUDIT=${_APP_MAINTENANCE_RETENTION_AUDIT:-1209600}
|
||||||
|
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=${_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE}
|
||||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=${_APP_MAINTENANCE_RETENTION_USAGE_HOURLY:-8640000}
|
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=${_APP_MAINTENANCE_RETENTION_USAGE_HOURLY:-8640000}
|
||||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES=${_APP_MAINTENANCE_RETENTION_SCHEDULES:-86400}
|
- _APP_MAINTENANCE_RETENTION_SCHEDULES=${_APP_MAINTENANCE_RETENTION_SCHEDULES:-86400}
|
||||||
|
|
||||||
appwrite-worker-usage:
|
appwrite-task-stats-resources:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: worker-usage
|
container_name: appwrite-task-stats-resources
|
||||||
container_name: appwrite-worker-usage
|
entrypoint: stats-resources
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- appwrite-redis
|
- appwrite-redis
|
||||||
- appwrite-mariadb
|
- appwrite-mariadb
|
||||||
@@ -541,12 +575,37 @@ services:
|
|||||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||||
- _APP_USAGE_STATS=${_APP_USAGE_STATS:-enabled}
|
- _APP_USAGE_STATS=${_APP_USAGE_STATS:-enabled}
|
||||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||||
- _APP_USAGE_AGGREGATION_INTERVAL=${_APP_USAGE_AGGREGATION_INTERVAL:-30}
|
- _APP_DATABASE_SHARED_TABLES=${_APP_DATABASE_SHARED_TABLES}
|
||||||
|
- _APP_STATS_RESOURCES_INTERVAL=${_APP_STATS_RESOURCES_INTERVAL}
|
||||||
|
|
||||||
appwrite-worker-usage-dump:
|
appwrite-worker-stats-resources:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: worker-usage-dump
|
entrypoint: worker-stats-resources
|
||||||
container_name: appwrite-worker-usage-dump
|
container_name: appwrite-worker-stats-resources
|
||||||
|
depends_on:
|
||||||
|
- appwrite-redis
|
||||||
|
- appwrite-mariadb
|
||||||
|
environment:
|
||||||
|
- _APP_ENV=${_APP_ENV:-production}
|
||||||
|
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||||
|
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
||||||
|
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||||
|
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||||
|
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||||
|
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||||
|
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||||
|
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||||
|
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||||
|
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||||
|
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||||
|
- _APP_USAGE_STATS=${_APP_USAGE_STATS:-enabled}
|
||||||
|
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||||
|
- _APP_STATS_RESOURCES_INTERVAL=${_APP_STATS_RESOURCES_INTERVAL}
|
||||||
|
|
||||||
|
appwrite-worker-stats-usage:
|
||||||
|
image: appwrite/appwrite:1.7.4
|
||||||
|
entrypoint: worker-stats-usage
|
||||||
|
container_name: appwrite-worker-stats-usage
|
||||||
depends_on:
|
depends_on:
|
||||||
- appwrite-redis
|
- appwrite-redis
|
||||||
- appwrite-mariadb
|
- appwrite-mariadb
|
||||||
@@ -568,7 +627,7 @@ services:
|
|||||||
- _APP_USAGE_AGGREGATION_INTERVAL=${_APP_USAGE_AGGREGATION_INTERVAL:-30}
|
- _APP_USAGE_AGGREGATION_INTERVAL=${_APP_USAGE_AGGREGATION_INTERVAL:-30}
|
||||||
|
|
||||||
appwrite-task-scheduler-functions:
|
appwrite-task-scheduler-functions:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: schedule-functions
|
entrypoint: schedule-functions
|
||||||
container_name: appwrite-task-scheduler-functions
|
container_name: appwrite-task-scheduler-functions
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -589,7 +648,7 @@ services:
|
|||||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||||
|
|
||||||
appwrite-task-scheduler-executions:
|
appwrite-task-scheduler-executions:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: schedule-executions
|
entrypoint: schedule-executions
|
||||||
container_name: appwrite-task-scheduler-executions
|
container_name: appwrite-task-scheduler-executions
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -610,7 +669,7 @@ services:
|
|||||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||||
|
|
||||||
appwrite-task-scheduler-messages:
|
appwrite-task-scheduler-messages:
|
||||||
image: appwrite/appwrite:1.6.0
|
image: appwrite/appwrite:1.7.4
|
||||||
entrypoint: schedule-messages
|
entrypoint: schedule-messages
|
||||||
container_name: appwrite-task-scheduler-messages
|
container_name: appwrite-task-scheduler-messages
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -636,33 +695,40 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- _APP_ASSISTANT_OPENAI_API_KEY=${_APP_ASSISTANT_OPENAI_API_KEY}
|
- _APP_ASSISTANT_OPENAI_API_KEY=${_APP_ASSISTANT_OPENAI_API_KEY}
|
||||||
|
|
||||||
|
appwrite-browser:
|
||||||
|
image: appwrite/browser:0.2.4
|
||||||
|
container_name: appwrite-browser
|
||||||
|
|
||||||
openruntimes-executor:
|
openruntimes-executor:
|
||||||
container_name: openruntimes-executor
|
container_name: openruntimes-executor
|
||||||
hostname: appwrite-executor
|
hostname: appwrite-executor
|
||||||
stop_signal: SIGINT
|
stop_signal: SIGINT
|
||||||
image: openruntimes/executor:0.6.11
|
image: openruntimes/executor:0.7.14
|
||||||
networks:
|
networks:
|
||||||
- runtimes
|
- runtimes
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- appwrite-builds:/storage/builds:rw
|
- appwrite-builds:/storage/builds:rw
|
||||||
- appwrite-functions:/storage/functions:rw
|
- appwrite-functions:/storage/functions:rw
|
||||||
|
- appwrite-sites:/storage/sites:rw
|
||||||
- /tmp:/tmp:rw
|
- /tmp:/tmp:rw
|
||||||
environment:
|
environment:
|
||||||
- OPR_EXECUTOR_INACTIVE_TRESHOLD=${_APP_FUNCTIONS_INACTIVE_THRESHOLD}
|
- OPR_EXECUTOR_INACTIVE_TRESHOLD=${_APP_COMPUTE_INACTIVE_THRESHOLD}
|
||||||
- OPR_EXECUTOR_MAINTENANCE_INTERVAL=${_APP_FUNCTIONS_MAINTENANCE_INTERVAL}
|
- OPR_EXECUTOR_MAINTENANCE_INTERVAL=${_APP_COMPUTE_MAINTENANCE_INTERVAL}
|
||||||
- OPR_EXECUTOR_NETWORK=${_APP_FUNCTIONS_RUNTIMES_NETWORK:-runtimes}
|
- OPR_EXECUTOR_NETWORK=${_APP_COMPUTE_RUNTIMES_NETWORK:-runtimes}
|
||||||
- OPR_EXECUTOR_DOCKER_HUB_USERNAME=${_APP_DOCKER_HUB_USERNAME}
|
- OPR_EXECUTOR_DOCKER_HUB_USERNAME=${_APP_DOCKER_HUB_USERNAME}
|
||||||
- OPR_EXECUTOR_DOCKER_HUB_PASSWORD=${_APP_DOCKER_HUB_PASSWORD}
|
- OPR_EXECUTOR_DOCKER_HUB_PASSWORD=${_APP_DOCKER_HUB_PASSWORD}
|
||||||
- OPR_EXECUTOR_ENV=${_APP_ENV:-production}
|
- OPR_EXECUTOR_ENV=${_APP_ENV:-production}
|
||||||
- OPR_EXECUTOR_RUNTIMES=${_APP_FUNCTIONS_RUNTIMES}
|
- OPR_EXECUTOR_RUNTIMES=${_APP_FUNCTIONS_RUNTIMES},${_APP_SITES_RUNTIMES}
|
||||||
- OPR_EXECUTOR_SECRET=$SERVICE_PASSWORD_64_APPWRITE
|
- OPR_EXECUTOR_SECRET=$SERVICE_PASSWORD_64_APPWRITE
|
||||||
|
- OPR_EXECUTOR_RUNTIME_VERSIONS=v5
|
||||||
- OPR_EXECUTOR_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
- OPR_EXECUTOR_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||||
- OPR_EXECUTOR_STORAGE_DEVICE=${_APP_STORAGE_DEVICE:-local}
|
- OPR_EXECUTOR_STORAGE_DEVICE=${_APP_STORAGE_DEVICE:-local}
|
||||||
- OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY:-local}
|
- OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY}
|
||||||
- OPR_EXECUTOR_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
- OPR_EXECUTOR_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
||||||
- OPR_EXECUTOR_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION}
|
- OPR_EXECUTOR_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION}
|
||||||
- OPR_EXECUTOR_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
- OPR_EXECUTOR_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
||||||
|
- OPR_EXECUTOR_STORAGE_S3_ENDPOINT=${_APP_STORAGE_S3_ENDPOINT}
|
||||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
- OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
||||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
- OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
||||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION}
|
- OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION}
|
||||||
@@ -703,6 +769,7 @@ services:
|
|||||||
--maxmemory-samples 5
|
--maxmemory-samples 5
|
||||||
volumes:
|
volumes:
|
||||||
- appwrite-redis:/data:rw
|
- appwrite-redis:/data:rw
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
runtimes:
|
runtimes:
|
||||||
name: runtimes
|
name: runtimes
|
||||||
@@ -712,7 +779,9 @@ volumes:
|
|||||||
appwrite-redis:
|
appwrite-redis:
|
||||||
appwrite-cache:
|
appwrite-cache:
|
||||||
appwrite-uploads:
|
appwrite-uploads:
|
||||||
|
appwrite-imports:
|
||||||
appwrite-certificates:
|
appwrite-certificates:
|
||||||
appwrite-functions:
|
appwrite-functions:
|
||||||
|
appwrite-sites:
|
||||||
appwrite-builds:
|
appwrite-builds:
|
||||||
appwrite-config:
|
appwrite-config:
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
authentik-server:
|
authentik-server:
|
||||||
image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2025.4.1}
|
image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2025.6.3}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: server
|
command: server
|
||||||
environment:
|
environment:
|
||||||
@@ -35,7 +35,7 @@ services:
|
|||||||
redis:
|
redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
authentik-worker:
|
authentik-worker:
|
||||||
image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2025.4.1}
|
image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2025.6.3}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: worker
|
command: worker
|
||||||
environment:
|
environment:
|
||||||
|
21
templates/compose/excalidraw.yaml
Normal file
21
templates/compose/excalidraw.yaml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# documentation: https://docs.excalidraw.com/docs
|
||||||
|
# slogan: Virtual whiteboard for sketching hand-drawn like diagrams
|
||||||
|
# tags: canvas,diagrams,drawing,productivity,whiteboard
|
||||||
|
# logo: svgs/excalidraw.svg
|
||||||
|
# port: 80
|
||||||
|
|
||||||
|
services:
|
||||||
|
excalidraw:
|
||||||
|
image: excalidraw/excalidraw:latest
|
||||||
|
environment:
|
||||||
|
- SERVICE_FQDN_EXCALIDRAW_80
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
- CMD
|
||||||
|
- wget
|
||||||
|
- '--spider'
|
||||||
|
- '--quiet'
|
||||||
|
- 'http://localhost'
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
File diff suppressed because one or more lines are too long
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"coolify": {
|
"coolify": {
|
||||||
"v4": {
|
"v4": {
|
||||||
"version": "4.0.0-beta.420.1"
|
"version": "4.0.0-beta.420.2"
|
||||||
},
|
},
|
||||||
"nightly": {
|
"nightly": {
|
||||||
"version": "4.0.0-beta.421"
|
"version": "4.0.0-beta.420.3"
|
||||||
},
|
},
|
||||||
"helper": {
|
"helper": {
|
||||||
"version": "1.0.8"
|
"version": "1.0.8"
|
||||||
|
Reference in New Issue
Block a user