Example Ansible Use Cases
Apply Harness IaCM Ansible integration to web fleets, database patching, multi-environment configuration, Kubernetes node bootstrap, and compliance hardening.
The scenarios below are patterns, not product clicks: they show how inventories, playbooks, and IACMAnsiblePlugin fit problems teams hit after they complete Get started with Ansible. Each use case explains when it applies, the moving parts, and a representative example so you can adapt the idea to your repositories and naming.
Go to Configuration management with Ansible to review the conceptual map first.
Use case 1: provision and configure a web server fleet
When this applies: Your compute tier is created by Terraform or OpenTofu (for example EC2 behind a load balancer), and you must install packages, deploy artifacts, and harden networking on those instances every time the fleet changes, without manual SSH.
You already use IaCM for the apply; the next stage is configuration that tracks infrastructure churn. A dynamic inventory linked to the same workspace keeps host lists aligned with state, and filters let you scope to a role such as webserver so databases are never touched by the web playbook.
Scenario: Your team uses Terraform to provision a fleet of EC2 instances behind an Application Load Balancer. After provisioning, you need to install and configure Nginx, deploy your application artifact, and enable the firewall, all without human intervention.
Setup
Configure the pattern in this order:
Create a dynamic inventory linked to the Terraform workspace that manages your EC2 fleet.
Add a filter to include only hosts where
tags.Rolecontainswebserver.Register a playbook stored at
playbooks/configure-web.ymlin your application repo.Add the
IACMAnsiblePluginstep immediately after theIACMTerraformPlugin(apply) step in your pipeline.
Playbook (configure-web.yml)
- name: Configure web servers
hosts: webservers
become: yes
vars:
app_version: "{{ lookup('env', 'APP_VERSION') }}"
app_artifact_url: "https://artifacts.example.com/app-{{ app_version }}.tar.gz"
tasks:
- name: Install Nginx
apt:
name: nginx
state: present
update_cache: yes
- name: Download and extract application artifact
unarchive:
src: "{{ app_artifact_url }}"
dest: /var/www/html
remote_src: yes
- name: Configure Nginx virtual host
template:
src: templates/nginx-vhost.conf.j2
dest: /etc/nginx/sites-available/app
notify: Reload Nginx
- name: Enable site
file:
src: /etc/nginx/sites-available/app
dest: /etc/nginx/sites-enabled/app
state: link
- name: Ensure Nginx is running
service:
name: nginx
state: started
enabled: yes
handlers:
- name: Reload Nginx
service:
name: nginx
state: reloadedResult: Every time the Terraform workspace provisions or replaces EC2 instances, the pipeline automatically configures them. Zero manual SSH sessions required.
Next steps for this pattern
Once this pattern is working, consider these follow-ups:
Refine filters so only the intended role receives the play (for example by tag or Name).
Add a smoke test stage after Ansible that hits the load balancer health check.
Go to Get started with Ansible to register inventories or the plugin step if you have not done so yet.
Use case 2: rolling OS patch across a database cluster
When this applies: You run a small, stateful cluster (for example PostgreSQL) where maintenance must happen one node at a time, with explicit ordering between replicas and primary. Static inventories mirror your known topology, and scheduled pipelines give predictable patch windows.
This pattern fits teams that value controlled blast radius over automatically discovered hosts; the playbook itself encodes order (serial, multiple plays) because orchestration is the hard part, not discovery.
Scenario: You maintain a three-node PostgreSQL cluster and need to apply monthly OS security patches with zero downtime. Hosts must be patched one at a time, with the primary gracefully relinquishing leadership before each patch cycle.
Setup
Configure the pattern in this order:
Create a static inventory with three groups:
primary,replica_1,replica_2.Register a playbook at
ops/rolling-patch.yml.Schedule a monthly pipeline run using a Harness pipeline trigger with a cron expression.
Playbook (rolling-patch.yml)
Result: Security patches are applied to each node in sequence, with the primary only patched after replicas are healthy. Full audit trail available in Harness pipeline logs.
Next steps for this pattern
Once this pattern is working, consider these follow-ups:
Add approval steps in front of the Ansible stage for production.
Capture pre- and post-patch health checks as small play sections or separate pipeline steps.
Go to Configuration management with Ansible to understand how static inventories fit the mental model.
Use case 3: Multi-environment configuration with variable overrides
When this applies: You want one playbook and different behavior per environment (dev, staging, prod) without forking YAML. Inventory-level variables in Harness carry environment truth; the playbook stays generic Jinja2.
Choose this when drift between environments is mostly configuration values, not different task sequences.
Scenario: You have three environments (dev, staging, and prod), each requiring different application configurations (log levels, database endpoints, feature flags). You want a single playbook that adapts based on the target environment, driven by inventory-level variables.
Setup
Configure the pattern in this order:
Create separate inventories for each environment with environment-specific variables set in each inventory's Variables tab.
Use a single playbook with Jinja2 variable references.
Create a pipeline per environment that selects the correct inventory.
Inventory variables (prod inventory)
log_level
string
error
db_host
string
prod-db.internal
db_port
string
5432
enable_feature_x
string
false
db_password
secret
<secret_ref>
Playbook (configure-app.yml)
Result: The same playbook handles all environments. Variable differences are managed through Harness inventory variables, keeping your playbook DRY and version-controlled.
Next steps for this pattern
Once this pattern is working, consider these follow-ups:
Name variables consistently across inventories so the same playbook never needs forked keys.
Document required keys in your playbook repo README and fail fast with explicit checks.
Go to Add inventory variables to review the product workflow for setting inventory variables.
Use case 4: bootstrap new Kubernetes worker nodes
When this applies: Terraform provisions Linux workers that must join a cluster before scheduling workloads. The dynamic inventory picks up new nodes from the provisioning workspace; Ansible installs runtime and runs kubeadm join (or your approved bootstrap path).
Use this when node bring-up is repeatable and you want it tied to the same pipeline that created the instance.
Scenario: Your platform team provisions new worker nodes via Terraform and needs to bootstrap them (install the container runtime, configure kubelet, and join them to the cluster) before the node is available to receive workloads.
Setup
Configure the pattern in this order:
Create a dynamic inventory linked to your node-provisioning Terraform workspace. Filter hosts by
role = worker.Store your bootstrap playbook in an ops repository.
Chain the Ansible step immediately after the Terraform apply step.
Playbook (bootstrap-worker.yml)
Result: New Kubernetes worker nodes are fully bootstrapped and joined to the cluster automatically within minutes of Terraform provisioning them, with no manual intervention from the platform team.
Next steps for this pattern
Once this pattern is working, consider these follow-ups:
Align Terraform outputs (for example API endpoint, labels) with variable names your playbook expects.
Add idempotency guards (such as
createson join) so reruns do not break joined nodes.Go to Get started with Ansible to review how to chain stages.
Use case 5: compliance hardening across all environments
When this applies: Security expects a baseline posture (for example CIS-style checks) on many Linux hosts on a schedule, with evidence in CI logs. Inventories can be broad dynamic sets or per-environment; the playbook encodes checks and remediations.
Scenario: Your security team requires all Linux hosts to conform to CIS Benchmark Level 1 hardening guidelines. You need to apply and verify hardening across hundreds of hosts, and surface any failures in the pipeline logs as a compliance record.
Setup
Configure the pattern in this order:
Create a dynamic inventory that spans all environments, or run separate pipelines per environment using environment-specific inventories.
Store your hardening playbook in a dedicated
securityrepository, versioned by release tag.Run the pipeline on a nightly schedule and collect the output as a compliance report.
Playbook (cis-hardening.yml, abbreviated)
Result: Compliance hardening is applied consistently across all hosts with every pipeline run. Any host that fails a task is flagged in the pipeline logs, giving your security team a clear audit trail.
Next steps for this pattern
Once this pattern is working, consider these follow-ups:
Treat the playbook as policy-as-code: tag releases and pin Harness to known Git refs.
Export or archive pipeline logs your auditors accept as evidence.
Expand coverage with profile-specific roles maintained by your security team.
Use case 6: manage SSH host key verification for dynamic or ephemeral hosts
When this applies: You are running Ansible against newly provisioned cloud instances, containers, or other short-lived hosts whose SSH fingerprints are not yet recorded on the delegate. SSH verifies a remote host's identity by checking its fingerprint against a known_hosts file on the machine initiating the connection. When a host is not in that file, SSH prompts the user to accept or reject the fingerprint. In automated pipelines there is no user to respond, so the run stalls or the connection fails.
This is especially common when running from a Harness delegate. The delegate is typically ephemeral: it starts with a clean environment and no existing known_hosts file. Target hosts provisioned in the same pipeline are also new, so every connection looks like a first-time attempt and triggers the authenticity prompt.
Scenario: Your pipeline provisions EC2 instances with Terraform and immediately runs Ansible against them. The delegate has no prior record of these hosts, so Ansible stalls at the SSH authenticity prompt and the playbook never starts.
Option a: disable strict host key checking
Add the following variable to your inventory or host variables:
This tells SSH to skip fingerprint verification and connect without prompting.
Disabling strict host key checking removes SSH-level protection against host spoofing. Use this only in private networks or controlled environments where that risk is managed at the network layer.
Option b: Pre-populate the known_hosts file
SSH trusts a host when its fingerprint already exists in ~/.ssh/known_hosts before the connection. Add a setup step before your Ansible stage to scan each target host and write its fingerprint:
For multiple hosts, iterate over the target list and run ssh-keyscan for each address. In automated environments this scan is typically a bootstrap or environment-prep step that runs before the Ansible stage, so all subsequent connections are trusted automatically. You can also connect to a host once manually and accept the fingerprint prompt to seed the file.
Result: Ansible connects to new or ephemeral hosts without blocking on fingerprint prompts, either by pre-loading fingerprints for strict SSH trust or by skipping verification in environments where network controls already limit that risk.
Next steps for this pattern
Once this pattern is working, consider these follow-ups:
For dynamic host sets, combine Option B with a step that reads host IPs from Terraform outputs and runs
ssh-keyscanacross the full list before the Ansible stage.Go to Add inventory variables to add
ansible_ssh_common_argsas an inventory variable.Go to Configuration management with Ansible to understand how inventory variables apply across hosts and host groups.
Use case 7: connect Windows hosts over WinRM
When this applies: You need to run Ansible against Windows hosts. SSH is the standard connection method for Linux, but Windows uses WinRM (Windows Remote Management) as its native remote management protocol. WinRM lets Ansible connect to Windows hosts to run commands, execute PowerShell, and apply configuration changes.
The Ansible plugin image already has WinRM support built in. Setup is primarily on the inventory and host variables side, and on the Windows host itself. The Windows machine needs WinRM enabled and listening, and the authentication method you choose must also be enabled on that host. By default, Windows commonly has NTLM and Kerberos available; methods like Basic or CredSSP may need extra configuration.
Scenario: Your team provisions Windows Server instances and needs to apply configuration via Ansible: install software, apply registry settings, or run PowerShell scripts. The hosts are not Linux, so SSH is not available and WinRM is the connection method.
Setup
Configure the pattern in this order:
Ensure WinRM is enabled and listening on each target Windows host. Run the following in PowerShell on the host:
Enable-PSRemoting -Force.In your Harness inventory, define these variables for each Windows host:
Store
ansible_passwordas a secret-type variable on the inventory Variables tab so it is masked in logs. Go to Add inventory variables to configure secret variables.
Variable reference
ansible_connection: winrm
Tells Ansible to use WinRM instead of SSH for this host.
ansible_port
5985 for HTTP, 5986 for HTTPS.
ansible_winrm_transport
Authentication method. ntlm is a practical starting point for local accounts.
ansible_winrm_server_cert_validation
ignore when using self-signed or untrusted HTTPS certificates. Use validate with a properly trusted certificate in production.
ansible_winrm_operation_timeout_sec
How long the remote WinRM operation is allowed to run before timing out.
ansible_winrm_read_timeout_sec
How long Ansible waits for the overall response. Setting this slightly higher than the operation timeout avoids read errors on slower operations.
Transport options for ansible_winrm_transport
The ansible_winrm_transport variable accepts these values:
ntlm: A practical default for many starter setups, works well for local accounts and straightforward Windows connectivity.kerberos: Recommended for domain environments. Current Ansible guidance recommends Kerberos over HTTP in domain setups.basic: Simple, but credentials are not adequately protected at the transport layer without HTTPS.credssp: Useful in delegated-auth or double-hop scenarios. Use only when necessary as it carries added security risk.certificate: Certificate-based authentication, less common for initial setup but supported.
A simple inventory example
For a first Windows setup: use winrm connection, ntlm transport, and port 5985 for HTTP. Set ansible_winrm_server_cert_validation: ignore while certificate validation is not yet configured. For domain-joined hosts, switch to kerberos over HTTP. For local accounts, ntlm or basic over HTTPS is the recommended route.
Result: Ansible connects to Windows hosts over WinRM and can run PowerShell, apply configuration, and manage software the same way it manages Linux hosts over SSH.
Next steps for this pattern
Once this pattern is working, consider these follow-ups:
Go to Get started with Ansible to register your Windows inventory and add host variables.
For domain environments, configure Kerberos on both the delegate and the target hosts before switching
ansible_winrm_transporttokerberos.Go to Configuration management with Ansible to understand how inventory variables and host groups work across mixed Linux and Windows targets.
Next steps
Continue with:
Go to Get started with Ansible to walk through inventory, playbook, and pipeline setup in the UI.
Go to Configuration management with Ansible to reinforce concepts and good practices.
Go to IaCM best practices to learn recommended patterns for structuring pipelines and workspaces at scale.
Last updated
Was this helpful?