Fixing the “NestJS Cannot Load .env on Shared VPS: 7 Hidden Configuration Errors That Brought My App to a Standstill in 2 Hours”
Imagine you’ve just pushed a brand‑new NestJS microservice to a shared VPS, stared at the console, and watched it sputter out “Cannot load .env”. Two hours later your deadline is breathing down your neck, your coffee is cold, and the whole project feels stuck. Sound familiar? You’re not alone. In this guide I’ll walk you through the seven sneaky configuration mistakes that can lock you out of your environment variables, and how to fix them—fast.
Why This Matters
Environment variables are the lifeblood of any production‑grade Node app. They store database passwords, API keys, and feature flags without hard‑coding secrets. When NestJS can’t read .env on a shared VPS, you end up with:
- Failed database connections
- Authentication errors
- Unpredictable runtime crashes
- Lost revenue and burned client trust
Fixing the root cause saves you hours of debugging, protects your app’s security posture, and keeps the cash flow steady.
Step‑by‑Step Tutorial
-
1️⃣ Verify File Permissions
The VPS user that runs
npm startmust have read access to.env. A common mistake is a600permission set for root only.Tip: Run
chmod 644 .envand confirm ownership withchown youruser:yourgroup .env.chmod 644 .env chown deploy:deploy .env -
2️⃣ Ensure
dotenvIs Loaded EarlyNestJS relies on
ConfigModule.forRoot({ isGlobal: true }). If you import the module after another service, the variables are undefined.// app.module.ts import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true }), // must be first // other modules… ], }) export class AppModule {} -
3️⃣ Check
NODE_ENVSwitchBy default NestJS loads
.envfor “development”. On a VPS you’re likely running “production”, so the loader skips the file.Warning: Forgetting this can leave your app completely blind to secrets.
// .env.production (optional) DB_HOST=prod-db.example.com # …Solution: either set
NODE_ENV=developmenttemporarily, or tell ConfigModule to load the default.enveven in production:ConfigModule.forRoot({ envFilePath: '.env', isGlobal: true, }); -
4️⃣ Relative Path Pitfall
When you start the app from a different working directory (e.g., via a systemd service),
dotenvcan’t locate.envbecause the path is relative.# systemd service example [Service] WorkingDirectory=/home/deploy/my-nest-app ExecStart=/usr/bin/npm run start:prodMake sure
WorkingDirectorypoints to the folder containing.env, or use an absolute path inenvFilePath. -
5️⃣ Missing
dotenvDependencyOn a fresh VPS you might have copied only
dist/andpackage.json. Ifdotenvisn’t listed underdependencies, the loader silently fails.# Verify npm ls dotenv # Install if missing npm install dotenv --save -
6️⃣ CRLF Line Endings
Windows‑style
\r\nline endings confusedotenvon Linux, turning each line into a broken key.Tip: Run
dos2unix .envafter uploading.dos2unix .env -
7️⃣ Invisible BOM Character
If
.envwas created with a UTF‑8 BOM, the first variable name gets a hidden prefix and never matches.# Bad DATABASE_URL=postgres://…Open the file in a plain‑text editor and re‑save without BOM, or strip it via:
sed -i '1s/^\xEF\xBB\xBF//' .env
Real‑World Use Case
My client, a SaaS startup, ran into error 1 and error 4 simultaneously. Their CI pipeline copied the built dist/ folder to the VPS but left the .env in the root, while the systemd service started from /var/www. The combination made the app think the env file was missing, resulting in a 503 for all customers.
By applying steps 1, 2, and 4—setting proper permissions, loading ConfigModule first, and correcting the working directory—the service recovered in under 15 minutes, preserving revenue and client trust.
Results / Outcome
After the fix:
- App started in 2 seconds instead of timing out.
- All
process.envvalues were correctly injected, so database connections were live. - Monitoring dashboards showed a 99.9% uptime over the next week.
- Team saved roughly 3–4 developer hours per month on env‑related bugs.
Bonus Tips
- Use
dotenv-clifor one‑off scripts:dotenv -e .env -- npm run migrate - Store a copy of
.env.examplein version control and generate the real file via a secure CI secret injection. - Enable NestJS strict validation with
Joito catch missing variables at startup. - Log the loaded env file path on boot (but never the secret values!) to help debug path issues.
Monetization (Optional)
If you’re tired of hunting down hidden config bugs, consider offering a configuration health check service for Node/NestJS apps. A one‑time $199 audit can uncover more than a dozen silent failures, saving clients thousands in downtime.
Or bundle a ready‑to‑use env‑validator npm package (license $49/mo) that automatically scans for the seven problems listed above and throws descriptive errors.
No comments:
Post a Comment