Repository navigation
Tandoor Update Webserver Issues - Integrated Nginx #3851
Description
Tandoor 2.3 Update
With Tandoor update 2.3.0 the migration to the internal nginx server was completed, removing the ability to access the integrated python wsgi server directly. This should not cause issues for people who had already migrated to the internal nginx (see below) but does cause issues for some people. Here are the relevant problems and fixes:
Tandoor Port Change
If you had TANDOOR_PORT set but still pointed your reverse proxy to 8080 you will no longer reach Tandoor. 6adf077.
Fix: point to whatever you configured in TANDOOR_PORT or unbind and point to port 80
Tandoor is not reachable
You are likely still using the old Tandoor v1 setup.
Fix: Remove the nginx as described in the section below.
502 Error after Login
The following error can happen after logging in to Tandoor v2.3.0 if you do not have a reverse proxy or in all versions if your reverse proxy is not configured to correctly forward the client ip address by setting the X-Forwarded-For header.
web_recipes-1 | django.db.utils.IntegrityError: null value in column "ip" of relation "usersessions_usersession" violates not-null constraint
web_recipes-1 | DETAIL: Failing row contains (2, 2025-10-06 21:33:08.606563+00, null, 2025-10-06 21:33:08.60659+00, vasudujcixxye751c1qtps2leojbif0c, Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:143.0) Gecko/20..., {}, 1).
Fix
- If you do not want to use a reverse proxy upgrade to version 2.3.1 and the issue is fixed.
- If you want to use a reverse proxy make sure it sets the header. Example for nginx is
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
See also #4126
Unraid
The unraid template is hardcoded to port 8080. The template was updated but it might not update existing installations (see #3851 (comment))
There are two fixes:
- add another Port mapping to port 80 as described here Can't Access Tandoor GUI After Update (Unraid) #4120 (comment)
- change
TANDOOR_PORTto8080(awaiting confirmation that this works but it should)
Tandoor 2 Update
Tandoor 1 includes gunicorn, a python WSGI server that handles python code well but is not meant to serve mediafiles. Thus it has always been recommended to setup an nginx webserver (not just a reverse proxy) in front of Tandoor to handle mediafiles. The gunicorn server by default is exposed on port 8080
Tandoor 2 now bundles nginx inside the container and exposes port 80 where mediafiles are handles by nginx and all the other requests are (mostly) passed to gunicorn.
To update you must simply change your port or reverse proxy configuration to access port 80 instead of port 8080.
Accessing 8080 directly is deprecated and will be removed in the future. Sufficient warnings and explanations will be given.
⚠️ UPDATE 2.3.0 changedTANDOOR_PORTto configure the internal nginx instead of gunicorn. This breaks in two cases
- if you had
TANDOOR_PORTset but still pointed your reverse proxy to80806adf077. Fix: point to whatever you configured inTANDOOR_PORTor unbind and point to port80- if you had the pre V2 default setup and pointed your proxy to
8080which is now no longer exposed. Fix: point your proxy to port80and remove the nginx
Should you have any issues with the change feel free to post your questions below, I will try to update this main comment with FAQ's should they arise.
Example
If you were using Traefik for the reverse proxy your Tandoor 1 docker-compose.yml might have looked something like this:
services:
db_recipes:
restart: always
image: postgres:16-alpine
volumes:
- ./postgresql:/var/lib/postgresql/data
env_file:
- ./.env
networks:
- default
web_recipes:
image: ghcr.io/tandoorrecipes/recipes
restart: always
env_file:
- ./.env
volumes:
- staticfiles:/opt/recipes/staticfiles
- mediafiles:/opt/recipes/mediafiles
- nginx:/opt/recipes/nginx/conf.d
depends_on:
- db_recipes
networks:
- default
nginx_recipes:
image: nginx:mainline-alpine
restart: always
env_file:
- ./.env
volumes:
- nginx:/etc/nginx/conf.d:ro
- mediafiles:/media
labels: # This lables are only examples!
- "traefik.enable=true"
- "traefik.http.routers.recipes.rule=Host(`recipes.sienz.family`)||Host(`rezepte.sienz.family`)"
- "traefik.http.routers.recipes.entrypoints=web_secure"
- "traefik.http.routers.recipes.tls.certresolver=le_resolver"
networks:
- default
- traefik
networks:
default:
traefik: # This is you external traefic network
external: true
volumes:
nginx:
staticfiles:
mediafiles:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: './mediafiles'
Beginning with Tandoor 2 (beta 6) you can now remove the nginx container and point your Traefik (reverse proxy) directly at Tandoor like this.
services:
db_recipes:
restart: always
image: postgres:16-alpine
volumes:
- ./postgresql:/var/lib/postgresql/data
env_file:
- ./.env
networks:
- default
web_recipes:
image: ghcr.io/tandoorrecipes/recipes
restart: always
env_file:
- ./.env
volumes:
- staticfiles:/opt/recipes/staticfiles
- mediafiles:/opt/recipes/mediafiles
depends_on:
- db_recipes
labels:
- "traefik.enable=true"
- "traefik.http.routers.recipes.rule=Host(`your.tandoor.url`)"
- "traefik.http.routers.recipes.entrypoints=web_secure"
- "traefik.http.routers.recipes.tls.certresolver=le_resolver"
networks:
- default
- traefik
networks:
default:
traefik: # This is you external traefic network
external: true
volumes:
staticfiles:
mediafiles:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: './mediafiles'
You also no longer need to mount the nginx volume to sync the default config from tandoor to the nginx container. Should you need to edit the nginx config for some reason you can do so by mounting the /opt/recipes/http.d/ directory to your host system. Keep in mind that when doing this you will not receive updates on this file in future versions.
Activity
soxism commentedon Jul 31, 2025
Just deployed this and can confirm its working smoothly.
I had an existing deployment and had defined ports in docker-compose and .env - so it should be noted that those need to change back to port 80.
99-lives commentedon Jul 31, 2025
Noting in case anyone else has this issue.
With this version, you must name your docker container
web_recipes, because that's the host that the built-in Nginx config is configured to proxy. If you name your container anything else, as I did, then it won't work. I've opened issue #3856 to track this, if it is indeed considered a bug.vabene1111 commentedon Jul 31, 2025
thanks for the report, this was not intended and is fixed now.
Thanks for the information. I will add a note about this in the migration guide and later remove the port option alltogether.
wilmardo commentedon Jul 31, 2025
@vabene1111 would you be willing to accept an PR for this change still? The has moved to stable so quick that I haven't had time to provide proper feedback.
But I can for sure say that this setup is going to have a lot of issues, bash doesn't forward signals to started processes so nginx will become a zombie when the container is restarted.
Also it would have been easy to setup nginx on port 8080 and setup a non root user as well.
vabene1111 commentedon Jul 31, 2025
I am happy to accept PRs. I wanted it on port 80 so that is on purpose. If you have a better idea on how to run the nginx feel free to suggest (I suggest we start a different issue for the discussion).
My plan was to deprecated the exposed gunicorn after the first error fixing phase of 2.0.0 in a few weeks maybe,just FYI
tomsinclair94 commentedon Jul 31, 2025
In my setup I have exposed Tandor on a different port and previously had this in the
nginx_recipessection:For this migration to the intergrated nginx, I simply removed the entire block for the
nginx_recipesimage (as mentioned in the docs) and added myports:config line to theweb_recipessection and everything is working and I can still access Tandoor on this custom port.Will exposing the internal port 80 to a custom external port still be supported?
Edit: I believe you may have been referring to removing the option to override the
TANDOOR_PORToption inside the .env file?vabene1111 commentedon Jul 31, 2025
yes, the option will no longer be necessary in the future because you can override the nginx config to change the port
vabene1111 commentedon Aug 8, 2025
note from #3911 :
if you delete your old nginx make sure to either down the container before changing the docker compose file or to remove the orphaned containers when starting the docker compose without nginx.
TomAFrench commentedon Sep 6, 2025
I'm running into an issue related to image files and how the nginx server is set up.
Opening
my.tandoor.com/media/recipes/recipe_file.jpgin the browser gets a response with the expected picture file being downloaded with the server header set tonginx. However if I openmy.tandoor.comthen all of the recipe images are white squares (note this is not the placeholder pizza image). If I open the network tab in the browser console then I can see thatgunicornis serving the request to the exact same URL I opened directly earlier and we're getting the tandoor page source being sent instead.Requests from
my.tandoor.comare then not being routed as expected by nginx but I'm not clear on what I should do to address this, if someone can help I'd be very grateful. I'm running tandoor 2.1.0 in a traefik setup basically identical to that in the OP.Edit: Curious, the images are loading fine on my phone.
Edit 2: Even more strangely this isn't affecting new recipes I'm adding. Only those which I exported from the hosted version of tandoor and reimported into my instance.
paulmaurovich commentedon Sep 14, 2025
After some debugging and manually looking through
http.d/andnginx/directories, I have found that doing the following80(instead of8080)80via treafik3TANDOOR_PORTunsetmakes the images load properly. Running inside
k8swithcontainerd.Setting port
8080and connecting to it works fine, but this results in non-loading images. If I've read it correctly, connecting to port8080is deprecated and80is the way to go (now; with v2).wolsen9 commentedon Sep 29, 2025
Just adding my comments to agree with @paulmaurovich , linking to port 80 with Tandoor 2 works as expected while port 8080 left me with no images. The docs still refer to port 8080, so I'm not entirely sure the correct method.
As for anyone else that may be using Caddy as a reverse proxy, the Tandoor docker compose I'm using is below. Nothing special with Caddy, just reverse proxing to the exposed port. Works with Kitchn as well. I am far from fluent with these networks and proxy forward headers:
vabene1111 commentedon Sep 30, 2025
With the next update (2.3) I will complete the migration to the internal nginx by removing the option to bind directly to gunicorn from outside of the container.
👍 everyone already using the integrated nginx by pointing to port 80 does not need to change anything if
TANDOOR_PORTis not set.Gunicorn will be bound to the nginx internally using a unix socket, that means binding it from the outside no longer works (i think, mabye you can bind the socket but you shouldn't).
The
TANDOOR_PORTenvironment variable will no longer configure gunicorn, it now configures nginx. This means if you hadTANDOOR_PORTconfigured before the update and pointed your reverse proxy to it everything works automatically, as you now just access nginx.TANDOOR_PORTset to any port but were still using port8080to directly access gunicorn your setup will no longer work. This configuration never made sense so you should either removeTANDOOR_PORTand just point to 8080 (should be the correct way for 99,99% of people) or changeTANDOOR_PORTto the port you want to use.greenbear48 commentedon Oct 7, 2025
Hi,
First, thank you for maintaining the vabene1111/recipes Docker image. It's a fantastic project.
I'm writing to report two critical issues I encountered after the image was updated on October 5th, 2025. These issues make the latest version unusable for me on Unraid, especially when using a reverse proxy. Downgrading to version 1.5.13 solved all problems.
Issue 1: Internal Listening Port Changed from 8080 to 80
Symptom: After the update, the container was completely unreachable via the network.
Cause: We discovered that the internal listening port of the container changed from the previous 8080 to 80.
Impact: This breaks the standard Unraid Community Application template for Tandoor, which has the container port locked to 8080. Users are unable to edit this, making the update immediately break their setup.
Workaround: We had to manually add a new, second port mapping in Unraid (Host Port 8155 -> Container Port 80) to regain access to the web UI.
Issue 2: Reverse Proxy IP Detection Failure (DB IntegrityError on Login)
This is the more critical bug.
Symptom: When accessing the container through a reverse proxy (Nginx Proxy Manager), the login page loads correctly. However, after submitting valid login credentials, the application crashes with a Server Error (500).
Cause: The container log shows a consistent database error. The application is unable to get the client's real IP address from the reverse proxy headers, causing it to try and write a NULL value to the ip column in the usersessions_usersession table.
Log Traceback:
django.db.utils.IntegrityError: null value in column "ip" of relation "usersessions_usersession" violates not-null constraint
Troubleshooting Steps Taken: We tried every standard environment variable to fix this, but none of them worked on the latest image:
BEHIND_REVERSE_PROXY=true
FORWARDED_ALLOW_IPS='*'
DJANGO_TRUSTED_PROXIES (with various values like 192.168.1.0/24 and the specific WireGuard IP of the proxy)
None of these variables resolved the 500 error, which strongly suggests the internal Nginx/Gunicorn configuration in the latest image is not correctly processing X-Forwarded-For headers.
Final Solution & System Info
Working Solution: The only way to fix the issues was to downgrade the image. By changing the repository in Unraid to vabene1111/recipes:1.5.13, the container started working perfectly again. The listening port reverted to 8080, and the reverse proxy login works without any extra environment variables.
My Environment:
Host: Unraid OS
Reverse Proxy: Nginx Proxy Manager (on a separate server, connected via WireGuard)
Problematic Image: vabene1111/recipes:latest (as of 2025-10-07)
Working Image: vabene1111/recipes:1.5.13
It seems the latest update introduced a breaking change in the networking setup. I hope this detailed report helps you track down and resolve the bug.
Thanks again for your work!
Best regards
greenbear
vabene1111 commentedon Oct 8, 2025
@greenbear48 thanks for the summary. While many things are true I cannot agree on some:
Issue 1: This is not a bug but a feature. The port was changed on purpose as indicated in the changelog. Someone needs to fix the unraid template which is not maintained by me but someone else.
What would be interesting if someone could change
TANDOOR_PORTto 8080, this should also fix the unraid setup.Issue 2:
As far as I have seen in the Issues any user that does use a reverse proxy could resolve the issue by adding the appropriate headers. It is only affecting users not running a reverse proxy at the moment. For everyone that has a reverse proxy make sure this header is present http://172.18.0.4:80/api/recipes/
for anyone else: please downgrade to 2.2.7 and wait for the next release which hopefully will include a fix.
[-]Integrated Nginx[/-][+]Tandoor Update Webserver Issues - Integrated Nginx[/+]LekoArts commentedon Oct 8, 2025
Unraid: Any new installations of the Unraid plugin should work as the author updated the template: https://forums.unraid.net/topic/98179-support-tandoor-recipes-corneliousjd-repo/page/5/#findComment-1582644
CorneliousJD/Docker-Templates@2826e3a
I'm not sure if this retroactively also updates existing installations, at least for me it didn't do that.
I've got my Unraid setting up working by updating the template myself, too. For that you'll need to edit the Docker container, remove the "Port" and re-add it with the Container Port being 80 (previously 8080). Then on the top right switch to "Advanced View" and change
WebUItohttp://[IP]:[PORT:80]uncoverbrokkoli commentedon Oct 9, 2025
Just updated to the newest version. After some hassle it now works fine with my ngnix reverse proxy running in a different container.
I use the pre-configured site configuration that come with nginx and there is still port 8080 mentioned. Updating it to port 80 resolved my issues. Maybe the nginx configuration defaults can be changed so that it makes updating easier?
vabene1111 commentedon Oct 10, 2025
definitely, if you see issues in existing documentation always feel free to fix them. I personally only maintain the docker installation instructions as I simply do not have the time to maintain all the community guides.
update-freak commentedon Oct 10, 2025
With latest update I got this on my synology nas (DSM 7.3) in docker:
(with Tandoor 2.2 it works)
docker compose:
EDIT: solved it via
AdrienPoupa commentedon Oct 14, 2025
I'm using a custom Nginx configuration. My setup was broken until I changed the proxy_pass instruction from a port to the socket: AdrienPoupa/docker-compose-nas@e940db7
I think it is confusing that there are two configurations in the repo at the moment:
TimNiceButDim commentedon Nov 16, 2025
Lost all my recipes, cant seem to figure out how to get this docker working anymore :( such a shame, how did an update break everything so badly
laur89 commentedon Nov 16, 2025
Take it as a learning lesson to back up your data.
vabene1111 commentedon Nov 18, 2025
there should be absolutely nothing going on about your data when performing the update. Worst that can happen is you rollback to the previous version.
Data loss is typically related to people not mounting the postgres directory properly.
PiiiRKO commentedon Jan 13, 2026
I feel you. Dealing with the same thing. I am not a big tech power user, so figuring this out is pretty beyond my capabilities. I know the recipes are still in the database, tandoor just doesn't want to see them in the new updated instance.
vabene1111 commentedon Jan 23, 2026
@PiiiRKO i recommend you open an issue with some information so people can actually help you because like this nobody can do anything. Otherwise the instructions do work for many people so maybe review if you have followed them correctly.