Self-hosted service
TandoorRecipes/recipes avatar
TandoorRecipes/recipes

Tandoor Recipes and the boundaries of a self-hosted recipe manager

Application for managing recipes, planning meals, building shopping lists and much much more!

8,738 stars906 forksHTMLNOASSERTION

At a glance

What is it?
Tandoor Recipes is a Django application for storing your own recipe collection, with meal planning, shopping lists, cookbooks and bulk import. What decides whether it works for you is Postgres, the structured data on the sites you import from, and an AGPL license with a selling exception.
Who is it for?
Tandoor Recipes fits a household or a small group that wants its recipes on its own server and is willing to own the Postgres instance behind it. It does not fit a public multi tenant site, a team expecting AI features to work without picking and paying for a model provider, or anyone who needs resale rights without a licensing review.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly HTML, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • TandoorRecipes/recipes8,738 ★ · +116
Star history
Repository2026-09-222026-11-14
TandoorRecipes/recipes8.6k8.7k

116 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The image is nginx, gunicorn, and a Postgres server you supply

Tandoor Recipes is a Django application, and most people meet it as a container image. The repository Dockerfile starts from python:3.14-alpine3.24 and installs the Alpine build of Postgres client libraries, gettext, nginx, tini, envsubst, nodejs and npm. Two details of that build change how you operate the thing.

bash
FROM python:3.14-alpine3.24
EXPOSE 80 8080
RUN apk add --no-cache postgresql-libs postgresql-client gettext zlib libjpeg libwebp libxml2-dev libxslt-dev openldap git libgcc libstdc++ nginx tini envsubst nodejs npm

The first detail is that the image is a web server as well as an application. It deletes /etc/nginx/http.d, symlinks the repository's own http.d directory in its place, sets that directory to mode 1777 so boot.sh can render configuration at startup, and links the nginx access and error logs to /dev/stdout and /dev/stderr so requests show up in your container logs. Two ports are exposed, 80 for nginx and 8080 for gunicorn.

The second detail is that no database ships inside. requirements.txt pins psycopg2-binary 2.9.12, so Postgres is an external service you run or rent, and it is the engine behind the search features described further down. The repository root holds what a first run touches: an .env.template, boot.sh, version.py, manage.py, a scripts directory, the http.d and nginx directories, and the apps themselves. The published image is vabene1111/recipes on Docker Hub, and the install guide at docs.tandoor.dev/install/docker carries compose files plus Kubernetes, Unraid and Synology examples. The repository does not print a minimal list of required environment variables, so copy the template and work from it.

Search runs on Postgres full text and trigram similarity over rows you own

Search is the part of Tandoor Recipes the project leans on hardest, and it is entirely a Postgres story. The feature list advertises customizable search with full text support plus TrigramSimilarity, which is Django's Postgres trigram distance function, and requirements.txt backs that with psycopg2-binary rather than SQLite. Swap the database for something lighter and the trigram half of the query disappears, and that half is what makes a near miss match when a title is slightly off.

Around that sit the tools for a collection that has grown: create and search tags, assign tags in batch to every file matching a filter, and merge or rename ingredients, tags and units in bulk, so duplicates left behind by hundreds of imports do not have to be cleaned by hand. requirements.txt pins django-treebeard 4.7.1, a modified preorder tree traversal library, django-scopes 2.1.0 for scoped queries, and thefuzz 0.22.1 for fuzzy string matching, which is the shape of stack that merge and rename work needs.

What none of this gives you is a catalog. No recipe library ships with the project, so search covers exactly the rows you imported or typed yourself, and a fresh install searches an empty database until you add something. That is a deliberate trade for a tool meant to hold your own collection, but it means the first evening with the app is spent importing rather than browsing.

Import quality is capped by the structured data a site chooses to publish

