Instructions for Setting Up a CentOS 7 System with Bridged Networking for Virtual Machines

CentOS 7 bridging network card for virtual machines

My goal is to set up virtualization where the guests can access the entire LAN as well as the host over the network. The host should also be able to reach all the guests via the network.

This task was so simple, but somehow it eluded me for over a year. I use this document to establish a new kvm host in my network pool.

Install virtualization tools

sudo yum -y install libvirt qemu-kvm virt-install
sudo systemctl enable libvirtd.service ; sudo systemctl start libvirtd.service
sudo setsebool -P virt_use_nfs 1

Adjust the ethernet configuration

sudo su -
this_nic="$( nmcli device show | awk '/^GENERAL.DEVICE:/ && $2 ~ /e.*/ {print $2}' )"
this_nic_count="$( printf "%s\n" "${this_nic}" | sed '/^\s*$/d' | wc -l )"
if test ${this_nic_count} -ne 1 ;
   echo "Other than 1 nic detected. Please deal with manually. Aborted."
   # prepare values for bridge definition
   this_mac="$( ip -o link | grep "${this_nic}" | grep -oE 'ether [a-fA-F0-9:]{17}' | awk '{print $2}' | tr '[[:lower:]]' '[[:upper:]]' )"
   this_ipaddr="$( ip -o address show "${this_nic}" | grep -oE 'inet [0-9\.]{7,15}' | awk '{print $2}' )"
   # define bridge interface
      echo "DEVICE=${this_bridge}"
      echo "TYPE=Bridge"
      echo "ONBOOT=yes"
      echo "DELAY=0"
      grep -h -E 'DNS1|DNS2|DOMAIN|IPADDR|PREFIX|BOOTPROTO|GATEWAY|DEFROUTE' "${indir}/ifcfg-${this_nic}"
   } > "${indir}/ifcfg-${this_bridge}"
   # define ethernet card
      echo "DEVICE=${this_nic}"
      echo "HWADDR=${this_mac}"
      echo "ONBOOT=yes"
      echo "BRIDGE=${this_bridge}"
      grep -h -E 'UUID' "${old_nic_file}"
   } > "${temp_nic_file}"
   chmod --reference "${old_nic_file}" "${temp_nic_file}"
   /bin/mv -f "${temp_nic_file}" "${old_nic_file}"

systemctl restart network.service NetworkManager.service

Using the virtual host

With the setup complete, the environment is ready to serve virtual machines!

Install a virtual machine

vm=c7-03a ; time sudo virt-install -n "${vm}" --memory 2048 --vcpus=1 --os-variant=centos7.0 --accelerate -v --disk path=/var/lib/libvirt/images/"${vm}".qcow2,size=20 -l /mnt/public/Support/SetupsBig/Linux/CentOS-7-x86_64-Minimal-1804.iso --initrd-inject=/mnt/public/Support/Platforms/CentOS7/centos7-ks.cfg --extra-args "ks=file:/centos7-ks.cfg SERVERNAME=${vm}" --debug --network type=bridge,source=br0 --noautoconsole

Delete a virtual machine

vm=c7-03a; sudo virsh destroy "${vm}"; sudo virsh undefine --remove-all-storage "${vm}";




Internal files

  1. file:///mnt/public/Support/Platforms/CentOS7/centos7-ks.cfg

Add custom kickstart file and root ca certificates to iso file

Introduction and goals

This is intended to be one of my longer posts. This article describes how to accomplish the following tasks:

  1. Insert custom kickstart files into an iso file
  2. Insert custom root CA certificates into the initrd.img of an iso file, so you can fetch a custom repository over https
  3. Write a sample kickstart file
  4. Open up the initrd.img to add more files

The example file used is Fedora-Workstation-netinst-x86_64-27-1.6.iso available from

The files

You will need a few files, including:

  1. kickstart file
  2. Root certificate

Kickstart files

My 2 different kickstart files are
fc27c-ks.cfg (saved to WordPress as a .doc, but it is truly just a plain text file)
Quite a few things to note about the content:
I had to use http for all my local repositories, even though I got the ca certficate loaded. I think how my ISP bounces back my https traffic causes enough slowdown on the ssl handshake it prevents anaconda from using it correctly. It was working earlier in the day but I had to disable it.
Observe in the %pre scriptlet the lines

