While Django technically supports multi-site hosting, where multiple Django sites, not apps, are hosted on the same server under the same hostname, accessed via a different URL path. According to Django’s documentation you need to set is the FORCE_SCRIPT_NAME to the path, say “/coolsite2”, and let it do the rest.
Well, to save you the trouble, it, in fact, will not do the rest. You need to edit settings related to static files to use that path explicitly, and your reverse proxy needs to be made aware of this change. On top of this, for some bloody reason, Django doubles up the path you set when actually running it, turning “127.0.0.1/coolsite2” to “127.0.0.1/coolsite2/coolsite2”.
If you’re using Traefik like I am, which is best for a Docker-based deployment, the ability to quickly strip out the second “/coolsite2” was removed in Traefik v2. It took me an embarrassingly long amount of time sifting through the Traefik docs to figure out how to do it. Instead of being two simple lines, it now takes four. Yes, that’s not too much, but it was simpler.
tags:
- "traefik.http.routers.gunicorn-${SITE_NAME}.rule=Host(`localhost`)"
# bring on the needless complexity!
- "traefik.http.routers.gunicorn-${SITE_NAME}.rule=PathPrefix(`/${SITE_NAME}`)"
# strip the path away and continue
- "traefik.http.routers.gunicorn-${SITE_NAME}.middlewares=gunicorn-${SITE_NAME}-stripprefix"
- "traefik.http.middlewares.gunicorn-${GROUP_NAME}-stripprefix.stripprefix.prefixes=/${SITE_NAME}"
However, I can code. So I wrote a Python-based Docker Compose wrapper to simplify this. I now have a few lines that I have to just copy and paste into my Django project’s settings.py file, run a handful of simple commands, and boom, it’s done, all on my own self-hosted hardware.
I’m not going to go too deep into the implementation details here, since I explain it in my GitHub repo: mase3206/web-dev-host. The code is fully open-source, though not open to contributions at the moment.
Full disclosure, I made this for my Web App Development class so each group’s project can be hosted on one VM, but it can be easily adapted to a personal use case. (I will be doing this myself.)