AWS EC2 cloud-init instance setup

Are you still manually checking your cloud-init scripts’  status for success or failure?

If you want to be notified when everything goes the right way, you can use a simple curl command at the end of your setup script:

curl -X POST \
  "https://hook.notify17.net/api/raw/${RAW_API_KEY}" \
  -F title="Instance setup: finished" \
  -F content="Instance ${HOSTNAME} has been set up correctly!"

If you want a more precise approach, you can use the following cloud-init example.

It runs:

  • A basic setup script (/root/setup.sh) that fails.
  • A background script that:
    • Waits for cloud-init to finish its initialization.
    • Checks if there have been any errors.
    • Notifies the user on success or on error (if error, reports the last messages of /var/log/cloud-init-output.log).
Example
#cloud-config

packages:
  - curl
runcmd:
  # Invokes Notify17 cloud init reporter in background

  - "nohup /root/n17-cloud-init.sh &"
  
  # Actual cloud init startup script

  - "bash /root/setup.sh"
  
write_files:
  # Our sample bash script that fails

  - owner: root:root
    permissions: '0644'
    path: /root/setup.sh
    content: |
      #!/bin/bash      

      echo "Hello!"
      exit 1

  # Cloud init report

  - owner: root:root
    permissions: '0755'
    path: /root/n17-cloud-init.sh
    content: |
      #!/bin/bash

      set -Eeumo pipefail

      # Fetch the EC2 instance private IP

      PRIVATE_IP=$(curl http://169.254.169.254/latest/meta-data/local-ipv4)
      
      # Set your Raw API key here

      N17_URL="https://hook.notify17.net/api/raw/RAW_API_KEY"

      curl -X POST "$N17_URL" \
        --data-urlencode "title=EC2 cloud-init started: $HOSTNAME ($PRIVATE_IP)" \
        || echo "Failed to report cloud-init started"

      # Block until cloud-init completes

      while [ ! -f /var/lib/cloud/instance/boot-finished ]; do sleep 1; done

      # Check the cloud-init result.json for errors

      if egrep '"errors": \[$' /var/lib/cloud/data/result.json; then
        # Fetch the last 30 rows of cloud-init logs

        LOGS=$(tail -n30 /var/log/cloud-init-output.log)
        CONTENT="Error occurred while initializing instance: $HOSTNAME ($PRIVATE_IP)"
        CONTENT="$CONTENT"$'\n\n'"$LOGS"
        curl -X POST "$N17_URL" \
          --data-urlencode "title=EC2 cloud-init error: $HOSTNAME ($PRIVATE_IP)" \
          --data-urlencode "content=$CONTENT" \
          || echo "Failed to report cloud-init error"
        exit 0
      fi

      CONTENT="Instance initialized successfully: $HOSTNAME ($PRIVATE_IP)"
      curl -X POST "$N17_URL" \
        --data-urlencode "title=EC2 cloud-init success: $HOSTNAME ($PRIVATE_IP)" \
        --data-urlencode "content=$CONTENT" \
        || echo "Failed to report cloud-init success"