{"id":51383,"date":"2025-08-07T05:55:39","date_gmt":"2025-08-07T05:55:39","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=51383"},"modified":"2025-08-07T09:40:47","modified_gmt":"2025-08-07T09:40:47","slug":"ansible-dynamic-ansible-inventory-script-for-aws-ec2-public-ips","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/ansible-dynamic-ansible-inventory-script-for-aws-ec2-public-ips\/","title":{"rendered":"Ansible: Dynamic Ansible Inventory Script for AWS EC2 Public IPs"},"content":{"rendered":"\n<p>Below is a <strong>simple dynamic inventory Bash script<\/strong> for Ansible that queries <strong>all EC2 instances in your AWS account<\/strong>, gets their <strong>public IPs<\/strong>, and outputs a valid Ansible inventory.<br>You just need the AWS CLI installed and properly configured (<code>aws configure<\/code>), and the script will work anywhere you have permissions.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Dynamic Ansible Inventory Script for AWS EC2 Public IPs<\/strong><\/h2>\n\n\n\n<p>Save this as <code>ec2_dynamic_inventory.sh<\/code> and make it executable (<code>chmod +x ec2_dynamic_inventory.sh<\/code>).<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">#!\/bin\/bash<\/span>\n\n<span class=\"hljs-comment\"># Simple AWS EC2 Dynamic Inventory for Ansible (public IPs)<\/span>\n<span class=\"hljs-comment\"># Requirements: awscli, jq<\/span>\n\nREGION=<span class=\"hljs-string\">\"${AWS_REGION:-ap-south-1}\"<\/span>\n\nget_instances() {\n    aws ec2 describe-instances \\\n        --region <span class=\"hljs-string\">\"$REGION\"<\/span> \\\n        --filters <span class=\"hljs-string\">\"Name=instance-state-name,Values=running\"<\/span> \\\n        --query <span class=\"hljs-string\">'Reservations&#91;*].Instances&#91;*].{PublicIp:PublicIpAddress,Name:Tags&#91;?Key==`Name`]|&#91;0].Value,Id:InstanceId}'<\/span> \\\n        --output json\n}\n\n<span class=\"hljs-keyword\">if<\/span> &#91;&#91; <span class=\"hljs-string\">\"$1\"<\/span> == <span class=\"hljs-string\">\"--list\"<\/span> ]]; then\n    INSTANCES=$(get_instances)\n    HOSTS=$(<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"$INSTANCES\"<\/span> | jq -r <span class=\"hljs-string\">'.&#91;]&#91;] | select(.PublicIp != null) | .PublicIp'<\/span> | jq -R . | jq -s .)\n    cat &lt;&lt;EOF\n{\n  <span class=\"hljs-string\">\"aws_ec2_public\"<\/span>: {\n    <span class=\"hljs-string\">\"hosts\"<\/span>: $HOSTS\n  }\n}\nEOF\n    <span class=\"hljs-keyword\">exit<\/span> <span class=\"hljs-number\">0<\/span>\nelif &#91;&#91; <span class=\"hljs-string\">\"$1\"<\/span> == <span class=\"hljs-string\">\"--host\"<\/span> ]]; then\n    <span class=\"hljs-comment\"># Not needed for most use cases; required by Ansible interface.<\/span>\n    <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"{}\"<\/span>\n    <span class=\"hljs-keyword\">exit<\/span> <span class=\"hljs-number\">0<\/span>\n<span class=\"hljs-keyword\">else<\/span>\n    <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Usage: $0 --list|--host &lt;hostname&gt;\"<\/span>\n    <span class=\"hljs-keyword\">exit<\/span> <span class=\"hljs-number\">1<\/span>\nfi\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Usage<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Plain text for <code>-i .\/ec2_dynamic_inventory.sh<\/code>:<\/strong> <code>.\/ec2_dynamic_inventory.sh<\/code><\/li>\n\n\n\n<li><strong>JSON for <code>-i .\/ec2_dynamic_inventory.sh --list<\/code><\/strong> <em>(for Ansible dynamic inventory integration):<\/em> <code>.\/ec2_dynamic_inventory.sh --list<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Requirements<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Install the AWS CLI (<code>yum install awscli<\/code> or <code>pip install awscli<\/code>)<\/li>\n\n\n\n<li>Install <code>jq<\/code> (<code>yum install jq<\/code> or <code>apt install jq<\/code>)<\/li>\n\n\n\n<li>Run <code>aws configure<\/code> first, or ensure AWS credentials are available in your environment.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How It Works<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Lists all running EC2 instances with public IPs<\/strong> in your chosen AWS region.<\/li>\n\n\n\n<li>Outputs a group called <code>[aws_ec2_public]<\/code> with each instance\u2019s public IP as a host.<\/li>\n\n\n\n<li>Also supports <code>--list<\/code> for JSON output compatible with Ansible\u2019s dynamic inventory system.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Sample Output<\/strong><\/h2>\n\n\n\n<p><strong>Text (INI) output:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-attr\">&#91;aws_ec2_public]<\/span>\n13<span class=\"hljs-selector-class\">.233<\/span><span class=\"hljs-selector-class\">.139<\/span><span class=\"hljs-selector-class\">.133<\/span>\n3<span class=\"hljs-selector-class\">.7<\/span><span class=\"hljs-selector-class\">.218<\/span><span class=\"hljs-selector-class\">.154<\/span>\n...\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>JSON output for <code>--list<\/code>:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JSON \/ JSON with Comments\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json\">{\n  <span class=\"hljs-attr\">\"aws_ec2_public\"<\/span>: {\n    <span class=\"hljs-attr\">\"hosts\"<\/span>: &#91;\n      <span class=\"hljs-string\">\"13.233.139.133\"<\/span>,\n      <span class=\"hljs-string\">\"3.7.218.154\"<\/span>\n    ]\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON with Comments<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">json<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><strong>You can now use this script with Ansible:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">ansible -i .\/ec2_dynamic_inventory.sh all -m ping\n<\/code><\/span><\/pre>\n\n\n<p>or for playbooks:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">ansible-playbook -i .\/ec2_dynamic_inventory.sh myplaybook.yml\n<\/code><\/span><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Below is a simple dynamic inventory Bash script for Ansible that queries all EC2 instances in your AWS account, gets their public IPs, and outputs a valid Ansible inventory.You just&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[],"class_list":["post-51383","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/51383","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=51383"}],"version-history":[{"count":2,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/51383\/revisions"}],"predecessor-version":[{"id":51394,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/51383\/revisions\/51394"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=51383"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=51383"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=51383"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}