Skip to main content
chezmoi includes support for AWS Secrets Manager to retrieve secrets stored in AWS.

Setup

Install AWS CLI

Ensure you have AWS credentials configured:
# Install AWS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

Configure AWS Credentials

aws configure
# Enter your AWS Access Key ID
# Enter your AWS Secret Access Key
# Enter your default region
Or use environment variables:
export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_DEFAULT_REGION="us-east-1"

Template Functions

awsSecretsManager

Retrieve structured JSON secrets:
{{ (awsSecretsManager "my-secret-name").username }}
{{ (awsSecretsManager "my-secret-name").password }}
This retrieves the secret and parses it as JSON.

awsSecretsManagerRaw

Retrieve raw secret strings:
{{ awsSecretsManagerRaw "my-secret-string" }}
Useful for non-JSON secrets like API tokens or passwords.

Configuration

Configure AWS Secrets Manager in chezmoi:
~/.config/chezmoi/chezmoi.toml
[awsSecretsManager]
    profile = "myWorkProfile"
    region = "us-east-2"
By default, chezmoi uses:
  • Standard AWS environment variables (AWS_PROFILE, AWS_REGION)
  • AWS config files (~/.aws/config, ~/.aws/credentials)

Usage Examples

Database Credentials (JSON)

Store a JSON secret in AWS:
aws secretsmanager create-secret \
    --name prod-database \
    --secret-string '{
        "host": "db.example.com",
        "port": "5432",
        "username": "app_user",
        "password": "super_secret_password",
        "database": "production_db"
    }'
Use in templates:
~/.config/db/config.yml.tmpl
production:
  host: {{ (awsSecretsManager "prod-database").host }}
  port: {{ (awsSecretsManager "prod-database").port }}
  username: {{ (awsSecretsManager "prod-database").username }}
  password: {{ (awsSecretsManager "prod-database").password }}
  database: {{ (awsSecretsManager "prod-database").database }}

API Tokens (Raw)

aws secretsmanager create-secret \
    --name github-token \
    --secret-string "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Multiple API Keys

# Store multiple secrets
aws secretsmanager create-secret --name github-api-token --secret-string "ghp_xxx"
aws secretsmanager create-secret --name gitlab-api-token --secret-string "glpat-xxx"
aws secretsmanager create-secret --name openai-api-key --secret-string "sk-xxx"
~/.config/api-keys.env.tmpl
GITHUB_TOKEN={{ awsSecretsManagerRaw "github-api-token" }}
GITLAB_TOKEN={{ awsSecretsManagerRaw "gitlab-api-token" }}
OPENAI_API_KEY={{ awsSecretsManagerRaw "openai-api-key" }}

AWS Credentials for Different Accounts

Store credentials for other AWS accounts:
aws secretsmanager create-secret \
    --name dev-aws-credentials \
    --secret-string '{
        "access_key_id": "AKIAIOSFODNN7EXAMPLE",
        "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
        "region": "us-west-2"
    }'
~/.aws/credentials.tmpl
[development]
aws_access_key_id = {{ (awsSecretsManager "dev-aws-credentials").access_key_id }}
aws_secret_access_key = {{ (awsSecretsManager "dev-aws-credentials").secret_access_key }}
region = {{ (awsSecretsManager "dev-aws-credentials").region }}

SSH Private Keys

aws secretsmanager create-secret \
    --name ssh-private-key \
    --secret-string file://~/.ssh/id_rsa

Application Configuration

aws secretsmanager create-secret \
    --name app-config \
    --secret-string '{
        "api_endpoint": "https://api.example.com",
        "api_key": "secret_key_here",
        "db_connection": "postgresql://user:pass@host:5432/db",
        "redis_url": "redis://localhost:6379",
        "jwt_secret": "jwt_signing_secret"
    }'
~/.config/app/config.yml.tmpl
api:
  endpoint: {{ (awsSecretsManager "app-config").api_endpoint }}
  key: {{ (awsSecretsManager "app-config").api_key }}

database:
  connection: {{ (awsSecretsManager "app-config").db_connection }}

redis:
  url: {{ (awsSecretsManager "app-config").redis_url }}

auth:
  jwt_secret: {{ (awsSecretsManager "app-config").jwt_secret }}

Using Different Regions and Profiles

Per-Profile Configuration

# ~/.config/chezmoi/chezmoi.toml
[awsSecretsManager]
    profile = "personal"
    region = "us-east-1"

Using ARNs

You can use full ARNs for cross-region or cross-account access:
{{ awsSecretsManagerRaw "arn:aws:secretsmanager:us-west-2:123456789012:secret:my-secret-ABC123" }}