Recipe import is a scraping problem wearing a nice interface, and its ceiling is set by the sites you point it at. The import path named in the README is structured data, ld+json or microdata, the two serialization paths of the schema.org Recipe vocabulary, and the project advertises import from thousands of websites.

requirements.txt shows the stack behind it: recipe-scrapers 15.13.0, microdata 0.8.0, beautifulsoup4 4.15.0 and lxml 6.1.3 for parsing, bleach 6.4.0 to scrub imported HTML, requests_hardened 1.3.0 and aiohttp 3.14.5 to fetch pages, and Pillow 13.0.0 for the image compression the feature list mentions.

Two limits follow from that design. A site that ships neither ld+json nor microdata has no structured path into the app, and no other path is named, so pages rendered by JavaScript and anything behind a login are where imports fail outright rather than degrade. Second, structured data is only as complete as its publisher: missing yields, missing units and absent nutrition stay absent, and the values that get filled in later are filled in by hand. There is also a whole collection import route from other recipe managers, and that is the one to use when you are moving rather than adding a few dishes.

The AI features are litellm calls, not a bundled model

The AI features are a thin layer over a provider you choose, and that is the accurate description. The feature list credits AI with recognizing images, sorting recipe steps and finding nutrition facts, jobs that need a model called with your own data.

requirements.txt pins litellm 1.106.2, a wrapper whose entire job is routing requests to whichever backend you select, and no default backend, model or credential variable is named in the README. The consequence for a first run is that nothing here works unattended. Without a configured provider, image recognition, step ordering and nutrition extraction have no service to call, and you are back to manual entry.

The second consequence is about where your data goes. Sending a photo of a family recipe to a hosted model means that image leaves your server, and the design of the wrapper is that traffic ends at a third party account you pay for. Decide that before uploading a few hundred recipes rather than after. Treating all three items as conveniences layered on top of a manual editor is the safer default for a household install, and it is the only configuration that costs nothing extra.

Storage, file sync, and login plug into a long tail of optional backends

A long list of optional backends is what lets Tandoor Recipes sit inside an existing setup, and it is also why the image is heavier than a recipe app looks like it needs to be.

File storage runs through django-storages 1.14.6 and boto3 1.43.118 for object storage, and the Dropbox and Nextcloud sync named in the feature list sits on webdavclient3 3.14.7 for the WebDAV half. Identity has the most options: django-allauth 65.19.4 with the mfa and socialaccount extras, django-auth-ldap 5.3.0 with python-ldap 3.4.7, python3-saml 1.16.0, python3-openid 3.2.0, pyjwt 2.15.1, and django-oauth-toolkit 3.4.1 on the API side. stripe 15.6.1 is present as well, with icalendar 7.3.0 for calendar output.

The cost lands on the build. The image installs openldap, and the dependency stage pulls gcc, cargo, rust, xmlsec and build-base before purging build dependencies afterwards, so your first image build compiles a large amount of native code even if you never touch single sign on. Every integration on that list also needs its own credentials, which makes each one a separate thing that can be half configured.

A basic permission system, and the project's own warning against public pages

The project states its own limit on who should be running this, and it is worth repeating. A basic permission system exists, and the application is not meant to be run as a public page. That sentence fixes the design target: a household, or a small group of friends and family who share recipes, which is exactly what the sharing and cookbook features are arranged around.

The rest of the dependency list is consistent with that audience. The permission system is described as basic, and nothing in the repository documents rate limiting, abuse controls or an invitation path for strangers, so a public deployment inherits the job of building all of it yourself.

If you need a public recipe site with open signup and per user isolation, this is the wrong tool, and the search, tagging and batch editing that make it pleasant for a family will not make it safe for the open internet. The project's own hosted offering at app.tandoor.dev is described as currently available in Germany only, which is another signal about the scale it was built for. Read the sharing features as private group features, and keep the container off any address strangers can reach.

Licensing is AGPL v3 with a selling exception the project calls unsettled

