Guidance for AI Agents working with this repository.
A sophisticated collection of infrastructure templates (boilerplates) with a Python CLI for management. Supports Terraform, Docker, Ansible, Kubernetes, etc. Built with Typer (CLI) and Jinja2 (templating).
cli/ - Python CLI application source code
cli/core/ - Core functionality (app, config, commands, logging)cli/modules/ - Technology-specific modules (terraform, docker, compose, config, etc.)library/ - Template collections organized by module
library/ansible/ - Ansible playbooks and configurationslibrary/compose/ - Docker Compose configurationslibrary/docker/ - Docker templateslibrary/kubernetes/ - Kubernetes deploymentslibrary/packer/ - Packer templateslibrary/terraform/ - OpenTofu/Terraform templates and examples# List available commands
python3 -m cli
# List templates for a module
python3 -m cli compose list
# Debugging commands
python3 -m cli --log-level DEBUG compose list
# Generate template to directory named after template (default)
python3 -m cli compose generate nginx
# Generate template to custom directory
python3 -m cli compose generate nginx my-nginx-server
# Generate template interactively (default - prompts for variables)
python3 -m cli compose generate authentik
# Generate template non-interactively (skips prompts, uses defaults and CLI variables)
python3 -m cli compose generate authentik my-auth --no-interactive
# Generate with variable overrides (non-interactive)
python3 -m cli compose generate authentik my-auth \
--var service_name=auth \
--var ports_enabled=false \
--var database_type=postgres \
--no-interactive
# Show template details
python3 -m cli compose show authentik
# Managing default values
python3 -m cli compose defaults set service_name my-app
python3 -m cli compose defaults get
python3 -m cli compose defaults list
Process: Tag-based workflow via .github/workflows/release.yaml. Push a semver tag (e.g., v1.2.3) to trigger.
Workflow Steps:
pyproject.toml and cli/__main__.py with versionImportant: Never manually edit version numbers - they're placeholders (0.0.0) that get auto-updated.
User Installation:
# Latest
curl -fsSL https://raw.githubusercontent.com/christianlempa/boilerplates/main/scripts/install.sh | bash
# Specific version
curl -fsSL https://raw.githubusercontent.com/christianlempa/boilerplates/main/scripts/install.sh | bash -s -- --version v1.2.3
The install.sh script downloads the release tarball and installs via pipx. PyPI publishing is currently disabled.
Modular architecture with dynamic module discovery:
cli/__main__.py: Entry point. Auto-discovers modules and registers commands.cli/core/registry.py: Central module class store.cli/core/module.py: Abstract Module base class for standardized commands (list, search, show, generate).cli/core/library.py: LibraryManager finds templates in library/ with priority system.cli/core/template.py: Parses templates, merges YAML frontmatter with Jinja2 content.cli/core/variables.py: Variable data structures (Variable, VariableSection, VariableCollection).cli/core/prompt.py: Interactive CLI prompts via rich library.cli/core/display.py: Consistent output rendering.Templates are directory-based. Each template is a directory containing all the necessary files and subdirectories for the boilerplate.
Requires template.yaml or template.yml with metadata and variables in YAML frontmatter:
---
kind: compose
metadata:
name: My Nginx Template
description: >
A template for a simple Nginx service.
Project: https://...
Source: https://
Documentation: https://
version: 0.1.0
author: Christian Lempa
date: '2024-10-01'
spec:
general:
vars:
nginx_version:
type: string
description: The Nginx version to use.
default: latest
.j2): Rendered by Jinja2, .j2 extension removed in output. Support {% include %} and {% import %}..j2 files copied as-is.library/compose/my-nginx-template/
├── template.yaml
├── compose.yaml.j2
├── config/
│ └── nginx.conf.j2
└── static/
└── README.md
Precedence (lowest to highest):
spec (defaults for all templates of that kind)spec (overrides module defaults)--var (highest priority)Key Features:
required: true (general is implicit). Users must provide all values.toggle: "bool_var_name". If false, section is skipped.needs: "section_name" or needs: ["sec1", "sec2"]. Dependent sections only shown when dependencies are enabled. Auto-validated (detects circular/missing/self dependencies). Topologically sorted.Example Section with Dependencies:
spec:
traefik:
title: "Traefik"
toggle: "traefik_enabled"
vars:
traefik_enabled:
type: "bool"
default: false
traefik_host:
type: "hostname"
traefik_tls:
title: "Traefik TLS/SSL"
needs: "traefik" # Only shown if traefik is enabled
toggle: "traefik_tls_enabled"
vars:
traefik_tls_enabled:
type: "bool"
default: true
traefik_tls_certresolver:
type: "str"
template.yaml/template.yml with descriptive IDs (lowercase-with-hyphens)config/)config module for app-specific configs vs complex directoriestypedefault values in template.yaml for all non-required variables (improves non-interactive generation)sensitive: true (hides input), autogenerated: true (auto-generates secure values when empty)Naming Conventions:
service_name, container_name, container_timezone, restart_policyauthentik_secret_key)database_* (type, enabled, external, host, port, name, user, password)network_* (enabled, name, external)traefik_* (enabled, host, tls_enabled, tls_entrypoint, tls_certresolver)ports_* (enabled, http, https, ssh)email_* (enabled, host, port, username, password, from)Patterns:
.env.{service}.j2 files for better security/organizationdepends_on, named volumes, health checks (DB), restart: {{ restart_policy | default('unless-stopped') }}{% if not database_external %} for service creationdatabase_enabled, email_enabled, traefik_enabled, ports_enabled, network_enabled