
Meet your instructor, Gourav Shah, a DevOps coach, corporate trainer, and author of Ansible Playbook Essentials. He has trained engineers at Cisco, Walmart Labs, Visa, and Intuit, and taught over 60,000 students across 160 countries. After this short intro you'll know who is guiding you and the 18 years of hands-on experience behind this step-by-step Ansible learning path.
Here you'll see how the course is laid out in three parts: theory first, then setting up your environment, then one topic at a time with demonstrations. You'll learn where to find the online lab guide and the supporting code repository so you never get stuck, plus how to use the practice activities and quizzes. After this you'll know exactly how to work through the lessons in the right order.
This course maps closely to the EX407 exam, the Red Hat Certified Specialist in Ansible Automation. You'll see how the course topics line up with the exam blueprint, which is fully practical, and you sit at a real environment and solve tasks. We compare the School of DevOps syllabus with Red Hat's official training side by side, so you'll know this course prepares you to pass EX407.
This is a self-paced course, so the first skill you'll build is reading the logs and working your way around errors on your own. When you get truly stuck, you'll know where to ask: our Gitter community channel where fellow learners and the instructor answer questions, plus the mailing lists and IRC channels for the technology you're learning. You'll leave knowing exactly how to get help and support.
Why do we need Ansible in the first place? You'll follow how infrastructure grew from a handful of servers to cloud and thousands of machines, and how operations teams moved from manual work to scripts to infrastructure-as-code tools. We look at the separate tools people use for ad-hoc management, configuration management like Puppet and Chef, deployment, and cloud provisioning, and you'll understand how Ansible combines all of these into one tool.
This lesson covers the first key feature of Ansible: simplicity. You'll learn why Ansible is simple to learn thanks to human-readable YAML, simple to set up because it is agentless and uses the push model over SSH with no agent on your managed nodes, and simple to extend since you can write custom modules in any language, even a shell script. After this you'll see why you don't need to know Python to use Ansible.
Ansible comes with batteries included, and those batteries are modules. You'll learn how modules let you manage system entities like users, packages, services, and files, and also provision cloud infrastructure, manage network devices, and integrate with tools like Docker, Kubernetes, and Jira. With 2000-plus modules built into the core and no plugins to install, you'll understand the range of infrastructure Ansible can handle out of the box.
This lesson explains infrastructure as code using a simple house-building analogy: scripts are procedural like a construction worker, while Ansible lets you be the architect who declares the desired state in YAML. You'll learn how declarative code differs from writing shell or Python scripts, and the real advantages you get: version control for your infrastructure, self-documented code, peer reviews, and even test-driven development for operations work.
Here you'll learn how Ansible separates code from data, which makes your code generic, reusable, and shareable across dev, staging, and production. Using an Apache example, you'll see how templating and variables let you keep one generic template instead of copying config files for every environment. This is what lets you package work as roles and pull ready-made roles from Ansible Galaxy instead of writing everything yourself.
This lesson explains idempotence, one of the most important Ansible properties, using a simple travel analogy about friends heading to the same destination by different routes. You'll learn how Ansible compares the current state with the desired state and only acts when there is a drift, choosing whether to run useradd, usermod, or passwd for you. After this you'll understand why running the same playbook again and again is safe.
Meet Michael DeHaan, the engineer who built Cobbler and Func, worked at Puppet Labs, then wrote Ansible in Python in 2012 to make configuration management both simpler and more powerful. You'll understand why Ansible went agentless and chose YAML, where the name came from, and how Red Hat's 2015 acquisition pushed it past Chef and Puppet in adoption. This context helps you see the design choices behind the tool before you touch it.
Ansible manages infrastructure at scale, so to practice it properly you need more than one machine. This short intro sets up what's coming: a lab environment with one Ansible control node and four managed nodes, built with Codespaces, our in-house tool. After this you'll know exactly what your practice setup looks like and why we need multiple nodes before writing any playbooks.
Setting up a DevOps lab usually means spinning up VMs for a control node plus several managed nodes, which eats RAM, CPU, and setup time. Codespaces packs a full multi-node environment into a single Docker-backed VM you can run on a laptop with as little as 2GB RAM, or on a cloud server. You'll understand how the control node and managed nodes map to real Ansible, Chef, or Puppet setups, and why this approach is cheaper and more consistent than Vagrant or bare-metal for learning.
Follow along to run the full Codespaces lab locally on Mac or Linux with Docker and Docker Compose. You'll clone the repo, run docker-compose up, and get an in-browser IDE on port 8000 with a terminal, file workspace, and six nodes including the Ansible controller. You'll also check out the chapter-by-chapter supporting code so you can catch up from any lecture. After this you can stand up your own practice environment in one command.
Prefer the cloud over a local Docker install? This shows you how to launch Codespaces on a DigitalOcean droplet in minutes. You'll pick a 2GB Ubuntu server, paste the user-data script that auto-installs Docker and pulls the Ansible Codespaces setup, then open the environment on port 8000. After this you can spin up a ready-to-use Ansible lab on any cloud, and you'll know where to grab the right startup script for Ansible, Chef, or Puppet.
Now that your lab is running, learn to operate it day to day. You'll move around the IDE, edit files and use the built-in terminals, and SSH into managed nodes as the devops user. Then you'll use docker-compose stop, start, and up to shut down or recreate the whole environment or a single node, and see how a Docker volume keeps your code safe across restarts. After this you can pause, resume, and reset your practice nodes without losing work.
This section moves from theory to the building blocks you actually write. You'll get an overview of the Ansible primitives used to automate infrastructure as code: playbooks, inventories, roles, and tasks. We'll also take a real use case and show how it maps into an Ansible code repository structure, so by the end you know where each piece of code belongs before the hands-on setup begins.
Starting from a three-tier app with a load balancer, you'll learn the top-down method for turning infrastructure into Ansible code. Begin with the desired end state, break it into per-application steps like install a package, create a user, drop a config, start a service, then map each step to an Ansible module and write it as a task in YAML. Finally you'll see how tasks plus their supporting files, templates, and defaults bundle into a role, with one role per application. After this you can decompose any app into tasks, modules, and roles.
You have roles per application, now learn to decide which role runs on which server. You'll build an inventory that lists your hosts, their connection details over SSH or WinRM, and groups them by category or environment. Then you'll write playbooks with plays that map host groups to roles and control sequencing. You'll also see why running different playbooks against the same nodes for config, deployment, and orchestration sets Ansible apart from Chef and Puppet.
A pointer to further reading: Gourav's book Ansible Playbook Essentials (published 2015) covers writing playbooks the right way, building modular code with roles, and applying best practices. It also digs into data-driven configuration with templates and variables, managing multiple environments, and zero-downtime rolling deployments. Use it to go deeper on playbook design once you've got the fundamentals from this course.
Where should your playbooks, roles, variables, and inventories actually live? This lecture walks through the two directory layouts from Ansible's own best practices documentation and shows you how to adapt them. You will learn where group_vars and host_vars belong, why a project-specific ansible.cfg helps, and how to keep environment-specific inventories separate so you can pick a layout that fits how your team works.
Meet the application you will automate through the rest of the course: a three-tier web app with an HAProxy load balancer, an app tier running on PHP and Apache, and a MySQL database backend. You will see the full picture of what needs configuring, how the tiers connect, and why the code must stay dynamic enough to run across dev, staging, and production. By the end you will understand the goal: separate playbooks for system setup, application install, and zero-downtime deployment.
Here you will design the actual code layout for the demo app. You will lay out environment-specific inventories for dev and prod, use group_vars to keep separate configuration profiles per environment, and create one role per application rather than per tier. You will also see how playbooks and a site.yml map which servers get which roles, and why keeping a project-level ansible.cfg under version control pays off when others clone your repo.
This short intro maps out the section ahead so you know where you are headed. You will get started with Ansible configuration, then define an inventory for your environment, validate connectivity, and run your first ad hoc commands against your nodes. You will also get a preview of host patterns for filtering which servers to target and a first look at Ansible modules before you move on to writing infrastructure as code.
Learn where Ansible looks for its configuration and how to override the defaults with your own project-specific ansible.cfg. You will use ansible --version and ansible-config to see which file is active, understand the precedence order from /etc/ansible up to the current directory, and create a custom config that sets your remote user, inventory path, and host key checking. After this you will know how to ship configuration inside your repo so anyone who clones it gets the same setup.
An inventory is just the list of servers Ansible manages, and here you will write your own from scratch in INI format. You will define hosts, group them into loadbalancer, app, and db groups, build a group of groups, and set connection parameters like ansible_user and ansible_connection. You will also see the difference between static and dynamic inventories, then validate the whole thing by pinging every node with the ping module.
Targeting the right servers is a skill of its own, and this lecture covers the full range of host patterns: wildcards, groups joined with a colon, exclusions, intersections with ampersand, subscripts for ranges, and regular expressions. You will also use --limit and control parallelism with forks. Then you will run ad hoc commands with the command and shell modules, and see firsthand why non-idempotent shell commands push you toward proper modules.
Why bother with modules when you can just run raw commands? This lecture answers that by contrasting the procedural approach with declarative desired state configuration. You will understand how modules let you describe what you want (a user present, a package installed) and let Ansible decide the how, why there is a one-to-one mapping between modules and system entities, and how Ansible's batteries-included library covers packages, services, files, cloud, and networking out of the box.
Now you put modules to work. You will invoke a module from the command line with ansible -m, read the documentation with ansible-doc to find required options, and install a package with the yum module in a declarative way. Most importantly you will run it twice and watch the change status flip to false the second time, so idempotence stops being theory and becomes something you can see.
This is hands-on practice with the modules you will reach for every day. You will create a group and a user with specific gid and uid values using the group and user modules, then copy a file to your servers with the copy module, setting source, destination, and mode. Along the way you will use ansible-doc to pick the right module and learn why become matters for privileged tasks and what happens to file ownership when you skip it.
Most jobs have a dedicated Ansible module, but sometimes you need to run a raw command on the node. This lesson walks you through the command, shell, and raw modules and shows when each one fits. You'll see why command can't use pipes or redirects while shell can, and why raw bypasses the Python module subsystem. You'll also learn to make these commands idempotent with the creates option, so a play stays safe to run again and again.
The ansible-console utility gives you an interactive shell to talk to your inventory nodes directly. You'll launch it with the become option for privileged commands, list available modules with a question mark, and run modules like command and yum against a whole group of servers at once. After this you'll be able to target a host pattern, install packages, and test modules live before you put them into a playbook.
Ad hoc commands are handy for quick one-off tasks, but the real power shows up when you define your infrastructure as code. This section starts your move into Ansible playbooks. You'll pick up the YAML basics, learn how a playbook is built and what fields it uses, write a few plays for system configuration, and run them with the ansible-playbook utility for syntax checking, dry runs, and applying changes.
Ansible describes the state of your infrastructure in YAML, so half an hour here saves you a lot of trouble later. You'll learn lists, dictionaries, key-value pairs, and why indentation matters so much, plus the line-folding styles using the greater-than and pipe symbols. Using a funny shopping-list example, you'll write your first YAML file and see how declarative syntax works. After this you'll be able to read and write the YAML that every playbook is built from.
A playbook is a collection of plays, and each play maps a set of hosts to the tasks you want to run on them. This lesson breaks down that structure: the name, the hosts pattern, the become options for privilege escalation, variables, and the tasks that call modules. You'll see the two ways to write a task and why the named, multi-line style makes your code self-documenting. After this you'll understand exactly how plays, hosts, tasks, and modules fit together before you write your own.
Time to write a real playbook for common system configuration across your Linux servers. You'll start from a problem statement and translate each step into a task: create an admin user with a specific UID, remove a user with state absent, and install packages with the yum and apt modules. Along the way you'll learn how to pick the right module from the docs and read its required options. By the end you'll have a working first playbook built from scratch.
Before you apply a playbook, you check it, and this lesson shows you how with the ansible-playbook utility. You'll run a syntax check and read the exit code, list hosts and tasks, add and filter with tags, and use check mode for a dry run that reports changes without making them. Then you'll apply the playbook, watch Ansible gather facts and converge to the desired state, and confirm idempotence when a second run reports zero changes.
Playbooks fail, and knowing how to read the failure is half the job. Here you'll add a service task, watch it fail because of a wrong service name, then connect to the node to find the real name and fix it. You'll also learn practical troubleshooting moves: set gather_facts to false to speed runs up, use the retry file with --limit to rerun only failed hosts, and use --step to walk through tasks one at a time.
One playbook can hold more than one play, each targeting a different group. In this lesson you'll add a second play just for the app servers, at the correct indentation level, to create a deploy user and install git with the generic package module. You'll also get more control over execution using --start-at-task to skip ahead and --limit to restrict a full playbook run to only the app servers, then validate the result with ansible-console.
Put your playbook skills to work in a hands-on project: deploy a static HTML site to your load balancer. You'll add the Nginx repository with the right module, install Nginx and git, then use the git module to clone the app source into the web root. Because Ansible checks current state against desired state, the playbook stays safe to rerun. Finish it and you'll have an end-to-end playbook that provisions and deploys on both Ubuntu and CentOS.
Your playbooks grow long and messy once the infrastructure gets bigger and spans many environments. This section shows you how Ansible roles fix that by turning tasks into modular, reusable blocks you can build into a code library. You will learn how a role is structured, how tasks get invoked, and how notifications, handlers, and role best practices fit together.
A single playbook that holds every host, play, and task works fine until it climbs to hundreds or thousands of lines and stays tied to one environment. Here you will see why that approach is hard to share and reuse, and how splitting tasks into per-application roles keeps your playbook simple. After this you will understand the before-and-after: one Apache role, one base config role, code you can reuse across projects and organizations.
A role is a package with tasks at its core plus everything those tasks depend on. This lesson walks through the full scaffold Ansible gives you: tasks, defaults and vars for properties, files and templates for configuration, handlers for restarting services, tests, and meta for metadata like version, license, and dependencies. You will know what each directory holds and why you usually map one role to one application.
As you automate a three-tier setup, the repository itself needs a plan. This lesson covers the best practices for organizing Ansible code: partition the infrastructure into layers, create inventory groups and groups of groups, build one role per application, and write a play per inventory group. You will also see how a common role added as a dependency and a single site-wide playbook give you both broad and fine-grained control.
Instead of hand-building role directories, you can generate the whole scaffold with one command. This lesson introduces Ansible Galaxy, both as a repository of community-contributed, open-source roles you can pull for tools like Apache, and as the utility that runs ansible-galaxy init to create your role structure. You will learn to generate a scaffold offline, and to search and install roles from Galaxy for your own projects.
Time to build your first real role. You will generate an Apache scaffold with ansible-galaxy init using the offline flag, then write separate task files for installing the package with the yum module and starting the service with the service module. You will also see why splitting tasks into install and service files and pulling them together with import_tasks in main.yml gives you cleaner, fine-grained control over a role.
A role does nothing until a playbook maps it to your hosts. Here you will write a short playbook that targets the app servers, uses become for escalated privileges, and calls the Apache role instead of listing tasks directly. After running it with a syntax check and applying it, you will verify the result with an ad-hoc ansible command and by opening the running web server in a browser.
Your role installs and starts Apache, but it does not manage configuration yet. This lesson adds a config task that uses the copy module to push a .conf file from the role's files directory, setting owner, group, and mode. You will then wire up notifications and handlers so the service restarts only when the config actually changes, and see the difference between restarted and reloaded states.
Your app runs on PHP, so it needs its own role alongside Apache. You will scaffold a PHP role with Ansible Galaxy and install two packages in a single task using a loop with with_items instead of writing one task per package. You will also learn why loop variables must be quoted, how to notify the restart handler, and how to add the second role to the same app-server playbook.
Common setup that every server needs should not be called by hand each time. This lesson moves your system configuration into its own role and sets it as a dependency in Apache's meta file, so it runs automatically whenever Apache does. You will learn how nested roles and role dependencies work, and how a site.yml playbook that imports your other playbooks lets you configure everything in one go.
Time to put everything you learned about roles to the test. In this hands-on project you write an Ansible role to deploy the DevOps demo app the way real teams ship software, pulling a tagged release artifact into a versioned releases directory and pointing a symlink at the current version. You add the frontend role to your existing playbook, run it, and confirm the app page loads on the target servers. By the end you can package a release-based deployment as a reusable role.
Your roles work, but they are still static and hard to reuse across environments. This section fixes that with variables and Jinja2 templates so the same role can drive dev, staging, and production without copying files. You will see how to define variables in different places, how precedence decides which value wins, and how templating separates data from code. After this you can write flexible, shareable roles and pull ready-made ones from Ansible Galaxy.
Managing config by copying three versions of a file and stacking conditionals gets messy fast, and it kills the reusability that roles are meant to give you. Here you learn why templates matter: instead of many static files, you keep one Jinja2 template with placeholders and inject the real values at runtime through variables. This is the idea of separating data from code, templates and tasks on one side, variables and facts on the other. You will understand when to reach for a template over the copy module.
Ansible is written in Python, so it uses Jinja2 as its templating engine, the same way Puppet and Chef lean on ERB in the Ruby world. In this lesson you learn how a Jinja2 template mixes plain text with dynamic fragments, and the two tag styles that mark them: double curly braces for variable substitution and the percent tags for code like if statements and loops. You will know how to write a .j2 template file and where Ansible plugs in your values at runtime.
Variables can come from role defaults, group_vars, host_vars, the playbook, the inventory, or the command line with -e, so you need to know which one wins. This lesson walks the Ansible variable precedence chart and gives you a practical version that covers almost every real case. You also learn the difference between user-defined variables and facts, the system properties Ansible gathers automatically, and how to reference flat variables and dictionaries. After this you can decide where to define a variable so the right value applies per environment.
This is a guided tour through the official Ansible variables docs so the reference stops feeling overwhelming. You will learn what makes a valid variable name, how to define variables in inventory and playbooks, how to read multi-level dictionaries, and how to work with facts, including turning fact gathering off for speed and generating your own custom facts. You also meet fact caching, magic variables for reading another host's facts, registered variables, and variable scope. After this you can navigate the docs and pick the right mechanism for each job.
Right now the app version is hardcoded in three places, so a version bump means editing the role every time. In this lesson you move that value into a single variable in the role's defaults/main.yml and reference it from your tasks, so changing the deployed version happens in one spot. You apply it, then log into a web server to confirm the new release is live. You also see how facts gathered at runtime can be used just like your own variables.
Variables alone are not enough for full config files, so here you generate config.ini from a Jinja2 template. You define app environment, preferences, and database connection details as variables in the role defaults, build the .j2 template with placeholders, and add a task using the template module instead of copy. You set source, destination, owner, mode, and apply it, then check the rendered config and the app's preferences page. By the end you can manage any application config file as a processed template driven by variables.
Now you see variable precedence in action by defining the same properties from several places at once. First you switch hash_behaviour from replace to merge in ansible.cfg so overriding one key in a dictionary keeps the rest, and you verify it with ansible-config dump. Then you set values in group_vars for production, in host_vars, and in the playbook's vars, run the play, and watch which source wins on the rendered page. After this you can layer environment-specific config confidently and know exactly where each value comes from.
Ansible lets you capture a task's output and act on it. In this lesson you register the result of a command into a variable and inspect what it holds, the return code (rc), stdout, stderr, and changed status, using the debug module to print it. Then you drive a second task with a when condition based on that result, watching it run or skip as the value changes. After this you can build conditional execution that reacts to real output from your hosts.
Run the setup module straight from the command line to see the full system profile Ansible gathers about each host. You will learn to filter facts by property, use regular expressions like ansible_*_mb, pick specific subsets such as network or memory, and dump per-host facts to a tree. After this you can find any fact you need and reuse it as a variable inside your tasks and templates.
So far you have written every role from scratch. This short intro shows you a faster path: reusing roles other people have already written and shared on Ansible Galaxy. You will get a preview of how to pick a role, pull it in, pass your own variables, and save real time on your playbooks.
Walk through galaxy.ansible.com and learn how to browse, search, and judge community roles. You will see how star ratings, download counts, tags, and the README tell you whether a role fits, and why checking the GitHub repo for recent commits, Ansible version compatibility, and the license matters before you trust it. After this you can shortlist and pick a solid role for your own use.
Search Ansible Galaxy for an HAProxy role and pick a good one by download count, star rating, and CentOS/Enterprise Linux support. You will read the role variables to see what to override, study the example playbook, then open the GitHub repo to trace the tasks, templates, handlers, and registered variables. After this you will understand exactly how the role works before you apply it.
Install the HAProxy role with the ansible-galaxy install command and call it from a short playbook, no tasks of your own needed. You will learn where roles land by default, how to set a custom roles path, and how the role installs and configures HAProxy for you. By the end HAProxy is running on your load balancer, ready for the backend troubleshooting that comes next.
HAProxy is up but not forwarding traffic, so you will debug it end to end. You will define backend servers as a group_vars dictionary with their IPs and ports, fix a broken health check, and re-run the playbook to watch the config and service reload through handlers. After this HAProxy load balances across your application servers, and you will add the HAProxy socket needed for dynamic backends later.
Your turn to practice. Pick a Galaxy role that sets up a MySQL server and client on CentOS Enterprise Linux, set the root password securely, and create a database called devops_demo with a devops user that owns it. You will supply all values through group_vars for your production group and apply the role from a db playbook, without editing the role itself. Try it before the solution video.
Here is the worked solution for the MySQL nano project using a well-documented Galaxy role. You will search and shortlist by downloads, set the root password, define your database and user through group_vars, and add the bind address so MySQL listens beyond localhost. You will also fix a deprecated include and confirm the service is running. By the end you have a configured MySQL database in minutes.
Point your application at the MySQL server you just built. You will override the role's default connection variables with your real database name, user, password, and DB host, all applied through the config template you already manage. After running the playbook the config file updates and the app connects successfully, giving you a working link between your app tier and database tier.
As a best practice you will move your installed Galaxy roles into the project repo so they ship alongside your own code. You will set a custom roles_path in ansible.cfg, reinstall HAProxy and MySQL roles there, and call everything from a site.yml wide playbook. Along the way you will fix a YAML typo and correct the roles_path config syntax so the full stack runs cleanly.
Ansible tags let you run only the parts of a playbook you care about. You'll tag tasks, roles, plays, and imported playbooks, then use --tags, --skip-tags, and --list-tags to pick or skip exactly what runs. You'll also see how tags get inherited, so a tag on a role or play flows down to every task inside it. After this you can target one config or install step without running the whole playbook.
Ansible: Mastering Infrastructure Automation
Embark on a journey to master the art of infrastructure automation with Ansible, the powerhouse tool that seamlessly blends simplicity and sophistication. In the ever-evolving world of IT Infrastructure Management, Ansible is poised to become the gold standard, and this course is designed to help you harness its full potential.
Ansible's core principle of simplicity is reflected in its thoughtful design choices, including an agentless setup, small footprint, push model, and the use of YAML as a language to define infrastructure state. Its ease of setup, code writing, and extensibility through custom modules makes it an ideal choice for IT professionals. Whether you're a systems administrator, network engineer, or DevOps practitioner, Ansible offers a comprehensive solution to streamline your infrastructure management tasks.
With Ansible, you can effortlessly manage systems at scale, execute ad-hoc tasks on a group of servers, automate systems and application configurations, perform change management, orchestrate application deployments, provision cloud servers, and even manage network and storage devices. This course is designed to help you master Ansible one step at a time, starting from the fundamental concepts of Infrastructure as Code and Idempotence, and progressing to more advanced topics.
Throughout this course, you'll dive into real-world use cases and gain hands-on experience with Ansible. You'll learn how to set up an inventory of servers and configure Ansible to manage them efficiently. You'll write playbooks for base systems configuration, create roles for automating web server provisioning and configurations, and leverage Galaxy roles to set up a load balancer. You'll also explore how to customize roles using group_vars to define your database and application configurations, secure sensitive information with Ansible Vault, and deploy applications in a rolling manner with zero downtime.
By the end of this course, you'll have a deep understanding of Ansible's primitives and be well-equipped to automate servers, applications, and infrastructure management tasks. You'll gain the skills and confidence to tackle complex automation scenarios and streamline your IT operations.
Don't miss this opportunity to unlock the full potential of Ansible and revolutionize your approach to infrastructure automation. Join us on this transformative learning journey and empower yourself with the tools and knowledge to excel in the world of IT Infrastructure Management.
Enroll now in "Ansible: Mastering Infrastructure Automation" and take your automation skills to new heights!