Django Gunicorn Setup
Nov 10, 2015

Gunicorn is a “Python WSGI HTTP Server for UNIX”. It is absolutely stupid simple to setup and get running.

I will be using the following for this guide:

  • Django 1.8
  • Debian 8 (jessie)

Gunicorn Installation

  1. Install.

    pip3 install gunicorn

  2. Create a blank WSGI file inside your project folder (where resides). This is where you can configure Gunicorn options instead of passing arguments to it.

    touch PROJECT.wsgi

  3. Start gunicorn.

    gunicorn --threads=COUNT PROJECT.wsgi:application

That’s it. You now have a Gunicorn WSGI server running on port 8000. Now I recommend that you place an nginx proxy in front of this to handle file caching rather than letting the Gunicorn/Python server hand out static content (CSS, Javascript, images, etc.). Even the documentation recommends this.

The Gunicorn docs recommend setting the thread count to 2x to 3x the core count of the server.

Running Gunicorn aaS (systemd)

After install Gunicorn and testing it out, you’ll probably want to set it up as a service so it can be started automatically on boot.

  1. Create a new user.

    adduser django

    Give it an extremely long and random password. You won’t be logging into this user.

  2. Move your Django project into /home/django/. This is now where your project will reside.

  3. Change the ownership of your project files.

    chown -R django:django /home/django/

    Update the static files path in nginx if you have one set.

  4. Create the Gunicorn systemd service file.

    nano /etc/systemd/system/gunicorn.service

    ``` [Unit] Description=gunicorn daemon Requires=gunicorn.socket

[Service] Environment=PYTHONHASHSEED=random PIDFile=/run/gunicorn/pid User=django Group=django WorkingDirectory=/home/django/PROJECT ExecStart=/usr/local/bin/gunicorn –pid /run/gunicorn/pid django.wsgi:application ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s TERM $MAINPID PrivateTmp=true



4. Create the Gunicorn systemd socket file.

   `nano /etc/systemd/system/gunicorn.socket`

[Unit] Description=gunicorn socket

[Socket] ListenStream=/run/gunicorn/socket ListenStream= ListenStream=[::]:8000


5. Change the permissions so the pid file can be created.
   `chown -R django:django /run/gunicorn`

6. Start the services.

systemctl start gunicorn.socket systemctl start gunicorn.service

7. Enable the services to be started on boot if there were no problems.

systemctl enable gunicorn.socket systemctl enable gunicorn.service ```

Final Tasks

  1. Update any cronjobs for Django to the new user.
  2. Change file permissions of the static files if you are not running nginx as the django user/group.

I had one small issue with Redis where the user had no permission to access /var/run/redis.sock. This was easily solved by using TCP sockets instead of Unix sockets.