Examples¶
Learn Mooncake through practical, hands-on examples. This page contains all examples from beginner to advanced, organized as a step-by-step learning path.
Running Examples¶
All examples are in the examples/ directory of the repository:
# Clone the repo
git clone https://github.com/alehatsman/mooncake.git
cd mooncake
# Run an example
mooncake run --config examples/01-hello-world/config.yml
Beginner Examples¶
01 - Hello World¶
Start here! This is the simplest possible Mooncake configuration.
What You'll Learn¶
- Running basic shell commands
- Using global system variables
- Multi-line shell commands
Quick Start¶
What It Does¶
- Prints a hello message
- Runs system commands to show OS info
- Uses Mooncake's global variables to display OS and architecture
Key Concepts¶
Shell Commands
Execute commands with the shell action:
Multi-line Commands
Use | for multiple commands:
Global Variables
Mooncake automatically provides system information:
- {{os}} - Operating system (linux, darwin, windows)
- {{arch}} - Architecture (amd64, arm64, etc.)
Output Example¶
▶ Print hello message
Hello from Mooncake!
✓ Print hello message
▶ Print system info
OS: Darwin
Arch: arm64
✓ Print system info
▶ Show global variables
Running on darwin/arm64
✓ Show global variables
02 - Variables and System Facts¶
Learn how to define custom variables and use Mooncake's comprehensive system facts.
What You'll Learn¶
- Defining custom variables with
vars - Using all available system facts
- Combining custom variables with system facts
- Using variables in file operations
Quick Start¶
What It Does¶
- Defines custom application variables
- Displays all system facts (OS, hardware, network, software)
- Creates files using both custom variables and system facts
Key Concepts¶
Custom Variables
Define your own variables:
Use them in commands and paths:
System Facts
Mooncake automatically collects system information:
| Category | Variable | Description |
|---|---|---|
| Basic | os, arch, hostname, user_home |
System basics |
| Hardware | cpu_cores, memory_total_mb |
Hardware info |
| Distribution | distribution, distribution_version, distribution_major |
OS distribution |
| Software | package_manager, python_version |
Installed software |
| Network | ip_addresses, ip_addresses_string |
Network info |
Variable Substitution
Variables work everywhere:
Seeing All Facts
Run mooncake explain to see all facts for your system:
03 - Files and Directories¶
Learn how to create and manage files and directories with Mooncake.
What You'll Learn¶
- Creating directories with
state: directory - Creating files with
state: file - Setting file permissions with
mode - Adding content to files
Quick Start¶
What It Does¶
- Creates application directory structure
- Creates files with specific content
- Sets appropriate permissions (755 for directories, 644 for files)
- Creates executable scripts
Key Concepts¶
Creating Directories
Creating Empty Files
Creating Files with Content
- name: Create config file
file:
path: /tmp/config.txt
state: file
content: |
Line 1
Line 2
mode: "0644"
File Permissions
| Mode | Meaning | Use Case |
|---|---|---|
| 0755 | rwxr-xr-x | Directories, executable scripts |
| 0644 | rw-r--r-- | Regular files, configs |
| 0600 | rw------- | Private files, secrets |
| 0700 | rwx------ | Private directories |
04 - Conditionals¶
Learn how to conditionally execute steps based on system properties or variables.
What You'll Learn¶
- Using
whenfor conditional execution - OS and architecture detection
- Complex conditions with logical operators
- Combining conditionals with tags
Quick Start¶
cd examples/04-conditionals
# Run all steps (only matching conditions will execute)
mooncake run --config config.yml
# Run only dev-tagged steps
mooncake run --config config.yml --tags dev
What It Does¶
- Demonstrates steps that always run
- Shows OS-specific steps (macOS vs Linux)
- Shows architecture-specific steps
- Demonstrates tag filtering
Key Concepts¶
Basic Conditionals
Use when to conditionally execute steps:
Available System Variables
os- darwin, linux, windowsarch- amd64, arm64, 386, etc.distribution- ubuntu, debian, centos, macos, etc.distribution_major- major version numberpackage_manager- apt, yum, brew, pacman, etc.
Comparison Operators
==- equals!=- not equals>,<,>=,<=- comparisons&&- logical AND||- logical OR!- logical NOT
Complex Conditions
- name: ARM Mac only
shell: echo "ARM-based macOS"
when: os == "darwin" && arch == "arm64"
- name: High memory systems
shell: echo "Lots of RAM!"
when: memory_total_mb >= 16000
- name: Ubuntu 20+
shell: apt update
when: distribution == "ubuntu" && distribution_major >= "20"
Tags vs Conditionals
- Conditionals (
when): Evaluated at runtime based on system facts - Tags: User-controlled filtering via CLI
--tagsflag
Intermediate Examples¶
05 - Templates¶
Learn how to render configuration files from templates using pongo2 syntax.
What You'll Learn¶
- Rendering
.j2template files - Using variables in templates
- Template conditionals (
{% if %}) - Template loops (
{% for %}) - Passing additional vars to templates
Quick Start¶
cd examples/05-templates
mooncake run --config config.yml
# Check the rendered files
ls -lh /tmp/mooncake-templates/
cat /tmp/mooncake-templates/config.yml
What It Does¶
- Defines variables for application, server, and database config
- Renders application config with loops and conditionals
- Renders nginx config with optional SSL
- Creates executable script from template
- Renders same template with different variables
Key Concepts¶
Template Action
Template Syntax (pongo2)
Variables:
Conditionals:
Loops:
Filters:
Passing Additional Vars
Override variables for specific templates:
- template:
src: ./templates/config.yml.j2
dest: /tmp/prod-config.yml
vars:
environment: production
debug: false
Common Use Cases
- Config files (app.yml, nginx.conf, etc.)
- Shell scripts (deployment, setup)
- Systemd units (service files)
- Dotfiles (.bashrc, .vimrc with customization)
06 - Loops¶
Learn how to iterate over lists and files to avoid repetition.
What You'll Learn¶
- Iterating over lists with
with_items - Iterating over files with
with_filetree - Using the
{{ item }}variable - Accessing file properties in loops
Quick Start¶
cd examples/06-loops
# Run list iteration example
mooncake run --config with-items.yml
# Run file tree iteration example
mooncake run --config with-filetree/config.yml
Examples Included¶
1. with-items.yml - List Iteration
Iterate over lists of items:
- vars:
packages:
- neovim
- ripgrep
- fzf
- name: Install package
shell: brew install {{ item }}
with_items: "{{ packages }}"
2. with-filetree/ - File Tree Iteration
Iterate over files in a directory:
- name: Copy dotfile
shell: cp "{{ item.src }}" "/tmp/backup/{{ item.name }}"
with_filetree: ./files
Key Concepts¶
List Iteration (with_items)
- vars:
users: [alice, bob, charlie]
- name: Create user directory
file:
path: "/home/{{ item }}"
state: directory
with_items: "{{ users }}"
This creates /home/alice, /home/bob, /home/charlie
File Tree Iteration (with_filetree)
- name: Process file
shell: echo "Processing {{ item.name }}"
with_filetree: ./dotfiles
when: item.is_dir == false
Available properties:
item.src- Full source pathitem.name- File nameitem.is_dir- Boolean, true if directory
Filtering in Loops
Skip directories:
- name: Copy files only
shell: cp "{{ item.src }}" "/tmp/{{ item.name }}"
with_filetree: ./files
when: item.is_dir == false
Real-World Use Cases
with_items:
- Installing multiple packages
- Creating multiple users/groups
- Setting up multiple services
with_filetree:
- Managing dotfiles
- Deploying configuration directories
- Backing up files
07 - Register¶
Learn how to capture command output and use it in subsequent steps.
What You'll Learn¶
- Capturing output with
register - Accessing stdout, stderr, and return codes
- Using captured data in conditionals
- Detecting if operations made changes
Quick Start¶
What It Does¶
- Checks if git is installed and captures the result
- Uses return code to conditionally show messages
- Captures username and uses it in file paths
- Captures OS version and displays it
- Detects if file operations made changes
Key Concepts¶
Basic Registration
- name: Check if git exists
shell: which git
register: git_check
- name: Use the result
shell: echo "Git is at {{ git_check.stdout }}"
when: git_check.rc == 0
Available Fields
For shell commands:
register_name.stdout- Standard outputregister_name.stderr- Standard errorregister_name.rc- Return/exit code (0 = success)register_name.failed- Boolean, true if rc != 0register_name.changed- Boolean, always true for shell
For file operations:
register_name.rc- 0 for success, 1 for failureregister_name.failed- Booleanregister_name.changed- Boolean, true if file created/modified
Using in Conditionals
- shell: test -f /tmp/file.txt
register: file_check
- shell: echo "File exists"
when: file_check.rc == 0
- shell: echo "File not found"
when: file_check.rc != 0
Using in Templates
- shell: whoami
register: current_user
- file:
path: "/tmp/{{ current_user.stdout }}_config.txt"
state: file
content: "User: {{ current_user.stdout }}"
Change Detection
- file:
path: /tmp/test.txt
state: file
content: "test"
register: result
- shell: echo "File was created or modified"
when: result.changed == true
Common Patterns
Checking for command existence:
- shell: which docker
register: docker_check
- shell: echo "Docker not installed"
when: docker_check.rc != 0
Conditional installation:
- shell: python3 --version
register: python_check
- shell: apt install python3
become: true
when: python_check.rc != 0
Advanced Examples¶
08 - Tags¶
Learn how to use tags to selectively run parts of your configuration.
What You'll Learn¶
- Adding tags to steps
- Filtering execution with
--tagsflag - Organizing workflows with tags
- Combining tags with conditionals
Quick Start¶
cd examples/08-tags
# Run all steps (no tag filter)
mooncake run --config config.yml
# Run only development steps
mooncake run --config config.yml --tags dev
# Run only production steps
mooncake run --config config.yml --tags prod
# Run multiple tag categories
mooncake run --config config.yml --tags dev,test
What It Does¶
Demonstrates different tagged workflows:
- Development setup
- Production deployment
- Testing
- Security audits
- Staging deployment
Key Concepts¶
Adding Tags
Tag Filtering Behavior
- No tags specified: All steps run (including untagged steps)
- Tags specified (
--tags dev): Only steps with matching tags run - Multiple tags (
--tags dev,prod): Steps run if they have ANY of the specified tags (OR logic)
Tag Organization Strategies
By Environment:
By Phase:
By Component:
By Role:
Multiple Tags Per Step
This runs with --tags test, --tags prod, or --tags security
Combining Tags and Conditionals
- name: Install Linux dev tools
shell: apt install build-essential
become: true
when: os == "linux"
tags:
- dev
- tools
Both must match:
1. Condition must be true (os == "linux")
2. Tag must match (if --tags specified)
Best Practices
- Use consistent naming - Pick a scheme and stick to it
- Multiple tags per step - Makes filtering more flexible
- Document your tags - In README or comments
- Combine with conditionals - For environment + OS filtering
09 - Sudo / Privilege Escalation¶
Learn how to execute commands and operations with elevated privileges.
What You'll Learn¶
- Using
become: truefor sudo operations - Providing sudo password via CLI
- System-level operations
- OS-specific privileged operations
Quick Start¶
cd examples/09-sudo
# Requires sudo password
mooncake run --config config.yml --sudo-pass <your-password>
# Preview what would run with sudo
mooncake run --config config.yml --sudo-pass <password> --dry-run
⚠️ Warning: This example contains commands that require root privileges. Review the config before running!
What It Does¶
- Runs regular command (no sudo)
- Runs privileged command with sudo
- Updates package list (Linux)
- Installs system packages
- Creates system directories and files
Key Concepts¶
Basic Sudo
Add become: true to run with sudo:
Providing Password
Three ways to provide sudo password:
-
Command line (recommended):
-
Environment variable:
Which Operations Need Sudo?
Typically require sudo:
- Package management (
apt,yum,dnf) - System file operations (
/etc,/opt,/usr/local) - Service management (
systemctl) - User/group management
- Mounting filesystems
- Network configuration
Don't require sudo:
- User-space operations
- Home directory files
/tmpdirectory- Homebrew on macOS (usually)
File Operations with Sudo
OS-Specific Sudo
# Linux package management
- name: Install package (Linux)
shell: apt install -y curl
become: true
when: os == "linux" and package_manager == "apt"
# macOS typically doesn't need sudo for homebrew
- name: Install package (macOS)
shell: brew install curl
when: os == "darwin"
Security Considerations
- Review before running - Check what commands will execute with sudo
- Use dry-run - Preview with
--dry-runfirst - Minimize sudo usage - Only use on steps that require it
- Specific commands - Don't use
become: trueon untrusted commands - Password handling - Be careful with password in shell history
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
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)
- 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
Including Task Files
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
Organization Strategies
By Environment:
By Platform:
By Component:
By Phase:
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
11 - Shell Execution Control¶
Learn advanced execution control for shell commands with timeouts, retries, environment variables, and custom result evaluation.
Important: These features are shell-specific and don't apply to file, template, or include operations.
What You'll Learn¶
- Setting command timeouts
- Retrying failed commands
- Configuring retry delays
- Setting environment variables
- Changing working directory
- Custom change detection with
changed_when - Custom failure detection with
failed_when - Running as different users with
become_user
Quick Start¶
Key Concepts¶
Timeouts
Prevent commands from running indefinitely:
Retries
Automatically retry failed operations:
Environment Variables
Set custom environment for commands:
Working Directory
Execute commands in specific directories:
Custom Change Detection
Override when a step counts as "changed":
Custom Failure Detection
Override when a step is considered failed:
- name: Grep with acceptable exit codes
shell: grep "pattern" file.txt
failed_when: "result.rc >= 2" # 0=found, 1=not found, 2+=error
Different Users
Run commands as specific users:
Real-World Example¶
Robust service deployment with retries and validation:
- name: Download release
shell: curl -O https://releases.example.com/app-{{version}}.tar.gz
timeout: 10m
retries: 3
retry_delay: 30s
- name: Install application
shell: pip install -r requirements.txt
cwd: /opt/myapp
become: true
become_user: appuser
timeout: 5m
env:
PIP_INDEX_URL: "{{pip_mirror}}"
- name: Run migrations
shell: ./manage.py migrate
cwd: /opt/myapp
become_user: appuser
timeout: 10m
register: migrate_result
changed_when: "'No migrations to apply' not in result.stdout"
- name: Wait for service
shell: curl -sf http://localhost:8080/health
retries: 30
retry_delay: 2s
failed_when: "result.rc != 0"
See complete example for detailed deployment workflow.
Real-World Example¶
Dotfiles Manager¶
A complete example showing how to manage and deploy dotfiles using Mooncake.
Features Demonstrated¶
- Multi-file organization
- Template rendering for dynamic configs
- File tree iteration
- Conditional deployment by OS
- Variable management
- Backup functionality
- Tag-based workflows
Quick Start¶
cd examples/real-world/dotfiles-manager
# Deploy all dotfiles
mooncake run --config setup.yml
# Deploy only shell configs
mooncake run --config setup.yml --tags shell
# Preview what would be deployed
mooncake run --config setup.yml --dry-run
Directory Structure¶
dotfiles-manager/
├── setup.yml # Main entry point
├── vars.yml # User configuration
├── dotfiles/ # Your actual dotfiles
│ ├── shell/
│ │ ├── .bashrc
│ │ └── .zshrc
│ ├── vim/
│ │ └── .vimrc
│ └── git/
│ └── .gitconfig
└── templates/ # Dynamic config templates
├── .tmux.conf.j2
└── .config/
└── nvim/
└── init.lua.j2
What It Does¶
- Backs up existing dotfiles
- Creates necessary directories
- Deploys static dotfiles
- Renders dynamic configs from templates
- Sets appropriate permissions
- OS-specific configuration
Configuration¶
Edit vars.yml to customize:
Usage¶
Full Deployment:
Selective Deployment:
# Only shell configs
mooncake run --config setup.yml --tags shell
# Only vim/neovim
mooncake run --config setup.yml --tags vim
# Only git config
mooncake run --config setup.yml --tags git
Backup Only:
Extending¶
Adding New Dotfiles:
- Add file to
dotfiles/directory - Add deployment step in
setup.yml:
Adding Templates:
- Create template in
templates/ - Add rendering step:
Real-World Tips¶
- Version control - Keep this in git
- Test first - Use
--dry-runbefore applying - Incremental - Add configs gradually
- Backup - The example includes backup steps
- Document - Add comments for custom settings
Summary¶
You've learned all core Mooncake features through these examples:
| Feature | Examples |
|---|---|
| Shell Commands | 01, 04, 06, 08, 11 |
| File Operations | 03, 06, Real-World |
| Templates | 05, Real-World |
| Variables | 02, 05, 06, 10 |
| Conditionals | 04, 08, 09 |
| Loops | 06, Real-World |
| Register | 07, 11 |
| Tags | 08, Real-World |
| Sudo | 09, 11 |
| Multi-file | 10, Real-World |
| Execution Control | 11 |
| Timeouts & Retries | 11 |
| Environment Variables | 11 |
Next Steps¶
- Read the Guide - Comprehensive documentation
- Reference - Detailed config reference
- GitHub - View source code
- Contributing - Help improve Mooncake