Skip to content

Instantly share code, notes, and snippets.

@kixorz
Last active November 5, 2021 08:28
Show Gist options
  • Star 43 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save kixorz/10194688 to your computer and use it in GitHub Desktop.
Save kixorz/10194688 to your computer and use it in GitHub Desktop.
Ubuntu CloudFormation Tools installation snippet. Modified version of http://krunchtime.it/setting-up-bootstrapping-using-cfn-init-for-aws-ubuntu-ec2-instance
"UserData": {
"Fn::Base64": { "Fn::Join":["", [
"#!/bin/bash -ex\n",
"apt-get update\n",
"apt-get -y install python-setuptools\n",
"mkdir aws-cfn-bootstrap-latest\n",
"curl https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz | tar xz -C aws-cfn-bootstrap-latest --strip-components 1\n",
"easy_install aws-cfn-bootstrap-latest\n",
"/usr/local/bin/cfn-init --stack ", { "Ref":"AWS::StackName" }, " --resource WebServer", " --region ", { "Ref": "AWS::Region" }, "\n",
"\n",
"/usr/local/bin/cfn-signal --exit-code $? '", { "Ref" : "WaitHandle" }, "'\n"
]]}
}
@franklanganke
Copy link

I got this working by adding a comma at the end of line 9 and defining the "WaitHandle" earlier in the template.

@kixorz
Copy link
Author

kixorz commented Oct 5, 2015

Thanks! I'll update it.

@dougireton
Copy link

Another example which uses pip instead of easy_install and works behind a proxy:

    "UserData": {
          "Fn::Base64": {
            "Fn::Join": ["", [
              "#!/bin/bash\n",
              "set -o errexit; set -o nounset; set -o pipefail\n",
              "echo 'Acquire::http::proxy \"http://myproxy.example.com:8080 \";' > /etc/apt/apt.conf.d/80proxy\n",
              "echo 'Acquire::https::proxy \"http://myproxy.example.com:8080 \";' >> /etc/apt/apt.conf.d/80proxy\n",

              "# Install AWS cfn-bootstrap utilities\n",
              "apt-get update\n",
              "apt-get -y install python-pip\n",
              "pip install --proxy http://myproxy.example.com:8080 https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n",

              "/usr/local/bin/cfn-init",
              " --stack ", { "Ref": "AWS::StackName" },
              " --resource MyLogicalResourceName",
              " --configsets bootstrap-chef",
              " --region ", { "Ref": "AWS::Region" }, "\n"
            ]]
          }
        }

@lukeocodes
Copy link