Advanced Usage

Versioned Secrets

AWS Secrets Manager supports versioning. By default, chezmoi retrieves the current version (AWSCURRENT).

Binary Secrets

For binary secrets, awsSecretsManagerRaw automatically decodes base64 data.

Nested JSON

Access nested JSON structures:
aws secretsmanager create-secret \
    --name complex-config \
    --secret-string '{
        "database": {
            "primary": {"host": "db1.example.com", "port": 5432},
            "replica": {"host": "db2.example.com", "port": 5432}
        },
        "cache": {"redis": {"host": "cache.example.com", "port": 6379}}
    }'
{{ (awsSecretsManager "complex-config").database.primary.host }}
{{ (awsSecretsManager "complex-config").cache.redis.host }}

Conditional Secrets by Environment

~/.config/app/config.yml.tmpl
{{ if eq .chezmoi.hostname "prod-server" -}}
# Production
api_key: {{ awsSecretsManagerRaw "prod-api-key" }}
db_password: {{ (awsSecretsManager "prod-database").password }}
{{ else -}}
# Development
api_key: {{ awsSecretsManagerRaw "dev-api-key" }}
db_password: {{ (awsSecretsManager "dev-database").password }}
{{ end }}

Complete Examples

Multi-Service Configuration

~/.config/services.yml.tmpl
services:
  database:
    host: {{ (awsSecretsManager "database").host }}
    port: {{ (awsSecretsManager "database").port }}
    username: {{ (awsSecretsManager "database").username }}
    password: {{ (awsSecretsManager "database").password }}
  
  redis:
    host: {{ (awsSecretsManager "redis").host }}
    port: {{ (awsSecretsManager "redis").port }}
    password: {{ awsSecretsManagerRaw "redis-password" }}
  
  api:
    github: {{ awsSecretsManagerRaw "github-token" }}
    gitlab: {{ awsSecretsManagerRaw "gitlab-token" }}
    openai: {{ awsSecretsManagerRaw "openai-key" }}

Kubernetes Secrets

~/.kube/config.tmpl
apiVersion: v1
kind: Config
clusters:
- cluster:
    server: {{ (awsSecretsManager "k8s-cluster").server }}
    certificate-authority-data: {{ (awsSecretsManager "k8s-cluster").ca_cert }}
  name: production
users:
- name: admin
  user:
    token: {{ awsSecretsManagerRaw "k8s-admin-token" }}
contexts:
- context:
    cluster: production
    user: admin
  name: prod-context
current-context: prod-context

IAM Permissions

Your AWS user/role needs these permissions:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue",
                "secretsmanager:DescribeSecret"
            ],
            "Resource": "arn:aws:secretsmanager:*:*:secret:*"
        }
    ]
}
For specific secrets:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "secretsmanager:GetSecretValue",
            "Resource": [
                "arn:aws:secretsmanager:us-east-1:123456789012:secret:my-secret-*",
                "arn:aws:secretsmanager:us-east-1:123456789012:secret:other-secret-*"
            ]
        }
    ]
}

Troubleshooting

AccessDeniedException

Ensure your IAM user/role has secretsmanager:GetSecretValue permission:
aws secretsmanager get-secret-value --secret-id my-secret

ResourceNotFoundException

Verify the secret exists in the correct region:
aws secretsmanager list-secrets --region us-east-1

Invalid JSON

If using awsSecretsManager (not awsSecretsManagerRaw), ensure your secret is valid JSON:
aws secretsmanager get-secret-value --secret-id my-secret | jq .SecretString

Credentials Not Found

Verify AWS credentials are configured:
aws configure list
aws sts get-caller-identity

Testing Templates

Test template functions:
chezmoi execute-template '{{ awsSecretsManagerRaw "test-secret" }}'

Best Practices

  1. Use IAM roles: On EC2/ECS, use IAM roles instead of access keys
  2. Least privilege: Grant only necessary permissions to specific secrets
  3. Use encryption: Enable encryption at rest for secrets
  4. Rotate secrets: Enable automatic rotation for database credentials
  5. Use resource policies: Control access with resource-based policies
  6. Tag secrets: Use tags for organization and cost allocation
  7. Monitor access: Enable CloudTrail logging for secret access
  8. Use VPC endpoints: Access Secrets Manager privately from VPC

Cost Considerations

AWS Secrets Manager pricing:
  • $0.40 per secret per month
  • $0.05 per 10,000 API calls
Consider:
  • Caching reduces API calls
  • Use AWS Systems Manager Parameter Store for simpler secrets (cheaper)
  • Delete unused secrets

See Also

Build docs developers (and LLMs) love