DEV Community

Luca Barbato
Luca Barbato

Posted on

Using uWSGI in Gentoo

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

and in /etc/metalog.conf I added:

uWSGI Emperor :
    program = "uwsgi"
    logdir  = "/var/log/uwsgi"
    break   = 1
Enter fullscreen mode Exit fullscreen mode

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 the ini configuration

  • Explicitly mention the python plugin in the ini 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)