Another more basic example with easy install for Debian 8.

    "UserData": {
      "Fn::Base64": { "Fn::Join":["", [
        "#!/bin/bash\n",
        "apt-get update\n",
        "apt-get -y install python-setuptools\n",
        "easy_install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n",
        "cfn-init --stack ", { "Ref": "AWS::StackName" }," --resource LaunchConfig --region ", { "Ref": "AWS::Region" }, "\n",
        "cfn-signal -e $? ","--stack ", { "Ref": "AWS::StackName" }," --resource WebServerGroup --region ", { "Ref": "AWS::Region" }, "\n"
      ]]}

@wtfiwtz
Copy link

wtfiwtz commented Oct 12, 2016

On Ubuntu 16.04.1 LTS this works:

#!/bin/bash -xe

mkdir -p /tmp/aws-cfn-bootstrap-latest

curl https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-1.4-8.tar.gz | tar xz -C /tmp/aws-cfn-bootstrap-latest --strip-components 1

curl https://s3-ap-southeast-2.amazonaws.com/bucket/cfn-hup.service -o /etc/systemd/system/cfn-hup.service

apt-get update

apt-get install -y python-pip libssl-dev libffi-dev

pip install pyopenssl ndg-httpsclient pyasn1

pip install --upgrade /tmp/aws-cfn-bootstrap-latest

cp /tmp/aws-cfn-bootstrap-latest/init/ubuntu/cfn-hup /etc/init.d/cfn-hup
/etc/init.d/
update-rc.d cfn-hup defaults
chmod 755 /etc/init.d/cfn-hup


A sample cfn-hup.service file is here: adamreeve/asp.net-docker@96f86bf

... although you might need to set the launch path to /usr/local/bin/cfn-hup

Another issue was that I had to disable the cfn-hup service setup - maybe Cloudformation's cloud-init and cfn-init is not compatible with systemd. You can install the upstart-sysv Ubuntu package to switch back to upstart although I had other difficulties with that.

@rozhok
Copy link

rozhok commented Mar 26, 2017

Another one taken from https://commscentral.net/tech/?post=50:

    "AppInstanceConfiguration": {
      "Type": "AWS::AutoScaling::LaunchConfiguration",
      "Metadata": {
        "AWS::CloudFormation::Init" : {
          "config" : {
            "files" : {

              "/etc/cfn/cfn-hup.conf" : {
                "content" : { "Fn::Join" : ["", [
                  "[main]\n",
                  "stack=", { "Ref" : "AWS::StackId" }, "\n",
                  "region=", { "Ref" : "AWS::Region" }, "\n"
                ]]},
                "mode"    : "000400",
                "owner"   : "root",
                "group"   : "root"
              },

              "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : {
                "content": { "Fn::Join" : ["", [
                  "[cfn-auto-reloader-hook]\n",
                  "triggers=post.update\n",
                  "path=Resources.AppInstanceConfiguration.Metadata.AWS::CloudFormation::Init\n",
                  "action=/usr/local/bin/cfn-init -v ",
                  "         --stack ", { "Ref" : "AWS::StackName" },
                  "         --resource AppInstanceConfiguration ",
                  "         --region ", { "Ref" : "AWS::Region" }, "\n",
                  "runas=root\n"
                ]]}
              }
            },

            "services" : {
              "sysvinit" : {
                "cfn-hup" : { "enabled" : "true", "ensureRunning" : "true",
                  "files" : ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"]}
              }
            }
          }
        }
      },
      "Properties": {
        "ImageId" : { "Fn::FindInMap" : [ "AWSRegionToUbuntuAMI", { "Ref" : "AWS::Region" }, "AMIID" ] },
        "SecurityGroups": [{"Ref": "AppInstanceSecurityGroup" }],
        "InstanceType": {"Ref": "AppInstanceType" },
        "IamInstanceProfile": {"Ref": "AppInstanceEC2InstanceProfile"},
        "KeyName": {"Ref": "SSHKey"},
        "UserData"       : { "Fn::Base64" : { "Fn::Join" : ["", [
          "Content-Type: multipart/mixed; boundary=\"=======6t461261365==\"\n",
          "MIME-Version: 1.0\n",
          "\n",
          "--=======6t461261365==\n",
          "Content-Type: text/x-shellscript; charset=\"us-ascii\"\n",
          "Content-Disposition: attachment; filename=\"cfn-setup.sh\"\n",
          "\n",
          "#!/bin/bash\n",
          "set -o errexit; set -o nounset; set -o pipefail\n",
          "# Install AWS cfn-bootstrap utilities\n",
          "apt-get update\n",
          "apt-get -y install python-pip\n",
          "pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n",
          "cp /usr/local/init/ubuntu/cfn-hup /etc/init.d/cfn-hup \n",
          "chmod +x /etc/init.d/cfn-hup \n",
          "update-rc.d cfn-hup defaults \n ",
          "service cfn-hup start \n",
          
          "/usr/local/bin/cfn-init",
          " --stack ", { "Ref": "AWS::StackName" },
          " --resource AppInstanceConfiguration",
          " --region ", { "Ref": "AWS::Region" }, "\n",

          "/usr/local/bin/cfn-signal -e $? ",
          "         --stack ", { "Ref" : "AWS::StackName" },
          "         --resource AppInstanceAutoScalingGroup",
          "         --region ", { "Ref" : "AWS::Region" }, "\n",
          "\n",
          "--=======6t461261365==--\n"
          ]]}
        }
      }
    },

Works like a charm.

@gregmac
Copy link

gregmac commented Jul 4, 2017

I was struggling with systemd service config, and finally got this working:

  BastionHost:
    Type: AWS::EC2::Instance
    Metadata:
      AWS::CloudFormation::Init:
        configSets:
          default: 
          - config-cfn-hup
        config-cfn-hup:
          files:
            #cfn-hup configuration 
            '/etc/cfn/cfn-hup.conf':
              content: !Sub |
                [main]
                stack=${AWS::StackId}
                region=${AWS::Region}
                interval=1
            '/etc/cfn/hooks.d/cfn-auto-reloader.conf':
              content: !Sub |
                [cfn-auto-reloader-hook]
                triggers=post.update
                path=Resources.BastionHost.Metadata.AWS::CloudFormation::Init
                action=/usr/local/bin/cfn-init -v --stack ${AWS::StackId} --resource BastionHost --region ${AWS::Region}
            #systemd service 
            '/etc/systemd/system/cfn-hup.service': 
              content: |
                [Unit]
                Description=Cloud formation helper daemon

                [Service]
                ExecStart=/usr/local/bin/cfn-hup
                Restart=always
                RestartSec=10s
                Type=notify
                NotifyAccess=all
                TimeoutStartSec=120
                TimeoutStopSec=15

                [Install]
                WantedBy=multi-user.target

          commands: 
            enable-cfn-hup:
              command: "systemctl enable cfn-hup.service" 
            start-cfn-hup:
              command: "systemctl start cfn-hup.service" 
    Properties:
      UserData:
        Fn::Base64: !Sub |
          #!bin/bash -xe
          apt-get update 
          apt-get -y install python-setuptools
          easy_install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz
          
          /usr/local/bin/cfn-init -v --stack ${AWS::StackId} --resource BastionHost --region ${AWS::Region}
          /usr/local/bin/cfn-signal -e $? --stack ${AWS::StackId} --resource BastionHost --region ${AWS::Region}

cfn-init doesn't handle systemd at all, from what I can tell. This also means you can't use the services: section, you have to manually invoke systemctl.

@cosimo-dw
Copy link

It seems like cfn-hup does not send notify signal so the service description by @gregmac would never start successfully. The daemon will run of course but systemd thinks it is not ready and will try to restart it every 2 minutes (TimeoutStartSec). To fix this simply replace the content of /etc/systemd/system/cfn-hup.service as follows:

            #systemd service 
            '/etc/systemd/system/cfn-hup.service': 
              content: |
                [Unit]
                Description=Cloud formation helper daemon

                [Service]
                ExecStart=/usr/local/bin/cfn-hup
                Restart=always
                Type=simple

                [Install]
                WantedBy=multi-user.target

@ishu3101
Copy link

ishu3101 commented Sep 12, 2018

Another one taken from https://commscentral.net/tech/?post=50:

    "AppInstanceConfiguration": {
      "Type": "AWS::AutoScaling::LaunchConfiguration",
      "Metadata": {
        "AWS::CloudFormation::Init" : {
          "config" : {
            "files" : {

              "/etc/cfn/cfn-hup.conf" : {
                "content" : { "Fn::Join" : ["", [
                  "[main]\n",
                  "stack=", { "Ref" : "AWS::StackId" }, "\n",
                  "region=", { "Ref" : "AWS::Region" }, "\n"
                ]]},
                "mode"    : "000400",
                "owner"   : "root",
                "group"   : "root"
              },

              "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : {
                "content": { "Fn::Join" : ["", [
                  "[cfn-auto-reloader-hook]\n",
                  "triggers=post.update\n",
                  "path=Resources.AppInstanceConfiguration.Metadata.AWS::CloudFormation::Init\n",
                  "action=/usr/local/bin/cfn-init -v ",
                  "         --stack ", { "Ref" : "AWS::StackName" },
                  "         --resource AppInstanceConfiguration ",
                  "         --region ", { "Ref" : "AWS::Region" }, "\n",
                  "runas=root\n"
                ]]}
              }
            },

            "services" : {
              "sysvinit" : {
                "cfn-hup" : { "enabled" : "true", "ensureRunning" : "true",
                  "files" : ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"]}
              }
            }
          }
        }
      },
      "Properties": {
        "ImageId" : { "Fn::FindInMap" : [ "AWSRegionToUbuntuAMI", { "Ref" : "AWS::Region" }, "AMIID" ] },
        "SecurityGroups": [{"Ref": "AppInstanceSecurityGroup" }],
        "InstanceType": {"Ref": "AppInstanceType" },
        "IamInstanceProfile": {"Ref": "AppInstanceEC2InstanceProfile"},
        "KeyName": {"Ref": "SSHKey"},
        "UserData"       : { "Fn::Base64" : { "Fn::Join" : ["", [
          "Content-Type: multipart/mixed; boundary=\"=======6t461261365==\"\n",
          "MIME-Version: 1.0\n",
          "\n",
          "--=======6t461261365==\n",
          "Content-Type: text/x-shellscript; charset=\"us-ascii\"\n",
          "Content-Disposition: attachment; filename=\"cfn-setup.sh\"\n",
          "\n",
          "#!/bin/bash\n",
          "set -o errexit; set -o nounset; set -o pipefail\n",
          "# Install AWS cfn-bootstrap utilities\n",
          "apt-get update\n",
          "apt-get -y install python-pip\n",
          "pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n",
          "cp /usr/local/init/ubuntu/cfn-hup /etc/init.d/cfn-hup \n",
          "chmod +x /etc/init.d/cfn-hup \n",
          "update-rc.d cfn-hup defaults \n ",
          "service cfn-hup start \n",
          
          "/usr/local/bin/cfn-init",
          " --stack ", { "Ref": "AWS::StackName" },
          " --resource AppInstanceConfiguration",
          " --region ", { "Ref": "AWS::Region" }, "\n",

          "/usr/local/bin/cfn-signal -e $? ",
          "         --stack ", { "Ref" : "AWS::StackName" },
          "         --resource AppInstanceAutoScalingGroup",
          "         --region ", { "Ref" : "AWS::Region" }, "\n",
          "\n",
          "--=======6t461261365==--\n"
          ]]}
        }
      }
    },

Works like a charm.

What version of Ubuntu are you using? I tried it using Ubuntu 16.04 & 18.04 but I'm getting this error when I run the command:
$ update-rc.d cfn-hup defaults

Job for cfn-hup.service failed because the control process exited with error code.
See "systemctl status cfn-hup.service" and "journalctl -xe" for details.

$ systemctl status cfn-hup.service

● cfn-hup.service
   Loaded: loaded (/etc/init.d/cfn-hup; generated)
   Active: failed (Result: exit-code) since Wed 2018-09-12 04:53:00 UTC; 14s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 7468 ExecStart=/etc/init.d/cfn-hup start (code=exited, status=1/FAILURE)

Sep 12 04:52:59 ip-172-31-0-64 systemd[1]: Starting cfn-hup.service...
Sep 12 04:53:00 ip-172-31-0-64 systemd[1]: cfn-hup.service: Control process exited, code=exited status=1
Sep 12 04:53:00 ip-172-31-0-64 systemd[1]: cfn-hup.service: Failed with result 'exit-code'.
Sep 12 04:53:00 ip-172-31-0-64 systemd[1]: Failed to start cfn-hup.service.

@mmasko
Copy link

mmasko commented Jan 30, 2019

Got this working on Ubuntu 18. Some small changes. Thanks, everyone here for their notes. They were very helpful in figuring out what was going on. Here's a link. https://gist.github.com/mmasko/66d34b651642525c63cd39251e0c2a8b

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment