apt Package Upgrades & Requirements

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $10.00

The apt module is the key to getting so much stuff installed. But, it can do more than that. When we first boot our server from the Ubuntu image, what guarantees that our packages aren't completely out of date? Nothing! In fact, I bet a lot of packages are old and need upgrading.

Check out the apt module options. See update_cache? That's equivalent to running apt-get update, which downloads the latest package lists from the Ubuntu repositories. We definitely need that. Then after, to actually upgrade the packages, we can use the upgrade option.

update_cache: Updating the Repositories Cache

Head back to your playbook and add a new task to update the APT package manager repositories cache. Add become: true, use the apt module, and set update_cache to yes:

---
- hosts: vb
tasks:
- ping: ~
- name: Update APT package manager repositories cache
become: true
apt:
update_cache: yes
... lines 11 - 21

Remember, yes and true mean the same thing.

upgrade: Upgrading Packages

Cool! Copy that task to create the next one: upgrade the existing packages. Now, set upgrade to dist:

---
- hosts: vb
tasks:
- ping: ~
- name: Update APT package manager repositories cache
become: true
apt:
update_cache: yes
- name: Upgrade installed packages
become: true
apt:
upgrade: dist
... lines 16 - 21

There are a few possible values for upgrade - some upgrade more aggressively than others.

Find your terminal and run that playbook!

ansible-playbook ansible/playbook.yml -i ansible/hosts.ini

The first time you do this... it might take awhile - like several minutes. So go get some coffee and bother your co-workers. And it makes sense that it's slow: our server probably is out of date, so this is doing a lot of work. Thanks to the power of TV, we'll fast-forward.

Yes! The "Upgrade installed packages" task says "changed". It did upgrade some stuff!

Module Requirements: Installing Aptitude (if needed)

Head back to the docs: one of the other values for the upgrade option is safe, which I kind of like because it's a bit more conservative than dist. When we use safe, it uses aptitude, instead of apt-get. That's important, because not all Ubuntu images come with aptitude installed out-of-the-box.

In fact, scroll up a bit. The apt module has a "Requirements" section. Interesting... It says that the host - meaning the virtual machine in our case - needs python-apt, which our VM has, and aptitude to be installed for things to work. So far, we think of modules as standalone workers that take care of everything for us... and that's mostly true. But sometimes, modules have requirements. And it's up to us to make sure those requirements are met before using the module.

Open a new terminal tab and SSH into the VM with:

vagrant ssh

Let's see if aptitude is installed:

aptitude

It opens! So it is installed. Hit "q" to quit.

In this case, the requirement is already met out-of-the-box. But in other situations, in fact, in older versions of this Ubuntu image, you may need to add a task to install aptitude via the apt module.

But now, just set upgrade to safe:

---
- hosts: vb
tasks:
... lines 5 - 11
- name: Upgrade installed packages
become: true
apt:
upgrade: safe
... lines 16 - 21

Then, try the playbook again to make sure it's still happy!

ansible-playbook ansible/playbook.yml -i ansible/hosts.ini

It didn't make any changes... but it is still happy! We rock!

With repositories cache and packages upgraded, we can go crazy and install everything we need.

Installing git

So let's add a task to install the Git version control system: we'll use it to "deploy" our code. Like always, become: true, use the apt module, and use name: git:

---
- hosts: vb
tasks:
... lines 5 - 21
- name: Install Git VCS
become: true
apt:
name: git

I'll move this below cowsay - but the order between these doesn't matter.

Try this out:

ansible-playbook ansible/playbook.yml -i ansible/hosts.ini

It looks like it worked. How could we know? Move over to the terminal tab that's already SSH'ed into the VM. Run git --version. Yes!

Using state: latest

Back on the apt docs, there's an option called state with values latest, absent, present or build-dep. This shouldn't be surprising: this module is a lot smarter than simply running apt-get install: the module helps guarantee that a package is in a specific state, like "present" or "absent"... if you wanted to make sure that a package was not installed.

Add state to our task, set to latest:

---
- hosts: vb
tasks:
... lines 5 - 21
- name: Install Git VCS
become: true
apt:
name: git
state: latest

Now, instead of simply making sure that the package is present on the system, it will make sure that it's upgraded to the latest available version. This setting is a bit more aggressive - so do what's best for you.

Try the playbook again!

ansible-playbook ansible/playbook.yml -i ansible/hosts.ini

Ok, it didn't make any changes: git is already at the latest version... which makes sense... because we just installed it a minute ago. But in the future, when a new version comes out, our playbook will grab it.

Ok, let's get PHP 7 installed!

Leave a comment!

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
    },
    "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
    }
}