External Configuration
External Configuration
The external configuration feature allows samstacks to generate standalone SAM configuration files that work independently with the SAM CLI. This enables powerful multi-environment workflows, GitOps practices, and direct team collaboration while maintaining samstacks’ orchestration benefits.
Overview
By default, samstacks uses local samconfig.yaml files in each stack directory. External configurations change this behavior by generating SAM config files at specified paths outside the stack directories.
Key Benefits
- Single Source of Truth: One pipeline definition supports multiple environments
- Standalone Configs: Generated configurations work independently with SAM CLI
- Clean Repositories: No generated files mixed with source code
- GitOps Ready: Commit generated configs for reproducible deployments
- Direct SAM CLI Usage: Skip orchestrator for quick individual stack deployments
- Team Collaboration: Different teams can use SAM CLI directly
Basic Usage
Add a config field to any stack definition to enable external configuration:
pipeline_name: My Application
stacks:
- id: api
dir: stacks/api/
config: configs/production/api/ # External config directory
params:
Environment: productionWhen deployed, samstacks will:
- Generate a complete SAM configuration file at
configs/production/api/samconfig.yaml - Deploy the stack using the external configuration
- Create all necessary directories automatically
Tip
Directory-Based Configs: Using config: configs/production/api/ (ending with /) automatically creates samconfig.yaml in that directory. This prevents conflicts with shared .aws-sam build directories and follows the “one directory, one stack” philosophy.
Multi-Environment Deployment
The most powerful use case is deploying the same pipeline to multiple environments using template expressions:
pipeline_name: Multi-Environment API
pipeline_settings:
inputs:
environment:
type: string
default: dev
stacks:
- id: backend-api
dir: stacks/api/
config: configs/${{ inputs.environment }}/api/
params:
Environment: ${{ inputs.environment }}
LogLevel: ${{ inputs.environment == 'prod' && 'WARN' || 'DEBUG' }}
InstanceType: ${{ inputs.environment == 'prod' && 't3.large' || 't3.micro' }}
- id: database
dir: stacks/database/
config: configs/${{ inputs.environment }}/database/
params:
Environment: ${{ inputs.environment }}
BackupRetentionDays: ${{ inputs.environment == 'prod' && '365' || '7' }}Deploy to Multiple Environments
# Deploy to development
samstacks deploy pipeline.yml --input environment=dev
# Deploy to staging
samstacks deploy pipeline.yml --input environment=staging
# Deploy to production
samstacks deploy pipeline.yml --input environment=prodDelete Environment-Specific Deployments
The delete command supports the same multi-environment functionality:
# Delete development environment
samstacks delete pipeline.yml --input environment=dev
# Delete staging environment (with dry-run preview)
samstacks delete pipeline.yml --input environment=staging --dry-run
# Delete production environment
samstacks delete pipeline.yml --input environment=prodFor external configurations, the delete command will:
- Resolve template expressions in config paths based on input values
- Use the appropriate external config files with
sam delete --config-file - Fall back to local
samconfig.yamlfiles when external configs aren’t found
This creates the following structure:
project/
├── pipeline.yml
├── stacks/
│ ├── api/
│ │ ├── template.yaml
│ │ └── src/
│ └── database/
│ └── template.yaml
└── configs/ # Generated external configs
├── dev/
│ ├── api/
│ │ └── samconfig.yaml # Dev-specific API config
│ └── database/
│ └── samconfig.yaml # Dev-specific DB config
├── staging/
│ ├── api/
│ │ └── samconfig.yaml
│ └── database/
│ └── samconfig.yaml
└── prod/
├── api/
│ └── samconfig.yaml
└── database/
└── samconfig.yamlTemplate Path Resolution
External SAM configurations automatically include proper template file references using relative paths:
Generated Configuration Example
When you define:
- id: api
dir: stacks/api/
config: configs/dev/api/The generated configs/dev/api/samconfig.yaml contains:
version: 0.1
default:
global:
parameters:
beta_features: false
build:
parameters:
template: ../../../stacks/api/template.yaml # Relative path to template
deploy:
parameters:
stack_name: my-app-dev-api
region: us-west-2
capabilities: CAPABILITY_IAM
parameter_overrides:
- Environment=dev
- LogLevel=DEBUG
template: ../../../stacks/api/template.yaml # Relative path to templateThe relative paths (../../../stacks/api/template.yaml) are automatically calculated to point from the config file location to the actual CloudFormation template.
Config Path Formats
samstacks supports two config path formats with built-in validation:
Directory-Based (Recommended)
# Automatically creates samconfig.yaml in the specified directory
config: configs/${{ inputs.environment }}/api/Benefits:
- Isolated Build Artifacts: Each config gets its own
.aws-sam/directory - Clean SAM CLI Usage:
cd configs/dev/api && sam deployworks naturally - No File Conflicts: Multiple stacks can’t interfere with each other
- Follows Best Practices: Maintains “one directory, one stack” philosophy
Explicit File Path
# Use a specific filename
config: configs/${{ inputs.environment }}/api/samconfig.yaml
config: shared/environments/dev-api-config.ymlValidation Rules
samstacks validates config paths to prevent common issues:
- Ends with
/: Directory path → automatically appendssamconfig.yaml - Ends with
.yamlor.yml: File path → used as-is - Anything else: Validation error with helpful message
# ✅ Valid configurations
config: configs/dev/api/ # Directory-based
config: configs/dev/api/samconfig.yaml # Explicit file
config: environments/dev/api-config.yml # Custom filename
# ❌ Invalid configurations
config: configs/dev/api # Missing trailing slash or extension
config: configs/dev/api/config.json # Wrong file extensionDirect SAM CLI Usage
Generated external configurations work seamlessly with the SAM CLI:
Individual Stack Deployment
# Navigate to the config directory and deploy
cd configs/dev/api
sam deploy
# Or specify the config file explicitly
sam deploy --config-file configs/dev/api/samconfig.yaml
# Build and deploy in sequence
cd configs/dev/api
sam build && sam deployIndividual Stack Deletion
# Navigate to the config directory and delete
cd configs/dev/api
sam delete --no-prompts
# Or specify the config file explicitly
sam delete --config-file configs/dev/api/samconfig.yaml --no-promptsTeam Workflows
Different team members can deploy and delete using their preferred tool:
# DevOps team uses samstacks for orchestration
samstacks deploy pipeline.yml --input environment=dev
samstacks delete pipeline.yml --input environment=dev
# Development team uses SAM CLI for quick iterations
cd configs/dev/api && sam deploy
cd configs/dev/api && sam delete --no-prompts
# CI/CD pipeline uses generated configs
sam deploy --config-file configs/prod/api/samconfig.yaml
sam delete --config-file configs/prod/api/samconfig.yaml --no-promptsConfiguration Backup and Safety
External configurations include built-in safety features:
Automatic Backups
When an external config file already exists, samstacks automatically creates a backup:
configs/dev/api/
├── samconfig.yaml # New configuration
└── samconfig.yaml.bak # Previous version backupDirectory Creation
samstacks automatically creates all necessary parent directories:
# This works even if configs/ doesn't exist yet
config: configs/new-env/new-stack/samconfig.yamlAdvanced Use Cases
GitOps Workflows
Commit generated configurations for reproducible deployments:
# Generate configs for all environments
samstacks deploy pipeline.yml --input environment=dev
samstacks deploy pipeline.yml --input environment=staging
samstacks deploy pipeline.yml --input environment=prod
# Commit the generated configs
git add configs/
git commit -m "Update deployment configurations"
git push
# Deploy/delete in CI/CD using committed configs
sam deploy --config-file configs/prod/api/samconfig.yaml
sam delete --config-file configs/prod/api/samconfig.yaml --no-promptsEnvironment Isolation
Keep different environments completely isolated:
stacks:
- id: api
dir: stacks/api/
config: environments/${{ inputs.environment }}/api/
if: ${{ inputs.environment != 'local' }} # Skip for local developmentCross-Stack Dependencies
External configs work perfectly with cross-stack dependencies:
stacks:
- id: vpc
dir: stacks/vpc/
config: configs/${{ inputs.environment }}/vpc/
- id: app
dir: stacks/app/
config: configs/${{ inputs.environment }}/app/
params:
VpcId: ${{ stacks.vpc.outputs.VpcId }} # Reference to previous stackMigration from Local Configs
Converting existing pipelines to use external configs is straightforward:
Before (Local Configs)
stacks:
- id: api
dir: stacks/api/ # Uses stacks/api/samconfig.yaml
params:
Environment: productionAfter (External Configs)
stacks:
- id: api
dir: stacks/api/
config: configs/production/api/ # External config directory
params:
Environment: productionThe functionality remains identical, but the configuration is now generated externally.
Best Practices
Directory Structure
Use consistent, predictable directory structures:
configs/
├── {environment}/
│ ├── {stack-name}/
│ │ └── samconfig.yaml
│ └── {another-stack}/
│ └── samconfig.yaml
└── {another-environment}/
└── ...Environment Naming
Use standard environment names:
# Good - Directory-based (recommended)
config: configs/${{ inputs.environment }}/api/
# Good - Explicit file path
config: configs/${{ inputs.environment }}/api/samconfig.yaml
# With validation
pipeline_settings:
inputs:
environment:
type: string
default: dev
allowed_values: [dev, staging, prod]Template Expressions
Leverage template expressions for environment-specific behavior:
params:
LogLevel: ${{ inputs.environment == 'prod' && 'WARN' || 'DEBUG' }}
InstanceType: ${{ inputs.environment == 'prod' && 't3.large' || 't3.micro' }}
EnableMonitoring: ${{ inputs.environment == 'prod' }}
BackupRetentionDays: ${{ inputs.environment == 'prod' && '365' || '7' }}Troubleshooting
Template File Not Found
If you see “Template file not found” errors:
- Check relative paths: Ensure the generated config can find the template
- Verify directory structure: Make sure stack directories exist
- Review working directory: SAM CLI runs from the config file’s directory
Permission Issues
If directories cannot be created:
- Check write permissions for the config path parent directories
- Avoid system directories like
/etcor/usr(blocked for security) - Use relative paths for better portability
Missing Parameters
If CloudFormation validation fails:
- Check parameter mapping in the pipeline definition
- Verify template requirements match provided parameters
- Review cross-stack dependencies are properly defined
Examples
For complete working examples, see:
- Multi-Environment Example - Single pipeline supporting multiple environments
- Generated Configs - Example external configuration outputs
- Configuration README - Detailed explanation of the example structure