commit
89c6563e00
@ -15,6 +15,9 @@ public function handle(Server $server, bool $async = true): string|Activity
|
||||
{
|
||||
try {
|
||||
$proxyType = $server->proxyType();
|
||||
if ($proxyType === 'NONE') {
|
||||
return 'OK';
|
||||
}
|
||||
$commands = collect([]);
|
||||
$proxy_path = get_proxy_path();
|
||||
$configuration = CheckConfiguration::run($server);
|
||||
|
@ -77,6 +77,9 @@ function (Scope $scope) {
|
||||
);
|
||||
}
|
||||
);
|
||||
if (str($e->getMessage())->contains('No space left on device')) {
|
||||
return;
|
||||
}
|
||||
ray('reporting to sentry');
|
||||
Integration::captureUnhandledException($e);
|
||||
});
|
||||
|
@ -374,6 +374,7 @@ private function deploy_docker_compose_buildpack()
|
||||
$this->cleanup_git();
|
||||
$this->application->loadComposeFile(isInit: false);
|
||||
if ($this->application->settings->is_raw_compose_deployment_enabled) {
|
||||
$this->application->parseRawCompose();
|
||||
$yaml = $composeFile = $this->application->docker_compose_raw;
|
||||
} else {
|
||||
$composeFile = $this->application->parseCompose(pull_request_id: $this->pull_request_id);
|
||||
@ -413,16 +414,33 @@ private function deploy_docker_compose_buildpack()
|
||||
]);
|
||||
}
|
||||
$this->write_deployment_configurations();
|
||||
|
||||
// Start compose file
|
||||
if ($this->docker_compose_custom_start_command) {
|
||||
$this->execute_remote_command(
|
||||
[executeInDocker($this->deployment_uuid, "cd {$this->basedir} && {$this->docker_compose_custom_start_command}"), "hidden" => true],
|
||||
);
|
||||
if ($this->application->settings->is_raw_compose_deployment_enabled) {
|
||||
if ($this->docker_compose_custom_start_command) {
|
||||
$this->execute_remote_command(
|
||||
["cd {$this->basedir} && {$this->docker_compose_custom_start_command}", "hidden" => true],
|
||||
);
|
||||
} else {
|
||||
$server_workdir = $this->application->workdir();
|
||||
ray("SOURCE_COMMIT={$this->commit} docker compose --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d");
|
||||
$this->execute_remote_command(
|
||||
["SOURCE_COMMIT={$this->commit} docker compose --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d", "hidden" => true],
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$this->execute_remote_command(
|
||||
[executeInDocker($this->deployment_uuid, "SOURCE_COMMIT={$this->commit} docker compose --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up -d"), "hidden" => true],
|
||||
);
|
||||
if ($this->docker_compose_custom_start_command) {
|
||||
$this->execute_remote_command(
|
||||
[executeInDocker($this->deployment_uuid, "cd {$this->basedir} && {$this->docker_compose_custom_start_command}"), "hidden" => true],
|
||||
);
|
||||
} else {
|
||||
$this->execute_remote_command(
|
||||
[executeInDocker($this->deployment_uuid, "SOURCE_COMMIT={$this->commit} docker compose --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up -d"), "hidden" => true],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$this->application_deployment_queue->addLogEntry("New container started.");
|
||||
}
|
||||
private function deploy_dockerfile_buildpack()
|
||||
|
@ -51,6 +51,9 @@ public function __construct($backup)
|
||||
{
|
||||
$this->backup = $backup;
|
||||
$this->team = Team::find($backup->team_id);
|
||||
if (is_null($this->team)) {
|
||||
return;
|
||||
}
|
||||
if (data_get($this->backup, 'database_type') === 'App\Models\ServiceDatabase') {
|
||||
$this->database = data_get($this->backup, 'database');
|
||||
$this->server = $this->database->service->server;
|
||||
@ -316,7 +319,7 @@ public function handle(): void
|
||||
private function backup_standalone_mongodb(string $databaseWithCollections): void
|
||||
{
|
||||
try {
|
||||
$url = $this->database->getDbUrl(useInternal: true);
|
||||
$url = $this->database->get_db_url(useInternal: true);
|
||||
if ($databaseWithCollections === 'all') {
|
||||
$commands[] = "mkdir -p " . $this->backup_dir;
|
||||
$commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=$url --gzip --archive > $this->backup_location";
|
||||
|
@ -9,6 +9,8 @@ class Advanced extends Component
|
||||
{
|
||||
public Application $application;
|
||||
public bool $is_force_https_enabled;
|
||||
public bool $is_gzip_enabled;
|
||||
public bool $is_stripprefix_enabled;
|
||||
protected $rules = [
|
||||
'application.settings.is_git_submodules_enabled' => 'boolean|required',
|
||||
'application.settings.is_git_lfs_enabled' => 'boolean|required',
|
||||
@ -19,13 +21,17 @@ class Advanced extends Component
|
||||
'application.settings.is_gpu_enabled' => 'boolean|required',
|
||||
'application.settings.is_build_server_enabled' => 'boolean|required',
|
||||
'application.settings.is_consistent_container_name_enabled' => 'boolean|required',
|
||||
'application.settings.is_gzip_enabled' => 'boolean|required',
|
||||
'application.settings.is_stripprefix_enabled' => 'boolean|required',
|
||||
'application.settings.gpu_driver' => 'string|required',
|
||||
'application.settings.gpu_count' => 'string|required',
|
||||
'application.settings.gpu_device_ids' => 'string|required',
|
||||
'application.settings.gpu_options' => 'string|required',
|
||||
];
|
||||
public function mount() {
|
||||
$this->is_force_https_enabled = $this->application->settings->is_force_https_enabled;
|
||||
$this->is_force_https_enabled = $this->application->isForceHttpsEnabled();
|
||||
$this->is_gzip_enabled = $this->application->isGzipEnabled();
|
||||
$this->is_stripprefix_enabled = $this->application->isStripprefixEnabled();
|
||||
}
|
||||
public function instantSave()
|
||||
{
|
||||
@ -40,6 +46,14 @@ public function instantSave()
|
||||
$this->application->settings->is_force_https_enabled = $this->is_force_https_enabled;
|
||||
$this->dispatch('resetDefaultLabels', false);
|
||||
}
|
||||
if ($this->application->settings->is_gzip_enabled !== $this->is_gzip_enabled) {
|
||||
$this->application->settings->is_gzip_enabled = $this->is_gzip_enabled;
|
||||
$this->dispatch('resetDefaultLabels', false);
|
||||
}
|
||||
if ($this->application->settings->is_stripprefix_enabled !== $this->is_stripprefix_enabled) {
|
||||
$this->application->settings->is_stripprefix_enabled = $this->is_stripprefix_enabled;
|
||||
$this->dispatch('resetDefaultLabels', false);
|
||||
}
|
||||
$this->application->settings->save();
|
||||
$this->dispatch('success', 'Settings saved.');
|
||||
}
|
||||
|
@ -263,7 +263,11 @@ public function submit($showToaster = true)
|
||||
}
|
||||
if ($this->application->build_pack === 'dockercompose') {
|
||||
$this->application->docker_compose_domains = json_encode($this->parsedServiceDomains);
|
||||
$this->parsedServices = $this->application->parseCompose();
|
||||
if ($this->application->settings->is_raw_compose_deployment_enabled) {
|
||||
$this->application->parseRawCompose();
|
||||
} else {
|
||||
$this->parsedServices = $this->application->parseCompose();
|
||||
}
|
||||
}
|
||||
$this->application->custom_labels = base64_encode($this->customLabels);
|
||||
$this->application->save();
|
||||
|
@ -46,9 +46,9 @@ class General extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->db_url = $this->database->getDbUrl(true);
|
||||
$this->db_url = $this->database->get_db_url(true);
|
||||
if ($this->database->is_public) {
|
||||
$this->db_url_public = $this->database->getDbUrl();
|
||||
$this->db_url_public = $this->database->get_db_url();
|
||||
}
|
||||
}
|
||||
public function instantSaveAdvanced() {
|
||||
@ -93,7 +93,7 @@ public function instantSave()
|
||||
return;
|
||||
}
|
||||
StartDatabaseProxy::run($this->database);
|
||||
$this->db_url_public = $this->database->getDbUrl();
|
||||
$this->db_url_public = $this->database->get_db_url();
|
||||
$this->dispatch('success', 'Database is now publicly accessible.');
|
||||
} else {
|
||||
StopDatabaseProxy::run($this->database);
|
||||
|
@ -44,9 +44,9 @@ class General extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->db_url = $this->database->getDbUrl(true);
|
||||
$this->db_url = $this->database->get_db_url(true);
|
||||
if ($this->database->is_public) {
|
||||
$this->db_url_public = $this->database->getDbUrl();
|
||||
$this->db_url_public = $this->database->get_db_url();
|
||||
}
|
||||
}
|
||||
public function instantSaveAdvanced()
|
||||
@ -95,7 +95,7 @@ public function instantSave()
|
||||
return;
|
||||
}
|
||||
StartDatabaseProxy::run($this->database);
|
||||
$this->db_url_public = $this->database->getDbUrl();
|
||||
$this->db_url_public = $this->database->get_db_url();
|
||||
$this->dispatch('success', 'Database is now publicly accessible.');
|
||||
} else {
|
||||
StopDatabaseProxy::run($this->database);
|
||||
|
@ -46,9 +46,9 @@ class General extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->db_url = $this->database->getDbUrl(true);
|
||||
$this->db_url = $this->database->get_db_url(true);
|
||||
if ($this->database->is_public) {
|
||||
$this->db_url_public = $this->database->getDbUrl();
|
||||
$this->db_url_public = $this->database->get_db_url();
|
||||
}
|
||||
}
|
||||
public function instantSaveAdvanced()
|
||||
@ -94,7 +94,7 @@ public function instantSave()
|
||||
return;
|
||||
}
|
||||
StartDatabaseProxy::run($this->database);
|
||||
$this->db_url_public = $this->database->getDbUrl();
|
||||
$this->db_url_public = $this->database->get_db_url();
|
||||
$this->dispatch('success', 'Database is now publicly accessible.');
|
||||
} else {
|
||||
StopDatabaseProxy::run($this->database);
|
||||
|
@ -53,9 +53,9 @@ class General extends Component
|
||||
];
|
||||
public function mount()
|
||||
{
|
||||
$this->db_url = $this->database->getDbUrl(true);
|
||||
$this->db_url = $this->database->get_db_url(true);
|
||||
if ($this->database->is_public) {
|
||||
$this->db_url_public = $this->database->getDbUrl();
|
||||
$this->db_url_public = $this->database->get_db_url();
|
||||
}
|
||||
}
|
||||
public function instantSaveAdvanced() {
|
||||
@ -87,7 +87,7 @@ public function instantSave()
|
||||
return;
|
||||
}
|
||||
StartDatabaseProxy::run($this->database);
|
||||
$this->db_url_public = $this->database->getDbUrl();
|
||||
$this->db_url_public = $this->database->get_db_url();
|
||||
$this->dispatch('success', 'Database is now publicly accessible.');
|
||||
} else {
|
||||
StopDatabaseProxy::run($this->database);
|
||||
|
@ -39,9 +39,9 @@ class General extends Component
|
||||
];
|
||||
public function mount()
|
||||
{
|
||||
$this->db_url = $this->database->getDbUrl(true);
|
||||
$this->db_url = $this->database->get_db_url(true);
|
||||
if ($this->database->is_public) {
|
||||
$this->db_url_public = $this->database->getDbUrl();
|
||||
$this->db_url_public = $this->database->get_db_url();
|
||||
}
|
||||
}
|
||||
public function instantSaveAdvanced() {
|
||||
@ -86,7 +86,7 @@ public function instantSave()
|
||||
return;
|
||||
}
|
||||
StartDatabaseProxy::run($this->database);
|
||||
$this->db_url_public = $this->database->getDbUrl();
|
||||
$this->db_url_public = $this->database->get_db_url();
|
||||
$this->dispatch('success', 'Database is now publicly accessible.');
|
||||
} else {
|
||||
StopDatabaseProxy::run($this->database);
|
||||
|
@ -18,6 +18,7 @@ public function getListeners()
|
||||
$userId = auth()->user()->id;
|
||||
return [
|
||||
"echo-private:user.{$userId},ServiceStatusChanged" => 'check_status',
|
||||
"check_status"
|
||||
];
|
||||
}
|
||||
public function render()
|
||||
|
@ -6,7 +6,6 @@
|
||||
use App\Actions\Service\StartService;
|
||||
use App\Actions\Service\StopService;
|
||||
use App\Events\ServiceStatusChanged;
|
||||
use App\Jobs\ContainerStatusJob;
|
||||
use App\Models\Service;
|
||||
use Livewire\Component;
|
||||
use Spatie\Activitylog\Models\Activity;
|
||||
@ -27,6 +26,10 @@ public function serviceStatusChanged()
|
||||
{
|
||||
$this->dispatch('refresh')->self();
|
||||
}
|
||||
public function check_status() {
|
||||
$this->dispatch('check_status');
|
||||
$this->dispatch('success', 'Service status updated.');
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.service.navbar');
|
||||
|
@ -18,6 +18,7 @@ class ServiceApplicationView extends Component
|
||||
'application.required_fqdn' => 'required|boolean',
|
||||
'application.is_log_drain_enabled' => 'nullable|boolean',
|
||||
'application.is_gzip_enabled' => 'nullable|boolean',
|
||||
'application.is_stripprefix_enabled' => 'nullable|boolean',
|
||||
];
|
||||
public function render()
|
||||
{
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
use App\Actions\Proxy\CheckConfiguration;
|
||||
use App\Actions\Proxy\SaveConfiguration;
|
||||
use App\Actions\Proxy\StartProxy;
|
||||
use App\Models\Server;
|
||||
use Livewire\Component;
|
||||
use Illuminate\Support\Str;
|
||||
@ -26,7 +27,7 @@ public function mount()
|
||||
|
||||
public function proxyStatusUpdated()
|
||||
{
|
||||
$this->server->refresh();
|
||||
$this->dispatch('refresh')->self();
|
||||
}
|
||||
|
||||
public function change_proxy()
|
||||
@ -41,6 +42,9 @@ public function select_proxy($proxy_type)
|
||||
$this->server->proxy->set('type', $proxy_type);
|
||||
$this->server->save();
|
||||
$this->selectedProxy = $this->server->proxy->type;
|
||||
if ($this->selectedProxy !== 'NONE') {
|
||||
StartProxy::run($this->server, false);
|
||||
}
|
||||
$this->dispatch('proxyStatusUpdated');
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
use Spatie\Activitylog\Models\Activity;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
class Application extends BaseModel
|
||||
@ -79,6 +80,18 @@ public function is_github_based(): bool
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public function isForceHttpsEnabled()
|
||||
{
|
||||
return data_get($this, 'settings.is_force_https_enabled', false);
|
||||
}
|
||||
public function isStripprefixEnabled()
|
||||
{
|
||||
return data_get($this, 'settings.is_stripprefix_enabled', true);
|
||||
}
|
||||
public function isGzipEnabled()
|
||||
{
|
||||
return data_get($this, 'settings.is_gzip_enabled', true);
|
||||
}
|
||||
public function link()
|
||||
{
|
||||
if (data_get($this, 'environment.project.uuid')) {
|
||||
@ -476,6 +489,10 @@ public function isHealthcheckDisabled(): bool
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public function workdir()
|
||||
{
|
||||
return application_configuration_dir() . "/{$this->uuid}";
|
||||
}
|
||||
public function isLogDrainEnabled()
|
||||
{
|
||||
return data_get($this, 'settings.is_log_drain_enabled', false);
|
||||
@ -710,6 +727,64 @@ function generateGitImportCommands(string $deployment_uuid, int $pull_request_id
|
||||
];
|
||||
}
|
||||
}
|
||||
function parseRawCompose()
|
||||
{
|
||||
try {
|
||||
$yaml = Yaml::parse($this->docker_compose_raw);
|
||||
} catch (\Exception $e) {
|
||||
throw new \Exception($e->getMessage());
|
||||
}
|
||||
$services = data_get($yaml, 'services');
|
||||
$commands = collect([]);
|
||||
$services = collect($services)->map(function ($service) use ($commands) {
|
||||
$serviceVolumes = collect(data_get($service, 'volumes', []));
|
||||
if ($serviceVolumes->count() > 0) {
|
||||
foreach ($serviceVolumes as $volume) {
|
||||
$workdir = $this->workdir();
|
||||
$type = null;
|
||||
$source = null;
|
||||
if (is_string($volume)) {
|
||||
$source = Str::of($volume)->before(':');
|
||||
if ($source->startsWith('./') || $source->startsWith('/') || $source->startsWith('~')) {
|
||||
$type = Str::of('bind');
|
||||
}
|
||||
} else if (is_array($volume)) {
|
||||
$type = data_get_str($volume, 'type');
|
||||
$source = data_get_str($volume, 'source');
|
||||
}
|
||||
if ($type->value() === 'bind') {
|
||||
if ($source->value() === "/var/run/docker.sock") {
|
||||
continue;
|
||||
}
|
||||
if ($source->value() === '/tmp' || $source->value() === '/tmp/') {
|
||||
continue;
|
||||
}
|
||||
if ($source->startsWith('.')) {
|
||||
$source = $source->after('.');
|
||||
$source = $workdir . $source;
|
||||
}
|
||||
$commands->push("mkdir -p $source > /dev/null 2>&1 || true");
|
||||
}
|
||||
}
|
||||
}
|
||||
$labels = collect(data_get($service, 'labels', []));
|
||||
if (!$labels->contains('coolify.managed')) {
|
||||
$labels->push('coolify.managed=true');
|
||||
}
|
||||
if (!$labels->contains('coolify.applicationId')) {
|
||||
$labels->push('coolify.applicationId=' . $this->id);
|
||||
}
|
||||
if (!$labels->contains('coolify.type')) {
|
||||
$labels->push('coolify.type=application');
|
||||
}
|
||||
data_set($service, 'labels', $labels->toArray());
|
||||
return $service;
|
||||
});
|
||||
data_set($yaml, 'services', $services->toArray());
|
||||
$this->docker_compose_raw = Yaml::dump($yaml, 10, 2);
|
||||
|
||||
instant_remote_process($commands, $this->destination->server, false);
|
||||
}
|
||||
function parseCompose(int $pull_request_id = 0)
|
||||
{
|
||||
if ($this->docker_compose_raw) {
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class LocalFileVolume extends BaseModel
|
||||
{
|
||||
|
@ -23,6 +23,10 @@ public function isLogDrainEnabled()
|
||||
{
|
||||
return data_get($this, 'is_log_drain_enabled', false);
|
||||
}
|
||||
public function isStripprefixEnabled()
|
||||
{
|
||||
return data_get($this, 'is_stripprefix_enabled', true);
|
||||
}
|
||||
public function isGzipEnabled()
|
||||
{
|
||||
return data_get($this, 'is_gzip_enabled', true);
|
||||
|
@ -21,9 +21,13 @@ public function isLogDrainEnabled()
|
||||
{
|
||||
return data_get($this, 'is_log_drain_enabled', false);
|
||||
}
|
||||
public function isStripprefixEnabled()
|
||||
{
|
||||
return data_get($this, 'is_stripprefix_enabled', true);
|
||||
}
|
||||
public function isGzipEnabled()
|
||||
{
|
||||
return true;
|
||||
return data_get($this, 'is_gzip_enabled', true);
|
||||
}
|
||||
public function type()
|
||||
{
|
||||
|
@ -126,7 +126,7 @@ public function portsMappingsArray(): Attribute
|
||||
);
|
||||
}
|
||||
|
||||
public function getDbUrl(bool $useInternal = false): string
|
||||
public function get_db_url(bool $useInternal = false): string
|
||||
{
|
||||
if ($this->is_public && !$useInternal) {
|
||||
return "mysql://{$this->mariadb_user}:{$this->mariadb_password}@{$this->destination->server->getIp}:{$this->public_port}/{$this->mariadb_database}";
|
||||
|
@ -142,7 +142,7 @@ public function type(): string
|
||||
{
|
||||
return 'standalone-mongodb';
|
||||
}
|
||||
public function getDbUrl(bool $useInternal = false)
|
||||
public function get_db_url(bool $useInternal = false)
|
||||
{
|
||||
if ($this->is_public && !$useInternal) {
|
||||
return "mongodb://{$this->mongo_initdb_root_username}:{$this->mongo_initdb_root_password}@{$this->destination->server->getIp}:{$this->public_port}/?directConnection=true";
|
||||
|
@ -127,7 +127,7 @@ public function portsMappingsArray(): Attribute
|
||||
);
|
||||
}
|
||||
|
||||
public function getDbUrl(bool $useInternal = false): string
|
||||
public function get_db_url(bool $useInternal = false): string
|
||||
{
|
||||
if ($this->is_public && !$useInternal) {
|
||||
return "mysql://{$this->mysql_user}:{$this->mysql_password}@{$this->destination->server->getIp}:{$this->public_port}/{$this->mysql_database}";
|
||||
|
@ -126,7 +126,7 @@ public function type(): string
|
||||
{
|
||||
return 'standalone-postgresql';
|
||||
}
|
||||
public function getDbUrl(bool $useInternal = false): string
|
||||
public function get_db_url(bool $useInternal = false): string
|
||||
{
|
||||
if ($this->is_public && !$useInternal) {
|
||||
return "postgres://{$this->postgres_user}:{$this->postgres_password}@{$this->destination->server->getIp}:{$this->public_port}/{$this->postgres_db}";
|
||||
|
@ -122,7 +122,7 @@ public function type(): string
|
||||
{
|
||||
return 'standalone-redis';
|
||||
}
|
||||
public function getDbUrl(bool $useInternal = false): string
|
||||
public function get_db_url(bool $useInternal = false): string
|
||||
{
|
||||
if ($this->is_public && !$useInternal) {
|
||||
return "redis://:{$this->redis_password}@{$this->destination->server->getIp}:{$this->public_port}/0";
|
||||
|
@ -215,7 +215,7 @@ function generateServiceSpecificFqdns(ServiceApplication|Application $resource,
|
||||
}
|
||||
return $payload;
|
||||
}
|
||||
function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true, ?string $service_name = null)
|
||||
function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true, ?bool $is_stripprefix_enabled = true, ?string $service_name = null)
|
||||
{
|
||||
$labels = collect([]);
|
||||
$labels->push('traefik.enable=true');
|
||||
@ -281,8 +281,10 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
||||
$labels->push("traefik.http.services.{$https_label}.loadbalancer.server.port=$port");
|
||||
}
|
||||
if ($path !== '/') {
|
||||
$labels->push("traefik.http.middlewares.{$https_label}-stripprefix.stripprefix.prefixes={$path}");
|
||||
$middlewares = collect(["{$https_label}-stripprefix"]);
|
||||
if ($is_stripprefix_enabled) {
|
||||
$labels->push("traefik.http.middlewares.{$https_label}-stripprefix.stripprefix.prefixes={$path}");
|
||||
$middlewares = collect(["{$https_label}-stripprefix"]);
|
||||
}
|
||||
if ($is_gzip_enabled) {
|
||||
$middlewares->push('gzip');
|
||||
}
|
||||
@ -334,8 +336,10 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
||||
$labels->push("traefik.http.routers.{$http_label}.service={$http_label}");
|
||||
}
|
||||
if ($path !== '/') {
|
||||
$labels->push("traefik.http.middlewares.{$http_label}-stripprefix.stripprefix.prefixes={$path}");
|
||||
$middlewares = collect(["{$http_label}-stripprefix"]);
|
||||
if ($is_stripprefix_enabled) {
|
||||
$labels->push("traefik.http.middlewares.{$http_label}-stripprefix.stripprefix.prefixes={$path}");
|
||||
$middlewares = collect(["{$http_label}-stripprefix"]);
|
||||
}
|
||||
if ($is_gzip_enabled) {
|
||||
$middlewares->push('gzip');
|
||||
}
|
||||
@ -392,7 +396,14 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
||||
$domains = Str::of(data_get($application, 'fqdn'))->explode(',');
|
||||
}
|
||||
// Add Traefik labels no matter which proxy is selected
|
||||
$labels = $labels->merge(fqdnLabelsForTraefik($appUuid, $domains, $application->settings->is_force_https_enabled, $onlyPort));
|
||||
$labels = $labels->merge(fqdnLabelsForTraefik(
|
||||
uuid: $appUuid,
|
||||
domains: $domains,
|
||||
onlyPort: $onlyPort,
|
||||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||
is_gzip_enabled: $application->isGzipEnabled(),
|
||||
is_stripprefix_enabled: $application->isStripprefixEnabled()
|
||||
));
|
||||
}
|
||||
return $labels->all();
|
||||
}
|
||||
|
@ -1047,7 +1047,15 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
$serviceLabels = $serviceLabels->merge($defaultLabels);
|
||||
if (!$isDatabase && $fqdns->count() > 0) {
|
||||
if ($fqdns) {
|
||||
$serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($resource->uuid, $fqdns, true, serviceLabels: $serviceLabels, is_gzip_enabled: $savedService->isGzipEnabled(), service_name: $serviceName));
|
||||
$serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik(
|
||||
uuid: $resource->uuid,
|
||||
domains: $fqdns,
|
||||
is_force_https_enabled: true,
|
||||
serviceLabels: $serviceLabels,
|
||||
is_gzip_enabled: $savedService->isGzipEnabled(),
|
||||
is_stripprefix_enabled: $savedService->isStripprefixEnabled(),
|
||||
service_name: $serviceName));
|
||||
|
||||
}
|
||||
}
|
||||
if ($resource->server->isLogDrainEnabled() && $savedService->isLogDrainEnabled()) {
|
||||
@ -1249,7 +1257,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
// Collect/create/update networks
|
||||
if ($serviceNetworks->count() > 0) {
|
||||
foreach ($serviceNetworks as $networkName => $networkDetails) {
|
||||
ray($networkDetails);
|
||||
$networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) {
|
||||
return $value == $networkName || $key == $networkName;
|
||||
});
|
||||
@ -1405,7 +1412,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
$generatedValue = generateEnvValue($command, $service);
|
||||
$generatedValue = generateEnvValue($command);
|
||||
if (!$foundEnv) {
|
||||
EnvironmentVariable::create([
|
||||
'key' => $key,
|
||||
@ -1581,7 +1588,7 @@ function parseEnvVariable(Str|string $value)
|
||||
'port' => $port,
|
||||
];
|
||||
}
|
||||
function generateEnvValue(string $command, Service $service)
|
||||
function generateEnvValue(string $command, ?Service $service = null)
|
||||
{
|
||||
switch ($command) {
|
||||
case 'PASSWORD':
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
// The release version of your application
|
||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||
'release' => '4.0.0-beta.232',
|
||||
'release' => '4.0.0-beta.233',
|
||||
// When left empty or `null` the Laravel environment will be used
|
||||
'environment' => config('app.env'),
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
<?php
|
||||
|
||||
return '4.0.0-beta.232';
|
||||
return '4.0.0-beta.233';
|
||||
|
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('application_settings', function (Blueprint $table) {
|
||||
$table->boolean('is_gzip_enabled')->default(true);
|
||||
$table->boolean('is_stripprefix_enabled')->default(true);
|
||||
});
|
||||
Schema::table('service_applications', function (Blueprint $table) {
|
||||
$table->boolean('is_stripprefix_enabled')->default(true);
|
||||
});
|
||||
Schema::table('service_databases', function (Blueprint $table) {
|
||||
$table->boolean('is_gzip_enabled')->default(true);
|
||||
$table->boolean('is_stripprefix_enabled')->default(true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('application_settings', function (Blueprint $table) {
|
||||
$table->dropColumn('is_gzip_enabled');
|
||||
$table->dropColumn('is_stripprefix_enabled');
|
||||
});
|
||||
Schema::table('service_applications', function (Blueprint $table) {
|
||||
$table->dropColumn('is_stripprefix_enabled');
|
||||
});
|
||||
Schema::table('service_databases', function (Blueprint $table) {
|
||||
$table->dropColumn('is_gzip_enabled');
|
||||
$table->dropColumn('is_stripprefix_enabled');
|
||||
});
|
||||
}
|
||||
};
|
BIN
public/svgs/changedetection.png
Normal file
BIN
public/svgs/changedetection.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
@ -1,8 +1,10 @@
|
||||
<div class="group">
|
||||
@if (data_get($application, 'fqdn') ||
|
||||
@if (
|
||||
(data_get($application, 'fqdn') ||
|
||||
collect(json_decode($this->application->docker_compose_domains))->count() > 0 ||
|
||||
data_get($application, 'previews', collect([]))->count() > 0 ||
|
||||
data_get($application, 'ports_mappings_array'))
|
||||
data_get($application, 'ports_mappings_array')) &&
|
||||
data_get($application, 'settings.is_raw_compose_deployment_enabled') !== true)
|
||||
<label tabindex="0" class="flex items-center gap-2 cursor-pointer hover:text-white"> Open Application
|
||||
<x-chevron-down />
|
||||
</label>
|
||||
|
@ -20,6 +20,11 @@
|
||||
helper="The deployed container will have the same name ({{ $application->uuid }}). <span class='font-bold text-warning'>You will lose the rolling update feature!</span>"
|
||||
instantSave id="application.settings.is_consistent_container_name_enabled"
|
||||
label="Consistent Container Names" />
|
||||
<x-forms.checkbox label="Enable gzip compression"
|
||||
helper="You can disable gzip compression if you want. Some services are compressing data by default. In this case, you do not need this."
|
||||
instantSave id="is_gzip_enabled" />
|
||||
<x-forms.checkbox helper="Strip Prefix is used to remove prefixes from paths. Like /api/ to /api."
|
||||
instantSave id="is_stripprefix_enabled" label="Strip Prefixes" />
|
||||
<h3>Logs</h3>
|
||||
@if (!$application->settings->is_raw_compose_deployment_enabled)
|
||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
||||
|
@ -45,9 +45,11 @@
|
||||
</div>
|
||||
@endif
|
||||
@if ($application->build_pack === 'dockercompose')
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox instantSave id="application.settings.is_raw_compose_deployment_enabled"
|
||||
label="Raw Compose Deployment"
|
||||
helper="WARNING: Advanced use cases only. Your docker compose file will be deployed as-is. Nothing is modified by Coolify. You need to configure the proxy parts. More info in the <a href='https://coolify.io/docs/docker/compose#raw-docker-compose-deployment'>documentation.</a>" />
|
||||
</div>
|
||||
@if (count($parsedServices) > 0 && !$application->settings->is_raw_compose_deployment_enabled)
|
||||
@foreach (data_get($parsedServices, 'services') as $serviceName => $service)
|
||||
@if (!isDatabaseImage(data_get($service, 'image')))
|
||||
|
@ -34,7 +34,9 @@
|
||||
<h3 class="pt-2">Advanced</h3>
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox instantSave id="application.is_gzip_enabled" label="Enable gzip compression"
|
||||
helper="You can disable gzip compression if you want. Some services are compressing data by default. In this case, you do not need this." />
|
||||
helper="You can disable gzip compression if you want. Some services are compressing data by default. In this case, you do not need this." />
|
||||
<x-forms.checkbox instantSave id="application.is_stripprefix_enabled" label="Strip Prefixes"
|
||||
helper="Strip Prefix is used to remove prefixes from paths. Like /api/ to /api." />
|
||||
<x-forms.checkbox instantSave label="Exclude from service status"
|
||||
helper="If you do not need to monitor this resource, enable. Useful if this service is optional."
|
||||
id="application.exclude_from_status"></x-forms.checkbox>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div>
|
||||
<div x-init="$wire.getLogs" id="screen" x-data="{ fullscreen: false, alwaysScroll: false, intervalId: null }">
|
||||
<div class="flex items-center gap-2">
|
||||
@if ($resource->type() === 'application')
|
||||
@if ($resource?->type() === 'application')
|
||||
<h3>{{ $container }}</h3>
|
||||
@else
|
||||
<h3>{{ str($container)->beforeLast('-')->headline() }}</h3>
|
||||
|
@ -25,7 +25,7 @@
|
||||
</div>
|
||||
<div wire:loading.remove wire:target="loadProxyConfiguration">
|
||||
@if ($proxy_settings)
|
||||
<div class="flex flex-col gap-2 pt-2">
|
||||
<div class="flex flex-col gap-2 pt-4">
|
||||
<x-forms.textarea label="Configuration file: traefik.conf" name="proxy_settings"
|
||||
wire:model="proxy_settings" rows="30" />
|
||||
<x-forms.button wire:click.prevent="reset_proxy_configuration">
|
||||
|
32
templates/compose/changedetection.yaml
Normal file
32
templates/compose/changedetection.yaml
Normal file
@ -0,0 +1,32 @@
|
||||
# documentation: https://github.com/dgtlmoon/changedetection.io/
|
||||
# slogan: Website change detection monitor and notifications.
|
||||
# tags: web, alert, monitor
|
||||
# logo: svgs/changedetection.png
|
||||
|
||||
services:
|
||||
changedetection:
|
||||
image: ghcr.io/dgtlmoon/changedetection.io
|
||||
volumes:
|
||||
- changedetection-data:/datastore
|
||||
environment:
|
||||
- SERVICE_FQDN_CHANGEDETECTION
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- BASE_URL=$SERVICE_FQDN_CHANGEDETECTION
|
||||
- PLAYWRIGHT_DRIVER_URL=ws://playwright-chrome:3000/?stealth=1&--disable-web-security=true
|
||||
# Hides the `Referer` header so that monitored websites can't see the changedetection.io hostname.
|
||||
- HIDE_REFERER=true
|
||||
depends_on:
|
||||
playwright-chrome:
|
||||
condition: service_started
|
||||
playwright-chrome:
|
||||
image: dgtlmoon/sockpuppetbrowser:latest
|
||||
# cap_add:
|
||||
# - SYS_ADMIN
|
||||
# SYS_ADMIN might be too much, but it can be needed on your platform https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-puppeteer-on-gitlabci
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- SCREEN_WIDTH=1920
|
||||
- SCREEN_HEIGHT=1024
|
||||
- SCREEN_DEPTH=16
|
||||
- MAX_CONCURRENT_CHROME_PROCESSES=10
|
@ -51,6 +51,18 @@
|
||||
"logo": "svgs\/unknown.svg",
|
||||
"minversion": "0.0.0"
|
||||
},
|
||||
"changedetection": {
|
||||
"documentation": "https:\/\/github.com\/dgtlmoon\/changedetection.io\/",
|
||||
"slogan": "Website change detection monitor and notifications.",
|
||||
"compose": "c2VydmljZXM6CiAgY2hhbmdlZGV0ZWN0aW9uOgogICAgaW1hZ2U6IGdoY3IuaW8vZGd0bG1vb24vY2hhbmdlZGV0ZWN0aW9uLmlvCiAgICB2b2x1bWVzOgogICAgICAtICdjaGFuZ2VkZXRlY3Rpb24tZGF0YTovZGF0YXN0b3JlJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9GUUROX0NIQU5HRURFVEVDVElPTgogICAgICAtIFBVSUQ9MTAwMAogICAgICAtIFBHSUQ9MTAwMAogICAgICAtIEJBU0VfVVJMPSRTRVJWSUNFX0ZRRE5fQ0hBTkdFREVURUNUSU9OCiAgICAgIC0gJ1BMQVlXUklHSFRfRFJJVkVSX1VSTD13czovL3BsYXl3cmlnaHQtY2hyb21lOjMwMDAvP3N0ZWFsdGg9MSYtLWRpc2FibGUtd2ViLXNlY3VyaXR5PXRydWUnCiAgICAgIC0gSElERV9SRUZFUkVSPXRydWUKICAgIGRlcGVuZHNfb246CiAgICAgIHBsYXl3cmlnaHQtY2hyb21lOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9zdGFydGVkCiAgcGxheXdyaWdodC1jaHJvbWU6CiAgICBpbWFnZTogJ2RndGxtb29uL3NvY2twdXBwZXRicm93c2VyOmxhdGVzdCcKICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTQ1JFRU5fV0lEVEg9MTkyMAogICAgICAtIFNDUkVFTl9IRUlHSFQ9MTAyNAogICAgICAtIFNDUkVFTl9ERVBUSD0xNgogICAgICAtIE1BWF9DT05DVVJSRU5UX0NIUk9NRV9QUk9DRVNTRVM9MTAK",
|
||||
"tags": [
|
||||
"web",
|
||||
"alert",
|
||||
"monitor"
|
||||
],
|
||||
"logo": "svgs\/changedetection.png",
|
||||
"minversion": "0.0.0"
|
||||
},
|
||||
"code-server": {
|
||||
"documentation": "https:\/\/coder.com\/docs\/code-server\/latest",
|
||||
"slogan": "Code-Server is a web-based code editor that enables remote coding and collaboration from any device, anywhere.",
|
||||
|
@ -4,7 +4,7 @@
|
||||
"version": "3.12.36"
|
||||
},
|
||||
"v4": {
|
||||
"version": "4.0.0-beta.232"
|
||||
"version": "4.0.0-beta.233"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user