<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Oluwadara Adesoji</title>
    <description>The latest articles on DEV Community by Oluwadara Adesoji (@adesoji).</description>
    <link>https://dev.to/adesoji</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F907381%2F6388f66d-74fb-4f69-8cc9-bc2099143745.jpeg</url>
      <title>DEV Community: Oluwadara Adesoji</title>
      <link>https://dev.to/adesoji</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adesoji"/>
    <language>en</language>
    <item>
      <title>How to Deploy and Run a NestJS App on Namecheap Shared Hosting</title>
      <dc:creator>Oluwadara Adesoji</dc:creator>
      <pubDate>Fri, 03 Jul 2026 16:00:00 +0000</pubDate>
      <link>https://dev.to/adesoji/how-to-deploy-and-run-a-nestjs-app-on-namecheap-shared-hosting-5c45</link>
      <guid>https://dev.to/adesoji/how-to-deploy-and-run-a-nestjs-app-on-namecheap-shared-hosting-5c45</guid>
      <description>&lt;p&gt;Deploying NestJS to Namecheap Shared Hosting is slightly different from deploying a static website or a PHP application.&lt;/p&gt;

&lt;p&gt;NestJS must be compiled from TypeScript to JavaScript, its production dependencies must be installed, and cPanel's Node.js application manager must start it through Passenger. External services such as Redis must also be reachable from the shared server.&lt;/p&gt;

&lt;p&gt;I learned those details while deploying a NestJS API with Bull queues, Redis, Swagger, PDF uploads, and a custom domain. This guide collects the complete working process—including the problems that initially left me with an empty deployment folder, missing build files, unavailable routes, and failed Redis connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Production Setup Works
&lt;/h2&gt;

&lt;p&gt;The final request path looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser or API client
        |
        v
Domain and HTTPS
        |
        v
Apache / Passenger on Namecheap
        |
        v
app.js
        |
        v
dist/main.js
        |
        v
NestJS application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You do not need PM2 for this setup. Namecheap's &lt;strong&gt;Setup Node.js App&lt;/strong&gt; interface and Passenger manage the application process.&lt;/p&gt;

&lt;p&gt;Namecheap currently lets shared-hosting customers choose the Node.js version, application mode, application root, URL, startup file, and environment variables from cPanel. Its official instructions are available in &lt;a href="https://www.namecheap.com/support/knowledgebase/article.aspx/10047/2182/how-to-work-with-nodejs-app/" rel="noopener noreferrer"&gt;How to work with Node.js App&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting, you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Namecheap Shared Hosting account with Node.js support&lt;/li&gt;
&lt;li&gt;A domain or subdomain assigned to the hosting account&lt;/li&gt;
&lt;li&gt;Access to cPanel&lt;/li&gt;
&lt;li&gt;SSH or cPanel Terminal access&lt;/li&gt;
&lt;li&gt;A working NestJS project&lt;/li&gt;
&lt;li&gt;A supported Node.js version compatible with the project&lt;/li&gt;
&lt;li&gt;Production credentials for any external database, Redis server, or API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the application locally before deploying:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run start:dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix local build or startup errors first. Production adds enough moving parts without bringing local errors along for the ride.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Prepare NestJS for Production
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Listen on the port supplied by the host
&lt;/h3&gt;

&lt;p&gt;Namecheap's Passenger environment controls how requests reach the application. Do not rely exclusively on a hard-coded local port.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;src/main.ts&lt;/code&gt;, listen on &lt;code&gt;process.env.PORT&lt;/code&gt; with a local fallback:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;NestFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fallback is useful locally. In production, the host-provided &lt;code&gt;PORT&lt;/code&gt; value takes priority.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add production scripts
&lt;/h3&gt;

