/home/$user is the customer's bind mount; they can plant symlinks in it. The
entrypoint ran as root and created/copied/chowned through customer paths (the
example-app copy, ecosystem.config.js generation + non-recursive chown, which
dereferences). Now: refuse to start if /home/$user is not a real dir; logs/ must
be a real dir and symlinks under it are removed and logged (nginx opens those
files as root); app/logs dirs, the example copy and ecosystem.config.js are
created AS THE CUSTOMER (setpriv, runuser fallback); the o+x directory pass runs
as the customer. chown -R is unchanged (GNU default -P never follows symlinks).
app/ itself may stay a symlink (release-dir deploys).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>