Cloud-Init Script Won't Run?
-
I am working through this Terraform https://learn.hashicorp.com/tutorials/terraform/cloud-init?in=terraform/provision , which boots up a Go web app on an EC2 instance, using Terraform and cloud-init. This is my Terraform config file:
terraform { required_version = ">= 0.13" required_providers { aws = { source = "hashicorp/aws" version = "~> 3.0" } } }
provider "aws" {
region = var.region
}data "aws_ami" "ubuntu" {
most_recent = truefilter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-20-amd64-server-*"]
}filter {
name = "virtualization-type"
values = ["hvm"]
}owners = ["099720109477"] # Canonical
}resource "aws_vpc" "vpc" {
cidr_block = var.cidr_vpc
enable_dns_support = true
enable_dns_hostnames = true
}resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.vpc.id
}resource "aws_subnet" "subnet_public" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.cidr_subnet
}resource "aws_route_table" "rtb_public" {
vpc_id = aws_vpc.vpc.idroute {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
}resource "aws_route_table_association" "rta_subnet_public" {
subnet_id = aws_subnet.subnet_public.id
route_table_id = aws_route_table.rtb_public.id
}resource "aws_security_group" "sg_22_80" {
name = "sg_22"
vpc_id = aws_vpc.vpc.idSSH access from the VPC
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}data "template_file" "user_data" {
template = file("../scripts/add-ssh-web-app.yaml")
}resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
subnet_id = aws_subnet.subnet_public.id
vpc_security_group_ids = [aws_security_group.sg_22_80.id]
associate_public_ip_address = true
user_data = data.template_file.user_data.renderedtags = {
Name = "Learn-CloudInit"
}
}output "public_ip" {
value = aws_instance.web.public_ip
}
My cloud-init script looks like this:
#cloud-config # Add groups to the system # Adds the ubuntu group with members 'root' and 'sys' # and the empty group hashicorp. #groups: - ubuntu: [root,sys] - hashicorp
Add users to the system. Users are added after groups are added.
users:
- default
- name: terraform
gecos: terraform
shell: /bin/bash
primary_group: hashicorp
sudo: ALL=(ALL) NOPASSWD:ALL
groups: users, admin
lock_passwd: false
ssh_authorized_keys:- ssh rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCMT6uYfhWx8jOmiGR9ryIPKcWy2ceqvyZ4
Q4+q5QTiZtlbWxbP37YZnT8uQhyjB4QRR1cjOyvGKC3Zu0Isy0eHIx2lGm/7B04b
soWWAUqhJmYWMZlivnHtJJJ4P5gnvXiRNmFg9iK07C7ClggNBAQZZHUeA5wcnvvH
T/pDkGUjMUqgLvmWRJqJM9qLT717e229F1Fyh+sYtAj08qmcFF1JCs2D33R46RQ8
YBMpQqmWLfjuJDUrjdvMu7Mv3aPpaeUWuYoC90iHR9XMeNonrtRlx21nY3CoMZ0A
OpeNl999UzyMJrsvN4qm6byK2Pc6jrEyKr9jI8SvMEGdSWgqr/Hd
- ssh rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCMT6uYfhWx8jOmiGR9ryIPKcWy2ceqvyZ4
Downloads the golang package
packages:
- golang-go
Sets the GOPATH & downloads the demo payload
runcmd:
- sudo su terraform
- sudo mkdir /home/terraform/go
- sudo chown terraform:hashicorp /home/terraform/go
- export GOPATH=/home/terraform/go
- go get github.com/hashicorp/learn-go-webapp-demo
After successfully applying the Terraform config, I obtain the following error when I try to SSH into this instance from the CLI using my OpenSSH private key:
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
To further investigate, I have SSH'd into the instance with AWS Direct Connect, from which I found none of the users, groups or directories had been created and the packages hadn't been installed - so it seems like the cloud-init script did not run at all. I'm guessing I can't SSH into my instance because the public key wasn't uploaded to it.
I assumed that this could be an issue with Ubuntu, so I changed the AMI to Linux 2, which resulted in the same error. Am I missing something obvious?
-
There are a few issues with this cloud-init script.
#groups
is commented out, so the list beneath it makes it invalid YAML.- Even if we uncomment groups,
- ubuntu: [root,sys]
is invalid because the default user already has a group specification. If you look near the bottom of/etc/cloud/cloud.cfg
on a launched instance, you should see something like:
system_info: # This will affect which distro class gets used distro: ubuntu # Default user name + that default users groups (if added/used) default_user: name: ubuntu lock_passwd: True gecos: Ubuntu groups: [adm, audio, cdrom, dialout, dip, floppy, lxd, netdev, plugdev, sudo, video] sudo: ["ALL=(ALL) NOPASSWD:ALL"] shell: /bin/bash
So you either need to remove the
ubuntu
line from your groups definition, or remove- default
from your user definition and define theubuntu
user manually.- Your ssh key is also pasted as invalid YAML. Keep it as a single line
- In your runcmd,
sudo su
doesn't work that way in a script. Instead you shouldsudo -u
for an individual user to run an individual command. Additionally,sudo
isn't needed for root permissions as all user scripts run as root already.
Fixing all of these issues, we should get a resulting cloud-init script that looks something like this:
#cloud-config
Add the empty group hashicorp.
groups:
- hashicorp
Add users to the system. Users are added after groups are added.
users:
- default
- name: terraform
gecos: terraform
shell: /bin/bash
primary_group: hashicorp
sudo: ALL=(ALL) NOPASSWD:ALL
groups: users, admin
lock_passwd: false
ssh_authorized_keys:- ssh rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCMT6uYfhWx8jOmiGR9ryIPKcWy2ceqvyZ4Q4+q5QTiZtlbWxbP37YZnT8uQhyjB4QRR1cjOyvGKC3Zu0Isy0eHIx2lGm/7B04bsoWWAUqhJmYWMZlivnHtJJJ4P5gnvXiRNmFg9iK07C7ClggNBAQZZHUeA5wcnvvHT/pDkGUjMUqgLvmWRJqJM9qLT717e229F1Fyh+sYtAj08qmcFF1JCs2D33R46RQ8YBMpQqmWLfjuJDUrjdvMu7Mv3aPpaeUWuYoC90iHR9XMeNonrtRlx21nY3CoMZ0AOpeNl999UzyMJrsvN4qm6byK2Pc6jrEyKr9jI8SvMEGdSWgqr/Hd
Downloads the golang package
packages:
- golang-go
Sets the GOPATH & downloads the demo payload
runcmd:
- mkdir /home/terraform/go
- chown terraform:hashicorp /home/terraform/go
- sudo GOPATH=/home/terraform/go -u terraform go install github.com/hashicorp/learn-go-webapp-demo@latest