&lt;p&gt;Your &lt;code&gt;package.json&lt;/code&gt; should include at least:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nest build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start:prod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node dist/main.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Keep runtime packages in &lt;code&gt;dependencies&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Packages needed after compilation belong in &lt;code&gt;dependencies&lt;/code&gt;, not &lt;code&gt;devDependencies&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This includes packages such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@nestjs/common
@nestjs/core
@nestjs/platform-express
reflect-metadata
rxjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Nest CLI, TypeScript, test tools, and linters can remain in &lt;code&gt;devDependencies&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This distinction matters because a production-only install may omit &lt;code&gt;devDependencies&lt;/code&gt;. The build can exist and still crash immediately if a required Nest package was classified as development-only.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Make the Build Produce &lt;code&gt;dist/main.js&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Namecheap runs JavaScript, not the TypeScript source directly. Compile the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The expected entry file for this guide is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist/main.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use a focused &lt;code&gt;tsconfig.build.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./tsconfig.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rootDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"src/**/*.ts"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"node_modules"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"**/*spec.ts"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restricting the production build to &lt;code&gt;src/&lt;/code&gt; prevents root-level JavaScript files such as &lt;code&gt;app.js&lt;/code&gt; from being type-checked and emitted. It also avoids a layout such as &lt;code&gt;dist/src/main.js&lt;/code&gt; when the desired output is &lt;code&gt;dist/main.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Verify the build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; dist/main.js
node dist/main.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the application starts, stop it with &lt;code&gt;Ctrl+C&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Create Passenger's Startup File
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;app.js&lt;/code&gt; in the project root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./dist/main&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your deployment should now resemble:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;application-root/
├── app.js
├── package.json
├── package-lock.json
├── dist/
│   └── main.js
└── src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passenger conventionally looks for &lt;code&gt;app.js&lt;/code&gt;, although cPanel also lets you specify another startup filename. The cPanel documentation likewise recommends &lt;code&gt;app.js&lt;/code&gt; as the standard startup file: &lt;a href="https://docs.cpanel.net/knowledge-base/web-services/how-to-install-a-node.js-application/" rel="noopener noreferrer"&gt;How to Install a Node.js Application&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The startup bridge is deliberately small. It loads the compiled NestJS application; it does not create a second server.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Decide Where to Build
&lt;/h2&gt;

&lt;p&gt;There are two sensible deployment strategies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A: Build locally and upload &lt;code&gt;dist&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is usually safer on shared hosting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm ci
npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upload:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;app.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dist/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package-lock.json&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then install only runtime dependencies on Namecheap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm ci &lt;span class="nt"&gt;--omit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach reduces CPU and memory usage on the shared server.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;dist/&lt;/code&gt; is listed in &lt;code&gt;.gitignore&lt;/code&gt;, a Git-only deployment will not send it. Use an artifact upload, SFTP, rsync, or another deployment step that deliberately transfers the build output.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option B: Build on Namecheap
&lt;/h3&gt;

&lt;p&gt;Upload the source and install all build dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm ci &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev
npm run build
npm prune &lt;span class="nt"&gt;--omit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps &lt;code&gt;dist/&lt;/code&gt; out of source control but requires enough server resources to run the Nest compiler.&lt;/p&gt;

&lt;p&gt;Choose one strategy and make it explicit. A common failure is ignoring &lt;code&gt;dist/&lt;/code&gt;, not building on the server, and then asking Passenger to load a file that does not exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Upload the Project
&lt;/h2&gt;

&lt;p&gt;You can use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cPanel File Manager&lt;/li&gt;
&lt;li&gt;SFTP&lt;/li&gt;
&lt;li&gt;rsync over SSH&lt;/li&gt;
&lt;li&gt;cPanel Git Version Control&lt;/li&gt;
&lt;li&gt;A custom Git deployment remote&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not upload:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your local &lt;code&gt;node_modules/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Local logs&lt;/li&gt;
&lt;li&gt;Test coverage&lt;/li&gt;
&lt;li&gt;Editor configuration&lt;/li&gt;
&lt;li&gt;Development secrets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install dependencies for the Node version selected in cPanel instead of copying &lt;code&gt;node_modules&lt;/code&gt; from your computer. Native modules compiled on macOS, for example, may not run on the Linux hosting server.&lt;/p&gt;

&lt;h3&gt;
  
  
  If Git creates only a &lt;code&gt;.git&lt;/code&gt; directory
&lt;/h3&gt;

&lt;p&gt;If the remote folder contains &lt;code&gt;.git&lt;/code&gt; but no application files, the pushed branch may not be the branch checked out by the server repository.&lt;/p&gt;

&lt;p&gt;For example, the server may initialize &lt;code&gt;master&lt;/code&gt; while you push &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/your-application-root
git branch &lt;span class="nt"&gt;-a&lt;/span&gt;
git checkout &lt;span class="nt"&gt;-f&lt;/span&gt; main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;main&lt;/code&gt; with the branch you actually pushed.&lt;/p&gt;

&lt;p&gt;Renaming a local branch can also align the two sides:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch &lt;span class="nt"&gt;-m&lt;/span&gt; main master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important detail is not whether the branch is called &lt;code&gt;main&lt;/code&gt; or &lt;code&gt;master&lt;/code&gt;; it is that the server worktree checks out the deployed branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Create the Node.js Application in cPanel
&lt;/h2&gt;

