Examples¶
Common use cases and configurations for the terraform-aws-cloud-init module.
Basic Web Server¶
Minimal configuration for a web server:
module "webserver_userdata" {
source = "registry.infrahouse.com/infrahouse/cloud-init/aws"
version = "2.2.3"
environment = "production"
role = "webserver"
}
With Custom Packages¶
Install additional packages during bootstrap:
module "webserver_userdata" {
source = "registry.infrahouse.com/infrahouse/cloud-init/aws"
version = "2.2.3"
environment = "production"
role = "webserver"
packages = [
"nginx",
"certbot",
"python3-certbot-nginx"
]
}
With Custom Facts¶
Inject custom Puppet facts:
module "app_userdata" {
source = "registry.infrahouse.com/infrahouse/cloud-init/aws"
version = "2.2.3"
environment = "production"
role = "app_server"
custom_facts = {
app_version = var.app_version
cluster_name = "web-cluster-1"
feature_flags = jsonencode(var.feature_flags)
}
}
With Pre/Post Commands¶
Run commands before and after Puppet:
module "app_userdata" {
source = "registry.infrahouse.com/infrahouse/cloud-init/aws"
version = "2.2.3"
environment = "production"
role = "app_server"
pre_runcmd = [
"mkdir -p /opt/myapp/data",
"chown -R ubuntu:ubuntu /opt/myapp"
]
post_runcmd = [
"systemctl enable myapp",
"systemctl start myapp"
]
}
With EBS Volume Mounts¶
Mount EBS volumes before Puppet runs:
module "database_userdata" {
source = "registry.infrahouse.com/infrahouse/cloud-init/aws"
version = "2.2.3"
environment = "production"
role = "database"
mounts = [
["/dev/xvdf", "/var/lib/postgresql", "ext4", "defaults,nofail", "0", "2"]
]
pre_runcmd = [
"mkfs -t ext4 /dev/xvdf || true" # Format if not already formatted
]
}
With Private APT Repository¶
Configure a private APT repository with authentication:
module "app_userdata" {
source = "registry.infrahouse.com/infrahouse/cloud-init/aws"
version = "2.2.3"
environment = "production"
role = "app_server"
extra_repos = {
"company-repo" = {
source = "deb [signed-by=$KEY_FILE] https://apt.company.com/ubuntu noble main"
keyid = "A627B7760019BA51B903453D37A181B689AD619"
machine = "apt.company.com"
authFrom = "arn:aws:secretsmanager:us-west-2:123456789012:secret:apt-credentials"
priority = 500
}
}
}
The secret in AWS Secrets Manager must contain JSON with the username as key and password as value:
This generates an APT auth entry: machine apt.company.com login deploy password s3cr3t-p4ssw0rd
See Architecture - Secret Format for details.
With SSH Host Keys¶
Pre-configure SSH host keys for consistent identification:
module "jumphost_userdata" {
source = "registry.infrahouse.com/infrahouse/cloud-init/aws"
version = "2.2.3"
environment = "production"
role = "jumphost"
ssh_host_keys = [
{
type = "rsa"
private = data.aws_secretsmanager_secret_version.ssh_rsa.secret_string
public = data.aws_secretsmanager_secret_version.ssh_rsa_pub.secret_string
},
{
type = "ed25519"
private = data.aws_secretsmanager_secret_version.ssh_ed25519.secret_string
public = data.aws_secretsmanager_secret_version.ssh_ed25519_pub.secret_string
}
]
}
Security Consideration
Embedding SSH host keys in userdata exposes them to anyone with EC2 read access (ec2:DescribeInstanceAttribute) or instance metadata access. While host keys only prove server identity (not grant access), an attacker with the key AND a network MITM position could impersonate the server.
For higher security environments, consider fetching host keys from Secrets Manager in pre_runcmd instead:
pre_runcmd = [
"aws secretsmanager get-secret-value --secret-id ssh-host-key-ed25519 --query SecretString --output text > /etc/ssh/ssh_host_ed25519_key",
"chmod 600 /etc/ssh/ssh_host_ed25519_key",
]
This requires AWS CLI to be installed (available after package installation phase).
With Extra Configuration Files¶
Create additional configuration files:
module "app_userdata" {
source = "registry.infrahouse.com/infrahouse/cloud-init/aws"
version = "2.2.3"
environment = "production"
role = "app_server"
extra_files = [
{
content = file("${path.module}/files/app-config.yaml")
path = "/etc/myapp/config.yaml"
permissions = "0644"
},
{
content = templatefile("${path.module}/files/env.tpl", {
database_host = var.database_host
redis_host = var.redis_host
})
path = "/etc/myapp/.env"
permissions = "0600"
}
]
}
With Gzip Compression¶
Enable compression for large userdata:
module "app_userdata" {
source = "registry.infrahouse.com/infrahouse/cloud-init/aws"
version = "2.2.3"
environment = "production"
role = "app_server"
gzip_userdata = true
# Large configuration that might exceed 16KB limit
extra_repos = { /* multiple repos */ }
extra_files = [ /* multiple files */ ]
}
With Debug Logging¶
Enable verbose Puppet output for troubleshooting:
module "app_userdata" {
source = "registry.infrahouse.com/infrahouse/cloud-init/aws"
version = "2.2.3"
environment = "development"
role = "app_server"
puppet_debug_logging = true
}
Complete Production Example¶
A comprehensive example combining multiple features:
module "production_app_userdata" {
source = "registry.infrahouse.com/infrahouse/cloud-init/aws"
version = "2.2.3"
environment = "production"
role = "app_server"
# Additional packages
packages = ["jq", "awscli"]
# Custom facts
custom_facts = {
app_version = var.app_version
deploy_id = var.deploy_id
cluster_name = var.cluster_name
}
# Private repository
extra_repos = {
"company-repo" = {
source = "deb [signed-by=$KEY_FILE] https://apt.company.com/ubuntu noble main"
keyid = var.company_repo_keyid
machine = "apt.company.com"
authFrom = var.apt_secret_arn
}
}
# Configuration files
extra_files = [
{
content = templatefile("${path.module}/templates/app.conf.tpl", local.app_config)
path = "/etc/myapp/app.conf"
permissions = "0644"
}
]
# Mount data volume
mounts = [
["/dev/xvdf", "/data", "ext4", "defaults,nofail", "0", "2"]
]
# Pre-puppet commands
pre_runcmd = [
"mkfs -t ext4 /dev/xvdf || true"
]
# Post-puppet commands
post_runcmd = [
"systemctl daemon-reload",
"systemctl restart myapp"
]
# Compress large userdata
gzip_userdata = true
}