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/README.md b/README.md
index 01c1ccef9..97580b875 100644
--- a/README.md
+++ b/README.md
@@ -34,7 +34,12 @@ Special thanks to our biggest sponsor, [CCCareers](https://cccareers.org/)!
 
 ## Github Sponsors ($40+)
 
+
 
+
 
+
+
+ 
 
 
 
@@ -62,6 +67,7 @@ Special thanks to our biggest sponsor, [CCCareers](https://cccareers.org/)!
 
 
 
+
 ## Individuals
 
 
diff --git a/app/Actions/Database/StartClickhouse.php b/app/Actions/Database/StartClickhouse.php
index d043da410..5f567802f 100644
--- a/app/Actions/Database/StartClickhouse.php
+++ b/app/Actions/Database/StartClickhouse.php
@@ -33,7 +33,6 @@ class StartClickhouse
         $environment_variables = $this->generate_environment_variables();
 
         $docker_compose = [
-            'version' => '3.8',
             'services' => [
                 $container_name => [
                     'image' => $this->database->image,
diff --git a/app/Actions/Database/StartDatabaseProxy.php b/app/Actions/Database/StartDatabaseProxy.php
index a1e47710c..547884b7a 100644
--- a/app/Actions/Database/StartDatabaseProxy.php
+++ b/app/Actions/Database/StartDatabaseProxy.php
@@ -107,7 +107,6 @@ class StartDatabaseProxy
     COPY nginx.conf /etc/nginx/nginx.conf
     EOF;
         $docker_compose = [
-            'version' => '3.8',
             'services' => [
                 $proxyContainerName => [
                     'build' => [
diff --git a/app/Actions/Database/StartDragonfly.php b/app/Actions/Database/StartDragonfly.php
index bb71d8c48..92daf195d 100644
--- a/app/Actions/Database/StartDragonfly.php
+++ b/app/Actions/Database/StartDragonfly.php
@@ -36,7 +36,6 @@ class StartDragonfly
         $environment_variables = $this->generate_environment_variables();
 
         $docker_compose = [
-            'version' => '3.8',
             'services' => [
                 $container_name => [
                     'image' => $this->database->image,
diff --git a/app/Actions/Database/StartKeydb.php b/app/Actions/Database/StartKeydb.php
index 489c74053..8c833efd5 100644
--- a/app/Actions/Database/StartKeydb.php
+++ b/app/Actions/Database/StartKeydb.php
@@ -37,7 +37,6 @@ class StartKeydb
         $this->add_custom_keydb();
 
         $docker_compose = [
-            'version' => '3.8',
             'services' => [
                 $container_name => [
                     'image' => $this->database->image,
@@ -96,7 +95,7 @@ class StartKeydb
         if (count($volume_names) > 0) {
             $docker_compose['volumes'] = $volume_names;
         }
-        if (!is_null($this->database->keydb_conf)) {
+        if (!is_null($this->database->keydb_conf) || !empty($this->database->keydb_conf)) {
             $docker_compose['services'][$container_name]['volumes'][] = [
                 'type' => 'bind',
                 'source' => $this->configuration_dir . '/keydb.conf',
@@ -162,7 +161,7 @@ class StartKeydb
     }
     private function add_custom_keydb()
     {
-        if (is_null($this->database->keydb_conf)) {
+        if (is_null($this->database->keydb_conf) || empty($this->database->keydb_conf)) {
             return;
         }
         $filename = 'keydb.conf';
diff --git a/app/Actions/Database/StartMariadb.php b/app/Actions/Database/StartMariadb.php
index e02b28b2e..c79df0dc5 100644
--- a/app/Actions/Database/StartMariadb.php
+++ b/app/Actions/Database/StartMariadb.php
@@ -32,7 +32,6 @@ class StartMariadb
         $environment_variables = $this->generate_environment_variables();
         $this->add_custom_mysql();
         $docker_compose = [
-            'version' => '3.8',
             'services' => [
                 $container_name => [
                     'image' => $this->database->image,
@@ -90,7 +89,7 @@ class StartMariadb
         if (count($volume_names) > 0) {
             $docker_compose['volumes'] = $volume_names;
         }
-        if (!is_null($this->database->mariadb_conf)) {
+        if (!is_null($this->database->mariadb_conf) || !empty($this->database->mariadb_conf)) {
             $docker_compose['services'][$container_name]['volumes'][] = [
                 'type' => 'bind',
                 'source' => $this->configuration_dir . '/custom-config.cnf',
@@ -165,7 +164,7 @@ class StartMariadb
     }
     private function add_custom_mysql()
     {
-        if (is_null($this->database->mariadb_conf)) {
+        if (is_null($this->database->mariadb_conf) || empty($this->database->mariadb_conf)) {
             return;
         }
         $filename = 'custom-config.cnf';
diff --git a/app/Actions/Database/StartMongodb.php b/app/Actions/Database/StartMongodb.php
index 7bb6cbcd0..46b426ad8 100644
--- a/app/Actions/Database/StartMongodb.php
+++ b/app/Actions/Database/StartMongodb.php
@@ -35,7 +35,6 @@ class StartMongodb
         $this->add_custom_mongo_conf();
 
         $docker_compose = [
-            'version' => '3.8',
             'services' => [
                 $container_name => [
                     'image' => $this->database->image,
@@ -51,8 +50,9 @@ class StartMongodb
                     ],
                     'healthcheck' => [
                         'test' => [
-                            'CMD-SHELL',
-                            'mongosh --eval "printjson(db.runCommand(\"ping\"))"'
+                            "CMD",
+                            "echo",
+                            "ok"
                         ],
                         'interval' => '5s',
                         'timeout' => '5s',
@@ -97,7 +97,7 @@ class StartMongodb
         if (count($volume_names) > 0) {
             $docker_compose['volumes'] = $volume_names;
         }
-        if (!is_null($this->database->mongo_conf)) {
+        if (!is_null($this->database->mongo_conf) || !empty($this->database->mongo_conf)) {
             $docker_compose['services'][$container_name]['volumes'][] = [
                 'type' => 'bind',
                 'source' => $this->configuration_dir . '/mongod.conf',
@@ -178,7 +178,7 @@ class StartMongodb
     }
     private function add_custom_mongo_conf()
     {
-        if (is_null($this->database->mongo_conf)) {
+        if (is_null($this->database->mongo_conf) || empty($this->database->mongo_conf)) {
             return;
         }
         $filename = 'mongod.conf';
diff --git a/app/Actions/Database/StartMysql.php b/app/Actions/Database/StartMysql.php
index b3f695d72..6fdc8cdad 100644
--- a/app/Actions/Database/StartMysql.php
+++ b/app/Actions/Database/StartMysql.php
@@ -32,7 +32,6 @@ class StartMysql
         $environment_variables = $this->generate_environment_variables();
         $this->add_custom_mysql();
         $docker_compose = [
-            'version' => '3.8',
             'services' => [
                 $container_name => [
                     'image' => $this->database->image,
@@ -90,7 +89,7 @@ class StartMysql
         if (count($volume_names) > 0) {
             $docker_compose['volumes'] = $volume_names;
         }
-        if (!is_null($this->database->mysql_conf)) {
+        if (!is_null($this->database->mysql_conf) || !empty($this->database->mysql_conf)) {
             $docker_compose['services'][$container_name]['volumes'][] = [
                 'type' => 'bind',
                 'source' => $this->configuration_dir . '/custom-config.cnf',
@@ -165,7 +164,7 @@ class StartMysql
     }
     private function add_custom_mysql()
     {
-        if (is_null($this->database->mysql_conf)) {
+        if (is_null($this->database->mysql_conf) || empty($this->database->mysql_conf)) {
             return;
         }
         $filename = 'custom-config.cnf';
diff --git a/app/Actions/Database/StartPostgresql.php b/app/Actions/Database/StartPostgresql.php
index f19a8b036..8db874ea6 100644
--- a/app/Actions/Database/StartPostgresql.php
+++ b/app/Actions/Database/StartPostgresql.php
@@ -35,7 +35,6 @@ class StartPostgresql
         $this->add_custom_conf();
 
         $docker_compose = [
-            'version' => '3.8',
             'services' => [
                 $container_name => [
                     'image' => $this->database->image,
@@ -78,7 +77,6 @@ class StartPostgresql
             data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
         }
         if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) {
-            ray('Log Drain Enabled');
             $docker_compose['services'][$container_name]['logging'] = [
                 'driver' => 'fluentd',
                 'options' => [
@@ -107,7 +105,7 @@ class StartPostgresql
                 ];
             }
         }
-        if (!is_null($this->database->postgres_conf)) {
+        if (!is_null($this->database->postgres_conf) && !empty($this->database->postgres_conf)) {
             $docker_compose['services'][$container_name]['volumes'][] = [
                 'type' => 'bind',
                 'source' => $this->configuration_dir . '/custom-postgres.conf',
@@ -165,8 +163,6 @@ class StartPostgresql
     private function generate_environment_variables()
     {
         $environment_variables = collect();
-        ray('Generate Environment Variables')->green();
-        ray($this->database->runtime_environment_variables)->green();
         foreach ($this->database->runtime_environment_variables as $env) {
             $environment_variables->push("$env->key=$env->real_value");
         }
@@ -203,11 +199,16 @@ class StartPostgresql
     }
     private function add_custom_conf()
     {
-        if (is_null($this->database->postgres_conf)) {
+        if (is_null($this->database->postgres_conf) || empty($this->database->postgres_conf)) {
             return;
         }
         $filename = 'custom-postgres.conf';
         $content = $this->database->postgres_conf;
+        if (!str($content)->contains('listen_addresses')) {
+            $content .= "\nlisten_addresses = '*'";
+            $this->database->postgres_conf = $content;
+            $this->database->save();
+        }
         $content_base64 = base64_encode($content);
         $this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/{$filename} > /dev/null";
     }
diff --git a/app/Actions/Database/StartRedis.php b/app/Actions/Database/StartRedis.php
index 01e9a9bef..5b6ab2999 100644
--- a/app/Actions/Database/StartRedis.php
+++ b/app/Actions/Database/StartRedis.php
@@ -37,7 +37,6 @@ class StartRedis
         $this->add_custom_redis();
 
         $docker_compose = [
-            'version' => '3.8',
             'services' => [
                 $container_name => [
                     'image' => $this->database->image,
@@ -100,7 +99,7 @@ class StartRedis
         if (count($volume_names) > 0) {
             $docker_compose['volumes'] = $volume_names;
         }
-        if (!is_null($this->database->redis_conf)) {
+        if (!is_null($this->database->redis_conf) || !empty($this->database->redis_conf)) {
             $docker_compose['services'][$container_name]['volumes'][] = [
                 'type' => 'bind',
                 'source' => $this->configuration_dir . '/redis.conf',
@@ -166,7 +165,7 @@ class StartRedis
     }
     private function add_custom_redis()
     {
-        if (is_null($this->database->redis_conf)) {
+        if (is_null($this->database->redis_conf) || empty($this->database->redis_conf)) {
             return;
         }
         $filename = 'redis.conf';
diff --git a/app/Actions/Docker/GetContainersStatus.php b/app/Actions/Docker/GetContainersStatus.php
new file mode 100644
index 000000000..f0e1de8f6
--- /dev/null
+++ b/app/Actions/Docker/GetContainersStatus.php
@@ -0,0 +1,657 @@
+server = $server;
+        if (!$this->server->isFunctional()) {
+            return 'Server is not ready.';
+        };
+        $this->applications = $this->server->applications();
+        $skip_these_applications = collect([]);
+        foreach ($this->applications as $application) {
+            if ($application->additional_servers->count() > 0) {
+                $skip_these_applications->push($application);
+                ComplexStatusCheck::run($application);
+                $this->applications = $this->applications->filter(function ($value, $key) use ($application) {
+                    return $value->id !== $application->id;
+                });
+            }
+        }
+        $this->applications = $this->applications->filter(function ($value, $key) use ($skip_these_applications) {
+            return !$skip_these_applications->pluck('id')->contains($value->id);
+        });
+        $this->old_way();
+        // if ($this->server->isSwarm()) {
+        //     $this->old_way();
+        // } else {
+        //     if (!$this->server->is_metrics_enabled) {
+        //         $this->old_way();
+        //         return;
+        //     }
+        //     $sentinel_found = instant_remote_process(["docker inspect coolify-sentinel"], $this->server, false);
+        //     $sentinel_found = json_decode($sentinel_found, true);
+        //     $status = data_get($sentinel_found, '0.State.Status', 'exited');
+        //     if ($status === 'running') {
+        //         ray('Checking with Sentinel');
+        //         $this->sentinel();
+        //     } else {
+        //         ray('Checking the Old way');
+        //         $this->old_way();
+        //     }
+        // }
+    }
+
+    private function sentinel()
+    {
+        try {
+            $containers = $this->server->getContainers();
+            if ($containers->count() === 0) {
+                return;
+            }
+            $databases = $this->server->databases();
+            $services = $this->server->services()->get();
+            $previews = $this->server->previews();
+            $foundApplications = [];
+            $foundApplicationPreviews = [];
+            $foundDatabases = [];
+            $foundServices = [];
+
+            foreach ($containers as $container) {
+                $labels = Arr::undot(data_get($container, 'labels'));
+                $containerStatus = data_get($container, 'state');
+                $containerHealth = data_get($container, 'health_status', 'unhealthy');
+                $containerStatus = "$containerStatus ($containerHealth)";
+                $applicationId = data_get($labels, 'coolify.applicationId');
+                if ($applicationId) {
+                    $pullRequestId = data_get($labels, 'coolify.pullRequestId');
+                    if ($pullRequestId) {
+                        if (str($applicationId)->contains('-')) {
+                            $applicationId = str($applicationId)->before('-');
+                        }
+                        $preview = ApplicationPreview::where('application_id', $applicationId)->where('pull_request_id', $pullRequestId)->first();
+                        if ($preview) {
+                            $foundApplicationPreviews[] = $preview->id;
+                            $statusFromDb = $preview->status;
+                            if ($statusFromDb !== $containerStatus) {
+                                $preview->update(['status' => $containerStatus]);
+                            }
+                        } else {
+                            //Notify user that this container should not be there.
+                        }
+                    } else {
+                        $application = $this->applications->where('id', $applicationId)->first();
+                        if ($application) {
+                            $foundApplications[] = $application->id;
+                            $statusFromDb = $application->status;
+                            if ($statusFromDb !== $containerStatus) {
+                                $application->update(['status' => $containerStatus]);
+                            }
+                        } else {
+                            //Notify user that this container should not be there.
+                        }
+                    }
+                } else {
+                    $uuid = data_get($labels, 'com.docker.compose.service');
+                    $type = data_get($labels, 'coolify.type');
+                    if ($uuid) {
+                        if ($type === 'service') {
+                            $database_id = data_get($labels, 'coolify.service.subId');
+                            if ($database_id) {
+                                $service_db = ServiceDatabase::where('id', $database_id)->first();
+                                if ($service_db) {
+                                    $uuid = $service_db->service->uuid;
+                                    $isPublic = data_get($service_db, 'is_public');
+                                    if ($isPublic) {
+                                        $foundTcpProxy = $containers->filter(function ($value, $key) use ($uuid) {
+                                            if ($this->server->isSwarm()) {
+                                                // TODO: fix this with sentinel
+                                                return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
+                                            } else {
+                                                return data_get($value, 'name') === "$uuid-proxy";
+                                            }
+                                        })->first();
+                                        if (!$foundTcpProxy) {
+                                            StartDatabaseProxy::run($service_db);
+                                            // $this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$service_db->service->name}", $this->server));
+                                        }
+                                    }
+                                }
+                            }
+                        } else {
+                            $database = $databases->where('uuid', $uuid)->first();
+                            if ($database) {
+                                $isPublic = data_get($database, 'is_public');
+                                $foundDatabases[] = $database->id;
+                                $statusFromDb = $database->status;
+                                if ($statusFromDb !== $containerStatus) {
+                                    $database->update(['status' => $containerStatus]);
+                                }
+                                if ($isPublic) {
+                                    $foundTcpProxy = $containers->filter(function ($value, $key) use ($uuid) {
+                                        if ($this->server->isSwarm()) {
+                                            // TODO: fix this with sentinel
+                                            return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
+                                        } else {
+                                            return data_get($value, 'name') === "$uuid-proxy";
+                                        }
+                                    })->first();
+                                    if (!$foundTcpProxy) {
+                                        StartDatabaseProxy::run($database);
+                                        $this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$database->name}", $this->server));
+                                    }
+                                }
+                            } else {
+                                // Notify user that this container should not be there.
+                            }
+                        }
+                    }
+                    if (data_get($container, 'name') === 'coolify-db') {
+                        $foundDatabases[] = 0;
+                    }
+                }
+                $serviceLabelId = data_get($labels, 'coolify.serviceId');
+                if ($serviceLabelId) {
+                    $subType = data_get($labels, 'coolify.service.subType');
+                    $subId = data_get($labels, 'coolify.service.subId');
+                    $service = $services->where('id', $serviceLabelId)->first();
+                    if (!$service) {
+                        continue;
+                    }
+                    if ($subType === 'application') {
+                        $service =  $service->applications()->where('id', $subId)->first();
+                    } else {
+                        $service =  $service->databases()->where('id', $subId)->first();
+                    }
+                    if ($service) {
+                        $foundServices[] = "$service->id-$service->name";
+                        $statusFromDb = $service->status;
+                        if ($statusFromDb !== $containerStatus) {
+                            // ray('Updating status: ' . $containerStatus);
+                            $service->update(['status' => $containerStatus]);
+                        }
+                    }
+                }
+            }
+            $exitedServices = collect([]);
+            foreach ($services as $service) {
+                $apps = $service->applications()->get();
+                $dbs = $service->databases()->get();
+                foreach ($apps as $app) {
+                    if (in_array("$app->id-$app->name", $foundServices)) {
+                        continue;
+                    } else {
+                        $exitedServices->push($app);
+                    }
+                }
+                foreach ($dbs as $db) {
+                    if (in_array("$db->id-$db->name", $foundServices)) {
+                        continue;
+                    } else {
+                        $exitedServices->push($db);
+                    }
+                }
+            }
+            $exitedServices = $exitedServices->unique('id');
+            foreach ($exitedServices as $exitedService) {
+                if (str($exitedService->status)->startsWith('exited')) {
+                    continue;
+                }
+                $name = data_get($exitedService, 'name');
+                $fqdn = data_get($exitedService, 'fqdn');
+                $containerName = $name ? "$name, available at $fqdn" : $fqdn;
+                $projectUuid = data_get($service, 'environment.project.uuid');
+                $serviceUuid = data_get($service, 'uuid');
+                $environmentName = data_get($service, 'environment.name');
+
+                if ($projectUuid && $serviceUuid && $environmentName) {
+                    $url =  base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/service/" . $serviceUuid;
+                } else {
+                    $url = null;
+                }
+                $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
+                $exitedService->update(['status' => 'exited']);
+            }
+
+            $notRunningApplications = $this->applications->pluck('id')->diff($foundApplications);
+            foreach ($notRunningApplications as $applicationId) {
+                $application = $this->applications->where('id', $applicationId)->first();
+                if (str($application->status)->startsWith('exited')) {
+                    continue;
+                }
+                $application->update(['status' => 'exited']);
+
+                $name = data_get($application, 'name');
+                $fqdn = data_get($application, 'fqdn');
+
+                $containerName = $name ? "$name ($fqdn)" : $fqdn;
+
+                $projectUuid = data_get($application, 'environment.project.uuid');
+                $applicationUuid = data_get($application, 'uuid');
+                $environment = data_get($application, 'environment.name');
+
+                if ($projectUuid && $applicationUuid && $environment) {
+                    $url =  base_url() . '/project/' . $projectUuid . "/" . $environment . "/application/" . $applicationUuid;
+                } else {
+                    $url = null;
+                }
+
+                $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
+            }
+            $notRunningApplicationPreviews = $previews->pluck('id')->diff($foundApplicationPreviews);
+            foreach ($notRunningApplicationPreviews as $previewId) {
+                $preview = $previews->where('id', $previewId)->first();
+                if (str($preview->status)->startsWith('exited')) {
+                    continue;
+                }
+                $preview->update(['status' => 'exited']);
+
+                $name = data_get($preview, 'name');
+                $fqdn = data_get($preview, 'fqdn');
+
+                $containerName = $name ? "$name ($fqdn)" : $fqdn;
+
+                $projectUuid = data_get($preview, 'application.environment.project.uuid');
+                $environmentName = data_get($preview, 'application.environment.name');
+                $applicationUuid = data_get($preview, 'application.uuid');
+
+                if ($projectUuid && $applicationUuid && $environmentName) {
+                    $url =  base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/application/" . $applicationUuid;
+                } else {
+                    $url = null;
+                }
+
+                $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
+            }
+            $notRunningDatabases = $databases->pluck('id')->diff($foundDatabases);
+            foreach ($notRunningDatabases as $database) {
+                $database = $databases->where('id', $database)->first();
+                if (str($database->status)->startsWith('exited')) {
+                    continue;
+                }
+                $database->update(['status' => 'exited']);
+
+                $name = data_get($database, 'name');
+                $fqdn = data_get($database, 'fqdn');
+
+                $containerName = $name;
+
+                $projectUuid = data_get($database, 'environment.project.uuid');
+                $environmentName = data_get($database, 'environment.name');
+                $databaseUuid = data_get($database, 'uuid');
+
+                if ($projectUuid && $databaseUuid && $environmentName) {
+                    $url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/database/" . $databaseUuid;
+                } else {
+                    $url = null;
+                }
+                $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
+            }
+
+            // Check if proxy is running
+            $this->server->proxyType();
+            $foundProxyContainer = $containers->filter(function ($value, $key) {
+                if ($this->server->isSwarm()) {
+                    // TODO: fix this with sentinel
+                    return data_get($value, 'Spec.Name') === 'coolify-proxy_traefik';
+                } else {
+                    return data_get($value, 'name') === 'coolify-proxy';
+                }
+            })->first();
+            if (!$foundProxyContainer) {
+                try {
+                    $shouldStart = CheckProxy::run($this->server);
+                    if ($shouldStart) {
+                        StartProxy::run($this->server, false);
+                        $this->server->team?->notify(new ContainerRestarted('coolify-proxy', $this->server));
+                    }
+                } catch (\Throwable $e) {
+                    ray($e);
+                }
+            } else {
+                $this->server->proxy->status = data_get($foundProxyContainer, 'state');
+                $this->server->save();
+                $connectProxyToDockerNetworks = connectProxyToNetworks($this->server);
+                instant_remote_process($connectProxyToDockerNetworks, $this->server, false);
+            }
+        } catch (\Exception $e) {
+            // send_internal_notification("ContainerStatusJob failed on ({$this->server->id}) with: " . $e->getMessage());
+            ray($e->getMessage());
+            return handleError($e);
+        }
+    }
+    private function old_way()
+    {
+        if ($this->server->isSwarm()) {
+            $containers = instant_remote_process(["docker service inspect $(docker service ls -q) --format '{{json .}}'"], $this->server, false);
+            $containerReplicates = instant_remote_process(["docker service ls --format '{{json .}}'"], $this->server, false);
+        } else {
+            // Precheck for containers
+            $containers = instant_remote_process(["docker container ls -q"], $this->server, false);
+            if (!$containers) {
+                return;
+            }
+            $containers = instant_remote_process(["docker container inspect $(docker container ls -q) --format '{{json .}}'"], $this->server, false);
+            $containerReplicates = null;
+        }
+        if (is_null($containers)) {
+            return;
+        }
+
+        $containers = format_docker_command_output_to_json($containers);
+        if ($containerReplicates) {
+            $containerReplicates = format_docker_command_output_to_json($containerReplicates);
+            foreach ($containerReplicates as $containerReplica) {
+                $name = data_get($containerReplica, 'Name');
+                $containers = $containers->map(function ($container) use ($name, $containerReplica) {
+                    if (data_get($container, 'Spec.Name') === $name) {
+                        $replicas = data_get($containerReplica, 'Replicas');
+                        $running = str($replicas)->explode('/')[0];
+                        $total = str($replicas)->explode('/')[1];
+                        if ($running === $total) {
+                            data_set($container, 'State.Status', 'running');
+                            data_set($container, 'State.Health.Status', 'healthy');
+                        } else {
+                            data_set($container, 'State.Status', 'starting');
+                            data_set($container, 'State.Health.Status', 'unhealthy');
+                        }
+                    }
+                    return $container;
+                });
+            }
+        }
+        $databases = $this->server->databases();
+        $services = $this->server->services()->get();
+        $previews = $this->server->previews();
+        $foundApplications = [];
+        $foundApplicationPreviews = [];
+        $foundDatabases = [];
+        $foundServices = [];
+
+        foreach ($containers as $container) {
+            if ($this->server->isSwarm()) {
+                $labels = data_get($container, 'Spec.Labels');
+                $uuid = data_get($labels, 'coolify.name');
+            } else {
+                $labels = data_get($container, 'Config.Labels');
+            }
+            $containerStatus = data_get($container, 'State.Status');
+            $containerHealth = data_get($container, 'State.Health.Status', 'unhealthy');
+            $containerStatus = "$containerStatus ($containerHealth)";
+            $labels = Arr::undot(format_docker_labels_to_json($labels));
+            $applicationId = data_get($labels, 'coolify.applicationId');
+            if ($applicationId) {
+                $pullRequestId = data_get($labels, 'coolify.pullRequestId');
+                if ($pullRequestId) {
+                    if (str($applicationId)->contains('-')) {
+                        $applicationId = str($applicationId)->before('-');
+                    }
+                    $preview = ApplicationPreview::where('application_id', $applicationId)->where('pull_request_id', $pullRequestId)->first();
+                    if ($preview) {
+                        $foundApplicationPreviews[] = $preview->id;
+                        $statusFromDb = $preview->status;
+                        if ($statusFromDb !== $containerStatus) {
+                            $preview->update(['status' => $containerStatus]);
+                        }
+                    } else {
+                        //Notify user that this container should not be there.
+                    }
+                } else {
+                    $application = $this->applications->where('id', $applicationId)->first();
+                    if ($application) {
+                        $foundApplications[] = $application->id;
+                        $statusFromDb = $application->status;
+                        if ($statusFromDb !== $containerStatus) {
+                            $application->update(['status' => $containerStatus]);
+                        }
+                    } else {
+                        //Notify user that this container should not be there.
+                    }
+                }
+            } else {
+                $uuid = data_get($labels, 'com.docker.compose.service');
+                $type = data_get($labels, 'coolify.type');
+
+                if ($uuid) {
+                    if ($type === 'service') {
+                        $database_id = data_get($labels, 'coolify.service.subId');
+                        if ($database_id) {
+                            $service_db = ServiceDatabase::where('id', $database_id)->first();
+                            if ($service_db) {
+                                $uuid = data_get($service_db, 'service.uuid');
+                                if ($uuid) {
+                                    $isPublic = data_get($service_db, 'is_public');
+                                    if ($isPublic) {
+                                        $foundTcpProxy = $containers->filter(function ($value, $key) use ($uuid) {
+                                            if ($this->server->isSwarm()) {
+                                                return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
+                                            } else {
+                                                return data_get($value, 'Name') === "/$uuid-proxy";
+                                            }
+                                        })->first();
+                                        if (!$foundTcpProxy) {
+                                            StartDatabaseProxy::run($service_db);
+                                            // $this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$service_db->service->name}", $this->server));
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    } else {
+                        $database = $databases->where('uuid', $uuid)->first();
+                        if ($database) {
+                            $isPublic = data_get($database, 'is_public');
+                            $foundDatabases[] = $database->id;
+                            $statusFromDb = $database->status;
+                            if ($statusFromDb !== $containerStatus) {
+                                $database->update(['status' => $containerStatus]);
+                            }
+                            if ($isPublic) {
+                                $foundTcpProxy = $containers->filter(function ($value, $key) use ($uuid) {
+                                    if ($this->server->isSwarm()) {
+                                        return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
+                                    } else {
+                                        return data_get($value, 'Name') === "/$uuid-proxy";
+                                    }
+                                })->first();
+                                if (!$foundTcpProxy) {
+                                    StartDatabaseProxy::run($database);
+                                    $this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$database->name}", $this->server));
+                                }
+                            }
+                        } else {
+                            // Notify user that this container should not be there.
+                        }
+                    }
+                }
+                if (data_get($container, 'Name') === '/coolify-db') {
+                    $foundDatabases[] = 0;
+                }
+            }
+            $serviceLabelId = data_get($labels, 'coolify.serviceId');
+            if ($serviceLabelId) {
+                $subType = data_get($labels, 'coolify.service.subType');
+                $subId = data_get($labels, 'coolify.service.subId');
+                $service = $services->where('id', $serviceLabelId)->first();
+                if (!$service) {
+                    continue;
+                }
+                if ($subType === 'application') {
+                    $service =  $service->applications()->where('id', $subId)->first();
+                } else {
+                    $service =  $service->databases()->where('id', $subId)->first();
+                }
+                if ($service) {
+                    $foundServices[] = "$service->id-$service->name";
+                    $statusFromDb = $service->status;
+                    if ($statusFromDb !== $containerStatus) {
+                        // ray('Updating status: ' . $containerStatus);
+                        $service->update(['status' => $containerStatus]);
+                    }
+                }
+            }
+        }
+        $exitedServices = collect([]);
+        foreach ($services as $service) {
+            $apps = $service->applications()->get();
+            $dbs = $service->databases()->get();
+            foreach ($apps as $app) {
+                if (in_array("$app->id-$app->name", $foundServices)) {
+                    continue;
+                } else {
+                    $exitedServices->push($app);
+                }
+            }
+            foreach ($dbs as $db) {
+                if (in_array("$db->id-$db->name", $foundServices)) {
+                    continue;
+                } else {
+                    $exitedServices->push($db);
+                }
+            }
+        }
+        $exitedServices = $exitedServices->unique('id');
+        foreach ($exitedServices as $exitedService) {
+            if (str($exitedService->status)->startsWith('exited')) {
+                continue;
+            }
+            $name = data_get($exitedService, 'name');
+            $fqdn = data_get($exitedService, 'fqdn');
+            $containerName = $name ? "$name, available at $fqdn" : $fqdn;
+            $projectUuid = data_get($service, 'environment.project.uuid');
+            $serviceUuid = data_get($service, 'uuid');
+            $environmentName = data_get($service, 'environment.name');
+
+            if ($projectUuid && $serviceUuid && $environmentName) {
+                $url =  base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/service/" . $serviceUuid;
+            } else {
+                $url = null;
+            }
+            $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
+            $exitedService->update(['status' => 'exited']);
+        }
+
+        $notRunningApplications = $this->applications->pluck('id')->diff($foundApplications);
+        foreach ($notRunningApplications as $applicationId) {
+            $application = $this->applications->where('id', $applicationId)->first();
+            if (str($application->status)->startsWith('exited')) {
+                continue;
+            }
+            $application->update(['status' => 'exited']);
+
+            $name = data_get($application, 'name');
+            $fqdn = data_get($application, 'fqdn');
+
+            $containerName = $name ? "$name ($fqdn)" : $fqdn;
+
+            $projectUuid = data_get($application, 'environment.project.uuid');
+            $applicationUuid = data_get($application, 'uuid');
+            $environment = data_get($application, 'environment.name');
+
+            if ($projectUuid && $applicationUuid && $environment) {
+                $url =  base_url() . '/project/' . $projectUuid . "/" . $environment . "/application/" . $applicationUuid;
+            } else {
+                $url = null;
+            }
+
+            $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
+        }
+        $notRunningApplicationPreviews = $previews->pluck('id')->diff($foundApplicationPreviews);
+        foreach ($notRunningApplicationPreviews as $previewId) {
+            $preview = $previews->where('id', $previewId)->first();
+            if (str($preview->status)->startsWith('exited')) {
+                continue;
+            }
+            $preview->update(['status' => 'exited']);
+
+            $name = data_get($preview, 'name');
+            $fqdn = data_get($preview, 'fqdn');
+
+            $containerName = $name ? "$name ($fqdn)" : $fqdn;
+
+            $projectUuid = data_get($preview, 'application.environment.project.uuid');
+            $environmentName = data_get($preview, 'application.environment.name');
+            $applicationUuid = data_get($preview, 'application.uuid');
+
+            if ($projectUuid && $applicationUuid && $environmentName) {
+                $url =  base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/application/" . $applicationUuid;
+            } else {
+                $url = null;
+            }
+
+            $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
+        }
+        $notRunningDatabases = $databases->pluck('id')->diff($foundDatabases);
+        foreach ($notRunningDatabases as $database) {
+            $database = $databases->where('id', $database)->first();
+            if (str($database->status)->startsWith('exited')) {
+                continue;
+            }
+            $database->update(['status' => 'exited']);
+
+            $name = data_get($database, 'name');
+            $fqdn = data_get($database, 'fqdn');
+
+            $containerName = $name;
+
+            $projectUuid = data_get($database, 'environment.project.uuid');
+            $environmentName = data_get($database, 'environment.name');
+            $databaseUuid = data_get($database, 'uuid');
+
+            if ($projectUuid && $databaseUuid && $environmentName) {
+                $url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/database/" . $databaseUuid;
+            } else {
+                $url = null;
+            }
+            $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
+        }
+
+        // Check if proxy is running
+        $this->server->proxyType();
+        $foundProxyContainer = $containers->filter(function ($value, $key) {
+            if ($this->server->isSwarm()) {
+                return data_get($value, 'Spec.Name') === 'coolify-proxy_traefik';
+            } else {
+                return data_get($value, 'Name') === '/coolify-proxy';
+            }
+        })->first();
+        if (!$foundProxyContainer) {
+            try {
+                $shouldStart = CheckProxy::run($this->server);
+                if ($shouldStart) {
+                    StartProxy::run($this->server, false);
+                    $this->server->team?->notify(new ContainerRestarted('coolify-proxy', $this->server));
+                }
+            } catch (\Throwable $e) {
+                ray($e);
+            }
+        } else {
+            $this->server->proxy->status = data_get($foundProxyContainer, 'State.Status');
+            $this->server->save();
+            $connectProxyToDockerNetworks = connectProxyToNetworks($this->server);
+            instant_remote_process($connectProxyToDockerNetworks, $this->server, false);
+        }
+    }
+}
diff --git a/app/Actions/Server/StartSentinel.php b/app/Actions/Server/StartSentinel.php
new file mode 100644
index 000000000..6f3c81d77
--- /dev/null
+++ b/app/Actions/Server/StartSentinel.php
@@ -0,0 +1,22 @@
+server, false);
             $this->latestVersion = get_latest_version_of_coolify();
             $this->currentVersion = config('version');
-            if ($settings->next_channel) {
-                ray('next channel enabled');
-                $this->latestVersion = 'next';
-            }
+            // if ($settings->next_channel) {
+            //     ray('next channel enabled');
+            //     $this->latestVersion = 'next';
+            // }
             if ($force) {
                 $this->update();
             } else {
diff --git a/app/Console/Commands/AdminRemoveUser.php b/app/Console/Commands/AdminRemoveUser.php
new file mode 100644
index 000000000..76af0a97f
--- /dev/null
+++ b/app/Console/Commands/AdminRemoveUser.php
@@ -0,0 +1,54 @@
+argument('email');
+            $confirm = $this->confirm('Are you sure you want to remove user with email: ' . $email . '?');
+            if (!$confirm) {
+                $this->info('User removal cancelled.');
+                return;
+            }
+            $this->info("Removing user with email: $email");
+            $user = User::whereEmail($email)->firstOrFail();
+            $teams = $user->teams;
+            foreach ($teams as $team) {
+                if ($team->members->count() > 1) {
+                    $this->error('User is a member of a team with more than one member. Please remove user from team first.');
+                    return;
+                }
+                $team->delete();
+            }
+            $user->delete();
+        } catch (\Exception $e) {
+            $this->error('Failed to remove user.');
+            $this->error($e->getMessage());
+            return;
+        }
+    }
+}
diff --git a/app/Console/Commands/Cloud.php b/app/Console/Commands/Cloud.php
deleted file mode 100644
index 1386b296c..000000000
--- a/app/Console/Commands/Cloud.php
+++ /dev/null
@@ -1,33 +0,0 @@
-whereNotNull('team.subscription')->where('team.subscription.stripe_trial_already_ended',true)->each(function($server){
-            $this->info($server->name);
-        });
-    }
-}
diff --git a/app/Console/Commands/RootResetPassword.php b/app/Console/Commands/RootResetPassword.php
index df385002e..af2b1a45c 100644
--- a/app/Console/Commands/RootResetPassword.php
+++ b/app/Console/Commands/RootResetPassword.php
@@ -29,7 +29,6 @@ class RootResetPassword extends Command
      */
     public function handle()
     {
-        //
         $this->info('You are about to reset the root password.');
         $password = password('Give me a new password for root user: ');
         $passwordAgain = password('Again');
diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php
index 31760f2fd..23289f90e 100644
--- a/app/Console/Kernel.php
+++ b/app/Console/Kernel.php
@@ -9,6 +9,7 @@ use App\Jobs\ScheduledTaskJob;
 use App\Jobs\InstanceAutoUpdateJob;
 use App\Jobs\ContainerStatusJob;
 use App\Jobs\PullHelperImageJob;
+use App\Jobs\PullSentinelImageJob;
 use App\Jobs\ServerStatusJob;
 use App\Models\InstanceSettings;
 use App\Models\ScheduledDatabaseBackup;
@@ -20,8 +21,10 @@ use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
 
 class Kernel extends ConsoleKernel
 {
+    private $all_servers;
     protected function schedule(Schedule $schedule): void
     {
+        $this->all_servers = Server::all();
         if (isDev()) {
             // Instance Jobs
             $schedule->command('horizon:snapshot')->everyMinute();
@@ -55,35 +58,38 @@ class Kernel extends ConsoleKernel
     }
     private function pull_helper_image($schedule)
     {
-        $servers = Server::all()->where('settings.is_usable', true)->where('settings.is_reachable', true)->where('ip', '!=', '1.2.3.4');
+        $servers = $this->all_servers->where('settings.is_usable', true)->where('settings.is_reachable', true)->where('ip', '!=', '1.2.3.4');
         foreach ($servers as $server) {
-            $schedule->job(new PullHelperImageJob($server))->everyTenMinutes()->onOneServer();
+            if (config('coolify.is_sentinel_enabled')) {
+                $schedule->job(new PullSentinelImageJob($server))->everyFiveMinutes()->onOneServer();
+            }
+            $schedule->job(new PullHelperImageJob($server))->everyFiveMinutes()->onOneServer();
         }
     }
     private function check_resources($schedule)
     {
         if (isCloud()) {
-            $servers = Server::all()->whereNotNull('team.subscription')->where('team.subscription.stripe_trial_already_ended', false)->where('ip', '!=', '1.2.3.4');
+            $servers = $this->all_servers->whereNotNull('team.subscription')->where('team.subscription.stripe_trial_already_ended', false)->where('ip', '!=', '1.2.3.4');
             $own = Team::find(0)->servers;
             $servers = $servers->merge($own);
             $containerServers = $servers->where('settings.is_swarm_worker', false)->where('settings.is_build_server', false);
         } else {
-            $servers = Server::all()->where('ip', '!=', '1.2.3.4');
+            $servers = $this->all_servers->where('ip', '!=', '1.2.3.4');
             $containerServers = $servers->where('settings.is_swarm_worker', false)->where('settings.is_build_server', false);
         }
         foreach ($containerServers as $server) {
-            $schedule->job(new ContainerStatusJob($server))->everyTwoMinutes()->onOneServer();
+            $schedule->job(new ContainerStatusJob($server))->everyMinute()->onOneServer();
             if ($server->isLogDrainEnabled()) {
-                $schedule->job(new CheckLogDrainContainerJob($server))->everyTwoMinutes()->onOneServer();
+                $schedule->job(new CheckLogDrainContainerJob($server))->everyMinute()->onOneServer();
             }
         }
         foreach ($servers as $server) {
-            $schedule->job(new ServerStatusJob($server))->everyTwoMinutes()->onOneServer();
+            $schedule->job(new ServerStatusJob($server))->everyMinute()->onOneServer();
         }
     }
     private function instance_auto_update($schedule)
     {
-        if (isDev()) {
+        if (isDev() || isCloud()) {
             return;
         }
         $settings = InstanceSettings::get();
@@ -134,7 +140,16 @@ class Kernel extends ConsoleKernel
                 $scheduled_task->delete();
                 continue;
             }
-
+            if ($application) {
+                if (str($application->status)->contains('running') === false) {
+                    continue;
+                }
+            }
+            if ($service) {
+                if (str($service->status())->contains('running') === false) {
+                    continue;
+                }
+            }
             if (isset(VALID_CRON_STRINGS[$scheduled_task->frequency])) {
                 $scheduled_task->frequency = VALID_CRON_STRINGS[$scheduled_task->frequency];
             }
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/Http/Controllers/Webhook/Bitbucket.php b/app/Http/Controllers/Webhook/Bitbucket.php
index 485720c23..7b569c278 100644
--- a/app/Http/Controllers/Webhook/Bitbucket.php
+++ b/app/Http/Controllers/Webhook/Bitbucket.php
@@ -47,7 +47,7 @@ class Bitbucket extends Controller
             if ($x_bitbucket_event === 'repo:push') {
                 $branch = data_get($payload, 'push.changes.0.new.name');
                 $full_name = data_get($payload, 'repository.full_name');
-
+                $commit = data_get($payload, 'push.changes.0.new.target.hash');
                 if (!$branch) {
                     return response([
                         'status' => 'failed',
@@ -104,6 +104,7 @@ class Bitbucket extends Controller
                         queue_application_deployment(
                             application: $application,
                             deployment_uuid: $deployment_uuid,
+                            commit: $commit,
                             force_rebuild: false,
                             is_webhook: true
                         );
diff --git a/app/Http/Controllers/Webhook/Github.php b/app/Http/Controllers/Webhook/Github.php
index 214843aab..baa23deec 100644
--- a/app/Http/Controllers/Webhook/Github.php
+++ b/app/Http/Controllers/Webhook/Github.php
@@ -129,6 +129,7 @@ class Github extends Controller
                                 application: $application,
                                 deployment_uuid: $deployment_uuid,
                                 force_rebuild: false,
+                                commit: data_get($payload, 'after', 'HEAD'),
                                 is_webhook: true,
                             );
                             $return_payloads->push([
@@ -177,6 +178,7 @@ class Github extends Controller
                                 pull_request_id: $pull_request_id,
                                 deployment_uuid: $deployment_uuid,
                                 force_rebuild: false,
+                                commit: data_get($payload, 'head.sha', 'HEAD'),
                                 is_webhook: true,
                                 git_type: 'github'
                             );
@@ -338,6 +340,7 @@ class Github extends Controller
                             queue_application_deployment(
                                 application: $application,
                                 deployment_uuid: $deployment_uuid,
+                                commit: data_get($payload, 'after', 'HEAD'),
                                 force_rebuild: false,
                                 is_webhook: true,
                             );
@@ -387,6 +390,7 @@ class Github extends Controller
                                 pull_request_id: $pull_request_id,
                                 deployment_uuid: $deployment_uuid,
                                 force_rebuild: false,
+                                commit: data_get($payload, 'head.sha', 'HEAD'),
                                 is_webhook: true,
                                 git_type: 'github'
                             );
diff --git a/app/Http/Controllers/Webhook/Gitlab.php b/app/Http/Controllers/Webhook/Gitlab.php
index 65ce9910b..dfa9394eb 100644
--- a/app/Http/Controllers/Webhook/Gitlab.php
+++ b/app/Http/Controllers/Webhook/Gitlab.php
@@ -38,6 +38,15 @@ class Gitlab extends Controller
             $headers = $request->headers->all();
             $x_gitlab_token = data_get($headers, 'x-gitlab-token.0');
             $x_gitlab_event = data_get($payload, 'object_kind');
+            $allowed_events = ['push', 'merge_request'];
+            if (!in_array($x_gitlab_event, $allowed_events)) {
+                $return_payloads->push([
+                    'status' => 'failed',
+                    'message' => 'Event not allowed. Only push and merge_request events are allowed.',
+                ]);
+                return response($return_payloads);
+            }
+
             if ($x_gitlab_event === 'push') {
                 $branch = data_get($payload, 'ref');
                 $full_name = data_get($payload, 'project.path_with_namespace');
@@ -124,6 +133,7 @@ class Gitlab extends Controller
                             queue_application_deployment(
                                 application: $application,
                                 deployment_uuid: $deployment_uuid,
+                                commit: data_get($payload, 'after', 'HEAD'),
                                 force_rebuild: false,
                                 is_webhook: true,
                             );
@@ -173,6 +183,7 @@ class Gitlab extends Controller
                                 application: $application,
                                 pull_request_id: $pull_request_id,
                                 deployment_uuid: $deployment_uuid,
+                                commit: data_get($payload, 'object_attributes.last_commit.id', 'HEAD'),
                                 force_rebuild: false,
                                 is_webhook: true,
                                 git_type: 'gitlab'
diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php
index 1717c5d08..47319ac10 100644
--- a/app/Jobs/ApplicationDeploymentJob.php
+++ b/app/Jobs/ApplicationDeploymentJob.php
@@ -2,6 +2,7 @@
 
 namespace App\Jobs;
 
+use App\Actions\Docker\GetContainersStatus;
 use App\Enums\ApplicationDeploymentStatus;
 use App\Enums\ProcessStatus;
 use App\Events\ApplicationStatusChanged;
@@ -95,7 +96,6 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
     private ?string $buildTarget = null;
     private Collection $saved_outputs;
     private ?string $full_healthcheck_url = null;
-    private bool $custom_healthcheck_found = false;
 
     private string $serverUser = 'root';
     private string $serverUserHomeDir = '/root';
@@ -107,6 +107,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
     private ?string $fullRepoUrl = null;
     private ?string $branch = null;
 
+    private ?string $coolify_variables = null;
+
     public $tries = 1;
     public function __construct(int $application_deployment_queue_id)
     {
@@ -303,7 +305,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
     {
 
         if ($this->server->isProxyShouldRun()) {
-            dispatch(new ContainerStatusJob($this->server));
+            GetContainersStatus::dispatch($this->server);
+            // dispatch(new ContainerStatusJob($this->server));
         }
         $this->next(ApplicationDeploymentStatus::FINISHED->value);
         if ($this->pull_request_id !== 0) {
@@ -405,7 +408,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
             );
         } 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} build"), "hidden" => true],
+                [executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build"), "hidden" => true],
             );
         }
 
@@ -435,9 +438,9 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
             } else {
                 $this->write_deployment_configurations();
                 $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");
+                ray("{$this->coolify_variables} 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],
+                    ["{$this->coolify_variables} docker compose --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d", "hidden" => true],
                 );
             }
         } else {
@@ -448,7 +451,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
                 $this->write_deployment_configurations();
             } 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],
+                    [executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up -d"), "hidden" => true],
                 );
                 $this->write_deployment_configurations();
             }
@@ -710,10 +713,40 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
     private function save_environment_variables()
     {
         $envs = collect([]);
+        $local_branch = $this->branch;
+        if ($this->pull_request_id !== 0) {
+            $local_branch = "pull/{$this->pull_request_id}/head";
+        }
+        $sort = $this->application->settings->is_env_sorting_enabled;
+        if ($sort) {
+            $sorted_environment_variables = $this->application->environment_variables->sortBy('key');
+            $sorted_environment_variables_preview = $this->application->environment_variables_preview->sortBy('key');
+        } else {
+            $sorted_environment_variables = $this->application->environment_variables->sortBy('id');
+            $sorted_environment_variables_preview = $this->application->environment_variables_preview->sortBy('id');
+        }
         $ports = $this->application->main_port();
         if ($this->pull_request_id !== 0) {
             $this->env_filename = ".env-pr-$this->pull_request_id";
-            foreach ($this->application->environment_variables_preview as $env) {
+            // Add SOURCE_COMMIT if not exists
+            if ($this->application->environment_variables_preview->where('key', 'SOURCE_COMMIT')->isEmpty()) {
+                if (!is_null($this->commit)) {
+                    $envs->push("SOURCE_COMMIT={$this->commit}");
+                } else {
+                    $envs->push("SOURCE_COMMIT=unknown");
+                }
+            }
+            if ($this->application->environment_variables_preview->where('key', 'COOLIFY_FQDN')->isEmpty()) {
+                $envs->push("COOLIFY_FQDN={$this->preview->fqdn}");
+            }
+            if ($this->application->environment_variables_preview->where('key', 'COOLIFY_URL')->isEmpty()) {
+                $url = str($this->preview->fqdn)->replace('http://', '')->replace('https://', '');
+                $envs->push("COOLIFY_URL={$url}");
+            }
+            if ($this->application->environment_variables_preview->where('key', 'COOLIFY_BRANCH')->isEmpty()) {
+                $envs->push("COOLIFY_BRANCH={$local_branch}");
+            }
+            foreach ($sorted_environment_variables_preview as $env) {
                 $real_value = $env->real_value;
                 if ($env->version === '4.0.0-beta.239') {
                     $real_value = $env->real_value;
@@ -734,20 +767,27 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
             if ($this->application->environment_variables_preview->where('key', 'HOST')->isEmpty()) {
                 $envs->push("HOST=0.0.0.0");
             }
+        } else {
+            $this->env_filename = ".env";
             // Add SOURCE_COMMIT if not exists
-            if ($this->application->environment_variables_preview->where('key', 'SOURCE_COMMIT')->isEmpty()) {
+            if ($this->application->environment_variables->where('key', 'SOURCE_COMMIT')->isEmpty()) {
                 if (!is_null($this->commit)) {
                     $envs->push("SOURCE_COMMIT={$this->commit}");
                 } else {
                     $envs->push("SOURCE_COMMIT=unknown");
                 }
             }
-            $envs = $envs->sort(function ($a, $b) {
-                return strpos($a, '$') === false ? -1 : 1;
-            });
-        } else {
-            $this->env_filename = ".env";
-            foreach ($this->application->environment_variables as $env) {
+            if ($this->application->environment_variables->where('key', 'COOLIFY_FQDN')->isEmpty()) {
+                $envs->push("COOLIFY_FQDN={$this->application->fqdn}");
+            }
+            if ($this->application->environment_variables->where('key', 'COOLIFY_URL')->isEmpty()) {
+                $url = str($this->application->fqdn)->replace('http://', '')->replace('https://', '');
+                $envs->push("COOLIFY_URL={$url}");
+            }
+            if ($this->application->environment_variables_preview->where('key', 'COOLIFY_BRANCH')->isEmpty()) {
+                $envs->push("COOLIFY_BRANCH={$local_branch}");
+            }
+            foreach ($sorted_environment_variables as $env) {
                 $real_value = $env->real_value;
                 if ($env->version === '4.0.0-beta.239') {
                     $real_value = $env->real_value;
@@ -768,17 +808,6 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
             if ($this->application->environment_variables->where('key', 'HOST')->isEmpty()) {
                 $envs->push("HOST=0.0.0.0");
             }
-            // Add SOURCE_COMMIT if not exists
-            if ($this->application->environment_variables->where('key', 'SOURCE_COMMIT')->isEmpty()) {
-                if (!is_null($this->commit)) {
-                    $envs->push("SOURCE_COMMIT={$this->commit}");
-                } else {
-                    $envs->push("SOURCE_COMMIT=unknown");
-                }
-            }
-            $envs = $envs->sort(function ($a, $b) {
-                return strpos($a, '$') === false ? -1 : 1;
-            });
         }
 
         if ($envs->isEmpty()) {
@@ -870,7 +899,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.");
@@ -878,6 +907,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.");
@@ -903,10 +935,13 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
         if ($this->server->isSwarm()) {
             // Implement healthcheck for swarm
         } else {
-            if ($this->application->isHealthcheckDisabled() && $this->custom_healthcheck_found === false) {
+            if ($this->application->isHealthcheckDisabled() && $this->application->custom_healthcheck_found === false) {
                 $this->newVersionIsHealthy = true;
                 return;
             }
+            if ($this->application->custom_healthcheck_found) {
+                $this->application_deployment_queue->addLogEntry("Custom healthcheck found, skipping default healthcheck.");
+            }
             // ray('New container name: ', $this->container_name);
             if ($this->container_name) {
                 $counter = 1;
@@ -914,6 +949,12 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
                 if ($this->full_healthcheck_url) {
                     $this->application_deployment_queue->addLogEntry("Healthcheck URL (inside the container): {$this->full_healthcheck_url}");
                 }
+                $this->application_deployment_queue->addLogEntry("Waiting for the start period ({$this->application->health_check_start_period} seconds) before starting healthcheck.");
+                $sleeptime = 0;
+                while ($sleeptime < $this->application->health_check_start_period) {
+                    Sleep::for(1)->seconds();
+                    $sleeptime++;
+                }
                 while ($counter <= $this->application->health_check_retries) {
                     $this->execute_remote_command(
                         [
@@ -922,9 +963,23 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
                             "save" => "health_check",
                             "append" => false
                         ],
-
+                        [
+                            "docker inspect --format='{{json .State.Health.Log}}' {$this->container_name}",
+                            "hidden" => true,
+                            "save" => "health_check_logs",
+                            "append" => false
+                        ],
                     );
                     $this->application_deployment_queue->addLogEntry("Attempt {$counter} of {$this->application->health_check_retries} | Healthcheck status: {$this->saved_outputs->get('health_check')}");
+                    $health_check_logs = data_get(collect(json_decode($this->saved_outputs->get('health_check_logs')))->last(), 'Output', '(no logs)');
+                    if (empty($health_check_logs)) {
+                        $health_check_logs = '(no logs)';
+                    }
+                    $health_check_return_code = data_get(collect(json_decode($this->saved_outputs->get('health_check_logs')))->last(), 'ExitCode', '(no return code)');
+                    if ($health_check_logs !== '(no logs)' || $health_check_return_code !== '(no return code)') {
+                        $this->application_deployment_queue->addLogEntry("Healthcheck logs: {$health_check_logs} | Return code: {$health_check_return_code}");
+                    }
+
                     if (Str::of($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'healthy') {
                         $this->newVersionIsHealthy = true;
                         $this->application->update(['status' => 'running']);
@@ -936,7 +991,11 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
                         break;
                     }
                     $counter++;
-                    Sleep::for($this->application->health_check_interval)->seconds();
+                    $sleeptime = 0;
+                    while ($sleeptime < $this->application->health_check_interval) {
+                        Sleep::for(1)->seconds();
+                        $sleeptime++;
+                    }
                 }
             }
         }
@@ -954,6 +1013,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
         $this->generate_image_names();
         $this->application_deployment_queue->addLogEntry("Starting pull request (#{$this->pull_request_id}) deployment of {$this->customRepository}:{$this->application->git_branch}.");
         $this->prepare_builder_image();
+        $this->check_git_if_build_needed();
         $this->clone_repository();
         $this->set_base_dir();
         $this->cleanup_git();
@@ -1005,7 +1065,9 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
                 "command" => "docker rm -f {$this->deployment_uuid}",
                 "ignore_errors" => true,
                 "hidden" => true
-            ],
+            ]
+        );
+        $this->execute_remote_command(
             [
                 $runCommand,
                 "hidden" => true,
@@ -1061,9 +1123,30 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
     {
         $this->application_deployment_queue->addLogEntry("Setting base directory to {$this->workdir}.");
     }
+    private function set_coolify_variables()
+    {
+        $this->coolify_variables = "SOURCE_COMMIT={$this->commit} ";
+        if ($this->pull_request_id === 0) {
+            $fqdn = $this->application->fqdn;
+        } else {
+            $fqdn = $this->preview->fqdn;
+        }
+        if (isset($fqdn)) {
+            $this->coolify_variables .= "COOLIFY_FQDN={$fqdn} ";
+            $url = str($fqdn)->replace('http://', '')->replace('https://', '');
+            $this->coolify_variables .= "COOLIFY_URL={$url} ";
+        }
+        if (isset($this->application->git_branch)) {
+            $this->coolify_variables .= "COOLIFY_BRANCH={$this->application->git_branch} ";
+        }
+    }
     private function check_git_if_build_needed()
     {
         $this->generate_git_import_commands();
+        $local_branch = $this->branch;
+        if ($this->pull_request_id !== 0) {
+            $local_branch = "pull/{$this->pull_request_id}/head";
+        }
         $private_key = data_get($this->application, 'private_key.private_key');
         if ($private_key) {
             $private_key = base64_encode($private_key);
@@ -1078,7 +1161,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
                     executeInDocker($this->deployment_uuid, "chmod 600 /root/.ssh/id_rsa")
                 ],
                 [
-                    executeInDocker($this->deployment_uuid, "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$this->customPort} -o Port={$this->customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git ls-remote {$this->fullRepoUrl} {$this->branch}"),
+                    executeInDocker($this->deployment_uuid, "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$this->customPort} -o Port={$this->customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git ls-remote {$this->fullRepoUrl} {$local_branch}"),
                     "hidden" => true,
                     "save" => "git_commit_sha"
                 ],
@@ -1086,15 +1169,19 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
         } else {
             $this->execute_remote_command(
                 [
-                    executeInDocker($this->deployment_uuid, "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$this->customPort} -o Port={$this->customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git ls-remote {$this->fullRepoUrl} {$this->branch}"),
+                    executeInDocker($this->deployment_uuid, "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$this->customPort} -o Port={$this->customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git ls-remote {$this->fullRepoUrl} {$local_branch}"),
                     "hidden" => true,
                     "save" => "git_commit_sha"
                 ],
             );
         }
+        ray("GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$this->customPort} -o Port={$this->customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git ls-remote {$this->fullRepoUrl} {$local_branch}");
         if ($this->saved_outputs->get('git_commit_sha') && !$this->rollback) {
             $this->commit = $this->saved_outputs->get('git_commit_sha')->before("\t");
+            $this->application_deployment_queue->commit = $this->commit;
+            $this->application_deployment_queue->save();
         }
+        $this->set_coolify_variables();
     }
     private function clone_repository()
     {
@@ -1104,12 +1191,29 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
         if ($this->pull_request_id !== 0) {
             $this->application_deployment_queue->addLogEntry("Checking out tag pull/{$this->pull_request_id}/head.");
         }
+        ray($importCommands);
         $this->execute_remote_command(
             [
                 $importCommands, "hidden" => true
             ]
         );
         $this->create_workdir();
+        $this->execute_remote_command(
+            [
+                executeInDocker($this->deployment_uuid, "cd {$this->workdir} && git log -1 {$this->commit} --pretty=%B"),
+                "hidden" => true,
+                "save" => "commit_message"
+            ]
+        );
+        ray($this->saved_outputs->get('commit_message'));
+        raY($this->commit);
+        if ($this->saved_outputs->get('commit_message')) {
+            $commit_message = str($this->saved_outputs->get('commit_message'))->limit(47);
+            $this->application_deployment_queue->commit_message = $commit_message->value();
+            ApplicationDeploymentQueue::whereCommit($this->commit)->whereApplicationId($this->application->id)->update(
+                ['commit_message' => $commit_message->value()]
+            );
+        }
     }
 
     private function generate_git_import_commands()
@@ -1197,6 +1301,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
     private function generate_env_variables()
     {
         $this->env_args = collect([]);
+        $this->env_args->put('SOURCE_COMMIT', $this->commit);
         if ($this->pull_request_id === 0) {
             foreach ($this->application->build_environment_variables as $env) {
                 if (!is_null($env->real_value)) {
@@ -1210,7 +1315,6 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
                 }
             }
         }
-        $this->env_args->put('SOURCE_COMMIT', $this->commit);
     }
 
     private function generate_compose_file()
@@ -1258,23 +1362,22 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
         if ($this->pull_request_id !== 0) {
             $labels = collect(generateLabelsApplication($this->application, $this->preview));
         }
-        $labels = $labels->map(function ($value, $key) {
-            return escapeDollarSign($value);
-        });
+        if ($this->application->settings->is_container_label_escape_enabled) {
+            $labels = $labels->map(function ($value, $key) {
+                return escapeDollarSign($value);
+            });
+        }
         $labels = $labels->merge(defaultLabels($this->application->id, $this->application->uuid, $this->pull_request_id))->toArray();
+
         // Check for custom HEALTHCHECK
-        $this->custom_healthcheck_found = false;
         if ($this->application->build_pack === 'dockerfile' || $this->application->dockerfile) {
             $this->execute_remote_command([
                 executeInDocker($this->deployment_uuid, "cat {$this->workdir}{$this->dockerfile_location}"), "hidden" => true, "save" => 'dockerfile_from_repo', "ignore_errors" => true
             ]);
             $dockerfile = collect(Str::of($this->saved_outputs->get('dockerfile_from_repo'))->trim()->explode("\n"));
-            if (str($dockerfile)->contains('HEALTHCHECK')) {
-                $this->custom_healthcheck_found = true;
-            }
+            $this->application->parseHealthcheckFromDockerfile($dockerfile);
         }
         $docker_compose = [
-            'version' => '3.8',
             'services' => [
                 $this->container_name => [
                     'image' => $this->production_image_name,
@@ -1282,7 +1385,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,
@@ -1300,6 +1407,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';
@@ -1317,18 +1427,17 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
         if (!is_null($this->env_filename)) {
             $docker_compose['services'][$this->container_name]['env_file'] = [$this->env_filename];
         }
-        if (!$this->custom_healthcheck_found) {
-            $docker_compose['services'][$this->container_name]['healthcheck'] = [
-                'test' => [
-                    'CMD-SHELL',
-                    $this->generate_healthcheck_commands()
-                ],
-                'interval' => $this->application->health_check_interval . 's',
-                'timeout' => $this->application->health_check_timeout . 's',
-                'retries' => $this->application->health_check_retries,
-                'start_period' => $this->application->health_check_start_period . 's'
-            ];
-        }
+        $docker_compose['services'][$this->container_name]['healthcheck'] = [
+            'test' => [
+                'CMD-SHELL',
+                $this->generate_healthcheck_commands()
+            ],
+            'interval' => $this->application->health_check_interval . 's',
+            'timeout' => $this->application->health_check_timeout . 's',
+            'retries' => $this->application->health_check_retries,
+            'start_period' => $this->application->health_check_start_period . 's'
+        ];
+
         if (!is_null($this->application->limits_cpuset)) {
             data_set($docker_compose, 'services.' . $this->container_name . '.cpuset', $this->application->limits_cpuset);
         }
@@ -1510,95 +1619,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 {
@@ -1610,12 +1632,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);
@@ -1804,12 +1826,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,
@@ -1827,11 +1854,11 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
             $this->application_deployment_queue->addLogEntry("Pulling latest images from the registry.");
             $this->execute_remote_command(
                 [executeInDocker($this->deployment_uuid, "docker compose --project-directory {$this->workdir} pull"), "hidden" => true],
-                [executeInDocker($this->deployment_uuid, "SOURCE_COMMIT={$this->commit} docker compose --project-directory {$this->workdir} build"), "hidden" => true],
+                [executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-directory {$this->workdir} build"), "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} build"), "hidden" => true],
+                [executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build"), "hidden" => true],
             );
         }
         $this->application_deployment_queue->addLogEntry("New images built.");
@@ -1843,16 +1870,16 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
             $this->application_deployment_queue->addLogEntry("Pulling latest images from the registry.");
             $this->execute_remote_command(
                 [executeInDocker($this->deployment_uuid, "docker compose --project-directory {$this->workdir} pull"), "hidden" => true],
-                [executeInDocker($this->deployment_uuid, "SOURCE_COMMIT={$this->commit} docker compose --project-directory {$this->workdir} up --build -d"), "hidden" => true],
+                [executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-directory {$this->workdir} up --build -d"), "hidden" => true],
             );
         } else {
             if ($this->use_build_server) {
                 $this->execute_remote_command(
-                    ["SOURCE_COMMIT={$this->commit} docker compose --project-directory {$this->configuration_dir} -f {$this->configuration_dir}{$this->docker_compose_location} up --build -d", "hidden" => true],
+                    ["{$this->coolify_variables} docker compose --project-directory {$this->configuration_dir} -f {$this->configuration_dir}{$this->docker_compose_location} up --build -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 --build -d"), "hidden" => true],
+                    [executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up --build -d"), "hidden" => true],
                 );
             }
         }
diff --git a/app/Jobs/ContainerStatusJob.php b/app/Jobs/ContainerStatusJob.php
index a9cec009b..11e7013ee 100644
--- a/app/Jobs/ContainerStatusJob.php
+++ b/app/Jobs/ContainerStatusJob.php
@@ -2,15 +2,8 @@
 
 namespace App\Jobs;
 
-use App\Actions\Database\StartDatabaseProxy;
-use App\Actions\Proxy\CheckProxy;
-use App\Actions\Proxy\StartProxy;
-use App\Actions\Shared\ComplexStatusCheck;
-use App\Models\ApplicationPreview;
+use App\Actions\Docker\GetContainersStatus;
 use App\Models\Server;
-use App\Models\ServiceDatabase;
-use App\Notifications\Container\ContainerRestarted;
-use App\Notifications\Container\ContainerStopped;
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldBeEncrypted;
 use Illuminate\Contracts\Queue\ShouldQueue;
@@ -18,7 +11,6 @@ use Illuminate\Foundation\Bus\Dispatchable;
 use Illuminate\Queue\InteractsWithQueue;
 use Illuminate\Queue\Middleware\WithoutOverlapping;
 use Illuminate\Queue\SerializesModels;
-use Illuminate\Support\Arr;
 
 class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
 {
@@ -44,335 +36,6 @@ class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
 
     public function handle()
     {
-        if (!$this->server->isFunctional()) {
-            return 'Server is not ready.';
-        };
-        $applications = $this->server->applications();
-        $skip_these_applications = collect([]);
-        foreach ($applications as $application) {
-            if ($application->additional_servers->count() > 0) {
-                $skip_these_applications->push($application);
-                ComplexStatusCheck::run($application);
-                $applications = $applications->filter(function ($value, $key) use ($application) {
-                    return $value->id !== $application->id;
-                });
-            }
-        }
-        $applications = $applications->filter(function ($value, $key) use ($skip_these_applications) {
-            return !$skip_these_applications->pluck('id')->contains($value->id);
-        });
-        try {
-            if ($this->server->isSwarm()) {
-                $containers = instant_remote_process(["docker service inspect $(docker service ls -q) --format '{{json .}}'"], $this->server, false);
-                $containerReplicates = instant_remote_process(["docker service ls --format '{{json .}}'"], $this->server, false);
-            } else {
-                // Precheck for containers
-                $containers = instant_remote_process(["docker container ls -q"], $this->server, false);
-                if (!$containers) {
-                    return;
-                }
-                $containers = instant_remote_process(["docker container inspect $(docker container ls -q) --format '{{json .}}'"], $this->server, false);
-                $containerReplicates = null;
-            }
-            if (is_null($containers)) {
-                return;
-            }
-
-            $containers = format_docker_command_output_to_json($containers);
-            if ($containerReplicates) {
-                $containerReplicates = format_docker_command_output_to_json($containerReplicates);
-                foreach ($containerReplicates as $containerReplica) {
-                    $name = data_get($containerReplica, 'Name');
-                    $containers = $containers->map(function ($container) use ($name, $containerReplica) {
-                        if (data_get($container, 'Spec.Name') === $name) {
-                            $replicas = data_get($containerReplica, 'Replicas');
-                            $running = str($replicas)->explode('/')[0];
-                            $total = str($replicas)->explode('/')[1];
-                            if ($running === $total) {
-                                data_set($container, 'State.Status', 'running');
-                                data_set($container, 'State.Health.Status', 'healthy');
-                            } else {
-                                data_set($container, 'State.Status', 'starting');
-                                data_set($container, 'State.Health.Status', 'unhealthy');
-                            }
-                        }
-                        return $container;
-                    });
-                }
-            }
-            $databases = $this->server->databases();
-            $services = $this->server->services()->get();
-            $previews = $this->server->previews();
-            $foundApplications = [];
-            $foundApplicationPreviews = [];
-            $foundDatabases = [];
-            $foundServices = [];
-
-            foreach ($containers as $container) {
-                if ($this->server->isSwarm()) {
-                    $labels = data_get($container, 'Spec.Labels');
-                    $uuid = data_get($labels, 'coolify.name');
-                } else {
-                    $labels = data_get($container, 'Config.Labels');
-                }
-                $containerStatus = data_get($container, 'State.Status');
-                $containerHealth = data_get($container, 'State.Health.Status', 'unhealthy');
-                $containerStatus = "$containerStatus ($containerHealth)";
-                $labels = Arr::undot(format_docker_labels_to_json($labels));
-                $applicationId = data_get($labels, 'coolify.applicationId');
-                if ($applicationId) {
-                    $pullRequestId = data_get($labels, 'coolify.pullRequestId');
-                    if ($pullRequestId) {
-                        if (str($applicationId)->contains('-')) {
-                            $applicationId = str($applicationId)->before('-');
-                        }
-                        $preview = ApplicationPreview::where('application_id', $applicationId)->where('pull_request_id', $pullRequestId)->first();
-                        if ($preview) {
-                            $foundApplicationPreviews[] = $preview->id;
-                            $statusFromDb = $preview->status;
-                            if ($statusFromDb !== $containerStatus) {
-                                $preview->update(['status' => $containerStatus]);
-                            }
-                        } else {
-                            //Notify user that this container should not be there.
-                        }
-                    } else {
-                        $application = $applications->where('id', $applicationId)->first();
-                        if ($application) {
-                            $foundApplications[] = $application->id;
-                            $statusFromDb = $application->status;
-                            if ($statusFromDb !== $containerStatus) {
-                                $application->update(['status' => $containerStatus]);
-                            }
-                        } else {
-                            //Notify user that this container should not be there.
-                        }
-                    }
-                } else {
-                    $uuid = data_get($labels, 'com.docker.compose.service');
-                    $type = data_get($labels, 'coolify.type');
-
-                    if ($uuid) {
-                        if ($type === 'service') {
-                            $database_id = data_get($labels, 'coolify.service.subId');
-                            if ($database_id) {
-                                $service_db = ServiceDatabase::where('id', $database_id)->first();
-                                if ($service_db) {
-                                    $uuid = $service_db->service->uuid;
-                                    $isPublic = data_get($service_db, 'is_public');
-                                    if ($isPublic) {
-                                        $foundTcpProxy = $containers->filter(function ($value, $key) use ($uuid) {
-                                            if ($this->server->isSwarm()) {
-                                                return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
-                                            } else {
-                                                return data_get($value, 'Name') === "/$uuid-proxy";
-                                            }
-                                        })->first();
-                                        if (!$foundTcpProxy) {
-                                            StartDatabaseProxy::run($service_db);
-                                            // $this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$service_db->service->name}", $this->server));
-                                        }
-                                    }
-                                }
-                            }
-                        } else {
-                            $database = $databases->where('uuid', $uuid)->first();
-                            if ($database) {
-                                $isPublic = data_get($database, 'is_public');
-                                $foundDatabases[] = $database->id;
-                                $statusFromDb = $database->status;
-                                if ($statusFromDb !== $containerStatus) {
-                                    $database->update(['status' => $containerStatus]);
-                                }
-                                if ($isPublic) {
-                                    $foundTcpProxy = $containers->filter(function ($value, $key) use ($uuid) {
-                                        if ($this->server->isSwarm()) {
-                                            return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
-                                        } else {
-                                            return data_get($value, 'Name') === "/$uuid-proxy";
-                                        }
-                                    })->first();
-                                    if (!$foundTcpProxy) {
-                                        StartDatabaseProxy::run($database);
-                                        $this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$database->name}", $this->server));
-                                    }
-                                }
-                            } else {
-                                // Notify user that this container should not be there.
-                            }
-                        }
-                    }
-                    if (data_get($container, 'Name') === '/coolify-db') {
-                        $foundDatabases[] = 0;
-                    }
-                }
-                $serviceLabelId = data_get($labels, 'coolify.serviceId');
-                if ($serviceLabelId) {
-                    $subType = data_get($labels, 'coolify.service.subType');
-                    $subId = data_get($labels, 'coolify.service.subId');
-                    $service = $services->where('id', $serviceLabelId)->first();
-                    if (!$service) {
-                        continue;
-                    }
-                    if ($subType === 'application') {
-                        $service =  $service->applications()->where('id', $subId)->first();
-                    } else {
-                        $service =  $service->databases()->where('id', $subId)->first();
-                    }
-                    if ($service) {
-                        $foundServices[] = "$service->id-$service->name";
-                        $statusFromDb = $service->status;
-                        if ($statusFromDb !== $containerStatus) {
-                            // ray('Updating status: ' . $containerStatus);
-                            $service->update(['status' => $containerStatus]);
-                        }
-                    }
-                }
-            }
-            $exitedServices = collect([]);
-            foreach ($services as $service) {
-                $apps = $service->applications()->get();
-                $dbs = $service->databases()->get();
-                foreach ($apps as $app) {
-                    if (in_array("$app->id-$app->name", $foundServices)) {
-                        continue;
-                    } else {
-                        $exitedServices->push($app);
-                    }
-                }
-                foreach ($dbs as $db) {
-                    if (in_array("$db->id-$db->name", $foundServices)) {
-                        continue;
-                    } else {
-                        $exitedServices->push($db);
-                    }
-                }
-            }
-            $exitedServices = $exitedServices->unique('id');
-            foreach ($exitedServices as $exitedService) {
-                if (str($exitedService->status)->startsWith('exited')) {
-                    continue;
-                }
-                $name = data_get($exitedService, 'name');
-                $fqdn = data_get($exitedService, 'fqdn');
-                $containerName = $name ? "$name, available at $fqdn" : $fqdn;
-                $projectUuid = data_get($service, 'environment.project.uuid');
-                $serviceUuid = data_get($service, 'uuid');
-                $environmentName = data_get($service, 'environment.name');
-
-                if ($projectUuid && $serviceUuid && $environmentName) {
-                    $url =  base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/service/" . $serviceUuid;
-                } else {
-                    $url = null;
-                }
-                $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
-                $exitedService->update(['status' => 'exited']);
-            }
-
-            $notRunningApplications = $applications->pluck('id')->diff($foundApplications);
-            foreach ($notRunningApplications as $applicationId) {
-                $application = $applications->where('id', $applicationId)->first();
-                if (str($application->status)->startsWith('exited')) {
-                    continue;
-                }
-                $application->update(['status' => 'exited']);
-
-                $name = data_get($application, 'name');
-                $fqdn = data_get($application, 'fqdn');
-
-                $containerName = $name ? "$name ($fqdn)" : $fqdn;
-
-                $projectUuid = data_get($application, 'environment.project.uuid');
-                $applicationUuid = data_get($application, 'uuid');
-                $environment = data_get($application, 'environment.name');
-
-                if ($projectUuid && $applicationUuid && $environment) {
-                    $url =  base_url() . '/project/' . $projectUuid . "/" . $environment . "/application/" . $applicationUuid;
-                } else {
-                    $url = null;
-                }
-
-                $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
-            }
-            $notRunningApplicationPreviews = $previews->pluck('id')->diff($foundApplicationPreviews);
-            foreach ($notRunningApplicationPreviews as $previewId) {
-                $preview = $previews->where('id', $previewId)->first();
-                if (str($preview->status)->startsWith('exited')) {
-                    continue;
-                }
-                $preview->update(['status' => 'exited']);
-
-                $name = data_get($preview, 'name');
-                $fqdn = data_get($preview, 'fqdn');
-
-                $containerName = $name ? "$name ($fqdn)" : $fqdn;
-
-                $projectUuid = data_get($preview, 'application.environment.project.uuid');
-                $environmentName = data_get($preview, 'application.environment.name');
-                $applicationUuid = data_get($preview, 'application.uuid');
-
-                if ($projectUuid && $applicationUuid && $environmentName) {
-                    $url =  base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/application/" . $applicationUuid;
-                } else {
-                    $url = null;
-                }
-
-                $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
-            }
-            $notRunningDatabases = $databases->pluck('id')->diff($foundDatabases);
-            foreach ($notRunningDatabases as $database) {
-                $database = $databases->where('id', $database)->first();
-                if (str($database->status)->startsWith('exited')) {
-                    continue;
-                }
-                $database->update(['status' => 'exited']);
-
-                $name = data_get($database, 'name');
-                $fqdn = data_get($database, 'fqdn');
-
-                $containerName = $name;
-
-                $projectUuid = data_get($database, 'environment.project.uuid');
-                $environmentName = data_get($database, 'environment.name');
-                $databaseUuid = data_get($database, 'uuid');
-
-                if ($projectUuid && $databaseUuid && $environmentName) {
-                    $url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/database/" . $databaseUuid;
-                } else {
-                    $url = null;
-                }
-                $this->server->team?->notify(new ContainerStopped($containerName, $this->server, $url));
-            }
-
-            // Check if proxy is running
-            $this->server->proxyType();
-            $foundProxyContainer = $containers->filter(function ($value, $key) {
-                if ($this->server->isSwarm()) {
-                    return data_get($value, 'Spec.Name') === 'coolify-proxy_traefik';
-                } else {
-                    return data_get($value, 'Name') === '/coolify-proxy';
-                }
-            })->first();
-            if (!$foundProxyContainer) {
-                try {
-                    $shouldStart = CheckProxy::run($this->server);
-                    if ($shouldStart) {
-                        StartProxy::run($this->server, false);
-                        $this->server->team?->notify(new ContainerRestarted('coolify-proxy', $this->server));
-                    }
-                } catch (\Throwable $e) {
-                    ray($e);
-                }
-            } else {
-                $this->server->proxy->status = data_get($foundProxyContainer, 'State.Status');
-                $this->server->save();
-                $connectProxyToDockerNetworks = connectProxyToNetworks($this->server);
-                instant_remote_process($connectProxyToDockerNetworks, $this->server, false);
-            }
-        } catch (\Throwable $e) {
-            send_internal_notification("ContainerStatusJob failed on ({$this->server->id}) with: " . $e->getMessage());
-            ray($e->getMessage());
-            return handleError($e);
-        }
+        GetContainersStatus::run($this->server);
     }
 }
diff --git a/app/Jobs/DatabaseBackupJob.php b/app/Jobs/DatabaseBackupJob.php
index befeffed0..ed9694536 100644
--- a/app/Jobs/DatabaseBackupJob.php
+++ b/app/Jobs/DatabaseBackupJob.php
@@ -289,7 +289,7 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
                     if ($this->backup->save_s3) {
                         $this->upload_to_s3();
                     }
-                    $this->team?->notify(new BackupSuccess($this->backup, $this->database));
+                    $this->team?->notify(new BackupSuccess($this->backup, $this->database, $database));
                     $this->backup_log->update([
                         'status' => 'success',
                         'message' => $this->backup_output,
@@ -305,8 +305,7 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
                         ]);
                     }
                     send_internal_notification('DatabaseBackupJob failed with: ' . $e->getMessage());
-                    $this->team?->notify(new BackupFailed($this->backup, $this->database, $this->backup_output));
-                    throw $e;
+                    $this->team?->notify(new BackupFailed($this->backup, $this->database, $this->backup_output, $database));
                 }
             }
         } catch (\Throwable $e) {
@@ -319,10 +318,15 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
     private function backup_standalone_mongodb(string $databaseWithCollections): void
     {
         try {
+            ray($this->database->toArray());
             $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";
+                if (str($this->database->image)->startsWith('mongo:4.0')) {
+                    $commands[] = "docker exec $this->container_name mongodump --uri=$url --gzip --archive > $this->backup_location";
+                } else {
+                    $commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=$url --gzip --archive > $this->backup_location";
+                }
             } else {
                 if (str($databaseWithCollections)->contains(':')) {
                     $databaseName = str($databaseWithCollections)->before(':');
@@ -333,9 +337,17 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
                 }
                 $commands[] = "mkdir -p " . $this->backup_dir;
                 if ($collectionsToExclude->count() === 0) {
-                    $commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=$url --db $databaseName --gzip --archive > $this->backup_location";
+                    if (str($this->database->image)->startsWith('mongo:4.0')) {
+                        $commands[] = "docker exec $this->container_name mongodump --uri=$url --gzip --archive > $this->backup_location";
+                    } else {
+                        $commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=$url --db $databaseName --gzip --archive > $this->backup_location";
+                    }
                 } else {
-                    $commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=$url --db $databaseName --gzip --excludeCollection " . $collectionsToExclude->implode(' --excludeCollection ') . " --archive > $this->backup_location";
+                    if (str($this->database->image)->startsWith('mongo:4.0')) {
+                        $commands[] = "docker exec $this->container_name mongodump --uri=$url --gzip --excludeCollection " . $collectionsToExclude->implode(' --excludeCollection ') . " --archive > $this->backup_location";
+                    } else {
+                        $commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=$url --db $databaseName --gzip --excludeCollection " . $collectionsToExclude->implode(' --excludeCollection ') . " --archive > $this->backup_location";
+                    }
                 }
             }
             $this->backup_output = instant_remote_process($commands, $this->server);
diff --git a/app/Jobs/InstanceAutoUpdateJob.php b/app/Jobs/InstanceAutoUpdateJob.php
index fa5c29421..dc35aa2b1 100644
--- a/app/Jobs/InstanceAutoUpdateJob.php
+++ b/app/Jobs/InstanceAutoUpdateJob.php
@@ -15,7 +15,8 @@ class InstanceAutoUpdateJob implements ShouldQueue, ShouldBeUnique, ShouldBeEncr
 {
     use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 
-    public $timeout = 120;
+    public $timeout = 600;
+    public $tries = 1;
 
     public function __construct(private bool $force = false)
     {
diff --git a/app/Jobs/PullSentinelImageJob.php b/app/Jobs/PullSentinelImageJob.php
new file mode 100644
index 000000000..1c51928f6
--- /dev/null
+++ b/app/Jobs/PullSentinelImageJob.php
@@ -0,0 +1,56 @@
+server->uuid))];
+    }
+
+    public function uniqueId(): string
+    {
+        return $this->server->uuid;
+    }
+    public function __construct(public Server $server)
+    {
+    }
+    public function handle(): void
+    {
+        try {
+            $version = get_latest_sentinel_version();
+            if (!$version) {
+                ray('Failed to get latest Sentinel version');
+                return;
+            }
+            $local_version = instant_remote_process(['docker exec coolify-sentinel sh -c "curl http://127.0.0.1:8888/api/version"'], $this->server, false);
+            if (empty($local_version)) {
+                $local_version = '0.0.0';
+            }
+            if (version_compare($local_version, $version, '<')) {
+                StartSentinel::run($this->server, $version, true);
+                return;
+            }
+            ray('Sentinel image is up to date');
+        } catch (\Throwable $e) {
+            send_internal_notification('PullSentinelImageJob failed with: ' . $e->getMessage());
+            ray($e->getMessage());
+            throw $e;
+        }
+    }
+}
diff --git a/app/Jobs/ScheduledTaskJob.php b/app/Jobs/ScheduledTaskJob.php
index 4a38a005b..a28f85901 100644
--- a/app/Jobs/ScheduledTaskJob.php
+++ b/app/Jobs/ScheduledTaskJob.php
@@ -8,14 +8,13 @@ use App\Models\Server;
 use App\Models\Application;
 use App\Models\Service;
 use App\Models\Team;
+use App\Notifications\ScheduledTask\TaskFailed;
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Foundation\Bus\Dispatchable;
 use Illuminate\Queue\InteractsWithQueue;
 use Illuminate\Queue\Middleware\WithoutOverlapping;
 use Illuminate\Queue\SerializesModels;
-use Illuminate\Support\Collection;
-use Throwable;
 
 class ScheduledTaskJob implements ShouldQueue
 {
@@ -77,8 +76,12 @@ class ScheduledTaskJob implements ShouldQueue
                         $this->containers[] = data_get($application, 'name') . '-' . data_get($this->resource, 'uuid');
                     }
                 });
+                $this->resource->databases()->get()->each(function ($database) {
+                    if (str(data_get($database, 'status'))->contains('running')) {
+                        $this->containers[] = data_get($database, 'name') . '-' . data_get($this->resource, 'uuid');
+                    }
+                });
             }
-
             if (count($this->containers) == 0) {
                 throw new \Exception('ScheduledTaskJob failed: No containers running.');
             }
@@ -89,7 +92,7 @@ class ScheduledTaskJob implements ShouldQueue
 
             foreach ($this->containers as $containerName) {
                 if (count($this->containers) == 1 || str_starts_with($containerName, $this->task->container . '-' . $this->resource->uuid)) {
-                    $cmd = 'sh -c "' . str_replace('"', '\"', $this->task->command)  . '"';
+                    $cmd = "sh -c '" . str_replace("'", "'\''", $this->task->command)   . "'";
                     $exec = "docker exec {$containerName} {$cmd}";
                     $this->task_output = instant_remote_process([$exec], $this->server, true);
                     $this->task_log->update([
@@ -110,6 +113,7 @@ class ScheduledTaskJob implements ShouldQueue
                     'message' => $this->task_output ?? $e->getMessage(),
                 ]);
             }
+            $this->team?->notify(new TaskFailed($this->task, $e->getMessage()));
             // send_internal_notification('ScheduledTaskJob failed with: ' . $e->getMessage());
             throw $e;
         }
diff --git a/app/Jobs/SendMessageToDiscordJob.php b/app/Jobs/SendMessageToDiscordJob.php
index b9255baaa..ddd6bd271 100644
--- a/app/Jobs/SendMessageToDiscordJob.php
+++ b/app/Jobs/SendMessageToDiscordJob.php
@@ -20,11 +20,12 @@ class SendMessageToDiscordJob implements ShouldQueue, ShouldBeEncrypted
      * @var int
      */
     public $tries = 5;
+    public $backoff = 10;
 
     /**
      * The maximum number of unhandled exceptions to allow before failing.
      */
-    public int $maxExceptions = 3;
+    public int $maxExceptions = 5;
 
     public function __construct(
         public string $text,
@@ -40,7 +41,6 @@ class SendMessageToDiscordJob implements ShouldQueue, ShouldBeEncrypted
         $payload = [
             'content' => $this->text,
         ];
-        ray($payload);
         Http::post($this->webhookUrl, $payload);
     }
 }
diff --git a/app/Jobs/SendMessageToTelegramJob.php b/app/Jobs/SendMessageToTelegramJob.php
index 4785da669..4191b02fe 100644
--- a/app/Jobs/SendMessageToTelegramJob.php
+++ b/app/Jobs/SendMessageToTelegramJob.php
@@ -57,7 +57,7 @@ class SendMessageToTelegramJob implements ShouldQueue, ShouldBeEncrypted
             }
         }
         $payload = [
-            'parse_mode' => 'markdown',
+            // 'parse_mode' => 'markdown',
             'reply_markup' => json_encode([
                 'inline_keyboard' => [
                     [...$inlineButtons],
diff --git a/app/Jobs/ServerLimitCheckJob.php b/app/Jobs/ServerLimitCheckJob.php
index 052260895..9d0e5db94 100644
--- a/app/Jobs/ServerLimitCheckJob.php
+++ b/app/Jobs/ServerLimitCheckJob.php
@@ -40,7 +40,7 @@ class ServerLimitCheckJob implements ShouldQueue, ShouldBeEncrypted
         try {
             $servers = $this->team->servers;
             $servers_count = $servers->count();
-            $limit = $this->team->limits['serverLimit'];
+            $limit = data_get($this->team->limits, 'serverLimit', 2);
             $number_of_servers_to_disable = $servers_count - $limit;
             ray('ServerLimitCheckJob', $this->team->uuid, $servers_count, $limit, $number_of_servers_to_disable);
             if ($number_of_servers_to_disable > 0) {
diff --git a/app/Jobs/ServerStatusJob.php b/app/Jobs/ServerStatusJob.php
index 31683d097..449ab85a0 100644
--- a/app/Jobs/ServerStatusJob.php
+++ b/app/Jobs/ServerStatusJob.php
@@ -17,7 +17,7 @@ class ServerStatusJob implements ShouldQueue, ShouldBeEncrypted
     use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 
     public int|string|null $disk_usage = null;
-    public $tries = 4;
+    public $tries = 3;
     public function backoff(): int
     {
         return isDev() ? 1 : 3;
@@ -43,6 +43,10 @@ class ServerStatusJob implements ShouldQueue, ShouldBeEncrypted
         try {
             if ($this->server->isFunctional()) {
                 $this->cleanup(notify: false);
+                $this->removeCoolifyYaml();
+                if (config('coolify.is_sentinel_enabled')) {
+                    $this->server->checkSentinel();
+                }
             }
         } catch (\Throwable $e) {
             send_internal_notification('ServerStatusJob failed with: ' . $e->getMessage());
@@ -50,6 +54,16 @@ class ServerStatusJob implements ShouldQueue, ShouldBeEncrypted
             return handleError($e);
         }
     }
+    private function removeCoolifyYaml()
+    {
+        // This will remote the coolify.yaml file from the server as it is not needed on cloud servers
+        if (isCloud() && $this->server->id !== 0) {
+            $file = $this->server->proxyPath() . "/dynamic/coolify.yaml";
+            return instant_remote_process([
+                "rm -f $file",
+            ], $this->server, false);
+        }
+    }
     public function cleanup(bool $notify = false): void
     {
         $this->disk_usage = $this->server->getDiskUsage();
diff --git a/app/Livewire/Boarding/Index.php b/app/Livewire/Boarding/Index.php
index 2681b69e0..8f4e87090 100644
--- a/app/Livewire/Boarding/Index.php
+++ b/app/Livewire/Boarding/Index.php
@@ -52,6 +52,9 @@ class Index extends Component
 
     public function mount()
     {
+        if (auth()->user()?->isMember() && auth()->user()->currentTeam()->show_boarding === true) {
+            return redirect()->route('dashboard');
+        }
         $this->privateKeyName = generate_random_name();
         $this->remoteServerName = generate_random_name();
         if (isDev()) {
diff --git a/app/Livewire/Notifications/Discord.php b/app/Livewire/Notifications/Discord.php
index 8aad8ccf0..88705437b 100644
--- a/app/Livewire/Notifications/Discord.php
+++ b/app/Livewire/Notifications/Discord.php
@@ -16,6 +16,7 @@ class Discord extends Component
         'team.discord_notifications_deployments' => 'nullable|boolean',
         'team.discord_notifications_status_changes' => 'nullable|boolean',
         'team.discord_notifications_database_backups' => 'nullable|boolean',
+        'team.discord_notifications_scheduled_tasks' => 'nullable|boolean',
     ];
     protected $validationAttributes = [
         'team.discord_webhook_url' => 'Discord Webhook',
diff --git a/app/Livewire/Notifications/Email.php b/app/Livewire/Notifications/Email.php
index 343cbda3e..6ef9b2255 100644
--- a/app/Livewire/Notifications/Email.php
+++ b/app/Livewire/Notifications/Email.php
@@ -28,6 +28,7 @@ class Email extends Component
         'team.smtp_notifications_deployments' => 'nullable|boolean',
         'team.smtp_notifications_status_changes' => 'nullable|boolean',
         'team.smtp_notifications_database_backups' => 'nullable|boolean',
+        'team.smtp_notifications_scheduled_tasks' => 'nullable|boolean',
         'team.use_instance_email_settings' => 'boolean',
         'team.resend_enabled' => 'nullable|boolean',
         'team.resend_api_key' => 'nullable',
diff --git a/app/Livewire/Notifications/Telegram.php b/app/Livewire/Notifications/Telegram.php
index 35b868527..685c9e8eb 100644
--- a/app/Livewire/Notifications/Telegram.php
+++ b/app/Livewire/Notifications/Telegram.php
@@ -18,10 +18,12 @@ class Telegram extends Component
         'team.telegram_notifications_deployments' => 'nullable|boolean',
         'team.telegram_notifications_status_changes' => 'nullable|boolean',
         'team.telegram_notifications_database_backups' => 'nullable|boolean',
+        'team.telegram_notifications_scheduled_tasks' => 'nullable|boolean',
         'team.telegram_notifications_test_message_thread_id' => 'nullable|string',
         'team.telegram_notifications_deployments_message_thread_id' => 'nullable|string',
         'team.telegram_notifications_status_changes_message_thread_id' => 'nullable|string',
         'team.telegram_notifications_database_backups_message_thread_id' => 'nullable|string',
+        'team.telegram_notifications_scheduled_tasks_thread_id' => 'nullable|string',
     ];
     protected $validationAttributes = [
         'team.telegram_token' => 'Token',
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 6926e52cb..718312d2d 100644
--- a/app/Livewire/Project/Application/General.php
+++ b/app/Livewire/Project/Application/General.php
@@ -22,6 +22,7 @@ class General extends Component
     public ?string $git_commit_sha = null;
     public string $build_pack;
     public ?string $ports_exposes = null;
+    public bool $is_container_label_escape_enabled = true;
 
     public $customLabels;
     public bool $labelsChanged = false;
@@ -30,7 +31,7 @@ class General extends Component
     public ?string $initialDockerComposeLocation = null;
     public ?string $initialDockerComposePrLocation = null;
 
-    public $parsedServices = [];
+    public null|Collection $parsedServices;
     public $parsedServiceDomains = [];
 
     protected $listeners = [
@@ -74,6 +75,7 @@ class General extends Component
         'application.post_deployment_command_container' => 'nullable',
         'application.settings.is_static' => 'boolean|required',
         'application.settings.is_build_server_enabled' => 'boolean|required',
+        'application.settings.is_container_label_escape_enabled' => 'boolean|required',
         'application.watch_paths' => 'nullable',
     ];
     protected $validationAttributes = [
@@ -109,12 +111,17 @@ class General extends Component
         'application.docker_compose_custom_build_command' => 'Docker compose custom build command',
         'application.settings.is_static' => 'Is static',
         'application.settings.is_build_server_enabled' => 'Is build server enabled',
+        'application.settings.is_container_label_escape_enabled' => 'Is container label escape enabled',
         'application.watch_paths' => 'Watch paths',
     ];
     public function mount()
     {
         try {
             $this->parsedServices = $this->application->parseCompose();
+            if (is_null($this->parsedServices) || empty($this->parsedServices)) {
+                $this->dispatch('error', "Failed to parse your docker-compose file. Please check the syntax and try again.");
+                return;
+            }
         } catch (\Throwable $e) {
             $this->dispatch('error', $e->getMessage());
         }
@@ -124,6 +131,7 @@ class General extends Component
         }
         $this->parsedServiceDomains = $this->application->docker_compose_domains ? json_decode($this->application->docker_compose_domains, true) : [];
         $this->ports_exposes = $this->application->ports_exposes;
+        $this->is_container_label_escape_enabled = $this->application->settings->is_container_label_escape_enabled;
         $this->customLabels = $this->application->parseContainerLabels();
         if (!$this->customLabels && $this->application->destination->server->proxyType() !== 'NONE') {
             $this->customLabels = str(implode("|", generateLabelsApplication($this->application)))->replace("|", "\n");
@@ -145,7 +153,7 @@ class General extends Component
         $this->application->settings->save();
         $this->dispatch('success', 'Settings saved.');
         $this->application->refresh();
-        if ($this->ports_exposes !== $this->application->ports_exposes) {
+        if ($this->ports_exposes !== $this->application->ports_exposes || $this->is_container_label_escape_enabled !== $this->application->settings->is_container_label_escape_enabled) {
             $this->resetDefaultLabels(false);
         }
     }
@@ -156,6 +164,10 @@ class General extends Component
                 return;
             }
             ['parsedServices' => $this->parsedServices, 'initialDockerComposeLocation' => $this->initialDockerComposeLocation, 'initialDockerComposePrLocation' => $this->initialDockerComposePrLocation] = $this->application->loadComposeFile($isInit);
+            if (is_null($this->parsedServices)) {
+                $this->dispatch('error', "Failed to parse your docker-compose file. Please check the syntax and try again.");
+                return;
+            }
             $compose = $this->application->parseCompose();
             $services = data_get($compose, 'services');
             if ($services) {
@@ -186,6 +198,7 @@ class General extends Component
             $this->dispatch('success', 'Docker compose file loaded.');
             $this->dispatch('compose_loaded');
             $this->dispatch('refresh_storages');
+            $this->dispatch('refreshEnvs');
         } catch (\Throwable $e) {
             $this->application->docker_compose_location = $this->initialDockerComposeLocation;
             $this->application->docker_compose_pr_location = $this->initialDockerComposePrLocation;
@@ -203,6 +216,9 @@ class General extends Component
         $this->application->docker_compose_domains = json_encode($this->parsedServiceDomains);
         $this->application->save();
         $this->dispatch('success', 'Domain generated.');
+        if ($this->application->build_pack === 'dockercompose') {
+            $this->loadComposeFile();
+        }
         return $domain;
     }
     public function updatedApplicationBaseDirectory()
@@ -254,12 +270,14 @@ 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;
-
+        $this->is_container_label_escape_enabled = $this->application->settings->is_container_label_escape_enabled;
         $this->application->custom_labels = base64_encode($this->customLabels);
         $this->application->save();
+        if ($this->application->build_pack === 'dockercompose') {
+            $this->loadComposeFile();
+        }
     }
 
     public function checkFqdns($showToaster = true)
@@ -298,10 +316,13 @@ 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) {
+            if ($this->ports_exposes !== $this->application->ports_exposes || $this->is_container_label_escape_enabled !== $this->application->settings->is_container_label_escape_enabled) {
                 $this->resetDefaultLabels();
             }
             if (data_get($this->application, 'build_pack') === 'dockerimage') {
diff --git a/app/Livewire/Project/Application/Heading.php b/app/Livewire/Project/Application/Heading.php
index 0717a51f0..619be693d 100644
--- a/app/Livewire/Project/Application/Heading.php
+++ b/app/Livewire/Project/Application/Heading.php
@@ -3,8 +3,8 @@
 namespace App\Livewire\Project\Application;
 
 use App\Actions\Application\StopApplication;
+use App\Actions\Docker\GetContainersStatus;
 use App\Events\ApplicationStatusChanged;
-use App\Jobs\ComplexContainerStatusJob;
 use App\Jobs\ContainerStatusJob;
 use App\Jobs\ServerStatusJob;
 use App\Models\Application;
@@ -14,6 +14,8 @@ use Visus\Cuid2\Cuid2;
 class Heading extends Component
 {
     public Application $application;
+    public ?string $lastDeploymentInfo = null;
+    public ?string $lastDeploymentLink = null;
     public array $parameters;
 
     protected string $deploymentUuid;
@@ -28,18 +30,23 @@ class Heading extends Component
     public function mount()
     {
         $this->parameters = get_route_parameters();
+        $lastDeployment = $this->application->get_last_successful_deployment();
+        $this->lastDeploymentInfo = data_get_str($lastDeployment, 'commit')->limit(7) . ' ' . data_get($lastDeployment, 'commit_message');
+        $this->lastDeploymentLink = $this->application->gitCommitLink(data_get($lastDeployment, 'commit'));
     }
 
     public function check_status($showNotification = false)
     {
         if ($this->application->destination->server->isFunctional()) {
-            dispatch(new ContainerStatusJob($this->application->destination->server));
+            GetContainersStatus::dispatch($this->application->destination->server);
+            // dispatch(new ContainerStatusJob($this->application->destination->server));
         } else {
             dispatch(new ServerStatusJob($this->application->destination->server));
         }
 
         if ($showNotification) $this->dispatch('success', "Success", "Application status updated.");
-        $this->dispatch('configurationChanged');
+        // Removed because it caused flickering
+        // $this->dispatch('configurationChanged');
     }
 
     public function force_deploy_without_cache()
diff --git a/app/Livewire/Project/Database/Backup/Execution.php b/app/Livewire/Project/Database/Backup/Execution.php
index 1f790d643..000b6fb2b 100644
--- a/app/Livewire/Project/Database/Backup/Execution.php
+++ b/app/Livewire/Project/Database/Backup/Execution.php
@@ -35,11 +35,6 @@ class Execution extends Component
         $this->executions = $executions;
         $this->s3s = currentTeam()->s3s;
     }
-    public function cleanupFailed()
-    {
-        $this->backup->executions()->where('status', 'failed')->delete();
-        $this->dispatch('refreshBackupExecutions');
-    }
     public function render()
     {
         return view('livewire.project.database.backup.execution');
diff --git a/app/Livewire/Project/Database/BackupEdit.php b/app/Livewire/Project/Database/BackupEdit.php
index f5f476257..d7f7f5503 100644
--- a/app/Livewire/Project/Database/BackupEdit.php
+++ b/app/Livewire/Project/Database/BackupEdit.php
@@ -35,7 +35,7 @@ class BackupEdit extends Component
     public function mount()
     {
         $this->parameters = get_route_parameters();
-        if (is_null($this->backup->s3_storage_id)) {
+        if (is_null(data_get($this->backup, 's3_storage_id'))) {
             $this->backup->s3_storage_id = 'default';
         }
     }
diff --git a/app/Livewire/Project/Database/BackupExecutions.php b/app/Livewire/Project/Database/BackupExecutions.php
index b127a685c..101bb4593 100644
--- a/app/Livewire/Project/Database/BackupExecutions.php
+++ b/app/Livewire/Project/Database/BackupExecutions.php
@@ -2,9 +2,7 @@
 
 namespace App\Livewire\Project\Database;
 
-use Illuminate\Support\Facades\Storage;
 use Livewire\Component;
-use Symfony\Component\HttpFoundation\StreamedResponse;
 
 class BackupExecutions extends Component
 {
@@ -16,11 +14,15 @@ class BackupExecutions extends Component
         $userId = auth()->user()->id;
         return [
             "echo-private:team.{$userId},BackupCreated" => 'refreshBackupExecutions',
-            "refreshBackupExecutions",
             "deleteBackup"
         ];
     }
 
+    public function cleanupFailed()
+    {
+        $this->backup?->executions()->where('status', 'failed')->delete();
+        $this->refreshBackupExecutions();
+    }
     public function deleteBackup($exeuctionId)
     {
         $execution = $this->backup->executions()->where('id', $exeuctionId)->first();
diff --git a/app/Livewire/Project/Database/Heading.php b/app/Livewire/Project/Database/Heading.php
index 960ff2689..d6a0fe087 100644
--- a/app/Livewire/Project/Database/Heading.php
+++ b/app/Livewire/Project/Database/Heading.php
@@ -11,6 +11,7 @@ use App\Actions\Database\StartMysql;
 use App\Actions\Database\StartPostgresql;
 use App\Actions\Database\StartRedis;
 use App\Actions\Database\StopDatabase;
+use App\Actions\Docker\GetContainersStatus;
 use App\Jobs\ContainerStatusJob;
 use Livewire\Component;
 
@@ -44,7 +45,8 @@ class Heading extends Component
 
     public function check_status($showNotification = false)
     {
-        dispatch_sync(new ContainerStatusJob($this->database->destination->server));
+        GetContainersStatus::run($this->database->destination->server);
+        // dispatch_sync(new ContainerStatusJob($this->database->destination->server));
         $this->database->refresh();
         if ($showNotification) $this->dispatch('success', 'Database status updated.');
     }
diff --git a/app/Livewire/Project/Database/Import.php b/app/Livewire/Project/Database/Import.php
index 74e41056a..d435289fa 100644
--- a/app/Livewire/Project/Database/Import.php
+++ b/app/Livewire/Project/Database/Import.php
@@ -27,6 +27,7 @@ class Import extends Component
     public string $postgresqlRestoreCommand = 'pg_restore -U $POSTGRES_USER -d $POSTGRES_DB';
     public string $mysqlRestoreCommand = 'mysql -u $MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE';
     public string $mariadbRestoreCommand = 'mariadb -u $MARIADB_USER -p$MARIADB_PASSWORD $MARIADB_DATABASE';
+    public string $mongodbRestoreCommand = 'mongorestore --authenticationDatabase=admin --username $MONGO_INITDB_ROOT_USERNAME --password $MONGO_INITDB_ROOT_PASSWORD --uri mongodb://localhost:27017 --gzip --archive=';
 
     public function getListeners()
     {
@@ -62,8 +63,7 @@ class Import extends Component
             $this->resource->getMorphClass() == 'App\Models\StandaloneRedis' ||
             $this->resource->getMorphClass() == 'App\Models\StandaloneKeydb' ||
             $this->resource->getMorphClass() == 'App\Models\StandaloneDragonfly' ||
-            $this->resource->getMorphClass() == 'App\Models\StandaloneClickhouse' ||
-            $this->resource->getMorphClass() == 'App\Models\StandaloneMongodb'
+            $this->resource->getMorphClass() == 'App\Models\StandaloneClickhouse'
         ) {
             $this->unsupported = true;
         }
@@ -101,6 +101,10 @@ class Import extends Component
                     $this->importCommands[] = "docker exec {$this->container} sh -c '{$this->postgresqlRestoreCommand} {$tmpPath}'";
                     $this->importCommands[] = "rm {$tmpPath}";
                     break;
+                case 'App\Models\StandaloneMongodb':
+                    $this->importCommands[] = "docker exec {$this->container} sh -c '{$this->mongodbRestoreCommand}{$tmpPath}'";
+                    $this->importCommands[] = "rm {$tmpPath}";
+                    break;
             }
 
             $this->importCommands[] = "docker exec {$this->container} sh -c 'rm {$tmpPath}'";
diff --git a/app/Livewire/Project/New/GithubPrivateRepository.php b/app/Livewire/Project/New/GithubPrivateRepository.php
index 322fd4a4e..58e3fe586 100644
--- a/app/Livewire/Project/New/GithubPrivateRepository.php
+++ b/app/Livewire/Project/New/GithubPrivateRepository.php
@@ -150,7 +150,7 @@ class GithubPrivateRepository extends Component
                 'repository_project_id' => $this->selected_repository_id,
                 'git_repository' => "{$this->selected_repository_owner}/{$this->selected_repository_repo}",
                 'git_branch' => $this->selected_branch_name,
-                'build_pack' => 'nixpacks',
+                'build_pack' => $this->build_pack,
                 'ports_exposes' => $this->port,
                 'publish_directory' => $this->publish_directory,
                 'environment_id' => $environment->id,
@@ -162,6 +162,9 @@ class GithubPrivateRepository extends Component
             $application->settings->is_static = $this->is_static;
             $application->settings->save();
 
+            if ($this->build_pack === 'dockerfile' || $this->build_pack === 'dockerimage') {
+                $application->health_check_enabled = false;
+            }
             $fqdn = generateFqdn($destination->server, $application->uuid);
             $application->fqdn = $fqdn;
 
diff --git a/app/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php b/app/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php
index ad52b9070..691b246fd 100644
--- a/app/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php
+++ b/app/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php
@@ -19,7 +19,7 @@ class GithubPrivateRepositoryDeployKey extends Component
     public $current_step = 'private_keys';
     public $parameters;
     public $query;
-    public $private_keys =[];
+    public $private_keys = [];
     public int $private_key_id;
 
     public int $port = 3000;
@@ -125,7 +125,7 @@ class GithubPrivateRepositoryDeployKey extends Component
                     'name' => generate_random_name(),
                     'git_repository' => $this->git_repository,
                     'git_branch' => $this->branch,
-                    'build_pack' => 'nixpacks',
+                    'build_pack' => $this->build_pack,
                     'ports_exposes' => $this->port,
                     'publish_directory' => $this->publish_directory,
                     'environment_id' => $environment->id,
@@ -138,7 +138,7 @@ class GithubPrivateRepositoryDeployKey extends Component
                     'name' => generate_random_name(),
                     'git_repository' => $this->git_repository,
                     'git_branch' => $this->branch,
-                    'build_pack' => 'nixpacks',
+                    'build_pack' => $this->build_pack,
                     'ports_exposes' => $this->port,
                     'publish_directory' => $this->publish_directory,
                     'environment_id' => $environment->id,
@@ -149,7 +149,9 @@ class GithubPrivateRepositoryDeployKey extends Component
                     'source_type' => $this->git_source->getMorphClass()
                 ];
             }
-
+            if ($this->build_pack === 'dockerfile' || $this->build_pack === 'dockerimage') {
+                $application_init['health_check_enabled'] = false;
+            }
             $application = Application::create($application_init);
             $application->settings->is_static = $this->is_static;
             $application->settings->save();
diff --git a/app/Livewire/Project/New/PublicGitRepository.php b/app/Livewire/Project/New/PublicGitRepository.php
index 8bbb5b052..f4f3008d4 100644
--- a/app/Livewire/Project/New/PublicGitRepository.php
+++ b/app/Livewire/Project/New/PublicGitRepository.php
@@ -94,6 +94,18 @@ class PublicGitRepository extends Component
                 $repository = str($this->repository_url)->after(':')->before('.git');
                 $this->repository_url = 'https://' . str($github_instance) . '/' . $repository;
             }
+            if (
+                (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('git.sr.ht'))
+            ) {
+                $this->repository_url = $this->repository_url . '.git';
+            }
+            if (str($this->repository_url)->contains('github.com')) {
+                $this->repository_url = str($this->repository_url)->before('.git')->value();
+            }
         } catch (\Throwable $e) {
             return handleError($e, $this);
         }
@@ -170,7 +182,6 @@ class PublicGitRepository extends Component
                     'name' => generate_random_name(),
                     'git_repository' => $this->git_repository,
                     'git_branch' => $this->git_branch,
-                    'build_pack' => 'nixpacks',
                     'ports_exposes' => $this->port,
                     'publish_directory' => $this->publish_directory,
                     'environment_id' => $environment->id,
@@ -183,7 +194,6 @@ class PublicGitRepository extends Component
                     'name' => generate_application_name($this->git_repository, $this->git_branch),
                     'git_repository' => $this->git_repository,
                     'git_branch' => $this->git_branch,
-                    'build_pack' => 'nixpacks',
                     'ports_exposes' => $this->port,
                     'publish_directory' => $this->publish_directory,
                     'environment_id' => $environment->id,
@@ -195,7 +205,9 @@ class PublicGitRepository extends Component
                 ];
             }
 
-
+            if ($this->build_pack === 'dockerfile' || $this->build_pack === 'dockerimage') {
+                $application_init['health_check_enabled'] = false;
+            }
             $application = Application::create($application_init);
 
             $application->settings->is_static = $this->is_static;
diff --git a/app/Livewire/Project/New/SimpleDockerfile.php b/app/Livewire/Project/New/SimpleDockerfile.php
index 55b48041a..172403a1a 100644
--- a/app/Livewire/Project/New/SimpleDockerfile.php
+++ b/app/Livewire/Project/New/SimpleDockerfile.php
@@ -70,6 +70,8 @@ CMD ["nginx", "-g", "daemon off;"]
             'fqdn' => $fqdn
         ]);
 
+        $application->parseHealthcheckFromDockerfile(dockerfile: collect(str($this->dockerfile)->trim()->explode("\n")), isInit: true);
+
         return redirect()->route('project.application.configuration', [
             'application_uuid' => $application->uuid,
             'environment_name' => $environment->name,
diff --git a/app/Livewire/Project/Resource/Create.php b/app/Livewire/Project/Resource/Create.php
index 3705d6f93..8ea77950e 100644
--- a/app/Livewire/Project/Resource/Create.php
+++ b/app/Livewire/Project/Resource/Create.php
@@ -12,7 +12,6 @@ class Create extends Component
     public $type;
     public function mount()
     {
-        $services = getServiceTemplates();
         $type = str(request()->query('type'));
         $destination_uuid = request()->query('destination');
         $server_id = request()->query('server_id');
@@ -25,83 +24,87 @@ class Create extends Component
         if (!$environment) {
             return redirect()->route('dashboard');
         }
-        if (in_array($type, DATABASE_TYPES)) {
-            if ($type->value() === "postgresql") {
-                $database = create_standalone_postgresql($environment->id, $destination_uuid);
-            } else if ($type->value() === 'redis') {
-                $database = create_standalone_redis($environment->id, $destination_uuid);
-            } else if ($type->value() === 'mongodb') {
-                $database = create_standalone_mongodb($environment->id, $destination_uuid);
-            } else if ($type->value() === 'mysql') {
-                $database = create_standalone_mysql($environment->id, $destination_uuid);
-            } else if ($type->value() === 'mariadb') {
-                $database = create_standalone_mariadb($environment->id, $destination_uuid);
-            } else if ($type->value() === 'keydb') {
-                $database = create_standalone_keydb($environment->id, $destination_uuid);
-            } else if ($type->value() === 'dragonfly') {
-                $database = create_standalone_dragonfly($environment->id, $destination_uuid);
-            } else if ($type->value() === 'clickhouse') {
-                $database = create_standalone_clickhouse($environment->id, $destination_uuid);
-            }
-            return redirect()->route('project.database.configuration', [
-                'project_uuid' => $project->uuid,
-                'environment_name' => $environment->name,
-                'database_uuid' => $database->uuid,
-            ]);
-        }
-        if ($type->startsWith('one-click-service-') && !is_null((int)$server_id)) {
-            $oneClickServiceName = $type->after('one-click-service-')->value();
-            $oneClickService = data_get($services, "$oneClickServiceName.compose");
-            $oneClickDotEnvs = data_get($services, "$oneClickServiceName.envs", null);
-            if ($oneClickDotEnvs) {
-                $oneClickDotEnvs = str(base64_decode($oneClickDotEnvs))->split('/\r\n|\r|\n/')->filter(function ($value) {
-                    return !empty($value);
-                });
-            }
-            if ($oneClickService) {
-                $destination = StandaloneDocker::whereUuid($destination_uuid)->first();
-                $service_payload = [
-                    'name' => "$oneClickServiceName-" . str()->random(10),
-                    'docker_compose_raw' => base64_decode($oneClickService),
-                    'environment_id' => $environment->id,
-                    'service_type' => $oneClickServiceName,
-                    'server_id' => (int) $server_id,
-                    'destination_id' => $destination->id,
-                    'destination_type' => $destination->getMorphClass(),
-                ];
-                if ($oneClickServiceName === 'cloudflared') {
-                    data_set($service_payload, 'connect_to_docker_network', true);
+        if (isset($type) && isset($destination_uuid) && isset($server_id)) {
+            $services = getServiceTemplates();
+
+            if (in_array($type, DATABASE_TYPES)) {
+                if ($type->value() === "postgresql") {
+                    $database = create_standalone_postgresql($environment->id, $destination_uuid);
+                } else if ($type->value() === 'redis') {
+                    $database = create_standalone_redis($environment->id, $destination_uuid);
+                } else if ($type->value() === 'mongodb') {
+                    $database = create_standalone_mongodb($environment->id, $destination_uuid);
+                } else if ($type->value() === 'mysql') {
+                    $database = create_standalone_mysql($environment->id, $destination_uuid);
+                } else if ($type->value() === 'mariadb') {
+                    $database = create_standalone_mariadb($environment->id, $destination_uuid);
+                } else if ($type->value() === 'keydb') {
+                    $database = create_standalone_keydb($environment->id, $destination_uuid);
+                } else if ($type->value() === 'dragonfly') {
+                    $database = create_standalone_dragonfly($environment->id, $destination_uuid);
+                } else if ($type->value() === 'clickhouse') {
+                    $database = create_standalone_clickhouse($environment->id, $destination_uuid);
                 }
-                $service = Service::create($service_payload);
-                $service->name = "$oneClickServiceName-" . $service->uuid;
-                $service->save();
-                if ($oneClickDotEnvs?->count() > 0) {
-                    $oneClickDotEnvs->each(function ($value) use ($service) {
-                        $key = str()->before($value, '=');
-                        $value = str(str()->after($value, '='));
-                        $generatedValue = $value;
-                        if ($value->contains('SERVICE_')) {
-                            $command = $value->after('SERVICE_')->beforeLast('_');
-                            $generatedValue = generateEnvValue($command->value(), $service);
-                        }
-                        EnvironmentVariable::create([
-                            'key' => $key,
-                            'value' => $generatedValue,
-                            'service_id' => $service->id,
-                            'is_build_time' => false,
-                            'is_preview' => false,
-                        ]);
-                    });
-                }
-                $service->parse(isNew: true);
-                return redirect()->route('project.service.configuration', [
-                    'service_uuid' => $service->uuid,
-                    'environment_name' => $environment->name,
+                return redirect()->route('project.database.configuration', [
                     'project_uuid' => $project->uuid,
+                    'environment_name' => $environment->name,
+                    'database_uuid' => $database->uuid,
                 ]);
             }
+            if ($type->startsWith('one-click-service-') && !is_null((int)$server_id)) {
+                $oneClickServiceName = $type->after('one-click-service-')->value();
+                $oneClickService = data_get($services, "$oneClickServiceName.compose");
+                $oneClickDotEnvs = data_get($services, "$oneClickServiceName.envs", null);
+                if ($oneClickDotEnvs) {
+                    $oneClickDotEnvs = str(base64_decode($oneClickDotEnvs))->split('/\r\n|\r|\n/')->filter(function ($value) {
+                        return !empty($value);
+                    });
+                }
+                if ($oneClickService) {
+                    $destination = StandaloneDocker::whereUuid($destination_uuid)->first();
+                    $service_payload = [
+                        'name' => "$oneClickServiceName-" . str()->random(10),
+                        'docker_compose_raw' => base64_decode($oneClickService),
+                        'environment_id' => $environment->id,
+                        'service_type' => $oneClickServiceName,
+                        'server_id' => (int) $server_id,
+                        'destination_id' => $destination->id,
+                        'destination_type' => $destination->getMorphClass(),
+                    ];
+                    if ($oneClickServiceName === 'cloudflared') {
+                        data_set($service_payload, 'connect_to_docker_network', true);
+                    }
+                    $service = Service::create($service_payload);
+                    $service->name = "$oneClickServiceName-" . $service->uuid;
+                    $service->save();
+                    if ($oneClickDotEnvs?->count() > 0) {
+                        $oneClickDotEnvs->each(function ($value) use ($service) {
+                            $key = str()->before($value, '=');
+                            $value = str(str()->after($value, '='));
+                            $generatedValue = $value;
+                            if ($value->contains('SERVICE_')) {
+                                $command = $value->after('SERVICE_')->beforeLast('_');
+                                $generatedValue = generateEnvValue($command->value(), $service);
+                            }
+                            EnvironmentVariable::create([
+                                'key' => $key,
+                                'value' => $generatedValue,
+                                'service_id' => $service->id,
+                                'is_build_time' => false,
+                                'is_preview' => false,
+                            ]);
+                        });
+                    }
+                    $service->parse(isNew: true);
+                    return redirect()->route('project.service.configuration', [
+                        'service_uuid' => $service->uuid,
+                        'environment_name' => $environment->name,
+                        'project_uuid' => $project->uuid,
+                    ]);
+                }
+            }
+            $this->type = $type->value();
         }
-        $this->type = $type->value();
     }
     public function render()
     {
diff --git a/app/Livewire/Project/Service/Configuration.php b/app/Livewire/Project/Service/Configuration.php
index 2cbda4e02..86c9a8a31 100644
--- a/app/Livewire/Project/Service/Configuration.php
+++ b/app/Livewire/Project/Service/Configuration.php
@@ -2,7 +2,7 @@
 
 namespace App\Livewire\Project\Service;
 
-use App\Jobs\ContainerStatusJob;
+use App\Actions\Docker\GetContainersStatus;
 use App\Models\Service;
 use Livewire\Component;
 
@@ -64,7 +64,8 @@ class Configuration extends Component
     public function check_status()
     {
         try {
-            dispatch_sync(new ContainerStatusJob($this->service->server));
+            GetContainersStatus::run($this->service->server);
+            // dispatch_sync(new ContainerStatusJob($this->service->server));
             $this->dispatch('refresh')->self();
             $this->dispatch('updateStatus');
         } catch (\Exception $e) {
diff --git a/app/Livewire/Project/Service/EditCompose.php b/app/Livewire/Project/Service/EditCompose.php
index 0f9c449f9..d6e867956 100644
--- a/app/Livewire/Project/Service/EditCompose.php
+++ b/app/Livewire/Project/Service/EditCompose.php
@@ -12,6 +12,7 @@ class EditCompose extends Component
     protected $rules = [
         'service.docker_compose_raw' => 'required',
         'service.docker_compose' => 'required',
+        'service.is_container_label_escape_enabled' => 'required',
     ];
     public function mount()
     {
@@ -23,6 +24,14 @@ class EditCompose extends Component
         $this->dispatch('info', "Saving new docker compose...");
         $this->dispatch('saveCompose', $this->service->docker_compose_raw);
     }
+    public function instantSave()
+    {
+        $this->validate([
+            'service.is_container_label_escape_enabled' => 'required',
+        ]);
+        $this->service->save(['is_container_label_escape_enabled' => $this->service->is_container_label_escape_enabled]);
+        $this->dispatch('success', "Service updated successfully");
+    }
     public function render()
     {
         return view('livewire.project.service.edit-compose');
diff --git a/app/Livewire/Project/Shared/Destination.php b/app/Livewire/Project/Shared/Destination.php
index fa19e8c42..2ccae47fd 100644
--- a/app/Livewire/Project/Shared/Destination.php
+++ b/app/Livewire/Project/Shared/Destination.php
@@ -3,6 +3,7 @@
 namespace App\Livewire\Project\Shared;
 
 use App\Actions\Application\StopApplicationOneServer;
+use App\Actions\Docker\GetContainersStatus;
 use App\Events\ApplicationStatusChanged;
 use App\Jobs\ContainerStatusJob;
 use App\Models\Server;
@@ -90,7 +91,8 @@ class Destination extends Component
     }
     public function refreshServers()
     {
-        ContainerStatusJob::dispatchSync($this->resource->destination->server);
+        GetContainersStatus::run($this->resource->destination->server);
+        // ContainerStatusJob::dispatchSync($this->resource->destination->server);
         $this->loadData();
         $this->dispatch('refresh');
         ApplicationStatusChanged::dispatch(data_get($this->resource, 'environment.project.team.id'));
diff --git a/app/Livewire/Project/Shared/EnvironmentVariable/All.php b/app/Livewire/Project/Shared/EnvironmentVariable/All.php
index 6a6d94142..561d20d19 100644
--- a/app/Livewire/Project/Shared/EnvironmentVariable/All.php
+++ b/app/Livewire/Project/Shared/EnvironmentVariable/All.php
@@ -5,11 +5,11 @@ namespace App\Livewire\Project\Shared\EnvironmentVariable;
 use App\Models\EnvironmentVariable;
 use Livewire\Component;
 use Visus\Cuid2\Cuid2;
-use Illuminate\Support\Str;
 
 class All extends Component
 {
     public $resource;
+    public string $resourceClass;
     public bool $showPreview = false;
     public ?string $modalId = null;
     public ?string $variables = null;
@@ -19,17 +19,44 @@ class All extends Component
         'refreshEnvs',
         'saveKey' => 'submit',
     ];
+    protected $rules = [
+        'resource.settings.is_env_sorting_enabled' => 'required|boolean',
+    ];
+
     public function mount()
     {
-        $resourceClass = get_class($this->resource);
+        $this->resourceClass = get_class($this->resource);
         $resourceWithPreviews = ['App\Models\Application'];
         $simpleDockerfile = !is_null(data_get($this->resource, 'dockerfile'));
-        if (Str::of($resourceClass)->contains($resourceWithPreviews) && !$simpleDockerfile) {
+        if (str($this->resourceClass)->contains($resourceWithPreviews) && !$simpleDockerfile) {
             $this->showPreview = true;
         }
         $this->modalId = new Cuid2(7);
+        $this->sortMe();
         $this->getDevView();
     }
+
+    public function sortMe()
+    {
+        if ($this->resourceClass === 'App\Models\Application' && data_get($this->resource, 'build_pack') !== 'dockercompose') {
+            if ($this->resource->settings->is_env_sorting_enabled) {
+                $this->resource->environment_variables = $this->resource->environment_variables->sortBy('key');
+                $this->resource->environment_variables_preview = $this->resource->environment_variables_preview->sortBy('key');
+            } else {
+                $this->resource->environment_variables = $this->resource->environment_variables->sortBy('id');
+                $this->resource->environment_variables_preview = $this->resource->environment_variables_preview->sortBy('id');
+            }
+        }
+        $this->getDevView();
+    }
+    public function instantSave()
+    {
+        if ($this->resourceClass === 'App\Models\Application' && data_get($this->resource, 'build_pack') !== 'dockercompose') {
+            $this->resource->settings->save();
+            $this->dispatch('success', 'Environment variable settings updated.');
+            $this->sortMe();
+        }
+    }
     public function getDevView()
     {
         $this->variables = $this->resource->environment_variables->map(function ($item) {
@@ -40,7 +67,7 @@ class All extends Component
                 return "$item->key=(multiline, edit in normal view)";
             }
             return "$item->key=$item->value";
-        })->sort()->join('
+        })->join('
 ');
         if ($this->showPreview) {
             $this->variablesPreview = $this->resource->environment_variables_preview->map(function ($item) {
@@ -51,13 +78,18 @@ class All extends Component
                     return "$item->key=(multiline, edit in normal view)";
                 }
                 return "$item->key=$item->value";
-            })->sort()->join('
+            })->join('
 ');
         }
     }
     public function switch()
     {
-        $this->view = $this->view === 'normal' ? 'dev' : 'normal';
+        if ($this->view === 'normal') {
+            $this->view = 'dev';
+        } else {
+            $this->view = 'normal';
+        }
+        $this->sortMe();
     }
     public function saveVariables($isPreview)
     {
@@ -66,6 +98,7 @@ class All extends Component
             $this->resource->environment_variables_preview()->whereNotIn('key', array_keys($variables))->delete();
         } else {
             $variables = parseEnvFormatToArray($this->variables);
+            ray($variables, $this->variables);
             $this->resource->environment_variables()->whereNotIn('key', array_keys($variables))->delete();
         }
         foreach ($variables as $key => $variable) {
diff --git a/app/Livewire/Project/Shared/ExecuteContainerCommand.php b/app/Livewire/Project/Shared/ExecuteContainerCommand.php
index 52d628dc1..4fc8bb8c6 100644
--- a/app/Livewire/Project/Shared/ExecuteContainerCommand.php
+++ b/app/Livewire/Project/Shared/ExecuteContainerCommand.php
@@ -122,7 +122,7 @@ class ExecuteContainerCommand extends Component
             if ($server->isForceDisabled()) {
                 throw new \RuntimeException('Server is disabled.');
             }
-            $cmd = 'sh -c "if [ -f ~/.profile ]; then . ~/.profile; fi; ' . str_replace('"', '\"', $this->command)  . '"';
+            $cmd = "sh -c 'if [ -f ~/.profile ]; then . ~/.profile; fi; " . str_replace("'", "'\''", $this->command)  . "'";
             if (!empty($this->workDir)) {
                 $exec = "docker exec -w {$this->workDir} {$container_name} {$cmd}";
             } else {
diff --git a/app/Livewire/Project/Shared/GetLogs.php b/app/Livewire/Project/Shared/GetLogs.php
index 996131f37..e14cd6113 100644
--- a/app/Livewire/Project/Shared/GetLogs.php
+++ b/app/Livewire/Project/Shared/GetLogs.php
@@ -91,15 +91,35 @@ class GetLogs extends Component
         if ($this->container) {
             if ($this->showTimeStamps) {
                 if ($this->server->isSwarm()) {
-                    $sshCommand = generateSshCommand($this->server, "docker service logs -n {$this->numberOfLines} -t {$this->container}");
+                    $command = "docker service logs -n {$this->numberOfLines} -t {$this->container}";
+                    if ($this->server->isNonRoot()) {
+                        $command = parseCommandsByLineForSudo(collect($command), $this->server);
+                        $command = $command[0];
+                    }
+                    $sshCommand = generateSshCommand($this->server, $command);
                 } else {
-                    $sshCommand = generateSshCommand($this->server, "docker logs -n {$this->numberOfLines} -t {$this->container}");
+                    $command = "docker logs -n {$this->numberOfLines} -t {$this->container}";
+                    if ($this->server->isNonRoot()) {
+                        $command = parseCommandsByLineForSudo(collect($command), $this->server);
+                        $command = $command[0];
+                    }
+                    $sshCommand = generateSshCommand($this->server, $command);
                 }
             } else {
                 if ($this->server->isSwarm()) {
-                    $sshCommand = generateSshCommand($this->server, "docker service logs -n {$this->numberOfLines} {$this->container}");
+                    $command = "docker service logs -n {$this->numberOfLines} {$this->container}";
+                    if ($this->server->isNonRoot()) {
+                        $command = parseCommandsByLineForSudo(collect($command), $this->server);
+                        $command = $command[0];
+                    }
+                    $sshCommand = generateSshCommand($this->server, $command);
                 } else {
-                    $sshCommand = generateSshCommand($this->server, "docker logs -n {$this->numberOfLines} {$this->container}");
+                    $command = "docker logs -n {$this->numberOfLines} {$this->container}";
+                    if ($this->server->isNonRoot()) {
+                        $command = parseCommandsByLineForSudo(collect($command), $this->server);
+                        $command = $command[0];
+                    }
+                    $sshCommand = generateSshCommand($this->server, $command);
                 }
             }
             if ($refresh) {
diff --git a/app/Livewire/Project/Shared/HealthChecks.php b/app/Livewire/Project/Shared/HealthChecks.php
index 3bf507cab..56f5a2759 100644
--- a/app/Livewire/Project/Shared/HealthChecks.php
+++ b/app/Livewire/Project/Shared/HealthChecks.php
@@ -17,18 +17,17 @@ class HealthChecks extends Component
         'resource.health_check_return_code' => 'integer',
         'resource.health_check_scheme' => 'string',
         'resource.health_check_response_text' => 'nullable|string',
-        'resource.health_check_interval' => 'integer',
-        'resource.health_check_timeout' => 'integer',
-        'resource.health_check_retries' => 'integer',
+        'resource.health_check_interval' => 'integer|min:1',
+        'resource.health_check_timeout' => 'integer|min:1',
+        'resource.health_check_retries' => 'integer|min:1',
         'resource.health_check_start_period' => 'integer',
+        'resource.custom_healthcheck_found' => 'boolean',
 
     ];
     public function instantSave()
     {
         $this->resource->save();
         $this->dispatch('success', 'Health check updated.');
-
-
     }
     public function submit()
     {
diff --git a/app/Livewire/Project/Shared/Logs.php b/app/Livewire/Project/Shared/Logs.php
index 68e4e193e..f1d70bf28 100644
--- a/app/Livewire/Project/Shared/Logs.php
+++ b/app/Livewire/Project/Shared/Logs.php
@@ -27,7 +27,7 @@ class Logs extends Component
     public $query;
     public $status;
     public $serviceSubType;
-
+    public $cpu;
     public function loadContainers($server_id)
     {
         try {
@@ -49,6 +49,14 @@ class Logs extends Component
             return handleError($e, $this);
         }
     }
+    public function loadMetrics()
+    {
+        return;
+        $server = data_get($this->resource, 'destination.server');
+        if ($server->isFunctional()) {
+            $this->cpu = $server->getMetrics();
+        }
+    }
     public function mount()
     {
         try {
@@ -95,6 +103,7 @@ class Logs extends Component
                 }
             }
             $this->containers = $this->containers->sort();
+            $this->loadMetrics();
         } catch (\Exception $e) {
             return handleError($e, $this);
         }
diff --git a/app/Livewire/Project/Shared/ScheduledTask/Add.php b/app/Livewire/Project/Shared/ScheduledTask/Add.php
index 3a7a3fa23..c415ff3e4 100644
--- a/app/Livewire/Project/Shared/ScheduledTask/Add.php
+++ b/app/Livewire/Project/Shared/ScheduledTask/Add.php
@@ -2,11 +2,14 @@
 
 namespace App\Livewire\Project\Shared\ScheduledTask;
 
+use Illuminate\Support\Collection;
 use Livewire\Component;
 
 class Add extends Component
 {
     public $parameters;
+    public string $type;
+    public Collection $containerNames;
     public string $name;
     public string $command;
     public string $frequency;
@@ -29,6 +32,9 @@ class Add extends Component
     public function mount()
     {
         $this->parameters = get_route_parameters();
+        if ($this->containerNames->count() > 0) {
+            $this->container = $this->containerNames->first();
+        }
     }
 
     public function submit()
@@ -40,6 +46,11 @@ class Add extends Component
                 $this->dispatch('error', 'Invalid Cron / Human expression.');
                 return;
             }
+            if (empty($this->container) || $this->container == 'null') {
+                if ($this->type == 'service') {
+                    $this->container = $this->subServiceName;
+                }
+            }
             $this->dispatch('saveScheduledTask', [
                 'name' => $this->name,
                 'command' => $this->command,
diff --git a/app/Livewire/Project/Shared/ScheduledTask/All.php b/app/Livewire/Project/Shared/ScheduledTask/All.php
index 975d695fa..e5ea66d13 100644
--- a/app/Livewire/Project/Shared/ScheduledTask/All.php
+++ b/app/Livewire/Project/Shared/ScheduledTask/All.php
@@ -3,14 +3,13 @@
 namespace App\Livewire\Project\Shared\ScheduledTask;
 
 use App\Models\ScheduledTask;
+use Illuminate\Support\Collection;
 use Livewire\Component;
-use Visus\Cuid2\Cuid2;
-use Illuminate\Support\Str;
 
 class All extends Component
 {
     public $resource;
-    public string|null $modalId = null;
+    public Collection $containerNames;
     public ?string $variables = null;
     public array $parameters;
     protected $listeners = ['refreshTasks', 'saveScheduledTask' => 'submit'];
@@ -18,7 +17,18 @@ class All extends Component
     public function mount()
     {
         $this->parameters = get_route_parameters();
-        $this->modalId = new Cuid2(7);
+        if ($this->resource->type() == 'service') {
+            $this->containerNames = $this->resource->applications()->pluck('name');
+            $this->containerNames = $this->containerNames->merge($this->resource->databases()->pluck('name'));
+        } elseif ($this->resource->type() == 'application') {
+            if ($this->resource->build_pack === 'dockercompose') {
+                $parsed = $this->resource->parseCompose();
+                $containers = collect(data_get($parsed,'services'))->keys();
+                $this->containerNames = $containers;
+            } else {
+                $this->containerNames = collect([]);
+            }
+        }
     }
     public function refreshTasks()
     {
diff --git a/app/Livewire/Project/Shared/ScheduledTask/Show.php b/app/Livewire/Project/Shared/ScheduledTask/Show.php
index 87b752509..7490c7055 100644
--- a/app/Livewire/Project/Shared/ScheduledTask/Show.php
+++ b/app/Livewire/Project/Shared/ScheduledTask/Show.php
@@ -17,6 +17,7 @@ class Show extends Component
     public string $type;
 
     protected $rules = [
+        'task.enabled' => 'required|boolean',
         'task.name' => 'required|string',
         'task.command' => 'required|string',
         'task.frequency' => 'required|string',
@@ -45,9 +46,18 @@ class Show extends Component
         $this->task = ModelsScheduledTask::where('uuid', request()->route('task_uuid'))->first();
     }
 
+    public function instantSave()
+    {
+        $this->validateOnly('task.enabled');
+        $this->task->save(['enabled' => $this->task->enabled]);
+        $this->dispatch('success', 'Scheduled task updated.');
+        $this->dispatch('refreshTasks');
+    }
     public function submit()
     {
         $this->validate();
+        $this->task->name = str($this->task->name)->trim()->value();
+        $this->task->container = str($this->task->container)->trim()->value();
         $this->task->save();
         $this->dispatch('success', 'Scheduled task updated.');
         $this->dispatch('refreshTasks');
@@ -60,11 +70,9 @@ class Show extends Component
 
             if ($this->type == 'application') {
                 return redirect()->route('project.application.configuration', $this->parameters);
-            }
-            else {
+            } else {
                 return redirect()->route('project.service.configuration', $this->parameters);
             }
-
         } catch (\Exception $e) {
             return handleError($e);
         }
diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php
index 14a2809c7..c1dcd34ce 100644
--- a/app/Livewire/Server/Form.php
+++ b/app/Livewire/Server/Form.php
@@ -82,6 +82,7 @@ class Form extends Component
             $this->server->settings->is_reachable = true;
             $this->server->settings->is_usable = true;
             $this->server->settings->save();
+            $this->dispatch('proxyStatusUpdated');
         } else {
             $this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.
Check this documentation for further help. 
Error: ' . $error);
             return;
diff --git a/app/Livewire/Server/Proxy/Status.php b/app/Livewire/Server/Proxy/Status.php
index bd0ffe431..fbc16fde4 100644
--- a/app/Livewire/Server/Proxy/Status.php
+++ b/app/Livewire/Server/Proxy/Status.php
@@ -2,6 +2,7 @@
 
 namespace App\Livewire\Server\Proxy;
 
+use App\Actions\Docker\GetContainersStatus;
 use App\Actions\Proxy\CheckProxy;
 use App\Jobs\ContainerStatusJob;
 use App\Models\Server;
@@ -49,7 +50,8 @@ class Status extends Component
     public function getProxyStatus()
     {
         try {
-            dispatch_sync(new ContainerStatusJob($this->server));
+            GetContainersStatus::run($this->server);
+            // dispatch_sync(new ContainerStatusJob($this->server));
             $this->dispatch('proxyStatusUpdated');
         } catch (\Throwable $e) {
             return handleError($e, $this);
diff --git a/app/Livewire/Settings/Configuration.php b/app/Livewire/Settings/Configuration.php
index 5281a1e01..54dbe1bdb 100644
--- a/app/Livewire/Settings/Configuration.php
+++ b/app/Livewire/Settings/Configuration.php
@@ -13,7 +13,7 @@ class Configuration extends Component
     public bool $is_auto_update_enabled;
     public bool $is_registration_enabled;
     public bool $is_dns_validation_enabled;
-    public bool $next_channel;
+    // public bool $next_channel;
     protected string $dynamic_config_path = '/data/coolify/proxy/dynamic';
     protected Server $server;
 
@@ -37,7 +37,7 @@ class Configuration extends Component
         $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->next_channel = $this->settings->next_channel;
+        // $this->next_channel = $this->settings->next_channel;
         $this->is_dns_validation_enabled = $this->settings->is_dns_validation_enabled;
     }
 
@@ -47,12 +47,12 @@ class Configuration extends Component
         $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;
-        if ($this->next_channel) {
-            $this->settings->next_channel = false;
-            $this->next_channel = false;
-        } else {
-            $this->settings->next_channel = $this->next_channel;
-        }
+        // if ($this->next_channel) {
+        //     $this->settings->next_channel = false;
+        //     $this->next_channel = false;
+        // } else {
+        //     $this->settings->next_channel = $this->next_channel;
+        // }
         $this->settings->save();
         $this->dispatch('success', 'Settings updated!');
     }
diff --git a/app/Livewire/Storage/Create.php b/app/Livewire/Storage/Create.php
index d1af807d5..1b2510f5d 100644
--- a/app/Livewire/Storage/Create.php
+++ b/app/Livewire/Storage/Create.php
@@ -16,13 +16,13 @@ class Create extends Component
     public string $endpoint;
     public S3Storage $storage;
     protected $rules = [
-        'name' => 'nullable|min:3|max:255',
+        'name' => 'required|min:3|max:255',
         'description' => 'nullable|min:3|max:255',
         'region' => 'required|max:255',
         'key' => 'required|max:255',
         'secret' => 'required|max:255',
         'bucket' => 'required|max:255',
-        'endpoint' => 'nullable|url|max:255',
+        'endpoint' => 'required|url|max:255',
     ];
     protected $validationAttributes = [
         'name' => 'Name',
diff --git a/app/Livewire/Tags/Deployments.php b/app/Livewire/Tags/Deployments.php
index 5c43edfb1..07034ed5d 100644
--- a/app/Livewire/Tags/Deployments.php
+++ b/app/Livewire/Tags/Deployments.php
@@ -26,6 +26,7 @@ class Deployments extends Component
                 "server_id",
                 "status"
             ])->sortBy('id')->groupBy('server_name')->toArray();
+            $this->dispatch('deployments', $this->deployments_per_tag_per_server);
         } catch (\Exception $e) {
             return handleError($e, $this);
         }
diff --git a/app/Livewire/Tags/Index.php b/app/Livewire/Tags/Index.php
index d04bb53f9..c2b2a5928 100644
--- a/app/Livewire/Tags/Index.php
+++ b/app/Livewire/Tags/Index.php
@@ -20,6 +20,12 @@ class Index extends Component
     public $webhook = null;
     public $deployments_per_tag_per_server = [];
 
+    protected $listeners = ['deployments' => 'update_deployments'];
+
+    public function update_deployments($deployments)
+    {
+        $this->deployments_per_tag_per_server = $deployments;
+    }
     public function tag_updated()
     {
         if ($this->tag == "") {
@@ -39,14 +45,13 @@ class Index extends Component
     public function redeploy_all()
     {
         try {
-            $message = collect([]);
-            $this->applications->each(function ($resource) use ($message) {
+            $this->applications->each(function ($resource){
                 $deploy = new Deploy();
-                $message->push($deploy->deploy_resource($resource));
+                $deploy->deploy_resource($resource);
             });
-            $this->services->each(function ($resource) use ($message) {
+            $this->services->each(function ($resource) {
                 $deploy = new Deploy();
-                $message->push($deploy->deploy_resource($resource));
+                $deploy->deploy_resource($resource);
             });
             $this->dispatch('success', 'Mass deployment started.');
         } catch (\Exception $e) {
diff --git a/app/Livewire/Team/AdminView.php b/app/Livewire/Team/AdminView.php
new file mode 100644
index 000000000..12546ff1b
--- /dev/null
+++ b/app/Livewire/Team/AdminView.php
@@ -0,0 +1,117 @@
+route('dashboard');
+        }
+        $this->getUsers();
+    }
+    public function submitSearch()
+    {
+        if ($this->search !== "") {
+            $this->users = User::where(function ($query) {
+                $query->where('name', 'like', "%{$this->search}%")
+                    ->orWhere('email', 'like', "%{$this->search}%");
+            })->get()->filter(function ($user) {
+                return $user->id !== auth()->id();
+            });
+        } else {
+            $this->getUsers();
+        }
+    }
+    public function getUsers()
+    {
+        $this->users = User::where('id', '!=', auth()->id())->get();
+        // $this->users = User::all();
+    }
+    private function finalizeDeletion(User $user, Team $team)
+    {
+        $servers = $team->servers;
+        foreach ($servers as $server) {
+            $resources = $server->definedResources();
+            foreach ($resources as $resource) {
+                ray("Deleting resource: " . $resource->name);
+                $resource->forceDelete();
+            }
+            ray("Deleting server: " . $server->name);
+            $server->forceDelete();
+        }
+
+        $projects = $team->projects;
+        foreach ($projects as $project) {
+            ray("Deleting project: " . $project->name);
+            $project->forceDelete();
+        }
+        $team->members()->detach($user->id);
+        ray('Deleting team: ' . $team->name);
+        $team->delete();
+    }
+    public function delete($id)
+    {
+        $user = User::find($id);
+        $teams = $user->teams;
+        foreach ($teams as $team) {
+            ray($team->name);
+            $user_alone_in_team = $team->members->count() === 1;
+            if ($team->id === 0) {
+                if ($user_alone_in_team) {
+                    ray('user is alone in the root team, do nothing');
+                    return $this->dispatch('error', 'User is alone in the root team, cannot delete');
+                }
+            }
+            if ($user_alone_in_team) {
+                ray('user is alone in the team');
+                $this->finalizeDeletion($user, $team);
+                continue;
+            }
+            ray('user is not alone in the team');
+            if ($user->isOwner()) {
+                $found_other_owner_or_admin = $team->members->filter(function ($member) {
+                    return $member->pivot->role === 'owner' || $member->pivot->role === 'admin';
+                })->where('id', '!=', $user->id)->first();
+
+                if ($found_other_owner_or_admin) {
+                    ray('found other owner or admin');
+                    $team->members()->detach($user->id);
+                    continue;
+                } else {
+                    $found_other_member_who_is_not_owner = $team->members->filter(function ($member) {
+                        return $member->pivot->role === 'member';
+                    })->first();
+                    if ($found_other_member_who_is_not_owner) {
+                        ray('found other member who is not owner');
+                        $found_other_member_who_is_not_owner->pivot->role = 'owner';
+                        $found_other_member_who_is_not_owner->pivot->save();
+                        $team->members()->detach($user->id);
+                    } else {
+                        // This should never happen as if the user is the only member in the team, the team should be deleted already.
+                        ray('found no other member who is not owner');
+                        $this->finalizeDeletion($user, $team);
+                    }
+                    continue;
+                }
+            } else {
+                ray('user is not owner');
+                $team->members()->detach($user->id);
+            }
+        }
+        ray("Deleting user: " . $user->name);
+        $user->delete();
+        $this->getUsers();
+    }
+    public function render()
+    {
+        return view('livewire.team.admin-view');
+    }
+}
diff --git a/app/Livewire/Upgrade.php b/app/Livewire/Upgrade.php
index 96ee76325..5ef966f43 100644
--- a/app/Livewire/Upgrade.php
+++ b/app/Livewire/Upgrade.php
@@ -3,7 +3,7 @@
 namespace App\Livewire;
 
 use App\Actions\Server\UpdateCoolify;
-use App\Models\InstanceSettings;
+
 use Livewire\Component;
 use DanHarrin\LivewireRateLimiting\WithRateLimiting;
 
@@ -11,6 +11,7 @@ class Upgrade extends Component
 {
     use WithRateLimiting;
     public bool $showProgress = false;
+    public bool $updateInProgress = false;
     public bool $isUpgradeAvailable = false;
     public string $latestVersion = '';
 
@@ -22,23 +23,17 @@ class Upgrade extends Component
         if (isDev()) {
             $this->isUpgradeAvailable = true;
         }
-        $settings = InstanceSettings::get();
-        if ($settings->next_channel) {
-            $this->isUpgradeAvailable = true;
-            $this->latestVersion = 'next';
-        }
     }
 
     public function upgrade()
     {
         try {
-            if ($this->showProgress) {
+            if ($this->updateInProgress) {
                 return;
             }
-            $this->rateLimit(1, 30);
-            $this->showProgress = true;
+            $this->rateLimit(1, 60);
+            $this->updateInProgress = true;
             UpdateCoolify::run(force: true, async: true);
-            $this->dispatch('success', "Updating Coolify to {$this->latestVersion} version...");
         } catch (\Throwable $e) {
             return handleError($e, $this);
         }
diff --git a/app/Models/Application.php b/app/Models/Application.php
index f28d389f4..0f3425dd6 100644
--- a/app/Models/Application.php
+++ b/app/Models/Application.php
@@ -113,6 +113,18 @@ class Application extends BaseModel
         }
         return null;
     }
+    public function failedTaskLink($task_uuid)
+    {
+        if (data_get($this, 'environment.project.uuid')) {
+            return route('project.application.scheduled-tasks', [
+                'project_uuid' => data_get($this, 'environment.project.uuid'),
+                'environment_name' => data_get($this, 'environment.name'),
+                'application_uuid' => data_get($this, 'uuid'),
+                'task_uuid' => $task_uuid
+            ]);
+        }
+        return null;
+    }
     public function settings()
     {
         return $this->hasOne(ApplicationSetting::class);
@@ -146,9 +158,13 @@ class Application extends BaseModel
                 if (!is_null($this->source?->html_url) && !is_null($this->git_repository) && !is_null($this->git_branch)) {
                     return "{$this->source->html_url}/{$this->git_repository}/tree/{$this->git_branch}";
                 }
+                // Convert the SSH URL to HTTPS URL
+                if (strpos($this->git_repository, 'git@') === 0) {
+                    $git_repository = str_replace(['git@', ':', '.git'], ['', '/', ''], $this->git_repository);
+                    return "https://{$git_repository}/tree/{$this->git_branch}";
+                }
                 return $this->git_repository;
             }
-
         );
     }
 
@@ -159,6 +175,11 @@ class Application extends BaseModel
                 if (!is_null($this->source?->html_url) && !is_null($this->git_repository) && !is_null($this->git_branch)) {
                     return "{$this->source->html_url}/{$this->git_repository}/settings/hooks";
                 }
+                // Convert the SSH URL to HTTPS URL
+                if (strpos($this->git_repository, 'git@') === 0) {
+                    $git_repository = str_replace(['git@', ':', '.git'], ['', '/', ''], $this->git_repository);
+                    return "https://{$git_repository}/settings/hooks";
+                }
                 return $this->git_repository;
             }
         );
@@ -171,10 +192,29 @@ class Application extends BaseModel
                 if (!is_null($this->source?->html_url) && !is_null($this->git_repository) && !is_null($this->git_branch)) {
                     return "{$this->source->html_url}/{$this->git_repository}/commits/{$this->git_branch}";
                 }
+                // Convert the SSH URL to HTTPS URL
+                if (strpos($this->git_repository, 'git@') === 0) {
+                    $git_repository = str_replace(['git@', ':', '.git'], ['', '/', ''], $this->git_repository);
+                    return "https://{$git_repository}/commits/{$this->git_branch}";
+                }
                 return $this->git_repository;
             }
         );
     }
+    public function gitCommitLink($link): string
+    {
+        if (!is_null($this->source?->html_url) && !is_null($this->git_repository) && !is_null($this->git_branch)) {
+            if (str($this->source->html_url)->contains('bitbucket')) {
+                return "{$this->source->html_url}/{$this->git_repository}/commits/{$link}";
+            }
+            return "{$this->source->html_url}/{$this->git_repository}/commit/{$link}";
+        }
+        if (strpos($this->git_repository, 'git@') === 0) {
+            $git_repository = str_replace(['git@', ':', '.git'], ['', '/', ''], $this->git_repository);
+            return "https://{$git_repository}/commit/{$link}";
+        }
+        return $this->git_repository;
+    }
     public function dockerfileLocation(): Attribute
     {
         return Attribute::make(
@@ -429,6 +469,10 @@ class Application extends BaseModel
         }
         return false;
     }
+    public function get_last_successful_deployment()
+    {
+        return ApplicationDeploymentQueue::where('application_id', $this->id)->where('status', 'finished')->where('pull_request_id', 0)->orderBy('created_at', 'desc')->first();
+    }
     public function get_last_days_deployments()
     {
         return ApplicationDeploymentQueue::where('application_id', $this->id)->where('created_at', '>=', now()->subDays(7))->orderBy('created_at', 'desc')->get();
@@ -847,7 +891,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
Check if you used the right extension (.yaml or .yml) in the compose file name.");
         } else {
             $this->docker_compose_raw = $composeFileContent;
             $this->save();
@@ -963,4 +1007,52 @@ class Application extends BaseModel
     {
         getFilesystemVolumesFromServer($this, $isInit);
     }
+
+    public function parseHealthcheckFromDockerfile($dockerfile, bool $isInit = false)
+    {
+        if (str($dockerfile)->contains('HEALTHCHECK') && ($this->isHealthcheckDisabled() || $isInit)) {
+            $healthcheckCommand = null;
+            $lines = $dockerfile->toArray();
+            foreach ($lines as $line) {
+                $trimmedLine = trim($line);
+                if (str_starts_with($trimmedLine, 'HEALTHCHECK')) {
+                    $healthcheckCommand .= trim($trimmedLine, '\\ ');
+                    continue;
+                }
+                if (isset($healthcheckCommand) && str_contains($trimmedLine, '\\')) {
+                    $healthcheckCommand .= ' ' . trim($trimmedLine, '\\ ');
+                }
+                if (isset($healthcheckCommand) && !str_contains($trimmedLine, '\\') && !empty($healthcheckCommand)) {
+                    $healthcheckCommand .= ' ' . $trimmedLine;
+                    break;
+                }
+            }
+            if (str($healthcheckCommand)->isNotEmpty()) {
+                $interval = str($healthcheckCommand)->match('/--interval=(\d+)/');
+                $timeout = str($healthcheckCommand)->match('/--timeout=(\d+)/');
+                $start_period = str($healthcheckCommand)->match('/--start-period=(\d+)/');
+                $start_interval = str($healthcheckCommand)->match('/--start-interval=(\d+)/');
+                $retries = str($healthcheckCommand)->match('/--retries=(\d+)/');
+                if ($interval->isNotEmpty()) {
+                    $this->health_check_interval = $interval->toInteger();
+                }
+                if ($timeout->isNotEmpty()) {
+                    $this->health_check_timeout = $timeout->toInteger();
+                }
+                if ($start_period->isNotEmpty()) {
+                    $this->health_check_start_period = $start_period->toInteger();
+                }
+                // if ($start_interval) {
+                //     $this->health_check_start_interval = $start_interval->value();
+                // }
+                if ($retries->isNotEmpty()) {
+                    $this->health_check_retries = $retries->toInteger();
+                }
+                if ($interval || $timeout || $start_period || $start_interval || $retries) {
+                    $this->custom_healthcheck_found = true;
+                    $this->save();
+                }
+            }
+        }
+    }
 }
diff --git a/app/Models/ApplicationDeploymentQueue.php b/app/Models/ApplicationDeploymentQueue.php
index 7f3f36d0a..c55f89e21 100644
--- a/app/Models/ApplicationDeploymentQueue.php
+++ b/app/Models/ApplicationDeploymentQueue.php
@@ -9,7 +9,8 @@ class ApplicationDeploymentQueue extends Model
 {
     protected $guarded = [];
 
-    public function setStatus(string $status) {
+    public function setStatus(string $status)
+    {
         $this->update([
             'status' => $status,
         ]);
@@ -21,7 +22,13 @@ class ApplicationDeploymentQueue extends Model
         }
         return collect(json_decode($this->logs))->where('name', $name)->first()?->output ?? null;
     }
-
+    public function commitMessage()
+    {
+        if (empty($this->commit_message) || is_null($this->commit_message)) {
+            return null;
+        }
+        return str($this->commit_message)->trim()->limit(50)->value();
+    }
     public function addLogEntry(string $message, string $type = 'stdout', bool $hidden = false)
     {
         if ($type === 'error') {
diff --git a/app/Models/Environment.php b/app/Models/Environment.php
index 7ed9e38e5..a1f3e4190 100644
--- a/app/Models/Environment.php
+++ b/app/Models/Environment.php
@@ -8,6 +8,18 @@ use Illuminate\Database\Eloquent\Model;
 class Environment extends Model
 {
     protected $guarded = [];
+
+    protected static function booted()
+    {
+        static::deleting(function ($environment) {
+            $shared_variables = $environment->environment_variables();
+            foreach ($shared_variables as $shared_variable) {
+                ray('Deleting environment shared variable: ' . $shared_variable->name);
+                $shared_variable->delete();
+            }
+
+        });
+    }
     public function isEmpty()
     {
         return $this->applications()->count() == 0 &&
diff --git a/app/Models/Project.php b/app/Models/Project.php
index 2621d3da1..c2be8cc32 100644
--- a/app/Models/Project.php
+++ b/app/Models/Project.php
@@ -25,6 +25,11 @@ class Project extends BaseModel
         static::deleting(function ($project) {
             $project->environments()->delete();
             $project->settings()->delete();
+            $shared_variables = $project->environment_variables();
+            foreach ($shared_variables as $shared_variable) {
+                ray('Deleting project shared variable: ' . $shared_variable->name);
+                $shared_variable->delete();
+            }
         });
     }
     public function environment_variables()
@@ -55,6 +60,7 @@ class Project extends BaseModel
         return $this->hasManyThrough(Application::class, Environment::class);
     }
 
+
     public function postgresqls()
     {
         return $this->hasManyThrough(StandalonePostgresql::class, Environment::class);
@@ -91,4 +97,7 @@ class Project extends BaseModel
     {
         return $this->applications()->count() + $this->postgresqls()->count() + $this->redis()->count() + $this->mongodbs()->count() + $this->mysqls()->count() + $this->mariadbs()->count() + $this->keydbs()->count() + $this->dragonflies()->count()  + $this->services()->count() + $this->clickhouses()->count();
     }
+    public function databases() {
+        return $this->postgresqls()->get()->merge($this->redis()->get())->merge($this->mongodbs()->get())->merge($this->mysqls()->get())->merge($this->mariadbs()->get())->merge($this->keydbs()->get())->merge($this->dragonflies()->get())->merge($this->clickhouses()->get());
+    }
 }
diff --git a/app/Models/Server.php b/app/Models/Server.php
index bda044320..2f4c29080 100644
--- a/app/Models/Server.php
+++ b/app/Models/Server.php
@@ -3,11 +3,14 @@
 namespace App\Models;
 
 use App\Actions\Server\InstallDocker;
+use App\Actions\Server\StartSentinel;
 use App\Enums\ProxyTypes;
+use App\Jobs\PullSentinelImageJob;
 use App\Notifications\Server\Revived;
 use App\Notifications\Server\Unreachable;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Casts\Attribute;
+use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Storage;
 use Spatie\SchemalessAttributes\Casts\SchemalessAttributes;
@@ -239,7 +242,7 @@ respond 404
         $dynamic_config_path = $this->proxyPath() . "/dynamic";
         if ($this->proxyType() === 'TRAEFIK_V2') {
             $file = "$dynamic_config_path/coolify.yaml";
-            if (empty($settings->fqdn)) {
+            if (empty($settings->fqdn) || (isCloud() && $this->id !== 0)) {
                 instant_remote_process([
                     "rm -f $file",
                 ], $this);
@@ -358,7 +361,7 @@ respond 404
             }
         } else if ($this->proxyType() === 'CADDY') {
             $file = "$dynamic_config_path/coolify.caddy";
-            if (empty($settings->fqdn)) {
+            if (empty($settings->fqdn) || (isCloud() && $this->id !== 0)) {
                 instant_remote_process([
                     "rm -f $file",
                 ], $this);
@@ -462,6 +465,36 @@ $schema://$host {
         Storage::disk('ssh-keys')->delete($sshKeyFileLocation);
         Storage::disk('ssh-mux')->delete($this->muxFilename());
     }
+    public function checkSentinel()
+    {
+        ray("Checking sentinel on server: {$this->name}");
+        if ($this->is_metrics_enabled) {
+            $sentinel_found = instant_remote_process(["docker inspect coolify-sentinel"], $this, false);
+            $sentinel_found = json_decode($sentinel_found, true);
+            $status = data_get($sentinel_found, '0.State.Status', 'exited');
+            if ($status !== 'running') {
+                ray('Sentinel is not running, starting it...');
+                PullSentinelImageJob::dispatch($this);
+            } else {
+                ray('Sentinel is running');
+            }
+        }
+    }
+    public function getMetrics()
+    {
+        if ($this->is_metrics_enabled) {
+            $from = now()->subMinutes(5)->toIso8601ZuluString();
+            $cpu = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl http://localhost:8888/api/cpu/history?from=$from'"], $this, false);
+            $cpu = str($cpu)->explode("\n")->skip(1)->all();
+            $parsedCollection = collect($cpu)->flatMap(function ($item) {
+                return collect(explode("\n", trim($item)))->map(function ($line) {
+                    list($time, $value) = explode(',', trim($line));
+                    return [(int) $time, (float) $value];
+                });
+            })->toArray();
+            return $parsedCollection;
+        }
+    }
     public function isServerReady(int $tries = 3)
     {
         if ($this->skipServer()) {
@@ -548,7 +581,36 @@ $schema://$host {
     {
         return instant_remote_process(["docker start $id"], $this);
     }
-    public function loadUnmanagedContainers()
+    public function getContainers(): Collection
+    {
+        $sentinel_found = instant_remote_process(["docker inspect coolify-sentinel"], $this, false);
+        $sentinel_found = json_decode($sentinel_found, true);
+        $status = data_get($sentinel_found, '0.State.Status', 'exited');
+        if ($status === 'running') {
+            $containers = instant_remote_process(['docker exec coolify-sentinel sh -c "curl http://127.0.0.1:8888/api/containers"'], $this, false);
+            if (is_null($containers)) {
+                return collect([]);
+            }
+            $containers = data_get(json_decode($containers, true), 'containers', []);
+            return collect($containers);
+        } else {
+            if ($this->isSwarm()) {
+                $containers = instant_remote_process(["docker service inspect $(docker service ls -q) --format '{{json .}}'"], $this, false);
+            } else {
+                $containers = instant_remote_process(["docker container ls -q"], $this, false);
+                if (!$containers) {
+                    return collect([]);
+                }
+                $containers = instant_remote_process(["docker container inspect $(docker container ls -q) --format '{{json .}}'"], $this, false);
+            }
+            if (is_null($containers)) {
+                return collect([]);
+            }
+
+            return format_docker_command_output_to_json($containers);
+        }
+    }
+    public function loadUnmanagedContainers(): Collection
     {
         if ($this->isFunctional()) {
             $containers = instant_remote_process(["docker ps -a --format '{{json .}}'"], $this);
diff --git a/app/Models/Service.php b/app/Models/Service.php
index 41e61cbb8..ab40a761c 100644
--- a/app/Models/Service.php
+++ b/app/Models/Service.php
@@ -171,7 +171,7 @@ class Service extends BaseModel
                             ],
                         ]);
                     }
-                    $fields->put('Tolgee', $data);
+                    $fields->put('Tolgee', $data->toArray());
                     break;
                 case str($image)?->contains('logto'):
                     $data = collect([]);
@@ -195,7 +195,7 @@ class Service extends BaseModel
                             ],
                         ]);
                     }
-                    $fields->put('Logto', $data);
+                    $fields->put('Logto', $data->toArray());
                     break;
                 case str($image)?->contains('unleash-server'):
                     $data = collect([]);
@@ -218,7 +218,7 @@ class Service extends BaseModel
                             ],
                         ]);
                     }
-                    $fields->put('Unleash', $data);
+                    $fields->put('Unleash', $data->toArray());
                     break;
                 case str($image)?->contains('grafana'):
                     $data = collect([]);
@@ -241,7 +241,7 @@ class Service extends BaseModel
                             ],
                         ]);
                     }
-                    $fields->put('Grafana', $data);
+                    $fields->put('Grafana', $data->toArray());
                     break;
                 case str($image)?->contains('directus'):
                     $data = collect([]);
@@ -267,7 +267,7 @@ class Service extends BaseModel
                             ],
                         ]);
                     }
-                    $fields->put('Directus', $data);
+                    $fields->put('Directus', $data->toArray());
                     break;
                 case str($image)?->contains('kong'):
                     $data = collect([]);
@@ -370,7 +370,7 @@ class Service extends BaseModel
                             ],
                         ]);
                     }
-                    $fields->put('Weblate', $data);
+                    $fields->put('Weblate', $data->toArray());
                     break;
                 case str($image)?->contains('meilisearch'):
                     $data = collect([]);
@@ -384,7 +384,7 @@ class Service extends BaseModel
                             ],
                         ]);
                     }
-                    $fields->put('Meilisearch', $data);
+                    $fields->put('Meilisearch', $data->toArray());
                     break;
                 case str($image)?->contains('ghost'):
                     $data = collect([]);
@@ -444,7 +444,33 @@ class Service extends BaseModel
                         ]);
                     }
 
-                    $fields->put('Ghost', $data);
+                    $fields->put('Ghost', $data->toArray());
+                    break;
+                default:
+                    $data = collect([]);
+                    $admin_user = $this->environment_variables()->where('key', 'SERVICE_USER_ADMIN')->first();
+                    $admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first();
+                    if ($admin_user) {
+                        $data = $data->merge([
+                            'User' => [
+                                'key' => 'SERVICE_USER_ADMIN',
+                                'value' => data_get($admin_user, 'value', 'admin'),
+                                'readonly' => true,
+                                'rules' => 'required',
+                            ],
+                        ]);
+                    }
+                    if ($admin_password) {
+                        $data = $data->merge([
+                            'Password' => [
+                                'key' => 'SERVICE_PASSWORD_ADMIN',
+                                'value' => data_get($admin_password, 'value'),
+                                'rules' => 'required',
+                                'isPassword' => true,
+                            ],
+                        ]);
+                    }
+                    $fields->put('Admin', $data->toArray());
                     break;
                 case str($image)?->contains('vaultwarden'):
                     $data = collect([]);
@@ -723,6 +749,18 @@ class Service extends BaseModel
         }
         return null;
     }
+    public function failedTaskLink($task_uuid)
+    {
+        if (data_get($this, 'environment.project.uuid')) {
+            return route('project.service.scheduled-tasks', [
+                'project_uuid' => data_get($this, 'environment.project.uuid'),
+                'environment_name' => data_get($this, 'environment.name'),
+                'application_uuid' => data_get($this, 'uuid'),
+                'task_uuid' => $task_uuid
+            ]);
+        }
+        return null;
+    }
     public function documentation()
     {
         $services = getServiceTemplates();
@@ -749,6 +787,17 @@ class Service extends BaseModel
     {
         return $this->belongsTo(Server::class);
     }
+    public function byUuid(string $uuid) {
+        $app = $this->applications()->whereUuid($uuid)->first();
+        if ($app) {
+            return $app;
+        }
+        $db = $this->databases()->whereUuid($uuid)->first();
+        if ($db) {
+            return $db;
+        }
+        return null;
+    }
     public function byName(string $name)
     {
         $app = $this->applications()->whereName($name)->first();
diff --git a/app/Models/StandaloneClickhouse.php b/app/Models/StandaloneClickhouse.php
index 3746a32f5..2197d51df 100644
--- a/app/Models/StandaloneClickhouse.php
+++ b/app/Models/StandaloneClickhouse.php
@@ -207,7 +207,4 @@ class StandaloneClickhouse extends BaseModel
     {
         return $this->morphMany(ScheduledDatabaseBackup::class, 'database');
     }
-    public function database_name() {
-        return $this->clickhouse_db;
-    }
 }
diff --git a/app/Models/StandaloneDragonfly.php b/app/Models/StandaloneDragonfly.php
index adc1ea6cc..7b18666b8 100644
--- a/app/Models/StandaloneDragonfly.php
+++ b/app/Models/StandaloneDragonfly.php
@@ -207,7 +207,4 @@ class StandaloneDragonfly extends BaseModel
     {
         return $this->morphMany(ScheduledDatabaseBackup::class, 'database');
     }
-    public function database_name() {
-        return '0';
-    }
 }
diff --git a/app/Models/StandaloneKeydb.php b/app/Models/StandaloneKeydb.php
index ff91322a0..c2c1b98da 100644
--- a/app/Models/StandaloneKeydb.php
+++ b/app/Models/StandaloneKeydb.php
@@ -208,7 +208,4 @@ class StandaloneKeydb extends BaseModel
     {
         return $this->morphMany(ScheduledDatabaseBackup::class, 'database');
     }
-    public function database_name() {
-        return '0';
-    }
 }
diff --git a/app/Models/StandaloneMariadb.php b/app/Models/StandaloneMariadb.php
index 37d39f882..5e18bbfde 100644
--- a/app/Models/StandaloneMariadb.php
+++ b/app/Models/StandaloneMariadb.php
@@ -208,7 +208,4 @@ class StandaloneMariadb extends BaseModel
     {
         return $this->morphMany(ScheduledDatabaseBackup::class, 'database');
     }
-    public function database_name() {
-        return $this->mariadb_database;
-    }
 }
diff --git a/app/Models/StandaloneMongodb.php b/app/Models/StandaloneMongodb.php
index 5538efe1a..8e4d327a3 100644
--- a/app/Models/StandaloneMongodb.php
+++ b/app/Models/StandaloneMongodb.php
@@ -223,7 +223,4 @@ class StandaloneMongodb extends BaseModel
     {
         return $this->morphMany(ScheduledDatabaseBackup::class, 'database');
     }
-    public function database_name() {
-        return $this->mongo_db;
-    }
 }
diff --git a/app/Models/StandaloneMysql.php b/app/Models/StandaloneMysql.php
index 53e9b6f22..eede451d7 100644
--- a/app/Models/StandaloneMysql.php
+++ b/app/Models/StandaloneMysql.php
@@ -209,7 +209,4 @@ class StandaloneMysql extends BaseModel
     {
         return $this->morphMany(ScheduledDatabaseBackup::class, 'database');
     }
-    public function database_name() {
-        return $this->mysql_database;
-    }
 }
diff --git a/app/Models/StandalonePostgresql.php b/app/Models/StandalonePostgresql.php
index 6435c49de..cf449a815 100644
--- a/app/Models/StandalonePostgresql.php
+++ b/app/Models/StandalonePostgresql.php
@@ -208,7 +208,4 @@ class StandalonePostgresql extends BaseModel
     {
         return $this->morphMany(ScheduledDatabaseBackup::class, 'database');
     }
-    public function database_name() {
-        return $this->postgres_db;
-    }
 }
diff --git a/app/Models/StandaloneRedis.php b/app/Models/StandaloneRedis.php
index de18c8c07..da4701df9 100644
--- a/app/Models/StandaloneRedis.php
+++ b/app/Models/StandaloneRedis.php
@@ -204,7 +204,4 @@ class StandaloneRedis extends BaseModel
     {
         return $this->morphMany(ScheduledDatabaseBackup::class, 'database');
     }
-    public function database_name() {
-        return '0';
-    }
 }
diff --git a/app/Models/Team.php b/app/Models/Team.php
index 29e434a5d..81206019f 100644
--- a/app/Models/Team.php
+++ b/app/Models/Team.php
@@ -26,6 +26,34 @@ class Team extends Model implements SendsDiscord, SendsEmail
                 throw new \Exception('You are not allowed to update this team.');
             }
         });
+
+        static::deleting(function ($team) {
+            $keys = $team->privateKeys;
+            foreach ($keys as $key) {
+                ray('Deleting key: ' . $key->name);
+                $key->delete();
+            }
+            $sources = $team->sources();
+            foreach ($sources as $source) {
+                ray('Deleting source: ' . $source->name);
+                $source->delete();
+            }
+            $tags = Tag::whereTeamId($team->id)->get();
+            foreach ($tags as $tag) {
+                ray('Deleting tag: ' . $tag->name);
+                $tag->delete();
+            }
+            $shared_variables = $team->environment_variables();
+            foreach ($shared_variables as $shared_variable) {
+                ray('Deleting team shared variable: ' . $shared_variable->name);
+                $shared_variable->delete();
+            }
+            $s3s = $team->s3s;
+            foreach ($s3s as $s3) {
+                ray('Deleting s3: ' . $s3->name);
+                $s3->delete();
+            }
+        });
     }
 
     public function routeNotificationForDiscord()
diff --git a/app/Models/User.php b/app/Models/User.php
index 0fa8ead2f..0e66fdaea 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -183,6 +183,7 @@ class User extends Authenticatable implements SendsEmail
         if (data_get($this, 'pivot')) {
             return $this->pivot->role;
         }
-        return auth()->user()->teams->where('id', currentTeam()->id)->first()->pivot->role;
+        $user = auth()->user()->teams->where('id', currentTeam()->id)->first();
+        return data_get($user, 'pivot.role');
     }
 }
diff --git a/app/Notifications/Application/DeploymentFailed.php b/app/Notifications/Application/DeploymentFailed.php
index 1705deda1..05fe544d0 100644
--- a/app/Notifications/Application/DeploymentFailed.php
+++ b/app/Notifications/Application/DeploymentFailed.php
@@ -69,10 +69,10 @@ class DeploymentFailed extends Notification implements ShouldQueue
     public function toDiscord(): string
     {
         if ($this->preview) {
-            $message = 'Coolify:  Pull request #' . $this->preview->pull_request_id . ' of **' . $this->application_name . '** (' . $this->preview->fqdn . ') deployment failed: ';
+            $message = 'Coolify:  Pull request #' . $this->preview->pull_request_id . ' of ' . $this->application_name . ' (' . $this->preview->fqdn . ') deployment failed: ';
             $message .= '[View Deployment Logs](' . $this->deployment_url . ')';
         } else {
-            $message = 'Coolify: Deployment failed of **' . $this->application_name . '** (' . $this->fqdn . '): ';
+            $message = 'Coolify: Deployment failed of ' . $this->application_name . ' (' . $this->fqdn . '): ';
             $message .= '[View Deployment Logs](' . $this->deployment_url . ')';
         }
         return $message;
@@ -80,9 +80,9 @@ class DeploymentFailed extends Notification implements ShouldQueue
     public function toTelegram(): array
     {
         if ($this->preview) {
-            $message = 'Coolify: Pull request #' . $this->preview->pull_request_id . ' of **' . $this->application_name . '** (' . $this->preview->fqdn . ') deployment failed: ';
+            $message = 'Coolify: Pull request #' . $this->preview->pull_request_id . ' of ' . $this->application_name . ' (' . $this->preview->fqdn . ') deployment failed: ';
         } else {
-            $message = 'Coolify: Deployment failed of **' . $this->application_name . '** (' . $this->fqdn . '): ';
+            $message = 'Coolify: Deployment failed of ' . $this->application_name . ' (' . $this->fqdn . '): ';
         }
         $buttons[] = [
             "text" => "Deployment logs",
diff --git a/app/Notifications/Application/DeploymentSuccess.php b/app/Notifications/Application/DeploymentSuccess.php
index 322df5cec..e138ac91e 100644
--- a/app/Notifications/Application/DeploymentSuccess.php
+++ b/app/Notifications/Application/DeploymentSuccess.php
@@ -45,13 +45,11 @@ class DeploymentSuccess extends Notification implements ShouldQueue
     {
         $channels = setNotificationChannels($notifiable, 'deployments');
         if (isCloud()) {
-            $channels = array_filter($channels, function ($channel) {
-                return $channel !== 'App\Notifications\Channels\EmailChannel';
-            });
+            // TODO: Make batch notifications work with email
+            $channels = array_diff($channels, ['App\Notifications\Channels\EmailChannel']);
         }
         return $channels;
     }
-
     public function toMail(): MailMessage
     {
         $mail = new MailMessage();
diff --git a/app/Notifications/Channels/TelegramChannel.php b/app/Notifications/Channels/TelegramChannel.php
index 1401bb324..6101ef208 100644
--- a/app/Notifications/Channels/TelegramChannel.php
+++ b/app/Notifications/Channels/TelegramChannel.php
@@ -14,22 +14,27 @@ class TelegramChannel
         $buttons = data_get($data, 'buttons', []);
         $telegramToken = data_get($telegramData, 'token');
         $chatId = data_get($telegramData, 'chat_id');
-        $topicId  = null;
+        $topicId = null;
         $topicsInstance = get_class($notification);
 
         switch ($topicsInstance) {
-            case 'App\Notifications\StatusChange':
-                $topicId = data_get($notifiable, 'telegram_notifications_status_changes_message_thread_id');
-                break;
             case 'App\Notifications\Test':
                 $topicId = data_get($notifiable, 'telegram_notifications_test_message_thread_id');
                 break;
-            case 'App\Notifications\Deployment':
+            case 'App\Notifications\Application\StatusChanged':
+                $topicId = data_get($notifiable, 'telegram_notifications_status_changes_message_thread_id');
+                break;
+            case 'App\Notifications\Application\DeploymentSuccess':
+            case 'App\Notifications\Application\DeploymentFailed':
                 $topicId = data_get($notifiable, 'telegram_notifications_deployments_message_thread_id');
                 break;
-            case 'App\Notifications\DatabaseBackup':
+            case 'App\Notifications\Database\BackupSuccess':
+            case 'App\Notifications\Database\BackupFailed':
                 $topicId = data_get($notifiable, 'telegram_notifications_database_backups_message_thread_id');
                 break;
+            case 'App\Notifications\ScheduledTask\TaskFailed':
+                $topicId = data_get($notifiable, 'telegram_notifications_scheduled_tasks_thread_id');
+                break;
         }
         if (!$telegramToken || !$chatId || !$message) {
             return;
diff --git a/app/Notifications/Container/ContainerRestarted.php b/app/Notifications/Container/ContainerRestarted.php
index 21dc799f8..d9c524da4 100644
--- a/app/Notifications/Container/ContainerRestarted.php
+++ b/app/Notifications/Container/ContainerRestarted.php
@@ -31,7 +31,7 @@ class ContainerRestarted extends Notification implements ShouldQueue
         $mail->view('emails.container-restarted', [
             'containerName' => $this->name,
             'serverName' => $this->server->name,
-            'url' => $this->url ,
+            'url' => $this->url,
         ]);
         return $mail;
     }
diff --git a/app/Notifications/Database/BackupFailed.php b/app/Notifications/Database/BackupFailed.php
index 3aa63ffd9..7cad486b3 100644
--- a/app/Notifications/Database/BackupFailed.php
+++ b/app/Notifications/Database/BackupFailed.php
@@ -15,21 +15,20 @@ class BackupFailed extends Notification implements ShouldQueue
 {
     use Queueable;
 
-    public $tries = 1;
+    public $backoff = 10;
+    public $tries = 2;
     public string $name;
-    public string $database_name;
     public string $frequency;
 
-    public function __construct(ScheduledDatabaseBackup $backup, public $database, public $output)
+    public function __construct(ScheduledDatabaseBackup $backup, public $database, public $output, public $database_name)
     {
         $this->name = $database->name;
-        $this->database_name = $database->database_name();
         $this->frequency = $backup->frequency;
     }
 
     public function via(object $notifiable): array
     {
-        return [DiscordChannel::class, TelegramChannel::class, MailChannel::class];
+        return setNotificationChannels($notifiable, 'database_backups');
     }
 
     public function toMail(): MailMessage
@@ -47,11 +46,11 @@ class BackupFailed extends Notification implements ShouldQueue
 
     public function toDiscord(): string
     {
-        return "Coolify: Database backup for {$this->name} (db:{$this->database_name}) with frequency of {$this->frequency} was FAILED.\n\nReason: {$this->output}";
+        return "Coolify: Database backup for {$this->name} (db:{$this->database_name}) with frequency of {$this->frequency} was FAILED.\n\nReason:\n{$this->output}";
     }
     public function toTelegram(): array
     {
-        $message = "Coolify:  Database backup for {$this->name} (db:{$this->database_name}) with frequency of {$this->frequency} was FAILED.\n\nReason: {$this->output}";
+        $message = "Coolify: Database backup for {$this->name} (db:{$this->database_name}) with frequency of {$this->frequency} was FAILED.\n\nReason:\n{$this->output}";
         return [
             "message" => $message,
         ];
diff --git a/app/Notifications/Database/BackupSuccess.php b/app/Notifications/Database/BackupSuccess.php
index 9ca3234e1..c43a12276 100644
--- a/app/Notifications/Database/BackupSuccess.php
+++ b/app/Notifications/Database/BackupSuccess.php
@@ -12,15 +12,14 @@ class BackupSuccess extends Notification implements ShouldQueue
 {
     use Queueable;
 
-    public $tries = 1;
+    public $backoff = 10;
+    public $tries = 3;
     public string $name;
-    public string $database_name;
     public string $frequency;
 
-    public function __construct(ScheduledDatabaseBackup $backup, public $database)
+    public function __construct(ScheduledDatabaseBackup $backup, public $database, public $database_name)
     {
         $this->name = $database->name;
-        $this->database_name = $database->database_name();
         $this->frequency = $backup->frequency;
     }
 
@@ -48,6 +47,7 @@ class BackupSuccess extends Notification implements ShouldQueue
     public function toTelegram(): array
     {
         $message = "Coolify: Database backup for {$this->name} (db:{$this->database_name}) with frequency of {$this->frequency} was successful.";
+        ray($message);
         return [
             "message" => $message,
         ];
diff --git a/app/Notifications/ScheduledTask/TaskFailed.php b/app/Notifications/ScheduledTask/TaskFailed.php
new file mode 100644
index 000000000..f61b1f573
--- /dev/null
+++ b/app/Notifications/ScheduledTask/TaskFailed.php
@@ -0,0 +1,64 @@
+application) {
+            $this->url = $task->application->failedTaskLink($task->uuid);
+        } else if ($task->service) {
+            $this->url = $task->service->failedTaskLink($task->uuid);
+        }
+    }
+
+    public function via(object $notifiable): array
+    {
+
+        return setNotificationChannels($notifiable, 'scheduled_tasks');
+    }
+
+    public function toMail(): MailMessage
+    {
+        $mail = new MailMessage();
+        $mail->subject("Coolify: [ACTION REQUIRED] Scheduled task ({$this->task->name}) failed.");
+        $mail->view('emails.scheduled-task-failed', [
+            'task' => $this->task,
+            'url' => $this->url,
+            'output' => $this->output,
+        ]);
+        return $mail;
+    }
+
+    public function toDiscord(): string
+    {
+        return "Coolify: Scheduled task ({$this->task->name}, [link]({$this->url})) failed with output: {$this->output}";
+    }
+    public function toTelegram(): array
+    {
+        $message = "Coolify: Scheduled task ({$this->task->name}) failed with output: {$this->output}";
+        if ($this->url) {
+            $buttons[] = [
+                "text" => "Open task in Coolify",
+                "url" => (string) $this->url
+            ];
+        }
+        return [
+            "message" => $message,
+        ];
+    }
+}
diff --git a/app/Notifications/Server/Revived.php b/app/Notifications/Server/Revived.php
index c670ded9a..36775976b 100644
--- a/app/Notifications/Server/Revived.php
+++ b/app/Notifications/Server/Revived.php
@@ -2,6 +2,7 @@
 
 namespace App\Notifications\Server;
 
+use App\Actions\Docker\GetContainersStatus;
 use App\Jobs\ContainerStatusJob;
 use App\Models\Server;
 use Illuminate\Bus\Queueable;
@@ -22,7 +23,8 @@ class Revived extends Notification implements ShouldQueue
         if ($this->server->unreachable_notification_sent === false) {
             return;
         }
-        dispatch(new ContainerStatusJob($server));
+        GetContainersStatus::dispatch($server);
+        // dispatch(new ContainerStatusJob($server));
     }
 
     public function via(object $notifiable): array
diff --git a/bootstrap/helpers/applications.php b/bootstrap/helpers/applications.php
index c0aaf4abf..a1995c645 100644
--- a/bootstrap/helpers/applications.php
+++ b/bootstrap/helpers/applications.php
@@ -6,7 +6,6 @@ use App\Models\Application;
 use App\Models\ApplicationDeploymentQueue;
 use App\Models\Server;
 use App\Models\StandaloneDocker;
-use Illuminate\Support\Collection;
 use Spatie\Url\Url;
 
 function queue_application_deployment(Application $application, string $deployment_uuid, int | null $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false, bool $restart_only = false, ?string $git_type = null, bool $no_questions_asked = false, Server $server = null, StandaloneDocker $destination = null, bool $only_this_server = false, bool $rollback = false)
diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php
index a70c85a72..a087c92c5 100644
--- a/bootstrap/helpers/docker.php
+++ b/bootstrap/helpers/docker.php
@@ -8,6 +8,7 @@ use App\Models\ServiceApplication;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Str;
 use Spatie\Url\Url;
+use Visus\Cuid2\Cuid2;
 
 function getCurrentApplicationContainerStatus(Server $server, int $id, ?int $pullRequestId = null, ?bool $includePullrequests = false): Collection
 {
@@ -272,7 +273,7 @@ function fqdnLabelsForCaddy(string $network, string $uuid, Collection $domains,
     }
     return $labels->sort();
 }
-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)
+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, bool $generate_unique_uuid = false)
 {
     $labels = collect([]);
     $labels->push('traefik.enable=true');
@@ -313,7 +314,9 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
     }
     foreach ($domains as $loop => $domain) {
         try {
-            // $uuid = new Cuid2(7);
+            if ($generate_unique_uuid) {
+                $uuid = new Cuid2(7);
+            }
             $url = Url::fromString($domain);
             $host = $url->getHost();
             $path = $url->getPath();
diff --git a/bootstrap/helpers/services.php b/bootstrap/helpers/services.php
index 8e3c0337e..26a69222a 100644
--- a/bootstrap/helpers/services.php
+++ b/bootstrap/helpers/services.php
@@ -18,7 +18,7 @@ function collectRegex(string $name)
 }
 function replaceVariables($variable)
 {
-    return $variable->replaceFirst('$', '')->replaceFirst('{', '')->replaceLast('}', '');
+    return $variable->before('}')->replaceFirst('$', '')->replaceFirst('{', '');
 }
 
 function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase|Application $oneService, bool $isInit = false)
@@ -27,7 +27,7 @@ function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase|Appli
         if ($oneService->getMorphClass() === 'App\Models\Application') {
             $workdir = $oneService->workdir();
             $server = $oneService->destination->server;
-        } else{
+        } else {
             $workdir = $oneService->service->workdir();
             $server = $oneService->service->server;
         }
diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php
index b2c34900e..6453108eb 100644
--- a/bootstrap/helpers/shared.php
+++ b/bootstrap/helpers/shared.php
@@ -95,6 +95,9 @@ function currentTeam()
 
 function showBoarding(): bool
 {
+    if (auth()->user()?->isMember()) {
+        return false;
+    }
     return currentTeam()->show_boarding ?? false;
 }
 function refreshSession(?Team $team = null): void
@@ -147,6 +150,18 @@ function get_route_parameters(): array
     return Route::current()->parameters();
 }
 
+function get_latest_sentinel_version(): string
+{
+    try {
+        $response = Http::get('https://cdn.coollabs.io/coolify/versions.json');
+        $versions = $response->json();
+        return data_get($versions, 'coolify.sentinel.version');
+    } catch (\Throwable $e) {
+        //throw $e;
+        ray($e->getMessage());
+        return '0.0.0';
+    }
+}
 function get_latest_version_of_coolify(): string
 {
     try {
@@ -637,7 +652,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
             $allServices = getServiceTemplates();
             $topLevelVolumes = collect(data_get($yaml, 'volumes', []));
             $topLevelNetworks = collect(data_get($yaml, 'networks', []));
-            $dockerComposeVersion = data_get($yaml, 'version') ?? '3.8';
             $services = data_get($yaml, 'services');
 
             $generatedServiceFQDNS = collect([]);
@@ -988,20 +1002,18 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
                             if ($fqdns_exploded->count() > 1) {
                                 continue;
                             }
-                            if ($resource->server->proxyType() === 'CADDY') {
-                                $env = EnvironmentVariable::where([
-                                    'key' => $key,
-                                    'service_id' => $resource->id,
-                                ])->first();
-                                if ($env) {
+                            $env = EnvironmentVariable::where([
+                                'key' => $key,
+                                'service_id' => $resource->id,
+                            ])->first();
+                            if ($env) {
 
-                                    $env_url = Url::fromString($savedService->fqdn);
-                                    $env_port = $env_url->getPort();
-                                    if ($env_port !== $predefinedPort) {
-                                        $env_url = $env_url->withPort($predefinedPort);
-                                        $savedService->fqdn = $env_url->__toString();
-                                        $savedService->save();
-                                    }
+                                $env_url = Url::fromString($savedService->fqdn);
+                                $env_port = $env_url->getPort();
+                                if ($env_port !== $predefinedPort) {
+                                    $env_url = $env_url->withPort($predefinedPort);
+                                    $savedService->fqdn = $env_url->__toString();
+                                    $savedService->save();
                                 }
                             }
                         }
@@ -1165,6 +1177,13 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
                         ]
                     ]);
                 }
+                if ($serviceLabels->count() > 0) {
+                    if ($resource->is_container_label_escape_enabled) {
+                        $serviceLabels = $serviceLabels->map(function ($value, $key) {
+                            return escapeDollarSign($value);
+                        });
+                    }
+                }
                 data_set($service, 'labels', $serviceLabels->toArray());
                 data_forget($service, 'is_database');
                 if (!data_get($service, 'restart')) {
@@ -1194,7 +1213,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
                 return $service;
             });
             $finalServices = [
-                'version' => $dockerComposeVersion,
                 'services' => $services->toArray(),
                 'volumes' => $topLevelVolumes->toArray(),
                 'networks' => $topLevelNetworks->toArray(),
@@ -1217,13 +1235,13 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
             try {
                 $yaml = Yaml::parse($resource->docker_compose_pr_raw);
             } catch (\Exception $e) {
-                throw new \Exception($e->getMessage());
+                return;
             }
         } else {
             try {
                 $yaml = Yaml::parse($resource->docker_compose_raw);
             } catch (\Exception $e) {
-                throw new \Exception($e->getMessage());
+                return;
             }
         }
         $server = $resource->destination->server;
@@ -1232,7 +1250,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
             $topLevelVolumes = collect([]);
         }
         $topLevelNetworks = collect(data_get($yaml, 'networks', []));
-        $dockerComposeVersion = data_get($yaml, 'version') ?? '3.8';
         $services = data_get($yaml, 'services');
 
         $generatedServiceFQDNS = collect([]);
@@ -1252,6 +1269,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
             $servicePorts = collect(data_get($service, 'ports', []));
             $serviceNetworks = collect(data_get($service, 'networks', []));
             $serviceVariables = collect(data_get($service, 'environment', []));
+            $serviceDependencies = collect(data_get($service, 'depends_on', []));
             $serviceLabels = collect(data_get($service, 'labels', []));
             $serviceBuildVariables = collect(data_get($service, 'build.args', []));
             $serviceVariables = $serviceVariables->merge($serviceBuildVariables);
@@ -1268,11 +1286,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
                     $serviceLabels->push("$removedLabelName=$removedLabel");
                 }
             }
-            if ($serviceLabels->count() > 0) {
-                $serviceLabels = $serviceLabels->map(function ($value, $key) {
-                    return escapeDollarSign($value);
-                });
-            }
+
             $baseName = generateApplicationContainerName($resource, $pull_request_id);
             $containerName = "$serviceName-$baseName";
             if (count($serviceVolumes) > 0) {
@@ -1363,6 +1377,13 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
                 data_set($service, 'volumes', $serviceVolumes->toArray());
             }
 
+            if ($pull_request_id !== 0 && count($serviceDependencies) > 0) {
+                $serviceDependencies = $serviceDependencies->map(function ($dependency) use ($pull_request_id) {
+                    return $dependency . "-pr-$pull_request_id";
+                });
+                data_set($service, 'depends_on', $serviceDependencies->toArray());
+            }
+
             // Decide if the service is a database
             $isDatabase = isDatabaseImage(data_get_str($service, 'image'));
             data_set($service, 'is_database', $isDatabase);
@@ -1620,7 +1641,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
                         $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik(
                             uuid: $resource->uuid,
                             domains: $fqdns,
-                            serviceLabels: $serviceLabels
+                            serviceLabels: $serviceLabels,
+                            generate_unique_uuid: $resource->build_pack === 'dockercompose'
                         ));
                         $serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy(
                             network: $resource->destination->network,
@@ -1644,6 +1666,13 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
                     ]
                 ]);
             }
+            if ($serviceLabels->count() > 0) {
+                if ($resource->settings->is_container_label_escape_enabled) {
+                    $serviceLabels = $serviceLabels->map(function ($value, $key) {
+                        return escapeDollarSign($value);
+                    });
+                }
+            }
             data_set($service, 'labels', $serviceLabels->toArray());
             data_forget($service, 'is_database');
             if (!data_get($service, 'restart')) {
@@ -1662,7 +1691,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
             });
         }
         $finalServices = [
-            'version' => $dockerComposeVersion,
             'services' => $services->toArray(),
             'volumes' => $topLevelVolumes->toArray(),
             'networks' => $topLevelNetworks->toArray(),
@@ -1842,7 +1870,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;
     }
@@ -1921,7 +1949,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/constants.php b/config/constants.php
index 091c60996..53f43ae5a 100644
--- a/config/constants.php
+++ b/config/constants.php
@@ -32,6 +32,7 @@ return [
             'basic' => env('LIMIT_SERVER_BASIC', 2),
             'pro' => env('LIMIT_SERVER_PRO', 10),
             'ultimate' => env('LIMIT_SERVER_ULTIMATE', 25),
+            'dynamic' => env('LIMIT_SERVER_DYNAMIC', 2),
         ],
         'email' => [
             'zero' => true,
@@ -39,6 +40,7 @@ return [
             'basic' => true,
             'pro' => true,
             'ultimate' => true,
+            'dynamic' => true,
         ],
     ],
 ];
diff --git a/config/coolify.php b/config/coolify.php
index a6d6d8581..c7cfe6101 100644
--- a/config/coolify.php
+++ b/config/coolify.php
@@ -14,4 +14,5 @@ return [
     'helper_image' => env('HELPER_IMAGE', 'ghcr.io/coollabsio/coolify-helper:latest'),
     'is_horizon_enabled' => env('HORIZON_ENABLED', true),
     'is_scheduler_enabled' => env('SCHEDULER_ENABLED', true),
+    'is_sentinel_enabled' => env('SENTINEL_ENABLED', false),
 ];
diff --git a/config/sentry.php b/config/sentry.php
index 2b48e1f14..693c33c3d 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.269',
+    'release' => '4.0.0-beta.285',
     // 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 bf35359e8..e09c4fd6a 100644
--- a/config/version.php
+++ b/config/version.php
@@ -1,3 +1,3 @@
 boolean('custom_healthcheck_found')->default(false);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('applications', function (Blueprint $table) {
+            $table->dropColumn('custom_healthcheck_found');
+        });
+    }
+};
diff --git a/database/migrations/2024_05_06_093236_add_custom_name_to_application_settings.php b/database/migrations/2024_05_06_093236_add_custom_name_to_application_settings.php
new file mode 100644
index 000000000..e2d68d240
--- /dev/null
+++ b/database/migrations/2024_05_06_093236_add_custom_name_to_application_settings.php
@@ -0,0 +1,28 @@
+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/database/migrations/2024_05_07_124019_add_server_metrics.php b/database/migrations/2024_05_07_124019_add_server_metrics.php
new file mode 100644
index 000000000..40c74850b
--- /dev/null
+++ b/database/migrations/2024_05_07_124019_add_server_metrics.php
@@ -0,0 +1,28 @@
+boolean('is_metrics_enabled')->default(true);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('servers', function (Blueprint $table) {
+            $table->dropColumn('is_metrics_enabled');
+        });
+    }
+};
diff --git a/database/migrations/2024_05_10_085215_make_stripe_comment_longer.php b/database/migrations/2024_05_10_085215_make_stripe_comment_longer.php
new file mode 100644
index 000000000..a51896f42
--- /dev/null
+++ b/database/migrations/2024_05_10_085215_make_stripe_comment_longer.php
@@ -0,0 +1,28 @@
+longText('stripe_comment')->change();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('subscriptions', function (Blueprint $table) {
+            $table->string('stripe_comment')->change();
+        });
+    }
+};
diff --git a/database/migrations/2024_05_15_091757_add_commit_message_to_app_deployment_queue.php b/database/migrations/2024_05_15_091757_add_commit_message_to_app_deployment_queue.php
new file mode 100644
index 000000000..78608f503
--- /dev/null
+++ b/database/migrations/2024_05_15_091757_add_commit_message_to_app_deployment_queue.php
@@ -0,0 +1,28 @@
+string('commit_message', 50)->nullable();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('application_deployment_queues', function (Blueprint $table) {
+            $table->dropColumn('commit_message');
+        });
+    }
+};
diff --git a/database/migrations/2024_05_15_151236_add_container_escape_toggle.php b/database/migrations/2024_05_15_151236_add_container_escape_toggle.php
new file mode 100644
index 000000000..aa1384518
--- /dev/null
+++ b/database/migrations/2024_05_15_151236_add_container_escape_toggle.php
@@ -0,0 +1,34 @@
+boolean('is_container_label_escape_enabled')->default(true);
+        });
+        Schema::table('services', function (Blueprint $table) {
+            $table->boolean('is_container_label_escape_enabled')->default(true);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('application_settings', function (Blueprint $table) {
+            $table->dropColumn('is_container_label_escape_enabled');
+        });
+        Schema::table('services', function (Blueprint $table) {
+            $table->dropColumn('is_container_label_escape_enabled');
+        });
+    }
+};
diff --git a/database/migrations/2024_05_17_082012_add_env_sorting_toggle.php b/database/migrations/2024_05_17_082012_add_env_sorting_toggle.php
new file mode 100644
index 000000000..d4e120e2b
--- /dev/null
+++ b/database/migrations/2024_05_17_082012_add_env_sorting_toggle.php
@@ -0,0 +1,28 @@
+boolean('is_env_sorting_enabled')->default(true);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('application_settings', function (Blueprint $table) {
+            $table->dropColumn('is_env_sorting_enabled');
+        });
+    }
+};
diff --git a/database/migrations/2024_05_21_125739_add_scheduled_tasks_notification_to_teams.php b/database/migrations/2024_05_21_125739_add_scheduled_tasks_notification_to_teams.php
new file mode 100644
index 000000000..0fcbb0655
--- /dev/null
+++ b/database/migrations/2024_05_21_125739_add_scheduled_tasks_notification_to_teams.php
@@ -0,0 +1,34 @@
+boolean('telegram_notifications_scheduled_tasks')->default(true);
+            $table->boolean('smtp_notifications_scheduled_tasks')->default(false)->after('smtp_notifications_status_changes');
+            $table->boolean('discord_notifications_scheduled_tasks')->default(true)->after('discord_notifications_status_changes');
+            $table->text('telegram_notifications_scheduled_tasks_thread_id')->nullable();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('teams', function (Blueprint $table) {
+            $table->dropColumn('telegram_notifications_scheduled_tasks');
+            $table->dropColumn('smtp_notifications_scheduled_tasks');
+            $table->dropColumn('discord_notifications_scheduled_tasks');
+            $table->dropColumn('telegram_notifications_scheduled_tasks_thread_id');
+        });
+    }
+};
diff --git a/database/seeders/TestTeamSeeder.php b/database/seeders/TestTeamSeeder.php
new file mode 100644
index 000000000..1d660c713
--- /dev/null
+++ b/database/seeders/TestTeamSeeder.php
@@ -0,0 +1,42 @@
+create([
+            'name' => '1 personal, 1 other team, owner, no other members',
+            'email' => '1@example.com',
+        ]);
+        $team = Team::create([
+            'name' => "1@example.com",
+            'personal_team' => false,
+            'show_boarding' => true
+        ]);
+        $user->teams()->attach($team, ['role' => 'owner']);
+
+        // User has 2 teams, 1 personal, 1 other where it is the owner and 1 other member is in the team
+        $user = User::factory()->create([
+            'name' => 'owner: 1 personal, 1 other team, owner, 1 other member',
+            'email' => '2@example.com',
+        ]);
+        $team = Team::create([
+            'name' => "2@example.com",
+            'personal_team' => false,
+            'show_boarding' => true
+        ]);
+        $user->teams()->attach($team, ['role' => 'owner']);
+        $user = User::factory()->create([
+            'name' => 'member: 1 personal, 1 other team, owner, 1 other member',
+            'email' => '3@example.com',
+        ]);
+        $team->members()->attach($user, ['role' => 'member']);
+    }
+}
diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml
index 6d76a9abd..91e90b989 100644
--- a/docker-compose.dev.yml
+++ b/docker-compose.dev.yml
@@ -1,5 +1,3 @@
-version: "3.8"
-
 services:
   coolify:
     build:
diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml
index f68b2c41c..f3dda9748 100644
--- a/docker-compose.prod.yml
+++ b/docker-compose.prod.yml
@@ -1,4 +1,3 @@
-version: '3.8'
 services:
   coolify:
     image: "ghcr.io/coollabsio/coolify:${LATEST_IMAGE:-latest}"
diff --git a/docker-compose.windows.yml b/docker-compose.windows.yml
index e35ece624..af5ecc0f7 100644
--- a/docker-compose.windows.yml
+++ b/docker-compose.windows.yml
@@ -1,4 +1,3 @@
-version: '3.8'
 services:
   coolify-testing-host:
     init: true
diff --git a/docker-compose.yml b/docker-compose.yml
index 6adfaf98a..8eed44f8c 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,4 +1,3 @@
-version: '3.8'
 services:
     coolify:
         container_name: coolify
@@ -11,7 +10,6 @@ services:
         depends_on:
             - postgres
             - redis
-
     postgres:
         image: postgres:15-alpine
         container_name: coolify-db
diff --git a/docker/coolify-helper/Dockerfile b/docker/coolify-helper/Dockerfile
index 5798c92bd..768d2ca89 100644
--- a/docker/coolify-helper/Dockerfile
+++ b/docker/coolify-helper/Dockerfile
@@ -2,15 +2,15 @@ FROM alpine:3.17
 
 ARG TARGETPLATFORM
 # https://download.docker.com/linux/static/stable/
-ARG DOCKER_VERSION=24.0.9
+ARG DOCKER_VERSION=26.1.2
 # https://github.com/docker/compose/releases
-ARG DOCKER_COMPOSE_VERSION=2.25.0
+ARG DOCKER_COMPOSE_VERSION=2.27.0
 # https://github.com/docker/buildx/releases
-ARG DOCKER_BUILDX_VERSION=0.13.1
+ARG DOCKER_BUILDX_VERSION=0.14.0
 # https://github.com/buildpacks/pack/releases
 ARG PACK_VERSION=0.33.2
 # https://github.com/railwayapp/nixpacks/releases
-ARG NIXPACKS_VERSION=1.21.2
+ARG NIXPACKS_VERSION=1.21.3
 
 USER root
 WORKDIR /artifacts
diff --git a/docker/dev-ssu/Dockerfile b/docker/dev-ssu/Dockerfile
index 0c7ce2b2a..f0e353d28 100644
--- a/docker/dev-ssu/Dockerfile
+++ b/docker/dev-ssu/Dockerfile
@@ -2,7 +2,7 @@ FROM serversideup/php:8.2-fpm-nginx-v2.2.1
 
 ARG TARGETPLATFORM
 # https://github.com/cloudflare/cloudflared/releases
-ARG CLOUDFLARED_VERSION=2024.2.1
+ARG CLOUDFLARED_VERSION=2024.4.1
 
 ARG POSTGRES_VERSION=15
 RUN apt-get update
diff --git a/docker/prod-ssu/Dockerfile b/docker/prod-ssu/Dockerfile
index dcc1c334d..2192f4f0e 100644
--- a/docker/prod-ssu/Dockerfile
+++ b/docker/prod-ssu/Dockerfile
@@ -15,7 +15,7 @@ FROM serversideup/php:8.2-fpm-nginx-v2.2.1
 
 ARG TARGETPLATFORM
 # https://github.com/cloudflare/cloudflared/releases
-ARG CLOUDFLARED_VERSION=2024.2.1
+ARG CLOUDFLARED_VERSION=2024.4.1
 ARG POSTGRES_VERSION=15
 
 WORKDIR /var/www/html
diff --git a/docker/testing-host/Dockerfile b/docker/testing-host/Dockerfile
index 6d0d0d5c5..deb09eeba 100644
--- a/docker/testing-host/Dockerfile
+++ b/docker/testing-host/Dockerfile
@@ -2,11 +2,11 @@ FROM debian:12-slim
 
 ARG TARGETPLATFORM
 # https://download.docker.com/linux/static/stable/
-ARG DOCKER_VERSION=24.0.5
+ARG DOCKER_VERSION=26.1.2
 # https://github.com/docker/compose/releases
-ARG DOCKER_COMPOSE_VERSION=2.21.0
+ARG DOCKER_COMPOSE_VERSION=2.27.0
 # https://github.com/docker/buildx/releases
-ARG DOCKER_BUILDX_VERSION=0.11.2
+ARG DOCKER_BUILDX_VERSION=0.14.0
 
 USER root
 WORKDIR /root
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/other/scripts/get-subs.php b/other/scripts/get-subs.php
new file mode 100644
index 000000000..3a23fc073
--- /dev/null
+++ b/other/scripts/get-subs.php
@@ -0,0 +1,11 @@
+$handle = fopen("/tmp/export.csv", "w");
+App\Models\Team::chunk(100, function ($teams) use ($handle) {
+  foreach ($teams as $team) {
+    if ($team->subscription->stripe_invoice_paid == true) {
+      foreach ($team->members as $member) {
+        fputcsv($handle, [$member->email, $member->name], ",");
+      }
+    }
+  }
+});
+fclose($handle);
diff --git a/public/svgs/listmonk.svg b/public/svgs/listmonk.svg
new file mode 100644
index 000000000..a4e5efd5f
--- /dev/null
+++ b/public/svgs/listmonk.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/public/svgs/twenty.svg b/public/svgs/twenty.svg
new file mode 100644
index 000000000..eef3a382a
--- /dev/null
+++ b/public/svgs/twenty.svg
@@ -0,0 +1 @@
+
diff --git a/public/svgs/vikunja.svg b/public/svgs/vikunja.svg
new file mode 100644
index 000000000..53176d66e
--- /dev/null
+++ b/public/svgs/vikunja.svg
@@ -0,0 +1,12 @@
+
diff --git a/resources/css/app.css b/resources/css/app.css
index 1f218490d..cae83b0de 100644
--- a/resources/css/app.css
+++ b/resources/css/app.css
@@ -32,7 +32,7 @@ body {
     @apply block w-full py-1.5 rounded border-0 text-sm ring-1 ring-inset;
 }
 
-.input[type='password'] {
+.input[type="password"] {
     @apply pr-10;
 }
 
@@ -41,7 +41,7 @@ option {
 }
 
 .button {
-    @apply flex items-center justify-center gap-2 px-2 py-1 text-sm text-black normal-case border rounded 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-black hover:text-black disabled:cursor-not-allowed min-w-fit focus:outline-1 dark:disabled:text-neutral-600 disabled:border-none disabled:hover:bg-transparent disabled:bg-transparent disabled:text-neutral-300;
+    @apply flex items-center justify-center gap-2 px-2 py-1 text-sm text-black normal-case border rounded 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 focus:outline-1 dark:disabled:text-neutral-600 disabled:border-none disabled:hover:bg-transparent disabled:bg-transparent disabled:text-neutral-300;
 }
 
 button[isError]:not(:disabled) {
@@ -52,7 +52,6 @@ button[isHighlighted]:not(:disabled) {
     @apply text-white bg-coollabs hover:bg-coollabs-100;
 }
 
-
 h1 {
     @apply text-2xl font-bold dark:text-white;
 }
@@ -78,7 +77,7 @@ label {
 }
 
 table {
-    @apply min-w-full divide-y dark:divide-coolgray-200 divide-neutral-300 ;
+    @apply min-w-full divide-y dark:divide-coolgray-200 divide-neutral-300;
 }
 
 thead {
@@ -117,7 +116,7 @@ tr td:first-child {
     @apply flex items-center gap-2 text-error;
 }
 .tag {
-    @apply px-2 py-1 cursor-pointer box-description dark:bg-coolgray-100 dark:hover:bg-coolgray-300 bg-neutral-100 hover:bg-neutral-200
+    @apply px-2 py-1 cursor-pointer box-description dark:bg-coolgray-100 dark:hover:bg-coolgray-300 bg-neutral-100 hover:bg-neutral-200;
 }
 .add-tag {
     @apply flex items-center px-2 text-xs cursor-pointer dark:text-neutral-500/20 text-neutral-500 group-hover:text-neutral-700 group-hover:dark:text-white dark:hover:bg-coolgray-300 hover:bg-neutral-200;
@@ -135,7 +134,6 @@ tr td:first-child {
 
 .badge-absolute {
     @apply absolute top-0 right-0 w-2 h-2 border-none rounded-t-none rounded-r-none;
-
 }
 
 .badge-success {
@@ -159,7 +157,7 @@ tr td:first-child {
 }
 
 .menu-item {
-    @apply flex items-center w-full gap-3 py-1 pl-2 dark:hover:bg-coolgray-100 dark:hover:text-white hover:bg-neutral-300;
+    @apply flex items-center w-full gap-3 px-2 py-1 text-sm sm:pr-0 dark:hover:bg-coolgray-100 dark:hover:text-white hover:bg-neutral-300 min-w-fit sm:min-w-64;
 }
 
 .menu-item-active {
@@ -174,7 +172,6 @@ tr td:first-child {
     @apply w-6 h-6 dark:hover:text-white;
 }
 
-
 .scrollbar {
     @apply scrollbar-thumb-coollabs-100 dark:scrollbar-track-coolgray-200 scrollbar-track-neutral-200 scrollbar-w-2;
 }
@@ -188,7 +185,7 @@ tr td:first-child {
 }
 
 .navbar-main {
-    @apply flex items-center h-10 gap-6 pb-2 border-b-2 border-solid dark:border-coolgray-200;
+    @apply flex flex-col gap-4 pb-2 border-b-2 border-solid h-fit md:flex-row justify-items-start sm:justify-between dark:border-coolgray-200 md:items-center;
 }
 
 .loading {
@@ -203,20 +200,19 @@ tr td:first-child {
     @apply relative flex lg:flex-row flex-col p-2 transition-colors cursor-pointer min-h-[4rem] dark:bg-coolgray-100 bg-white border text-black dark:text-white hover:text-black border-neutral-200 dark:border-black hover:bg-neutral-100 dark:hover:bg-coollabs-100 dark:hover:text-white hover:no-underline;
 }
 .box-boarding {
-    @apply flex lg:flex-row flex-col p-2 transition-colors cursor-pointer min-h-[4rem] dark:bg-coolgray-100 dark:text-white bg-neutral-50 border border-neutral-200 dark:border-black hover:bg-neutral-100 dark:hover:bg-coollabs-100 dark:hover:text-white hover:text-black hover:no-underline text-black  ;
+    @apply flex lg:flex-row flex-col p-2 transition-colors cursor-pointer min-h-[4rem] dark:bg-coolgray-100 dark:text-white bg-neutral-50 border border-neutral-200 dark:border-black hover:bg-neutral-100 dark:hover:bg-coollabs-100 dark:hover:text-white hover:text-black hover:no-underline text-black;
 }
 .box-without-bg {
-    @apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem]   border border-neutral-200 dark:border-black;
+    @apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem] border border-neutral-200 dark:border-black;
 }
 .box-without-bg-without-border {
-    @apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem]   ;
+    @apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem];
 }
 
 .on-box {
     @apply rounded hover:bg-neutral-300 dark:hover:bg-coolgray-500/20;
 }
 
-
 .box-title {
     @apply font-bold text-black dark:text-white group-hover:dark:text-white;
 }
diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php
index f57d8c6fc..e04d3633d 100644
--- a/resources/views/auth/register.blade.php
+++ b/resources/views/auth/register.blade.php
@@ -4,8 +4,7 @@
             
                 Coolify
             
-            
{{ $description }}
+
+{{ $output }}
+
+
+Click [here]({{ $url }}) to view the task.
+Username should be