&lt;p&gt;Open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Namecheap Dashboard
→ Hosting List
→ Go to cPanel
→ Software
→ Setup Node.js App
→ Create application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Choose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js version:&lt;/strong&gt; Match the version supported by your project&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application mode:&lt;/strong&gt; Production&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application root:&lt;/strong&gt; The folder containing &lt;code&gt;app.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application URL:&lt;/strong&gt; Your domain or subdomain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application startup file:&lt;/strong&gt; &lt;code&gt;app.js&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The application root must point to the directory that contains &lt;code&gt;app.js&lt;/code&gt;, &lt;code&gt;package.json&lt;/code&gt;, and &lt;code&gt;dist/&lt;/code&gt;. Do not point it directly at &lt;code&gt;dist&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Install Dependencies in the Correct Environment
&lt;/h2&gt;

&lt;p&gt;The Node.js application page shows a command for entering its virtual environment through SSH. Copy and run that command exactly.&lt;/p&gt;

&lt;p&gt;Then enter the application root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/your-application-root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm ci &lt;span class="nt"&gt;--omit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you chose to build on the server instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm ci &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev
npm run build
npm prune &lt;span class="nt"&gt;--omit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use the &lt;strong&gt;Run NPM Install&lt;/strong&gt; button in the cPanel Node.js application interface. Namecheap documents both the virtual-environment command and the cPanel install action in its &lt;a href="https://www.namecheap.com/support/knowledgebase/article.aspx/10047/2182/how-to-work-with-nodejs-app/" rel="noopener noreferrer"&gt;Node.js App guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Configure Environment Variables
&lt;/h2&gt;

&lt;p&gt;In &lt;strong&gt;Setup Node.js App&lt;/strong&gt;, edit the application and add the required variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NODE_ENV=production
OPENAI_API_KEY=...
REDIS_URL=...
DATABASE_URL=...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only add variables your application actually uses.&lt;/p&gt;

&lt;p&gt;You may also use a &lt;code&gt;.env&lt;/code&gt; file in the application root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;application-root/
├── .env
├── app.js
├── package.json
└── dist/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not put &lt;code&gt;.env&lt;/code&gt; inside &lt;code&gt;dist&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Protect it with &lt;code&gt;.gitignore&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.env
.env.*
!.env.example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not put real credentials in &lt;code&gt;.env.example&lt;/code&gt;. If a secret has ever been committed or published, removing it from the latest file is not enough—rotate the credential.&lt;/p&gt;

&lt;p&gt;When a variable exists in both cPanel and &lt;code&gt;.env&lt;/code&gt;, the existing process environment normally takes precedence. Make sure an old cPanel value is not overriding the current &lt;code&gt;.env&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;Restart the application after changing environment variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Start or Restart the App
&lt;/h2&gt;

&lt;p&gt;Return to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cPanel → Setup Node.js App
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;strong&gt;Start App&lt;/strong&gt; or &lt;strong&gt;Restart&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Do not keep the application alive by running &lt;code&gt;npm run start:prod&lt;/code&gt; in an SSH terminal. The process will be disconnected from the hosting lifecycle, may conflict with Passenger, and can produce &lt;code&gt;EADDRINUSE&lt;/code&gt; errors.&lt;/p&gt;

&lt;p&gt;Passenger should own the production process.&lt;/p&gt;

&lt;p&gt;For environments using a direct Passenger configuration, cPanel also documents the &lt;code&gt;tmp/restart.txt&lt;/code&gt; mechanism. On Namecheap's managed interface, the restart button is simpler.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Test the Deployment
&lt;/h2&gt;

&lt;p&gt;Start with a simple GET route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.example.com/v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you use NestJS URI versioning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enableVersioning&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;VersioningType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;URI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;defaultVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then controller routes receive the &lt;code&gt;/v1&lt;/code&gt; prefix.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api/parse-bank-statement&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PdfParserController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;job/:jobId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;getJobStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /v1/api/parse-bank-statement/job/:jobId
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test from a terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; https://api.example.com/v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A NestJS JSON response—even a NestJS-formatted 404—proves that the request reached the application. It does not necessarily mean the proxy or deployment failed.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Understand Why Swagger May Return 404
&lt;/h2&gt;

&lt;p&gt;Many applications intentionally disable Swagger in production:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setupSwaggerDocs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In that case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /docs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cannot GET /docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Not Found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That response is expected. The NestJS application is running, but the documentation route was never registered.&lt;/p&gt;

