Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine


Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

We need to talk about 2 important words in Ansible: modules and hosts.

Ansible comes built with a ton of things called modules: small programs that do some work on the server. Most of the time, instead of saying:

Ansible! Execute this command!

you'll say:

Ansible! Execute this module and allow it to run whatever commands it needs to get its job done.

For example, if you want to install something on an Ubuntu server, instead of running sudo apt-get install php7.1, you'll use the apt module. Need to edit a file? There's a module for that too.

And when you execute a module, you'll of course always execute that module on one or more servers. These are called hosts. So, in Ansible language, we'll say:

I want to run this module on these hosts.

Running your First Module

Ok, terminology garbage done. Let's do something! The simplest way to execute a module is from the command line. ansible localhost means that - for now - we're going to run this module against our local machine. Then, -m command to run the "command" module - the simplest module in Ansible that allows you to... well... just run a command directly on the server. Then, add -a "/bin/echo 'Hello Ansible'" to pass that as an argument to the command module:

ansible localhost -m command -a "/bin/echo 'Hello Ansible'"

Try it! We see some output and... Hello Ansible! Congrats! You just ran your first module: command. In this case, we can even remove the -m option:

ansible localhost -a "/bin/echo 'Hello Ansible'"

The command module is so fundamental, it's the default module... if we don't pass one.

Hey! Let's try another module!

ansible localhost -m ping

You can probably guess what this does: ping is a small program that makes sure that we can contact the server.

What other modules can we use? Flip back to your browser and Google for "Ansible modules". They have a few pages, like "modules by category". But let's go to the full All Modules page.

Woh! If we're commanding a robot army, we just found out that a lot of our robots already know how to do a ton of stuff. Yes! This is all free functionality!

The composer Module

One of these modules should look pretty interesting to PHP developers: the composer module. Instead of executing Composer commands manually on the server, you can use this.

For example, back on the command line, if you setup your project like I did, then your vendor/ directory is populated with files. Let's kill them! Be reckless by running:

rm -rf vendor/

Now, take the composer module for a test drive:

ansible localhost -m composer

Woh! It fails!

Missing required arguments: working_dir.

The Ansible module documentation is pretty awesome: each page lists all of that module's options, their default value and whether or not they're required, like working_dir. And below, they usually have a bunch of really nice examples.

In this case, to pass the option, add -a "working_dir=./" to point to this directory, since the module will run on this machine. We also need to pass no_dev=false. That's just another option for this module - and we'll talk about what it does in a little while.

Ok, try that!

ansible localhost -m composer -a "working_dir=./ no_dev=false"

Woohoo! It looks like it's working! My terminal tab even shows the crazy things it's doing behind the scenes.


If it doesn't work on your machine, no big deal. This module requires you to have PHP and Composer installed. Soon, we'll guarantee that these are installed on a fresh Ubuntu machine.

Once it's done... boom! We see the full output of everything that happened.

The "changed" Status

AND, we see one really important thing: it says "changed true" and the output is yellow. The module detected that this command made a change to the server. Run the module again:

ansible localhost -m composer -a "working_dir=./ no_dev=false"

Woh! Now the output is green and it says "changed: false".

That is one of the most important superpowers of modules: not only do they make something happen on your server, they're able to detect whether or not the server changed by running the module. This will be important: later, we can trigger different actions based on whether or not a module did or did not actually make any changes.

But how the heck did Ansible know that the server didn't change the second time? That cleverness is actually built into each module. The composer module is smart enough to know that nothing changed based on the output of the command - the fact that it said:

Nothing to install or update

By the way, now that we're rocking Ansible, we could have cleared the vendor directory via the command module:

ansible localhost -a "rm -rf vendor/"

To prove that worked, run the composer module again:

ansible localhost -m composer -a "working_dir=./ no_dev=false"

Ha! Back to "changed: true" with yellow output.

Next, let's talk about how we organize which servers we're running Ansible against. Because obviously, we don't want to run against localhost forever!

Leave a comment!

Login or Register to join the conversation
Default user avatar
Default user avatar Karsten Frohwein | posted 5 years ago

Dear Ryan,

I believe there is a typo. The text states "bin/echo" and the video shows "/bin/echo".

Drove me a bit nuts because I thought you probably ment the symfony "bin/" folder but why "echo"?!?




Hey Karsten,

Woops, I missed it! Fixed in https://github.com/knpunive...

Thank you for letting us know,

Default user avatar
Default user avatar Karsten Frohwein | Victor | posted 5 years ago

Oh I can fork you on github? :D Good to know! Thanks!


Yep, you can! All our tutorials are public on GitHub so if you see a misprint - feel free to create a PR if you don't mind or just let us know in commends, open an issue on GitHub, email us, etc. It's a bit tricky for code blocks, because we use our internal tool for them, but misprints in text you can easily fix with PRs ;)

P.S. we have an "Edit on GitHub" button (a pencil icon in the right up corner of any chapter), so you don't need to look for the right repository and chapter on GitHub - it already refers to the proper page :)

Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial is built using an older version of Symfony, but the core concepts of Ansible are still valid. New versions of Ansible may contain some features that we don't use here.

What PHP libraries does this tutorial use?

// composer.json
    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.1.*", // v3.1.4
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.6.4
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.3.11
        "symfony/monolog-bundle": "^2.8", // 2.11.1
        "symfony/polyfill-apcu": "^1.0", // v1.2.0
        "sensio/distribution-bundle": "^5.0", // v5.0.12
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "doctrine/doctrine-migrations-bundle": "^1.2", // v1.2.0
        "snc/redis-bundle": "^2.0", // 2.0.0
        "predis/predis": "^1.1", // v1.1.1
        "composer/package-versions-deprecated": "^1.11" // 1.11.99
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.0.8
        "symfony/phpunit-bridge": "^3.0", // v3.1.4
        "doctrine/data-fixtures": "^1.1", // 1.3.3
        "hautelook/alice-bundle": "^1.3" // v1.4.1