monitoring

When Astro Isn’t the Problem: Tracking Down a Plesk Deployment Mystery

For several hours I found myself chasing what appeared to be a collection of unrelated problems while trying to deploy an Astro website through Plesk.

At first glance, the symptoms suggested everything from broken Node.js installations to Astro build failures, missing npm binaries, permission problems, and even filesystem corruption. None of the errors seemed to point towards a single root cause.

As it turned out, Astro wasn’t the problem at all.

The Symptoms

The deployment environment was producing a wide variety of errors, including:

npm: command not found
find: command not found
dirname: command not found
whoami: command not found

At the same time, filesystem-related commands were also failing:

cd: /var/www/vhosts/... No such file or directory
ls: cannot access '/var/www': No such file or directory

What made this particularly confusing was that all of these commands worked perfectly when run manually over SSH.

Node.js added another layer of confusion. Sometimes node appeared to exist while npm was missing. Paths seemed inconsistent and Plesk’s Node.js integration behaved unpredictably.

Astro eventually began failing with permission-related errors such as:

EACCES: permission denied, rename ...

At this stage it looked as though several independent issues were occurring simultaneously.

The Real Cause

After a considerable amount of investigation, the actual problem turned out to be surprisingly simple.

The Plesk subscription user was running inside a restricted chroot shell environment.

This meant the deployment scripts were executing inside a limited filesystem rather than the same environment available through a normal shell session.

As a result:

  • Standard binaries were unavailable.
  • PATH values differed.
  • Filesystem visibility differed.
  • Runtime behaviour differed.
  • Deployment scripts and manual SSH sessions were effectively operating in two completely different environments.

The deployment system wasn’t seeing the same server that I was.

The Fix

Inside Plesk, the subscription user’s SSH access was changed from:

  • Forbidden
  • Chrooted Shell

to:

  • /bin/bash
  • Normal shell access

Once this change was made, almost every deployment issue disappeared immediately.

What Happened Next

The moment normal shell access was enabled:

  • /var/www/vhosts/... paths resolved correctly.
  • npm became available normally.
  • Node.js path issues vanished.
  • Deployment scripts behaved consistently.
  • Astro builds started completing successfully.
  • The GitHub-to-Plesk deployment workflow stabilised.

After days of troubleshooting, the solution turned out to be a single configuration setting.

Additional Permission Repairs

Some cleanup was still required because earlier failed deployments had left files and directories with inconsistent ownership and permissions.

The Astro project directory ownership was corrected, write permissions were repaired, and Plesk’s filesystem repair utility was run to normalise metadata and ownership mappings.

Once those repairs were completed:

  • Astro could recreate the dist directory correctly.
  • Vite could rename generated assets.
  • npm could manage dependencies normally.
  • Subsequent deployments completed successfully.

The Final Deployment Workflow

Ironically, once the environment was fixed, the deployment process became extremely straightforward:

  1. Pull the latest code from GitHub.
  2. Run npm install.
  3. Build the Astro site.
  4. Copy the contents of dist into httpdocs.

No elaborate CI/CD pipeline was required.

Lessons Learned

1. Check the Environment First

If you’re troubleshooting deployment issues in Plesk, the first question should be:

Is the subscription user running inside a chroot shell?

This single check could save hours of debugging.

2. Chroot Environments Can Be Misleading

The symptoms looked like:

  • Broken Node.js installations
  • Missing binaries
  • Astro or Vite bugs
  • Filesystem corruption

In reality, none of those were the root cause. The issue was simply environment isolation.

3. Simpler Is Better

Once the underlying environment matched the expected runtime environment, Astro behaved exactly as intended.

The deployment scripts became smaller, easier to understand, and far more reliable.

Final Thoughts

This experience was a useful reminder that deployment failures are often caused by environmental assumptions rather than application code.

For several days Astro appeared to be the culprit. In reality, Astro was doing exactly what it should have been doing all along. The real issue was that the deployment process was running inside a different world from the one I was using to diagnose it.

Sometimes the hardest bugs are not bugs at all—they’re configuration problems hiding in plain sight.