The license is the one place where the repository is openly uncertain, and you should read it before you build a plan on top of this application. From version 0.10.0 the code is GNU AGPL v3 with a common clause selling exception. The README says there appears to be a whole range of legal issues with licensing anything other than the standard completely open licenses, that professional legal advice is being sought, and that issue 238 holds the discussion and reasoning.

In practice the common clause means you may use, self host and modify the code freely, including commercially inside your own organization, but you may not resell the software itself as a hosted product. The stated reason is time: a significant amount of work across multiple years, funded by a paid hosted version planned to be identical in features and codebase to what the repository offers.

For a family or a small team this is a non issue. For a company that might want to offer this to its own customers, it is a licensing review rather than an engineering one, and the uncertainty described above is a reason to get your own answer rather than assume the selling exception is settled. LICENSE.md in the repository is the authority, not the summary above it.

The healthcheck is commented out in the Dockerfile, tracked as issue 3478

The container ships without a health probe, and the reason is left in the file rather than explained. The block that would define HEALTHCHECK with a 30 second interval, a 5 second timeout and a 10 second start period is commented out, with a note that it is commented for now and a link to issue 3478.

bash
#HEALTHCHECK --interval=30s \
#            --timeout=5s \
#            --start-period=10s \

The operational consequence is specific. Nothing inside the container tells an orchestrator whether the application is actually working, so a container can keep serving connections on port 80 through nginx while gunicorn on 8080 has no reachable database behind it, and a compose file or Kubernetes deployment without its own probe will report that as healthy until a user hits an error page. Supply your own readiness check that touches the application rather than the port.

Release cadence is otherwise steady, with 2.7.0 and 2.7.1 on 2026-10-23 and 2.7.2 on 2026-10-27, and a push to the develop branch, which is the default branch, on 2026-11-01. Development tooling is pinned hard: pytest 9.0.3 with pytest-django 4.11.1, pytest-cov 6.2.1 and pytest-xdist 3.8.0, flake8 7.3.0 and yapf 0.40.2, and the image strips the development block out of the dependency list with a single line.

Editorial conclusion

Tandoor Recipes fits a household or a small group that wants its recipes on its own server and is willing to own the Postgres instance behind it. It does not fit a public multi tenant site, a team expecting AI features to work without picking and paying for a model provider, or anyone who needs resale rights without a licensing review. Check three things before committing: that you can host Postgres and accept a first image build that compiles native code for libraries you may never use, that the sites you import from publish ld+json or microdata, and that the common clause selling exception in LICENSE.md clears for your organisation.

Frequently asked questions

What can Tandoor Recipes tell me about what to cook tonight?

No catalog of dishes ships with it. You keep your own collection, plan multiple meals for each day, and build a shopping list either from the meal plan or straight from a single recipe.

What are the trending recipes right now according to Tandoor Recipes?

Nothing in it tracks popularity. Search combines full text support with trigram similarity over the rows in your own database, so results only ever cover recipes you imported or entered.

Does Tandoor Recipes import recipes from other websites?

It claims import from thousands of sites, but only through structured data, ld+json or microdata, handled by recipe-scrapers 15.13.0 and microdata 0.8.0. A site publishing neither has no import path named in the README.

Can I run Tandoor Recipes as a public website for anyone to sign up?

The project says a basic permission system exists and that the application is not meant to be run as a public page. Treat sharing as a feature for family and friends, not for strangers.

What license is Tandoor Recipes released under?

GNU AGPL v3 with a common clause selling exception since version 0.10.0. Use and self hosting are free, reselling the software as a hosted product is not, and issue 238 tracks the open legal questions.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. TandoorRecipes/recipes on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/tandoorrecipes-recipes.svg)](https://hysenlabs.com/projects/tandoorrecipes-recipes)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/tandoorrecipes-recipes.svg)](https://hysenlabs.com/projects/tandoorrecipes-recipes)

Was this useful?