AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible AWS: Complete Guide to Cloud Automation (2026)

By Luca Berton · Published 2026-04-03 · Category: installation

Complete guide to automating AWS with Ansible. Manage EC2, S3, IAM, VPC, RDS, and Lambda with amazon.aws collection and practical examples.

Ansible's amazon.aws and community.aws collections let you automate your entire AWS infrastructure — from EC2 instances to S3 buckets to RDS databases.

Setup

# Install collections
ansible-galaxy collection install amazon.aws
ansible-galaxy collection install community.aws

# Python requirements
pip install boto3 botocore

Authentication

# Method 1: Environment variables
# export AWS_ACCESS_KEY_ID='your-key'
# export AWS_SECRET_ACCESS_KEY='your-secret'
# export AWS_REGION='us-east-1'

# Method 2: In playbook (use vault!)
- hosts: localhost
  vars:
    aws_access_key: "{{ vault_aws_key }}"
    aws_secret_key: "{{ vault_aws_secret }}"
  environment:
    AWS_ACCESS_KEY_ID: "{{ aws_access_key }}"
    AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}"
    AWS_REGION: us-east-1

# Method 3: AWS CLI profile
# ~/.aws/credentials configured, use profile parameter

See also: Ansible for AWS: Complete Guide to Cloud Automation with EC2, S3, RDS, and More

EC2 Instances

Launch an EC2 instance

- name: Launch EC2 instance
  amazon.aws.ec2_instance:
    name: web-server-01
    instance_type: t3.medium
    image_id: ami-0abcdef1234567890
    key_name: my-keypair
    security_groups:
      - web-sg
    vpc_subnet_id: subnet-12345678
    network:
      assign_public_ip: true
    volumes:
      - device_name: /dev/sda1
        ebs:
          volume_size: 50
          volume_type: gp3
    tags:
      Environment: production
      Role: webserver
    state: running
  register: ec2

- name: Show instance IP
  debug:
    msg: "Instance IP: {{ ec2.instances[0].public_ip_address }}"

Stop/Terminate instances

- name: Stop instances by tag
  amazon.aws.ec2_instance:
    filters:
      "tag:Environment": staging
    state: stopped

- name: Terminate instance
  amazon.aws.ec2_instance:
    instance_ids:
      - i-1234567890abcdef0
    state: terminated

Security Groups

- name: Create security group
  amazon.aws.ec2_security_group:
    name: web-sg
    description: Web server security group
    vpc_id: vpc-12345678
    rules:
      - proto: tcp
        ports: [80, 443]
        cidr_ip: 0.0.0.0/0
        rule_desc: HTTP/HTTPS
      - proto: tcp
        ports: [22]
        cidr_ip: 10.0.0.0/8
        rule_desc: SSH from internal
    rules_egress:
      - proto: all
        cidr_ip: 0.0.0.0/0
    tags:
      Name: web-sg

See also: Ansible Troubleshooting: Resolving community.aws.ec2_instance Issues

S3 Buckets

- name: Create S3 bucket
  amazon.aws.s3_bucket:
    name: my-app-assets-{{ aws_account_id }}
    versioning: true
    encryption: AES256
    public_access:
      block_public_acls: true
      block_public_policy: true
    tags:
      Environment: production

- name: Upload file to S3
  amazon.aws.s3_object:
    bucket: my-app-assets
    object: configs/app.yml
    src: /opt/app/config.yml
    mode: put

- name: Download from S3
  amazon.aws.s3_object:
    bucket: my-app-assets
    object: configs/app.yml
    dest: /opt/app/config.yml
    mode: get

- name: Sync directory to S3
  community.aws.s3_sync:
    bucket: my-website
    file_root: /opt/website/public
    permission: public-read

VPC Networking

- name: Create VPC
  amazon.aws.ec2_vpc_net:
    name: app-vpc
    cidr_block: 10.0.0.0/16
    region: us-east-1
    tags:
      Environment: production
  register: vpc