&lt;p&gt;Do not use &lt;code&gt;/docs&lt;/code&gt; as your only health check when production configuration disables it.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Read Namecheap Production Logs
&lt;/h2&gt;

&lt;p&gt;Open the Passenger log configured for the application. It is often named &lt;code&gt;stderr.log&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Display recent errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 100 stderr.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow new entries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; stderr.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Press &lt;code&gt;Ctrl+C&lt;/code&gt; to stop following.&lt;/p&gt;

&lt;p&gt;Find other logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-maxdepth&lt;/span&gt; 3 &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.log"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cPanel → Metrics → Errors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Namecheap says this interface displays the latest web-server error entries: &lt;a href="https://www.namecheap.com/support/knowledgebase/article.aspx/9797/29/cpanel-control-panel-overview/" rel="noopener noreferrer"&gt;cPanel control panel overview&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Connect External Services Carefully
&lt;/h2&gt;

&lt;p&gt;A working HTTP route does not prove that Redis, a database, or another API is reachable.&lt;/p&gt;

&lt;p&gt;For Redis-backed Bull queues, test the TCP port from Namecheap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc &lt;span class="nt"&gt;-vz&lt;/span&gt; &amp;lt;redis-host&amp;gt; &amp;lt;redis-port&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then send a real Redis &lt;code&gt;PING&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;-r&lt;/span&gt; dotenv/config &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'const Redis=require("ioredis"); const r=new Redis(process.env.REDIS_URL,{connectTimeout:5000,maxRetriesPerRequest:1,retryStrategy:()=&amp;gt;null}); r.on("error",()=&amp;gt;{}); r.ping().then(console.log).catch(e=&amp;gt;console.error(e.code,e.message)).finally(()=&amp;gt;r.disconnect())'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Success returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Redis works locally but Namecheap reports &lt;code&gt;ECONNREFUSED&lt;/code&gt; or &lt;code&gt;ETIMEDOUT&lt;/code&gt;, check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Redis server's firewall&lt;/li&gt;
&lt;li&gt;Cloud security-group rules&lt;/li&gt;
&lt;li&gt;Redis source-IP allowlists&lt;/li&gt;
&lt;li&gt;Whether Namecheap permits the outbound destination port&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my deployment, Namecheap Support had to permit the Redis port before the production application could connect.&lt;/p&gt;

&lt;p&gt;For the full Redis setup and debugging process, see &lt;a href="//./redis-namecheap-shared-hosting-nodejs.md"&gt;How to Connect Redis to a Node.js App on Namecheap Shared Hosting&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  14. Await Important Asynchronous Operations
&lt;/h2&gt;

&lt;p&gt;Production networking exposes bugs that local development may hide.&lt;/p&gt;

&lt;p&gt;For example, do not queue a job without awaiting the promise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;processPdfQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jobData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;processPdfQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jobData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without &lt;code&gt;await&lt;/code&gt;, the controller can return “queued successfully” before Redis has accepted the job. A later unhandled rejection can also terminate the Node.js process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Deployment Errors
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error or symptom&lt;/th&gt;
&lt;th&gt;Likely cause&lt;/th&gt;
&lt;th&gt;What to check&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Only &lt;code&gt;.git&lt;/code&gt; appears on the server&lt;/td&gt;
&lt;td&gt;The pushed branch is not checked out&lt;/td&gt;
&lt;td&gt;Run &lt;code&gt;git branch -a&lt;/code&gt; and check out the deployed branch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Cannot find module './dist/main'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Missing build or wrong output layout&lt;/td&gt;
&lt;td&gt;Run the build and verify &lt;code&gt;dist/main.js&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EADDRINUSE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Another process already uses the fallback port&lt;/td&gt;
&lt;td&gt;Stop the manual process and let Passenger manage the app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Cannot GET /docs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Swagger is disabled in production&lt;/td&gt;
&lt;td&gt;Test a real API or health route&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NestJS-formatted 404&lt;/td&gt;
&lt;td&gt;The app is running, but that route does not exist&lt;/td&gt;
&lt;td&gt;Check version prefixes and controller paths&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MaxRetriesPerRequestError&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Redis requests repeatedly failed&lt;/td&gt;
&lt;td&gt;Find the underlying connection error&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ECONNREFUSED&lt;/code&gt; to an external service&lt;/td&gt;
&lt;td&gt;Port closed, service stopped, or connection rejected&lt;/td&gt;
&lt;td&gt;Test with &lt;code&gt;nc&lt;/code&gt;; inspect firewalls and hosting rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Environment variable appears stale&lt;/td&gt;
&lt;td&gt;cPanel value overrides &lt;code&gt;.env&lt;/code&gt;, or app was not restarted&lt;/td&gt;
&lt;td&gt;Check both locations and restart&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App works in terminal but not through domain&lt;/td&gt;
&lt;td&gt;cPanel application root, URL, or startup file is wrong&lt;/td&gt;
&lt;td&gt;Verify the Node.js App configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App crashes after production-only install&lt;/td&gt;
&lt;td&gt;Runtime package is in &lt;code&gt;devDependencies&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Move runtime packages to &lt;code&gt;dependencies&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Production Checklist
&lt;/h2&gt;

