Wednesday, February 21, 2018

Create a LIVE bootable VDI Kiosk using Vmware Horizon View Client 4.7.0 and Debian 9 with minimal packages.

Creating the environment

In my example, I will be building on Debian 9, but I have also tested this and works fine in Ubuntu 16.04 and KDE Neon, so I am sure any Debian based distro will do just fine.

Start off by creating a fresh new folder to setup your build environment. We’ll call this folder “live-image”. Inside this folder you will need two folders, “chroot” for our chroot environment and “image” where we will create our ISO image later on.

$ mkdir live-image
$ mkdir live-image/chroot
$ mkdir live-image/image

In my case, I’m creating the folders in my home directory, but you can create them wherever you have read/write access.

Let’s now grab our tools. I’ll be using apt. If you’re trying with another distro, such as CentOS, you’ll need to refer to your packages of the same tools by a different name.

 $ sudo apt install debootstrap syslinux isolinux squashfs-tools genisoimage

Often you see in these types of guides, you’re told to just install packages and go on, but I want to leave you in the dark too much here. If you’re a pro you can skip these package breakdowns, but if you want more info on what you’re doing, I’ll try to break down what each of these things will do for you.

Package Breakdown
debootstrap – This is a utility for pulling down a bootstrap of a basic Debain system from scratch and does so by unpacking the basic packages and installing them into a directory that will become your root filesystem. This directory can then be later chrooted (changed root) so that it can be worked in directly. You’re installing Debian in Debian! - Well… not really.

syslinux – syslinux is a good old fashioned bootloader that has been around a long time. It is primarily a bootloader to boot Linux from FAT or NTFS filesystems. There are ways of creating live images using Grub and Ext filesystems but that will not be covered here.

Isolinux – isolinux is a bootloader that enables you to create a bootable ISO image for
CD-ROM ISO 9660 filesystems. The modules from syslinux are required to make Isolinux work.
squashfs-tools – These are tools to help you compress your live filesystem into a compressed format called squashfs (yep, squashed filesystem). This makes the filesystem nice and tiny for live booting.

genisoimage – This is a tool for creating an ISO image. This is a very simple and fast tool so it will be used in this example over other alternatives you may be used to.

Once you have the tools installed, we can move on to creating the Debian file system.
Debian 9 Stretch will be used, and I will be going for a 64bit architecture. You may want or need to use a 32bit (in that case you’ll use arch=i386), but for this example I’ll be building this 64bit.

This example assumes you are in your home directory where your live-image directory exists. If you see a ~ symbol in the path, that is referring to your home directory.

 $ sudo debootstrap --arch=amd64 --variant=minbase stretch ~/live-image/chroot

This will take a little bit as it downloads all your packages and creates the filesystem in your live-image/chroot directory.

Once finished, you’ll be able to see the familiar GNU filesystem in your chroot directory.

Now we can chroot into your “chroot” directory and get to setting up the image basics and installing a kernel for the system.

Start by chrooting into the system.

$ cd ~/live-image
$ sudo chroot chroot/

In the Debian dungeon with chroot

You are now root of your new Debian minimal OS and you will see “root@debian:/#” Going forward, all commands used in chroot will be shown using the # instead of the $ 

Let’s set up a hostname for our new image.

# echo “vdi-live” > /etc/hostname

And lets install a Linux kernel so we can give our image a brain. You can search for available kernels using the apt search command.

# apt search linux-image

Choose a standard kernel. You can use the image metapackage to choose the latest standard kernel: linux-image-arm64

While in chroot installing packages, ensure you’re using the –no-install-recommends option to install only the packages you want and not attached little extras to cause bloat to your system

Let’s install that kernel and generate our initramfs.

# apt install --no-install-recommends linux-image-amd64

Next, we’ll need to install-boot and the systemd system links package.

# apt install live-boot systemd-sysv

Package Breakdown
live-boot  This is a package that contains scripts that aid in booting Debian in a live environment and is used in Debian’s existing live CD images.

