Sitecore Rendering Host on Azure Linux web app loading with error 500

Sitecore Rendering Host on Azure Linux web app loading with error 500

Sitecore JSS Next.js app deployment on Azure Linux Web App

·

11 min read

Introduction

I recently worked on a project that used Sitecore 10.3 XM (Sitecore Experience Edge [XE] for content delivery), the Sitecore JavaScript Rendering SDK (JSS) for Next.js front-end build, and the Sitecore Headless SXA (Sitecore Experience Accelerator) for setting up the content tree. As you are aware, Next.js applications can be hosted using various services, depending on the prerendering form and your preference.

We decided to set up Sitecore Rendering Host on Azure Linux Web App Service instead of Vercel as the hosting choice for the SSG Next.JS project due to security concerns.

Deploying a modern Sitecore JSS Next.js app on a Azure Linux web app sounds like a recipe for success, but we greeted by a daunting 500 Internal Server error at start-up 😁. Fear not, fellow developers, this blog post chronicles my journey of troubleshooting and resolving start-up issues that led to Error 500 Internal Server on a setup of Sitecore Rendering Host which deployed (Next.js deployment) on Azure Linux Web App. 🔝

The Challenge

The problem started when our Next.js application on an Azure Linux Web App began to load with an error message indicating an internal 500 server. This error is a generic HTTP status code that indicates an unexpected condition was encountered.

When attempting to visit the Sitecore Rendering Host (front-end application built with the Sitecore JSS Next.js SDK), we were seeing the Application Error screen in the browser: 🔝

🕵️The Investigation

I looked through the server logs first in an attempt to identify the source of the issue. Server logs are a treasure trove of data and frequently reveal what's wrong with the system.