&lt;p&gt;Before considering the deployment complete, verify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The application builds locally&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dist/main.js&lt;/code&gt; exists&lt;/li&gt;
&lt;li&gt;Root-level &lt;code&gt;app.js&lt;/code&gt; loads &lt;code&gt;./dist/main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Runtime Nest packages are in &lt;code&gt;dependencies&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;node_modules&lt;/code&gt; was installed on the server, not copied from macOS or Windows&lt;/li&gt;
&lt;li&gt;The cPanel application root contains &lt;code&gt;app.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The cPanel startup file is &lt;code&gt;app.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The selected Node.js version matches the project&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NODE_ENV&lt;/code&gt; is set correctly&lt;/li&gt;
&lt;li&gt;Secrets are not committed to Git&lt;/li&gt;
&lt;li&gt;The app was restarted after environment changes&lt;/li&gt;
&lt;li&gt;A simple GET route works through HTTPS&lt;/li&gt;
&lt;li&gt;Expected version prefixes such as &lt;code&gt;/v1&lt;/code&gt; are included&lt;/li&gt;
&lt;li&gt;Production logs are accessible&lt;/li&gt;
&lt;li&gt;External databases and Redis are reachable from Namecheap&lt;/li&gt;
&lt;li&gt;Important asynchronous operations are awaited&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Takeaway
&lt;/h2&gt;

&lt;p&gt;Running NestJS on Namecheap Shared Hosting is entirely workable once the responsibilities are clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nest compiles the TypeScript application into &lt;code&gt;dist&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app.js&lt;/code&gt; gives Passenger a predictable startup file.&lt;/li&gt;
&lt;li&gt;cPanel selects the Node version, root directory, URL, mode, and environment.&lt;/li&gt;
&lt;li&gt;Passenger owns the process and production port.&lt;/li&gt;
&lt;li&gt;Your deployment method must transfer or create &lt;code&gt;dist&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;External services must accept connections from the Namecheap server.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;stderr.log&lt;/code&gt; tells you what happened when the browser only shows a generic error.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most of the difficult failures were not mysterious NestJS bugs. They were boundary problems between the build, Git worktree, Passenger configuration, environment variables, and network access. Test those boundaries one at a time, and the deployment becomes much easier to reason about.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>namecheap</category>
      <category>nestjs</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Connect Redis to a Node.js App on Namecheap Shared Hosting</title>
      <dc:creator>Oluwadara Adesoji</dc:creator>
      <pubDate>Thu, 02 Jul 2026 13:09:01 +0000</pubDate>
      <link>https://dev.to/adesoji/how-to-connect-redis-to-a-nodejs-app-on-namecheap-shared-hosting-4n5p</link>
      <guid>https://dev.to/adesoji/how-to-connect-redis-to-a-nodejs-app-on-namecheap-shared-hosting-4n5p</guid>
      <description>&lt;p&gt;If you deploy a Node.js application to Namecheap Shared Hosting and it uses Bull, BullMQ, sessions, caching, or another Redis-backed feature, you may discover that a Redis connection which works locally fails in production.&lt;/p&gt;

&lt;p&gt;That happened to me. The application deployed successfully, HTTP routes worked, and environment variables loaded correctly—but every queue operation eventually failed with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MaxRetriesPerRequestError: Reached the max retries per request limit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The underlying error was more useful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;connect ECONNREFUSED &amp;lt;redis-host&amp;gt;:&amp;lt;redis-port&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix was not installing Redis inside the shared-hosting account. Instead, I connected the Namecheap-hosted Node.js application to an external Redis server and asked Namecheap Support to permit the required outbound TCP port.&lt;/p&gt;

&lt;p&gt;This guide walks through the complete setup and the troubleshooting lessons that mattered.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Are Actually Building
&lt;/h2&gt;

