mirror of
https://github.com/coollabsio/coolify.git
synced 2026-10-07 22:45:27 -04:00
- Servers with caddy-docker-proxy older than 2.9 show a warning on the Proxy page and the traffic analytics settings, with the fix. - Caddy 2.9+ images get the basic_auth label; older ones keep the deprecated basicauth, which Caddy 2.7 still needs. - Caddy mounts StartSentinel::trafficLogDirectory() as /traffic, so Caddy and Sentinel use the same access log, also in development. - The development data volume is configurable (DEV_COOLIFY_DATA_VOLUME, same default as before) and shared by Traefik, Caddy, and Sentinel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
109 lines
5.2 KiB
PHP
109 lines
5.2 KiB
PHP
<?php
|
|
|
|
use App\Enums\ProxyTypes;
|
|
use App\Models\Application;
|
|
use App\Models\ApplicationPreview;
|
|
use App\Models\Environment;
|
|
use App\Models\Project;
|
|
use App\Models\Server;
|
|
use App\Models\StandaloneDocker;
|
|
use App\Models\Team;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(fn () => Server::flushIdentityMap());
|
|
|
|
afterEach(fn () => Server::flushIdentityMap());
|
|
|
|
function basicAuthCaddyProxy(string $image, array $overrides = []): array
|
|
{
|
|
return array_merge([
|
|
'type' => ProxyTypes::CADDY->value,
|
|
'status' => 'running',
|
|
'last_saved_settings' => 'applied',
|
|
'last_applied_settings' => 'applied',
|
|
'last_saved_proxy_configuration' => "services:\n caddy:\n image: '{$image}'\n",
|
|
], $overrides);
|
|
}
|
|
|
|
function caddyBasicAuthLabel(iterable $labels): ?string
|
|
{
|
|
return collect($labels)->first(fn (string $label) => preg_match('/^caddy_\d+\.basic_?auth\./', $label) === 1);
|
|
}
|
|
|
|
it('uses the directive name that the Caddy version knows', function (bool $supportsBasicAuthDirective, string $directive) {
|
|
$labels = fqdnLabelsForCaddy('coolify', 'app-uuid', collect(['https://example.com']),
|
|
is_http_basic_auth_enabled: true,
|
|
http_basic_auth_username: 'admin',
|
|
http_basic_auth_password: 'secret',
|
|
supports_basic_auth_directive: $supportsBasicAuthDirective,
|
|
);
|
|
|
|
$label = caddyBasicAuthLabel($labels);
|
|
|
|
expect($label)->toStartWith("caddy_0.{$directive}.admin=\"")
|
|
->and(password_verify('secret', trim(str($label)->after('=')->value(), '"')))->toBeTrue();
|
|
})->with([
|
|
'Caddy 2.8+' => [true, 'basic_auth'],
|
|
'Caddy 2.7' => [false, 'basicauth'],
|
|
]);
|
|
|
|
it('keeps the deprecated directive by default', function () {
|
|
$labels = fqdnLabelsForCaddy('coolify', 'app-uuid', collect(['https://example.com']),
|
|
is_http_basic_auth_enabled: true,
|
|
http_basic_auth_username: 'admin',
|
|
http_basic_auth_password: 'secret',
|
|
);
|
|
|
|
expect(caddyBasicAuthLabel($labels))->toStartWith('caddy_0.basicauth.admin=');
|
|
});
|
|
|
|
it('uses basic_auth only when the saved Caddy image runs Caddy 2.8 or newer', function (array $proxy, bool $expected) {
|
|
$server = Server::factory()->make(['proxy' => $proxy]);
|
|
|
|
expect($server->caddySupportsBasicAuthDirective())->toBe($expected);
|
|
})->with([
|
|
'caddy-docker-proxy 2.8 (Caddy 2.7.6)' => [basicAuthCaddyProxy('lucaslorentz/caddy-docker-proxy:2.8-alpine'), false],
|
|
'caddy-docker-proxy 2.9' => [basicAuthCaddyProxy('lucaslorentz/caddy-docker-proxy:2.9'), true],
|
|
'caddy-docker-proxy 2.13' => [basicAuthCaddyProxy('lucaslorentz/caddy-docker-proxy:2.13-alpine'), true],
|
|
'latest tag' => [basicAuthCaddyProxy('lucaslorentz/caddy-docker-proxy:latest'), false],
|
|
'custom image' => [basicAuthCaddyProxy('caddy:2.11'), false],
|
|
'new image saved but not applied' => [basicAuthCaddyProxy('lucaslorentz/caddy-docker-proxy:2.13-alpine', ['last_saved_settings' => 'new']), false],
|
|
]);
|
|
|
|
it('emits the matching basic auth directive in application labels', function (string $image, bool $exactLabels, bool $preview, string $directive) {
|
|
$team = Team::factory()->create();
|
|
$environment = Environment::factory()->create(['project_id' => Project::factory()->create(['team_id' => $team->id])->id]);
|
|
$server = Server::factory()->create(['team_id' => $team->id, 'proxy' => basicAuthCaddyProxy($image)]);
|
|
$server->settings->update(['generate_exact_labels' => $exactLabels]);
|
|
$destination = StandaloneDocker::query()->where('server_id', $server->id)->firstOrFail();
|
|
$application = Application::factory()->createOne([
|
|
'environment_id' => $environment->id,
|
|
'destination_id' => $destination->id,
|
|
'destination_type' => $destination->getMorphClass(),
|
|
'fqdn' => 'https://example.com',
|
|
'is_http_basic_auth_enabled' => true,
|
|
'http_basic_auth_username' => 'admin',
|
|
'http_basic_auth_password' => 'secret',
|
|
]);
|
|
Server::flushIdentityMap();
|
|
|
|
$applicationPreview = $preview
|
|
? (new ApplicationPreview)->forceFill(['pull_request_id' => 7, 'fqdn' => 'https://pr-7.example.com'])
|
|
: null;
|
|
|
|
$label = caddyBasicAuthLabel(generateLabelsApplication($application->fresh(), $applicationPreview));
|
|
|
|
expect($label)->toStartWith("caddy_0.{$directive}.admin=\"");
|
|
})->with([
|
|
'caddy-docker-proxy 2.8, all proxies' => ['lucaslorentz/caddy-docker-proxy:2.8-alpine', false, false, 'basicauth'],
|
|
'caddy-docker-proxy 2.8, exact labels' => ['lucaslorentz/caddy-docker-proxy:2.8-alpine', true, false, 'basicauth'],
|
|
'caddy-docker-proxy 2.8, preview, all proxies' => ['lucaslorentz/caddy-docker-proxy:2.8-alpine', false, true, 'basicauth'],
|
|
'caddy-docker-proxy 2.8, preview, exact labels' => ['lucaslorentz/caddy-docker-proxy:2.8-alpine', true, true, 'basicauth'],
|
|
'caddy-docker-proxy 2.13, all proxies' => ['lucaslorentz/caddy-docker-proxy:2.13-alpine', false, false, 'basic_auth'],
|
|
'caddy-docker-proxy 2.13, exact labels' => ['lucaslorentz/caddy-docker-proxy:2.13-alpine', true, false, 'basic_auth'],
|
|
'caddy-docker-proxy 2.13, preview, all proxies' => ['lucaslorentz/caddy-docker-proxy:2.13-alpine', false, true, 'basic_auth'],
|
|
'caddy-docker-proxy 2.13, preview, exact labels' => ['lucaslorentz/caddy-docker-proxy:2.13-alpine', true, true, 'basic_auth'],
|
|
]);
|