coolify/app/Actions/V5/Proxy/GenerateCaddyIngressConfiguration.php

114 lines
3.3 KiB
PHP
Raw Normal View History

2026-06-20 07:23:16 +00:00
<?php
namespace App\Actions\V5\Proxy;
use App\Models\V5\Application;
use App\Models\V5\ApplicationDomain;
use Illuminate\Support\Collection;
2026-06-20 07:23:16 +00:00
use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml;
class GenerateCaddyIngressConfiguration
{
use AsAction;
/**
* @param Collection<int, Application>|null $applications
* @return array{compose: string, caddyfile: string, apps: array<int, array{name: string, caddyfile: string}>}
2026-06-20 07:23:16 +00:00
*/
public function handle(?Collection $applications = null): array
2026-06-20 07:23:16 +00:00
{
return [
'compose' => $this->compose(),
'caddyfile' => $this->rootCaddyfile(),
'apps' => $this->appCaddyfiles($applications ?? collect()),
];
}
private function compose(): string
{
return Yaml::dump([
2026-06-20 07:23:16 +00:00
'services' => [
'caddy' => [
'image' => 'docker.io/library/caddy:2-alpine',
'container_name' => 'coolify-v5-caddy',
'restart' => 'unless-stopped',
'ports' => [
'80:80',
],
'volumes' => [
'./Caddyfile:/etc/caddy/Caddyfile:ro',
'./apps:/etc/caddy/apps:ro',
2026-06-20 07:23:16 +00:00
'./data:/data',
'./config:/config',
],
],
],
], 8, 2);
}
2026-06-20 07:23:16 +00:00
private function rootCaddyfile(): string
{
return <<<'CADDY'
2026-06-20 07:23:16 +00:00
:80 {
respond /coolify-health 200
respond 404
}
import apps/*.caddy
2026-06-20 07:23:16 +00:00
CADDY;
}
2026-06-20 07:23:16 +00:00
/**
* @param Collection<int, Application> $applications
* @return array<int, array{name: string, caddyfile: string}>
*/
private function appCaddyfiles(Collection $applications): array
{
return $applications
->each(fn (Application $application) => $application->loadMissing('domains'))
->map(fn (Application $application) => [
'name' => $this->appFileName($application),
'caddyfile' => $this->applicationCaddyfile($application),
])
->filter(fn (array $file) => $file['caddyfile'] !== '')
->sortBy('name')
->values()
->all();
}
private function applicationCaddyfile(Application $application): string
{
if (! $application->ingress_enabled || ! $application->internal_port) {
return '';
}
return $application->domains
->map(fn (ApplicationDomain $domain) => $this->applicationRoute($application, $domain))
->filter()
->sort()
->implode("\n\n");
}
private function applicationRoute(Application $application, ApplicationDomain $domain): ?string
{
if ($domain->domain === '') {
return null;
}
$namespace = $application->mesh_namespace ?: 'default';
$upstream = "{$application->container_name}.{$namespace}.coolify.internal:{$application->internal_port}";
return implode("\n", [
"http://{$domain->domain} {",
" reverse_proxy {$upstream}",
'}',
]);
}
private function appFileName(Application $application): string
{
return 'app_'.$application->getKey();
2026-06-20 07:23:16 +00:00
}
}