Note: This article has been duplicated from the previous article which uses Terraform and has been modified for Ansible.

AWS has introduced Lightsail (https://aws to compete with Digital Ocean, Linode, etc. for an inexpensive VPS (Virtual Private Server) offering.

In this article we will use Ansible (https://www NULL.ansible (Infrastructure as Code) to swiftly bring up an AWS Lightsail instance in us-east-1 on a dynamic IP and install docker/docker-compose on it.

We will use ‘myweb’ as an example in this article, using the same base path of ‘dev’ that was previously created, the container-admin group and using ~/.local/bin|lib for the binaries/libraries.

Please use ‘Get started with Lightsail for free’ (https://portal prior to commencing with this article.

Go in to the dev directory/link located within your home directory:

$ cd ~/dev

Upgrade the AWS CLI on your host:

$ pip3 install awscli --upgrade --user && chmod 754 ~/.local/bin/aws

Install/Upgrade Ansible:

$ pip3 install ansible --upgrade --user && chmod 754 ~/.local/bin/ansible ~/.local/bin/ansible-playbook

Install/Upgrade Boto3:

$ pip3 install boto3 --upgrade --user

Create a work folder and change in to it:

$ mkdir -p ansible/myweb/scripts && cd ansible/myweb

Add an IAM Policy to the container-admin group so it will have access to the Lightsail API:
AWS UI Console -> Services -> Security, Identity, & Compliance -> IAM -> Policies -> Create Policy -> JSON (replace <AWS ACCOUNT ID> in the Resource arn with your Account’s ID (shown under the top right drop-down (of your name) within the My Account page next to the Account Id: under Account Settings)):

     "Version": "2012-10-17",
     "Statement": [
             "Effect": "Allow",
             "Action": [
             "Resource": "*"         
             "Effect": "Allow",
             "Action": "lightsail:",
             "Resource": [
                 "arn:aws:lightsail::<AWS ACCOUNT ID>:StaticIp/*",
                 "arn:aws:lightsail::<AWS ACCOUNT ID>:ExportSnapshotRecord/*",
                 "arn:aws:lightsail::<AWS ACCOUNT ID>:Instance/*",
                 "arn:aws:lightsail::<AWS ACCOUNT ID>:CloudFormationStackRecord/*",
                 "arn:aws:lightsail::<AWS ACCOUNT ID>:RelationalDatabaseSnapshot/*",
                 "arn:aws:lightsail::<AWS ACCOUNT ID>:RelationalDatabase/*",
                 "arn:aws:lightsail::<AWS ACCOUNT ID>:InstanceSnapshot/*",
                 "arn:aws:lightsail::<AWS ACCOUNT ID>:Domain/*",
                 "arn:aws:lightsail::<AWS ACCOUNT ID>:LoadBalancer/*",
                 "arn:aws:lightsail::<AWS ACCOUNT ID>:KeyPair/*",
                 "arn:aws:lightsail::<AWS ACCOUNT ID>:Disk/*"

Review Policy ->

Name: AllowLightsail
Description: Allow access to Lightsail.

Create Policy.

Groups -> container-admin -> Attach Policy -> Search for AllowLightsail -> Attach Policy.

Generate an SSH Key Pair (no password) and restrict permissions on it:

$ ssh-keygen -q -t rsa -b 2048 -N '' -f ~/.ssh/myweb && chmod 400 ~/.ssh/myweb

Import the public key to Lightsail:

$ aws lightsail import-key-pair --key-pair-name myweb --public-key-base64 file://~/.ssh/

Create a hosts file and specify localhost:

$ cat << 'EOF' > hosts
> [local]
> localhost

Create a micro instance based off of Ubuntu 18_04 and reference an extraneous file for user_data (run once script on Virtual Machine boot):

$ cat << 'EOF' > lightsail.yml
> # Create a new AWS Lightsail instance, register the instance details and add a way to destroy it
> ---
> - hosts: local
>   connection: local
>   tasks:
>     - lightsail:
>         state: present
>         name:
>         region: us-east-1
>         zone: us-east-1a
>         blueprint_id: ubuntu_18_04
>         bundle_id: micro_2_0
>         key_pair_name: myweb
>         user_data: "{{ lookup('file', './scripts/') }}"
>         wait_timeout: 500
>       register: myweb
>     - debug: msg="Public IP is {{ myweb.instance.public_ip_address }} for {{ }}"
>       when: myweb.instance.public_ip_address is defined
>     - debug: msg="Run this playbook for {{ }} shortly to list the Public IP."
>       when: myweb.instance.public_ip_address is not defined
>     - lightsail:
>         state: absent
>         name:
>         region: us-east-1
>       tags: [ 'never', 'destroy' ]

Create the shell script for user_data:

$ cat << 'EOF' > scripts/
> #!/bin/bash
> MY_HOME="/home/ubuntu"
> export DEBIAN_FRONTEND=noninteractive
> # Install prereqs
> apt update
> apt install -y python3-pip apt-transport-https ca-certificates curl software-properties-common
> # Install docker
> curl -fsSL | apt-key add -
> add-apt-repository "deb [arch=amd64] $(lsb_release -cs) stable"
> apt update
> apt install -y docker-ce
> # Install docker-compose
> su ubuntu -c "mkdir -p $MY_HOME/.local/bin"
> su ubuntu -c "pip3 install docker-compose --upgrade --user && chmod 754 $MY_HOME/.local/bin/docker-compose"
> usermod -aG docker ubuntu
> # Add PATH
> printf "\nexport PATH=\$PATH:$MY_HOME/.local/bin\n" >> $MY_HOME/.bashrc
> exit 0

Run the playbook:

$ ansible-playbook -i hosts lightsail.yml

Log on to the instance (up to ~30 seconds may be needed for the attachment of the dynamic IP to the instance):

$ ssh -i ~/.ssh/myweb ubuntu@<The value of public_ip_address that was reported.  One can also re-run the playbook to print it again.>

Type yes and hit enter to accept.

On the host (a short while is needed for the run-once script to complete):

$ docker --version
$ docker-compose --version
$ logout

Tear down the instance:

$ ansible-playbook -i hosts lightsail.yml --tags "destroy"



ansible_myweb (https://github

« »