{"id":1619,"date":"2021-12-30T13:44:01","date_gmt":"2021-12-30T18:44:01","guid":{"rendered":"https:\/\/enterpriseadmins.org\/blog\/?p=1619"},"modified":"2021-12-30T13:44:01","modified_gmt":"2021-12-30T18:44:01","slug":"horizon-virtual-desktop-non-persistent-ubuntu-20-04","status":"publish","type":"post","link":"https:\/\/enterpriseadmins.org\/blog\/virtualization\/horizon-virtual-desktop-non-persistent-ubuntu-20-04\/","title":{"rendered":"Horizon Virtual Desktop &#8211; Non Persistent Ubuntu 20.04"},"content":{"rendered":"\n<p>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 (<a href=\"https:\/\/twitter.com\/DennisCode\/status\/1475343774695886849\">https:\/\/twitter.com\/DennisCode\/status\/1475343774695886849<\/a>), 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.  <\/p>\n\n\n\n<p>The first step was creating a virtual machine.  <\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>VM Name: vdi_g01_ubuntu-2004 &#8212; 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.<\/li><li>Compatible with: ESXi 7.0 U2 and later (vmx-19) &#8212; 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&#8217;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&#8217;ll want to specify something that is capable of running on the versions of ESXi available in your environment.<\/li><li>Guest OS Family: Linux<\/li><li>Guest OS Version: Ubuntu Linux (64-bit)<\/li><li>Virtual Hardware Configuration<ul><li>vCPU: 1<\/li><li>Memory: 2GB<\/li><li>New Hard disk: 24GB, thin provisioned<\/li><li>SCSI Controller: LSI Logic Parallel<\/li><li>New Network: 192.168.37.0 &#8212; this is the port group I use for VDI desktops<\/li><li>Video Card &gt; Number of displays 2<\/li><li>Video Card &gt; Total video memory: 32mb<\/li><\/ul><\/li><li>VM Options<ul><li>Advanced &gt; Configuration Parameters &gt; Add Configuration Params &gt; Name: <code>devices.hotplug<\/code>, value <code>false<\/code> &#8212; this is based on a recommendation here: <a href=\"https:\/\/techzone.vmware.com\/manually-creating-optimized-windows-images-vmware-horizon-vms#create-a-vsphere-based-virtual-machine\">https:\/\/techzone.vmware.com\/manually-creating-optimized-windows-images-vmware-horizon-vms#create-a-vsphere-based-virtual-machine<\/a>, I&#8217;m adding it to the Linux VM for similar reasons.<\/li><\/ul><\/li><\/ul>\n\n\n\n<p>I then selected &#8216;launch remote console&#8217; 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 &#8216;Install Ubuntu&#8217; and accepted defaults.  For my name I entered <code>template-admin<\/code> and for computer name I entered <code>vdig01ubu2004.lab.enterpriseadmins.org<\/code>.  I entered a good password, selected require password to log in and didn&#8217;t enable Active Directory (we&#8217;ll do that later).  <\/p>\n\n\n\n<p>After the final reboot, we&#8217;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&#8217;ll do this by entering <code>sudo apt install openssh-server -y<\/code>.  With that complete we can find our IP address &#8212; either from the vCenter Server &gt; VM &gt; Summary tab, or by typing <code>ip addr<\/code> at that terminal session.  We can then ssh into the system for the majority of the next configuration items.<\/p>\n\n\n\n<p>The first few changes I made were generic system wide changes.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># apply any system updates &amp; remove any obsolete packages\nsudo apt update &amp;&amp; sudo apt upgrade -y\nsudo apt clean &amp;&amp; sudo apt -y autoremove --purge\n\n# Prevent ctrl-alt-del from causing a reboot\nsudo systemctl mask ctrl-alt-del.target\n\n# Disable auto-suspend\nsudo systemctl unmask sleep.target suspend.target hibernate.target hybrid-sleep.target\n\n# refresh systemctl\nsudo systemctl daemon-reload\n\n# Disable auto-updates\nsudo sed -i 's\/APT::Periodic::Update-Package-Lists \"1\"\/APT::Periodic::Update-Package-Lists \"0\"\/' \/etc\/apt\/apt.conf.d\/20auto-upgrades\n\n# Disable LTS Upgrade MOTD\nsudo sed -i '16 s\/.*Prompt.*\/Prompt=never\/' \/etc\/update-manager\/release-upgrades\n\n# Remove some of the initial setup packages\nsudo apt remove --purge gnome-initial-setup gnome-online-accounts update-manager-core -y\n\n# setup script to generate new ssh keys at boot\ncat &lt;&lt; 'EOL' | sudo tee \/etc\/rc.local\n#!\/bin\/sh -e\n#\n# rc.local\n#\ntest -f \/etc\/ssh\/ssh_host_dsa_key || dpkg-reconfigure openssh-server\nexit 0\nEOL\n\n# make sure the script is executable\nsudo chmod +x \/etc\/rc.local<\/code><\/pre>\n\n\n\n<p>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&#8217;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 (<a href=\"https:\/\/docs.vmware.com\/en\/VMware-Horizon\/2111\/linux-desktops-setup\/GUID-D8E3A4AA-83E9-46A4-8BBA-824027146E93.html\">https:\/\/docs.vmware.com\/en\/VMware-Horizon\/2111\/linux-desktops-setup\/GUID-D8E3A4AA-83E9-46A4-8BBA-824027146E93.html<\/a>).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># install required components\nsudo apt install sssd sssd-tools realmd libnss-sss adcli samba-common-bin  -y\n\n# join the domain\necho '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\n\n# Tell pam.d to create the home directory at login\necho \"session required pam_mkhomedir.so skel=\/etc\/skel umask=0022\" | sudo tee \/etc\/pam.d\/common-session\n\n# Since we only have the one domain, lets use short names for most things\nsudo sed -i 's\/use_fully_qualified_names = True\/use_fully_qualified_names = False\/g' \/etc\/sssd\/sssd.conf\n\necho '%domain\\ users  ALL=(ALL) ALL,!ROOTONLY' | sudo tee -a \/etc\/sudoers\n# Note that '\\ ' is to escape the space between domain &amp; 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).\n\n# Note: I did need to delegate extra permissions to this service account compared to PBIS Open.  I followed this guide:\n# https:\/\/www.computertechblog.com\/active-directory-permissions-required-to-join-linux-and-windows-computers-to-a-domain\/<\/code><\/pre>\n\n\n\n<p>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 &#8212; there isn&#8217;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: <a href=\"https:\/\/askubuntu.com\/questions\/1028822\/disable-the-new-ubuntu-18-04-welcome-screen\">https:\/\/askubuntu.com\/questions\/1028822\/disable-the-new-ubuntu-18-04-welcome-screen<\/a> and I applied them all as they seemed somewhat hit or miss in my testing.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mkdir \/etc\/skel\/.config\nsudo touch \/etc\/skel\/.config\/gnome-initial-setup-done\nsudo sed -i '\/\\&#91;daemon\\]\/a InitialSetupEnable=false' \/etc\/gdm3\/custom.conf<\/code><\/pre>\n\n\n\n<p>I like to install a few packages to do administrative type activities.  These include:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>firefox &#8212; a web browser (installed by default)<\/li><li>net-tools &#8212; the legacy network tools like ifconfig<\/li><li>powershell \/ powercli &#8212; a scripting language &amp; module I use often<\/li><li>remmina &#8212; a remote desktop client<\/li><li>zenmap &#8212; a GUI for the nmap scanner<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code># install net-tools\nsudo apt install net-tools -y\n\n# install Powershell &amp; PowerCLI\n# Download the Microsoft repository GPG keys\nwget -q https:\/\/packages.microsoft.com\/config\/ubuntu\/20.04\/packages-microsoft-prod.deb\n\n# Register the Microsoft repository GPG keys\nsudo dpkg -i packages-microsoft-prod.deb\n\n# Update the list of products\nsudo apt-get update\n\n# Install PowerShell\nsudo apt-get install -y powershell\n\n# Start PowerShell, but as sudo se we can install PowerCLI for all users\nsudo pwsh\nInstall-Module vmware.powercli -scope:allusers -Confirm:$false\nSet-PowerCLIConfiguration -ParticipateInCeip $true -Scope:AllUsers -Confirm:$false\n\n# Confirm that VMware* modules are available in the \/usr\/local\/share\/powershell\/Modules path:\nls \/usr\/local\/share\/powershell\/Modules\nexit # this is to exit pwsh\n\n# Install remmina\nsudo apt install remmina -y\n\n# Install zenmap\nsudo apt install curl ndiff -y\n\nwget http:\/\/archive.ubuntu.com\/ubuntu\/pool\/universe\/p\/pygtk\/python-gtk2_2.24.0-5.1ubuntu2_amd64.deb\nsudo apt install .\/python-gtk2_2.24.0-5.1ubuntu2_amd64.deb -y\nwget http:\/\/archive.ubuntu.com\/ubuntu\/pool\/universe\/n\/nmap\/zenmap_7.60-1ubuntu5_all.deb\nsudo apt install .\/zenmap_7.60-1ubuntu5_all.deb -y\n\n# cleanup &amp; remove installers\nrm python-gtk2_2.24.0-5.1ubuntu2_amd64.deb packages-microsoft-prod.deb zenmap_7.60-1ubuntu5_all.deb<\/code><\/pre>\n\n\n\n<p>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.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo \"user-db:user\" | sudo tee \/etc\/dconf\/profile\/user\necho \"system-db:local\" | sudo tee -a \/etc\/dconf\/profile\/user\nsudo mkdir \/etc\/dconf\/db\/local.d\necho \"&#91;org\/gnome\/shell]\" | sudo tee \/etc\/dconf\/db\/local.d\/00-favorite-apps\necho \"favorite-apps = &#91;'firefox.desktop', 'org.remmina.Remmina.desktop', 'nautilus.desktop', 'gedit.desktop', 'gnome-terminal.desktop']\" | sudo tee -a \/etc\/dconf\/db\/local.d\/00-favorite-apps\nsudo dconf update<\/code><\/pre>\n\n\n\n<p>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&#8217;d like, but I wanted to leave the example in case.  The <code>gsettings<\/code> commands are per user only, so to make this setting available to other users that may use the pool, we&#8217;ll write them to a profile script that is executed at login.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo 'gsettings set org.gnome.desktop.lockdown disable-lock-screen true' | sudo tee \/etc\/profile.d\/02-weak-security.sh\necho 'gsettings set org.gnome.desktop.screensaver lock-delay 3600' | sudo tee -a \/etc\/profile.d\/02-weak-security.sh\necho 'gsettings set org.gnome.desktop.screensaver lock-enabled false' | sudo tee -a \/etc\/profile.d\/02-weak-security.sh\necho 'gsettings set org.gnome.desktop.screensaver idle-activation-enabled false' | sudo tee -a \/etc\/profile.d\/02-weak-security.sh<\/code><\/pre>\n\n\n\n<p>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 &amp; don&#8217;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.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/tmp\nwget http:\/\/www.example.com\/VMware-horizonagent-linux-x86_64-7.13.1-19066964.tar.gz\ntar -xzf VMware-horizonagent-linux-x86_64-7.13.1-19066964.tar.gz\ncd VMware-horizonagent-linux-x86_64-7.13.1-19066964\/\n.\/install_viewagent.sh -A yes -G yes\n\n# 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.\nsudo sed -i 's\/#Clipboard.Direction=1\/Clipboard.Direction=1\/g' \/etc\/vmware\/config\n\n# 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)\necho \"OfflineJoinDomain=sssd\" | sudo tee -a \/etc\/vmware\/viewagent-custom.conf<\/code><\/pre>\n\n\n\n<p>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: <a href=\"https:\/\/enterpriseadmins.org\/blog\/lab-infrastructure\/installing-windows-ca-root-certificate-on-linux-and-firefox\/\">https:\/\/enterpriseadmins.org\/blog\/lab-infrastructure\/installing-windows-ca-root-certificate-on-linux-and-firefox\/<\/a>.  I&#8217;m going to follow those steps in this golden image as well.<\/p>\n\n\n\n<p>To shut things down (now, and anytime we make changes to our template) I like to run the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># clean up the command history of the VM template-admin user\nsudo rm -rf \/tmp\/*\nsudo rm -rf \/var\/tmp\/*\nsudo rm -f \/etc\/ssh\/ssh_host_*\nhistory -c\nsudo shutdown -h now<\/code><\/pre>\n\n\n\n<p>I then like to edit the &#8216;Notes&#8217; property of the template with the date &amp; 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 <code>2021-12-29: Initial creation of Ubuntu 20.04 Non Persistent VDI Desktop<\/code>.  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.<\/p>\n\n\n\n<p>I hope you find this post helpful, feel free to drop any suggestions or comments below.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 &hellip; <a href=\"https:\/\/enterpriseadmins.org\/blog\/virtualization\/horizon-virtual-desktop-non-persistent-ubuntu-20-04\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[9,4],"tags":[],"class_list":["post-1619","post","type-post","status-publish","format-standard","hentry","category-lab-infrastructure","category-virtualization"],"_links":{"self":[{"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/posts\/1619","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/comments?post=1619"}],"version-history":[{"count":22,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/posts\/1619\/revisions"}],"predecessor-version":[{"id":1642,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/posts\/1619\/revisions\/1642"}],"wp:attachment":[{"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/media?parent=1619"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/categories?post=1619"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/tags?post=1619"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}