systemd-sysv – Love it or hate it, systemd is here to stay. But, some of the good old power commands in sbin have gone away. This package brings back links to classic commands like reboot, shutdown, and init.

Now we need to install the rest of our tools. We aren’t building a general utility-like live image here so we only need what’s necessary for video, internet, and a few minor tools if we do happen to need them in a live disk to troubleshoot VDI.

For this live image’s window manager, I’m going with OpenBox for it’s Kiosk like abilities without having to lock much down.

# apt install --no-install-recommends network-manager net-tools wireless-tools wpagui openbox xserver-xorg-core xserver-xorg xinit xterm pciutils usbutils ntfs-3g hfsprogs dosfstools syslinux nano wget

Package Breakdown
network-manager - network-manager is a system network service that manages your network devices
and connections, attempting to keep active network connectivity when

net-tools - net-tools includes the important tools for controlling the network
subsystem of the Linux kernel.

wireless-tools - wireless-tools contains the Wireless tools, used to manipulate
the Linux Wireless Extensions.

wpagui -  wpagui provides a UI for wireless, it also provides a method for browsing 802.11 SSID scan
results, an event history log of messages generated by wpa_supplicant,
and a method to add or edit wpa_supplicant networks.

openbox - openbox is a fast, light-weight and extensible window manager and is great for kiosk environments as well as any desktop.

xserver-xorg-core - xserver-xorg-core is the core portion of the xserver graphics system for displaying GUIs.

xserver-xorg - xserver-xorg package doesn't install the xserver-xorg itselft, but installs some script and documentation components.

xinit - xinit brings in tools for X server initialisation and brings in the startx command.

xterm - xterm is a terminal emulator for the xserver system.

pciutils - pciutils brings in utilites for searching connected hardware components through the PCI interface.

usbutils - usbutils brings in utilites for searching connected USB devices.

ntfs-3g - ntfs-3g allows for read/write to the NTFS file system. This is useful if you need to read a local Windows hard drive at some point.

hfsprogs - hfsprogs allows for read/write to the HFS file system. This is useful if you need to read a local Apple hard drive at some point.

dosfstools - dosfstools allows for read/write to FAT/DOS based file systems.

syslinux - syslinux is a bootloader and is used in this case to boot linux after isolinux boots the filesystem.

nano - nano is a simple and light-weight text editor.

wget - wget allows you to download files from the internet/network based on url.

During install, you might be prompted to choose your keyboard layout. This is normal and just press the key to the keyboard layout you wish. 1 is for standard US/English.

We'll need to have a user for our image to log into that's not root, so let’s create a new user called “live-user”. 

# adduser live-user

Enter in a password when prompted, one you will know. Don’t worry, you wont need to give it out to anyone and this user won't have sudo permissions anyway. Just continue pressing enter or filling out the info if you like until the user is fully created after pressing “y” at the end.

Now let’s set the systems root password. Again, you need to remember this password, but don’t give it out to anyone you don't want to be able to break out of your kiosk.

# passwd root

At this point, if we finalized and created our boot media, we’d see a lot of Linux boot text scrolling along as it boots. A lot of modern distros have a splash screen. Lets make a clean boot and install Plymouth for that polished feel with a boot splash screen system.

# apt install --no-install-recommends plymouth plymouth-themes

Package Breakdown
plymouth A splash screen boot display system, very light weight.

plymouth-themes Contains a few libraries needed for plymouth to display properly.

Now, we won’t install VMware quite just yet, we are going to need a few packages to install since VMware doesn’t have a debian package and uses a giant .bundle file that uses python 2.7. I’ll break down these requirements into two sections. So let’s install our requirements for installing.

# apt install --no-install-recommends python

For this live image we will want to install VMware Horizon View Client with as many options as possible, but there are going to be two options I’m going to leave out for this project.

