Deploying a Flask web application on FreeBSD • 20 Feb 2013

Flask logo Go web scale with Flask! Flask is a small framework which can be used to build web applications. It also has good documentation. Flask's built-in webserver is only usable for development, so for production purposes I use gunicorn as the webserver. It will run a few instances of the web application in a few worker threads. Nginx as a reverse-proxy is used to free the worker threads from requests by slow clients (like mobile phones). And lastly, supervisor is used to monitor the web application and restart it, should it terminate for some reason. It also starts the web application when the server reboots.

Typographical ornament

Flask and the web application

Install FreeBSD on a machine. Become root and install Python if it's not already installed. Then install pip and Flask (via pip). Alternatively, you could install the port /usr/ports/www/py-flask.

# cd /usr/ports/devel/py-pip # make install clean # pip install flask

This is the source code of the example web application (in this article, it lives in /usr/home/user/prj/python/flask-examples/example2.py):

import flask app = flask.Flask(__name__) from werkzeug.contrib.fixers import ProxyFix app.wsgi_app = ProxyFix(app.wsgi_app) @app.route("/") def index(): return "Hello, " + flask.request.remote_addr if __name__ == "__main__": app.run(host="")

Start the web application: # python example2.py * Running on

...point a webbrowser, preferably on another machine, to http://SERVER:5000/, where SERVER is the IP address of the machine you run the web application on, and the app should respond with something like this:


Ok, the webapp works. But it still uses the built-in development webserver which is not suitable for production environments.

Typographical ornament


Let's start a real webserver and create 4 worker-threads for the web application. First, install gunicorn, either by installing the port www/py-gunicorn or via pip:

# pip install gunicorn # rehash # gunicorn -w 4 -b example2:app

Point your browser to http://SERVER:8005 to verify it still works. Then, type Control-C to stop the web application.

Typographical ornament


The next step is to put nginx in front of it, to make the application resilient to many concurrent requests from slow clients:

# cd /usr/ports/www/nginx # make install clean

This is a simple /usr/local/etc/nginx/nginx.conf which serves static content from the /www directory:

events { worker_connections 1024; } http { server { location / { root /www; index index.html; } } }

To proxy our web application, we need the following server entry in /usr/local/etc/nginx/nginx.conf:

server { listen 81; server_name _; location / { proxy_pass; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }

Add this to /etc/rc.conf:


Now start nginx:

# /usr/local/etc/rc.d/nginx start

If you now point your webbrowser to http://SERVER:81, you'll get a 'Bad Gateway' error from nginx, because the web application is not running.

Typographical ornament


We have to make our web application controllable by a monitoring program. Should the web application crash for some reason, it has to be restarted. Also in the case of a server reboot, it must be started. Supervisor does the job.

# cd /usr/ports/sysutils/py-supervisord # make install clean

And put this in /etc/rc.conf:


Add the web application to /usr/local/etc/supervisord.conf as 'flaskexample':

[unix_http_server] file=/var/run/supervisor/supervisor.sock [supervisord] logfile=/var/log/supervisor/supervisord.log pidfile=/var/run/supervisor/supervisord.pid user=root [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface [supervisorctl] serverurl=unix:///var/run/supervisor/supervisor.sock [program:flaskexample] command=/usr/local/bin/gunicorn -w 4 -b example2:app directory=/home/user/prj/python/flask-examples user=root autostart=true autorestart=true stdout_logfile=NONE stderr_logfile=NONE ; Handy for debugging: ; stdout_logfile=/var/log/supervisor/webapp.stdout ; stderr_logfile=/var/log/supervisor/webapp.stderr

...and then start the supervisord daemon. It should start the web application.

# /usr/local/etc/rc.d/supervisord start Starting supervisord. # supervisorctl status flaskexample RUNNING pid 5778, uptime 0:00:06

Point your browser to http://SERVER:81 and see if it responds with something like "Hello,".

Deploy via Subversion

When I use subversion to deploy updates to a webserver, I often use this script, 'updatesite':

svn update sudo supervisorctl restart webapp

That's it! If you have any questions or remarks, please email me.


JoongSeob vito kim • 11 Jul 2013

Nice post. It helps much! Thank you.

Jordan • 19 Jul 2014

Thanks for the guide!

Gerald • 8 Dec 2014

Thank you very much. It is extreme helpful.

Dani • 1 Oct 2015

Awesome man!

Dude • 30 Mar 2017

svn checkout and update makes a fully functional workcopy including files in .svn dir, you don't need it on production so use svn export instead to get only project files without any unnecessary things

Leave a comment

name (required)

content last edited on March 17, 2013, 14:51 - rendered in 2.25 msec