0
votes

I have created a web app starting with the command npx create-react-app myapp. I am hoping to use Phusion Passenger with Nginx to serve the app from its own subdomain. My problem (I believe) is telling Phusion Passenger where to find the file that Node.js needs to launch.

Everything is working fine on my development machine.

I have used git push ... to upload the project to my Ubuntu 16.04 server. There, as described here, I have run npm run build.

According to the documentation this...

  • Builds the app for production to the build folder.
  • Correctly bundles React in production mode and optimizes the build for the best performance.
  • Ensures that the build is minified and the filenames include the hashes.

In short: Your app is ready to be deployed.

I've successfully used serve -s build to launch the app on port 5000, and have checked using curl http://localhost:5000 that a minified HTML file is served locally on the server.

Now I need to tell Phusion Passenger to launch the app, and this is where I need help. Following the instructions here, I've created the following nginx config file:

server {
    listen 80;
    server_name subdomain.example.com;

    # Tell Nginx and Passenger where your app's 'public' directory is
    root /var/www/myapp/web/public;

    # Turn on Passenger
    passenger_enabled on;
    # Tell Passenger that your app is a Node.js app
    passenger_app_type node;
    passenger_startup_file app.js; ## THIS IS WHERE I THINK THE ISSUE IS ##
} 

My understanding is that the last line must indicate which file Node.js should be launching. In the case of a project create using npx create-react-app..., the file launched by Node.js in development mode is at src/index.js, and not app.js.

Where should I tell passenger_startup_file to find the file to run in production mode? Or should I be thinking about this in a completely different way?

1

1 Answers

0
votes

Your approach is OK and Nginx/Phusion Passeger run by default in production mode.

I didn't try running Node apps yet but I did it for Python. I assume for Node it works the same way. However, I didn't need to specify the passenger_app_type and passenger_startup_file bacause the Phusion Passenger uses default Python app settings like:

passenger_app_type wsgi;
passenger_startup_file passenger_wsgi.py;

The passenger_wsgi.py or in your case the app.js is the application entry point so it must be created in the app's folder, in your case: /var/www/myapp/web In this file you need to import your actual Node app. So leave the config file like it is but make sure in the app.js you import and start your Node app. The wsgi app-name must be 'application' so in my case (Python app) the passenger_wsgi.py contains just a single line:

from app import MyApp as application

It may be possible that your app.js already is your Node app so you don't need to import your app there, it depends on how you set things up...

You can see the error log at nginx default location /var/log/nginx/error.log but to see the contents you probably need to use:

sudo vi /var/log/nginx/error.log

Open the file and clear it or mark the last line with "START NEW LOG" so you know where the new log starts when you next time open the log to view it. Restart your server with:

$ sudo service nginx restart

Then go to your browser and open your page: http://www.yourdomain.com then go back to your server and view the Nginx error log.

What do you see in the log? Sometime it help to have your Node script or your entry point file (app.js) to print some info like environment variables etc to be sure it uses the right ones and that everything is set as you expect. So for Python I would do in my app.py or directly in passenger_wsgi.py:

import sys
import os 
def application(environ, start_response):
       start_response("200 OK", [("Content-Type", "text/plain")])
       ret = ["%s: %s\n" % (key, value)
               for key, value in environ.items()]
       ret.append('sys.version: {}\n'.format(sys.version))
       ret.append('sys.executable: {}\n'.format(sys.executable))
       ret.append('sys.path: {}\n'.format(sys.path))
       return ret

But you need to translate it to JavaScript or TypeScript as your app is a Node app. So next time you open your app in the browser you will see the environment and system settings printed. Then you need to compare it with what you see when you run the app locally on the server in Terminal (not using the browser and URL) Hope it helps