- name: Create public subnet
  amazon.aws.ec2_vpc_subnet:
    vpc_id: "{{ vpc.vpc.id }}"
    cidr: 10.0.1.0/24
    az: us-east-1a
    tags:
      Name: public-subnet-1a
  register: public_subnet

- name: Create Internet Gateway
  amazon.aws.ec2_vpc_igw:
    vpc_id: "{{ vpc.vpc.id }}"
    tags:
      Name: app-igw
  register: igw

See also: Ansible S3 Module: Upload, Download, Manage AWS S3 Objects (Complete Guide)

RDS Databases

- name: Create RDS PostgreSQL instance
  community.aws.rds_instance:
    db_instance_identifier: myapp-db
    engine: postgres
    engine_version: "16.1"
    db_instance_class: db.t3.medium
    allocated_storage: 100
    master_username: admin
    master_user_password: "{{ vault_rds_password }}"
    vpc_security_group_ids:
      - sg-12345678
    db_subnet_group_name: my-db-subnet-group
    backup_retention_period: 7
    multi_az: true
    tags:
      Environment: production

Dynamic Inventory

# inventory/aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
  - us-east-1
filters:
  tag:managed_by: ansible
keyed_groups:
  - key: tags.Role
    prefix: role
  - key: tags.Environment
    prefix: env
compose:
  ansible_host: public_ip_address
ansible-inventory -i inventory/aws_ec2.yml --graph

Complete Example: Web Application Stack

- name: Deploy AWS web stack
  hosts: localhost
  connection: local
  tasks:
    - name: Create VPC and networking
      include_tasks: tasks/networking.yml

    - name: Create RDS database
      include_tasks: tasks/database.yml

    - name: Launch web servers
      amazon.aws.ec2_instance:
        name: "web-{{ item }}"
        instance_type: t3.medium
        image_id: "{{ ami_id }}"
        key_name: deploy-key
        security_groups: ["{{ web_sg.group_id }}"]
        vpc_subnet_id: "{{ public_subnet.subnet.id }}"
        user_data: "{{ lookup('file', 'userdata.sh') }}"
        count: 1
        tags:
          Role: webserver
          Environment: production
      loop: "{{ range(1, 4) | list }}"

FAQ

Should I use Ansible or Terraform for AWS?

Use both: Terraform for infrastructure provisioning (VPCs, subnets, RDS), Ansible for configuration management (installing software, deploying apps). They complement each other.

How do I handle AWS credentials securely?

Use IAM roles for EC2 instances (no credentials needed), AWS SSO profiles, or Ansible Vault for encrypted credentials. Never put keys in plaintext.

Can Ansible replace CloudFormation?

For many use cases, yes. Ansible's AWS modules cover most services. CloudFormation has better drift detection and rollback. Choose based on your team's workflow.

Setup

# Install AWS collection
ansible-galaxy collection install amazon.aws

# Install Python dependencies
pip install boto3 botocore

# Configure credentials
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=us-east-1

Launch EC2 Instance

- name: Launch EC2
  amazon.aws.ec2_instance:
    name: web-server
    instance_type: t3.micro
    image_id: ami-0c55b159cbfafe1f0
    key_name: deploy-key
    security_groups: [web-sg]
    subnet_id: subnet-abc123
    state: running
    tags:
      Environment: production
      Team: web
    wait: true
  register: ec2

S3 Bucket

- amazon.aws.s3_bucket:
    name: my-app-backups
    versioning: true
    tags:
      Environment: production

- amazon.aws.s3_object:
    bucket: my-app-backups
    object: backups/db-backup.sql
    src: /tmp/db-backup.sql
    mode: put

VPC and Networking

- amazon.aws.ec2_vpc_net:
    name: my-vpc
    cidr_block: 10.0.0.0/16
    tags: { Name: my-vpc }
  register: vpc

- amazon.aws.ec2_vpc_subnet:
    vpc_id: "{{ vpc.vpc.id }}"
    cidr: 10.0.1.0/24
    az: us-east-1a
    tags: { Name: public-subnet }
  register: subnet

