fix(server): keep ip and user as strings after save

Closes #12444

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andras BacsaiandClaude Opus 5.5 committed 2026-11-03 17:52:35 +01:00
1 parent 19f82b6e07
commit ed03a31b3a
3 files changed
+47 -2

No files matched your search

+1
View File
@@ -20,6 +20,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
- Save the update channel in **Settings > Updates** when you select **Preview** or **Nightly**. Before, the "Save changes" bar did not open for these channels, so the change was lost when you refreshed the page
- Save the healthcheck **Check type** when it is the only change. Before, the "Save changes" bar did not open when you changed only the check type, for example from **Container command** back to **HTTP request**
- Coolify Cloud: end a paid subscription that lost its link to Stripe when the customer cancels it. Before, it stayed active, and `cloud:sync-stripe-subscriptions` did not report it
- Keep the dashboard proxy configuration of a server with the IP `host.docker.internal` that is not the default localhost server. Before, Coolify did not see this server as localhost after it saved the server, for example after a proxy restart, and deleted `coolify.yaml`, so the dashboard was not reachable at its domain ([#12444](https://github.com/coollabsio/coolify/issues/12444))
## [v4.6.0] - 2026-11-02
+2 -2
View File
@@ -179,10 +179,10 @@ class Server extends BaseModel
static::saving(function ($server) {
$payload = [];
if ($server->user) {
$payload['user'] = str($server->user)->trim();
$payload['user'] = trim($server->user);
}
if ($server->ip) {
$payload['ip'] = str($server->ip)->trim();
$payload['ip'] = trim($server->ip);
// Update ip_previous when ip is being changed
if ($server->isDirty('ip') && $server->getOriginal('ip')) {
@@ -0,0 +1,44 @@
<?php
use App\Models\InstanceSettings;
use App\Models\PrivateKey;
use App\Models\Server;
use App\Models\Team;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Process;
uses(RefreshDatabase::class);
beforeEach(function () {
Server::flushIdentityMap();
Process::fake();
InstanceSettings::forceCreate(['id' => 0]);
$team = Team::factory()->create();
$privateKey = PrivateKey::factory()->create(['team_id' => $team->id]);
$this->server = Server::factory()->create([
'team_id' => $team->id,
'private_key_id' => $privateKey->id,
'ip' => ' host.docker.internal ',
'user' => ' root ',
]);
});
it('keeps ip and user as trimmed strings on the same instance after save', function () {
expect($this->server->id)->not->toBe(0)
->and($this->server->ip)->toBe('host.docker.internal')
->and($this->server->user)->toBe('root')
->and($this->server->isLocalhost())->toBeTrue();
$this->server->save();
expect($this->server->ip)->toBe('host.docker.internal')
->and($this->server->user)->toBe('root')
->and($this->server->isLocalhost())->toBeTrue();
});
it('returns the normalized ip after save, not the raw input', function () {
$this->server->update(['ip' => ' 2A01:04F8::0001 ']);
expect($this->server->ip)->toBe('2a01:4f8::1')
->and($this->server->fresh()->ip)->toBe('2a01:4f8::1');
});