- Client Drive Redirection : There’s no use for a shared network drive on a read-only image, so we won’t waste the time installing it. It will still be possible to share files via USB drive.

- Pack for Skype for Business : Not useful unless you actually NEED this feature. For the scope of this project, I will not be showing how to source the requirements for this feature.

All the other VMware options, we are going to have the libraries for as Debian is pretty darn good at having the requirements already there. But there are two essential packages that do need a little bit of work to get working: Multimedia Redirection (MMR) and Real-Time Audio-Video (The ability to use your webcam and stream audio for things like a conference call, that’s not Skype apparently)

For Multimedia Redirection, which is essential for HTML5 and flash video redirection (video processes on the client hardware rather than the VM) for watching smooth YouTube video, you’ll need to install the libgstreamer0.10 package and the libgstreamer-plugins-base0.10 package. But here’s the kicker, these have been removed from Debian 9 and Ubuntu 16.04 base images and are not in APT! These will need to be manually downloaded and installed from the Debian 8 packages.

We are going to temporarily download these packages, so lets go to the root folder to use as scratch space.

# cd /root

# wget
# wget

And we’ll now need to install them using dpkg, the deb package installer.

# dpkg -i libgstreamer0.10-0_0.10.36-1.5_amd64.deb
# dpkg -i libgstreamer-plugins-base0.10-0_0.10.36-2_amd64.deb

You WILL see an error after installing the second package saying it has dependency problems. This is normal and to be expected! We’ll fix, don't you worry! This is the great thing about Debian’s package management.

# apt --fix-broken install

This will install iso-codes and liborc-0.4-0 (our missing dependency) and will finish by installing our libgstreamer-plugins package automatically

Package Breakdown
libgstreamer – libgstreamer is a media library framework for real-time video and audio.

Next, for support of our Real-Time Video and Audio support (yeah, I know… what about libgstreamer? Ask VMware…), we’ll install libv4l-0 and libspeexdsp1, which luckily are in apt.

# apt install --no-install-recommends libv4l-0 libspeexdsp1

Package Breakdown
libv4l-0  libV4l (Library for Video4Linux) is a library used for the Real-Time video processing side of VMware.