- amazon.aws.ec2_security_group:
    name: web-sg
    description: Web server SG
    vpc_id: "{{ vpc.vpc.id }}"
    rules:
      - proto: tcp
        ports: [80, 443]
        cidr_ip: 0.0.0.0/0
      - proto: tcp
        ports: [22]
        cidr_ip: 10.0.0.0/8

RDS Database

- amazon.aws.rds_instance:
    db_instance_identifier: myapp-db
    engine: postgres
    engine_version: "16.2"
    db_instance_class: db.t3.micro
    allocated_storage: 20
    master_username: admin
    master_user_password: "{{ vault_db_password }}"
    vpc_security_group_ids: ["{{ sg.group_id }}"]
    tags: { Environment: production }

Dynamic Inventory

# aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
  - us-east-1
keyed_groups:
  - key: tags.Environment
    prefix: env
  - key: instance_type
    prefix: type
filters:
  instance-state-name: running
ansible-inventory -i aws_ec2.yml --list
ansible -i aws_ec2.yml env_production -m ping

Key Modules

ModulePurpose
ec2_instanceManage EC2 instances
s3_bucketS3 buckets
s3_objectS3 files
ec2_vpc_netVPCs
ec2_vpc_subnetSubnets
ec2_security_groupSecurity groups
rds_instanceRDS databases
iam_roleIAM roles
route53DNS records
elb_application_lbALB

FAQ

Ansible vs Terraform for AWS?

Terraform is purpose-built for AWS infrastructure with state management. Ansible can provision AWS resources but excels at post-provisioning configuration. Many teams use both.

How do I authenticate?

Environment variables (AWS_ACCESS_KEY_ID), IAM instance profiles, ~/.aws/credentials, or aws_access_key/aws_secret_key in tasks.

Can I manage multiple AWS accounts?

Yes — use profile parameter or set credentials per task/play.

Install Collection

ansible-galaxy collection install amazon.aws
pip install boto3 botocore

Configure Credentials

# Option 1: Environment variables
# export AWS_ACCESS_KEY_ID=AKIA...
# export AWS_SECRET_ACCESS_KEY=...

# Option 2: In playbook
- hosts: localhost
  vars:
    aws_access_key: "{{ vault_aws_key }}"
    aws_secret_key: "{{ vault_aws_secret }}"
    region: us-east-1

Launch EC2 Instance

- amazon.aws.ec2_instance:
    name: web-server-1
    instance_type: t3.medium
    image_id: ami-0c55b159cbfafe1f0
    key_name: my-keypair
    security_group: web-sg
    subnet_id: subnet-abc123
    network:
      assign_public_ip: true
    tags:
      Environment: production
      Role: webserver
    state: running
  register: ec2

Manage S3

# Create bucket
- amazon.aws.s3_bucket:
    name: my-app-backups
    state: present
    versioning: true
    encryption: AES256

# Upload file
- amazon.aws.s3_object:
    bucket: my-app-backups
    object: backups/db-2026-04-07.sql.gz
    src: /tmp/db-backup.sql.gz
    mode: put

Create VPC

- amazon.aws.ec2_vpc_net:
    name: my-vpc
    cidr_block: 10.0.0.0/16
    region: us-east-1
    tags: { Environment: production }
  register: vpc

- amazon.aws.ec2_vpc_subnet:
    vpc_id: "{{ vpc.vpc.id }}"
    cidr: 10.0.1.0/24
    az: us-east-1a
    tags: { Name: public-subnet }
  register: subnet

Security Groups

- amazon.aws.ec2_security_group:
    name: web-sg
    description: Web server security group
    vpc_id: "{{ vpc.vpc.id }}"
    rules:
      - proto: tcp
        ports: [80, 443]
        cidr_ip: 0.0.0.0/0
      - proto: tcp
        ports: [22]
        cidr_ip: 10.0.0.0/8
    rules_egress:
      - proto: all
        cidr_ip: 0.0.0.0/0

