Here some quick notes on how to use uwsgi (and flask on Gentoo.
Flask
Flask is a python microframework for web development, it is fairly simple and you can find lots of extensions for nearly everything.
Flask implements the wsgi specification so usually it is deployed using gunicorn or other WSGI servers.
I like a lot uwsgi
uWSGI
uWSGI is a neat multi-language server that has a fairly good support for python.
It has a fairly straightforward configuration system that let you do simple things in simple ways and increase complexity as you need.
Using both in Gentoo
Usually you use virtualenv to keep your webapp dependencies in a single place, so portage is not in the equation for Flask.
uWSGI on the other hand can be managed by your init system and for stable deployments it is a good idea.
Emperor vs single-instance
uWSGI has multiple ways to run, the OpenRC init scripts let you pick if you want it to host multiple webapp by itself (emperor) or just run every instance as a single service.
/etc/init.d/uwsgi <- emperor mode
/etc/init.d/uwsgi.app_name <- single instance
You simply use ln -s
to create the single instances and then write its configuration in /etc/conf.d/uwsgi.app_name
as usual.
If you want to use the emperor mode you should put the configuration in /etc/uwsgi.d/
, I find the ini
variants simpler, but uwsgi supports multiple formats.
[uwsgi]
plugins = python38
socket = /run/app.sock
chown-socket = app_user:nginx
chmod-socket = 664
chdir = /home/app/path
virtualenv = /home/app/path/.venv
mount = /=your_python_class:app
threads = 4
env=SOME_VAR=somevalue
Usually you have a callable called app
in your application main class. Since it is common to run flask
by calling the App::run()
method, make sure you do not have it or you have guarded with the usual if __name__ == "__main__"
.
nginx
I prefer using nginx as frontend server, the configuration of its side is simple enough as well:
server {
...
server_name name.tdl;
access_log /var/log/nginx/name.access_log main;
error_log /var/log/nginx/name.error_log info;
location / {
include uwsgi_params;
uwsgi_pass unix:/run/app.sock;
}
}
uwsgi_params
are already provided and you just have to make sure both nginx and uwsgi can access the socket.
metalog
I like to have uwsgi log using the syslog facility so in its /etc/conf.d/uwsgi
I have:
UWSGI_EXTRA_OPTIONS="--logger syslog:uwsgi"
and in /etc/metalog.conf
I added:
uWSGI Emperor :
program = "uwsgi"
logdir = "/var/log/uwsgi"
break = 1
Pitfalls
Overall it is that kind of simple, but here a checklist if something does not work as intended:
If you use App::run() make sure it is guarded. It was fairly common when you develop to call directly your app using
python
.flask run
made it way less common.Mention the
virtualenv
in theini
configurationExplicitly mention the python
plugin
in theini
configuration, uWSGI supports multiple languages.Add the app user to the
nginx
group and make sure all can write to the socket path.
Top comments (0)