Tutorial

How To Deploy a Flask Application on an Ubuntu VPS

Published on July 4, 2013
author

Kundan Singh

How To Deploy a Flask Application on an Ubuntu VPS
Not using Ubuntu 12.04?Choose a different version or distribution.
Ubuntu 12.04

What the Highlighting Means

The lines that the user needs to enter or customize will be highlighed in this tutorial! The rest should mostly be copy-and-pastable.

Introduction

Flask is a micro-framework written in Python and based on the Werkzeug and Jinja2 template engine for developing web applications. It is intended for developing web apps quickly.

Setup

You need to have Apache already installed and running on your VPS. If this is not the case, follow Step One of our article on installing a LAMP stack on Ubuntu.

Step One— Install and Enable mod_wsgi

WSGI (Web Server Gateway Interface) is an interface between web servers and web apps for python. Mod_wsgi is an Apache HTTP server mod that enables Apache to serve Flask applications.

Open terminal and type the following command to install mod_wsgi:

sudo apt-get install libapache2-mod-wsgi python-dev

To enable mod_wsgi, run the following command:

sudo a2enmod wsgi 

Step Two – Creating a Flask App

In this step, we will create a flask app. We will place our app in the /var/www directory.

Use the following command to move to the /var/www directory:

cd /var/www 

Create the application directory structure using mkdir as shown. Replace "FlaskApp" with the name you would like to give your application. Create the initial directory FlaskApp by giving following command:

sudo mkdir FlaskApp

Move inside this directory using the following command:

cd FlaskApp

Create another directory FlaskApp by giving following command:

sudo mkdir FlaskApp

Then, move inside this directory and create two subdirectories named static and templates using the following commands:

cd FlaskApp
sudo mkdir static templates

Your directory structure should now look like this:

|----FlaskApp
|---------FlaskApp
|--------------static
|--------------templates

Now, create the __init__.py file that will contain the flask application logic.

sudo nano __init__.py 

Add following logic to the file:

from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
    return "Hello, I love Digital Ocean!"
if __name__ == "__main__":
    app.run()

Save and close the file.

Step Three – Install Flask

Setting up a virtual environment will keep the application and its dependencies isolated from the main system. Changes to it will not affect the cloud server's system configurations.

In this step, we will create a virtual environment for our flask application.

We will use pip to install virtualenv and Flask. If pip is not installed, install it on Ubuntu through apt-get.

sudo apt-get install python-pip 

If virtualenv is not installed, use pip to install it using following command:

sudo pip install virtualenv 

Give the following command (where venv is the name you would like to give your temporary environment):

sudo virtualenv venv

Now, install Flask in that environment by activating the virtual environment with the following command:

source venv/bin/activate 

Give this command to install Flask inside:

sudo pip install Flask 

Next, run the following command to test if the installation is successful and the app is running:

sudo python __init__.py 

It should display “Running on http://localhost:5000/” or "Running on http://127.0.0.1:5000/". If you see this message, you have successfully configured the app.

To deactivate the environment, give the following command:

deactivate

Step Four – Configure and Enable a New Virtual Host

Issue the following command in your terminal:

sudo nano /etc/apache2/sites-available/FlaskApp

NOTE: Newer versions of Ubuntu (13.10+) require a ".conf" extension for VirtualHost files -- run the following command instead:

sudo nano /etc/apache2/sites-available/FlaskApp.conf

Add the following lines of code to the file to configure the virtual host. Be sure to change the ServerName to your domain or cloud server's IP address:

<VirtualHost *:80>
		ServerName mywebsite.com
		ServerAdmin admin@mywebsite.com
		WSGIScriptAlias / /var/www/FlaskApp/flaskapp.wsgi
		<Directory /var/www/FlaskApp/FlaskApp/>
			Order allow,deny
			Allow from all
		</Directory>
		Alias /static /var/www/FlaskApp/FlaskApp/static
		<Directory /var/www/FlaskApp/FlaskApp/static/>
			Order allow,deny
			Allow from all
		</Directory>
		ErrorLog ${APACHE_LOG_DIR}/error.log
		LogLevel warn
		CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Save and close the file.

Enable the virtual host with the following command:

sudo a2ensite FlaskApp

Step Five – Create the .wsgi File

Apache uses the .wsgi file to serve the Flask app. Move to the /var/www/FlaskApp directory and create a file named flaskapp.wsgi with following commands:

cd /var/www/FlaskApp
sudo nano flaskapp.wsgi 

Add the following lines of code to the flaskapp.wsgi file:

#!/usr/bin/python
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0,"/var/www/FlaskApp/")

from FlaskApp import app as application
application.secret_key = 'Add your secret key'

Now your directory structure should look like this:

|--------FlaskApp
|----------------FlaskApp
|-----------------------static
|-----------------------templates
|-----------------------venv
|-----------------------__init__.py
|----------------flaskapp.wsgi

Step Six – Restart Apache

Restart Apache with the following command to apply the changes:

sudo service apache2 restart 

You may see a message similar to the following:

Could not reliably determine the VPS's fully qualified domain name, using 127.0.0.1 for ServerName 

This message is just a warning, and you will be able to access your virtual host without any further issues. To view your application, open your browser and navigate to the domain name or IP address that you entered in your virtual host configuration.

You have successfully deployed a flask application.

Article Submitted by: Kundan Singh

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
20 Comments
Leave a comment...

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

One can simply use tornado and will avoid apache and setting virtual hosts.

Old comment but…yeah you sure can, and i’ve actually been playing with tornado frontended with cloudflare as my nginx/cache/security. It works really well and multi-threading is pretty sweet too. Example deployment with tornado below…

