Sunday, May 3, 2026

Why My NestJS App Crashes on a VPS After a Simple HTTPS Redirect – 7 Lightning‑Fast Fixes I Wish I Knew Earlier

Why My NestJS App Crashes on a VPS After a Simple HTTPS Redirect – 7 Lightning‑Fast Fixes I Wish I Knew Earlier

You spent hours polishing a NestJS API, pushed it to a brand‑new VPS, added a one‑line HTTPS redirect, and…boom! The server crashes on launch. The error log looks like a cryptic maze of “ERR_SSL_PROTOCOL_ERROR” and “Module not found”. If this sounds familiar, you’re not alone. In this article you’ll discover the exact reasons behind the crash and walk away with seven battle‑tested fixes that will get your app back online in minutes.

Why This Matters

Every minute your API is down means lost traffic, angry developers, and a dent in revenue. A broken redirect is a cheap mistake that can snowball into costly downtime, especially when you’re running a SaaS product or an automation service that customers rely on 24/7. Fixing it fast isn’t just a convenience—it’s a business imperative.

7 Lightning‑Fast Fixes

  1. Validate Your SSL Certificate Chain

    VPS providers often give you a self‑signed cert or a partial chain. Browsers will reject the connection and Nest’s https.createServer will throw.

    Tip: Use openssl s_client -connect yourdomain.com:443 -showcerts to see the full chain. If “Verify return code: 21” appears, the chain is incomplete.
  2. Set NODE_ENV=production Correctly

    When NODE_ENV is “development” Nest loads extra debug modules that expect a dev‑cert.pem. On a bare VPS those files don’t exist, causing a crash.

    export NODE_ENV=production
    export PORT=3000
    npm run start:prod
  3. Configure globalPrefix Before the Redirect

    If you add app.setGlobalPrefix('api'); after the redirect middleware, Nest tries to route / to a non‑existent controller, throwing a 404 that bubbles up as an uncaught exception.

    async function bootstrap() {
      const app = await NestFactory.create(AppModule);
      app.setGlobalPrefix('api');
      app.useGlobalFilters(new HttpExceptionFilter());
    
      // HTTPS redirect must come AFTER the prefix
      app.use((req, res, next) => {
        if (!req.secure) {
          return res.redirect(`https://${req.headers.host}${req.url}`);
        }
        next();
      });
    
      await app.listen(process.env.PORT || 3000);
    }
  4. Don’t Mix http and https Servers

    Running two separate listen() calls in the same process confuses Nest’s internal HttpAdapterHost. Choose one entry point and let a reverse proxy (NGINX, Caddy) handle HTTP → HTTPS.

    Warning: Removing the second app.listen() will stop “Address already in use” crashes.
  5. Make Sure listen() Uses the Correct Host

    On many VPSes localhost resolves to 127.0.0.1, which blocks external traffic. Use 0.0.0.0 or omit the host argument.

    await app.listen(3000, '0.0.0.0');
  6. Check pm2 or Systemd Service Files

    If you start the app with pm2 start dist/main.js, make sure the ecosystem.config.js sets env_production correctly. A missing --ssl flag will cause the process to abort.

    module.exports = {
      apps: [{
        name: 'my-nest',
        script: 'dist/main.js',
        env_production: {
          NODE_ENV: 'production',
          PORT: 443,
          SSL_KEY: '/etc/ssl/private/key.pem',
          SSL_CERT: '/etc/ssl/certs/cert.pem'
        }
      }]
    };
  7. Enable Detailed Logging for One Run

    Turn on Nest’s built‑in logger temporarily to capture the exact stack trace.

    import { Logger } from '@nestjs/common';
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule, {
        logger: ['error', 'warn', 'log', 'debug', 'verbose'],
      });
      // ...rest of bootstrap
    }
    bootstrap();

    After you pinpoint the issue, revert to the default logger to keep the output clean.

Real‑World Use Case: Crashing SaaS API

A small SaaS startup switched from Heroku to a DigitalOcean droplet to cut costs. Their NestJS API used app.useGlobalPipes(new ValidationPipe()) and a custom HTTPS redirect. Within minutes of deployment the process exited with “ERR_CERT_AUTHORITY_INVALID”. By applying Fix #1 (full cert chain) and Fix #4 (remove duplicate HTTP server), they restored uptime and saved roughly $200/month in wasted server restarts.

Results / Outcome

  • Zero downtime after the first deploy.
  • HTTPS works on all browsers and mobile devices.
  • CPU usage drops 15% because the extra HTTP server is gone.
  • Log clutter disappears – only real errors surface.

Bonus Tips

  • Use certbot with the --nginx plugin to automate certificate renewal.
  • Keep your package.json scripts explicit: "start:prod": "node dist/main.js".
  • Run npm audit weekly; vulnerable OpenSSL versions can cause silent crashes.
  • Consider a Docker container; isolation eliminates host‑specific networking quirks.

Monetization Hook (Optional)

If you’re building APIs for clients, bundle automated SSL setup, monitoring, and weekly health checks into a premium support plan. Customers love “set‑and‑forget” services, and you can charge $49‑$99 per month per instance.

Fixing a crashing NestJS app after a simple HTTPS redirect doesn’t have to be a nightmare. With the seven fixes above you’ll be back to building features, automating workflows, and scaling your product—all without the fear of a mysterious server crash.

No comments:

Post a Comment