Monitoring

Note

Make sure that when using either of these service monitors you do not enable the Gunicorn’s daemon mode. These monitors expect that the process they launch will be the process they need to monitor. Daemonizing will fork-exec which creates an unmonitored process and generally just confuses the monitor services.

Gaffer

Using Gafferd and gaffer

Gaffer can be used to monitor Gunicorn. A simple configuration is:

  1. [process:gunicorn]
  2. cmd = gunicorn -w 3 test:app
  3. cwd = /path/to/project

Then you can easily manage Gunicorn using Gaffer.

Using a Procfile

Create a Procfile in your project:

  1. gunicorn = gunicorn -w 3 test:app

You can launch any other applications that should be launched at the same time.

Then you can start your Gunicorn application using Gaffer:

  1. gaffer start

If gafferd is launched you can also load your Procfile in it directly:

  1. gaffer load

All your applications will be then supervised by gafferd.

Runit

A popular method for deploying Gunicorn is to have it monitored by runit. Here is an example service definition:

  1. #!/bin/sh
  2. GUNICORN=/usr/local/bin/gunicorn
  3. ROOT=/path/to/project
  4. PID=/var/run/gunicorn.pid
  5. APP=main:application
  6. if [ -f $PID ]; then rm $PID; fi
  7. cd $ROOT
  8. exec $GUNICORN -c $ROOT/gunicorn.conf.py --pid=$PID $APP

Save this as /etc/sv/[app_name]/run, and make it executable (chmod u+x /etc/sv/[app_name]/run). Then run ln -s /etc/sv/[app_name] /etc/service/[app_name]. If runit is installed, Gunicorn should start running automatically as soon as you create the symlink.

If it doesn’t start automatically, run the script directly to troubleshoot.

Supervisor

Another useful tool to monitor and control Gunicorn is Supervisor. A simple configuration is:

  1. [program:gunicorn]
  2. command=/path/to/gunicorn main:application -c /path/to/gunicorn.conf.py
  3. directory=/path/to/project
  4. user=nobody
  5. autostart=true
  6. autorestart=true
  7. redirect_stderr=true

Upstart

Using Gunicorn with upstart is simple. In this example we will run the app “myapp” from a virtualenv. All errors will go to /var/log/upstart/myapp.log.

/etc/init/myapp.conf:

  1. description "myapp"
  2. start on (filesystem)
  3. stop on runlevel [016]
  4. respawn
  5. setuid nobody
  6. setgid nogroup
  7. chdir /path/to/app/directory
  8. exec /path/to/virtualenv/bin/gunicorn myapp:app

Systemd

A tool that is starting to be common on linux systems is Systemd. It is a system services manager that allows for strict process management, resources and permissions control.

Below are configurations files and instructions for using systemd to create a unix socket for incoming Gunicorn requests. Systemd will listen on this socket and start gunicorn automatically in response to traffic. Later in this section are instructions for configuring Nginx to forward web traffic to the newly created unix socket:

/etc/systemd/system/gunicorn.service:

  1. [Unit]
  2. Description=gunicorn daemon
  3. Requires=gunicorn.socket
  4. After=network.target
  5. [Service]
  6. Type=notify
  7. # the specific user that our service will run as
  8. User=someuser
  9. Group=someuser
  10. # another option for an even more restricted service is
  11. # DynamicUser=yes
  12. # see http://0pointer.net/blog/dynamic-users-with-systemd.html
  13. RuntimeDirectory=gunicorn
  14. WorkingDirectory=/home/someuser/applicationroot
  15. ExecStart=/usr/bin/gunicorn applicationname.wsgi
  16. ExecReload=/bin/kill -s HUP $MAINPID
  17. KillMode=mixed
  18. TimeoutStopSec=5
  19. PrivateTmp=true
  20. [Install]
  21. WantedBy=multi-user.target

/etc/systemd/system/gunicorn.socket:

  1. [Unit]
  2. Description=gunicorn socket
  3. [Socket]
  4. ListenStream=/run/gunicorn.sock
  5. # Our service won't need permissions for the socket, since it
  6. # inherits the file descriptor by socket activation
  7. # only the nginx daemon will need access to the socket
  8. User=www-data
  9. # Optionally restrict the socket permissions even more.
  10. # Mode=600
  11. [Install]
  12. WantedBy=sockets.target

Next enable and start the socket (it will autostart at boot too):

  1. systemctl enable --now gunicorn.socket

Now let’s see if the nginx daemon will be able to connect to the socket. Running sudo -u www-data curl --unix-socket /run/gunicorn.sock http, our Gunicorn service will be automatically started and you should see some HTML from your server in the terminal.

Note

systemd employs cgroups to track the processes of a service, so it doesn’t need pid files. In the rare case that you need to find out the service main pid, you can use systemctl show --value -p MainPID gunicorn.service, but if you only want to send a signal an even better option is systemctl kill -s HUP gunicorn.service.

Note

www-data is the default nginx user in debian, other distriburions use different users (for example: http or nginx). Check you distro to know what to put for the socket user, and for the sudo command.

You must now configure your web proxy to send traffic to the new Gunicorn socket. Edit your nginx.conf to include the following:

/etc/nginx/nginx.conf:

  1. user www-data;
  2. ...
  3. http {
  4. server {
  5. listen 8000;
  6. server_name 127.0.0.1;
  7. location / {
  8. proxy_pass http://unix:/run/gunicorn.sock;
  9. }
  10. }
  11. }
  12. ...

Note

The listen and server_name used here are configured for a local machine. In a production server you will most likely listen on port 80, and use your URL as the server_name.

Now make sure you enable the nginx service so it automatically starts at boot:

  1. systemctl enable nginx.service

Either reboot, or start Nginx with the following command:

  1. systemctl start nginx

Now you should be able to test Nginx with Gunicorn by visiting http://127.0.0.1:8000/ in any web browser. Systemd is now set up.