Monday, December 5, 2016

How to build uwsgi from source and run as a service

As you might have already noticed, I always deploy python applications using uwsgi and nginx. But I didn't write yet how to install uwsgi. Probably there is some version in repository, but I don't really care about it. I know it's old and not what I actually need.

I need to build uwsgi with plugin support, which would allow me to work both with python 3 and 2. Then I will create service config file, so that you can use it as service. Sounds good, isn't it? Let's do it then.

1. Download uwsgi and extract it
cd ~
curl -O
tar -xvzf uwsgi-2.0.12.tar.gz

2. Build uwsgi core
cd ~/uwsgi-2.0.12
python --build nolang

3. Build uwsgi python plugins (2 and 3)
cd ~/uwsgi-2.0.12
PYTHON=python2.7 ./uwsgi --build-plugin "plugins/python python27
PYTHON=python3.4 ./uwsgi --build-plugin "plugins/python python34

4. Copy plugins to system directories:
sudo mkdir -p /usr/lib/uwsgi
sudo cp /usr/lib/uwsgi/
sudo cp /usr/lib/uwsgi/

5. Install uwsgi binary system wide
cd ~/uwsgi-2.0.12
UWSGI_PROFILE=nolang python install

6. Create vassals directory
sudo mkdir -p /etc/uwsgi/vassals/

7. Create service config (replace 'www-data' with user that uwsgi should be run as) and save it to the file '/etc/systemd/system/uwsgi.service':
Description=uWSGI Emperor service

ExecStart=/usr/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data


8. Enable and start uwsgi service
sudo systemctl enable uwsgi
sudo systemctl start uwsgi

Now you can start using uwsgi. As an example of uwsgi config file, you can check this article, which I wrote last time about trac deployment. There you can find 'plugins-dir' and 'plugin' parameters, that's why we've built it with plugin support. Now you can easily change python27 to python34 in some of your other projects.


  1. Hi, following your instruction I had problems in running :

    `sudo systemctl start uwsgi`

    The error log is just:

    sudo systemctl start uwsgi
    Job for uwsgi.service failed because the control process exited with error code.
    See "systemctl status uwsgi.service" and "journalctl -xe" for details.

    This the output from: `systemctl status uwsgi.service`

    uwsgi.service - uWSGI Emperor service
    Loaded: loaded (/etc/systemd/system/uwsgi.service; enabled; vendor preset: enabled)
    Active: failed (Result: exit-code) since Wed 2017-05-10 13:32:03 CEST; 38s ago
    Process: 10761 ExecStart=/usr/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data (code=exited, status=203/EXEC)
    Main PID: 10761 (code=exited, status=203/EXEC)
    CPU: 781us

    1. try running it manually, something like:
      /usr/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data

      or with different parameters.

      Also check what is the error in the log file.

  2. Hi, Thanks a lot for your help!

    That was my bad!
    my `uwsgi ` executable was in `/usr/local/bin/`

    Starting the process manually I got:

    epinux@geohab-tools:~/dev/src/uwsgi-2.0.15$ /usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data
    *** Starting uWSGI 2.0.15 (64bit) on [Wed May 10 14:38:13 2017] ***
    compiled with version: 6.3.0 20170406 on 10 May 2017 13:27:06
    os: Linux-4.10.0-20-generic #22-Ubuntu SMP Thu Apr 20 09:22:42 UTC 2017
    machine: x86_64
    clock source: unix
    pcre jit disabled
    detected number of CPU cores: 8
    current working directory: /home/epinux/dev/src/uwsgi-2.0.15
    detected binary path: /usr/local/bin/uwsgi
    *** WARNING: you are running uWSGI without its master process manager ***
    your processes number limit is 127282
    your memory page size is 4096 bytes
    detected max file descriptor number: 1024
    *** starting uWSGI Emperor ***
    *** has_emperor mode detected (fd: 6) ***
    [uWSGI] getting INI configuration from trac.ini
    /usr/lib/uwsgi// undefined symbol: python27_plugin
    Wed May 10 14:38:13 2017 - [emperor] curse the uwsgi instance trac.ini (pid: 21650)
    Wed May 10 14:38:13 2017 - [emperor] removed uwsgi instance trac.ini
    *** has_emperor mode detected (fd: 6) ***

    'ldd' on the plugin:
    epinux@geohab-tools:~/dev/src/uwsgi-2.0.15$ ldd /usr/lib/uwsgi/ => (0x00007fff6dd35000) => /lib/x86_64-linux-gnu/ (0x00007ff830618000) => /lib/x86_64-linux-gnu/ (0x00007ff830414000) => /usr/lib/x86_64-linux-gnu/ (0x00007ff82fe82000) => /lib/x86_64-linux-gnu/ (0x00007ff82fabb000)
    /lib64/ (0x0000557387b89000) => /lib/x86_64-linux-gnu/ (0x00007ff82f89f000) => /lib/x86_64-linux-gnu/ (0x00007ff82f69a000) => /lib/x86_64-linux-gnu/ (0x00007ff82f391000)
    I'm following your instruction on how to set-up `trac` with `nginx`.
    After I start the process manually, the log file looks like :

    The log file from the `trac` instance `/opt/trac_www/conf/uwsgi.ini` is populated only when I start the uwsgi demon manually. while it should start logging after issuing:

    `sudo systemctl start uwsgi`

    From the log seems there are some issues with my `trac` cnfiguration, I'll continue on once fixed the `systemctl` issue.

  3. I think the main issue is the way how the distro is handling the startup scripts, I'm on ubuntu 17.04 and the `start` command is no more available. I need to use systemd and store the conf in `/etc/init.d/` with different instructions.

    1. Hi! I'm glad that you found a solution. These instructions should work for Centos, but I didn't check it for other distros.

      In Ubuntu/Debian you can also try this:
      sudo chmod +x /etc/rc.local

      and add this line to /etc/rc.local:
      /usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data

      rc.local should be started on reboot. This can be easiest solution, but creating service might be better.