From 0134401f7cfc43326b3c899470d63a0ae86636aa Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Thu, 10 Sep 2026 09:24:37 +0200 Subject: [PATCH] fix(service): write compose .env files atomically via temp rename Replace direct .env overwrite with a unique temp file and mv so a partial write cannot leave a truncated environment file on disk. --- app/Models/Service.php | 6 +++--- tests/Unit/ServiceComposeConfigAtomicWriteTest.php | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 tests/Unit/ServiceComposeConfigAtomicWriteTest.php diff --git a/app/Models/Service.php b/app/Models/Service.php index 3b80a1941..e963571cb 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -1587,7 +1587,7 @@ public function saveComposeConfigs() Storage::disk('local')->delete("tmp/{$filename}"); $commands[] = "cd $workdir"; - $commands[] = 'rm -f .env || true'; + $environmentFilename = new_public_id().'.env.tmp'; $envs = collect([]); @@ -1618,10 +1618,10 @@ public function saveComposeConfigs() $envs->push("{$env->key}={$env->real_value}"); } if ($envs->count() === 0) { - $commands[] = 'touch .env'; + $commands[] = "touch {$environmentFilename} && mv {$environmentFilename} .env"; } else { $envs_base64 = base64_encode($envs->implode("\n")); - $commands[] = "echo '$envs_base64' | base64 -d | tee .env > /dev/null"; + $commands[] = "echo '$envs_base64' | base64 -d | tee {$environmentFilename} > /dev/null && mv {$environmentFilename} .env"; } instant_remote_process($commands, $this->server); diff --git a/tests/Unit/ServiceComposeConfigAtomicWriteTest.php b/tests/Unit/ServiceComposeConfigAtomicWriteTest.php new file mode 100644 index 000000000..ebe5d7b71 --- /dev/null +++ b/tests/Unit/ServiceComposeConfigAtomicWriteTest.php @@ -0,0 +1,14 @@ +not->toContain("'rm -f .env || true'") + ->toContain("new_public_id().'.env.tmp'") + ->toContain('tee {$environmentFilename} > /dev/null && mv {$environmentFilename} .env') + ->toContain('touch {$environmentFilename} && mv {$environmentFilename} .env'); +});