&lt;p&gt;On shared hosting, you generally do not control the operating system or run persistent system services such as your own Redis daemon. The practical architecture is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser or API client
        |
        v
Node.js app on Namecheap Shared Hosting
        |
        | Outbound TCP connection
        v
External Redis server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Redis server can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A managed Redis service&lt;/li&gt;
&lt;li&gt;Redis running on a VPS or cloud server you control&lt;/li&gt;
&lt;li&gt;Another externally reachable Redis-compatible service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important requirement is that Namecheap's server must be able to reach the Redis host and port.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;You will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Node.js application configured through &lt;strong&gt;cPanel → Setup Node.js App&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;SSH or cPanel Terminal access&lt;/li&gt;
&lt;li&gt;An external Redis instance&lt;/li&gt;
&lt;li&gt;The Redis hostname, port, username, password, and TLS requirements&lt;/li&gt;
&lt;li&gt;A Redis client such as &lt;code&gt;ioredis&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Namecheap's official guide explains how to create the Node.js application, choose its root and startup file, add environment variables, install packages, and restart it: &lt;a href="https://www.namecheap.com/support/knowledgebase/article.aspx/10047/2182/how-to-work-with-nodejs-app/" rel="noopener noreferrer"&gt;How to work with Node.js App&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Create or Obtain an External Redis Instance
&lt;/h2&gt;

&lt;p&gt;Create a Redis database with your chosen provider, or configure Redis on a separate server.&lt;/p&gt;

&lt;p&gt;Your provider should give you a connection URL resembling one of these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;redis://default:PASSWORD@HOST:PORT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a TLS-encrypted connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rediss://default:PASSWORD@HOST:PORT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;redis://&lt;/code&gt; uses a normal TCP connection. &lt;code&gt;rediss://&lt;/code&gt; tells compatible clients to use TLS. Use the exact scheme supplied by your Redis provider; do not change it by guesswork.&lt;/p&gt;

&lt;p&gt;Do not use a provider's HTTP REST URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://example-redis-provider.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bull and &lt;code&gt;ioredis&lt;/code&gt; require the Redis TCP endpoint.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secure the Redis server
&lt;/h3&gt;

&lt;p&gt;Never expose an unauthenticated Redis instance to the public internet. Redis warns that an exposed server can allow destructive commands such as &lt;code&gt;FLUSHALL&lt;/code&gt;. Use authentication, network restrictions, and TLS where available. See the official &lt;a href="https://redis.io/docs/latest/operate/oss_and_stack/management/security/" rel="noopener noreferrer"&gt;Redis security guidance&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If your provider has an IP allowlist, you may need the outgoing public IP of the Namecheap server. From the Namecheap terminal, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://api.ipify.org
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add that IP to the Redis provider's allowlist. Do not use &lt;code&gt;0.0.0.0/0&lt;/code&gt; merely to make the connection work.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Configure the Node.js Application
&lt;/h2&gt;

&lt;p&gt;For a NestJS application using Bull, install the required packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @nestjs/bull bull ioredis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure Bull with the connection URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BullModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/bull&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ConfigModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;ConfigModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;isGlobal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;BullModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REDIS_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a plain Node.js connection test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ioredis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REDIS_URL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Add &lt;code&gt;REDIS_URL&lt;/code&gt; in cPanel
&lt;/h2&gt;

&lt;p&gt;Open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cPanel → Setup Node.js App → Edit application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under &lt;strong&gt;Environment variables&lt;/strong&gt;, add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Name:  REDIS_URL
Value: redis://default:PASSWORD@HOST:PORT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;rediss://&lt;/code&gt; if your provider requires TLS.&lt;/p&gt;

&lt;p&gt;You may also keep a &lt;code&gt;.env&lt;/code&gt; file in the application root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;application-root/
├── app.js
├── package.json
├── .env
└── dist/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.env&lt;/code&gt; file belongs beside &lt;code&gt;app.js&lt;/code&gt; and &lt;code&gt;package.json&lt;/code&gt;, not inside &lt;code&gt;dist&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Do not commit &lt;code&gt;.env&lt;/code&gt; to Git. Add it to &lt;code&gt;.gitignore&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.env
.env.*
!.env.example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the same variable exists in both cPanel and &lt;code&gt;.env&lt;/code&gt;, the value already present in the process environment normally wins. A blank or outdated cPanel value can therefore override the correct value in &lt;code&gt;.env&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After adding or changing environment variables, restart the application from &lt;strong&gt;Setup Node.js App&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Confirm That the Environment Variable Loads
&lt;/h2&gt;

