Search code examples
nginxflaskubuntu-16.04passengervps

Deploying Flask app on NginX / Passenger server on Ubuntu 16.04 LTS in production mode on VPS


Question 1: What is the problem?: Following this tutorial I installed Nginx and Passenger on Ubuntu 16.04 to run Python Flask app and I run into this issue: When I visit my server at http://hXXXXXXX.stratoserver.net/ in the browser I am getting this error:

We're sorry, but something went wrong.

Question 2: Passenger version and integration mode: Passenger open source 6.0.4 + Nginx

Question 3: OS or Linux distro, platform (including version): Ubuntu 16.04 LTS

$ uname -a
Linux hXXXXXXX.stratoserver.net 4.4.0-042stab141.3 #1 SMP Fri Nov 15 22:45:34 MSK 2019 x86_64 x86_64 x86_64 GNU/Linux

Question 4: Passenger installation method: Nginx + Phusion APT repo

Question 5: Your app's programming language: Python 3.7.6 + Flask 1.1.1

Question 6: Are you using a PaaS and/or containerization? If so which one? No

Question 7: Anything else about your setup that we should know? I have a VPS at strato.nl with Ubuntu 16.04 installed, and the host address is: http://hXXXXXXX.stratoserver.net/ and I was following "Deploying a Python app with Passenger to production" tutorial making the following choices in the tutorial:

1. Linux/Unix
2. Nginx
3. Passenger open source
4. Python installed via LinuxBrew (Python v3.7.6)
5. Ubuntu 16.04 LTS
6. Demo Flask app from github

The demo Flask app was cloned from Phusio Passenger github like this:

git clone https://github.com/phusion/passenger-python-flask-demo.git

Running passenger-memory-stats gives:

$ sudo /usr/sbin/passenger-memory-stats
Version: 6.0.4
Date   : 2020-01-29 13:12:15 +0100
------------- Apache processes -------------
*** WARNING: The Apache executable cannot be found.
Please set the APXS2 environment variable to your 'apxs2' executable's filename, or set the HTTPD environment variable to your 'httpd' or 'apache2' executable's filename.


---------- Nginx processes -----------
PID    PPID   VMSize    Private  Name
--------------------------------------
23320  1      174.9 MB  0.8 MB   nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
23325  23320  174.9 MB  0.8 MB   nginx: worker process
### Processes: 2
### Total private dirty RSS: 1.54 MB


----- Passenger processes -----
PID    VMSize    Private  Name
-------------------------------
23309  445.7 MB  2.5 MB   Passenger watchdog
23312  672.3 MB  7.5 MB   Passenger core
### Processes: 2
### Total private dirty RSS: 9.98 MB

When I run the app locally on the server everything works as expected:

$ python app.py
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Then in another terminal:

$ curl localhost:5000
<!DOCTYPE html>
<html>
<head>
  <title>Hello</title>
  <style>
    html, body {
      font-family: sans-serif;
      background: #f0f0f0;
      margin: 4em;
    }

    .main {
      background: white;
      border: solid 1px #c0c0c0;
      border-radius: 8px;
      padding: 2em;
    }
  </style>
</head>
<body>

  <section class="main">
    <h1>Hello world!</h1>
    <p>Welcome to the Passenger Flask example app.</p>
  </section>

</body>
</html>

So it looks like locally all works fine. However when I visit http://hXXXXXXX.stratoserver.net/ in the browser I got an error page like described above. The nginx error /var/log/nginx/error.log contains the following:


App 29730 output: from flask import Flask, render_template
App 29730 output: ImportError
App 29730 output: :
App 29730 output: No module named flask

So it looks like the script cannot find the packages I previously installed for Python3 and it uses Python2 packages. Printing sys.version in server response gives:

sys.version: 2.7.17 (default, Dec 24 2019, 17:49:09)

I installed all my packages for Python3 so I need my script on the server uses Python3. How can I setup the Python version and Python libraries in NginX/Passenger?

My demoapp config is:

$ vi /etc/nginx/sites-enabled/demoapp.conf
server {
    listen 80;
    server_name hXXXXXXX.stratoserver.net;

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

    # Turn on Passenger
    passenger_enabled on;
}

What are the passenger / Nginx settings that I need to set to successfully run a Flask application? How can I set Passenger / Nginx to use Python3 and Python3 site-packages?


Solution

  • The solution is to add the path to Python's binary in the app's config file (in the server context). So now my config file demoapp.conf looks like:

    $ vi /etc/nginx/sites-enabled/demoapp.conf
    server {
        listen 80;
        server_name hXXXXXXX.stratoserver.net;
    
        # Tell Nginx and Passenger where your app's 'public' directory is
        root /var/www/demoapp/code/public;
        
        # Tell Nginx and Passenger which Python executable to use
        passenger_python /Users/<username>/.pyenv/versions/3.9.2/envs/v3.9.2/bin/python3;
    
        # Turn on Passenger
        passenger_enabled on;
    }
    

    And everything works as expected. Please note this line:

    passenger_python /home/linuxbrew/.linuxbrew/bin/python3;
    

    which points to the Python v3.7.6 binary I installed with linuxbrew.

    Another option is to use Python virtual environment where you can also specify the Python version you want to use.