One of the issues you may encounter with ESXi is the fact that it doesn't offer an option to natively clone VMs. Of course, you can just copy necessary files and then just register the VM in ESXi, but that will still use file names that are in the original VM. I don't like this, so I am going to show you all the steps in 'cloning' the VM (basically just copying the necessary files from one location to another) and then making changes to the
.vmdk files to reflect new naming convention.
This whole process is extremely useful when you make a golden template of a VM that you want to use in the future. This way you can avoid installing the VMs whenever you need a new instance up and running. Make sure that you set everything up in your VM and once done, follow this process.
ESXi VM cloning
Let's start by selecting
Storage on the left side of the screen, and then selecting
Datastore browser. That will open another window where we will click on
Enter the name of the new directory and press
Once the directory is created, position yourself in the directory that holds your existing VM that you want to use a source. Select the
.vmx file first, right click and click on
This will open another window where you need to select a destination folder for this file:
We will select previously created folder and then click on
.vmx file is very quick and you may not even notice status bar at the bottom of the screen changing.
Next, we will copy
.vmdk file. This is basically your whole hard disk. This process may take some time, depending on your infrastructure (whether you're using SSDs or NVMe drives or regular HDDs).
Same as before, select your source
.vmdk file, right click and select
Next, select the directory where you want to copy the file to:
As I mentioned, this may take some time, so watch your status bar for progress:
If you don't want to deal with changing the name of the files and references in the files you copied, you can jump to the end of this post where I explain on how to register the newly copied VM. If you want to make sure that everything is named exactly as you want it, continue reading.
Changes in the CLI
Before you continue, make sure that
SSH server is running on your ESXi instance:
If it's not, just click on
Services and select
TSM-SSH service and click on
SSH service will now be enabled, until the restart of the ESXi server. It will complain about SSH running next time you log into the system, but you can ignore that message. VMWare insists that running SSH on a server is not a great idea, so I will leave it up to you if you want to leave it running or disabling it after you're done with the changes we are about to make.
So, with this all out of the way, let's connect to our ESXi via SSH. Use
root credentials to log in and you will be greeted with prompt like this:
╰─>$ ssh [email protected] ([email protected]) Password: The time and date of this login have been sent to the system logs. WARNING: All commands run on the ESXi shell are logged and may be included in support bundles. Do not provide passwords directly on the command line. Most tools can prompt for secrets or accept them from standard input. VMware offers powerful and supported automation tools. Please see https://developer.vmware.com for details. The ESXi Shell can be disabled by an administrative user. See the vSphere Security documentation for more information. [root@esxi-ntg:~]
Position yourself in the directory you previously created in GUI:
[root@esxi-ntg:~] cd /vmfs/volumes/datastore1/Debian\ Desktop\ -\ 02/ [root@esxi-ntg:/vmfs/volumes/64b6cb2a-91d9a1d5-800b-005056902e9a/Debian Desktop - 02]
Datastores are available under
/vmfs/volumes, followed by the datastore name - in my case that is
datastore1, which is the default name given by ESXi when you install the system. If you changed the name of the datastore, this will be different for you. After that, comes the name of the directory you created.
Let's list all the files in that directory:
[root@esxi-ntg:/vmfs/volumes/64b6cb2a-91d9a1d5-800b-005056902e9a/Debian Desktop - 02] ls -alh total 9016448 drwxr-xr-x 1 root root 72.0K Jul 23 20:12 . drwxr-xr-t 1 root root 76.0K Jul 23 19:59 .. -rw------- 1 root root 100.0G Jul 23 20:01 Debian Desktop - 01-flat.vmdk -rw------- 1 root root 564 Jul 23 20:12 Debian Desktop - 01.vmdk -rw------- 1 root root 3.4K Jul 23 20:00 Debian Desktop - 01.vmx
You will notice that there are actually 3 files there, not only 2 that we used to copy everything - a
.vmx file, a
.vmdk file and a new one called
-flat.vmdk. Notice that the size of the
-flat.vmdk file is actually the size of the HDD you assigned to your VM when you created it.
Let's customize this a little bit. Instead of having names of the previous VM, we will rename them so that it reflects the names of the new VM. I'm going to make this simple, so I will just choose
Debian Desktop - 02, but you can choose whatever name you want.
We will simply rename files:
[root@esxi-ntg:/vmfs/volumes/64b6cb2a-91d9a1d5-800b-005056902e9a/Debian Desktop - 02] mv 'Debian Desktop - 01-flat.vmdk' 'Debian Desktop - 02-flat .vmdk' [root@esxi-ntg:/vmfs/volumes/64b6cb2a-91d9a1d5-800b-005056902e9a/Debian Desktop - 02] mv 'Debian Desktop - 01.vmdk' 'Debian Desktop - 02.vmdk' [root@esxi-ntg:/vmfs/volumes/64b6cb2a-91d9a1d5-800b-005056902e9a/Debian Desktop - 02] mv 'Debian Desktop - 01.vmx' 'Debian Desktop - 02.vmx'
Note that I'm using single quotes
' between names, as there are spaces in the names of the files so this way I'm sure that right files are being renamed. Make sure that you use the quote before and after the name of the file!
Finally, we have our new file names:
[root@esxi-ntg:/vmfs/volumes/64b6cb2a-91d9a1d5-800b-005056902e9a/Debian Desktop - 02] ls -alh total 9016448 drwxr-xr-x 1 root root 72.0K Jul 23 20:41 . drwxr-xr-t 1 root root 76.0K Jul 23 19:59 .. -rw------- 1 root root 100.0G Jul 23 20:01 Debian Desktop - 02-flat.vmdk -rw------- 1 root root 564 Jul 23 20:12 Debian Desktop - 02.vmdk -rw------- 1 root root 3.4K Jul 23 20:00 Debian Desktop - 02.vmx
Now, with this out of the way, the easy part is done. We still need to change name references in
.vmx files. DO NOT try to open
-flat.vmdk file in your editor!
Unfortunately, ESXi only comes with
vi editor - if you're not familiar with it, you can always go back to GUI and download these two files from ESXi server to your local computer and edit them in
Notepad or whatever you're using on your local computer and edit it there. Since this is not a
vi tutorial, we will do exactly that, but if you're comfortable in using it, you can just make changes there directly and save them. I believe that most homelabers are not, so I will show you how to download the files, make changes and the upload it back to the server.
So, open your datastore browser and download both
.vmx files. Once again, make sure that you're not selecting the
-flat.vmdk file while doing this!
.vmdk file and there is only one reference to the name of the
-flat.vmdk inside of double quotes
". Make your change there and save the file:
Now, open the second file (
.vmx) and look for any references of the old name. Depending on your VM, it will have a few variables that need to be changed. In my case, these were the variables that needed to be changed to reflect the new names:
"Debian Desktop - 02.vmdk"
"Debian Server - 02"
"Debian Desktop - 02.scoreboard"
"/vmfs/volumes/64b6cb2a-91d9a1d5-800b-005056902e9a/Debian Desktop - 02/Debian Desktop - 02-b2f95b67.vswp"
"./Debian Desktop - 02-e139194a.hlog"
Save the file and upload both files back to your ESXi server. After the upload, let's check if everything is as it should be:
[root@esxi-ntg:/vmfs/volumes/64b6cb2a-91d9a1d5-800b-005056902e9a/Debian Desktop - 02] cat 'Debian Desktop - 02.vmdk' # Disk DescriptorFile version=1 encoding="UTF-8" CID=018c325a parentCID=ffffffff createType="vmfs" # Extent description RW 209715200 VMFS "Debian Desktop - 02-flat.vmdk" # The Disk Data Base #DDB ddb.adapterType = "buslogic" ddb.deletable = "true" ddb.geometry.cylinders = "13054" ddb.geometry.heads = "255" ddb.geometry.sectors = "63" ddb.longContentID = "f1d4fc7a314c3e2b047794eb018c325a" ddb.thinProvisioned = "1" ddb.toolsInstallType = "4" ddb.toolsVersion = "12352" ddb.uuid = "60 00 C2 91 5c 00 a6 1e-89 32 0d de 86 e7 c2 0d" ddb.virtualHWVersion = "14"
Notice that it shows the new name of the file, so this file was successfully uploaded. Let's check the
[root@esxi-ntg:/vmfs/volumes/64b6cb2a-91d9a1d5-800b-005056902e9a/Debian Desktop - 02] cat 'Debian Desktop - 02.vmx' .encoding = "UTF-8" config.version = "8" virtualHW.version = "20" vmci0.present = "TRUE" floppy0.present = "FALSE" svga.vramSize = "268435456" numvcpus = "4" memSize = "4096" bios.bootRetry.delay = "10" powerType.suspend = "soft" tools.upgrade.policy = "manual" sched.cpu.units = "mhz" sched.cpu.affinity = "all" vm.createDate = "1689709598501053" scsi0.virtualDev = "pvscsi" scsi0.present = "TRUE" sata0.present = "TRUE" usb.present = "TRUE" ehci.present = "TRUE" scsi0:0.deviceType = "scsi-hardDisk" scsi0:0.fileName = "Debian Desktop - 02.vmdk" sched.scsi0:0.shares = "normal" sched.scsi0:0.throughputCap = "off" scsi0:0.present = "TRUE" ethernet0.virtualDev = "vmxnet3" ethernet0.networkName = "VLAN200-Business" ethernet0.addressType = "generated" ethernet0.wakeOnPcktRcv = "FALSE" ethernet0.uptCompatibility = "TRUE" ethernet0.present = "TRUE" displayName = "Debian Server - 02" guestOS = "debian12-64" toolScripts.afterPowerOn = "TRUE" toolScripts.afterResume = "TRUE" toolScripts.beforeSuspend = "TRUE" toolScripts.beforePowerOff = "TRUE" tools.syncTime = "FALSE" uuid.bios = "56 4d d6 f4 b8 53 be 03-ec 2c 98 cb ae 7a b6 03" uuid.location = "56 4d d6 f4 b8 53 be 03-ec 2c 98 cb ae 7a b6 03" vc.uuid = "52 0b 71 c4 41 49 dd 21-af ac e6 8d 81 52 62 87" sched.cpu.min = "0" sched.cpu.shares = "normal" sched.mem.min = "0" sched.mem.minSize = "0" sched.mem.shares = "normal" ethernet0.generatedAddress = "00:0c:29:7a:b6:03" vmci0.id = "-657187315" cleanShutdown = "TRUE" cpuid.coresPerSocket = "1" tools.guest.desktop.autolock = "TRUE" nvram = "Debian Desktop - 02.nvram" svga.present = "TRUE" pciBridge0.present = "TRUE" pciBridge4.present = "TRUE" pciBridge4.virtualDev = "pcieRootPort" pciBridge4.functions = "8" pciBridge5.present = "TRUE" pciBridge5.virtualDev = "pcieRootPort" pciBridge5.functions = "8" pciBridge6.present = "TRUE" pciBridge6.virtualDev = "pcieRootPort" pciBridge6.functions = "8" pciBridge7.present = "TRUE" pciBridge7.virtualDev = "pcieRootPort" pciBridge7.functions = "8" hpet0.present = "TRUE" RemoteDisplay.maxConnections = "-1" sched.cpu.latencySensitivity = "normal" vmxstats.filename = "Debian Desktop - 02.scoreboard" numa.autosize.cookie = "40012" numa.autosize.vcpu.maxPerVirtualNode = "4" sched.swap.derivedName = "/vmfs/volumes/64b6cb2a-91d9a1d5-800b-005056902e9a/Debian Desktop - 02/Debian Desktop - 02-b2f95b67.vswp" pciBridge0.pciSlotNumber = "17" pciBridge4.pciSlotNumber = "21" pciBridge5.pciSlotNumber = "22" pciBridge6.pciSlotNumber = "23" pciBridge7.pciSlotNumber = "24" scsi0.pciSlotNumber = "160" usb.pciSlotNumber = "32" ethernet0.pciSlotNumber = "192" ehci.pciSlotNumber = "33" sata0.pciSlotNumber = "34" scsi0.sasWWID = "50 05 05 64 b8 53 be 00" vmotion.checkpointFBSize = "4194304" vmotion.checkpointSVGAPrimarySize = "268435456" vmotion.svga.mobMaxSize = "268435456" vmotion.svga.graphicsMemoryKB = "262144" ethernet0.generatedAddressOffset = "0" monitor.phys_bits_used = "45" softPowerOff = "TRUE" usb:1.speed = "2" usb:1.present = "TRUE" usb:1.deviceType = "hub" usb:1.port = "1" usb:1.parent = "-1" svga.guestBackedPrimaryAware = "TRUE" guestInfo.detailed.data = "architecture='X86' bitness='64' distroAddlVersion='12 (bookworm)' distroName='Debian GNU/Linux' distroVersion='12' familyName='Linux' kernelVersion='6.1.0-10-amd64' prettyName='Debian GNU/Linux 12 (bookworm)'" tools.remindInstall = "FALSE" migrate.hostLog = "./Debian Desktop - 02-e139194a.hlog" scsi0:0.redo = "" usb:0.present = "TRUE" usb:0.deviceType = "hid" usb:0.port = "0" usb:0.parent = "-1"
It seems that this file is also OK now, so let's go and import our new/old VM into ESXi.
Importing the cloned VM to ESXi
Virtual Machines in the menu on the left side of the screen, then click on
Create / Register VM and select
Register an existing virtual machine:
NEXT and in the next window click on
Datastore browser window will open, so position yourself in the directory of your new VM and select the
.vmx file and click on
SELECT after that:
This will take you back to the previous window, with the newly selected VM in the list. Click on
Finally, your new VM is ready to be imported:
FINISH to finalise the process.
Your new VM should show up on the list of VMs and you should be able to start it by clicking on the
Power on button at the top.
A message will appear immediately after you press on
Power on button:
As you can see, it asks you what you actually did with the VM, and by default
I Copied It is selected. Since we made changes in all the necessary files, we can actually select
I Moved It, as there are no changes necessary to be made:
If you didn't follow this whole procedure and jumped to the bottom of this post immediately after copying the
.vmdk files at the beginning, make sure to choose
I Copied It option, as this will allow ESXi to make necessary changes to the
.vmdk files - although, if you go back to CLI, you will notice that the naming convention is still using old names from the source VM, just the references in the files have changed.
One last thing - when your new VM has started, make sure to change the IP address (if assigned statically) and the name of the VM.
And this is the end of this article. Hopefully you find it useful, and if you have any questions or comments, leave them in the comments section.