##########

Main

##########

if name == “main”:

# TORNADO WEB SERVER REGISTRATION
server = HTTPServer(WSGIContainer(app))
server.bind(80)
server.start(0)  # Forks multiple sub-processes, 1 per CPU
IOLoop.current().start()

I have followed this exactly, but instead of putting mywebsite.com i put flaskapp.myip in and tried going to http://flaskapp.myip. It came up with a “flaskapp.myip is unavailable or may not exist.” error.

What should I do?

Okay, now I’ve got it to sort of work, but instead of it showing the “Hello I love Digital Ocean” message it just shows me a directory of my files… :/

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
August 16, 2013

@garethprice: Disable Apache’s default virtualhost:

<pre>sudo a2dissite default</pre>

Edit the virtualhost you created and set ServerName to e.g. <pre> ServerName flaskapp.dev</pre> and restart Apache.

<pre>sudo service apache2 restart</pre>

Edit <pre>/etc/hosts</pre> <strong>on your computer</strong> and add this line to the bottom:

<pre>1.2.3.4 flaskapp.dev</pre>

Where 1.2.3.4 is your droplet’s IP address. Save it and point your browser to http://flaskapp.dev - it should load your flask app properly.

Thanks, Kamal. I’ll give it a go.

But what if I want others to be able to access it?

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
August 17, 2013

@garethprice: I assumed you don’t have a domain name since you set it to something.ip at first. If you own a domain name:

Kamal,

I set up a new droplet and followed this tutorial: https://www.digitalocean.com/community/articles/how-to-launch-your-site-on-a-new-ubuntu-12-04-server-with-lamp-sftp-and-dns

I did what you suggested and all I get is my list of files still. I’ve copied exactly your FlaskApp demonstration. You can see them at: http://opendiscovery.co.uk/FlaskApp/

Sorry for being noobish.

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
August 21, 2013

@garethprice: Try running the following commands:

<pre>sudo a2dissite default sudo service apache2 restart</pre>

Does that fix it?

Yes, thank you! Last question: is there a way of getting the normal apache to load html/php files in the root dir, and wsgi to handle Flask in a subdir (as achieve through WSGIScriptAlias)?

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
August 27, 2013

@garethprice: The recommended way of doing that is to have php/html in a separate directory and your flask app in another directory and <strong>not</strong> mixing both apps together.

Create a separate virtualhost on a separate subdomain/domain for the php/html app.

Hi I have followed the exacts steps as recommended. All the print statements from apache to flaskapp.wsgi to init.py file gets printed. No error reported in apache-error log file From from FlaskApp import views also works fine as it prints the first line in views.py but when I type the url http://ip/hello in the browser and post I get 404.

View.py #from FlaskApp import app app = Flask(name) @app.route(“/hello”) def hello(): return “Hello, World!” init.py from flask import Flask print “Importing 1” #app = Flask(name) app = Flask(‘FlaskApp’) from FlaskApp import views

Can you please guide on how to resolve

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
September 2, 2013

@itsanjalirk: Please pastebin apache’s config files.

Hi - What is the purpose of creating a FlaskApp directory inside another FlaskApp directory? Is it just for python package management? Couldn’t you just have a main.py file inside one FlaskApp and then

from main import app

?

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
September 17, 2013

@john: It’s so that you can create files such as .wsgi that do not belong to the app itself but are required to make it work.

e.g. FlaskApp.wsgi is created in /var/www/FlaskApp

I am getting an import error:

ImportError: No module named flask

Isn’t the WSGI file supposed to activate the virtual environment we created or something?

If you modify your flaskapp.wsgi as such:

#!/usr/bin/python                                                                
activate_this = '/var/www/FlaskApp/FlaskApp/venv/bin/activate_this.py'
execfile(activate_this, dict(__file__=activate_this))

import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0,"/var/www/FlaskApp/")

from FlaskApp import app as application
application.secret_key = 'Add your secret key'

Lines 2 and 3 activate the virtual environment containing the Flask module you installed.

Could it be that you are using Python3?

Please use the command to install the package:

sudo apt-get install libapache2-mod-wsgi-py3

Reference: https://stackoverflow.com/a/64639580/46971

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
September 18, 2013

@ljernejcic: <pre>ImportError: No module named flask</pre>Flask isn’t installed. Did you follow <strong>Step Two – Install Flask</strong>?

Correct me if I’m wrong but you create a virtualenv and then promptly set up an app which doesn’t use the virtualenv… right?

This worked great for the simple Hello World example. I tried to adapt it to fit my own website, and it’s no longer working. The browser says 500 Internal Error, which turns out to be an ImportError inside the apache logs. I think it’s a different problem from ljernejcic because the ImportError is occurring on my own module.

The apache error.log output is at http://pastebin.com/aRau7TwA.

Thanks in advance for any ideas.

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
October 6, 2013

@brian.schiller: That paste has been removed. Are you still experiencing this issue?

I have used your above described configuration to set up my flask application and I’m experiencing following issue: Basic page (and every static page) is displayed with 404.html message. Only login page is displayed correctly. I did my site similarly as http://www.youtube.com/watch?v=jELLsj1KPNQ; tested on my own linux machine, with flask development server. It works. So, I have renamed main file (the one I called with application name to init.py, as described here. Structure looks like this:

/myapp myappwhatever.wsgi /myapp init.py /templates --------- bunch of html files (with basic html ancestor and childs) /static --------- css module1.py module2.py module3.py

And I made Apache2 and wsgi file according your description. And it does not work as supposed. Do you have any clue why?

Thanks

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.