Dynamic Inventory

# aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
  - us-east-1
filters:
  tag:Environment: production
keyed_groups:
  - key: tags.Role
    prefix: role
compose:
  ansible_host: public_ip_address
ansible-inventory -i aws_ec2.yml --graph

RDS Database

- amazon.aws.rds_instance:
    db_instance_identifier: my-postgres
    engine: postgres
    engine_version: "16.2"
    db_instance_class: db.t3.medium
    allocated_storage: 50
    master_username: admin
    master_user_password: "{{ vault_rds_password }}"
    vpc_security_group_ids: ["{{ db_sg.group_id }}"]
    state: present
  no_log: true

IAM

- amazon.aws.iam_user:
    name: deploy-bot
    state: present

- amazon.aws.iam_policy:
    iam_type: user
    iam_name: deploy-bot
    policy_name: s3-access
    policy_json: |
      {
        "Version": "2012-10-17",
        "Statement": [{
          "Effect": "Allow",
          "Action": "s3:*",
          "Resource": "arn:aws:s3:::my-app-*"
        }]
      }

FAQ

Do I need boto3?

Yes — all amazon.aws modules require boto3 and botocore Python packages on the controller.

How to use IAM roles instead of keys?

On EC2 instances with an IAM role, boto3 auto-discovers credentials. No access keys needed.

Can I manage multiple regions?

Yes — set region per task or use dynamic inventory with multiple regions.

Install Collection

ansible-galaxy collection install amazon.aws
pip install boto3 botocore

Authentication

# Environment variables (recommended)
# export AWS_ACCESS_KEY_ID=AKIA...
# export AWS_SECRET_ACCESS_KEY=...
# export AWS_DEFAULT_REGION=us-east-1

# Or in playbook
- hosts: localhost
  vars:
    aws_access_key: "{{ vault_aws_key }}"
    aws_secret_key: "{{ vault_aws_secret }}"
    region: us-east-1

EC2 Instance

- amazon.aws.ec2_instance:
    name: web-server
    instance_type: t3.micro
    image_id: ami-0abcdef1234567890
    key_name: my-keypair
    security_group: web-sg
    subnet_id: subnet-12345
    state: running
    tags:
      Environment: production
      App: mywebapp
  register: ec2

S3 Bucket

- amazon.aws.s3_bucket:
    name: my-app-assets
    state: present
    versioning: true
    tags:
      Environment: production

- amazon.aws.s3_object:
    bucket: my-app-assets
    object: config/app.conf
    src: files/app.conf
    mode: put

Security Group

- amazon.aws.ec2_security_group:
    name: web-sg
    description: Web server security group
    rules:
      - proto: tcp
        ports: [80, 443]
        cidr_ip: 0.0.0.0/0
      - proto: tcp
        ports: [22]
        cidr_ip: 10.0.0.0/8

VPC

- amazon.aws.ec2_vpc_net:
    name: my-vpc
    cidr_block: 10.0.0.0/16
    tags:
      Environment: production
  register: vpc

- amazon.aws.ec2_vpc_subnet:
    vpc_id: "{{ vpc.vpc.id }}"
    cidr: 10.0.1.0/24
    az: us-east-1a
    tags:
      Name: public-subnet

IAM User

- amazon.aws.iam_user:
    name: deploy-user
    state: present
    managed_policies:
      - arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

Dynamic Inventory

# aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
  - us-east-1
keyed_groups:
  - key: tags.Environment
    prefix: env
  - key: instance_type
    prefix: type
filters:
  instance-state-name: running
compose:
  ansible_host: public_ip_address

FAQ

How to use AWS profiles?

Set AWS_PROFILE environment variable or profile parameter in modules.

Costs from Ansible runs?

Ansible API calls to AWS are free. Costs come from resources you create (EC2, S3, etc.).

amazon.aws vs community.aws?

amazon.aws is maintained by Red Hat (certified). community.aws has additional community-contributed modules.

Related: Ansible Database Automation

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home