10 - Multi-File Configurations¶
Learn how to organize large configurations into multiple files.
What You'll Learn¶
- Splitting configuration into multiple files
- Using
includeto load other configs - Using
include_varsto load variables - Organizing by environment (dev/prod)
- Organizing by platform (Linux/macOS)
- Relative path resolution
Quick Start¶
cd examples/10-multi-file-configs
# Run with development environment (default)
mooncake run --config main.yml
# Run with specific tags
mooncake run --config main.yml --tags install
mooncake run --config main.yml --tags dev
Directory Structure¶
10-multi-file-configs/
├── main.yml # Entry point
├── tasks/ # Modular task files
│ ├── common.yml # Common setup
│ ├── linux.yml # Linux-specific
│ ├── macos.yml # macOS-specific
│ └── dev-tools.yml # Development tools
└── vars/ # Environment variables
├── development.yml # Dev settings
└── production.yml # Prod settings
What It Does¶
- Sets project variables
- Loads environment-specific variables
- Runs common setup tasks
- Runs OS-specific tasks (Linux or macOS)
- Conditionally runs dev tools setup
Key Concepts¶
Entry Point (main.yml)¶
The main file orchestrates everything:
- vars:
project_name: MyProject
env: development
- name: Load environment variables
include_vars: ./vars/{{env}}.yml
- name: Setup common configuration
include: ./tasks/common.yml
- name: Setup OS-specific configuration
include: ./tasks/macos.yml
when: os == "darwin"
Including Variable Files¶
Load variables from external YAML:
vars/development.yml:
Including Task Files¶
Load and execute tasks from other files:
tasks/common.yml:
Relative Path Resolution¶
Paths are relative to the current file, not the working directory:
main.yml:
include: ./tasks/common.yml # Relative to main.yml
tasks/common.yml:
template:
src: ./templates/config.j2 # Relative to common.yml, not main.yml
Organization Strategies¶
By Environment:
By Platform:
By Component:
By Phase:
Real-World Example¶
Project Structure¶
my-project/
├── setup.yml # Main entry
├── environments/
│ ├── dev.yml
│ ├── staging.yml
│ └── prod.yml
├── platforms/
│ ├── linux.yml
│ └── macos.yml
├── components/
│ ├── postgres.yml
│ ├── nginx.yml
│ └── app.yml
└── templates/
├── nginx.conf.j2
└── app-config.yml.j2
Main File¶
# setup.yml
- vars:
environment: "{{ lookup('env', 'ENVIRONMENT') or 'dev' }}"
- include_vars: ./environments/{{ environment }}.yml
- include: ./platforms/{{ os }}.yml
- include: ./components/postgres.yml
- include: ./components/nginx.yml
- include: ./components/app.yml
Switching Environments¶
Method 1: Modify main.yml
Method 2: Use environment variable
Method 3: Different main files
Benefits of Multi-File Organization¶
- Maintainability - Easier to find and update specific parts
- Reusability - Share tasks across projects
- Collaboration - Team members can work on different files
- Testing - Test components independently
- Clarity - Clear separation of concerns
Testing¶
# Run full configuration
mooncake run --config main.yml
# Preview what will run
mooncake run --config main.yml --dry-run
# Run with debug logging to see includes
mooncake run --config main.yml --log-level debug
# Run specific tagged sections
mooncake run --config main.yml --tags install
Best Practices¶
- Clear naming - Use descriptive file names
- Logical grouping - Group related tasks together
- Document includes - Comment what each include does
- Avoid deep nesting - Keep include hierarchy shallow (2-3 levels max)
- Use variables - Make includes reusable with variables
Next Steps¶
Explore the real-world dotfiles example to see a complete practical application!