Skip to main content

Environments

Environments in carlin enable multi-stage deployment workflows (development, staging, production) with automatic termination protection and environment-specific configurations.

Defining Environments

Specify environment using CLI option, environment variable, or config file:

CLI Option

carlin deploy --environment production

Environment Variable

CARLIN_ENVIRONMENT=staging carlin deploy

Config File

Create carlin.yml:

environment: staging

Deploy:

carlin deploy

Environment Benefits

1. Termination Protection

Stacks deployed with --environment automatically enable CloudFormation termination protection, preventing accidental deletion:

carlin deploy --environment production
# Stack created with termination protection enabled

carlin deploy --destroy --environment production
# Error: Cannot delete stack with termination protection

To delete protected stacks:

# Option 1: Remove environment flag and use stack name
carlin deploy --destroy --stack-name my-app-production

# Option 2: Disable protection in AWS Console first

2. Environment-Specific Naming

Environment name becomes part of the stack name:

carlin deploy --environment staging
# Stack: my-app-staging

carlin deploy --environment production
# Stack: my-app-production

This creates clear separation between environments without manual stack name management.

3. Environment-Specific Parameters

Use different CloudFormation parameters per environment:

# Staging with smaller instance
carlin deploy --environment staging --parameters '{"InstanceType":"t3.micro"}'

# Production with larger instance
carlin deploy --environment production --parameters '{"InstanceType":"t3.large"}'

4. Configuration Inheritance

Create environment-specific config files:

# carlin.yml (base configuration)
region: us-east-1
parameters:
DomainName: app.example.com
# carlin.staging.yml
environment: staging
parameters:
DomainName: staging.app.example.com
InstanceType: t3.micro
# carlin.production.yml
environment: production
parameters:
DomainName: app.example.com
InstanceType: t3.large

Deploy to specific environment:

carlin deploy --config carlin.staging.yml
carlin deploy --config carlin.production.yml

Common Environment Patterns

Three-Stage Pipeline

# 1. Development (feature branches, no environment)
git checkout feature/new-feature
carlin deploy
# Stack: my-app-feature-new-feature
# No termination protection

# 2. Staging (shared pre-production)
carlin deploy --environment staging
# Stack: my-app-staging
# Termination protection enabled

# 3. Production (live environment)
carlin deploy --environment production
# Stack: my-app-production
# Termination protection enabled

Environment-Based AWS Accounts

Use different AWS credentials per environment:

# Staging (AWS account 111111111111)
AWS_PROFILE=staging carlin deploy --environment staging

# Production (AWS account 222222222222)
AWS_PROFILE=production carlin deploy --environment production

CI/CD Integration

Configure GitHub Actions for automatic environment deployments:

# .github/workflows/deploy.yml
name: Deploy

on:
push:
branches:
- main
- staging

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Deploy to Staging
if: github.ref == 'refs/heads/staging'
run: carlin deploy --environment staging
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID_STAGING }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_STAGING }}

- name: Deploy to Production
if: github.ref == 'refs/heads/main'
run: carlin deploy --environment production
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID_PROD }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_PROD }}

Environment vs Branch Naming

See Stack Naming for the full naming algorithm.

Key difference: deploying with --environment enables termination protection and the environment name takes precedence over the branch name.

Environment Variables

Use CloudFormation parameters to pass environment-specific values:

carlin deploy --environment staging --parameters '{"Environment":"staging","DatabaseInstanceType":"db.t3.small"}'

Best Practices

  • Always use --environment for shared stages (staging, production) to enable termination protection
  • Separate AWS accounts for production when possible
  • Use parameterized values instead of hardcoding environment-specific settings
  • Document your environment setup in a README

Troubleshooting

Cannot Delete Environment Stack

Problem: Deletion fails with "Stack has termination protection enabled"

Solution: Use stack name without environment:

carlin deploy --destroy --stack-name my-app-production

Wrong Environment Deployed

Problem: Deployed to production instead of staging

Solution: Always explicitly set environment:

# Instead of relying on defaults
carlin deploy

# Always specify explicitly
carlin deploy --environment staging

Environment Variable Not Working

Problem: CARLIN_ENVIRONMENT not being recognized

Solution: Verify environment variable is exported:

export CARLIN_ENVIRONMENT=staging
echo $CARLIN_ENVIRONMENT # Should print: staging
carlin deploy