cp -p /run/install/repo/ /etc/pki/ca-trust/source/anchors 2>/dev/null || :
update-ca-trust || :

These 2 lines load up the root certificate authority cert into the running initrd trusted keys, so the ssl connections are trusted.
Please see the attached or indicated files.

Root certificate

A root certificate is the certificate that signs other certificates for that namespace. I use my own in my ipa domain, and I use it on my web server. So to connect with ssl because I want to encrypt everything possible, I need this cert in the runtime environment on the iso disc image. My root ca file is
not shared on this blog. Go get your own!

The steps

Mount original iso

mkdir -p /mnt/originaliso
mount -v -o loop /mnt/public/Support/SetupsBig/Linux/Fedora-Workstation-netinst-x86_64-27-1.6.iso /mnt/originaliso/

Copy contents to work directory

mkdir -p /mnt/newiso ; cd /mnt/
time cp -pr originaliso/* newiso/

Copy in kickstart files

cp -pf /mnt/public/Support/Platforms/Fedora/fc27{x,c}-ks.cfg /mnt/newiso/
chown root:root /mnt/newiso/*ks.cfg
echo done

Tell disc to use new ks file

This task:

  • Adds xfce and cinnamon menu options
  • Find all the append= lines, and add to the end this attribute: ks=hd:LABEL=fc26:/fc26x-ks.cfg

The important piece is to have the LABEL= the volume name that you give the mkisofs -V “label” a few commands later in this article. If you really want to use a file:/ks.cfg, then you have to open up the initrd, which Appendix A demonstrates.

Fedora 27 xfce and cinnamon
sed -r -e "/append/{s/LABEL=([A-Za-z0-9_\-]*)(\s|:)/LABEL=${label}\2/;s/quiet//;};" -e '/label linux/,/^\s*$/H;' -e '/^\s*$/{x;};' "${tf}" | \
awk "BEGIN{a=0;b=0;labels[1]=\"xfce\";labels[2]=\"cinnamon\";} /^label [^l]/{b=b+1} b < 1 && /label linux/{a=a+1;\$0=\$0\" \"labels[a];} b < 1 && /menu label/{\$0=\$0\" \"labels[a];} b < 1 && /append/{\$0=\$0\"ks=hd:LABEL=${label}:/${label}\"substr(labels[a],1,1)\"-ks.cfg\";} {print;}" > "${tf}.$$"
mv -f "${tf}.$$" "${tf}"
Centos 7
sed -r -e "/append/{s/LABEL=([A-Za-z0-9_\-]*)(\s|:)/LABEL=${label}\2/;s/quiet//;};" "${tf}" | \
awk "BEGIN{a=0;b=0;labels[1]=\"with my bgstack15 custom kickstart\";} /^label [^l]/{b=b+1} b < 1 && /label linux/{a=a+1;\$0=\$0\" \"labels[a];} b < 1 && /menu label/{\$0=\$0\" \"labels[a];} b < 1 && /append/{\$0=\$0\"ks=hd:LABEL=${label}:/${label}-ks.cfg\";} {print;}" > "${tf}.$$"
mv -f "${tf}.$$" "${tf}"

Copy in certificate file

This will be used by the kickstart file and injected into the running initrd so https connections can be trusted to download the repos.

/bin/cp -pf /mnt/public/www/smith122/certs/ /mnt/newiso/
chown root:root /mnt/newiso/*.crt

Make new iso

Fedora 27
ti="${label}manual.iso"; cd /mnt/newiso;
rm -f /mnt/newiso/"${ti:-NOTHINGTODELETE}" ; __func() { mkisofs -V "${label}" -m '*.iso' -o "../${ti}" -b isolinux/isolinux.bin -c isolinux/ -no-emul-boot -boot-load-size 4 -boot-info-table -r -J -v -T . ; implantisomd5 "/mnt/${ti}" ; } ; time __func
CentOS 7
ti=centos7manual.iso ; cd /mnt/newiso ;
rm -f /mnt/newiso/"${ti:-NOTHINGTODELETE}" ; __func() { mkisofs -V "${label}" -m '*.iso' -o "../${ti}" -b isolinux/isolinux.bin -c isolinux/ -no-emul-boot -boot-load-size 4 -boot-info-table -r -J -v -T . ; implantisomd5 "/mnt/${ti}" ; } ; time __func

Copy to server so vm1 can access

time su bgstack15 -c "cp -pf /mnt/${ti} /mnt/public/Support/SetupsBig/Linux/";
echo done

Next steps

After that, the iso is ready to be burned to disc or used by virt-install. I have not actually tried burning a disc or usb drive, but I assume it’s pretty similar to a regular Live iso.
For virt-install, I was simply unable to get my fancy customized iso to work fully automatically. For a regular, unattended vm install, I use the regular Fedora netinstall iso and I inject my kickstart file.

vm=fc27x-02a ; time sudo virt-install -n "${vm}" --memory 2048 --vcpus=1 --os-variant=fedora25 --accelerate -v --disk path=/var/lib/libvirt/images/"${vm}".qcow2,size=20 -l /mnt/public/Support/SetupsBig/Linux/Fedora-Workstation-netinst-x86_64-27-1.6.iso  --initrd-inject=/mnt/public/Support/Platforms/Fedora/fc27x-ks.cfg --extra-args "ks=file:/fc27x-ks.cfg SERVERNAME=${vm}" --debug --network type=direct,source=eno1

And to destroy that vm when I’m done with it:

vm=fc27x-02a; sudo virsh destroy "${vm}"; sudo virsh undefine --remove-all-storage "${vm}";

But this custom iso that we built is ready to be inserted into a vm, where you can manually select the xfce or the cinnamon option. After that initial menu choice, everything else is automatic and unattended.


Appendix A: Modify initrd.img file

Right after step “Copy in certificate file,” if you want to modify the initrd.img file, you can use these steps:

Open initrd.img xz file

mkdir -p /mnt/initrd1; cd /mnt/initrd1; time xzcat /mnt/originaliso/isolinux/initrd.img | cpio -d -i -m

Perform any file modifications to that filesystem in /mnt/initrd1.

Assemble new initrd.img file

cd /mnt/initrd1 ; time find . | cpio -o -H newc | xz --check=crc32 --x86 --lzma2=dict=512KiB > /mnt/newiso/isolinux/initrd.img




Internal documents

~/2017/Systems/guides/Add custom kickstart to iso file.odt

Inject hostname into kickstart

The story

I have been learning how to automate my centos installations in my virtual environment. I’ve learned how to use the virsh command line to spin up a new vm the way I like, and to feed it a kickstart file. I also learned how to use kickstarts.

Set hostname automatically with a kickstart

In the main area of the kickstart file, include this line:

%include /tmp/network.ks

Include in your %pre section this section:

echo "network  --bootproto=dhcp --device=eth0 --ipv6=auto --activate --hostname" > /tmp/network.ks
for x in $( cat /proc/cmdline );
   case $x in SERVERNAME*)
      eval $x
      echo "network  --bootproto=dhcp --device=eth0 --ipv6=auto --activate --hostname ${SERVERNAME}" > /tmp/network.ks

To paraphrase the post I’m duplicating for myself, you need the first echo redirection to the file in case there was no SERVERNAME= parameter given to the kernel.
When you boot, you need to include on the kernel command (usually the “linux” one), the value SERVERNAME=myhostname.

For my virsh command, that is:

vm=centos7-02a ; virt-install -n "${vm}" --memory 2048 --vcpus=1 --os-variant=rhel7.2 --accelerate -v --disk path=/var/lib/libvirt/images/"${vm}".qcow2,size=20 -l /mnt/public/Support/SetupsBig/CentOS-7-x86_64-Minimal-1511.iso  --initrd-inject=/mnt/public/Public/centos7-ks.cfg --extra-args "ks=file:/centos7-ks.cfg SERVERNAME=${vm}" --debug --network type=direct,source=eno1


  1. Install system-config-kickstart on Fedora 25
    sudo dnf install python-kickstart system-config-kickstart;