Deploy Tandoor
Recipe manager and meal planner with automatic shopping lists
Redis
Just deployed
/data
Tandoor
Just deployed
Just deployed
/var/lib/postgresql/data
tandoor-media
Bucket
Just deployed

Deploy and Host Tandoor on Railway
Tandoor is an open-source recipe manager and meal planner for people tired of losing recipes to bookmarks, screenshots and blog posts buried under nine paragraphs of preamble. Paste a URL and it reads the page's structured data, pulling out the title, times, photo and method and splitting every ingredient line into a real amount, unit and food. That data then drives a meal calendar, a shopping list grouped by aisle, a pantry inventory and full-text search. Households share a space, so two people plan the week together and check items off the same list from their phones.
Self-host Tandoor on Railway and this template gives you the production shape, not the single-container demo. The Tandoor service runs the Django app behind its bundled nginx and is the only service with a public URL. Managed PostgreSQL holds recipes, plans, lists and the food catalogue; managed Redis backs Django's cache, keeping signed media links fast across every worker; and a managed object storage bucket holds every uploaded photo, so images survive redeploys and the app service stays stateless.

Getting Started with Tandoor on Railway
Set TANDOOR_ADMIN_USER and TANDOOR_ADMIN_PASSWORD before you deploy — the only two values this template asks of you. The image creates that superuser at startup, before the web server accepts a request, closing the setup page Tandoor otherwise leaves open and unauthenticated on a public URL.
When the deployment goes green, open the public URL and sign in. A short wizard asks you to name your space, pick a default unit and create a household. Its second step offers the community Open Data import — accept it. That seeds roughly 390 foods, 14 units, 22 supermarket categories and 163 conversions, which is what makes shopping lists group by aisle and lets the app convert cups to grams.
Your first real action should be an import. Click Import, choose Url Import, paste a link to any recipe page and step through. Watch the Steps screen: if each ingredient line has split into a number, a unit and a food, the parser, the database and the Open Data catalogue are working together. Save it, drag the recipe onto a day in Meal Plan, then add its ingredients to your shopping list. If the list appears scaled to your serving count and sorted under category headings, the deployment is healthy end to end.
Public registration is off by default. To add family members, open Settings, create an invite link and send it to them.

