I recently built a new Ubuntu Desktop 20.04 machine to be used as an instant clone golden image for a Horizon 7.13 environment. I kept some notes on the steps I followed on my desktop, but after seeing a funny tweet this week (https://twitter.com/DennisCode/status/1475343774695886849), I decided I should share this document. This blog post will outline those steps to create a Ubuntu 20.04 Desktop for use as a Horizon 7.13 non persistent pool.
The first step was creating a virtual machine.
- VM Name: vdi_g01_ubuntu-2004 — this is my naming convention for VDI golden images. The VDI is pretty obvious, the g01 is for golden image #1 and then the last part is the OS name.
- Compatible with: ESXi 7.0 U2 and later (vmx-19) — my test hosts for VDI are running the latest available 7.0 release. I typically only visit compatibility levels when VMs are initially created. Since I’m able to run this version, and knowing 6.5/6.7 reach end of support in just a few months, I decided to go with the latest available. You’ll want to specify something that is capable of running on the versions of ESXi available in your environment.
- Guest OS Family: Linux
- Guest OS Version: Ubuntu Linux (64-bit)
- Virtual Hardware Configuration
- vCPU: 1
- Memory: 2GB
- New Hard disk: 24GB, thin provisioned
- SCSI Controller: LSI Logic Parallel
- New Network: 192.168.37.0 — this is the port group I use for VDI desktops
- Video Card > Number of displays 2
- Video Card > Total video memory: 32mb
- VM Options
I then selected ‘launch remote console’ to open the VMware Remote Console. I find this is the easiest way to install operating systems from ISO image. During the install I skipped the file check (just to save time) and selected ‘Install Ubuntu’ and accepted defaults. For my name I entered
template-admin and for computer name I entered
vdig01ubu2004.lab.enterpriseadmins.org. I entered a good password, selected require password to log in and didn’t enable Active Directory (we’ll do that later).
After the final reboot, we’ll login as our template-admin user, launch the terminal and install sshd, so that we can use it for the rest of the configuration. We’ll do this by entering
sudo apt install openssh-server -y. With that complete we can find our IP address — either from the vCenter Server > VM > Summary tab, or by typing
ip addr at that terminal session. We can then ssh into the system for the majority of the next configuration items.
The first few changes I made were generic system wide changes.
# apply any system updates & remove any obsolete packages
sudo apt update && sudo apt upgrade -y
sudo apt clean && sudo apt -y autoremove --purge
# Prevent ctrl-alt-del from causing a reboot
sudo systemctl mask ctrl-alt-del.target
# Disable auto-suspend
sudo systemctl unmask sleep.target suspend.target hibernate.target hybrid-sleep.target
# refresh systemctl
sudo systemctl daemon-reload
# Disable auto-updates
sudo sed -i 's/APT::Periodic::Update-Package-Lists "1"/APT::Periodic::Update-Package-Lists "0"/' /etc/apt/apt.conf.d/20auto-upgrades
# Disable LTS Upgrade MOTD
sudo sed -i '16 s/.*Prompt.*/Prompt=never/' /etc/update-manager/release-upgrades
# Remove some of the initial setup packages
sudo apt remove --purge gnome-initial-setup gnome-online-accounts update-manager-core -y
# setup script to generate new ssh keys at boot
cat << 'EOL' | sudo tee /etc/rc.local
test -f /etc/ssh/ssh_host_dsa_key || dpkg-reconfigure openssh-server
# make sure the script is executable
sudo chmod +x /etc/rc.local
I then made a few changes related to authentication and Active Directory membership. This is likely a questionable security practice, as we are letting all members of Domain Users to be able to not only login but run commands with sudo. For purposes of this lab desktop it works like I like, but you may want to make a few changes for your environment. In the past, I’ve used pbis-open for Active Directory authentication, but it appears that project is no longer maintained as of 2019. For this example, I will switch to sssd, as it is called out as supported by Horizon documentation and is recommended for ease of deployment (https://docs.vmware.com/en/VMware-Horizon/2111/linux-desktops-setup/GUID-D8E3A4AA-83E9-46A4-8BBA-824027146E93.html).
# install required components
sudo apt install sssd sssd-tools realmd libnss-sss adcli samba-common-bin -y
# join the domain
echo 'VMware1!' | sudo realm join lab.enterpriseadmins.org --user svc-windowsjoin --computer-ou='OU=EUC VDI Linux Parents,OU=LAB Computers,DC=lab,DC=enterpriseadmins,DC=org' --os-name='other' --verbose
# Tell pam.d to create the home directory at login
echo "session required pam_mkhomedir.so skel=/etc/skel umask=0022" | sudo tee /etc/pam.d/common-session
# Since we only have the one domain, lets use short names for most things
sudo sed -i 's/use_fully_qualified_names = True/use_fully_qualified_names = False/g' /etc/sssd/sssd.conf
echo '%domain\ users ALL=(ALL) ALL,!ROOTONLY' | sudo tee -a /etc/sudoers
# Note that '\ ' is to escape the space between domain & users. In PBIS-Open spaces were denoted as ^ and those had to be changed for group names to show the escaped space (example: '\ ' without the quotes).
# Note: I did need to delegate extra permissions to this service account compared to PBIS Open. I followed this guide:
I also like to suppress some of the initial popup and configuration steps. I use these desktop for testing purposes and they are disposed of at logoff — there isn’t a lot of value in getting comfy and setting up everything perfectly as a user as those settings are lost at logoff. There were a couple different options listed here: https://askubuntu.com/questions/1028822/disable-the-new-ubuntu-18-04-welcome-screen and I applied them all as they seemed somewhat hit or miss in my testing.
sudo mkdir /etc/skel/.config
sudo touch /etc/skel/.config/gnome-initial-setup-done
sudo sed -i '/\[daemon\]/a InitialSetupEnable=false' /etc/gdm3/custom.conf
I like to install a few packages to do administrative type activities. These include:
- firefox — a web browser (installed by default)
- net-tools — the legacy network tools like ifconfig
- powershell / powercli — a scripting language & module I use often
- remmina — a remote desktop client
- zenmap — a GUI for the nmap scanner
# install net-tools
sudo apt install net-tools -y
# install Powershell & PowerCLI
# Download the Microsoft repository GPG keys
wget -q https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb
# Register the Microsoft repository GPG keys
sudo dpkg -i packages-microsoft-prod.deb
# Update the list of products
sudo apt-get update
# Install PowerShell
sudo apt-get install -y powershell
# Start PowerShell, but as sudo se we can install PowerCLI for all users
Install-Module vmware.powercli -scope:allusers -Confirm:$false
Set-PowerCLIConfiguration -ParticipateInCeip $true -Scope:AllUsers -Confirm:$false
# Confirm that VMware* modules are available in the /usr/local/share/powershell/Modules path:
exit # this is to exit pwsh
# Install remmina
sudo apt install remmina -y
# Install zenmap
sudo apt install curl ndiff -y
sudo apt install ./python-gtk2_2.24.0-5.1ubuntu2_amd64.deb -y
sudo apt install ./zenmap_7.60-1ubuntu5_all.deb -y
# cleanup & remove installers
rm python-gtk2_2.24.0-5.1ubuntu2_amd64.deb packages-microsoft-prod.deb zenmap_7.60-1ubuntu5_all.deb
There are a few edits I made to keep these apps pinned to the menu on the desktop. The following lines should make that happen.
echo "user-db:user" | sudo tee /etc/dconf/profile/user
echo "system-db:local" | sudo tee -a /etc/dconf/profile/user
sudo mkdir /etc/dconf/db/local.d
echo "[org/gnome/shell]" | sudo tee /etc/dconf/db/local.d/00-favorite-apps
echo "favorite-apps = ['firefox.desktop', 'org.remmina.Remmina.desktop', 'nautilus.desktop', 'gedit.desktop', 'gnome-terminal.desktop']" | sudo tee -a /etc/dconf/db/local.d/00-favorite-apps
sudo dconf update
I also like to leave this desktop open for long periods of time and like to come back to it without needing to reauthenticate. Again, for production purposes this is a questionable practice, but this is a lab. You can leave this out if you’d like, but I wanted to leave the example in case. The
gsettings commands are per user only, so to make this setting available to other users that may use the pool, we’ll write them to a profile script that is executed at login.
echo 'gsettings set org.gnome.desktop.lockdown disable-lock-screen true' | sudo tee /etc/profile.d/02-weak-security.sh
echo 'gsettings set org.gnome.desktop.screensaver lock-delay 3600' | sudo tee -a /etc/profile.d/02-weak-security.sh
echo 'gsettings set org.gnome.desktop.screensaver lock-enabled false' | sudo tee -a /etc/profile.d/02-weak-security.sh
echo 'gsettings set org.gnome.desktop.screensaver idle-activation-enabled false' | sudo tee -a /etc/profile.d/02-weak-security.sh
Now to install the Horizon Agent. I could download the installer from inside the desktop, but I try to launch the fewest apps possible in my golden image & don’t like logging into websites from that template. Instead, I download the agent installer and post it to an internal web server, then download that copy with wget as shown below.
tar -xzf VMware-horizonagent-linux-x86_64-7.13.1-19066964.tar.gz
./install_viewagent.sh -A yes -G yes
# Lets set clipboard redirection system wide, both directions. Default is 2. 0 means disable; 1 means both direction; 2 means from client to agent only, 3 means from agent to client only.
sudo sed -i 's/#Clipboard.Direction=1/Clipboard.Direction=1/g' /etc/vmware/config
# Update the config to use sssd instead of pbis-open (https://communities.vmware.com/t5/Horizon-for-Linux/True-SSO-for-CentOs-7-Instant-Clone-agent-initialization-state/td-p/509274)
echo "OfflineJoinDomain=sssd" | sudo tee -a /etc/vmware/viewagent-custom.conf
I also like to have my Certificate Authority root cert installed as a trusted authority for both the system and Firefox. I previously wrote a post on that here: https://enterpriseadmins.org/blog/lab-infrastructure/installing-windows-ca-root-certificate-on-linux-and-firefox/. I’m going to follow those steps in this golden image as well.
To shut things down (now, and anytime we make changes to our template) I like to run the following:
# clean up the command history of the VM template-admin user
sudo rm -rf /tmp/*
sudo rm -rf /var/tmp/*
sudo rm -f /etc/ssh/ssh_host_*
sudo shutdown -h now
I then like to edit the ‘Notes’ property of the template with the date & a note about what was changed. This field is copied each time the VM is cloned, so I have a bit of an idea of what was included. For example, I would enter something like
2021-12-29: Initial creation of Ubuntu 20.04 Non Persistent VDI Desktop. Once the note is added, I would create a snapshot with the same message. From here, I was able to create a Horizon Instant Clone Pool, selecting our new VM and snapshot.
I hope you find this post helpful, feel free to drop any suggestions or comments below.