Difference between revisions of "UWSGI"

From ArchWiki
Jump to: navigation, search
m (rm gap)
(Extended configuration. Cleaned up 'running uwsgi' and 'nginx (in chroot)'. Added useful help links and 'Tips and tricks' on hardening and proper socket activation.)
 
(43 intermediate revisions by 13 users not shown)
Line 1: Line 1:
[[Category:Web Server]]
+
{{Lowercase title}}
== Installation ==
+
[[Category:Web server]]
 +
[[ja:UWSGI]]
 +
uWSGI is a fast, self-healing and developer/sysadmin-friendly application container server coded in pure C.
  
[[Pacman|Install]] package {{Pkg|uwsgi}} in the [[Official Repositories|official repositories]]. Note, the package does not come with plugins as it is just a compact package. External plugins have to be installed separately. It is a very efficient software due to the reason it is written in C. There are alternatives written in python like gunicorn, but they are slower inherently.
+
There are alternatives written in Python such as {{AUR|gunicorn}}.
  
== Starting Service ==
+
== Installation ==
  
To enable the uwsgi service by default at start-up, run:
+
[[Install]] the package {{Pkg|uwsgi}} from the [[official repositories]].
# systemctl enable uwsgi@helloworld.service
+
Note, that the package does not come with plugins. They have to be installed separately:  
 +
* {{Pkg|uwsgi-plugin-cgi}} for CGI support
 +
* {{Pkg|uwsgi-plugin-jvm}} for [[Java]] support
 +
* {{Pkg|uwsgi-plugin-lua51}} for Lua support
 +
* {{Pkg|uwsgi-plugin-mono}} for [[Mono]] support
 +
* {{Pkg|uwsgi-plugin-php}} for [[PHP]] support
 +
* {{Pkg|uwsgi-plugin-psgi}} for Perl support
 +
* {{Pkg|uwsgi-plugin-pypy}} for [[PyPy]] support
 +
* {{Pkg|uwsgi-plugin-python}} for [[Python]] support
 +
* {{Pkg|uwsgi-plugin-python2}} for Python2 support
 +
* {{Pkg|uwsgi-plugin-rack}} for [[Ruby]] Rack support
 +
* {{Pkg|uwsgi-plugin-webdav}} for [[WebDAV]] support
  
This will enable the service for the application configured in /etc/uwsgi/helloworld.ini. Otherwise, you can also enable it through the socket interface with the following command:
+
== Configuration ==
# systemctl enable uwsgi@helloworld.socket
+
  