libspeexdsp1  libspeexdsp1 (Extended library for Speex, an audio codec used for the audio portion of Vmware’s Real-Time audio.

Next before we install VMware, I’m going to very highly suggest you install the chromium browser. One reason is because it provides a good browser to use for local non-VDI inernet if needed, but another is because it will install every package needed with the exception to the above for VMware Horizon Client to run.

# apt install --no-install-recommends chromium

Finally to VMware. Now we should be set to download the Vmware-Horizon-Client installer bundle. While still in the /root directory in your chroot.

# wget

Your package won’t be executable, so we’ll need to modify that.

# chmod +x VMware-Horizon-Client-4.7.0-7395152.x64.bundle

Now we can install. Note that this installer will be text based. If you have installed this before, you’ll probably be expecting a GUI. Nope, not in this chroot buddy! Never fear, I’ll guide you along.

# ./VMware-Horizon-Client-4.7.0-7395152.x64.bundle

Installing VMware Horizon Client 4.7.0 into the CHROOT Debian 9

  1. You’ll be asked to accept a License Agreement. Just press Enter.
  2. If you don’t want to read the license (hoping there’s no HumancentIpad clause) you can go ahead and press the q key and type “yes” and hit enter.
  3. Client Drive Redirection. We won’t have the libraries or the ability so type “No” and press enter.
  4. Multimedia Redirection. We want that. Default answer is Yes so just press enter.
  5. Smart Card. You never know, and we have the libraries so hit enter to choose Yes.
  6. Real-Time Audio-Video. You went to all that work! Hit enter to choose Yes.
  7. VMware Horizon(R) Virtualization Pack for Skype for Business. For issues beyond libraries, this is not supported in the scope of this project. Type “No” and hit enter.
  8. USB Redirection. VDI without USB Redirection is just sad. Hit enter to choose Yes.
  9. Virtual Printing (AKA ThinPrint) this is only really useful if CUPS is installed, but it doesn’t hurt to just install it anyway. Hit enter to choose yes.
  10. Hit enter again to continue to install.
  11. You will want to Register and start the install services, so type “Yes” and hit enter.
  12. Here’s were we will ENSURE that all the libraries were found. Type “Yes” to scan. I highly recommend you do this to see if everything installed properly.

Hopefully after your scan you should see this:

VMware Horizon Multimedia Redirection (MMR)
VMware Horizon Smart Card
VMware Horizon Real-Time Audio-Video
VMware Horizon PCoIP
VMware Horizon USB Redirection
VMware Horizon Virtual Printing
VMware Horizon Client

If not, take note of the missing .so files it lists and look them up to see what packages they belong to. Feel free to post your problems here and we can find if there’s a new requirement or package change.

Now, I’m sure you’re getting antsy to test this live image already, but as it is right now, you wont see anything if you tried it. We’re going to need to finish configuring Debian to properly boot and to automatically log in as a live user for the disk. We will also need to make the experience a little more like a Kiosk.

Let’s start by getting autologin to work. Let’s navigate to the systemd system directory.

# cd /etc/systemd/system

Here we will want to create a new folder. The name is a bit easy to typo, so pay close attention to avoid troubleshooting issues later. Ensure you do use the @ sign in the name.
Now we’ll need to make a configuration file that automatically logs our user in

# cd getty@tty1.service.d
# nano override.conf

This will bring you into the Nano text editor. If you never used it, its a easy text editor that lets you get in and out quick. (If you have used it, and prefer vi, good luck and have fun, and I hope you exit someday.)
In our file, make sure you have the follow exactly as shown, including the double ExecStart lines.


ExecStart=-/sbin/agetty --autologin live-user --noclear %I $TERM

Press Ctrl-x, then y and enter to save.

You now have your user we created “live-user” automatically logging into the main terminal window, but we still wont have any GUI.

Next, we’ll create the startup scripts for getting your GUI up. We’ll set this up only for the live-user so that the root account can do what it needs to without anything automatically starting up.

# cd /home/live-user/

Now we’ll edit a hidden file here called .profile and add a line to start the xwindow system.

# nano .profile

At the very bottom of the file, append this line.

[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && exec startx

Ctrl-x, y and enter to save and quit.

Now we need to tell OpenBox to autostart VMware once the user logs in.

From the /home/live-user directory we’ll need to create the .config directory and the openbox directory , which doesn’t exist, and change the owner to the live-user

# mkdir .config
# mkdir .config/openbox
# chown -R live-user .config/

Now we’ll go into the openbox directory and create a new file for autostarting VMware.

# cd .config/openbox
# nano autostart

Enter in the following line of text

vmware-view --nomenubar --once &

Ctrl-x, y and enter to save and quit.

There are more things we can do for OpenBox, customize menues and themes but for the scope of just getting this up and functional, we’ll skip and I’ll add it on at a later time. Before we go into the creation of the image, we should create a policy file for VMware that really finalizes that Kiosk experience.

Navigate to the /etc/vmware folder and create a new file called view-mandatory-config.
This is the file that controls vmware’s options so that the user cannot change them. You can restrict this as much as needed. Vmware’s documentation can go further into all the possible options but I’ll just touch on a few of the basics.

# cd /etc/vmware
# nano view-mandatory-config

Enter in the following text:

view.sslVerificationMode = "3"
view.allMonitors = "TRUE"
view.allowDefaultBroker = "TRUE"
view.fullScreen = "TRUE"
view.nonInteractive = "TRUE"

You may see in vmware documentation of an option view.kioskLogin. This isn’t what it seems and it won’t help you with a Kiosk experience for the Live disk itself.

If you have a default VDI server that you want to lock the user into you may add it to the file like so (IP or FQDN can be used):

view.defaultBroker = ""

Ctrl-x, y and enter to save and exit.

Now, lets make that live disk! Let’s clean up apt to make sure our filesize is small and exit chroot.

# apt clean
# exit

Every time you make updates to this image in the future, make sure you end with apt clean or apt-get clean. Not doing so can bloat your image filesize by a few hundred mb.

We are no longer in CHROOT and all examples are now using $ instead of #.

To setup our image for the ISO, lets go into our image folder we created at the beginning of this guide.

Setting up the Live Image ISO and SquashFS

Now that we're out of the chroot dungeon, we can start by going back to our live-image directory to get ready to start putting together the files needed for creating our filesystem and ISO.

$ cd ~/live-image/image

Here, we’ll create two new folders.

$ mkdir live
$ mkdir isolinux

In our live folder, we’ll need to copy our Linux kernel and Initramfs file from the chroot folder.

$ cp ~/live-image/chroot/boot/vmlinuz-4.9.0-4-amd64 ~/live-image/image/live/vmlinuz1
$ cp ~/live-image/chroot/boot/initrd.img-4.9.0-4-amd64 ~/live-image/image/live/initrd1

vmlinuz1 and initrd1 in the live folder are the Linux kernel and Initramfs from our image, but we need them to boot the disk as well. They will be copied to the live folder to help bootstrap the image.

Now we’ll need to create our menu for our boot. I’m going to make ours very simple but you can add more options later on for things like memtest86+ (A system memory checker)

$ nano ~/live-image/image/isolinux/isolinux.cfg

In this file, add the following text:

UI menu.c32

prompt 0
menu title Our Example VDI Live Disk

timeout 300

label VDI-LIVE
menu label ^VDI-LIVE
menu default
kernel /live/vmlinuz1
append initrd=/live/initrd1 boot=live quiet splash

Ctrl-x, y and enter to save and exit.

The title’s and labels may be customized to your liking, but you may want to leave as it is for now to give this a try. Rebuilding at this point will be quick and easy down the road.

Notice the “quite splash” added on to the bottom line. This is required for using Plymouth, the boot splash screen we installed earlier

To finish setting up isolinux, we’ll need to copy some files into the isolinux directory

$ cp /usr/lib/ISOLINUX/isolinux.bin ~/live-image/image/isolinux/
$ cp /usr/lib/syslinux/modules/bios/menu.c32 ~/live-image/image/isolinux/
$ cp /usr/lib/syslinux/modules/bios/hdt.c32 ~/live-image/image/isolinux/
$ cp /usr/lib/syslinux/modules/bios/ldlinux.c32 ~/live-image/image/isolinux/
$ cp /usr/lib/syslinux/modules/bios/libmenu.c32 ~/live-image/image/isolinux/
$ cp /usr/lib/syslinux/modules/bios/libcom32.c32 ~/live-image/image/isolinux/
$ cp /usr/lib/syslinux/modules/bios/libgpl.c32 ~/live-image/image/isolinux/
$ cp /usr/share/misc/pci.ids ~/live-image/image/isolinux/

That’s it! Now we can create our squashfs filesystem for our disk. 

This part needs to be run as sudo.

$ sudo mksquashfs ~/live-image/chroot ~/live-image/image/live/filesystem.squashfs -e boot

This will take a bit of time, but won’t take too long. Once it’s finished we’ll finally be ready to create that ISO file and start testing! It should be around the filesize of 462MB (give or take based on the packages installed)! That’s pretty amazing considering your uncompressed linux image is actually around 1.1GB at this point!

Now we’ll create that ISO file.

$ sudo genisoimage -rational-rock -volid "VDI LIVE" -cache-inodes -joliet -hfs -full-iso9660-filenames -b isolinux/isolinux.bin -c isolinux/ -no-emul-boot -boot-load-size 4 -boot-info-table -output ~/live-image/vdi-live.iso ~/live-image/image

That’s it! Your iso file should be named “vdi-live.iso” and sitting in your live-image directory.

If you’re familiar with qemu, you can try testing it there. If you have VirtualBox, VMware Workstation, ect boot up your ISO and see your creation!

When recreating new squashfs files, make sure you delete the filesystem.squashfs file. It will actually keep appending it rather than replacing it!

For further customization, themes, colors, mouse pointers, scripts, ect I’ll add on another post. At this point, you should have what you need to start playing on your own.

Have fun!


  1. Hi Chad,
    This is awesome. I was searching on how to build a live VMware horizon kiosk.
    And this post is god send.
    I will start build mine, based on your instructions in the next 2-3 days and I will share with you how it goes.
    The only difference is that I am going to base it on Ubuntu LTS.

    Once again, great post!!!!!

    1. Glad its helpful! In the past, when I've built kiosks with Ubuntu LTS, it ended up being a bigger ISO file due slight difference in some package sizes for whatever reason, but not big enough to matter. There are also a few differences with Ubuntu LTS with the libraries for the VMware Horizon Client, which can be solved with a little linking as I recall the libraries where just named differently. I think I also had to borrow a library from a Ubuntu 14.04 deb as well, but that might be solved using the Debian 8 files I posted as well.

      Good luck! I hope it works out well for you!

  2. Hi Chad,
    I tried to make the iso but at the last step when creating the iso, I get the error "I cant find the boot catalog directory 'isolinux'". I am not sure why.
    Any ideas?

    On your article please check the following
    1. In some commends the "--" in "--no-install-recommends" is actually a long "-"
    2. At the section when you create the iso, you have "~/live-image/image/isolinux/" or "~/live-image/image/live/" but that path actually is "~/live-image/isolinux/". There is an additional "image" in the middle.

    1. 1. Thanks, I'll fix that. Automatic formatting is a mighty enemy.

      2. Actually that's not a typo at all! I accidentally missed the section where you create the two sub-folders! This also what is likely causing your error with not finding isolinux! (oops!)

      Your folder layout under ~/live-image should be as follows:


      In the section where you are copying the isolinux files, you will see it lays out the path where they need to go:

      $ cp /usr/lib/ISOLINUX/isolinux.bin ~/live-image/image/isolinux/
      $ cp /usr/lib/syslinux/modules/bios/menu.c32 ~/live-image/image/isolinux/
      $ cp /usr/lib/syslinux/modules/bios/hdt.c32 ~/live-image/image/isolinux/
      $ cp /usr/lib/syslinux/modules/bios/ldlinux.c32 ~/live-image/image/isolinux/
      $ cp /usr/lib/syslinux/modules/bios/libmenu.c32 ~/live-image/image/isolinux/
      $ cp /usr/lib/syslinux/modules/bios/libcom32.c32 ~/live-image/image/isolinux/
      $ cp /usr/lib/syslinux/modules/bios/libgpl.c32 ~/live-image/image/isolinux/
      $ cp /usr/share/misc/pci.ids ~/live-image/image/isolinux/

      Hope this helps and sorry for the confusion!

    2. I have fixed the issues you have found. Thanks again for your feedback!

  3. 1. You missed one at "apt –fix-broken install" :)
    2. I honestly did not think of that.
    I tested it out using Debian and it works great. Although more testing is needed.

    When you tried out Ubuntu did you get and error regarding "live-boot"?

    1. Again, thanks! I've fixed it.

      It was a while ago when I did this with Ubuntu, but I didn't run into an error with Live-Boot. I believe I used more packages from the server install, however, so I may have done it differently. Unfortunately I didn't document what I did at the time.

    2. Update on the Ubuntu side of things. Just converted an Ubuntu system to a live disk system (16.04 based). I didn't have issues with live-boot, but I did have to copy an additional c32 file for isolinux (libutils.c32). Other than that, no other issues with Ubuntu side of things.