About Hosting Tandoor
Recipe collections are personal data with a long life, and most popular places to keep them are somebody else's business model. Tandoor suits households and small cooking groups who want that collection in a database they control, exportable at any time, with no subscription and no ads around the method. Teams also run it for test kitchens and catering, where a structured ingredient list beats a spreadsheet.
Key features:
- URL import from thousands of recipe sites, plus JSON, HTML and bookmarklet importers
- An ingredient parser turning free text into amount, unit and food records
- Meal plan calendar with an auto-planner and recurring entries
- Shopping lists built from recipes and plans, grouped by supermarket category
- Pantry inventory, households and spaces with roles and invites
- Recipe books, keywords, nutrition properties, unit conversions
- A full REST API and a progressive web app for phones
The architecture is deliberately split. Tandoor is the Django application and its bundled nginx, serving the API and the Vue frontend on one port. PostgreSQL is the system of record and powers search through its trigram and unaccent extensions, which the migrations enable. Redis is Django's shared cache — without it each worker keeps its own in-memory copy, so signed media URLs are recomputed constantly. Object storage holds uploaded images behind short-lived signed URLs, so pictures are never publicly listable.
Why Deploy Tandoor on Railway
Railway removes the parts of self-hosting a Django app that are not about cooking.
- PostgreSQL, Redis and object storage are provisioned and wired up
- TLS and a public domain are automatic; custom domains take a click
- The first admin is created at boot, so no setup page is exposed
- Photos live in object storage, so the app holds no state
- Scaling and metrics are built in, with no server to patch
Common Use Cases
- A household collecting recipes from across the web and planning the week together, with one list both phones check off at the shops
- Replacing a paid recipe app with a private instance that exports cleanly and keeps working when a subscription lapses
- Catering teams standardising quantities, conversions and nutrition data in one shared recipe book
- Developers pulling recipe data from the REST API to drive kitchen displays
Dependencies for Tandoor
- Tandoor — gridalpha/tandoor-railway, a thin layer over the official
vabene1111/recipesimage. Runs Django, gunicorn and nginx. - PostgreSQL 18 — system of record for recipes, plans, lists, foods and users, and the search backend via
pg_trgmandunaccent. - Redis 8.2 — Django's shared cache, keeping signed image URLs hot across workers.
- Object storage bucket — recipe photos and files, behind signed URLs.
Environment Variables Reference
| Variable | Purpose |
|---|---|
SECRET_KEY | Django signing key. Must stay stable — changing it logs everyone out |
TANDOOR_ADMIN_USER | Username for the superuser created at first boot |
TANDOOR_ADMIN_PASSWORD | Password for that account. Change it in the app after |
ENABLE_SIGNUP | 0 closes public registration; use invite links instead |
ALLAUTH_TRUSTED_PROXY_COUNT | Proxy hops in front of the app. 3 is correct on Railway |
S3_ACCESS_KEY | Setting any value switches media storage to the bucket |
Deployment Dependencies
- Source repo: gridalpha/tandoor-railway
- Upstream: TandoorRecipes/recipes
- Image: vabene1111/recipes
- Docs: docs.tandoor.dev
Hardware Requirements for Self-Hosting Tandoor
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 1 vCPU | 2 vCPU |
| RAM | 1 GB | 2 GB |
| Storage | 2 GB database | 5 GB plus object storage |
| Runtime | Python 3.13, PostgreSQL 12+ | Python 3.13, PostgreSQL 18, Redis 8 |
A household instance is comfortable at the minimum. Bulk imports are the heaviest operation; give the app 2 GB to import a large collection at once.
Self-Hosting Tandoor with Docker
The official image needs PostgreSQL and a handful of variables. A minimal Compose file:
services:
db:
image: postgres:18-alpine
env_file: [.env]
volumes: ["./pgdata:/var/lib/postgresql/data"]
web:
image: vabene1111/recipes:latest
ports: ["8080:80"]
env_file: [.env]
volumes: ["./media:/opt/recipes/mediafiles"]
depends_on: ["db"]
Or build from source:
git clone https://github.com/TandoorRecipes/recipes.git
cd recipes
cp .env.template .env # fill in SECRET_KEY and POSTGRES_PASSWORD
docker compose up -d
Either way you own TLS, backups, the database and the media directory. On Railway those come with it.
Is Tandoor Free to Self-Host?
Tandoor is open source under the AGPL v3 with a Commons Clause selling exception. There is no paid tier, licence key or usage limit — every feature is in the code you deploy. The project accepts sponsorship, and a hosted option exists for anyone who would rather not run it. On Railway you pay only for the compute, database and storage the deployment uses.
FAQ
What is Tandoor? A self-hosted recipe manager and meal planner. It imports recipes from the web, parses their ingredients into structured data, and turns your weekly plan into a categorised shopping list the household shares.
What does this Railway template deploy? Four things: the Tandoor application, a managed PostgreSQL database, a managed Redis cache, and an object storage bucket for photos. Only the application gets a public URL.
Why does the template include Redis and object storage? Redis is Django's shared cache, so signed image URLs are computed once rather than once per worker. Object storage keeps photos off the container filesystem, so images survive redeploys and the app can be scaled out.
How do I create the first user in self-hosted Tandoor?
Set TANDOOR_ADMIN_USER and TANDOOR_ADMIN_PASSWORD before deploying. The account is created at startup, so the unauthenticated setup page never becomes reachable. Change the password from the account menu once you are in.
How do I let my family sign up to my Tandoor instance?
Leave ENABLE_SIGNUP at 0 and use invite links from the settings screen. That keeps the instance closed to the internet while letting anyone you invite create an account.
Template Content
