With User Data

Configure an EC2 instance with a user data script to automate setup at launch.

module "app_server" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/ec2-instance/aws"
  version = "1.5.0"

  instance_name      = "app-server"
  instance_type      = "t3.medium"
  ami_id             = data.aws_ami.amazon_linux.id
  subnet_id          = module.vpc.private_subnets[0]
  security_group_ids = [aws_security_group.app.id]

  user_data = <<-EOF
    #!/bin/bash
    set -e

    # Update system packages
    yum update -y

    # Install Docker
    amazon-linux-extras install docker -y
    systemctl start docker
    systemctl enable docker
    usermod -aG docker ec2-user

    # Install CloudWatch agent
    yum install -y amazon-cloudwatch-agent

    # Pull and run application container
    docker pull myregistry.example.com/myapp:latest
    docker run -d -p 8080:8080 myregistry.example.com/myapp:latest

    # Signal completion (for use with cfn-signal or similar)
    echo "User data script completed successfully"
  EOF

  tags = {
    Environment = "production"
    Application = "myapp"
  }
}

Using a Template File

For more complex scripts, use templatefile():

module "templated_server" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/ec2-instance/aws"
  version = "1.5.0"

  instance_name = "templated-server"
  instance_type = "t3.medium"
  ami_id        = data.aws_ami.amazon_linux.id
  subnet_id     = module.vpc.private_subnets[0]

  user_data = templatefile("${path.module}/scripts/init.sh", {
    environment   = "production"
    app_version   = "1.2.3"
    config_bucket = aws_s3_bucket.config.id
  })
}

Notes

  • User data scripts run as root on first boot only
  • Scripts are limited to 16 KB (use S3 for larger scripts)
  • Check /var/log/cloud-init-output.log for debugging
  • Use base64encode() for binary user data