== Configuring ==
+
Web applications (e.g. [[Wordpress]], [[ownCloud]], [[Mailman]], [[cgit]]) served by uWSGI are configured in {{ic|/etc/uwsgi/}}, where each of them requires its own configuration file (ini-style). Details can be found [http://uwsgi-docs.readthedocs.org/en/latest/ in the uWSGI documentation].
  
You can create a configuration by editing and putting that in {{ic|/etc/uwsgi/}}. There is a build file shipped with the package located at {{ic|/etc/uwsgi/archlinux.ini}}.  
+
Alternatively, you can run uWSGI in [http://uwsgi-docs.readthedocs.org/en/latest/Emperor.html Emperor mode] (configured in {{ic|/etc/uwsgi/emperor.ini}}). It enables a single uWSGI instance to run a set of different apps (called vassals) using a single main supervisor (called emperor).
  
More details can be found [http://uwsgi-docs.readthedocs.org/en/latest/ in the uwsgi documentation].
+
=== Web applications ===
  
===== Application configuration =====
+
uWSGI supports many different languages and thus also many web applications.
 +
As an example the configuration file {{ic|/etc/uwsgi/example.ini}} and the prior installation of the plugin needed for your web application is assumed.
 +
For further common configuration examples, have a look at this [https://sleepmap.de/2016/securely-serving-webapps-using-uwsgi/ blog post].
  
The following is a simple example to get python support. You may need to install the uwsgi-plugin-python or uwsgi-plugin-python2 plugin from the community repository by pacman.
+
==== Python ====
 +
The following is a simple example for a [[Python]] application.
  
 +
{{hc|/etc/uwsgi/example.ini|<nowiki>
 
  [uwsgi]
 
  [uwsgi]
  chdir = /srv/http/helloworld
+
  chdir = /srv/http/example
  module = helloworld
+
  module = example
 
  plugins = python
 
  plugins = python
 +
</nowiki>}}
  
It is also possible to run uwsgi separately with the following syntax for instance:
+
It is also possible to run uWSGI separately with the following syntax for instance:
 +
 
 +
{{Note|It seems --wsgi-file option is not available from {{Pkg|uwsgi}}. Official guides suggest building from sources (see http://uwsgi-docs.readthedocs.org/en/latest/WSGIquickstart.html#installing-uwsgi-with-python-support).}}
  
 
  uwsgi --socket 127.0.0.1:3031 --plugin python2 --wsgi-file ~/foo.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191 --uid --gid
 
  uwsgi --socket 127.0.0.1:3031 --plugin python2 --wsgi-file ~/foo.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191 --uid --gid
  
Note, you should avoid running this command as root.
+
{{Note|You should avoid running this command as root}}
 +
 
 +
==== Php ====
 +
The following is a simple example for a [[PHP]] based website.
 +
 
 +
{{hc|/etc/uwsgi/example.ini|<nowiki>
 +
[uwsgi]
 +
; maximum number of worker processes
 +
processes = 4
 +
; the user and group id of the process once it’s started
 +
uid = http
 +
gid = http
 +
socket = /run/uwsgi/%n.sock
 +
master = true
 +
chdir = /srv/http/%n
 +
; php
 +
plugins = php
 +
; jail our php environment
 +
php-docroot = /srv/http/%n
 +
php-index = index.php
 +
; clear environment on exit
 +
vacuum = true
 +
</nowiki>}}
 +
 
 +
=== Web server ===
 +
uWSGI can be the backend to many web servers, that support the forwarding of access. The following are examples for configurations.
 +
 
 +
==== Nginx ====
 +
[[nginx]] can redirect access towards unix sockets or ports (on localhost or remote machine), depending on your web application.
 +
 
 +
 
 +
{{hc|/etc/nginx/example.conf|<nowiki>
 +
# ...
 +
# forward all access to / towards
 +
location / {
 +
  root /usr/share/nginx/html;
 +
  index index.html index.htm;
 +
  include uwsgi_params;
 +
  # this is the correct uwsgi_modifier1 parameter for a php based application
 +
  uwsgi_modifier1 14;
 +
  # uncomment the following if you want to use the unix socket instead
 +
  # uwsgi_pass unix:/var/run/uwsgi/example.sock;
 +
  # access is redirected to localhost:3031
 +
  uwsgi_pass 127.0.0.1:3031;
 +
}
 +
# ...
 +
</nowiki>}}
 +
 
 +
{{Tip|Have a look at [https://uwsgi-docs.readthedocs.io/en/latest/Protocol.html#packet-descriptions the documentation] for the list of {{ic|uwsgi_modifier1}} parameters fitting to your web application.}}
 +
 
 +
==== Nginx (in chroot) ====
 +
 
 +
{{Note|Please refer to the below tips if you have deployed Nginx as described here: [[Nginx#Installation in a chroot]]}}
 +
 
 +
{{Note|It is assumed your Nginx chroot is located within {{ic|/srv/http}}}}
 +
 
 +
{{Note|You will most likely want to read through uWSGI documentation to understand your configuration from both performance and security point of view}}
 +
 
 +
First create ini file that will point to your application:
 +
{{hc|/etc/uwsgi/application1.ini|<nowiki>
 +
[uwsgi]
 +
chroot = /srv/http
 +
chdir = /www/application1
 +
wsgi-file = application1.py
 +
plugins = python
 +
socket = /run/application1.sock
 +
uid = http
 +
gid = http
 +
threads = 2
 +
stats = 127.0.0.1:9191
 +
vacuum = true
 +
</nowiki>}}
 +
 
 +
Since we are chrooting to {{ic|/srv/http}} above configuration will result in following unix socket being created {{ic|/srv/http/run/application1.sock}}
 +
 
 +
{{Note|Your application must be placed within {{ic|/srv/http/www/application1}} before service is started. Depending on configuration your application may be cached so you may need to restart the service when you modify it}}
 +
{{Note|If you are deploying python application you may need to copy standard python libraries - if you develop under python 3 then you can copy them from {{ic|/lib/python3.4}} to {{ic|/srv/http/lib/python3.4}}
 +
You can try to run following:
 +
# cp -r -p /lib/python3.4 /srv/http/lib
 +
# cp -r -p /lib/*python*so /srv/http/lib
 +
}}
 +
 
 +
You will need to disable notifications within your service file:
 +
{{hc|/etc/systemd/system/multi-user.target.wants/uwsgi\@application1.service|<nowiki>
 +
[Unit]
 +
Description=uWSGI service unit
 +
After=syslog.target
 +
 
 +
[Service]
 +
PIDFile=/run/%I.pid
 +
RemainAfterExit=yes
 +
ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/%I.ini
 +
ExecReload=/bin/kill -HUP $MAINPID
 +
ExecStop=/bin/kill -INT $MAINPID
 +
Restart=always
 +
StandardError=syslog
 +
KillSignal=SIGQUIT
 +
 
 +
[Install]
 +
WantedBy=multi-user.target
 +
</nowiki>}}
 +
 
 +
{{Note|PID file will be created within {{ic|/run}} rather than {{ic|/srv/http/run}}}}
 +
 
 +
After modification make sure to [[reload]] to incorporate the new or changed units.
 +
 
 +
You are then free to [[enable]] and [[start]] {{ic|uwsgi@application1.service}}.
 +
 
 +
Edit {{ic|/srv/http/etc/nginx/nginx.conf}} and add new {{ic|server}} section within it that would contain at least following:
 +
{{hc|/srv/http/etc/nginx/nginx.conf|<nowiki>
 +
...
 +
    server
 +
    {
 +
        listen      80;
 +
        server_name  127.0.0.1;
 +
        location /
 +
        {
 +
            root  /www/application1;
 +
            include uwsgi_params;
 +
            uwsgi_pass unix:/run/application1.sock;
 +
        }
 +
 
 +
        error_page  500 502 503 504  /50x.html;
 +
        location = /50x.html
 +
        {
 +
            root  /usr/share/nginx/html;
 +
        }
 +
    }
 +
...
 +
</nowiki>}}
 +
 
 +
Make sure to now [[restart]] {{ic|nginx.service}} to have your {{ic|application1}} be served at {{ic|127.0.0.1}}.
 +
 
 +
 
 +
== Running uWSGI ==
 +
 
 +
{{Note| This assumes the used web application has been properly configured, is being served by your web server, which redirects towards the socket or port it is using and was configured in {{ic|/etc/uwsgi/}}.}}
 +
 
 +
If you plan on using a web application all the time (without it being activated on demand), you can simply [[start]] and [[enable]] {{ic|uwsgi@example}}.
 +
 
 +
If you plan on having your web application be started on demand you can [[start]] and [[enable]] {{ic|uwsgi@example.socket}}.
 +
 
 +
 
 +
To use the Emperor mode, [[start]] and [[enable]] {{ic|emperor.uwsgi.service}}.
 +
 
 +
To use socket activation of this mode [[start]] and [[enable]] {{ic|emperor.uwsgi.socket}}.
 +
 
 +
 
 +
 
 +
== Tips and tricks ==
 +
Some functionality, that uWSGI offers is not accessible by using the [[systemd]] service files provided in the [[official repositories]].
 +
Changes to them are explained in the following sections. For further information about this, [https://sleepmap.de/2016/securely-serving-webapps-using-uwsgi/ read this blog post].
 +
 
 +
=== Socket activation ===
 +
Using socket activation, you want to
 +
* direct your web server to a unix socket and thereby start your uWSGI instance running the application
 +
* you most likely want to have the application be closed by uWSGI after a certain idle time
 +
* you want your web server be able to start the application again, once it is accessed
 +
 
 +
uWSGI offers settings, with which you can have the instance close the application:
 +
{{hc|/etc/uwsgi/example.ini|<nowiki>
 +
[uwsgi]
 +
# ...
 +
 
 +
# set idle time in seconds
 +
idle = 600
 +
# kill the application after idle time was reached
 +
kill-on-idle = true
 +
 
 +
# ...
 +
</nowiki>}}
 +
 
 +
The current {{ic|uwsgi@.service}} file however doesn't allow this, because [[systemd]] treats non-zero exit codes as failure and thereby marking the unit as failed and additionally the {{ic|1=Restart=always}} directive makes a closing after idle time useless.
 +
A fix for this is to add the exit codes, that uWSGI may provide after closing an application by itself to a list, that [[systemd]] will treat as success by using the {{ic|SuccessExitStatus}} directive (for further information [https://sleepmap.de/2016/securely-serving-webapps-using-uwsgi/ read this blog post])
 +
 
 +
{{hc|/etc/systemd/system/uwsgi-socket@.service|<nowiki>
 +
[Unit]
 +
Description=uWSGI service unit
 +
After=syslog.target
 +
 
 +
[Service]
 +
ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/%I.ini
 +
ExecReload=/bin/kill -HUP $MAINPID
 +
ExecStop=/bin/kill -INT $MAINPID
 +
Type=notify
 +
SuccessExitStatus=15 17 29 30
 +
StandardError=syslog
 +
NotifyAccess=all
 +
KillSignal=SIGQUIT
 +
 
 +
[Install]
 +
WantedBy=multi-user.target
 +
</nowiki>}}
 +
 
 +
This will allow for proper socket activation with kill-after-idle functionality.
 +
 
 +
=== Hardening uWSGI ===
 +
Web applications are exposed to the wild and depending on their quality and the security of their underlying languages, some are more dangerous to run, than others.
 +
A good way to start dealing with possible unsafe web applications is to jail them. [[systemd]] has some functionality, that can be put to use.
 +
Have a look at the following example (and for further information read the [https://www.freedesktop.org/software/systemd/man/systemd.exec.html systemd.exec manual] and [https://sleepmap.de/2016/securely-serving-webapps-using-uwsgi/ this blog post]):
 +
 
 +
{{hc|/etc/systemd/system/uwsgi-secure@.service|<nowiki>
 +
[Unit]
 +
Description=uWSGI service unit
 +
After=syslog.target
 +
 
 +
[Service]
 +
ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/%I.ini
 +
ExecReload=/bin/kill -HUP $MAINPID
 +
ExecStop=/bin/kill -INT $MAINPID
 +
Type=notify
 +
SuccessExitStatus=15 17 29 30
 +
StandardError=syslog
 +
NotifyAccess=all
 +
KillSignal=SIGQUIT
 +
PrivateDevices=yes
 +
PrivateTmp=yes
 +
ProtectSystem=full
 +
ReadWriteDirectories=/etc/webapps /var/lib/
 +
ProtectHome=yes
 +
NoNewPrivileges=yes
  
===== Nginx configuration =====
+
[Install]
 +
WantedBy=multi-user.target
 +
</nowiki>}}
  
location / {
+
{{Note| Using {{ic|1=NoNewPrivileges=yes}} doesn't work with [[Mailman]]'s cgi frontend! Remove this setting, if you want to use it in conjunction with it.}}
    root  /usr/share/nginx/html;
+
    index  index.html index.htm;
+
    include uwsgi_params;
+
    # uwsgi_pass unix:/var/run/uwsgi/helloworld.sock;
+
    uwsgi_pass 127.0.0.1:3031;
+
}
+
  
 
== See Also ==
 
== See Also ==
 
* [http://uwsgi-docs.readthedocs.org/en/latest Official Documentation]
 
* [http://uwsgi-docs.readthedocs.org/en/latest Official Documentation]
* [https://github.com/unbit/uwsgi-docs UWsgi Github]
+
* [https://github.com/unbit/uwsgi-docs uWSGI Github]
 +
* [https://sleepmap.de/2016/securely-serving-webapps-using-uwsgi/ Securely serving webapps using uWSGI]
 
* [http://blog.kgriffs.com/ Fluffy White Stuff Benchmark]
 
* [http://blog.kgriffs.com/ Fluffy White Stuff Benchmark]
* [http://flask.pocoo.org/docs/deploying/uwsgi/ Flash uwsgi deploying]
+
* [http://flask.pocoo.org/docs/deploying/uwsgi/ Flask uWSGI deploying]
 
* [https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/uwsgi/ Django and uWSGI]
 
* [https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/uwsgi/ Django and uWSGI]
* [http://www.youtube.com/watch?v=tD6UCfPCVLA Flask with uwsgi and nginx video]
+
* [http://www.youtube.com/watch?v=tD6UCfPCVLA Flask with uWSGI and nginx video]
* [http://uwsgi-docs.readthedocs.org/en/latest/Apache.html Apache and uwsgi]
+
* [http://uwsgi-docs.readthedocs.org/en/latest/Apache.html Apache and uWSGI]

Latest revision as of 18:51, 8 October 2016

uWSGI is a fast, self-healing and developer/sysadmin-friendly application container server coded in pure C.

There are alternatives written in Python such as gunicornAUR.

Installation

Install the package uwsgi from the official repositories. Note, that the package does not come with plugins. They have to be installed separately:

Configuration

Web applications (e.g. Wordpress, ownCloud, Mailman, cgit) served by uWSGI are configured in /etc/uwsgi/, where each of them requires its own configuration file (ini-style). Details can be found in the uWSGI documentation.

Alternatively, you can run uWSGI in Emperor mode (configured in /etc/uwsgi/emperor.ini). It enables a single uWSGI instance to run a set of different apps (called vassals) using a single main supervisor (called emperor).

Web applications

uWSGI supports many different languages and thus also many web applications. As an example the configuration file /etc/uwsgi/example.ini and the prior installation of the plugin needed for your web application is assumed. For further common configuration examples, have a look at this blog post.

Python

The following is a simple example for a Python application.

/etc/uwsgi/example.ini
 [uwsgi]
 chdir = /srv/http/example
 module = example
 plugins = python

It is also possible to run uWSGI separately with the following syntax for instance:

Note: It seems --wsgi-file option is not available from uwsgi. Official guides suggest building from sources (see http://uwsgi-docs.readthedocs.org/en/latest/WSGIquickstart.html#installing-uwsgi-with-python-support).
uwsgi --socket 127.0.0.1:3031 --plugin python2 --wsgi-file ~/foo.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191 --uid --gid
Note: You should avoid running this command as root

Php

The following is a simple example for a PHP based website.

/etc/uwsgi/example.ini
[uwsgi]
; maximum number of worker processes
processes = 4
; the user and group id of the process once it’s started
uid = http
gid = http
socket = /run/uwsgi/%n.sock
master = true
chdir = /srv/http/%n
; php
plugins = php
; jail our php environment
php-docroot = /srv/http/%n
php-index = index.php
; clear environment on exit
vacuum = true

Web server

uWSGI can be the backend to many web servers, that support the forwarding of access. The following are examples for configurations.

Nginx

nginx can redirect access towards unix sockets or ports (on localhost or remote machine), depending on your web application.


/etc/nginx/example.conf
# ...
# forward all access to / towards 
location / {
  root /usr/share/nginx/html;
  index index.html index.htm;
  include uwsgi_params;
  # this is the correct uwsgi_modifier1 parameter for a php based application
  uwsgi_modifier1 14;
  # uncomment the following if you want to use the unix socket instead
  # uwsgi_pass unix:/var/run/uwsgi/example.sock;
  # access is redirected to localhost:3031
  uwsgi_pass 127.0.0.1:3031;
}
# ...
Tip: Have a look at the documentation for the list of uwsgi_modifier1 parameters fitting to your web application.

Nginx (in chroot)

Note: Please refer to the below tips if you have deployed Nginx as described here: Nginx#Installation in a chroot
Note: It is assumed your Nginx chroot is located within /srv/http
Note: You will most likely want to read through uWSGI documentation to understand your configuration from both performance and security point of view

First create ini file that will point to your application:

/etc/uwsgi/application1.ini
[uwsgi]
chroot = /srv/http
chdir = /www/application1
wsgi-file = application1.py
plugins = python
socket = /run/application1.sock
uid = http
gid = http
threads = 2
stats = 127.0.0.1:9191
vacuum = true

Since we are chrooting to /srv/http above configuration will result in following unix socket being created /srv/http/run/application1.sock

Note: Your application must be placed within /srv/http/www/application1 before service is started. Depending on configuration your application may be cached so you may need to restart the service when you modify it
Note: If you are deploying python application you may need to copy standard python libraries - if you develop under python 3 then you can copy them from /lib/python3.4 to /srv/http/lib/python3.4

You can try to run following:

# cp -r -p /lib/python3.4 /srv/http/lib
# cp -r -p /lib/*python*so /srv/http/lib

You will need to disable notifications within your service file:

/etc/systemd/system/multi-user.target.wants/uwsgi\@application1.service
[Unit]
Description=uWSGI service unit
After=syslog.target

[Service]
PIDFile=/run/%I.pid
RemainAfterExit=yes
ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/%I.ini
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -INT $MAINPID
Restart=always
StandardError=syslog
KillSignal=SIGQUIT

[Install]
WantedBy=multi-user.target
Note: PID file will be created within /run rather than /srv/http/run

After modification make sure to reload to incorporate the new or changed units.

You are then free to enable and start uwsgi@application1.service.

Edit /srv/http/etc/nginx/nginx.conf and add new server section within it that would contain at least following:

/srv/http/etc/nginx/nginx.conf
...
    server
    {
        listen       80;
        server_name  127.0.0.1;
        location /
        {
            root   /www/application1;
            include uwsgi_params;
            uwsgi_pass unix:/run/application1.sock;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html
        {
            root   /usr/share/nginx/html;
        }
    }
...

Make sure to now restart nginx.service to have your application1 be served at 127.0.0.1.


Running uWSGI

Note: This assumes the used web application has been properly configured, is being served by your web server, which redirects towards the socket or port it is using and was configured in /etc/uwsgi/.

If you plan on using a web application all the time (without it being activated on demand), you can simply start and enable uwsgi@example.

If you plan on having your web application be started on demand you can start and enable uwsgi@example.socket.


To use the Emperor mode, start and enable emperor.uwsgi.service.

To use socket activation of this mode start and enable emperor.uwsgi.socket.


Tips and tricks

Some functionality, that uWSGI offers is not accessible by using the systemd service files provided in the official repositories. Changes to them are explained in the following sections. For further information about this, read this blog post.

Socket activation

Using socket activation, you want to

  • direct your web server to a unix socket and thereby start your uWSGI instance running the application
  • you most likely want to have the application be closed by uWSGI after a certain idle time
  • you want your web server be able to start the application again, once it is accessed

uWSGI offers settings, with which you can have the instance close the application:

/etc/uwsgi/example.ini
[uwsgi]
# ...

# set idle time in seconds
idle = 600
# kill the application after idle time was reached
kill-on-idle = true

# ...

The current uwsgi@.service file however doesn't allow this, because systemd treats non-zero exit codes as failure and thereby marking the unit as failed and additionally the Restart=always directive makes a closing after idle time useless. A fix for this is to add the exit codes, that uWSGI may provide after closing an application by itself to a list, that systemd will treat as success by using the SuccessExitStatus directive (for further information read this blog post)

/etc/systemd/system/uwsgi-socket@.service
[Unit]
Description=uWSGI service unit
After=syslog.target

[Service]
ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/%I.ini
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -INT $MAINPID
Type=notify
SuccessExitStatus=15 17 29 30
StandardError=syslog
NotifyAccess=all
KillSignal=SIGQUIT

[Install]
WantedBy=multi-user.target

This will allow for proper socket activation with kill-after-idle functionality.

Hardening uWSGI

Web applications are exposed to the wild and depending on their quality and the security of their underlying languages, some are more dangerous to run, than others. A good way to start dealing with possible unsafe web applications is to jail them. systemd has some functionality, that can be put to use. Have a look at the following example (and for further information read the systemd.exec manual and this blog post):

/etc/systemd/system/uwsgi-secure@.service
[Unit]
Description=uWSGI service unit
After=syslog.target

[Service]
ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/%I.ini
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -INT $MAINPID
Type=notify
SuccessExitStatus=15 17 29 30
StandardError=syslog
NotifyAccess=all
KillSignal=SIGQUIT
PrivateDevices=yes
PrivateTmp=yes
ProtectSystem=full
ReadWriteDirectories=/etc/webapps /var/lib/
ProtectHome=yes
NoNewPrivileges=yes

[Install]
WantedBy=multi-user.target
Note: Using NoNewPrivileges=yes doesn't work with Mailman's cgi frontend! Remove this setting, if you want to use it in conjunction with it.

See Also