How to Deploy a Flask App in Ubuntu 20.04 using Apache and Passenger

Flask is a Python micro framework that is very popular. In this guide we will deploy a Flask application on an Ubuntu 20.04 server using Apache Web Server and Passenger. Passenger is an open source web application server

Prerequisites

  • A domain name (or subdomain) we’ll use to access our deployed application
  • A server installed with Ubuntu 20.04
  • Python 3.x. Our sample app runs on python 3.
  • Your application should be pushed to Github or Gitlab. I use Gitlab here

Procedure

1. Acquire a server.

Your choice of Cloud Provider for your applucations depends on your preferences. There are many such as AWS, GCP, Azure, Digital Ocean, Linode, Vultr and in Africa, Truehost Cloud

2. Uninstall Python 2 (If it comes by default with your installation) and Install Python3

To uninstall Python 2, run the commands below

sudo apt remove python2
sudo apt remove python-is-python2
sudo apt autoremove --purge

To install python3, run the command below

sudo apt-get update
sudo apt-get install -y python3 python3-pip

You can then run the command below to set aliases for python and python3 commands

sudo apt-get install python-is-python3

3. Install Apache

sudo apt-get install apache2

4. Install Passenger and Apache modules Install Passengers PGP key and enable https support for APT

sudo apt-get install -y dirmngr gnupg
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
sudo apt-get install -y apt-transport-https ca-certificates

Add Passenger’s repo

sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger bionic main > /etc/apt/sources.list.d/passenger.list'
sudo apt-get update

Install Passenger and Mod Passenger

sudo apt-get install -y libapache2-mod-passenger

You can then enable the passenger module, so it automatically starts on reboot

sudo a2enmod passenger
systemctl restart apache2

Validate whether Passenger has been installed properly

sudo /usr/bin/passenger-config validate-install

5.On the server, create a user for your App. By convention, the user has the same name as the app. In my case here, I will use the username portfolio

useradd portfolio
passwd portfolio

6.Install Git

sudo apt-get install -y git

7.Upload your application files. We’ll use git and pull our app from Gitlab
We’ll first navigate to the application folder location. This is /var/www/portfolio for me

sudo mkdir -p  /var/www/portfolio
sudo chown portfolio: /var/www/portfolio

Replace the first portfolio with your App User created in step 5 above and the last portfolio with your App document root. To pull our code, run the following

cd /var/www/portfolio
sudo -u portfolio -H git clone https://gitlab.com/wwmwabini/portfolio.git code

Replace the git URL with your application URL

8.Install app dependencies.
Most times, dependencies should be included in your requirements.txt file. If you didn’t create this, you can first go back to you development environment and run the command below to get your packages into a requirements.txt file

pip freeze >> requirements.txt

Once you get it and upload it to the server, run the command below to install packages

pip3 install -r requirements.txt

9.Configure Apache and Passenger to serve your application
Create a VHOST for your application

sudo vim /etc/apache2/sites-enabled/portfolio.conf

Copy the content below into your portfolio.conf file.

<VirtualHost *:80>
    ServerAdmin [email protected]
    ServerName ww.mwabini.co.ke

    # Tell Apache and Passenger where your app's code directory is
    DocumentRoot /var/www/portfolio/code/
    PassengerAppRoot /var/www/portfolio/code

    # Tell Passenger that your app is a Python app
    PassengerAppType wsgi
    PassengerStartupFile passenger_wsgi.py

    ErrorLog /var/www/ww.mwabini.co.ke/logs/error.log
    CustomLog /var/www/ww.mwabini.co.ke/logs/access.log combined

    Alias /static/ /var/www/portfolio/static
    <Directory /var/www/portfolio/static>
        Order allow,deny
        Allow from all
    </Directory>

</VirtualHost>

Replace ww.mwabini.co.ke with your server’s host name, replace /var/www/portfolio/code with your application’s code directory path and replace passenger_wsgi.py with your app’s WSGI entry point file.

10.Restart Apache

systemctl restart apache2

Congrats! Your site is now deployed and should be accessible via your server’s hostname, in my case, ww.mwabini.co.ke

Troubleshooting

If your site does not load, you can troubleshoot it by enabling error display on the site, or reviewing the logs. You can remove the friendly page of Passenger by adding the directive below in your VHOST just under PassengerStartupFile passenger_wsgi.py line

PassengerAppEnv development

This will display the actual error on the site and allow you to troubleshoot. Once done, remove the line or comment it out.
Once you enable errors display as above there are 2 errors you may encounter

  1. /bin/sh: 1: exec: python: not found

CAUSE: A probable cause for this is the missing Python 2 since we uninstalled it. Passenger is trying to execute the python code using python command but misses it because the command is normally used with python 2 by default.


FIX: The solution is to install aliases that map python command to python3 using the command below

apt-get install python-is-python3

2.ImportError: No module named flask

CAUSE: A probable cause for this is missing flask module because when we installed it, it was installed in python2 yet our app uses python3. This is why we started by removing python 2.


FIX: Remove python 2 as your app does not need it and use python3, then run the command below to avoid error 1

apt-get install python-is-python3


NOTE: This solution best works for you if the only thing running on your server is the Flask application. If this is on localhost, where you probably have some desktop applications that need python 2, its probably not a good idea to uninstall python2. In that case, you need to either deploy the app on a virtual environment (e.g using PyCharm) or install VirtualBox where you can spin up a server for operations without affecting your localhost setup.

3.Error in database connection

If your app uses MySQL 8 and you experience issues connecting to the database, you may consider using the checking the below solution on stack overflow

https://stackoverflow.com/questions/39281594/error-1698-28000-access-denied-for-user-rootlocalhost

Leave a Reply

Your email address will not be published. Required fields are marked *