Take Control of Your Recipe Collection
Storing recipes across browser bookmarks, screenshot folders, and dog-eared cookbooks is a familiar kind of chaos. Tandoor is an open-source, self-hosted recipe manager that centralizes everything – importing from URLs, organizing with tags and categories, generating shopping lists, and scaling ingredient quantities – all running on your own server, with no subscription fees and no third-party access to your data.

What You Need Before You Start
Tandoor runs best via Docker, so the setup assumes you have Docker and Docker Compose installed on your host machine. This could be a home server, a Raspberry Pi 4 or later, a VPS, or any Linux machine with a stable connection. The application itself is lightweight enough to run on modest hardware, but if you plan to store hundreds of recipes with images, allocate at least 2GB of RAM and sufficient disk space for your media files.
You will also need a basic understanding of editing configuration files in a terminal. Tandoor uses a PostgreSQL database by default, which Docker Compose handles automatically – you do not need to install or configure Postgres separately. A reverse proxy like Nginx or Caddy is strongly recommended if you want to access Tandoor from a web browser using a clean domain name rather than an IP address and port number. If you plan to expose the application outside your local network, consider using a Cloudflare Tunnel to expose the service without opening firewall ports.
Create a dedicated directory for the project before anything else. Something like /opt/tandoor or ~/docker/tandoor works well. Inside that directory you will place your docker-compose.yml file and a .env file holding environment variables. Keeping these separate from other Docker projects prevents configuration conflicts and makes future updates much easier to manage.
Pull the official Tandoor repository or copy the sample Docker Compose file from the project’s GitHub page at github.com/TandoorRecipes/recipes. The repository includes a ready-made docker-compose.yml with a PostgreSQL service, the Tandoor app container, and volume definitions for persistent data. Download that file directly into your project directory rather than writing one from scratch – the official version handles volume naming and service dependencies correctly.

Configuring and Running Tandoor
The .env file is where most of your configuration lives. Create it in the same directory as docker-compose.yml. At minimum, you need to set the following variables: SECRET_KEY, POSTGRES_PASSWORD, POSTGRES_USER, POSTGRES_DB, and DB_ENGINE. The secret key should be a long, random string – you can generate one with openssl rand -base64 50 in your terminal. Set DB_ENGINE to django.db.backends.postgresql and make sure the Postgres credentials in your .env file match what the Docker Compose file expects.
For the TANDOOR_PORT variable, pick a port that is not already in use on your host – 8080 is a common choice. Set ALLOWED_HOSTS to either your server’s IP address or the domain name you plan to use. If you are running a reverse proxy in front of Tandoor, set GUNICORN_MEDIA to 0 so that Nginx or Caddy handles static file serving instead of the application itself, which noticeably improves performance for image-heavy recipe collections.
Once the .env file is saved, start the stack with docker compose up -d from inside your project directory. Docker will pull the Tandoor and PostgreSQL images, create the named volumes, and start both containers. The first startup takes longer than usual because Django applies database migrations automatically. Watch the logs with docker compose logs -f web – when you see the Gunicorn server reporting that it is listening, the application is ready.
Open a browser and navigate to http://your-server-ip:8080. Tandoor will prompt you to create an admin account on first access. Fill in a username, email, and strong password, then log in. The interface is clean and organized into sections: Recipes, Books, Shopping, and Meal Plans. Before importing anything, go to Settings and configure your preferred units (metric or imperial), default number of servings, and language. These settings apply globally and save you from adjusting each recipe individually.
Importing a recipe from a URL is the fastest way to test whether everything is working. Paste a link from any major recipe website into the import field – Tandoor uses structured data parsing to extract ingredients, steps, and images automatically. Not every website formats its structured data cleanly, so some imports need minor manual corrections, particularly for ingredient quantities written as fractions or ranges. For recipes that do not have a web source, Tandoor supports manual entry and bulk import via JSON or a compatible format, giving you a clear path for migrating content from other tools.
Organizing, Sharing, and Staying Updated
Tandoor’s organizational system uses keywords, categories, and books – think of books as curated collections, similar to folders, while keywords work more like tags that cut across multiple books. A recipe can belong to several books and carry multiple keywords simultaneously, which makes filtering by cuisine type, cooking method, or dietary restriction fast and reliable once your library grows. The shopping list feature pulls ingredients directly from any recipe and lets you combine multiple recipes into a single list, adjusting quantities automatically when you change serving sizes.

Keeping Tandoor updated is straightforward with Docker. Run docker compose pull to fetch the latest images, then docker compose up -d to restart the stack with the new version. Database migrations run automatically on startup, so you rarely need to intervene manually. Back up your PostgreSQL data and media volume periodically – a simple docker exec command targeting the Postgres container with pg_dump produces a portable backup file. Losing a carefully tagged library of three hundred recipes because of an unplanned disk failure is the kind of problem that only happens once before backup routines become non-negotiable.





