From 4ca6d492e6a37cec0346f4bdc697378b9c881cd1 Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Sat, 9 May 2026 22:29:12 +0300 Subject: [PATCH] copy laravel app root instead of symlinking PHP's __DIR__ follows symlinks, so an artisan symlink at /var/lib/tide/app/artisan resolved back to the read only store path. That made every Laravel file path ultimately resolve into the store, including storage/logs/laravel.log and bootstrap/cache, which Laravel must be able to write. The redirected symlinks for those two subtrees never even got consulted because resolution happened upstream of them. Switch tide-prepare to copy the package contents into appRoot, then mount /var/lib/tide/state over storage/ and bootstrap/cache/ via symlinks out of a writable parent. Now __DIR__ resolves to the writable copy and Laravel can boot. --- nix/module.nix | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/nix/module.nix b/nix/module.nix index 2fa939f..d759468 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -139,29 +139,24 @@ in }; script = '' set -eu + + # Copy the immutable store package into a writable app root. + # Symlinking would defeat Laravel's __DIR__ based path + # resolution: PHP's __DIR__ follows symlinks back to the + # read only store, breaking storage/ and bootstrap/cache/ + # writes even when those subtrees are themselves symlinked + # into a writable state dir. rm -rf ${appRoot} mkdir -p ${appRoot} - for entry in ${cfg.backendPackage}/share/php/tide-backend/*; do - name="$(basename "$entry")" - case "$name" in - storage|bootstrap) - ;; - *) - ln -s "$entry" "${appRoot}/$name" - ;; - esac - done - # bootstrap dir: symlink everything from the store - # except cache/ which must be writable. - mkdir -p ${appRoot}/bootstrap - for entry in ${cfg.backendPackage}/share/php/tide-backend/bootstrap/*; do - name="$(basename "$entry")" - if [ "$name" != "cache" ]; then - ln -sf "$entry" "${appRoot}/bootstrap/$name" - fi - done - ln -sfn ${stateRoot}/bootstrap-cache ${appRoot}/bootstrap/cache + cp -rL ${cfg.backendPackage}/share/php/tide-backend/. ${appRoot}/ + chmod -R u+w ${appRoot} + + # Redirect the two mutable subtrees to /var/lib/tide/state + # so they survive activations and don't accumulate inside + # the disposable app root copy. + rm -rf ${appRoot}/storage ${appRoot}/bootstrap/cache ln -sfn ${stateRoot}/storage ${appRoot}/storage + ln -sfn ${stateRoot}/bootstrap-cache ${appRoot}/bootstrap/cache chown -R ${cfg.user}:${cfg.group} ${appRoot} ${stateRoot} '';