Basic Patterns for creating base images from vms

  • 6 February 2024
  • 7 replies

I have been relatively successful using a blueprint to define all the tasks and installations to create a solid VM. I now want to bake this VM into an image, so it has all those tasks already performed on it. I tried creating a VM template, but when i launch an instance from it, it has no Dynamic IP assigned.


What is, or can someone point me to, the best practice/standard pattern for building a catalog of images with various apps and tasks pre-baked-in, so we don’t have to apply their installation every time?


7 replies

Userlevel 4
Badge +5

NCM Self-Service provides an option to create an image from an application. This is available for both blueprint type deployments.

Once the image is in PC Image Service, it can be used by NCM Self-Service as well as PC VM deployment.

For the specific issue around networking, it depends on OS basis. You’ll have to make sure to comply with whatever your OS distribution requirements are for generalizing images.

Also, curious the use case for using VM template instead of continue deploying the workloads through NCM Self-Service.

(This is the third time i’m writing this due to crashes in this support page. please forgive any terseness.)


My goal is to provide a suite of marketplace items/blueprints for deploying various infra on our system… single “base” vms, multi-vm base clusters, up to multi-vm pre-configured Mongo or RabbitMQ clusters, for example.

My assumption is that the basic process is to get a VM/application into a state you like, and then save that as a deployable image. 

My scenario: i take a VM from an application i’ve deployed with a blueprint that does a bunch of configuration tasks, and create an image from the boot disk. I then use that disk in another blueprint/vm template (same result either way), but it does not result in a useable VM. It is not pingable, and when i connect with Launch Console, i almost always get an unuseable shell.

I’m sure i’m doing something wrong/inefficient, but i can’t find docs or articles on any best practices/patterns for this. Anything you can point me to will be appreciated!



Userlevel 4
Badge +5

Make sure as part of the deployment from the golden image you still pass bootstrap configuration. For Windows with sysprep, and for Linux with cloud-init. That’s the standard approach for customizing the VM deployment.

so in the blueprint ive been developing, the cloud-init portion includes these steps:

  1. create two users
  2. update /etc/environment with internal proxy servers
  3. update /etc/yum.conf with internal proxy server
  4. run sudo yum update/upgrade
  5. install epel-release repo
  6. set `ssh_pwauth = true`
  7. restart sshd

All of that is still necessary even when using a prebaked image?

Is there anything else I should add in there?


Userlevel 4
Badge +5

You’ll have to check the OS documentation on how to generalize/capture an image since it is different between them.

Network issues with cloud-init are usually related to persistent-net.rules/network-scripts

once again, this site ate my long reply….


After looking into your clue of `persistent-net.rules` etc with chatgpt, i’m putting together a script to clean up and prepare the disk for imaging. I’ll reply back with what i come up with.

So, I put together a script to run on a VM prior to imaging it, to wipe off temp files, logs, and any static configuration that needs to be overridden when provisioning a new VM. It doesn’t change the result at all. I still get a boot screen. I am still doing the cloud-init setup in the blueprint.

[7.233640] fbcon: bochsdrmfb (fb0) is primary device
[7.245908] Console: switching to colour frame buffer device 128x48
[7.248205] bochs-drm 0000:00:02.0: fb0: bochsdrmfb frame buffer device
[7.251292] AVX2 version of gcm_enc/dec engaged
[7.251733] AES CTR mode by8 optimization enabled
[7.273877] [drm] Initialized bochs-drm 1.0.0 20130925 for 0000:00:02.0 on minor 0
[7.307776] ppdev: user-space parallel port driver
[7.310521] alg: No test for __gcm-aes-aesni (__driver-gcm-aes-aesni)
[7.311678] alg: No test for __generic-gcm-aes-aesni (__driver-generic-gcm-aes-aesni)
[95.427101] type=1305 audit(1707339485.932:4): audit_pid=590 old=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:auditd_t:s0 res=1

I am creating the disk image as shown below. Am i selecting the right one? The 250 GB disk is the data disk. Not sure what the IDE disk is.

The prep script:


# Step 1: Clean Up Temporary Files and Logs
echo "Cleaning up temporary files and logs..."
rm -rf /tmp/*
rm -rf /var/tmp/*

logrotate -f /etc/logrotate.conf

rm -f /var/log/*-???????? /var/log/*.gz
rm -f /var/log/dmesg.old
rm -f /var/log/anaconda/*
rm -rf /var/log/*.log

# Step 2: Remove SSH Keys
echo "Removing SSH keys..."
rm -f /etc/ssh/ssh_host_*

echo "Regenerate new SSH host keys..."
ssh-keygen -A

# Step 3: Handle Network Configuration (Remove persistent-net.rules if exists)
echo "Handling network configuration..."

# Ensure predictable network interface names are used (handled by default in CentOS 7)
# Remove any custom udev rules that may affect network interface naming
rm -f /etc/udev/rules.d/70-persistent-net.rules

# Check if the symlink /etc/udev/rules.d/80-net-name-slot.rules exists and points to /dev/null
if [ "$(readlink -f /etc/udev/rules.d/80-net-name-slot.rules)" != "/dev/null" ]; then
# Remove the existing file or symlink if it does not point to /dev/null
rm -f /etc/udev/rules.d/80-net-name-slot.rules
# Create the symlink pointing to /dev/null
ln -s /dev/null /etc/udev/rules.d/80-net-name-slot.rules
echo "Created symlink /etc/udev/rules.d/80-net-name-slot.rules pointing to /dev/null."
echo "Symlink /etc/udev/rules.d/80-net-name-slot.rules already points to /dev/null."

# Optional: Remove specific network configurations if needed
# rm -f /etc/sysconfig/network-scripts/ifcfg-eth*

# Step 4: Reset Hostname
echo "Resetting hostname..."
hostnamectl set-hostname localhost.localdomain

# Step 5: Regenerate Machine ID
echo "Regenerating machine ID..."
rm -f /etc/machine-id
touch /etc/machine-id

# Step 6: Prepare cloud-init
echo "Preparing cloud-init..."
cloud-init clean

# Step 7: Clean YUM cache
echo "Cleaning YUM cache..."
yum clean all

# Enable and start the SSH service
systemctl enable sshd
systemctl start sshd

# Allow SSH through the firewall
firewall-cmd --permanent --add-service=ssh
firewall-cmd --reload

echo "Syncing filesystem..."

# Notify user script has finished
echo "Preparation complete. The system is ready for image capture. Shutting down now..."
shutdown -h now