devmaker.net
start/ homelab/ production-server-for-a-django-app
Homelab

Production Server for a Django App

Developing a Django web application is already a demanding task, but the correct configuration of your server stack can have a significant impact on your application's performance and productivity. In this article, we will focus on using Nginx Unit as a WSGI (Web Server Gateway Interface) server for your Django app and how this configuration can increase efficiency.

Harry_im_Homelab31 (Portrait)
Harald Henning
2026-06-17 · ~5 min read
Nginx Unit as a lean production server for Django
Nginx Unit as a lean production server for Django
Part of a guide

This article is part of the Homelab Self-Hosting Guide – the curated learning path for your own homelab.

Why not just Gunicorn?

When you want to put a Django app into production, you reflexively reach for Gunicorn or uWSGI – both have been the standard stack behind every Django deployment for years. So did I, for a long time.

But after the third project where I had to restart the service for every configuration change, and the endless Nginx-as-reverse-proxy-in-front-of-Gunicorn setup, I came across Nginx Unit. The appeal: one component instead of two, live-configurable via REST API, and without the typical reload downtime.

What is Nginx Unit?

Nginx Unit is an application server from the makers of Nginx that serves Python (WSGI/ASGI), Go, PHP, Ruby, Java and more in a single process. The entire configuration runs through a REST API – no editing config files, no service restart. Changes are applied atomically, without dropping a single request.

Installation

On Debian/Ubuntu, Unit is in the official repos. Don't forget the Python module:

bash
sudo apt update
sudo apt install unit unit-dev unit-python3

After installation the Unit daemon runs automatically. The API is reachable via a Unix socket – no open port, no auth problem.

The JSON configuration

Instead of classic config files, Unit works with a JSON payload. Here is the minimal configuration for a Django project:

json
{
  "listeners": {
    "*:8000": {
      "pass": "applications/django"
    }
  },
  "applications": {
    "django": {
      "type": "python 3",
      "path": "/var/www/myproject/",
      "module": "myproject.wsgi",
      "environment": {
        "DJANGO_SETTINGS_MODULE": "myproject.settings"
      }
    }
  }
}

The structure is self-explanatory: a listener on port 8000 forwards everything to the Django app. path points to the project directory, module to the WSGI module. That's all you need to get started.

Applying the configuration – without a restart

The configuration is sent to the Unit socket via curl. This is the moment where Unit plays its biggest advantage – the change takes effect immediately, without interrupting the running service:

bash
sudo curl -X PUT --data-binary @config.json \
  --unix-socket /var/run/control.unit.sock \
  http://localhost/config/
Live reconfiguration

You can change worker processes, listener ports or even the Python version while it is running – just adjust the JSON and PUT it again. Unit applies the changes atomically. No systemctl reload, no risk of dropped requests.

After the PUT, the Django app is immediately reachable on port 8000. For production use you typically still put a reverse proxy like Nginx or Traefik in front – but Unit itself can also serve static files directly.

What I left out

Honest boundaries

This article shows the minimal setup. The following is deliberately not covered:

  • Docker deployment. Unit has an official Docker image – that would be an article of its own.
  • Serving static files directly via Unit. It works, but for large projects Whitenoise or a CDN is usually the better solution.
  • ASGI instead of WSGI. Unit can do ASGI too (for Channels, async views) – it needs a slightly different JSON config.
  • systemd hardening. In production the Unit process should be locked down via systemd (ProtectSystem, NoNewPrivileges etc.).

Conclusion & outlook

Nginx Unit is, for me, the cleanest way to put a Django app into production once you are tired of the Gunicorn-plus-Nginx double pack. One component, JSON config over REST, live reconfiguration without downtime. For small to mid-sized projects the setup is done in 15 minutes.

If you already run a reverse proxy like Traefik or Nginx Proxy Manager in your homelab, just put Unit behind it and you have a complete production setup.

// More recommendations

Ad · Affiliate link – if you buy through it, I may earn a commission. It doesn’t change the price for you.

// related posts

> echo "your thoughts" >> production-server-for-a-django-app.responses

Post your comment

Required for comment verification