diff --git a/.gitpod.yml b/.gitpod.yml
index 228f1b94c..6fd6797b5 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -3,7 +3,7 @@ tasks:
# Fix because of https://github.com/gitpod-io/gitpod/issues/16614
before: sudo curl -o /usr/local/bin/docker-compose -fsSL https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-$(uname -m)
init: |
- cp .env.example .env &&
+ cp .env.development.example .env &&
sed -i "s#APP_URL=http://localhost#APP_URL=$(gp url 8000)#g" .env
sed -i "s#USERID=#USERID=33333#g" .env
sed -i "s#GROUPID=#GROUPID=33333#g" .env
@@ -20,7 +20,7 @@ tasks:
echo "Waiting for Sail environment to boot up."
gp sync-await spin-is-ready
./vendor/bin/spin exec vite npm install
- ./vendor/bin/spin exec vite npm run dev
+ ./vendor/bin/spin exec vite npm run dev -- --host
- name: Laravel Queue Worker, listening to code changes
command: |
diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php
index 1241751f0..daba1cecb 100644
--- a/app/Http/Controllers/Controller.php
+++ b/app/Http/Controllers/Controller.php
@@ -37,7 +37,7 @@ class Controller extends BaseController
public function email_verify(EmailVerificationRequest $request) {
$request->fulfill();
$name = request()->user()?->name;
- send_internal_notification("User {$name} verified their email address.");
+ // send_internal_notification("User {$name} verified their email address.");
return redirect(RouteServiceProvider::HOME);
}
public function forgot_password(Request $request) {
diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php
index efa906388..e3221e091 100644
--- a/app/Jobs/ApplicationDeploymentJob.php
+++ b/app/Jobs/ApplicationDeploymentJob.php
@@ -869,7 +869,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
$this->write_deployment_configurations();
$this->server = $this->original_server;
}
- if (count($this->application->ports_mappings_array) > 0 || (bool) $this->application->settings->is_consistent_container_name_enabled || $this->pull_request_id !== 0 || str($this->application->custom_docker_run_options)->contains('--ip') || str($this->application->custom_docker_run_options)->contains('--ip6')) {
+ if (count($this->application->ports_mappings_array) > 0 || (bool) $this->application->settings->is_consistent_container_name_enabled || isset($this->application->settings->custom_internal_name) || $this->pull_request_id !== 0 || str($this->application->custom_docker_run_options)->contains('--ip') || str($this->application->custom_docker_run_options)->contains('--ip6')) {
$this->application_deployment_queue->addLogEntry("----------------------------------------");
if (count($this->application->ports_mappings_array) > 0) {
$this->application_deployment_queue->addLogEntry("Application has ports mapped to the host system, rolling update is not supported.");
@@ -877,6 +877,9 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
if ((bool) $this->application->settings->is_consistent_container_name_enabled) {
$this->application_deployment_queue->addLogEntry("Consistent container name feature enabled, rolling update is not supported.");
}
+ if (isset($this->application->settings->custom_internal_name)) {
+ $this->application_deployment_queue->addLogEntry("Custom internal name is set, rolling update is not supported.");
+ }
if ($this->pull_request_id !== 0) {
$this->application->settings->is_consistent_container_name_enabled = true;
$this->application_deployment_queue->addLogEntry("Pull request deployment, rolling update is not supported.");
@@ -1292,7 +1295,11 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
'restart' => RESTART_MODE,
'expose' => $ports,
'networks' => [
- $this->destination->network,
+ $this->destination->network => [
+ 'aliases' => [
+ $this->container_name
+ ]
+ ]
],
'mem_limit' => $this->application->limits_memory,
'memswap_limit' => $this->application->limits_memory_swap,
@@ -1310,6 +1317,9 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
]
]
];
+ if (isset($this->application->settings->custom_internal_name)) {
+ $docker_compose['services'][$this->container_name]['networks'][$this->destination->network]['aliases'][] = $this->application->settings->custom_internal_name;
+ }
// if (str($this->saved_outputs->get('dotenv'))->isNotEmpty()) {
// if (data_get($docker_compose, "services.{$this->container_name}.env_file")) {
// $docker_compose['services'][$this->container_name]['env_file'][] = '.env';
@@ -1519,95 +1529,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
return $local_persistent_volumes_names;
}
- /*private function generate_environment_variables($ports)
- {
- $environment_variables = collect();
- if ($this->pull_request_id === 0) {
- foreach ($this->application->runtime_environment_variables as $env) {
- // This is necessary because we have to escape the value of the environment variable
- // but only if the environment variable is created after 4.0.0-beta.240
- // when I implemented the escaping feature.
-
- // Old environment variables are not escaped, because it could break the application
- // as the application could expect the unescaped value.
- if ($env->version === '4.0.0-beta.239') {
- $real_value = $env->real_value;
- } else {
- $real_value = escapeEnvVariables($env->real_value);
- }
- if ($env->is_literal) {
- $real_value = escapeDollarSign($real_value);
- $environment_variables->push("$env->key='$real_value'");
- } else {
- $environment_variables->push("$env->key=$real_value");
- }
- }
- foreach ($this->application->nixpacks_environment_variables as $env) {
- if ($env->version === '4.0.0-beta.239') {
- $real_value = $env->real_value;
- } else {
- $real_value = escapeEnvVariables($env->real_value);
- }
- if ($env->is_literal) {
- $real_value = escapeDollarSign($real_value);
- $environment_variables->push("$env->key='$real_value'");
- } else {
- $environment_variables->push("$env->key=$real_value");
- }
- }
- } else {
- foreach ($this->application->runtime_environment_variables_preview as $env) {
- if ($env->version === '4.0.0-beta.239') {
- $real_value = $env->real_value;
- } else {
- $real_value = escapeEnvVariables($env->real_value);
- }
- if ($env->is_literal) {
- $real_value = escapeDollarSign($real_value);
- $environment_variables->push("$env->key='$real_value'");
- } else {
- $environment_variables->push("$env->key=$real_value");
- }
- }
- foreach ($this->application->nixpacks_environment_variables_preview as $env) {
- if ($env->version === '4.0.0-beta.239') {
- $real_value = $env->real_value;
- } else {
- $real_value = escapeEnvVariables($env->real_value);
- }
- if ($env->is_literal) {
- $real_value = escapeDollarSign($real_value);
- $environment_variables->push("$env->key='$real_value'");
- } else {
- $environment_variables->push("$env->key=$real_value");
- }
- }
- }
- // Add PORT if not exists, use the first port as default
- if ($environment_variables->filter(fn ($env) => Str::of($env)->startsWith('PORT'))->isEmpty()) {
- $environment_variables->push("PORT={$ports[0]}");
- }
- // Add HOST if not exists
- if ($environment_variables->filter(fn ($env) => Str::of($env)->startsWith('HOST'))->isEmpty()) {
- $environment_variables->push("HOST=0.0.0.0");
- }
- if ($environment_variables->filter(fn ($env) => Str::of($env)->startsWith('SOURCE_COMMIT'))->isEmpty()) {
- if (!is_null($this->commit)) {
- $environment_variables->push("SOURCE_COMMIT={$this->commit}");
- } else {
- $environment_variables->push("SOURCE_COMMIT=unknown");
- }
- }
- ray($environment_variables->all());
- return $environment_variables->all();
- }*/
-
private function generate_healthcheck_commands()
{
- // if ($this->application->dockerfile || $this->application->build_pack === 'dockerfile' || $this->application->build_pack === 'dockerimage') {
- // // TODO: disabled HC because there are several ways to hc a simple docker image, hard to figure out a good way. Like some docker images (pocketbase) does not have curl.
- // return 'exit 0';
- // }
if (!$this->application->health_check_port) {
$health_check_port = $this->application->ports_exposes_array[0];
} else {
@@ -1619,12 +1542,12 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
if ($this->application->health_check_path) {
$this->full_healthcheck_url = "{$this->application->health_check_method}: {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$health_check_port}{$this->application->health_check_path}";
$generated_healthchecks_commands = [
- "curl -s -X {$this->application->health_check_method} -f {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$health_check_port}{$this->application->health_check_path} > /dev/null"
+ "curl -s -X {$this->application->health_check_method} -f {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$health_check_port}{$this->application->health_check_path} > /dev/null || wget -q -O- {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$health_check_port}{$this->application->health_check_path} > /dev/null || exit 1"
];
} else {
$this->full_healthcheck_url = "{$this->application->health_check_method}: {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$health_check_port}/";
$generated_healthchecks_commands = [
- "curl -s -X {$this->application->health_check_method} -f {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$health_check_port}/"
+ "curl -s -X {$this->application->health_check_method} -f {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$health_check_port}/ > /dev/null || wget -q -O- {$this->application->health_check_scheme}://{$this->application->health_check_host}:{$health_check_port}/ > /dev/null || exit 1"
];
}
return implode(' ', $generated_healthchecks_commands);
@@ -1813,12 +1736,17 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
["docker rm -f $containerName >/dev/null 2>&1", "hidden" => true, "ignore_errors" => true],
);
});
- if ($this->application->settings->is_consistent_container_name_enabled) {
+ if ($this->application->settings->is_consistent_container_name_enabled || isset($this->application->settings->custom_internal_name)) {
$this->execute_remote_command(
["docker rm -f $this->container_name >/dev/null 2>&1", "hidden" => true, "ignore_errors" => true],
);
}
} else {
+ if ($this->application->dockerfile || $this->application->build_pack === 'dockerfile' || $this->application->build_pack === 'dockerimage') {
+ $this->application_deployment_queue->addLogEntry("----------------------------------------");
+ $this->application_deployment_queue->addLogEntry("WARNING: Dockerfile or Docker Image based deployment detected. The healthcheck needs a curl or wget command to check the health of the application. Please make sure that it is available in the image or turn off healthcheck on Coolify's UI.");
+ $this->application_deployment_queue->addLogEntry("----------------------------------------");
+ }
$this->application_deployment_queue->addLogEntry("New container is not healthy, rolling back to the old container.");
$this->application_deployment_queue->update([
'status' => ApplicationDeploymentStatus::FAILED->value,
diff --git a/app/Livewire/Project/Application/Advanced.php b/app/Livewire/Project/Application/Advanced.php
index d35867e8f..45cb57ee3 100644
--- a/app/Livewire/Project/Application/Advanced.php
+++ b/app/Livewire/Project/Application/Advanced.php
@@ -21,6 +21,7 @@ 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.custom_internal_name' => 'string|nullable',
'application.settings.is_gzip_enabled' => 'boolean|required',
'application.settings.is_stripprefix_enabled' => 'boolean|required',
'application.settings.gpu_driver' => 'string|required',
@@ -30,7 +31,8 @@ class Advanced extends Component
'application.settings.is_raw_compose_deployment_enabled' => 'boolean|required',
'application.settings.connect_to_docker_network' => 'boolean|required',
];
- public function mount() {
+ public function mount()
+ {
$this->is_force_https_enabled = $this->application->isForceHttpsEnabled();
$this->is_gzip_enabled = $this->application->isGzipEnabled();
$this->is_stripprefix_enabled = $this->application->isStripprefixEnabled();
@@ -65,7 +67,8 @@ class Advanced extends Component
$this->dispatch('success', 'Settings saved.');
$this->dispatch('configurationChanged');
}
- public function submit() {
+ public function submit()
+ {
if ($this->application->settings->gpu_count && $this->application->settings->gpu_device_ids) {
$this->dispatch('error', 'You cannot set both GPU count and GPU device IDs.');
$this->application->settings->gpu_count = null;
@@ -76,6 +79,16 @@ class Advanced extends Component
$this->application->settings->save();
$this->dispatch('success', 'Settings saved.');
}
+ public function saveCustomName()
+ {
+ if (isset($this->application->settings->custom_internal_name)) {
+ $this->application->settings->custom_internal_name = str($this->application->settings->custom_internal_name)->slug()->value();
+ } else {
+ $this->application->settings->custom_internal_name = null;
+ }
+ $this->application->settings->save();
+ $this->dispatch('success', 'Custom name saved.');
+ }
public function render()
{
return view('livewire.project.application.advanced');
diff --git a/app/Livewire/Project/Application/General.php b/app/Livewire/Project/Application/General.php
index 873422985..885f84247 100644
--- a/app/Livewire/Project/Application/General.php
+++ b/app/Livewire/Project/Application/General.php
@@ -255,7 +255,6 @@ class General extends Component
}
public function resetDefaultLabels()
{
- ray('resetDefaultLabels');
$this->customLabels = str(implode("|", generateLabelsApplication($this->application)))->replace("|", "\n");
$this->ports_exposes = $this->application->ports_exposes;
@@ -299,7 +298,10 @@ class General extends Component
}
if ($this->application->build_pack === 'dockercompose' && $this->initialDockerComposeLocation !== $this->application->docker_compose_location) {
- $this->loadComposeFile();
+ $compose_return = $this->loadComposeFile();
+ if ($compose_return instanceof \Livewire\Features\SupportEvents\Event) {
+ return;
+ }
}
$this->validate();
if ($this->ports_exposes !== $this->application->ports_exposes) {
diff --git a/app/Livewire/Project/New/PublicGitRepository.php b/app/Livewire/Project/New/PublicGitRepository.php
index c6c699acf..b71a0b670 100644
--- a/app/Livewire/Project/New/PublicGitRepository.php
+++ b/app/Livewire/Project/New/PublicGitRepository.php
@@ -98,7 +98,8 @@ class PublicGitRepository extends Component
(str($this->repository_url)->startsWith('https://') ||
str($this->repository_url)->startsWith('http://')) &&
!str($this->repository_url)->endsWith('.git') &&
- !str($this->repository_url)->contains('github.com')
+ (!str($this->repository_url)->contains('github.com') ||
+ !str($this->repository_url)->contains('git.sr.ht'))
) {
$this->repository_url = $this->repository_url . '.git';
}
diff --git a/app/Models/Application.php b/app/Models/Application.php
index 98b2c23b1..1ce33cefb 100644
--- a/app/Models/Application.php
+++ b/app/Models/Application.php
@@ -847,7 +847,7 @@ class Application extends BaseModel
if (!$composeFileContent) {
$this->docker_compose_location = $initialDockerComposeLocation;
$this->save();
- throw new \RuntimeException("Could not load base compose file from $workdir$composeFile");
+ throw new \RuntimeException("Docker Compose file not found at: $workdir$composeFile");
} else {
$this->docker_compose_raw = $composeFileContent;
$this->save();
diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php
index 6c5ec2319..d5cacb06c 100644
--- a/bootstrap/helpers/shared.php
+++ b/bootstrap/helpers/shared.php
@@ -1841,7 +1841,7 @@ function validate_dns_entry(string $fqdn, Server $server)
$dns_servers = data_get($settings, 'custom_dns_servers');
$dns_servers = str($dns_servers)->explode(',');
if ($server->id === 0) {
- $ip = data_get($settings, 'public_ipv4') || data_get($settings, 'public_ipv6') || $server->ip;
+ $ip = data_get($settings, 'public_ipv4', data_get($settings, 'public_ipv6', $server->ip));
} else {
$ip = $server->ip;
}
@@ -1920,7 +1920,6 @@ function check_domain_usage(ServiceApplication|Application|null $resource = null
$naked_domain = str($domain)->value();
if ($domains->contains($naked_domain)) {
if (data_get($resource, 'uuid')) {
- ray($resource->uuid, $app->uuid);
if ($resource->uuid !== $app->uuid) {
throw new \RuntimeException("Domain $naked_domain is already in use by another resource called:
{$app->name}.");
}
diff --git a/config/sentry.php b/config/sentry.php
index 633e5bcd6..7aa3e5aab 100644
--- a/config/sentry.php
+++ b/config/sentry.php
@@ -7,7 +7,7 @@ return [
// 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.274',
+ 'release' => '4.0.0-beta.275',
// When left empty or `null` the Laravel environment will be used
'environment' => config('app.env'),
diff --git a/config/version.php b/config/version.php
index 3cb55c8fd..fc9a2d839 100644
--- a/config/version.php
+++ b/config/version.php
@@ -1,3 +1,3 @@
string('custom_internal_name')->nullable();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('application_settings', function (Blueprint $table) {
+ $table->dropColumn('custom_internal_name');
+ });
+ }
+};
diff --git a/lang/zh-cn.json b/lang/zh-cn.json
new file mode 100644
index 000000000..70c457fa8
--- /dev/null
+++ b/lang/zh-cn.json
@@ -0,0 +1,30 @@
+{
+ "auth.login": "登录",
+ "auth.login.azure": "使用 Microsoft 登录",
+ "auth.login.bitbucket": "使用 Bitbucket 登录",
+ "auth.login.github": "使用 GitHub 登录",
+ "auth.login.gitlab": "使用 Gitlab 登录",
+ "auth.login.google": "使用 Google 登录",
+ "auth.already_registered": "已经注册?",
+ "auth.confirm_password": "确认密码",
+ "auth.forgot_password": "忘记密码",
+ "auth.forgot_password_send_email": "发送密码重置邮件",
+ "auth.register_now": "注册",
+ "auth.logout": "退出登录",
+ "auth.register": "注册",
+ "auth.registration_disabled": "注册已禁用,请联系管理员",
+ "auth.reset_password": "重置密码",
+ "auth.failed": "这些凭据与我们的记录不符",
+ "auth.failed.callback": "处理第三方登录的回调时出错",
+ "auth.failed.password": "密码错误",
+ "auth.failed.email": "该账户未注册",
+ "auth.throttle": "登录次数过多,请在 :seconds 秒后重试",
+ "input.name": "用户名",
+ "input.email": "邮箱",
+ "input.password": "密码",
+ "input.password.again": "确认密码",
+ "input.code": "验证码",
+ "input.recovery_code": "恢复码",
+ "button.save": "保存",
+ "repository.url": "示例
对于公共代码仓库,请使用 https://...。
对于私有代码仓库,请使用 git@...。
https://github.com/coollabsio/coolify-examples main 分支将被选择
https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify nodejs-fastify 分支将被选择。
https://gitea.com/sedlav/expressjs.git main 分支将被选择。
https://gitlab.com/andrasbacsai/nodejs-example.git main 分支将被选择"
+}
diff --git a/resources/views/components/popup-small.blade.php b/resources/views/components/popup-small.blade.php
index 97ed025fe..ba6839bab 100644
--- a/resources/views/components/popup-small.blade.php
+++ b/resources/views/components/popup-small.blade.php
@@ -8,7 +8,7 @@
x-transition:leave-end="translate-y-full" x-init="setTimeout(() => { bannerVisible = true }, bannerVisibleAfter);"
class="fixed bottom-0 right-0 h-auto duration-300 ease-out px-5 pb-5 max-w-[46rem] z-[999]" x-cloak>