Sitecore Rendering Host (Front-end app)

  1. In our instance, the problem was occurring during the web application's start-up, according to the Sitecore Rendering Host logs, which were confirmed by the following logs: 🔝

     Require stack:
         - /home/site/wwwroot/node_modules/.bin/next
         at Module._resolveFilename (node:internal/modules/cjs/loader:939:15)
         at Module._load (node:internal/modules/cjs/loader:780:27)
         at Module.require (node:internal/modules/cjs/loader:1005:19)
         at require (node:internal/modules/cjs/helpers:102:18)
         at Object.<anonymous> (/home/site/wwwroot/node_modules/.bin/next:3:35)
         at Module._compile (node:internal/modules/cjs/loader:1105:14)
         at Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
         at Module.load (node:internal/modules/cjs/loader:981:32)
         at Module._load (node:internal/modules/cjs/loader:827:12)
         at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12) {
             code: 'MODULE_NOT_FOUND',
             requireStack: [ '/home/site/wwwroot/node_modules/.bin/next' ]
         }
    
  2. We (with other team members) examined the Sitecore Rendering Host Next.js Code base package's (package.json) start-up command and details are: 🔝

     "scripts": { 
         "bootstrap": "ts-node --project tsconfig.scripts.json scripts/bootstrap.ts && graphql-let", 
         "build": "npm-run-all --serial bootstrap next:build", 
         "graphql:update": "ts-node --project tsconfig.scripts.json ./scripts/fetch-graphql-introspection-data.ts", 
         "install-pre-push-hook": "ts-node --project tsconfig.scripts.json ./scripts/install-pre-push-hook.ts", 
         "jss": "jss", 
         "lint": "eslint ./src/**/*.tsx ./src/**/*.ts ./scripts/**/*.ts", 
         "next:build": "next build", 
         "next:dev": "cross-env NODE_OPTIONS='--inspect' next dev", 
         "next:start": "next start", 
         "scaffold": "ts-node --project tsconfig.scripts.json scripts/scaffold-component/index.ts", 
         "start": " next start –p 80", 
         "start:connected": "npm-run-all --serial bootstrap --parallel next:dev start:watch-components", 
         "start:disconnected-proxy": "ts-node --project tsconfig.scripts.json ./scripts/disconnected-mode-proxy.ts", 
         "start:production": "npm-run-all --serial bootstrap next:build next:start", 
         "start:watch-components": "ts-node --project tsconfig.scripts.json scripts/generate-component-builder/index.ts --watch" 
       }
    
  3. We (with other team members) checked the webroot (wwwroot) directory of the Azure Linux web app with Kudu (Development Tools -> Advanced Tools) to identify whether the node_modules/next/dist/bin/next and /node_modules/.bin/ folder exists or not.

  4. We checked the .env file (\src\rendering\.env) of the Sitecore Rendering Host project to identify the SITECORE_API_HOST and other required configurations: 🔝

     # Your Sitecore API key is needed to build the app. Typically, the API key is
     # defined in `scjssconfig.json` (as `sitecore.apiKey`). This file may not exist
     # when building locally (if you've never run `jss setup`), or when building in a
     # higher environment (since `scjssconfig.json` is ignored from source control).
     # In this case, use this environment variable to provide the value at build time.
     SITECORE_API_KEY=
    
     # Your Sitecore API hostname is needed to build the app. Typically, the API host is
     # defined in `scjssconfig.json` (as `sitecore.layoutServiceHost`). This file may
     # not exist when building locally (if you've never run `jss setup`), or when building
     # in a higher environment (since `scjssconfig.json` is ignored from source control).
     # In this case, use this environment variable to provide the value at build time.
     SITECORE_API_HOST=
    
     # Your GraphQL Edge endpoint. This is required for Sitecore Experience Edge.
     # For Sitecore XM, this is typically optional. By default, the endpoint is calculated using
     # the resolved Sitecore API hostname + the `graphQLEndpointPath` defined in your `package.json`.
     GRAPH_QL_ENDPOINT=
    
  5. We tried changing the start-up command of the Azure Linux web app to

     /home/site/wwwroot/node_modules/next/dist/bin/next start -p 8080
    

    Then it’s giving the below error: 🔝

     ERROR - Container myapp_434amit for site myapp has exited, failing site start 
    
     ERROR - Container myapp_434amit didn't respond to HTTP pings on port: 8080, failing site start. See container logs for debugging. 
    
     INFO  - Stopping site myapp because it failed during startup
    
    💡
    The default port used by the Azure Linux web app service (container) is 8080, which it transfers to an external http/https (80/443) port.
  6. Using the following modifications made to the Sitecore Rendering Host code base's .env file (\src\rendering\.env), we attempted to build the application on an Agent PC (Win machine in build pipeline): 🔝

     # The public URL to use for absolute URLs, which are required when
     # the Next.js app is run within Sitecore editors.
     # This should match the `serverSideRenderingEngineApplicationUrl`
     # in your Sitecore configuration (see \sitecore\config\contosoproject.config).
     # Be sure to update these values accordingly as your public endpoint changes.
     # See https://jss.sitecore.com/docs/fundamentals/services/view-engine
     PUBLIC_URL=http://localhost:3000
    
     # Your Sitecore API key is needed to build the app. Typically, the API key is
     # defined in `scjssconfig.json` (as `sitecore.apiKey`). This file may not exist
     # when building locally (if you've never run `jss setup`), or when building in a
     # higher environment (since `scjssconfig.json` is ignored from source control).
     # In this case, use this environment variable to provide the value at build time.
     SITECORE_API_KEY=
    
     # Your Sitecore API hostname is needed to build the app. Typically, the API host is
     # defined in `scjssconfig.json` (as `sitecore.layoutServiceHost`). This file may
     # not exist when building locally (if you've never run `jss setup`), or when building
     # in a higher environment (since `scjssconfig.json` is ignored from source control).
     # In this case, use this environment variable to provide the value at build time.
     SITECORE_API_HOST=
    
     # Your GraphQL Edge endpoint. This is required for Sitecore Experience Edge.
     # For Sitecore XM, this is typically optional. By default, the endpoint is calculated using
     # the resolved Sitecore API hostname + the `graphQLEndpointPath` defined in your `package.json`.
     GRAPH_QL_ENDPOINT=
    
     # The way in which layout and dictionary data is fetched from Sitecore
     FETCH_WITH=GraphQL
    
     # Indicates whether SSG `getStaticPaths` pre-render any pages
     # Set the environment variable DISABLE_SSG_FETCH=true
     # to enable full ISR (Incremental Static Regeneration) flow
     DISABLE_SSG_FETCH=0
    

    The GRAPH_QL_ENDPOINT is set as the Sitecore Experience Edge (XE) end point, and SITECORE_API_HOST is empty. After that, execute the following commands on the Sitecore Rendering Host Code base root folder:

     npm run build
     npm run next:dev
    

    The Sitecore Rendering Host app is accessible using http://localhost:3000 and a static resource URL pointing to localhost:3000. 🔝

  7. we attempted to build the application on an Agent PC (Win machine in build pipeline) with all PROD environment variable configurations ▶️ PROD Build Locally (on Agent PC) ▶️ Deployed Build manually after deletion of .next folder in wwwroot of Azure Linux web app but still Sitecore Rendering Host not working and giving Application Error

  8. I also ran the npm cache clean –force command within the wwwroot directory of Sitecore Rendering Host on the Azure Linux web app, and then it worked again. 🔝

Sitecore CM Server (Back-end app)

  1. We checked the log file of the Sitecore CM role and saw the logs whenever SITECORE_API_HOST was set as the Sitecore CMS Endpoint.

⚡The Solution

Following a comprehensive analysis, I was able to determine that the root of the problem was a symlink. Specifically, the build was indeed present at /home/site/wwwroot/node_modules/next/dist/bin/next, but the symlink was attempting to execute commands from the folder /home/site/wwwroot/node_modules/.bin/next, for which there was no mapping. 🔝

What is a Symlink?
Symlinks, or symbolic links, are “virtual” files or folders which reference a physical file or folder located elsewhere, and are an important feature built in to many operating systems, including Linux and Windows. looked through the server logs first in an attempt to identify the source of the issue. Server logs are a treasure trove of data and frequently reveal what's wrong with the system.

