<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Anarch157a's Blog (Posts about Cloud)</title><link>https://www.anarch157a.com/</link><description></description><atom:link href="https://www.anarch157a.com/categories/cat_cloud.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2026 &lt;a href="mailto:anarch+nospam@replace_this_by_the_blog_domain.com"&gt;Anarch157a&lt;/a&gt; 
&lt;a rel="license" href="https://creativecommons.org/licenses/by-nc-sa/4.0/"&gt;
&lt;img alt="Creative Commons License BY-NC-SA"
style="border-width:0; margin-bottom:12px;"
src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png"&gt;&lt;/a&gt;</copyright><lastBuildDate>Wed, 04 Nov 2026 20:27:21 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Running Ansible with AWS System Manager</title><link>https://www.anarch157a.com/posts/ssm-ansible/</link><dc:creator>Anarch157a</dc:creator><description>&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Ansible is a fantastic tool to automate tasks and manage fleets of servers&lt;/p&gt;
&lt;p&gt;Amazon SSM, or Systems Manager, also offers tools to manage your fleet of servers. One of the tools they offer is Session Manager, which allows you to run an interactive shell without having to open a TCP port to the world or dealing with SSH keys.&lt;/p&gt;
&lt;p&gt;Usualy, ansible uses SSH to connect and send payloads to the managed servers, if you're using only SSM to mange your instances, how can Ansible connect to them? Well, by using SSM itself to communicate and an S3 bucket to store the payload.&lt;/p&gt;
&lt;h5&gt;Debian/Ubuntu users beware&lt;/h5&gt;
&lt;p&gt;System Manager uses a small script to determine if the connection was sucessfull, by watching the results on Stdout/Stderr. Problem is, they specify &lt;code&gt;/bin/sh&lt;/code&gt; as the shell, only to use some Bash specific syntax on it. This is a problem for Debian based distributions, because by default, they symlink &lt;code&gt;/bin/sh&lt;/code&gt; to &lt;strong&gt;Dash&lt;/strong&gt;, instead of Bash. Since Dash doesn't support the Bashisms that AWS uses, it will return an error. The best way to fix this, is run a script using SSM to re-link &lt;code&gt;/bin/sh&lt;/code&gt; to Bash instead.&lt;/p&gt;
&lt;p&gt;As &lt;code&gt;root&lt;/code&gt;, run this script on all your Debian instances to change it:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dash dash/sh boolean false"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;debconf-set-selections
debconf-show&lt;span class="w"&gt; &lt;/span&gt;dash
&lt;span class="nv"&gt;DEBIAN_FRONTEND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;noninteractive&lt;span class="w"&gt; &lt;/span&gt;dpkg-reconfigure&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;critical&lt;span class="w"&gt; &lt;/span&gt;dash
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can do this from AWS SSM Control Pannel by selecting &lt;em&gt;Run Command&lt;/em&gt; under &lt;em&gt;Node Management&lt;/em&gt; and selecting &lt;em&gt;AWS-RunShellScript&lt;/em&gt; as the document. No need to spam &lt;code&gt;sudo&lt;/code&gt; on the script, this document runs the scripts as root by default.&lt;/p&gt;
&lt;p&gt;After that, all scripts that specify &lt;code&gt;/bin/sh&lt;/code&gt; as the interpreter will use Bash instead, which should not cause any more problems.&lt;/p&gt;
&lt;h4&gt;Preparation&lt;/h4&gt;
&lt;p&gt;To do that, we need to first make sure all the instances that will be managed can be accessed with SSM. All of them will need an IAM Role with SSM permissions, in addition to that, we need a S3 bucket that the instances can aread from too, so the IAM Role would also need at least read permission on the bucket. This can be acomplished by adding the appropriate permission to the IAM Role attached to the instances or with a Bucket Policy. Make those settings then test them by acessing an instance using SSM, the command for that is &lt;code&gt;aws ssm start-session --target &amp;lt;instance-id&amp;gt;&lt;/code&gt;, then use the AWS CLI tool to list the contents of the bucket with the command &lt;code&gt;aws s3 ls s3://ansible-bucket/&lt;/code&gt;. If we succeed with the connection and listing the Buclet, we're good to go.&lt;/p&gt;
&lt;h4&gt;Ansible Configuration&lt;/h4&gt;
&lt;p&gt;Using the AWS community modules for ANsible, it's possible to get a list of all your EC2 instances and use that as an inventory. To do that, we need to enable it on Ansible's configuration. We can do that by creating an &lt;code&gt;ansible.cfg&lt;/code&gt; on our playbook directory. Open the file and add the following lines:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;[inventory]&lt;/span&gt;
&lt;span class="na"&gt;enable_plugins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;aws_ec2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, let's create the inventory itself. Create an YAML file, like &lt;code&gt;ec2_inventory.yaml&lt;/code&gt; with this content:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nt"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;aws_ec2&lt;/span&gt;
&lt;span class="nt"&gt;regions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"us-east-1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# replace this with your region&lt;/span&gt;

