Running Django with Nginx Unit

Running Django with Nginx Unit

I first discovered Unit back in 2019, when it was first released. Submitted a couple of issues on their Github. I was quite interested but it's not ready yet at that time.

Then I forgot, until yesterday. Was reading some discussion (forgot where) and someone mentioned Unit in the comment. Damn, I should check it back.

Nginx Unit is described as a universal application server, as it can run many different languages such as Python, PHP, Java, Ruby, Nodejs, Go and so on. All from the same unit executable, no need for extra program.

My current deployment setup right now is using Podman running under systemd. While it seems to work, there are a few things that left me unsatisfied:-

  • It uses podman 3.4 as that the latest version available in Ubuntu 22.04. Podman 4 has a better way of running under systemd.

  • Running under systemd as the system's unit file with User= is not supported. So you're left with running it as a user's services. I'm fine with this, and this is what I prefer except ...

  • Systemd user's service only meant to last for the login user's session. You log out, it's gone. Wth. So it's meant for an interactive session, iow desktop, not server.

  • The workaround is to run loginctl enable-linger. This would let the service continue running even after you have logout.

So when Nginx Unit came back into the picture, I was thrilled. Unit configuration is done through HTTP API. You submit the config as json string. This is great for automation. No more sed to replace some placeholder in nginx config. Everything can be done programmatically.

The documentation is also very complete now, to the extent that this blog post is not needed actually. But I'll just add some extra notes that may not easily found in the docs. For the rest, just refer to their Django docs.

So the extra notes:-

  • When serving static files through routes match, the matched path is not stripped of the $uri value. So if you have url path such as /static/css/app.css, you need to have a directory static as well. In other words, your share value has to be /path/to/app/$uri and not /path/to/app/static/$uri. Because /static also exists in $uri.

  • Also static files, it served by the router process which runs under a different user than the user we specified for our app, so need to make sure that the user has permission to read the static files. In my case, the app is running as a user myapp but the router process is running under the user unit. You can check with ps auxw | grep unit. There are 3 processes run by unit. The first is unitd runs as root, and then router and controller process running under the user unit.

That's all for now. I'll add more as I spend more time with Unit.