A source of trouble occasionally arises when you attempting to deploy a Next.js code base using the command mentioned in the package.json start script (e.g.., next start) and in certain deployment it may actually fail with MODULE_NOT_FOUND error. 🔝

It appears that Azure is experiencing issues with the next start command since symlinks are kept during the build process of the Sitecore JSS Next.js SDK-based application. node_modules/.bin, which is symlinked to node_modules/next/dist/bin/next, is used by Next.js (and other frameworks of a similar nature). The .bin folder aids in enabling NPM to use various commands, such as next start.

To resolve this issue, we went with the Microsoft recommendation at Configure Node.js apps - Azure App Service | Microsoft Learn to run the application using PM2 instead of using npm start (or) node server.js (or) next start. 🔝

To implement PM2, we followed the steps mentioned on the javascript - unable to deploy next js to azure - Stack Overflow:

  1. Add the ecosystem.config.js file to your Next.JS app with the following code: 🔝

     module.exports = { 
       apps: [ 
         {      
           name: "myapp", 
           script: "./node_modules/next/dist/bin/next", 
           args: "start -p " + (process.env.PORT || 3000), 
           watch: false, 
           autorestart: true, 
         }, 
       ], 
     };
    

Change the start-up command for your Azure app to be this:

pm2 --no-daemon start /home/site/wwwroot/ecosystem.config.js

The deployed code will immediately launch PM2 as soon as it locates the ecosystem.config.js file during deployment, in accordance with the Microsoft instructions previously specified. 🔝

The container automatically starts your app with PM2 when one of the common Node.js files is found in your project:
bin/www
server.js
app.js
index.js
hostingstart.js
(or) One of the following PM2 files: process.json or ecosystem.config.js

Once the configurations were corrected, I restarted the Sitecore Rendering host app. To my relief, the Sitecore Rendering host app loaded successfully without any error 500. It was a moment of triumph, but more importantly, it was a learning experience that reinforced the importance of meticulous troubleshooting and the value of understanding the technologies we work with.

I hope that sharing my experience will help others who might be facing similar challenges. Remember, every error is a step closer to the solution. Happy debugging! 🔝

Please note that the specifics of each situation can vary, and what worked in this instance might not work in another. Always approach each problem with a fresh perspective and a willingness to explore different solutions. 

🙏Credit/References

deployment - Deploying Next.js App on Microsoft Azure App Service - Stack Overflow

Deploying NextJS app on Azure App Service (youtube.com)

javascript - unable to deploy next js to azure - Stack Overflow

Icons by icon8

Configure Node.js apps - Azure App Service - Microsoft Learn

node.js - How do I get my Next.js app to start in an Azure App Service running ubuntu-latest? - Stack Overflow

Troubleshooting JSS Next.js apps - Sitecore Documentation

Enable diagnostics logging - Azure App Service - Microsoft Learn

reactjs - How to deploy a NextJs SSR React app on Azure - Stack Overflow

asp.net mvc 5 - How to resolve error 500 on Azure web app? - Stack Overflow

NextJS Deployment on App Service Linux - (azureossd.github.io)

🔝

🏓Pingback

Enlighten with Amit (hashnode.dev)What is Sitecore Search?: A Definitive Introduction (hashnode.dev)What is Sitecore XM Cloud - XM Cloud Building blocks (hashnode.dev) 🔝
Sitecore Headless SXAsitecore jss nextjssitecore jamstack
How to resolve "HTTP/1.1 500 Internal Server Error" on AzureWhat is error code 500 in Azure?What is error 500 in Azure API?
How do I fix Microsoft 500 error?How do I fix Error 500 on my website?How to resolve error 500 on Azure web app?
Web App Service returns 500 Internal Server Error whenAddressing 500 Server Error on Web AppInternal Server Error 500 when deploying web app
Error: Failed to deploy web package to App ServiceAzure DevOps Error 500 when release App ServicePage on Static Web App throw a 500 error when I used 🔝
Server error 500 on Azure Web App deploymentFixing HTTP Error 500 on Azure App Service when runningHow to fix error 500 on azure web app
azure 500 internal server errorerror 500 azure devopsa call to warmup your site failed with response code: 'internalservererror'.
azurewebsites.net is currently unable to handle this request. http error 500azure http 1.1 500 internal server errorstatuscode 500, message'': internal server error 🔝
azure requestfailedexception service request failed statusMonitoring HTTP 5xx errors in an Azure App ServiceDiagnose Azure App Serivce (Web App) - HTTP 500 Server
500 error when run the app in azureStatic Web App Azure Functions backend returns 500 errorTroubleshooting the Azure Web App Error 500
Rendering host container returns 500Azure Sitecore WebApp 500 errors after config changeHow to fix 500 error in Sitecore ribbon on first Experience Connection to your rendering host failed with a Not Found 🔝