What are we going to do?
In this article, I’m going to show you how you can configure your Centos server to get its yum
updates from the ISO file that was used for installation. The advantage of using this method is that you don’t need an Internet connection to download the packages you need. This should be useful in places where Internet access is restricted, has low bandwidth, or no Internet at all.
I’m going to first show you the manual way of doing it, and then how we can use Ansible to automate the process and propagate it to even thousands of machines at the same time. So, let’s get started.
The traditional way
Step 1: mount your ISO file
Depending on how you installed Centos, this might be an ISO file or a DVD. In all cases, it should be mounted to a specific path. So, first let’s create that path:
sudo mkdir -p /mnt/dvd
Now, the following step is going to be different depending on your installation media:
If you used a physical DVD
You might need to unmount it first if it is already mounted so that you have a well-known mount directory:
sudo umount /dev/sr0
Where /dev/sr0
is the device that corresponds to your DVD device.
Now, mount the device to the directory we created earlier:
sudo mount -t iso9660 -o ro /dev/sr0 /mnt/dvd
If you are using an ISO file
If this is a virtual machine, you’re probably using an ISO file that was downloaded from Centos.org. In this case, you will need to first upload the file to your machine using a command like scp
, rsync
, sftp
or whatever method you prefer. Assuming that the the ISO file is located in /opt/CentOS-7-x86_64-DVD-1804.iso
, you can use the following command to mount it:
sudo mount -t iso9660 -o loop,ro /opt/CentOS-7-x86_64-DVD-1804.iso /mnt/dvd
Step 2: Create the repository
Creating a YUM repository is very simple. All what you need is make a new file in /etc/yum.repos.d
, choose a name for your repo and add some instructions that yum
will use to determine how it should use this repo to handle files.
Using your favorite editor (I’ll use vim
here), create the following file in /etc/yum.repos.d/local.repo
and add the following lines:
[local]
name=Local DVD repository
baseurl=file:///mnt/dvd
gpgcheck=0
enabled=1
Save your file.
Step 3: Test your repo
Your repository is ready now. You can test it by running the following yum
command:
yum install --disablerepo="*" --enablerepo="local" httpd
The above command will install Apache 2 (called httpd
in Centos and Red Hat repositories). Notice how we used the --disablerepo="*"
to disable all the configured repositories and --enablerepo="local"
to selectively enable our local
repository, the one that points to the ISO file or DVD.
The Ansible way
If you are not familiar with Ansible, you can have a look at the documentation, or you can enroll in my course: Beginning Ansible with Vagrant and Amazon AWS. The readers of this article can enjoy a 90% discount and have this course for only $10.99. Just use this code when you checkout: ZSAVE2018.
First things first, you need to ensure that Ansible is installed on your laptop (or the control machine). There is more than one way to install Ansible. I will use the OS package manager method here:
Centos/Red Hat client
sudo yum install -y ansible
Ubuntu/Debian
sudo apt install ansible -y
Test your installation by running ansible --version
, it should give you the currently-installed version of Ansible. At the time of writing this, Ansible is released under version 2.5.1
.
We also need to perform additional setup to ensure that Ansible can connect to the remote host(s) using public/private keys and use the sudo
command without needing a password. This is covered in detail in my course.
Step 1: the inventory file
The inventory file is the one that contains a list of one or more hosts that Ansible is made aware of when being executed. They can be placed in groups for easier management. The inventory file is placed by default under /etc/ansible/inventory
, however, it is possible to place your inventory file elsewhere as long as you point to it when executing the ansible-playbook
command. The good thing about this approach is that you can have all your Ansible files in one location. This makes it portable and can be further added to version control, which is a highly recommended practice.
So, create a new file called inventory
in the current directory and add the following:
[centos]
centos
We created a group called centos
and added the machine that we wanted to configure. You can use the DNS name or the IP address depending on the method you prefer to connect to your remote host.
Step 2: the playbook
The playbook is where you write the instructions that Ansible will use to bring your machine to the desired state. We’ll create a directory called playbooks
and place our playbook file inside it. We’ll also create a files
subdirectory where the CentOS-7-x86_64-DVD-1804.iso
file will be placed. Then, we can start editing our playbook (I called it local_repo.yaml
). The steps are demonstrated below:
mkdir -p playbooks/files
cd playbooks
mv /opt/CentOS-7-x86_64-DVD-1804.iso files/
vim local_repo.yaml
Let’s start adding our tasks:
Task 1: Uploading the ISO file
---
- hosts: centos
become: yes
vars:
- source_iso: "files/CentOS-7-x86_64-DVD-1804.iso"
- dest_iso: "/opt/CentOS-7-x86_64-DVD-1804.iso"
- repo_mount: "/mnt/dvd"
tasks:
- name: Upload the ISO file to the remote host
copy:
src: "{{ source_iso }}"
dest: "{{ dest_iso }}"
force: no
The first task uses Ansible’s copy module to upload the ISO file from the source directory on the control machine to the destination path on the remote host(s).
Notice that we needed to add some variables first to define the source and destination paths, and also the mount directory.
The force: no
attribute is used to enforce idempotence. This will ensure that the file will not be re-uploaded if it already exists.
Task 2: Mounting the ISO file
Now that our file is there, we need to mount it so that it can be later referenced in our repository file. Ad the following to the playbook:
- name: Mount the ISO file
mount:
path: "{{repo_mount}}"
src: "{{dest_iso}}"
fstype: iso9660
opts: loop,ro
state: mounted
The mount module is used to mount/unmount devices and configure the /etc/fstab
file accordingly. In our case, we are using it to mount our ISO file to the specified mount point.
Notice that the module will create the mount point directory if it does not already exist. So, this saved us an extra task where we would ensure that the mount point directory is created.
The fstype
corresponds to the -t
option in the mount
command, where you specify the filesystem type of the device to be mounted.
The opts
attribute allows you to add different mount options separated by commas, just like how you’d supply them to the mount command after the -o
command line option.
Finally, the state
attribute defines what are you intending to do with the mount point. In our case, we chose mounted
, which will both mount the device and add the appropriate fstab
entry to ensure that this mount point is activated on boot. It is worth mentioning that the present
choice will only configure the fstab
file without actually performing the mount operation.
Task 3: Creating the repository
Our final task will be to actually create the repository that uses our mounted ISO file as its source. We can create the repo file locally and use the copy
module again to upload it to the appropriate location, but Ansible has a module designed specifically for managing YUM repositories so let’s use it. Add the following to your playbook file:
- name: Add repository
yum_repository:
name: local
description: Local DVD repository
baseurl: "file://{{repo_mount}}"
enabled: yes
gpgcheck: no
Executing the playbook and testing the results
Now, you should have an inventory
file, and a directory called playbooks
that contains a files
directory where the Centos ISO file resides, and a local_repo.yaml
file that represents your playbook. The tree shoul look as follows:
├── hosts
└── playbooks
├── files
│ └── CentOS-7-x86_64-DVD-1804.iso
└── local_repo.yaml
Your playbook should look like this:
---
- hosts: centos
become: yes
vars:
- source_iso: "files/CentOS-7-x86_64-DVD-1804.iso"
- dest_iso: "/opt/CentOS-7-x86_64-DVD-1804.iso"
- repo_mount: "/mnt/dvd"
tasks:
- name: Upload the ISO file to the remote host
copy:
src: "{{ source_iso }}"
dest: "{{ dest_iso }}"
force: no
- name: Mount the ISO file
mount:
path: "{{repo_mount}}"
src: "{{dest_iso}}"
fstype: iso9660
opts: loop,ro
state: mounted
- name: Add repository
yum_repository:
name: local
description: Local DVD repository
baseurl: "file://{{repo_mount}}"
enabled: yes
gpgcheck: no
The playbook can be executed by running the following command:
ansible-playbook -i hosts playbooks/local_repo.yaml
The output should look as follows:
PLAY [centos] ************************************************************************************************
TASK [Gathering Facts] ************************************************************************************************
ok: [server]
TASK [Upload the ISO file to the remote host] ************************************************************************************************
changed: [server]
TASK [Mount the ISO file] ************************************************************************************************
changed: [server]
TASK [Add repository] ************************************************************************************************
changed: [server]
PLAY RECAP ************************************************************************************************
server : ok=4 changed=3 unreachable=0 failed=0
You can now login to your remote server and ensure Ansible has did the job right by issuing the command that we mentioned earlier:
sudo yum install --disablerepo="*" --enablerepo="local" httpd
It should use the local repository to install the Apache 2 web server
Further thoughts
In this article I demonstrated how we can use Ansible to save time and effort by automating a repetitive task like building a local YUM repository for a Centos machine. This example could be further enhanced to create a central repository where the ISO file gets mounted and served to a whole environment over http or FTP. I may cover that in a separate article.
If you enjoyed this post and want to have hands-on learning labs on Ansible, I suggest you enroll in my course: Beginning Ansible with Vagrant and Amazon AWS. In this course, I take you from “What is Ansible?” to successfully deploying two real-world web application stacks: the LAMP and the MEAN stacks. I use Vagrant, which is another excellent DevOps tool to avail the infrastructure for the course labs. I also included a special section about using Ansible to create and manage Amazon EC2 instances. For a limited time, you can use the coupon code: ZSAVE2018 at checkout to enjoy 90% discount.