&lt;span class="c1"&gt;# Example filters. Bring only running instances.&lt;/span&gt;
&lt;span class="c1"&gt;# The commented line show how to filter using a Tag&lt;/span&gt;
&lt;span class="nt"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;instance-state-name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;running&lt;/span&gt;
&lt;span class="c1"&gt;#  tag:OS_Type: Linux &lt;/span&gt;

&lt;span class="c1"&gt;# Example exclusion. We don't want instances running Windows Server&lt;/span&gt;
&lt;span class="nt"&gt;exclude_filters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;windows&lt;/span&gt;

&lt;span class="c1"&gt;# Building the inventory itself. This example will use the instance-id&lt;/span&gt;
&lt;span class="c1"&gt;# as Hostname. This is needed to use SSM as a cennection method.&lt;/span&gt;
&lt;span class="c1"&gt;# The keyed_groups key will generate groups based on platform details and&lt;/span&gt;
&lt;span class="c1"&gt;# Tags. This is optional.&lt;/span&gt;
&lt;span class="nt"&gt;hostnames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;instance-id&lt;/span&gt;
&lt;span class="nt"&gt;keyed_groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;platform&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;platform_details&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Tags&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tags&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, to test if our inventory is working, we use the command &lt;code&gt;ansible-inventory -i ec2_inventory.yaml --graph&lt;/code&gt;. The result should be a tree graph listing all our instances.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nt"&gt;@all&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;|--@Tags_Some_Tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;&lt;span class="err"&gt;  |--i-12345abcd&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;&lt;span class="err"&gt;  |--i-23456cdefg&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;|--@Tags_Another_Tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;&lt;span class="err"&gt;  |--i-567fghd&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;&lt;span class="err"&gt;  |--i-9875poi&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;&lt;span class="err"&gt;  |--i-4567kjb&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Running a Playbook&lt;/h4&gt;
&lt;p&gt;Now lets try running a simple Playbook that colelcts minimum facts and lists the content of &lt;code&gt;/etc/os-release&lt;/code&gt;. &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;SSM Playbook&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;all&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;gather_facts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# This is where we tell Ansible to connect using SSM&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ansible_connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;aws_ssm&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# The bucket that will be used to transfer the payload&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ansible_aws_ssm_bucket_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ansible-bucket&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# AWS Region where the instances are&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ansible_aws_ssm_region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;us-east-1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# This is why we should use the Instande-Id as hostname, so&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# we can pass it to the SSM module using Ansible's inventory_hostname variable&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ansible_aws_ssm_instance_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;inventory_hostname&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Collect Facts&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;ansible.builtin.setup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;gather_subset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'!all'&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'!min'&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Cat a file&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;register&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;os_release&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;ansible.builtin.shell&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;cat /etc/os-release&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Show the content of the file&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"os-release:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{os_release}}"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we just watch the output. If everything is correct, we should see the contents of &lt;code&gt;/etc/os-release&lt;/code&gt; from all our instances on the terminal.&lt;/p&gt;
&lt;p&gt;I hope this mini-guide helps. Any doubts or comments, hit me on Mastodon: @nerdeiro@fosstodon.org&lt;/p&gt;
&lt;p&gt;See you on the next one.&lt;/p&gt;</description><category>Ansible</category><category>AWS</category><category>Clous</category><category>SSM</category><guid>https://www.anarch157a.com/posts/ssm-ansible/</guid><pubDate>Mon, 12 Dec 2022 19:30:00 GMT</pubDate></item></channel></rss>