Deploying a Python app on an AWS production server
with Passenger in Standalone mode on Ubuntu 18.04 LTS (with APT)

This page describes the deployment of a Python app, assuming that Passenger was installed through the following operating system configuration or installation method: Ubuntu 18.04 LTS (with APT). Is this not how Passenger was installed? Go back to the operating system / installation method selection menu.

On this page you will learn how you can deploy your app to a server that is running Passenger. You can either follow these instructions with your own app, or you can use the sample Flask app we prepared.


Table of contents

  • Loading...

1 Transferring the app code to the server

1.1 Push your code to a Git repository

If you are using our sample app, you can skip to the next step.

We want to transfer our application's code to the server. The easiest way to do that is via Git.

If you have already setup a Git repository, push your application's code to that repository by running this on your local computer:

$ git push

If you have not already setup a Git repository, go to Github, create a repository and push your application's code there.

1.2 Login to your server, create a user for the app

Login to your server with SSH:

$ ssh -i your_ec2_key.pem adminuser@yourserver.com

Replace adminuser with the name of an account with administrator privileges or sudo privileges. This is usually admin, ec2-user, root or ubuntu.

Starting from this point, unless stated otherwise, all commands that we instruct you to run should be run on the server, not on your local computer!

Now that you have logged in, you should create an operating system user account for your app. For security reasons, it is a good idea to run each app under its own user account, in order to limit the damage that security vulnerabilities in the app can do. Passenger will automatically run your app under this user account as part of its user account sandboxing feature.

You should give the user account the same name as your app. But for demonstration purposes, this tutorial names the user account myappuser.

$ sudo adduser myappuser

We also ensure that that user has your SSH key installed:

$ sudo mkdir -p ~myappuser/.ssh
$ touch $HOME/.ssh/authorized_keys
$ sudo sh -c "cat $HOME/.ssh/authorized_keys >> ~myappuser/.ssh/authorized_keys"
$ sudo chown -R myappuser: ~myappuser/.ssh
$ sudo chmod 700 ~myappuser/.ssh
$ sudo sh -c "chmod 600 ~myappuser/.ssh/*"

1.3 Install Git on the server

$ sudo apt-get install -y git

1.4 Pull code

You need to pick a location in which to permanently store your application's code. A good location is /var/www/APP_NAME. Let us create that directory.

$ sudo mkdir -p /var/www/myapp
$ sudo chown myappuser: /var/www/myapp

Replace myapp and myappuser with your app's name and your app user account's name.

Now let us pull the code from Git:

$ cd /var/www/myapp
$ sudo -u myappuser -H git clone git://github.com/username/myapp.git code

If you are using our sample app, use this Git clone command instead:

$ cd /var/www/myapp
$ sudo -u myappuser -H git clone --branch=end_result https://github.com/phusion/passenger-python-flask-demo.git code

Your app's code now lives on the server at /var/www/myapp/code.

2 Preparing the app's environment

2.1 Install app dependencies

Your application has various dependencies. They must be installed. Most of these dependencies are Python libraries. A common way to install Python libraries is through pip. For example, if your application depends on Flask:

$ sudo pip install flask

Your app may also depend on services, such as PostgreSQL, Redis, etc. Installing services that your app depends on is outside of this tutorial's scope.

3 Starting the app in Passenger

Now that you are done with transferring your app's code to the server and setting up an environment for your app, it is time to start your app in Passenger.

3.1 Create a Passenger config file

Since this is a production environment, we need to customize Passenger a little bit. Go to your application's code directory and create a file named Passengerfile.json:

$ cd /var/www/myapp/code
$ sudo nano Passengerfile.json

Insert:

{
  // Tell Passenger that this is a Python app.
  // Replace "passenger_wsgi.py" with your app's WSGI entry point file.
  "app_type": "wsgi",
  "startup_file": "passenger_wsgi.py",
  // Run the app in a production environment. The default value is "development".
  "environment": "production",
  // Run Passenger on port 80, the standard HTTP port.
  "port": 80,
  // Tell Passenger to daemonize into the background.
  "daemonize": true,
  // Tell Passenger to run the app as the given user. Only has effect
  // if Passenger was started with root privileges.
  "user": "myappuser"
}

Replace myappuser with your app's user account name.

Finally, fix the permissions on the file:

$ sudo chown myappuser: Passengerfile.json

3.2 Start Passenger Standalone

While in your application's code directory, start Passenger. As configured, it will start on port 80 and will daemonize into the background.

Note that, because Passenger is configured to listen on port 80, this command must be run with root privileges. Only root privileged processes can listen on ports lower than 1024.

$ cd /var/www/myapp/code
$ sudo passenger start

3.3 Test drive

You should now be able to access your app through the server's host name! Try running this from your local computer. Replace yourserver.com with your server's hostname.

$ curl http://yourserver.com/
...your app's front page HTML...

If you do not see your app's front page HTML, then the most likely cause is that you did not setup DNS records. Setting up DNS is outside the scope of this tutorial. In the mean time, we recommend that you use your server's IP address as the server name.

3.4 Make sure Passenger Standalone starts on system boot

Passenger is now running and serving your app, but that only lasts until you reboot your server. So you must configure your server to start Passenger Standalone on system boot.

The easiest way to do that is to add it to the file /etc/rc.local. This script is called during system boot. Ensure that it's executable and open it in a text editor:

$ sudo chmod +x /etc/rc.local
$ sudo nano /etc/rc.local

Here is an example of what you may want to add to /etc/rc.local. If there is an exit command in rc.local, make sure you add these before the exit command.

#!/bin/sh
# Change working directory to your webapp.
cd /var/www/myapp/code

# Start Passenger Standalone in daemonized mode. Passenger will be started as
# root when run from this file, but Passengerfile.json tells it to drop its
# privileges to a normal user.
passenger start

Next step

Congratulations, you have successfully deployed your app!

Continue: Deploying updates »