Merge pull request #5060 from coollabsio/next

v4.0.0-beta.392
This commit is contained in:
Andras Bacsai
2025-02-13 10:41:40 +01:00
committed by GitHub
29 changed files with 108 additions and 72 deletions

View File

@@ -67,7 +67,7 @@ Special thanks to our biggest sponsors!
* [Juxtdigital](https://juxtdigital.dev/?ref=coolify.io) - A digital agency offering web development, design, and digital marketing services for businesses.
* [Saasykit](https://saasykit.com/?ref=coolify.io) - A Laravel-based boilerplate providing essential components and features for building SaaS applications quickly.
* [Massivegrid](https://massivegrid.com/?ref=coolify.io) - A cloud hosting provider offering scalable infrastructure solutions for businesses of all sizes.
* [LiquidWeb](https://liquidweb.com/?utm_source=coolify.io) - Fast web hosting provider.
* [LiquidWeb](https://liquidweb.com/?utm_source=coolify.io) - A Fast web hosting provider.
## Github Sponsors ($40+)

View File

@@ -253,6 +253,9 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
return;
}
try {
// Make sure the private key is stored in the filesystem
$this->server->privateKey->storeInFileSystem();
// Generate custom host<->ip mapping
$allContainers = instant_remote_process(["docker network inspect {$this->destination->network} -f '{{json .Containers}}' "], $this->server);
@@ -2281,7 +2284,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
} else {
if ($this->use_build_server) {
$this->execute_remote_command(
["{$this->coolify_variables} docker compose --project-name {$this->application->uuid} --project-directory {$this->configuration_dir} -f {$this->configuration_dir}{$this->docker_compose_location} up --build -d", 'hidden' => true],
["{$this->coolify_variables} docker compose --project-name {$this->application->uuid} --project-directory {$this->configuration_dir} -f {$this->configuration_dir}{$this->docker_compose_location} up --pull always --build -d", 'hidden' => true],
);
} else {
$this->execute_remote_command(

View File

@@ -24,6 +24,7 @@ class SendMessageToSlackJob implements ShouldQueue
public function handle(): void
{
Http::post($this->webhookUrl, [
'text' => $this->message->title,
'blocks' => [
[
'type' => 'section',

View File

@@ -53,13 +53,13 @@ class DeploymentNavbar extends Component
public function cancel()
{
$kill_command = "docker rm -f {$this->application_deployment_queue->deployment_uuid}";
$build_server_id = $this->application_deployment_queue->build_server_id;
$build_server_id = $this->application_deployment_queue->build_server_id ?? $this->application->destination->server_id;
$server_id = $this->application_deployment_queue->server_id ?? $this->application->destination->server_id;
try {
if ($this->application->settings->is_build_server_enabled) {
$server = Server::find($build_server_id);
$server = Server::ownedByCurrentTeam()->find($build_server_id);
} else {
$server = Server::find($server_id);
$server = Server::ownedByCurrentTeam()->find($server_id);
}
if ($this->application_deployment_queue->logs) {
$previous_logs = json_decode($this->application_deployment_queue->logs, associative: true, flags: JSON_THROW_ON_ERROR);

View File

@@ -33,17 +33,30 @@ class GithubApp extends BaseModel
public static function ownedByCurrentTeam()
{
return GithubApp::whereTeamId(currentTeam()->id);
return GithubApp::where(function ($query) {
$query->where('team_id', currentTeam()->id)
->orWhere('is_system_wide', true);
});
}
public static function public()
{
return GithubApp::whereTeamId(currentTeam()->id)->whereisPublic(true)->whereNotNull('app_id')->get();
return GithubApp::where(function ($query) {
$query->where(function ($q) {
$q->where('team_id', currentTeam()->id)
->orWhere('is_system_wide', true);
})->where('is_public', true);
})->whereNotNull('app_id')->get();
}
public static function private()
{
return GithubApp::whereTeamId(currentTeam()->id)->whereisPublic(false)->whereNotNull('app_id')->get();
return GithubApp::where(function ($query) {
$query->where(function ($q) {
$q->where('team_id', currentTeam()->id)
->orWhere('is_system_wide', true);
})->where('is_public', false);
})->whereNotNull('app_id')->get();
}
public function team()

View File

@@ -43,8 +43,18 @@ class S3Storage extends BaseModel
public function testConnection(bool $shouldSave = false)
{
try {
set_s3_target($this);
Storage::disk('custom-s3')->files();
$disk = Storage::build([
'driver' => 's3',
'region' => $this['region'],
'key' => $this['key'],
'secret' => $this['secret'],
'bucket' => $this['bucket'],
'endpoint' => $this['endpoint'],
'use_path_style_endpoint' => true,
]);
// Test the connection by listing files with ListObjectsV2 (S3)
$disk->files();
$this->unusable_email_sent = false;
$this->is_usable = true;
} catch (\Throwable $e) {
@@ -53,13 +63,14 @@ class S3Storage extends BaseModel
$mail = new MailMessage;
$mail->subject('Coolify: S3 Storage Connection Error');
$mail->view('emails.s3-connection-error', ['name' => $this->name, 'reason' => $e->getMessage(), 'url' => route('storage.show', ['storage_uuid' => $this->uuid])]);
$users = collect([]);
$members = $this->team->members()->get();
foreach ($members as $user) {
if ($user->isAdmin()) {
$users->push($user);
}
}
// Load the team with its members and their roles explicitly
$team = $this->team()->with(['members' => function ($query) {
$query->withPivot('role');
}])->first();
// Get admins directly from the pivot relationship for this specific team
$users = $team->members()->wherePivotIn('role', ['admin', 'owner'])->get(['users.id', 'users.email']);
foreach ($users as $user) {
send_user_an_email($mail, $user->email);
}

View File

@@ -248,15 +248,17 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, Sen
{
$sources = collect([]);
$github_apps = GithubApp::where(function ($query) {
$query->where('team_id', $this->id)
->Where('is_public', false)
->orWhere('is_system_wide', true);
$query->where(function ($q) {
$q->where('team_id', $this->id)
->orWhere('is_system_wide', true);
})->where('is_public', false);
})->get();
$gitlab_apps = GitlabApp::where(function ($query) {
$query->where('team_id', $this->id)
->Where('is_public', false)
->orWhere('is_system_wide', true);
$query->where(function ($q) {
$q->where('team_id', $this->id)
->orWhere('is_system_wide', true);
})->where('is_public', false);
})->get();
return $sources->merge($github_apps)->merge($gitlab_apps);

View File

@@ -80,7 +80,7 @@ class HighDiskUsage extends CustomEmailNotification
$description .= "Tips for cleanup: https://coolify.io/docs/knowledge-base/server/automated-cleanup\n";
$description .= "Change settings:\n";
$description .= '- Threshold: '.base_url().'/server/'.$this->server->uuid."#advanced\n";
$description .= '- Notifications: '.base_url().'/notifications/discord';
$description .= '- Notifications: '.base_url().'/notifications/slack';
return new SlackMessage(
title: 'High disk usage detected',

View File

@@ -1,17 +0,0 @@
<?php
use App\Models\S3Storage;
function set_s3_target(S3Storage $s3)
{
config()->set('filesystems.disks.custom-s3', [
'driver' => 's3',
'region' => $s3['region'],
'key' => $s3['key'],
'secret' => $s3['secret'],
'bucket' => $s3['bucket'],
'endpoint' => $s3['endpoint'],
'use_path_style_endpoint' => true,
'aws_url' => $s3->awsUrl(),
]);
}

View File

@@ -2,7 +2,7 @@
return [
'coolify' => [
'version' => '4.0.0-beta.391',
'version' => '4.0.0-beta.392',
'helper_version' => '1.0.6',
'realtime_version' => '1.0.5',
'self_hosted' => env('SELF_HOSTED', true),

View File

@@ -1,5 +1,6 @@
{
"auth.login": "تسجيل الدخول",
"auth.login.authentik": "تسجيل الدخول باستخدام Authentik",
"auth.login.azure": "تسجيل الدخول باستخدام Microsoft",
"auth.login.bitbucket": "تسجيل الدخول باستخدام Bitbucket",
"auth.login.github": "تسجيل الدخول باستخدام GitHub",
@@ -34,5 +35,6 @@
"resource.delete_volumes": "حذف جميع المجلدات والملفات المرتبطة بهذا المورد بشكل دائم.",
"resource.delete_connected_networks": "حذف جميع الشبكات غير المحددة مسبقًا والمرتبطة بهذا المورد بشكل دائم.",
"resource.delete_configurations": "حذف جميع ملفات التعريف من الخادم بشكل دائم.",
"database.delete_backups_locally": "حذف كافة النسخ الاحتياطية نهائيًا من التخزين المحلي."
"database.delete_backups_locally": "حذف كافة النسخ الاحتياطية نهائيًا من التخزين المحلي.",
"warning.sslipdomain": "تم حفظ ملفات التعريف الخاصة بك، ولكن استخدام نطاق sslip مع https <span class='dark:text-red-500 text-red-500 font-bold'>غير</span> مستحسن، لأن خوادم Let's Encrypt مع هذا النطاق العام محدودة المعدل (ستفشل عملية التحقق من شهادة SSL). <br><br>استخدم نطاقك الخاص بدلاً من ذلك."
}

View File

@@ -1,5 +1,6 @@
{
"auth.login": "Connexion",
"auth.login.authentik": "Connexion avec Authentik",
"auth.login.azure": "Connexion avec Microsoft",
"auth.login.bitbucket": "Connexion avec Bitbucket",
"auth.login.github": "Connexion avec GitHub",
@@ -34,5 +35,6 @@
"resource.delete_volumes": "Supprimer définitivement tous les volumes associés à cette ressource.",
"resource.delete_connected_networks": "Supprimer définitivement tous les réseaux non-prédéfinis associés à cette ressource.",
"resource.delete_configurations": "Supprimer définitivement tous les fichiers de configuration du serveur.",
"database.delete_backups_locally": "Toutes les sauvegardes seront définitivement supprimées du stockage local."
"database.delete_backups_locally": "Toutes les sauvegardes seront définitivement supprimées du stockage local.",
"warning.sslipdomain": "Votre configuration est enregistrée, mais l'utilisation du domaine sslip avec https <span class='dark:text-red-500 text-red-500 font-bold'>N'EST PAS</span> recommandée, car les serveurs Let's Encrypt avec ce domaine public sont limités en taux (la validation du certificat SSL échouera). <br><br>Utilisez plutôt votre propre domaine."
}

View File

@@ -1,5 +1,6 @@
{
"auth.login": "Accedi",
"auth.login.authentik": "Accedi con Authentik",
"auth.login.azure": "Accedi con Microsoft",
"auth.login.bitbucket": "Accedi con Bitbucket",
"auth.login.github": "Accedi con GitHub",
@@ -27,5 +28,13 @@
"input.code": "Codice monouso",
"input.recovery_code": "Codice di recupero",
"button.save": "Salva",
"repository.url": "<span class='text-helper'>Esempi</span><br>Per i repository pubblici, utilizza <span class='text-helper'>https://...</span>.<br>Per i repository privati, utilizza <span class='text-helper'>git@...</span>.<br><br>https://github.com/coollabsio/coolify-examples verrà selezionato il branch <span class='text-helper'>main</span><br>https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify verrà selezionato il branch <span class='text-helper'>nodejs-fastify</span>.<br>https://gitea.com/sedlav/expressjs.git verrà selezionato il branch <span class='text-helper'>main</span>.<br>https://gitlab.com/andrasbacsai/nodejs-example.git verrà selezionato il branch <span class='text-helper'>main</span>."
"repository.url": "<span class='text-helper'>Esempi</span><br>Per i repository pubblici, utilizza <span class='text-helper'>https://...</span>.<br>Per i repository privati, utilizza <span class='text-helper'>git@...</span>.<br><br>https://github.com/coollabsio/coolify-examples verrà selezionato il branch <span class='text-helper'>main</span><br>https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify verrà selezionato il branch <span class='text-helper'>nodejs-fastify</span>.<br>https://gitea.com/sedlav/expressjs.git verrà selezionato il branch <span class='text-helper'>main</span>.<br>https://gitlab.com/andrasbacsai/nodejs-example.git verrà selezionato il branch <span class='text-helper'>main</span>.",
"service.stop": "Questo servizio verrà arrestato.",
"resource.docker_cleanup": "Esegui pulizia Docker (rimuove immagini non utilizzate e cache del builder).",
"resource.non_persistent": "Tutti i dati non persistenti verranno eliminati.",
"resource.delete_volumes": "Elimina definitivamente tutti i volumi associati a questa risorsa.",
"resource.delete_connected_networks": "Elimina definitivamente tutte le reti non predefinite associate a questa risorsa.",
"resource.delete_configurations": "Elimina definitivamente tutti i file di configurazione dal server.",
"database.delete_backups_locally": "Tutti i backup verranno eliminati definitivamente dall'archiviazione locale.",
"warning.sslipdomain": "La tua configurazione è stata salvata, ma il dominio sslip con https <span class='dark:text-red-500 text-red-500 font-bold'>NON</span> è raccomandato, poiché i server di Let's Encrypt con questo dominio pubblico hanno limitazioni di frequenza (la convalida del certificato SSL fallirà). <br><br>Utilizza invece il tuo dominio personale."
}

View File

@@ -26,7 +26,7 @@
@endphp
@if ($showUnhealthyHelper)
<x-helper
helper="Unhealthy state. <span class='dark:text-warning text-coollabs'>This doesn't mean that the resource is malfunctioning.</span><br><br>- If the resource is accessible, it indicates that no health check is configured - it is not mandatory.<br>- If the resource is not accessible (returning 404 or 503), it may indicate that a health check is needed and has not passed. <span class='dark:text-warning text-coollabs'>Your action is required.</span><br><br>More details in the <a href='https://coolify.io/docs/knowledge-base/traefik/healthcheck/' class='underline dark:text-warning text-coollabs' target='_blank'>documentation</a>.">
helper="Unhealthy state. <span class='dark:text-warning text-coollabs'>This doesn't mean that the resource is malfunctioning.</span><br><br>- If the resource is accessible, it indicates that no health check is configured - it is not mandatory.<br>- If the resource is not accessible (returning 404 or 503), it may indicate that a health check is needed and has not passed. <span class='dark:text-warning text-coollabs'>Your action is required.</span><br><br>More details in the <a href='https://coolify.io/docs/knowledge-base/proxy/traefik/healthchecks' class='underline dark:text-warning text-coollabs' target='_blank'>documentation</a>.">
<x-slot:icon>
<svg class="hidden w-4 h-4 dark:text-warning lg:block" viewBox="0 0 256 256"
xmlns="http://www.w3.org/2000/svg">

View File

@@ -23,7 +23,7 @@
if (checkNumber > 5) {
this.popups.realtime = true;
console.error(
'Coolify could not connect to its real-time service. This will cause unusual problems on the UI if not fixed! Please check the related documentation (https://coolify.io/docs/knowledge-base/cloudflare/tunnels) or get help on Discord (https://coollabs.io/discord).)'
'Coolify could not connect to its real-time service. This will cause unusual problems on the UI if not fixed! Please check the related documentation (https://coolify.io/docs/knowledge-base/cloudflare/tunnels/overview) or get help on Discord (https://coollabs.io/discord).)'
);
}

View File

@@ -108,16 +108,16 @@
<div id="logs" class="flex flex-col font-mono">
@forelse ($this->logLines as $line)
<div @class([
'mt-2' => $line['command'] ?? false,
'mt-2' => isset($line['command']) && $line['command'],
'flex gap-2 dark:hover:bg-coolgray-500 hover:bg-gray-100',
])>
<span x-show="showTimestamps" class="shrink-0 text-gray-500">{{ $line['timestamp'] }}</span>
<span @class([
'text-coollabs dark:text-warning' => $line['hidden'],
'text-red-500' => $line['stderr'],
'font-bold' => $line['command'] ?? false,
'font-bold' => isset($line['command']) && $line['command'],
'whitespace-pre-wrap',
])>{!! $line['line'] !!}</span>
])>{!! (isset($line['command']) && $line['command'] ? '[CMD]: ' : '') . trim($line['line']) !!}</span>
</div>
@empty
<span class="font-mono text-neutral-400 mb-2">No logs yet.</span>

View File

@@ -31,7 +31,7 @@
then you should validate the server.
<br /><br />
For more information, please read our <a
href="https://coolify.io/docs/knowledge-base/cloudflare/tunnels/" target="_blank"
href="https://coolify.io/docs/knowledge-base/cloudflare/tunnels/overview" target="_blank"
class="font-medium underline hover:text-yellow-600 dark:hover:text-yellow-200">documentation</a>.
</div>
@endif

View File

@@ -1,6 +1,6 @@
<form wire:submit.prevent='submit' class="flex flex-col gap-2 w-full">
<x-forms.input id="cloudflare_token" required label="Cloudflare Token" type="password" />
<x-forms.input id="ssh_domain" label="Configured SSH Domain" required
helper="The SSH domain you configured in Cloudflare. Make sure there is no protocol like http(s):// so you provide a FQDN not a URL. <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/cloudflare/tunnels/#automated' target='_blank'>Documentation</a>" />
helper="The SSH domain you configured in Cloudflare. Make sure there is no protocol like http(s):// so you provide a FQDN not a URL. <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/cloudflare/tunnels/server-ssh' target='_blank'>Documentation</a>" />
<x-forms.button type="submit" isHighlighted @click="modalOpen=false">Continue</x-forms.button>
</form>

View File

@@ -1,6 +1,6 @@
<div class="w-full">
<div class="mb-4">For more details, please visit the <a class="underline dark:text-warning"
href="https://coolify.io/docs/knowledge-base/s3" target="_blank">Coolify Docs</a>.</div>
href="https://coolify.io/docs/knowledge-base/s3/introduction" target="_blank">Coolify Docs</a>.</div>
<form class="flex flex-col gap-2" wire:submit='submit'>
<div class="flex gap-2">
<x-forms.input required label="Name" id="name" />

View File

@@ -22,7 +22,7 @@
'If the storage location is in use by any backup jobs those backup jobs will only store the backup locally on the server.',
]" confirmationText="{{ $storage->name }}"
confirmationLabel="Please confirm the execution of the actions by entering the Storage Name below"
shortConfirmationLabel="Storage Name" :confirmWithPassword="false" step2ButtonText="Permanently Delet" />
shortConfirmationLabel="Storage Name" :confirmWithPassword="false" step2ButtonText="Permanently Delete" />
</div>
<div class="flex gap-2">
<x-forms.input label="Name" id="storage.name" />

View File

@@ -1,4 +1,4 @@
<div x-data="{ selected: 'monthly' }" class="w-full pb-20">
<div x-data="{ selected: 'monthly' }" class="w-full pb-20 pt-10">
<div class="px-6 mx-auto lg:px-8">
<div class="flex justify-center">
<fieldset

View File

@@ -27,7 +27,7 @@
<div>You can't delete your last / personal team.</div>
@elseif(currentTeam()->subscription)
<div>Please cancel your subscription <a class="underline dark:text-white"
href="{{ route('subscription.show') }}">here</a> before delete this team.</div>
href="{{ route('subscription.show') }}">here</a> before deleting this team.</div>
@else
@if (currentTeam()->isEmpty())
<div class="pb-4">This will delete your team. Beware! There is no coming back!</div>

View File

@@ -20,5 +20,4 @@ services:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- PORT=45876
# Public Key from "Add a new system" in the UI and restart the agent
# - KEY=""
- KEY=${KEY}

View File

@@ -1,4 +1,4 @@
# documentation: https://cal.com/docs
# documentation: https://cal.com/docs/developing/introduction
# slogan: Scheduling infrastructure for everyone.
# tags: calcom,calendso,scheduling,open,source
# logo: svgs/calcom.svg

View File

@@ -11,7 +11,9 @@ services:
- SERVICE_FQDN_DUPLICATI_8200
- PUID=1000
- PGID=1000
- TZ=Europe/Madrid
- TZ=${TZ:-Europe/London}
- SETTINGS_ENCRYPTION_KEY=${SERVICE_PASSWORD_ENCRYPT}
- DUPLICATI__WEBSERVICE_PASSWORD=${SERVICE_PASSWORD_WEB}
volumes:
- duplicati-config:/config
- duplicati-backups:/backups

View File

@@ -63,6 +63,15 @@ services:
- DISCORD_SERVER_ROLES=${DISCORD_SERVER_ROLES}
- PGSSLMODE=${PGSSLMODE:-disable}
- FORCE_HTTPS=${FORCE_HTTPS:-true}
- SMTP_HOST=${SMTP_HOST}
- SMTP_PORT=${SMTP_PORT}
- SMTP_USERNAME=${SMTP_USERNAME}
- SMTP_PASSWORD=${SMTP_PASSWORD}
- SMTP_FROM_EMAIL=${SMTP_FROM_EMAIL}
- SMTP_REPLY_EMAIL=${SMTP_REPLY_EMAIL}
- SMTP_TLS_CIPHERS=${SMTP_TLS_CIPHERS}
- SMTP_SECURE=${SMTP_SECURE}
- SMTP_NAME=${SMTP_NAME}
healthcheck:
disable: true

View File

@@ -20,7 +20,7 @@ services:
content: |
---
# For configuration options and examples, please see:
# https://gethomepage.dev/latest/configs/bookmarks
# https://gethomepage.dev/configs/bookmarks
- Developer:
- Github:
@@ -53,7 +53,7 @@ services:
content: |
---
# For configuration options and examples, please see:
# https://gethomepage.dev/latest/configs/docker/
# https://gethomepage.dev/configs/docker/
# my-docker:
# host: 127.0.0.1
@@ -75,7 +75,7 @@ services:
content: |
---
# For configuration options and examples, please see:
# https://gethomepage.dev/latest/configs/services
# https://gethomepage.dev/configs/services
- My First Group:
- My First Service:
@@ -98,7 +98,7 @@ services:
content: |
---
# For configuration options and examples, please see:
# https://gethomepage.dev/latest/configs/settings
# https://gethomepage.dev/configs/settings
providers:
openweathermap: openweathermapapikey
@@ -110,7 +110,7 @@ services:
content: |
---
# For configuration options and examples, please see:
# https://gethomepage.dev/latest/configs/service-widgets
# https://gethomepage.dev/widgets/services
- resources:
cpu: true

File diff suppressed because one or more lines are too long

View File

@@ -1,10 +1,10 @@
{
"coolify": {
"v4": {
"version": "4.0.0-beta.391"
"version": "4.0.0-beta.392"
},
"nightly": {
"version": "4.0.0-beta.392"
"version": "4.0.0-beta.393"
},
"helper": {
"version": "1.0.6"