Deploying a Flask app on Opalstack

2020-10-22


Deploying a Flask app on Opalstack

Flask is a micro web framework allowing one to write web applications in python. Its my preferred tool for writing everything from static sites (with flask-freeze as a static site generator) to small websites to larger applications due to its flexibility. I have been using Webfaction for hosting my projects for a few years. For a comparatively modest price, I get a shared server on which I can host any number of apps. Unfortunately, Webfaction were taken over by another company and their automatic migration to tsohost failed, so I decided it was time to look for a new home for the apps. A little research suggested that Opalstack was the best fit, as their services and setup is very similar to Webfacton.

So I signed up for a "Value stack" at $9.50 per month and set out to see how easy or difficult it was to deploy a flask application. The documentation on Opalstack (https://help.opalstack.com/article/60/pythonuwsgi-applications) regarding this is quite good and overall deployment is a lot easier than on Webfaction, but let me document the whole procedure as it may be helpful for someone.

Let's first write a very basic app in flask.


mkdir my_app
mkvirtualenv -p /usr/bin/python3 flask_basic
pip install flask

It's always better to work in a virtual environment and while I am using to mkvirtualenv to create that, you can do it any other way too. The simplest flask application below with just one route that says "Hello!".


# my_app/__init__.py
"""
Minimal flask app to test deployment
"""

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return "Hello!"


if __name__ == "__main__":
    app.run(port=8080)

In a terminal, if we now run


export FLASK_APP=my_app
flask run

we should see "Hello!" at localhost:8080. Now that we have the app running locally, we can test the deployment.

In Opalstack, go to applications > Add application and choose python/uWsgi. Lets give it a name 'my_app' and click on the button to add the application.

If you haven't done it already, create a shell user. If you log in with ssh and your shell user credentials now, you can see the application in your apps folder. Note that for the ssh login below, you will have to use the shell username that you created. The server name may also be different.


$ ssh {username}@opal5.opalstack.com
$ ls apps
my_app
$ ls apps/my_app
env start stop kill tmp myapp uwsgi.ini
$ exit

Very helpfully a virtual environment is already set up (env) and there are scripts to control the application (start, stop and kill). All we need to do is replace the sample app (myapp) with our application and modify uwsgi to point to it.

Lets push the files.


$ rsync -av  -e ssh {username}@opal5.opalstack.com

This command can now be used each time you want to push modified code from now onwards. Now lets install the dependencies in the virtual environment and then modify the uwsgi.ini file.


$ ssh {username}@opal5.opalstack.com
$ cd apps/my_app
$ source env/bin/activate
$ pip install flask
$ {your_favourite_editor} apps/my_app/uwsgi.ini

Uncomment the last two line (wsgi-file and touch-reload) and direct to your app like this.


#wsgi-file = /home/username/apps/appname/myapp/wsgi.py
#touch-reload = /home/username/apps/appname/myapp/wsgi.py
module = myapp:app
touch-reload = /home/{username}/apps/my_app/myapp/__init__.py

Restart the server now and we should be good to go.


$ ./stop
$ ./start

To have the site accessible from a domain name, lets create a domain and a site route. In the menu, click on 'Domains' and add domain. Since the domain .opalstacked.com is available, you can use the domain myapp..opalstacked.com to host the application. Once this domain is created, click on 'Site Routes'. Give it a name, choose the my_app application, select the domain we created and set the route to '/'. Now the application would be served from the domain name.

Navigate to my_app.{username}.opalstacked.com on your browser now and you should see "Hello!". Now we can go ahead and expand it into a more useful application.