feat: add Tandoor recipe manager to infrastructure
Added Tandoor Recipes as a comprehensive recipe management solution: **Tandoor Stack** (tandoor.pivoine.art): - Modern recipe manager with smart scaling and collaboration - PostgreSQL backend for recipe persistence - Email notifications via IONOS SMTP - Static and media file storage in dedicated volumes - User signups disabled (admin-only access) **Features:** - Smart recipe scaling (auto-adjust ingredients for servings) - Spaces for collaboration (family/roommate recipe sharing) - Meal planning and shopping lists - Recipe import from URLs - Mobile app support (Kitshn app) - Nutritional information and pricing **Infrastructure updates:** - Added tandoor database to PostgreSQL init script - Added environment variables to arty.yml - Updated compose.yaml include list - Added Tandoor volumes (staticfiles, mediafiles) to Restic backup - Configured email notifications for invitations and notifications **Tech stack:** - Django/Python backend - Vue.js frontend - PostgreSQL database (shared core instance) - Gunicorn WSGI server Tandoor provides superior UX compared to Mealie with better recipe scaling, collaboration features, and mobile app experience. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
13
arty.yml
13
arty.yml
@@ -54,6 +54,19 @@ envs:
|
|||||||
MATTERMOST_IMAGE: mattermost/mattermost-team-edition:latest
|
MATTERMOST_IMAGE: mattermost/mattermost-team-edition:latest
|
||||||
MATTERMOST_TRAEFIK_HOST: mattermost.pivoine.art
|
MATTERMOST_TRAEFIK_HOST: mattermost.pivoine.art
|
||||||
MATTERMOST_DB_NAME: mattermost
|
MATTERMOST_DB_NAME: mattermost
|
||||||
|
# Tandoor
|
||||||
|
TANDOOR_TRAEFIK_ENABLED: true
|
||||||
|
TANDOOR_COMPOSE_PROJECT_NAME: tandoor
|
||||||
|
TANDOOR_IMAGE: vabene1111/recipes:latest
|
||||||
|
TANDOOR_TRAEFIK_HOST: tandoor.pivoine.art
|
||||||
|
TANDOOR_DB_NAME: tandoor
|
||||||
|
TANDOOR_ENABLE_SIGNUP: 0
|
||||||
|
TANDOOR_REVERSE_PROXY_AUTH: 0
|
||||||
|
TANDOOR_EMAIL_USE_TLS: 0
|
||||||
|
TANDOOR_EMAIL_USE_SSL: 1
|
||||||
|
TANDOOR_GUNICORN_MEDIA: 0
|
||||||
|
TANDOOR_COMMENT_PREF_DEFAULT: 1
|
||||||
|
TANDOOR_SHOPPING_MIN_AUTOSYNC_INTERVAL: 5
|
||||||
# Scrapy
|
# Scrapy
|
||||||
SCRAPY_TRAEFIK_ENABLED: true
|
SCRAPY_TRAEFIK_ENABLED: true
|
||||||
SCRAPY_COMPOSE_PROJECT_NAME: scrapy
|
SCRAPY_COMPOSE_PROJECT_NAME: scrapy
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ include:
|
|||||||
- awsm/compose.yaml
|
- awsm/compose.yaml
|
||||||
- sexy/compose.yaml
|
- sexy/compose.yaml
|
||||||
- mattermost/compose.yaml
|
- mattermost/compose.yaml
|
||||||
|
- tandoor/compose.yaml
|
||||||
- scrapy/compose.yaml
|
- scrapy/compose.yaml
|
||||||
- n8n/compose.yaml
|
- n8n/compose.yaml
|
||||||
- stash/compose.yaml
|
- stash/compose.yaml
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-E
|
|||||||
SELECT 'CREATE DATABASE mattermost'
|
SELECT 'CREATE DATABASE mattermost'
|
||||||
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mattermost')\gexec
|
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mattermost')\gexec
|
||||||
|
|
||||||
|
-- Tandoor recipe manager database
|
||||||
|
SELECT 'CREATE DATABASE tandoor'
|
||||||
|
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'tandoor')\gexec
|
||||||
|
|
||||||
-- Grant privileges to all databases
|
-- Grant privileges to all databases
|
||||||
GRANT ALL PRIVILEGES ON DATABASE directus TO $POSTGRES_USER;
|
GRANT ALL PRIVILEGES ON DATABASE directus TO $POSTGRES_USER;
|
||||||
GRANT ALL PRIVILEGES ON DATABASE umami TO $POSTGRES_USER;
|
GRANT ALL PRIVILEGES ON DATABASE umami TO $POSTGRES_USER;
|
||||||
@@ -40,11 +44,12 @@ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-E
|
|||||||
GRANT ALL PRIVILEGES ON DATABASE linkwarden TO $POSTGRES_USER;
|
GRANT ALL PRIVILEGES ON DATABASE linkwarden TO $POSTGRES_USER;
|
||||||
GRANT ALL PRIVILEGES ON DATABASE joplin TO $POSTGRES_USER;
|
GRANT ALL PRIVILEGES ON DATABASE joplin TO $POSTGRES_USER;
|
||||||
GRANT ALL PRIVILEGES ON DATABASE mattermost TO $POSTGRES_USER;
|
GRANT ALL PRIVILEGES ON DATABASE mattermost TO $POSTGRES_USER;
|
||||||
|
GRANT ALL PRIVILEGES ON DATABASE tandoor TO $POSTGRES_USER;
|
||||||
|
|
||||||
-- Log success
|
-- Log success
|
||||||
SELECT 'Compose databases initialized:' AS status;
|
SELECT 'Compose databases initialized:' AS status;
|
||||||
SELECT datname FROM pg_database
|
SELECT datname FROM pg_database
|
||||||
WHERE datname IN ('directus', 'umami', 'n8n', 'linkwarden', 'joplin', 'mattermost')
|
WHERE datname IN ('directus', 'umami', 'n8n', 'linkwarden', 'joplin', 'mattermost', 'tandoor')
|
||||||
ORDER BY datname;
|
ORDER BY datname;
|
||||||
EOSQL
|
EOSQL
|
||||||
|
|
||||||
@@ -59,4 +64,5 @@ echo " • n8n - Workflow automation database"
|
|||||||
echo " • linkwarden - Bookmark manager database"
|
echo " • linkwarden - Bookmark manager database"
|
||||||
echo " • joplin - Note-taking server database"
|
echo " • joplin - Note-taking server database"
|
||||||
echo " • mattermost - Chat platform database"
|
echo " • mattermost - Chat platform database"
|
||||||
|
echo " • tandoor - Recipe manager database"
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ services:
|
|||||||
- backup_mattermost_config:/volumes/mattermost_config:ro
|
- backup_mattermost_config:/volumes/mattermost_config:ro
|
||||||
- backup_mattermost_data:/volumes/mattermost_data:ro
|
- backup_mattermost_data:/volumes/mattermost_data:ro
|
||||||
- backup_mattermost_plugins:/volumes/mattermost_plugins:ro
|
- backup_mattermost_plugins:/volumes/mattermost_plugins:ro
|
||||||
|
- backup_tandoor_staticfiles:/volumes/tandoor_staticfiles:ro
|
||||||
|
- backup_tandoor_mediafiles:/volumes/tandoor_mediafiles:ro
|
||||||
- backup_scrapyd_data:/volumes/scrapyd_data:ro
|
- backup_scrapyd_data:/volumes/scrapyd_data:ro
|
||||||
- backup_scrapy_code:/volumes/scrapy_code:ro
|
- backup_scrapy_code:/volumes/scrapy_code:ro
|
||||||
- backup_n8n_data:/volumes/n8n_data:ro
|
- backup_n8n_data:/volumes/n8n_data:ro
|
||||||
@@ -95,6 +97,12 @@ volumes:
|
|||||||
backup_mattermost_plugins:
|
backup_mattermost_plugins:
|
||||||
name: mattermost_plugins
|
name: mattermost_plugins
|
||||||
external: true
|
external: true
|
||||||
|
backup_tandoor_staticfiles:
|
||||||
|
name: tandoor_staticfiles
|
||||||
|
external: true
|
||||||
|
backup_tandoor_mediafiles:
|
||||||
|
name: tandoor_mediafiles
|
||||||
|
external: true
|
||||||
backup_scrapyd_data:
|
backup_scrapyd_data:
|
||||||
name: scrapy_scrapyd_data
|
name: scrapy_scrapyd_data
|
||||||
external: true
|
external: true
|
||||||
|
|||||||
78
tandoor/compose.yaml
Normal file
78
tandoor/compose.yaml
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
services:
|
||||||
|
tandoor:
|
||||||
|
image: ${TANDOOR_IMAGE:-vabene1111/recipes:latest}
|
||||||
|
container_name: ${TANDOOR_COMPOSE_PROJECT_NAME}_app
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
# Django settings
|
||||||
|
SECRET_KEY: ${TANDOOR_SECRET_KEY}
|
||||||
|
ALLOWED_HOSTS: ${TANDOOR_TRAEFIK_HOST}
|
||||||
|
TIMEZONE: ${TIMEZONE:-Europe/Berlin}
|
||||||
|
|
||||||
|
# Database configuration
|
||||||
|
DB_ENGINE: django.db.backends.postgresql
|
||||||
|
POSTGRES_HOST: ${CORE_DB_HOST}
|
||||||
|
POSTGRES_PORT: ${CORE_DB_PORT}
|
||||||
|
POSTGRES_USER: ${DB_USER}
|
||||||
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||||
|
POSTGRES_DB: ${TANDOOR_DB_NAME}
|
||||||
|
|
||||||
|
# Application settings
|
||||||
|
ENABLE_SIGNUP: ${TANDOOR_ENABLE_SIGNUP:-0}
|
||||||
|
REVERSE_PROXY_AUTH: ${TANDOOR_REVERSE_PROXY_AUTH:-0}
|
||||||
|
|
||||||
|
# Email configuration (IONOS SMTP)
|
||||||
|
EMAIL_HOST: ${EMAIL_SMTP_HOST}
|
||||||
|
EMAIL_PORT: ${EMAIL_SMTP_PORT}
|
||||||
|
EMAIL_HOST_USER: ${EMAIL_SMTP_USER}
|
||||||
|
EMAIL_HOST_PASSWORD: ${EMAIL_SMTP_PASSWORD}
|
||||||
|
EMAIL_USE_TLS: ${TANDOOR_EMAIL_USE_TLS:-0}
|
||||||
|
EMAIL_USE_SSL: ${TANDOOR_EMAIL_USE_SSL:-1}
|
||||||
|
DEFAULT_FROM_EMAIL: ${EMAIL_FROM}
|
||||||
|
|
||||||
|
# Gunicorn settings
|
||||||
|
GUNICORN_MEDIA: ${TANDOOR_GUNICORN_MEDIA:-0}
|
||||||
|
|
||||||
|
# Optional features
|
||||||
|
COMMENT_PREF_DEFAULT: ${TANDOOR_COMMENT_PREF_DEFAULT:-1}
|
||||||
|
SHOPPING_MIN_AUTOSYNC_INTERVAL: ${TANDOOR_SHOPPING_MIN_AUTOSYNC_INTERVAL:-5}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- tandoor_staticfiles:/opt/recipes/staticfiles
|
||||||
|
- tandoor_mediafiles:/opt/recipes/mediafiles
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- postgres
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- compose_network
|
||||||
|
|
||||||
|
labels:
|
||||||
|
- 'traefik.enable=${TANDOOR_TRAEFIK_ENABLED}'
|
||||||
|
# HTTP to HTTPS redirect
|
||||||
|
- 'traefik.http.middlewares.${TANDOOR_COMPOSE_PROJECT_NAME}-redirect-web-secure.redirectscheme.scheme=https'
|
||||||
|
- 'traefik.http.routers.${TANDOOR_COMPOSE_PROJECT_NAME}-web.middlewares=${TANDOOR_COMPOSE_PROJECT_NAME}-redirect-web-secure'
|
||||||
|
- 'traefik.http.routers.${TANDOOR_COMPOSE_PROJECT_NAME}-web.rule=Host(`${TANDOOR_TRAEFIK_HOST}`)'
|
||||||
|
- 'traefik.http.routers.${TANDOOR_COMPOSE_PROJECT_NAME}-web.entrypoints=web'
|
||||||
|
# HTTPS router
|
||||||
|
- 'traefik.http.routers.${TANDOOR_COMPOSE_PROJECT_NAME}-web-secure.rule=Host(`${TANDOOR_TRAEFIK_HOST}`)'
|
||||||
|
- 'traefik.http.routers.${TANDOOR_COMPOSE_PROJECT_NAME}-web-secure.tls.certresolver=resolver'
|
||||||
|
- 'traefik.http.routers.${TANDOOR_COMPOSE_PROJECT_NAME}-web-secure.entrypoints=web-secure'
|
||||||
|
- 'traefik.http.middlewares.${TANDOOR_COMPOSE_PROJECT_NAME}-web-secure-compress.compress=true'
|
||||||
|
- 'traefik.http.routers.${TANDOOR_COMPOSE_PROJECT_NAME}-web-secure.middlewares=${TANDOOR_COMPOSE_PROJECT_NAME}-web-secure-compress,security-headers@file'
|
||||||
|
# Service
|
||||||
|
- 'traefik.http.services.${TANDOOR_COMPOSE_PROJECT_NAME}-web-secure.loadbalancer.server.port=8080'
|
||||||
|
- 'traefik.docker.network=${NETWORK_NAME}'
|
||||||
|
# Watchtower
|
||||||
|
- 'com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}'
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
tandoor_staticfiles:
|
||||||
|
name: ${TANDOOR_COMPOSE_PROJECT_NAME}_staticfiles
|
||||||
|
tandoor_mediafiles:
|
||||||
|
name: ${TANDOOR_COMPOSE_PROJECT_NAME}_mediafiles
|
||||||
|
|
||||||
|
networks:
|
||||||
|
compose_network:
|
||||||
|
name: ${NETWORK_NAME}
|
||||||
|
external: true
|
||||||
Reference in New Issue
Block a user