Source to Image

Salim Haniff
5 min readApr 18, 2020



Due to some changes in my schedule and re-designing the network lab, we will be taking a break from the Kubernetes setup this week. In the meantime, this post will go over how to set up a source-to-image (S2I) workflow using our single virtualization node.

The first time I came across the concept of S2I was through RedHat’s OpenShift project. This allowed you to use “source code” that will be used to define an image, similar to the Dockerfile concept. For this post, we will be using HashiCorp’s Packer product to help build our VMs.

The importance of using the concept of S2I in a DevOps environment is that it allows us to fine-tune our images in a controlled manner. We define in source what our image should be and use a workflow to create this image. Once we determine that changes need to be made to the VM, we just need to update the source code and push those changes to a Git repo. From there we can run that image building process through a CICD and perform our various validation that the VM is working correctly and meets our current requirements for a given sprint. Then we can do the necessary deployments to the prod environment.


This post will focus on CentOS for building our source to image solution. One of the mechanisms RedHat has offered for a couple of decades now is loading a text file configuration through the installation process through a product called Kickstart. If you log into any CentOS system and look in /root/ you will see a file called anaconda-ks.cfg or original-ks.cfg. These files contain the configurations that were used to install that instance of the OS. An example of a Kickstart configuration is listed below:

In the typical installation method, this Kickstart configuration would be placed on a server and exposed through HTTP, HTTPS, FTP or NFS. You would then need to amend the installation boot loader line to indicate the location of this Kickstart configuration.


append initrd=initrd.img inst.ks=

If the environment is equipped with DHCP then more elaborate PXE setups can be used. Since we are doing things a bit differently in this post we will not focus on those approaches, however, RedHat has excellent documentation on this

Packer simplifies our setup by removing the need for network infrastructure (DHCP, PXE, HTTP, etc) being set up for creating our S2I rollouts. Packer will automatically setup that webserver for us and tell CentOS to go there and read the Kickstart configuration. From there, Packer will run through its configuration on how to build that image and deliver it.


There are a couple of items needed to get this set up. First, log onto the Virtualization Node and download Packer.

$ mkdir ~/bin
$ cd bin
$ curl -o
$ unzip
$ ./packer version
Packer v1.5.5

You may want to add this path to your environment path to simplify constantly adding the full path to execute packer. E.g.

$ export PATH=${PWD}:$PATH

Now let’s create a directory for putting our S2I files in.

$ mkdir -p ~/packer/centos
$ cd ~/packer/centos
$ mkdir httpd

You will need to make 2 files. The first file is the Kickstart file. You could use the Kickstart configuration below:

You need to set the password for the root and cloud user. To do this run the following command (Found from

$ python -c ‘import crypt,getpass; print(crypt.crypt(getpass.getpass(), crypt.mksalt(crypt.METHOD_SHA512)))’

Once you have set the passwords, we will now need to create a configuration for Packer to produce our image. A configuration has already been created for you to grab and use.

Since we are using Centos-7, the base ISO will be the CentOS-7.7 minimal ISO. We also include the SHA256 checksum to verify the ISO is correct. The configuration sets the VNC port range between 5915–5920. This is useful in the event you need to debug the installation process. We Could open up the port ranges using the following firewall command:

$ sudo firewall-cmd –-add-port=5915–5920/tcp –-permanent
$ sudo firewall-cmd –reload

Now we can run Packer to build our image. Make sure to replace MyAwesomePassword with the one you created for the cloud user. Enter the following command to start the build:

$ packer build -var 'user_pass=MyAwesomePassword' centos-7.json

Once the build is completed, the image will be placed in the qemu directory. We can now try out the image and test to see if it meets our needs. The image should be copied into the libvirt image directory.

$ sudo cp qemu/CentOS-GoldImage /var/lib/libvirt/images/CentOS-GoldImage-stock.qcow2
$ sudo restorecon -FvvR /var/lib/libvirt/images/
$ sudo virt-install — connect qemu:///system — noautoconsole — name CentOS-GoldImate-test — memory 4096 — vcpus 2 — import — disk /var/lib/libvirt/images/CentOS-GoldImage-stock.qcow2 — network bridge=virbr0,model=virtio
$ sudo virsh
virsh # list
Id Name State
— — — — — — — — — — — — — — — — — — — — — — — — — —
3 CentOS-GoldImate-test running
virsh # console CentOS-GoldImate-test
(Hit enter a couple of times to get the prompt)
Connected to domain CentOS-GoldImate-test
Escape character is ^]
CentOS Linux 7 (Core)
Kernel 3.10.0–1062.18.1.el7.x86_64 on an x86_64
localhost login:

Log in with the cloud user credentials and try to ping an external address.

Congrats! You have now gone through the steps to create a source-to-image workflow. You can now add more configurations to the Kickstart file and repeat this process to get this base image to meet your organization’s needs. If there are common packages and configurations needed for the image then try looking at the provisioners offered by Packer. In a later post, we will be using a provisioner to help roll out solutions.

Take care for now and have a good one…



Salim Haniff

Founder of Factory 127, an Industry 4.0 company. Specializing in cloud, coding and circuits.