&lt;p&gt;From the application root in the Namecheap terminal, run this safe check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;-r&lt;/span&gt; dotenv/config &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'const v=process.env.REDIS_URL; console.log({set:Boolean(v), protocol:v ? v.split(":")[0] : null, length:v ? v.length : 0})'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ set: true, protocol: 'redis', length: 107 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This confirms that the &lt;code&gt;.env&lt;/code&gt; value exists without printing the password.&lt;/p&gt;

&lt;p&gt;One subtlety: environment variables configured in cPanel are injected into the Passenger-managed application process. They may not automatically appear in an ordinary SSH shell. The command above explicitly reads the &lt;code&gt;.env&lt;/code&gt; file through &lt;code&gt;dotenv&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Test the Network Before Testing the Application
&lt;/h2&gt;

&lt;p&gt;First test whether the Redis TCP port is reachable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc &lt;span class="nt"&gt;-vz&lt;/span&gt; &amp;lt;redis-host&amp;gt; &amp;lt;redis-port&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Possible results include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Connection succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Connection refused
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A normal ICMP &lt;code&gt;ping&lt;/code&gt; is not enough. It only tests whether a host responds to ICMP; it does not prove that Redis is listening or reachable on its TCP port.&lt;/p&gt;

&lt;p&gt;Next, test the Redis protocol using the same client library as the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;-r&lt;/span&gt; dotenv/config &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'const Redis=require("ioredis"); const r=new Redis(process.env.REDIS_URL,{connectTimeout:5000,maxRetriesPerRequest:1,retryStrategy:()=&amp;gt;null}); r.on("error",()=&amp;gt;{}); r.ping().then(x=&amp;gt;console.log("Redis:",x)).catch(e=&amp;gt;console.error(e.code,e.message)).finally(()=&amp;gt;r.disconnect())'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A successful connection prints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Redis: PONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Redis &lt;code&gt;PING&lt;/code&gt; command is specifically intended for testing whether a connection is alive. See the official &lt;a href="https://redis.io/docs/latest/commands/ping/" rel="noopener noreferrer"&gt;&lt;code&gt;PING&lt;/code&gt; command documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;redis-cli&lt;/code&gt; is available, you can also use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redis-cli &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$REDIS_URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; PING
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Redis documents URI-based connections and notes that &lt;code&gt;rediss&lt;/code&gt; is the scheme for TLS: &lt;a href="https://redis.io/docs/latest/develop/tools/cli/" rel="noopener noreferrer"&gt;Redis CLI documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. When It Works Locally but Fails on Namecheap
&lt;/h2&gt;

&lt;p&gt;This was the key production issue in my deployment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Redis test returned &lt;code&gt;PONG&lt;/code&gt; on my local machine.&lt;/li&gt;
&lt;li&gt;The same connection returned &lt;code&gt;ECONNREFUSED&lt;/code&gt; from the Namecheap terminal.&lt;/li&gt;
&lt;li&gt;The environment variable was present and correctly formatted.&lt;/li&gt;
&lt;li&gt;Namecheap Support opened the required outbound port.&lt;/li&gt;
&lt;li&gt;The connection then worked from production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you encounter the same pattern, first check:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Whether the Redis provider allowlists source IP addresses&lt;/li&gt;
&lt;li&gt;Whether your Redis server's firewall permits the Namecheap server&lt;/li&gt;
&lt;li&gt;Whether a cloud security group permits the Redis port&lt;/li&gt;
&lt;li&gt;Whether Redis is actually listening on the advertised external interface and port&lt;/li&gt;
&lt;li&gt;Whether Namecheap permits outbound TCP traffic to that destination port&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the destination-side settings are correct, contact Namecheap Support with a precise request:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please confirm whether outbound TCP connections from my shared-hosting server to &lt;code&gt;&amp;lt;redis-host&amp;gt;:&amp;lt;redis-port&amp;gt;&lt;/code&gt; are permitted. My Node.js application requires this connection for Redis.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your Namecheap shared-server hostname&lt;/li&gt;
&lt;li&gt;The destination Redis hostname or IP&lt;/li&gt;
&lt;li&gt;The destination TCP port&lt;/li&gt;
&lt;li&gt;The exact error, such as &lt;code&gt;ECONNREFUSED&lt;/code&gt; or &lt;code&gt;ETIMEDOUT&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Never include your Redis password in the support message.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Configure Queue Operations to Fail Safely
&lt;/h2&gt;

&lt;p&gt;Redis connectivity is not the only concern. Make sure asynchronous queue operations are awaited.&lt;/p&gt;

