From 1b6513f0fbb70006348bc6541ac9e43a318d5dab Mon Sep 17 00:00:00 2001 From: ignacionelson Date: Fri, 21 Aug 2026 12:03:23 -0300 Subject: [PATCH] Stop container detection from taking the dashboard down on shared hosting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deciding which update instructions to print starts with asking whether we are running in a container, and that question is asked by looking for the file a container runtime leaves in the root of the filesystem. Shared hosting confines PHP to the webspace with open_basedir, where looking outside it is a warning rather than a false — and the framework's error handler turns warnings into exceptions, so the probe threw instead of answering. The dashboard is the one page that asks, so it returned a 500 while everything else worked (#1663). Suppress both probes. A host that keeps PHP inside a single directory is not our published image, so false is the right answer as well as the surviving one, and it lands on the manual instructions that shared hosting wants anyway. Checking ini_get('open_basedir') instead would get a hardened container wrong in the other direction, handing the manual sequence to someone whose files are inside an image. The dashboard was only the first symptom. updateNotice() reaches the same call on every Inertia response once a newer release exists, and RunningCodeState reaches it whenever the applied and running versions disagree — so the next release, or the host's next update attempt, would have taken every page rather than one. --- CHANGELOG.md | 12 ++++++++++++ app/Modules/Platform/Installation/Installation.php | 11 ++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2dc787aa..9061bd2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,18 @@ Anything under **Upgrade notes** is something you have to do, not something we d This section collects changes as they land; the release process turns it into a numbered entry when a version is cut. +### Fixed + +- **The dashboard no longer fails on shared hosting.** To decide which update instructions to print, + ProjectSend asks whether it is running inside a container by looking for a file in the root of the + filesystem. On shared hosting PHP is usually confined to your own directory, and looking outside it + is treated as an error rather than as a "no" — so the one page that asks the question, the + dashboard, returned a 500 while every other page worked. It now takes the restriction as the answer + it always was: a server that keeps PHP inside a single directory is not our container image, and + gets the manual update instructions, which is correct for shared hosting anyway. Nothing to change + on your side, and no setting you would have been able to change if there were. + ([#1663](https://github.com/projectsend/projectsend/issues/1663)) + ## 2.1.0 — 18 August 2026 Updating, mostly. ProjectSend now tells you when there is a new version, ends an update somewhere diff --git a/app/Modules/Platform/Installation/Installation.php b/app/Modules/Platform/Installation/Installation.php index 7ccb88e2..d3a5b9ef 100644 --- a/app/Modules/Platform/Installation/Installation.php +++ b/app/Modules/Platform/Installation/Installation.php @@ -43,6 +43,15 @@ class Installation protected function inContainer(): bool { // Docker writes the first; Podman writes the second. - return file_exists('/.dockerenv') || file_exists('/run/.containerenv'); + // + // Suppressed, and it has to stay that way. Shared hosting sets + // open_basedir to the webspace, and probing a path outside it is a + // warning rather than a false — which the framework's error handler + // turns into an exception, so the one call that asks which install + // this is took the whole dashboard down with it (#1663). Under `@` + // the warning is filtered and the probe answers false, which is the + // right answer anyway: a host that restricts PHP to a vhost + // directory is not the container image. + return @file_exists('/.dockerenv') || @file_exists('/run/.containerenv'); } }