{"id":2001,"date":"2025-06-10T03:18:20","date_gmt":"2025-06-10T03:18:20","guid":{"rendered":"https:\/\/www.nicktailor.com\/?p=2001"},"modified":"2025-07-11T03:23:21","modified_gmt":"2025-07-11T03:23:21","slug":"how-to-deploy-a-custom-rocky-linux-image-in-azure-with-cloud-init","status":"publish","type":"post","link":"https:\/\/nicktailor.com\/tech-blog\/how-to-deploy-a-custom-rocky-linux-image-in-azure-with-cloud-init\/","title":{"rendered":"How to Deploy a Custom Rocky Linux Image in Azure with cloud-init"},"content":{"rendered":"<p>Need a clean, hardened Rocky Linux image in Azure \u2014 ready to go with your tools and configs? Here&#8217;s how to use <strong>Packer<\/strong> to build a Rocky image and then <strong>deploy it with cloud-init<\/strong> using Azure CLI.<\/p>\n<h2>Step 0: Install Azure CLI<\/h2>\n<p>Before deploying anything, make sure you have Azure CLI installed.<\/p>\n<h3>Linux\/macOS:<\/h3>\n<pre><code>curl -sL https:\/\/aka.ms\/InstallAzureCLIDeb | sudo bash<\/code><\/pre>\n<h3>Windows:<\/h3>\n<p>Download and install from <a href=\"https:\/\/aka.ms\/installazurecli\">https:\/\/aka.ms\/installazurecli<\/a><\/p>\n<h3>Login:<\/h3>\n<pre><code>az login<\/code><\/pre>\n<p>This opens a browser window for authentication. Once done, you&#8217;re ready to deploy.<\/p>\n<h2>Step 1: Build a Custom Image with Packer<\/h2>\n<p>Create a Packer template with Azure as the target and make sure <code>cloud-init<\/code> is installed during provisioning.<\/p>\n<h3>Packer Template Example (rocky-azure.pkr.hcl):<\/h3>\n<pre><code>source \"azure-arm\" \"rocky\" {\n  client_id       = var.client_id\n  client_secret   = var.client_secret\n  tenant_id       = var.tenant_id\n  subscription_id = var.subscription_id\n\n  managed_image_resource_group_name = \"packer-images\"\n  managed_image_name                = \"rocky-image\"\n  location                          = \"East US\"\n  os_type                           = \"Linux\"\n  image_publisher                   = \"OpenLogic\"\n  image_offer                       = \"CentOS\"\n  image_sku                         = \"8_2\"\n  vm_size                           = \"Standard_B1s\"\n  build_resource_group_name         = \"packer-temp\"\n}\n\nbuild {\n  sources = [\"source.azure-arm.rocky\"]\n\n  provisioner \"shell\" {\n    inline = [\n      \"dnf install -y cloud-init\",\n      \"systemctl enable cloud-init\"\n    ]\n  }\n}<\/code><\/pre>\n<h3>Variables File (variables.pkrvars.hcl):<\/h3>\n<pre><code>client_id       = \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\nclient_secret   = \"your-secret\"\ntenant_id       = \"your-tenant-id\"\nsubscription_id = \"your-subscription-id\"<\/code><\/pre>\n<h3>Build the Image:<\/h3>\n<pre><code>packer init .\npacker build -var-file=variables.pkrvars.hcl .<\/code><\/pre>\n<h2>Step 2: Prepare a Cloud-init Script<\/h2>\n<p>This will run the first time the VM boots and set things up.<\/p>\n<h3>cloud-init.yaml:<\/h3>\n<pre><code>#cloud-config\nhostname: rocky-demo\nusers:\n  - name: devops\n    sudo: ALL=(ALL) NOPASSWD:ALL\n    groups: users, admin\n    shell: \/bin\/bash\n    ssh_authorized_keys:\n      - ssh-rsa AAAA...your_key_here...\n\nruncmd:\n  - yum update -y\n  - echo 'Cloud-init completed!' &gt; \/etc\/motd<\/code><\/pre>\n<h2>Step 3: Deploy the VM in Azure<\/h2>\n<p>Use the Azure CLI to deploy a VM from the managed image and inject the <code>cloud-init<\/code> file.<\/p>\n<pre><code>az vm create \\\n  --resource-group my-rg \\\n  --name rocky-vm \\\n  --image \/subscriptions\/&lt;SUB_ID&gt;\/resourceGroups\/packer-images\/providers\/Microsoft.Compute\/images\/rocky-image \\\n  --admin-username azureuser \\\n  --generate-ssh-keys \\\n  --custom-data cloud-init.yaml<\/code><\/pre>\n<h2>Step 4: Verify Cloud-init Ran<\/h2>\n<pre><code>ssh azureuser@&lt;public-ip&gt;\ncat \/etc\/motd<\/code><\/pre>\n<p>You should see:<\/p>\n<pre><code>Cloud-init completed!<\/code><\/pre>\n<h2>Recap<\/h2>\n<ul>\n<li><strong>Install Azure CLI<\/strong> and authenticate with <code>az login<\/code><\/li>\n<li><strong>Packer<\/strong> creates a reusable Rocky image with <code>cloud-init<\/code> preinstalled<\/li>\n<li><strong>Cloud-init<\/strong> configures the VM at first boot using a YAML script<\/li>\n<li><strong>Azure CLI<\/strong> deploys the VM and injects custom setup<\/li>\n<\/ul>\n<p>By combining Packer and cloud-init, you ensure your Azure VMs are fast, consistent, and ready from the moment they boot.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Need a clean, hardened Rocky Linux image in Azure \u2014 ready to go with your tools and configs? Here&#8217;s how to use Packer to build a Rocky image and then deploy it with cloud-init using Azure CLI. Step 0: Install Azure CLI Before deploying anything, make sure you have Azure CLI installed. Linux\/macOS: curl -sL https:\/\/aka.ms\/InstallAzureCLIDeb | sudo bash Windows:<a href=\"https:\/\/nicktailor.com\/tech-blog\/how-to-deploy-a-custom-rocky-linux-image-in-azure-with-cloud-init\/\" class=\"read-more\">Read More &#8230;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[146,138],"tags":[],"class_list":["post-2001","post","type-post","status-publish","format-standard","hentry","category-azure","category-linux"],"_links":{"self":[{"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/posts\/2001","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/comments?post=2001"}],"version-history":[{"count":5,"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/posts\/2001\/revisions"}],"predecessor-version":[{"id":2010,"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/posts\/2001\/revisions\/2010"}],"wp:attachment":[{"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/media?parent=2001"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/categories?post=2001"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/tags?post=2001"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}