fix(realtime): preserve proxy routing and browser port settings

Keep the coolify-realtime network alias for existing proxy upstreams, stop overriding PUSHER_PORT, and bind the terminal to port 6002 across production and Windows Compose files. Add regression coverage for these settings.
This commit is contained in:
Andras Bacsai
2026-09-25 08:24:35 +02:00
parent a86188f391
commit 0f41b8e6d9
5 changed files with 59 additions and 11 deletions
+7 -3
View File
@@ -19,18 +19,22 @@ services:
- PHP_FPM_PM_START_SERVERS=${PHP_FPM_PM_START_SERVERS:-1}
- PHP_FPM_PM_MIN_SPARE_SERVERS=${PHP_FPM_PM_MIN_SPARE_SERVERS:-1}
- PHP_FPM_PM_MAX_SPARE_SERVERS=${PHP_FPM_PM_MAX_SPARE_SERVERS:-10}
- PUSHER_PORT=${PUSHER_PORT:-6001}
- PUSHER_BACKEND_PORT=${PUSHER_BACKEND_PORT:-6001}
env_file:
- /data/coolify/source/.env
ports:
- "${APP_PORT:-8000}:8080"
- "${REVERB_PORT:-${SOKETI_PORT:-6001}}:6001"
- "${TERMINAL_PORT:-6002}:6002"
- "6002:6002"
expose:
- "${APP_PORT:-8000}"
- "6001"
- "${TERMINAL_PORT:-6002}"
- "6002"
networks:
coolify:
# Realtime ran in the coolify-realtime container before 4.4; keep the name for existing proxy upstreams.
aliases:
- coolify-realtime
healthcheck:
test: curl --fail http://127.0.0.1:8080/api/health && curl --fail http://127.0.0.1:${PUSHER_BACKEND_PORT:-6001}/up || exit 1
interval: 5s
+2 -2
View File
@@ -52,11 +52,11 @@ services:
ports:
- "${APP_PORT:-8000}:8080"
- "${REVERB_PORT:-${SOKETI_PORT:-6001}}:6001"
- "${TERMINAL_PORT:-6002}:6002"
- "6002:6002"
expose:
- "${APP_PORT:-8000}"
- "6001"
- "${TERMINAL_PORT:-6002}"
- "6002"
healthcheck:
test: curl --fail http://localhost:8080/api/health && curl --fail http://localhost:${PUSHER_BACKEND_PORT:-6001}/up || exit 1
interval: 5s
+7 -3
View File
@@ -19,18 +19,22 @@ services:
- PHP_FPM_PM_START_SERVERS=${PHP_FPM_PM_START_SERVERS:-1}
- PHP_FPM_PM_MIN_SPARE_SERVERS=${PHP_FPM_PM_MIN_SPARE_SERVERS:-1}
- PHP_FPM_PM_MAX_SPARE_SERVERS=${PHP_FPM_PM_MAX_SPARE_SERVERS:-10}
- PUSHER_PORT=${PUSHER_PORT:-6001}
- PUSHER_BACKEND_PORT=${PUSHER_BACKEND_PORT:-6001}
env_file:
- /data/coolify/source/.env
ports:
- "${APP_PORT:-8000}:8080"
- "${REVERB_PORT:-${SOKETI_PORT:-6001}}:6001"
- "${TERMINAL_PORT:-6002}:6002"
- "6002:6002"
expose:
- "${APP_PORT:-8000}"
- "6001"
- "${TERMINAL_PORT:-6002}"
- "6002"
networks:
coolify:
# Realtime ran in the coolify-realtime container before 4.4; keep the name for existing proxy upstreams.
aliases:
- coolify-realtime
healthcheck:
test: curl --fail http://127.0.0.1:8080/api/health && curl --fail http://127.0.0.1:${PUSHER_BACKEND_PORT:-6001}/up || exit 1
interval: 5s
+2 -2
View File
@@ -51,11 +51,11 @@ services:
ports:
- "${APP_PORT:-8000}:8080"
- "${REVERB_PORT:-${SOKETI_PORT:-6001}}:6001"
- "${TERMINAL_PORT:-6002}:6002"
- "6002:6002"
expose:
- "${APP_PORT:-8000}"
- "6001"
- "${TERMINAL_PORT:-6002}"
- "6002"
healthcheck:
test: curl --fail http://localhost:8080/api/health && curl --fail http://localhost:${PUSHER_BACKEND_PORT:-6001}/up || exit 1
interval: 5s
@@ -1,6 +1,9 @@
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Request as RequestFacade;
use Illuminate\Support\Str;
use Symfony\Component\Yaml\Yaml;
it('uses Reverb as the first-party broadcast server', function () {
expect(file_get_contents(base_path('composer.json')))
@@ -117,8 +120,10 @@ it('runs Reverb and terminal websocket services inside the Coolify containers',
it('removes the dedicated realtime service from bundled compose files', function (string $composeFile, bool $hasRuntimeEnvironment) {
$composeContents = file_get_contents(base_path($composeFile));
// Production keeps "coolify-realtime" only as a network alias of the coolify container.
expect($composeContents)
->not->toContain('coolify-realtime')
->not->toContain('container_name: coolify-realtime')
->not->toContain('coolify-realtime:')
->not->toContain('soketi:')
->not->toContain('SOKETI_DEFAULT_APP_ID')
->toContain('6001')
@@ -263,6 +268,41 @@ it('stops publishing or preserving the obsolete realtime image', function () {
->not->toContain('| Realtime');
});
it('keeps 4.3.23 realtime setups working with the production compose files', function (string $composeFile) {
$coolify = Yaml::parseFile(base_path($composeFile))['services']['coolify'];
// The browser port comes only from .env (for example PUSHER_PORT=443 for Cloudflare Tunnel).
expect(collect($coolify['environment'])->filter(fn (string $entry) => Str::startsWith($entry, 'PUSHER_PORT')))->toBeEmpty()
->and($coolify['networks']['coolify']['aliases'])->toContain('coolify-realtime')
->and($coolify['ports'])->toContain('6002:6002')
->and(implode("\n", [...$coolify['ports'], ...$coolify['expose']]))->not->toContain('TERMINAL_PORT');
})->with([
'production compose' => ['docker-compose.prod.yml'],
'nightly production compose' => ['other/nightly/docker-compose.prod.yml'],
]);
it('keeps TERMINAL_PORT browser-only in the Windows compose files', function (string $composeFile) {
$coolify = Yaml::parseFile(base_path($composeFile))['services']['coolify'];
expect($coolify['ports'])->toContain('6002:6002')
->and(implode("\n", [...$coolify['ports'], ...$coolify['expose']]))->not->toContain('TERMINAL_PORT');
})->with([
'windows compose' => ['docker-compose.windows.yml'],
'nightly windows compose' => ['other/nightly/docker-compose.windows.yml'],
]);
it('resolves the browser websocket port like 4.3.23', function (string $pageUrl, ?string $pusherPort, ?string $expectedPort) {
config()->set('constants.pusher.port', $pusherPort);
RequestFacade::swap(Request::create($pageUrl));
expect(getRealtime())->toBe($expectedPort);
})->with([
'https domain through the Coolify proxy' => ['https://coolify.example.com/', null, null],
'https domain with an empty PUSHER_PORT' => ['https://coolify.example.com/', '', null],
'direct IP and port access' => ['http://203.0.113.10:8000/', null, '6001'],
'Cloudflare Tunnel guide' => ['https://coolify.example.com/', '443', '443'],
]);
it('uses current Reverb and terminal names in development tooling', function () {
expect(file_get_contents(base_path('scripts/dev-instances')))
->toContain('"REVERB" "TERMINAL"')