Drupal Recipe Development Guide
Drupal Recipe Development Guide
Separation of Duties: See Separation of Duties - Drupal recipes are responsible for Drupal site configuration. They do NOT own agent manifests, execution, or OSSA spec.
Complete guide for developing and managing Drupal recipes for the LLM Platform.
Table of Contents
Overview
Drupal recipes provide a standardized way to install and configure Drupal sites with predefined sets of modules, configuration, and content. The LLM Platform uses recipes to deploy consistent AI-powered environments.
Key Concepts
- Recipe: A YAML-based blueprint for site setup
- Sub-Recipe: Modular recipe components that can be composed
- Recipe Onboarding: Module for managing recipe deployment
- Validation: Automated checks for recipe integrity
Recipe Structure
Basic Recipe
recipe_name/
recipe.yml # Main recipe definition
README.md # Documentation
config/ # Configuration files
install/ # Config to import on install
update/ # Config updates
content/ # Default content
node/
modules/ # Custom modules for this recipe
subrecipes/ # Modular sub-recipes
core/
api/
security/
tests/ # Recipe tests
RecipeTest.php
Recipe Definition (recipe.yml)
name: 'Recipe Name' description: 'Clear description of what this recipe provides' type: 'Site' version: '1.0.0' # Module dependencies install: - drupal:system - drupal:user - drupal:node - ai:ai - ai_agents:ai_agents - mcp_registry:mcp_registry - recipe_onboarding:recipe_onboarding # Configuration to apply config: import: # Core system config system.site: name: 'LLM Platform' mail: 'admin@example.com' slogan: 'AI-Powered Enterprise Platform' # Module-specific config ai.settings: default_provider: 'openai' cache_enabled: true actions: # Set module config ai.provider.openai.settings: model: 'gpt-4' temperature: 0.7 # Content to create content: node: - type: page title: 'Welcome' body: value: '<p>Welcome to the LLM Platform</p>' format: 'full_html' # Roles and permissions roles: ai_user: label: 'AI User' permissions: - 'access ai interface' - 'execute ai workflows' # Sub-recipes to apply recipes: - './subrecipes/core' - './subrecipes/security' - './subrecipes/api'
Development Workflow
1. Recipe Location
Source Location (edit here):
$LLM_ROOT/all_drupal_custom/recipes/recipe_name/
Deployment Location:
$LLM_ROOT/llm-platform/recipes/recipe_name/
2. Create New Recipe
# Manual creation mkdir -p $LLM_ROOT/all_drupal_custom/recipes/my_recipe cd $LLM_ROOT/all_drupal_custom/recipes/my_recipe # Create recipe.yml cat > recipe.yml << 'EOF' name: 'My Recipe' description: 'Recipe description' type: 'Site' version: '1.0.0' install: [] EOF # Create README cat > README.md << 'EOF' # My Recipe Description of recipe functionality. EOF
3. Apply Recipe
# Apply recipe to site drush recipe recipes/my_recipe # Apply with specific options drush recipe recipes/my_recipe --no-cache --verbose
4. Validation
# Validate recipe structure drush recipe:validate recipes/my_recipe # Via recipe_onboarding module drush recipe-onboarding:validate recipes/my_recipe
Sub-Recipes
Sub-recipes provide modular components that can be composed into larger recipes.
Sub-Recipe Structure
subrecipes/
core/
recipe.yml
config/
security/
recipe.yml
config/
api/
recipe.yml
config/
Core Sub-Recipe Example
# subrecipes/core/recipe.yml name: 'LLM Core Foundation' description: 'Core LLM platform modules and configuration' type: 'Configuration' version: '1.0.0' install: - drupal:system - drupal:user - drupal:node - drupal:field - drupal:serialization - drupal:rest - drupal:jsonapi config: import: system.performance: cache: page: max_age: 3600 css: preprocess: true js: preprocess: true
Security Sub-Recipe Example
# subrecipes/security/recipe.yml name: 'LLM Security Framework' description: 'Security hardening and compliance' type: 'Configuration' version: '1.0.0' install: - security_review:security_review - seckit:seckit - password_policy:password_policy - autologout:autologout - tfa:tfa config: import: seckit.settings: seckit_xss: csp: checkbox: true policy: "default-src 'self'" seckit_csrf: origin: true password_policy.policy.admin: label: 'Admin Password Policy' password_length: 12 character_types: 3
API Management Sub-Recipe
# subrecipes/api/recipe.yml name: 'API Management' description: 'REST, GraphQL, and API tooling' type: 'Configuration' version: '1.0.0' install: - drupal:rest - drupal:jsonapi - drupal:serialization - graphql:graphql - graphql_compose:graphql_compose - openapi_ui:openapi_ui - openapi_ui_redoc:openapi_ui_redoc - simple_oauth:simple_oauth - api_normalization:api_normalization config: import: rest.settings: bc_entity_resource_permissions: false link_domain: ~
Validation
Recipe Onboarding Module
The recipe_onboarding module provides comprehensive validation:
# Install recipe_onboarding drush en recipe_onboarding -y # Validate recipe drush recipe-onboarding:validate recipes/my_recipe # List available recipes drush recipe-onboarding:list # Get recipe info drush recipe-onboarding:info recipes/my_recipe
Validation Checks
- Syntax: YAML is valid
- Structure: Required fields present
- Dependencies: Modules exist and are available
- Config: Configuration schemas are valid
- Content: Content types and fields exist
- Sub-Recipes: Referenced sub-recipes exist
Manual Validation
# Check YAML syntax php -r "yaml_parse_file('recipe.yml');" # Verify modules exist drush pm:list --type=module | grep module_name # Test config import drush config:import --partial --source=recipes/my_recipe/config/install
Deployment
1. Recipe Testing
# Test on fresh install lando rebuild -y drush si minimal -y drush recipe recipes/my_recipe drush uli # Verify installation drush pm:list --type=module --status=enabled drush config:status
2. Production Deployment
# Export recipe to production rsync -av recipes/my_recipe/ production:/var/www/html/recipes/my_recipe/ # Apply on production ssh production "cd /var/www/html && drush recipe recipes/my_recipe"
3. CI/CD Integration
# .gitlab-ci.yml test-recipe: stage: test script: - composer install - drush si minimal -y - drush recipe recipes/my_recipe - drush status
Examples
LLM Platform Recipe
The main platform recipe with sub-recipes:
# recipes/llm_platform/recipe.yml name: 'LLM Platform' description: 'Complete LLM Platform installation with AI agents, workflows, and APIs' type: 'Site' version: '1.0.0' # Sub-recipes provide modular components recipes: - './subrecipes/llm_core_foundation' - './subrecipes/llm_security_framework' - './subrecipes/llm_model_integration' - './subrecipes/api_management' - './subrecipes/ecosystem_orchestration' - './subrecipes/llm_user_workflows' - './subrecipes/llm_langflow_integration' # Main recipe modules install: - ai_agentic_workflows:ai_agentic_workflows - ai_agents_orchestra:ai_agents_orchestra - mcp_registry:mcp_registry - code_executor:code_executor - gov_compliance:gov_compliance config: import: system.site: name: 'LLM Platform' mail: 'admin@llm.local' slogan: 'Enterprise AI Platform' roles: llm_admin: label: 'LLM Administrator' permissions: - 'administer llm platform' - 'manage ai agents' - 'configure mcp registry'
Secure Drupal Recipe
Security-focused recipe:
# recipes/secure_drupal/recipe.yml name: 'Secure Drupal' description: 'Hardened Drupal with security best practices' type: 'Site' version: '1.0.0' install: - security_review:security_review - seckit:seckit - password_policy:password_policy - tfa:tfa - autologout:autologout - login_security:login_security - paranoia:paranoia config: import: seckit.settings: seckit_xss: csp: checkbox: true seckit_various: from_origin: true referrer_policy: true password_policy.policy.default: label: 'Default Password Policy' password_length: 14 character_types: 4 autologout.settings: timeout: 900 max_timeout: 1800
Recipe Management Commands
Drush Commands
# List all recipes drush recipe:list # Apply recipe drush recipe recipes/my_recipe # Validate recipe drush recipe:validate recipes/my_recipe # Export current config as recipe drush recipe:export --name=my_recipe --destination=recipes/ # Show recipe info drush recipe:info recipes/my_recipe # Rollback recipe (if supported) drush recipe:rollback recipes/my_recipe
Recipe Onboarding Commands
# Enable recipe onboarding drush en recipe_onboarding -y # List recipes drush recipe-onboarding:list # Deploy recipe with sub-recipe support drush recipe-onboarding:deploy recipes/llm_platform # Validate complex recipe drush recipe-onboarding:validate recipes/llm_platform --strict # Show recipe tree drush recipe-onboarding:tree recipes/llm_platform
Best Practices
1. Modular Design
Use sub-recipes for reusable components:
recipes/
llm_platform/ # Main platform recipe
recipe.yml
subrecipes/
core/ # Core functionality
security/ # Security hardening
api/ # API management
ai/ # AI integration
secure_drupal/ # Security-focused recipe
recipe.yml
2. Version Control
Track recipe changes in git:
cd recipes/my_recipe git add recipe.yml config/ README.md git commit -m "feat: add AI provider configuration"
3. Documentation
Include comprehensive README:
# Recipe Name ## Purpose What this recipe provides ## Requirements - Drupal ^10.3 || ^11 - PHP 8.1+ - Required modules ## Installation drush recipe recipes/my_recipe ## Configuration Post-installation steps ## Troubleshooting Common issues and solutions
4. Testing
Test recipes thoroughly:
# Test on fresh install lando rebuild -y drush si minimal -y drush recipe recipes/my_recipe # Verify functionality drush pm:list --status=enabled drush config:status drush watchdog:show
Troubleshooting
Common Issues
Missing Dependencies
# Error: Module 'example' not found # Fix: Add to composer.json and install composer require drupal/example
Config Import Errors
# Error: Unknown configuration schema # Fix: Clear cache and retry drush cr drush recipe recipes/my_recipe
Sub-Recipe Not Found
# Error: Sub-recipe './subrecipes/core' does not exist # Fix: Verify path is relative to recipe.yml recipes: - './subrecipes/core' # Relative path
Resources
See Also
- Module Development
- AI Agents OSSA Module - OSSA compliance and validation
- Drupal Standards