Answers: <p>There are a few issues with this cloud-init script.</p>
  <ul>
  <li><code>#groups</code> is commented out, so the list beneath it makes it invalid YAML.</li>
  <li>Even if we uncomment groups, <code>  - ubuntu: [root,sys]</code> is invalid because the default user already has a group specification. If you look near the bottom of <code>/etc/cloud/cloud.cfg</code> on a launched instance, you should see something like:</li>
  </ul>
  <pre class="lang-yaml prettyprint-override"><code>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: [&quot;ALL=(ALL) NOPASSWD:ALL&quot;]
       shell: /bin/bash
  </code></pre>
  <p>So you either need to remove the <code>ubuntu</code> line from your groups definition, or remove <code>- default</code> from your user definition and define the <code>ubuntu</code> user manually.</p>
  <ul>
  <li>Your ssh key is also pasted as invalid YAML. Keep it as a single line</li>
  <li>In your runcmd, <code>sudo su</code> doesn't work that way in a script. Instead you should <code>sudo -u &lt;user&gt;</code> for an individual user to run an individual command. Additionally, <code>sudo</code> isn't needed for root permissions as all user scripts run as root already.</li>
  </ul>
  <p>Fixing all of these issues, we should get a resulting cloud-init script that looks something like this:</p>
  <pre class="lang-yaml prettyprint-override"><code>#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 &amp; 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
  </code></pre>
  
Answers: CC BY-SA 4.0
Answers: 2022-04-26T16:54:03.550Z
Answers: I've used this cloud-init script, but I obtain the following error: Permission denied (publickey). I've ensured that I'm using the correct private key, in PEM format.
Answers: Huzi 
Answers: CC BY-SA 4.0
Answers: 2022-04-27T18:05:41.500Z
Answers: I copied what you initially provided, but every public RSA key I've seen starts with `ssh-rsa` not `ssh rsa`. Ensure you've copied the key correctly.
Answers: falcojr
Answers: CC BY-SA 4.0
Answers: 2022-04-25T14:38:34.163Z
Answers: 2022-04-25T14:38:34.163Z
Answers: falcojr
Answers: <p>Maybe it does not matter but also try to add &quot;${}&quot; around terraform's file function before rendering:</p>
  <pre><code>data &quot;template_file&quot; &quot;init_script&quot; {
    template = &quot;${file(&quot;../scripts/add-ssh-web-app.yaml&quot;)}&quot;
  }
  </code></pre>
  
