Local Hosting pt II: Flask and Apache
In part one, we went over how to host a website on your a raspberry pi in your home. Next, we need to take it to the next level. Currently our self hosted website is just static assets--like css, html, and javascript.
If we want our apache server to handle data, we need to have a backend. Enter flask and way too much time setting up config stuff.
Before we get started, we are assuming you have a linux machine set up and apache2 installed. Our linux machine will be our raspberry pi.
Step One: Install and Enable mod_wsgi
WSGI (Web Server Gateway Interface) is an interface between web servers and web apps for python. Python is single threaded, meaning that it can only do one thing at a time. As you can imagine, if one user had to wait for another in order to do something on your website, then it wouldn't be a very popular site. WSGI fixes that problem.
Plus more importantly, its the needed add on to get your flask app working on an apache server, so we have to do it, even if we were cool with having a single threaded web app.
To install mod_wsgi, in the terminal type:
sudo apt-get install libapache2-mod-wsgi python-dev
Next, you need to enable mod_wsgi
sudo a2enmod wsgi
Step Two: Creating (or Moving) your Flask App
Next we need to have an app to actually serve on the server, and your static website won't work here.
It is convention to store your app in the /var/www directory. If for whatever reason you don't have permission to write in that folder use the following command:
chmod -R "USERNAME" /var/www
So lets move into this folder:
cd /var/www
If you have an app, move it into this folder now (preferably using git). Once its in there you can skip ahead to Step Three. If not, lets create an app.
Ok back to creating the app--
Lets create a project folder and move into it:
sudo mkdir proj
cd proj
Create another folder called flaskapp and move into it:
sudo mkdir flaskapp
cd flaskapp
Next we are going to create some folders inside here:
sudo mkdir static templates
Your directory structure should look like the following:
|----proj
|---------flaskapp
|--------------static
|--------------templates
You should currently be in the flaskapp directory. You can always check this with
pwd
. Next we are going to add the barebones logic for our flask app.
sudo nano __init__.py
And within that file we just created, copy paste the following:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "My first flask app"
if __name__ == "__main__":
app.run()
Save and close!
Step Three: Install Flask and Create a Virtual Environment
NOTE: if you used git to bring your app over into /var/www then you can skip this step. Just check and make sure that venv has all the packages you need. We will cover this in Step Four.
In general, you should set up a virtual environment to keep your application isolated from the rest of your server.
Make sure you are using python3. To test enter the following:
python3
If you see >>> _
that means that you have python3 installed and working. Type in
exit()
to leave.
Python 3 is needed as it supports virtual environments out of the box. So we can use the following to create a virtual environment:
sudo virtualenv venv
Next we need to activate the venv.
source venv/bin/activate
Once it is done your console will change from $
to (venv) $ _
.
Python 3 comes with pip, which is python's package manager. We will use that to install flask.
sudo pip install flask
Step Four: Checking our Progress
Let's stop and breathe for a second. Too dramatic? Probably. But let's stop anyways and make sure that we have what we need.
First let's look at directory structure:
|----proj
|---------flaskapp
|--------------static
|--------------templates
|--------------venv
If yours looks like that, we are looking good thus far. Next let's make sure flask is in our virtual environment. Let's cd into our virtual environment and make sure its there.
cd /var/www/proj/flaskapp/venv/lib/python3.7/site-packages
ls
You should see a bunch of packages here including flask. If you can't get to that directory it might be
because python 2 not 3.7 is installed in venv. Got to venv/lib
to check.
Next lets get back to where we should be:
cd /var/www/proj/flaskapp/
And see if we can run __init__.py
.
sudo python __init__.py
It should display “Running on http://localhost:5000/” or "Running on http://127.0.0.1:5000/".
If not, check your folder structure and make sure they you have all the packages and stuff.
Ok, lets get out of the virtual environment:
deactivate
Step Five: Create the .wsgi File
This file will actually serve the flask app.
We are going to store this in the proj folder:
cd /var/www/proj
sudo nano config.wsgi
Add the following:
import sys
import logging
import site
# this tells wsgi where the libraries are
site.addsitedir('/var/www/proj/flaskapp/venv/lib/python3.7/site-packages')
logging.basicConfig(stream=sys.stderr)
# name of the top level folder for the project
sys.path.insert(0,"/var/www/proj/")
# flaskapp will be the inner folder from your project folder
from flaskapp import app as application
application.secret_key = 'key'
So there are three comments here and three things you may want to change. Let's walk through all three.
Where your libraries are
# this tells wsgi where the libraries are
site.addsitedir('/var/www/proj/flaskapp/venv/lib/python3.7/site-packages')
logging.basicConfig(stream=sys.stderr)
This part tells WSGI where your virtual environment is. It should point to your venv folder in your project.
Where your project is
# name of the top level folder for the project
sys.path.insert(0,"/var/www/proj/")
This tells python where the root directory is for the project. It should be the top level folder for your project.
Where your app is
# flaskapp will be the inner folder from your project folder
from flaskapp import app as application
application.secret_key = 'key'
On line 2 where it says from flaskapp
, replace flaskapp
with whatever the name of your
app is (its the folder within your proj folder).
Step Six: Configure and Enable Your Virtual Host
This is going to tell apache which app to run.
sudo nano /etc/apache2/sites-available/FlaskApp.conf
Add the following to the file:
<VirtualHost *:80>
ServerName <<YOUR IP ADDRESS>>
WSGIScriptAlias / /var/www/proj/config.wsgi
<Directory /var/www/proj/flaskapp/>
Order allow,deny
Allow from all
</Directory>
Alias /static /var/www/proj/flaskapp/static
<Directory /var/www/proj/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 your file.
Next enable the virtual host with the following command:
sudo a2ensite FlaskApp
Step Seven: Restart Apache and Bask in Success
Finally, just restart apache to apply the changes.
sudo service apache2 restart
You shouldn't get any error messages at this point! To check and make sure this worked go to a different laptop and enter your IP address into your web browser, and you should see your flask app!
Just in Case:
Let's say that not everything is perfect, and you are getting a server 500 error at this point. Let's go over how to check the error logs.
To check the error logs:
nano /var/log/apache2/error.log
If there is a bunch of information in there, you may want to clear out the logs first.
sudo bash -c 'echo > /var/log/apache2/error.log'
Then refresh the page and view the logs again.
nano /var/log/apache2/error.log