&lt;p&gt;Avoid this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;processPdfQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jobData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Job queued successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Redis is unavailable, the application may report success before the rejected promise is observed. In some Node.js configurations, the unhandled rejection can terminate the process.&lt;/p&gt;

&lt;p&gt;Use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;processPdfQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jobData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Job queued successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;jobId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the surrounding &lt;code&gt;try/catch&lt;/code&gt; can return an honest error response when Redis is unavailable.&lt;/p&gt;

&lt;p&gt;Do not treat a larger &lt;code&gt;maxRetriesPerRequest&lt;/code&gt; value as the fix for an unreachable Redis server. More retries only postpone the same failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Read Production Logs
&lt;/h2&gt;

&lt;p&gt;For a Namecheap Node.js application, application and Passenger errors commonly appear in the configured log file, often named &lt;code&gt;stderr.log&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Display recent entries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 100 stderr.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow new entries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; stderr.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Press &lt;code&gt;Ctrl+C&lt;/code&gt; to stop following the file.&lt;/p&gt;

&lt;p&gt;You can also inspect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cPanel → Metrics → Errors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Namecheap documents that this view shows the latest web-server errors in its &lt;a href="https://www.namecheap.com/support/knowledgebase/article.aspx/9797/29/cpanel-control-panel-overview/" rel="noopener noreferrer"&gt;cPanel overview&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Redis Connection Errors
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;What it usually means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ECONNREFUSED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The host was reached, but the port rejected the connection or nothing was listening&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ETIMEDOUT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A firewall, security group, routing problem, or unreachable host silently dropped the connection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ENOTFOUND&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The Redis hostname could not be resolved&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;WRONGPASS&lt;/code&gt; or authentication error&lt;/td&gt;
&lt;td&gt;The username or password is wrong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TLS or socket reset errors&lt;/td&gt;
&lt;td&gt;The client and server may disagree about TLS; verify &lt;code&gt;redis://&lt;/code&gt; versus &lt;code&gt;rediss://&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MaxRetriesPerRequestError&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The client retried a failed request repeatedly; inspect earlier logs for the underlying connection error&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Deployment Checklist
&lt;/h2&gt;

&lt;p&gt;Before calling the setup complete, verify all of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Redis is running on an external, reachable server&lt;/li&gt;
&lt;li&gt;[ ] Authentication is enabled&lt;/li&gt;
&lt;li&gt;[ ] TLS is enabled when supported&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;REDIS_URL&lt;/code&gt; uses the provider's TCP endpoint&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;.env&lt;/code&gt; is outside &lt;code&gt;dist&lt;/code&gt; and excluded from Git&lt;/li&gt;
&lt;li&gt;[ ] The cPanel environment variable is correct&lt;/li&gt;
&lt;li&gt;[ ] The Node.js app was restarted after configuration changes&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;nc -vz &amp;lt;host&amp;gt; &amp;lt;port&amp;gt;&lt;/code&gt; succeeds from Namecheap&lt;/li&gt;
&lt;li&gt;[ ] The &lt;code&gt;ioredis&lt;/code&gt; test returns &lt;code&gt;PONG&lt;/code&gt; from Namecheap&lt;/li&gt;
&lt;li&gt;[ ] Redis allows the Namecheap server's source IP where allowlisting is used&lt;/li&gt;
&lt;li&gt;[ ] Namecheap permits the required outbound destination port&lt;/li&gt;
&lt;li&gt;[ ] Queue operations such as &lt;code&gt;queue.add()&lt;/code&gt; are awaited&lt;/li&gt;
&lt;li&gt;[ ] Production logs are available and monitored&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Takeaway
&lt;/h2&gt;

&lt;p&gt;The hardest part was not the Node.js or Bull configuration. It was identifying where the connection failed.&lt;/p&gt;

&lt;p&gt;Checking the problem layer by layer made the answer clear:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Confirm the environment variable exists.&lt;/li&gt;
&lt;li&gt;Confirm the URL is a Redis TCP URL.&lt;/li&gt;
&lt;li&gt;Test the destination port from the production terminal.&lt;/li&gt;
&lt;li&gt;Run a real Redis &lt;code&gt;PING&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Compare local and production results.&lt;/li&gt;
&lt;li&gt;Check both destination firewalls and Namecheap's outbound rules.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once Namecheap permitted the required outbound port, the application connected to Redis and the background jobs started working.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>namecheap</category>
      <category>redis</category>
      <category>node</category>
    </item>
  </channel>
</rss>