Answers: CC BY-SA 4.0
Answers: 2022-04-26T07:19:18.433Z
Answers: 2022-04-26T07:19:18.433Z
Answers: Serve Laurijssen
Body: <p>I am working through this Terraform <a href="https://learn.hashicorp.com/tutorials/terraform/cloud-init?in=terraform/provision" rel="nofollow noreferrer">tutorial</a>, which boots up a Go web app on an EC2 instance, using Terraform and cloud-init. This is my Terraform config file:</p>
  <pre><code>terraform {
    required_version = &quot;&gt;= 0.13&quot;
    required_providers {
      aws = {
        source  = &quot;hashicorp/aws&quot;
        version = &quot;~&gt; 3.0&quot;
      }
    }
  }
  
  
  provider &quot;aws&quot; {
    region = var.region
  }
  
  data &quot;aws_ami&quot; &quot;ubuntu&quot; {
    most_recent = true
  
    filter {
      name   = &quot;name&quot;
      values = [&quot;ubuntu/images/hvm-ssd/ubuntu-*20*-amd64-server-*&quot;]
    }
  
    filter {
      name   = &quot;virtualization-type&quot;
      values = [&quot;hvm&quot;]
    }
  
    owners = [&quot;099720109477&quot;] # Canonical
  }
  
  resource &quot;aws_vpc&quot; &quot;vpc&quot; {
    cidr_block           = var.cidr_vpc
    enable_dns_support   = true
    enable_dns_hostnames = true
  }
  
  resource &quot;aws_internet_gateway&quot; &quot;igw&quot; {
    vpc_id = aws_vpc.vpc.id
  }
  
  resource &quot;aws_subnet&quot; &quot;subnet_public&quot; {
    vpc_id     = aws_vpc.vpc.id
    cidr_block = var.cidr_subnet
  }
  
  resource &quot;aws_route_table&quot; &quot;rtb_public&quot; {
    vpc_id = aws_vpc.vpc.id
  
    route {
      cidr_block = &quot;0.0.0.0/0&quot;
      gateway_id = aws_internet_gateway.igw.id
    }
  }
  
  resource &quot;aws_route_table_association&quot; &quot;rta_subnet_public&quot; {
    subnet_id      = aws_subnet.subnet_public.id
    route_table_id = aws_route_table.rtb_public.id
  }
  
  resource &quot;aws_security_group&quot; &quot;sg_22_80&quot; {
    name   = &quot;sg_22&quot;
    vpc_id = aws_vpc.vpc.id
  
    # SSH access from the VPC
    ingress {
      from_port   = 22
      to_port     = 22
      protocol    = &quot;tcp&quot;
      cidr_blocks = [&quot;0.0.0.0/0&quot;]
    }
  
    ingress {
      from_port   = 80
      to_port     = 80
      protocol    = &quot;tcp&quot;
      cidr_blocks = [&quot;0.0.0.0/0&quot;]
    }
  
  
    ingress {
      from_port   = 8080
      to_port     = 8080
      protocol    = &quot;tcp&quot;
      cidr_blocks = [&quot;0.0.0.0/0&quot;]
    }
  
    egress {
      from_port   = 0
      to_port     = 0
      protocol    = &quot;-1&quot;
      cidr_blocks = [&quot;0.0.0.0/0&quot;]
    }
  }
  
  data &quot;template_file&quot; &quot;user_data&quot; {
    template = file(&quot;../scripts/add-ssh-web-app.yaml&quot;)
  }
  
  resource &quot;aws_instance&quot; &quot;web&quot; {
    ami                         = data.aws_ami.ubuntu.id
    instance_type               = &quot;t2.micro&quot;
    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.rendered
  
    tags = {
      Name = &quot;Learn-CloudInit&quot;
    }
  }
  
  output &quot;public_ip&quot; {
    value = aws_instance.web.public_ip
  }
  </code></pre>
  <p>My cloud-init script looks like this:</p>
  <pre><code>#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
  
  
  
  # Downloads the golang package
  packages:
    - golang-go
  
  # Sets the GOPATH &amp; 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
  </code></pre>
  <p>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:</p>
  <p><em>Permission denied (publickey,gssapi-keyex,gssapi-with-mic).</em></p>
  <p>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.</p>
  <p>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?</p>
  
Comments: CC BY-SA 4.0
Comments: 2022-04-21T12:34:44.920Z
Comments: this may just be stackexchange formatting so I wouldn't want to consider this a real answer. It's pretty important that the public key is formatted correctly.  I think yaml will munge your rsa key together, but can you try just removing the newlines?
Comments: Peter Turner
Tags: <amazon-web-services><terraform><infrastructure-as-code><ssh><cloud-init>
Title: Cloud-Init Script Won't Run?
UserDisplayName: Huzi 
ThreadText: # Cloud-Init Script Won't Run?
  
  (Asked by: username_0 on 2022-04-21)
  
  I am working through this Terraform [tutorial](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 = true
  
    filter {
      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.id
  
    route {
      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.id
  
    # SSH 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.rendered
  
    tags = {
      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
  
  # 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?
  
  **Tags:** amazon-web-services, terraform, infrastructure-as-code, ssh, cloud-init
  
  > **Comments:**
  > **username_1**: this may just be stackexchange formatting so I wouldn't want to consider this a real answer. It's pretty important that the public key is formatted correctly.  I think yaml will munge your rsa key together, but can you try just removing the newlines?  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_2 on 2022-04-25. Score: 3
  
  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:
  
  ```yaml
  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 the `ubuntu` 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 should `sudo -u <user>` 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:
  
  ```yaml
  #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
  
  ```
  
  > **Comments:**
  > **username_0**: I've used this cloud-init script, but I obtain the following error: Permission denied (publickey). I've ensured that I'm using the correct private key, in PEM format.  
  > **username_2**: I copied what you initially provided, but every public RSA key I've seen starts with `ssh-rsa` not `ssh rsa`. Ensure you've copied the key correctly.  
  
  ---
  
  ### Answer by username_3 on 2022-04-26. Score: 0
  
  Maybe it does not matter but also try to add "${}" around terraform's file function before rendering:
  
  ```
  data "template_file" "init_script" {
    template = "${file("../scripts/add-ssh-web-app.yaml")}"
  }
  
  ```
  
  
  ---
  
  