{"id":1036,"date":"2026-07-19T05:17:10","date_gmt":"2026-07-19T05:17:10","guid":{"rendered":"https:\/\/www.devopsschool.com\/tutorials\/?p=1036"},"modified":"2026-07-19T05:17:11","modified_gmt":"2026-07-19T05:17:11","slug":"azure-storage-services-lab-using-an-existing-ubuntu-24-04-vm","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/tutorials\/azure-storage-services-lab-using-an-existing-ubuntu-24-04-vm\/","title":{"rendered":"Azure Storage Services Lab Using an Existing Ubuntu 24.04 VM"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Blob Storage, Azure Files and Managed Disks<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Interface:<\/strong> Azure portal for resource creation and configuration<br><strong>Client system:<\/strong> Existing Azure VM running Ubuntu Server 24.04 LTS<br><strong>Validation date:<\/strong> July 19, 2026<br><strong>Authentication model:<\/strong> Managed identity for Blob Storage; storage account key for the introductory Azure Files SMB exercise<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">1. Lab objectives<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">By completing this lab, the student will be able to:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create a general-purpose v2 Azure storage account.<\/li>\n\n\n\n<li>Create and use a private Blob Storage container.<\/li>\n\n\n\n<li>Enable a system-assigned managed identity on an existing Ubuntu VM.<\/li>\n\n\n\n<li>Grant the VM permission to access Blob Storage without storing credentials.<\/li>\n\n\n\n<li>Upload, list and download blobs from Ubuntu.<\/li>\n\n\n\n<li>Create an SMB Azure file share.<\/li>\n\n\n\n<li>Mount the Azure file share on Ubuntu 24.04.<\/li>\n\n\n\n<li>Configure the file share to mount after a reboot.<\/li>\n\n\n\n<li>Create and attach an Azure managed data disk.<\/li>\n\n\n\n<li>Partition, format and permanently mount the disk.<\/li>\n\n\n\n<li>Transfer a file across the managed disk, Azure Files and Blob Storage.<\/li>\n\n\n\n<li>Validate and safely clean up all lab resources.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">2. Lab architecture<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>Azure Portal\n    |\n    +-- Existing Ubuntu 24.04 VM\n    |       |\n    |       +-- System-assigned managed identity\n    |       +-- \/datadrive          -&gt; Azure Managed Disk\n    |       +-- \/mnt\/azurefiles     -&gt; Azure Files SMB share\n    |       +-- Azure CLI           -&gt; Azure Blob Storage\n    |\n    +-- Standard GPv2 Storage Account\n            |\n            +-- Private blob container: blob-lab\n            +-- SMB file share: files-lab\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The VM accesses Blob Storage by using Microsoft Entra ID and Azure RBAC. Microsoft recommends Microsoft Entra credentials for Blob Storage data operations, and Azure VMs can authenticate through a managed identity without storing passwords, keys or service-principal secrets.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">3. Required permissions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The student needs permission to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>View and connect to the existing VM.<\/li>\n\n\n\n<li>Modify the VM to enable its managed identity.<\/li>\n\n\n\n<li>Create a storage account.<\/li>\n\n\n\n<li>Attach a data disk to the VM.<\/li>\n\n\n\n<li>Assign an Azure role to the VM&#8217;s managed identity.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A role such as <strong>Contributor<\/strong> can create and modify resources but does not necessarily allow role assignments. Assigning Azure roles requires <code>Microsoft.Authorization\/roleAssignments\/write<\/code>, available through roles such as <strong>Role Based Access Control Administrator<\/strong> or <strong>User Access Administrator<\/strong>. An instructor can preconfigure the managed-identity role assignment when students do not have this permission.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The VM must also have:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SSH connectivity.<\/li>\n\n\n\n<li>Outbound HTTPS access on TCP 443.<\/li>\n\n\n\n<li>Outbound SMB access on TCP 445 for Azure Files.<\/li>\n\n\n\n<li><code>sudo<\/code> access inside Ubuntu.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">4. Naming worksheet<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Replace these sample values with values assigned by the instructor.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Resource<\/th><th>Lab value<\/th><\/tr><\/thead><tbody><tr><td>Existing VM<\/td><td><code>&lt;vm-name&gt;<\/code><\/td><\/tr><tr><td>Resource group<\/td><td><code>&lt;vm-resource-group&gt;<\/code><\/td><\/tr><tr><td>Azure region<\/td><td>Same region as the VM<\/td><\/tr><tr><td>Storage account<\/td><td><code>stlab&lt;initials&gt;&lt;digits&gt;<\/code><\/td><\/tr><tr><td>Blob container<\/td><td><code>blob-lab<\/code><\/td><\/tr><tr><td>Azure file share<\/td><td><code>files-lab<\/code><\/td><\/tr><tr><td>Managed disk<\/td><td><code>disk-lab-data-01<\/code><\/td><\/tr><tr><td>File share mount point<\/td><td><code>\/mnt\/azurefiles<\/code><\/td><\/tr><tr><td>Managed disk mount point<\/td><td><code>\/datadrive<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Storage account names must be globally unique, contain only lowercase letters and numbers, and be between 3 and 24 characters long.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Exercise 1: Inspect the existing Ubuntu VM<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1.1: Open the VM<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Sign in to the Azure portal.<\/li>\n\n\n\n<li>In the portal search bar, enter <strong>Virtual machines<\/strong>.<\/li>\n\n\n\n<li>Select <strong>Virtual machines<\/strong>.<\/li>\n\n\n\n<li>Select the existing Ubuntu 24.04 VM.<\/li>\n\n\n\n<li>On the <strong>Overview<\/strong> page, record:\n<ul class=\"wp-block-list\">\n<li>VM name<\/li>\n\n\n\n<li>Resource group<\/li>\n\n\n\n<li>Subscription<\/li>\n\n\n\n<li>Location<\/li>\n\n\n\n<li>Public IP address, when present<\/li>\n\n\n\n<li>Virtual network and subnet<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Confirm that the VM status is <strong>Running<\/strong>.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1.2: Connect to Ubuntu<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">From the VM page:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Select <strong>Connect<\/strong>.<\/li>\n\n\n\n<li>Select <strong>Connect via SSH<\/strong> or the SSH option available in the portal.<\/li>\n\n\n\n<li>Copy the displayed SSH command.<\/li>\n\n\n\n<li>Run it from a terminal that has access to the VM.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh &lt;admin-username&gt;@&lt;vm-public-ip&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Validate the operating system:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat \/etc\/os-release\nuname -r\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected result:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME=\"Ubuntu\"\nVERSION=\"24.04...\"\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Exercise 2: Create the storage account<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">This lab uses a Standard general-purpose v2 account. The <strong>Preferred storage type<\/strong> selection only customizes the portal guidance; it does not prevent the account from using other supported storage services. Therefore, selecting Azure Files still allows Blob Storage containers to be created in the same GPv2 account.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2.1: Start storage account creation<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>In the Azure portal search bar, enter <strong>Storage accounts<\/strong>.<\/li>\n\n\n\n<li>Select <strong>Storage accounts<\/strong>.<\/li>\n\n\n\n<li>Select <strong>Create<\/strong>.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2.2: Configure the Basics tab<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Enter the following values:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Setting<\/th><th>Value<\/th><\/tr><\/thead><tbody><tr><td>Subscription<\/td><td>The subscription containing the VM<\/td><\/tr><tr><td>Resource group<\/td><td>The VM resource group or an instructor-provided lab resource group<\/td><\/tr><tr><td>Storage account name<\/td><td>Your globally unique name<\/td><\/tr><tr><td>Region<\/td><td>Same region as the VM<\/td><\/tr><tr><td>Preferred storage type<\/td><td>Azure Files<\/td><\/tr><tr><td>Performance<\/td><td>Standard<\/td><\/tr><tr><td>File share billing<\/td><td>Pay-as-you-go<\/td><\/tr><tr><td>Redundancy<\/td><td>Locally-redundant storage, or LRS<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Using pay-as-you-go allows the same StorageV2 account to host both blobs and an HDD-backed SMB file share. Microsoft currently recommends provisioned v2 for new production Azure Files workloads, but pay-as-you-go remains fully supported and is suitable for a small multipurpose training account.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2.3: Configure the Advanced tab<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Use these settings:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Setting<\/th><th>Lab selection<\/th><\/tr><\/thead><tbody><tr><td>Require secure transfer for REST API operations<\/td><td>Enabled<\/td><\/tr><tr><td>Allow storage account key access<\/td><td>Enabled<\/td><\/tr><tr><td>Enable hierarchical namespace<\/td><td>Disabled<\/td><\/tr><tr><td>Enable SFTP<\/td><td>Disabled<\/td><\/tr><tr><td>Enable NFS v3<\/td><td>Disabled<\/td><\/tr><tr><td>Blob access tier<\/td><td>Hot<\/td><\/tr><tr><td>Enable Managed Identity for SMB<\/td><td>Disabled for the core lab<\/td><\/tr><tr><td>Require Encryption in Transit for SMB<\/td><td>Enabled<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Storage account key access remains enabled because the core Azure Files exercise uses the broadly supported SMB account-key mounting method. Blob Storage will still use managed identity rather than the account key.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2.4: Configure the Networking tab<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For a classroom lab, configure:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Setting<\/th><th>Lab selection<\/th><\/tr><\/thead><tbody><tr><td>Public network access<\/td><td>Enabled<\/td><\/tr><tr><td>Public network access scope<\/td><td>Enable from all networks<\/td><\/tr><tr><td>Routing preference<\/td><td>Microsoft network routing<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This selection reduces lab failures caused by missing network rules. For production, restrict the storage account through selected virtual networks, private endpoints or another approved network-security model. Azure Storage firewall rules can restrict access by subnet, IP address, resource instance or trusted-service exception.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2.5: Create the account<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Select <strong>Review + create<\/strong>.<\/li>\n\n\n\n<li>Wait for validation to succeed.<\/li>\n\n\n\n<li>Select <strong>Create<\/strong>.<\/li>\n\n\n\n<li>After deployment succeeds, select <strong>Go to resource<\/strong>.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Validation checkpoint<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">On the storage account <strong>Overview<\/strong> page, confirm:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Status is available.<\/li>\n\n\n\n<li>Performance is Standard.<\/li>\n\n\n\n<li>Redundancy is LRS.<\/li>\n\n\n\n<li>Account kind is StorageV2.<\/li>\n\n\n\n<li>Primary location matches the VM region.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Exercise 3: Create the Blob Storage container<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3.1: Create a private container<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the storage account.<\/li>\n\n\n\n<li>Under <strong>Data storage<\/strong>, select <strong>Containers<\/strong>.<\/li>\n\n\n\n<li>Select <strong>+ Container<\/strong>.<\/li>\n\n\n\n<li>Enter:<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Setting<\/th><th>Value<\/th><\/tr><\/thead><tbody><tr><td>Name<\/td><td><code>blob-lab<\/code><\/td><\/tr><tr><td>Anonymous access level<\/td><td>Private \u2014 no anonymous access<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<ol start=\"5\" class=\"wp-block-list\">\n<li>Select <strong>Create<\/strong>.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Containers hold blobs, and the default private access level prevents anonymous public access.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Validation checkpoint<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The <strong>Containers<\/strong> page should now list:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>blob-lab\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Exercise 4: Enable the VM managed identity<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4.1: Enable the system-assigned identity<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open <strong>Virtual machines<\/strong>.<\/li>\n\n\n\n<li>Select the Ubuntu VM.<\/li>\n\n\n\n<li>Under <strong>Security<\/strong>, select <strong>Identity<\/strong>.<\/li>\n\n\n\n<li>Select the <strong>System assigned<\/strong> tab.<\/li>\n\n\n\n<li>Change <strong>Status<\/strong> to <strong>On<\/strong>.<\/li>\n\n\n\n<li>Select <strong>Save<\/strong>.<\/li>\n\n\n\n<li>Confirm the operation when prompted.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Azure creates a Microsoft Entra service principal tied to the VM&#8217;s lifecycle. The credentials are managed by Azure and are not exposed to the student.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4.2: Grant Blob Storage access<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Return to the storage account.<\/li>\n\n\n\n<li>Select <strong>Access control (IAM)<\/strong>.<\/li>\n\n\n\n<li>Select <strong>Add<\/strong>.<\/li>\n\n\n\n<li>Select <strong>Add role assignment<\/strong>.<\/li>\n\n\n\n<li>Search for and select:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>Storage Blob Data Contributor\n<\/code><\/pre>\n\n\n\n<ol start=\"6\" class=\"wp-block-list\">\n<li>Select <strong>Next<\/strong>.<\/li>\n\n\n\n<li>For <strong>Assign access to<\/strong>, select <strong>Managed identity<\/strong>.<\/li>\n\n\n\n<li>Select <strong>+ Select members<\/strong>.<\/li>\n\n\n\n<li>For <strong>Managed identity<\/strong>, select <strong>Virtual machine<\/strong>.<\/li>\n\n\n\n<li>Select the subscription.<\/li>\n\n\n\n<li>Select the existing Ubuntu VM.<\/li>\n\n\n\n<li>Select <strong>Select<\/strong>.<\/li>\n\n\n\n<li>Select <strong>Review + assign<\/strong>.<\/li>\n\n\n\n<li>Select <strong>Review + assign<\/strong> again.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">The Storage Blob Data Contributor role permits the VM identity to read, write and delete blob data. Role assignments can take several minutes, and Microsoft notes that propagation can take up to approximately 10 minutes.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Exercise 5: Install Azure CLI on Ubuntu 24.04<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Microsoft&#8217;s current Azure CLI installation documentation lists Ubuntu 24.04 as a tested apt-based distribution.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5.1: Check whether Azure CLI is already installed<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>az version\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the command succeeds, continue to Exercise 6.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5.2: Install prerequisites<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt-get update\nsudo apt-get install -y \\\n  apt-transport-https \\\n  ca-certificates \\\n  curl \\\n  gnupg \\\n  lsb-release\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5.3: Add the Microsoft signing key<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mkdir -p \/etc\/apt\/keyrings\n\ncurl -sLS https:\/\/packages.microsoft.com\/keys\/microsoft.asc \\\n  | gpg --dearmor \\\n  | sudo tee \/etc\/apt\/keyrings\/microsoft.gpg &gt; \/dev\/null\n\nsudo chmod go+r \/etc\/apt\/keyrings\/microsoft.gpg\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5.4: Add the Azure CLI repository<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>AZ_DIST=$(lsb_release -cs)\n\necho \"Types: deb\nURIs: https:\/\/packages.microsoft.com\/repos\/azure-cli\/\nSuites: ${AZ_DIST}\nComponents: main\nArchitectures: $(dpkg --print-architecture)\nSigned-by: \/etc\/apt\/keyrings\/microsoft.gpg\" \\\n| sudo tee \/etc\/apt\/sources.list.d\/azure-cli.sources\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5.5: Install Azure CLI<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt-get update\nsudo apt-get install -y azure-cli\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Validate:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>az version\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Exercise 6: Use Blob Storage from the VM<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6.1: Sign in with the VM identity<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>az login --identity\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>--identity<\/code> option signs Azure CLI in by using the VM&#8217;s system-assigned managed identity rather than student credentials or a stored secret.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6.2: Set lab variables<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Replace the storage account value:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>STORAGE_ACCOUNT=\"&lt;your-storage-account-name&gt;\"\nBLOB_CONTAINER=\"blob-lab\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check the variables:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo \"$STORAGE_ACCOUNT\"\necho \"$BLOB_CONTAINER\"\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6.3: Create a sample file<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; \"$HOME\/blob-demo.txt\" &lt;&lt;EOF\nAzure Blob Storage lab\nSource VM: $(hostname)\nCreated: $(date --iso-8601=seconds)\nAuthentication: System-assigned managed identity\nEOF\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Display it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat \"$HOME\/blob-demo.txt\"\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6.4: Upload the blob<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>az storage blob upload \\\n  --account-name \"$STORAGE_ACCOUNT\" \\\n  --container-name \"$BLOB_CONTAINER\" \\\n  --name \"blob-demo.txt\" \\\n  --file \"$HOME\/blob-demo.txt\" \\\n  --auth-mode login\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>--auth-mode login<\/code> option tells Azure CLI to authorize the data operation with the signed-in Microsoft Entra identity.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6.5: List the blobs<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>az storage blob list \\\n  --account-name \"$STORAGE_ACCOUNT\" \\\n  --container-name \"$BLOB_CONTAINER\" \\\n  --auth-mode login \\\n  --output table\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected result includes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>blob-demo.txt\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6.6: Download the blob<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>rm -f \"$HOME\/blob-demo-downloaded.txt\"\n\naz storage blob download \\\n  --account-name \"$STORAGE_ACCOUNT\" \\\n  --container-name \"$BLOB_CONTAINER\" \\\n  --name \"blob-demo.txt\" \\\n  --file \"$HOME\/blob-demo-downloaded.txt\" \\\n  --auth-mode login\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Compare the original and downloaded files:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cmp \"$HOME\/blob-demo.txt\" \"$HOME\/blob-demo-downloaded.txt\" \\\n  &amp;&amp; echo \"Blob upload and download validation passed.\"\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6.7: Verify through the portal<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the storage account.<\/li>\n\n\n\n<li>Select <strong>Containers<\/strong>.<\/li>\n\n\n\n<li>Select <strong>blob-lab<\/strong>.<\/li>\n\n\n\n<li>Confirm that <code>blob-demo.txt<\/code> is present.<\/li>\n\n\n\n<li>Select the blob and inspect its properties.<\/li>\n\n\n\n<li>Optionally download it through the portal.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Exercise 7: Create an Azure file share<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Step 7.1: Create the SMB share<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the storage account.<\/li>\n\n\n\n<li>Under <strong>Data storage<\/strong>, select <strong>Classic file shares<\/strong>.<\/li>\n\n\n\n<li>Select <strong>+ File share<\/strong>.<\/li>\n\n\n\n<li>On the <strong>Basics<\/strong> tab, configure:<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Setting<\/th><th>Value<\/th><\/tr><\/thead><tbody><tr><td>Name<\/td><td><code>files-lab<\/code><\/td><\/tr><tr><td>Access tier<\/td><td>Transaction optimized<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<ol start=\"5\" class=\"wp-block-list\">\n<li>Open the <strong>Backup<\/strong> tab.<\/li>\n\n\n\n<li>Clear <strong>Enable backup<\/strong> for this temporary lab.<\/li>\n\n\n\n<li>Select <strong>Review + create<\/strong>.<\/li>\n\n\n\n<li>Select <strong>Create<\/strong>.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">The Azure portal enables backup by default when creating a classic file share. Disabling it avoids creating extra backup resources for this disposable exercise.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Exercise 8: Mount Azure Files on Ubuntu<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">This exercise uses SMB with a storage account key because it is simple and broadly reproducible for an introductory lab. Microsoft recommends identity-based access for production implementations. SMB 3.1.1 is the recommended protocol, and Ubuntu versions newer than 18.04 support the required encrypted SMB capabilities.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 8.1: Obtain the portal-generated connection script<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the <code>files-lab<\/code> file share.<\/li>\n\n\n\n<li>Select <strong>Connect<\/strong>.<\/li>\n\n\n\n<li>Select <strong>Linux<\/strong>.<\/li>\n\n\n\n<li>Select the storage-account-key authentication option.<\/li>\n\n\n\n<li>Use <code>\/mnt\/azurefiles<\/code> as the mount location when the portal displays a mount-path field.<\/li>\n\n\n\n<li>Select <strong>Show script<\/strong> or the equivalent option.<\/li>\n\n\n\n<li>Copy the generated Linux script.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">The generated script is preferable because it contains the exact storage-account endpoint and current account key for the lab.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Do not include the generated script or storage key in screenshots, reports, source control or chat messages.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 8.2: Install the SMB client<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">On the Ubuntu VM, run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt-get update\nsudo apt-get install -y cifs-utils netcat-openbsd\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Microsoft&#8217;s Linux Azure Files guidance requires <code>cifs-utils<\/code> for SMB mounting.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 8.3: Test TCP 445 connectivity<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>STORAGE_ACCOUNT=\"&lt;your-storage-account-name&gt;\"\nFILE_HOST=\"${STORAGE_ACCOUNT}.file.core.windows.net\"\n\nnc -zvw3 \"$FILE_HOST\" 445\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected result:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Connection to &lt;storage-account&gt;.file.core.windows.net 445 port succeeded\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Azure Files SMB uses TCP port 445. A failed test normally indicates an outbound NSG, firewall, routing or DNS restriction.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 8.4: Run the portal-generated script<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Paste and run the script copied from the Azure portal.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The script should:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create the local mount directory.<\/li>\n\n\n\n<li>Create a protected credentials file.<\/li>\n\n\n\n<li>Mount the SMB share.<\/li>\n\n\n\n<li>Use the storage account as the SMB username.<\/li>\n\n\n\n<li>Use the storage account key as the SMB password.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Step 8.5: Identify the actual mount point<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>findmnt -t cifs\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the portal script used the requested location, the output should include:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/mnt\/azurefiles\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Set a variable for later exercises:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>AZURE_FILES_MOUNT=\"\/mnt\/azurefiles\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the portal script used a different location, replace the value above with the displayed mount point.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 8.6: Write data to the share<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>echo \"Written from Ubuntu VM $(hostname) at $(date --iso-8601=seconds)\" \\\n  | sudo tee \"$AZURE_FILES_MOUNT\/from-ubuntu-vm.txt\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">List the share:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ls -la \"$AZURE_FILES_MOUNT\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Read the file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat \"$AZURE_FILES_MOUNT\/from-ubuntu-vm.txt\"\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 8.7: Verify through the portal<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Return to the <code>files-lab<\/code> share.<\/li>\n\n\n\n<li>Select <strong>Browse<\/strong>.<\/li>\n\n\n\n<li>Confirm that <code>from-ubuntu-vm.txt<\/code> appears.<\/li>\n\n\n\n<li>Select or download the file.<\/li>\n\n\n\n<li>Confirm that its content matches the VM output.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Step 8.8: Validate persistent mounting<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check whether the portal-generated script added an <code>\/etc\/fstab<\/code> entry:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -n \"$STORAGE_ACCOUNT.file.core.windows.net\" \/etc\/fstab\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Before testing, back up the file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo cp \/etc\/fstab \/etc\/fstab.before-azure-files-lab\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Test all configured mounts without rebooting:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mount -a\nfindmnt \"$AZURE_FILES_MOUNT\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Do not reboot until <code>sudo mount -a<\/code> completes without errors.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Exercise 9: Create and attach a managed disk<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Step 9.1: Attach a new data disk<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>In the Azure portal, open the Ubuntu VM.<\/li>\n\n\n\n<li>Under <strong>Settings<\/strong>, select <strong>Disks<\/strong>.<\/li>\n\n\n\n<li>Under <strong>Data disks<\/strong>, select <strong>Create and attach a new disk<\/strong>.<\/li>\n\n\n\n<li>Configure:<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Setting<\/th><th>Value<\/th><\/tr><\/thead><tbody><tr><td>Disk name<\/td><td><code>disk-lab-data-01<\/code><\/td><\/tr><tr><td>Storage type<\/td><td>Standard SSD LRS<\/td><\/tr><tr><td>Size<\/td><td>4 GiB or the smallest permitted lab size<\/td><\/tr><tr><td>Encryption<\/td><td>Platform-managed key<\/td><\/tr><tr><td>Host caching<\/td><td>Leave at the displayed default<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<ol start=\"5\" class=\"wp-block-list\">\n<li>Select <strong>Save<\/strong>.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">The portal creates the managed disk and updates the VM configuration. The number of supported data disks depends on the VM size.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Exercise 10: Prepare the managed disk in Ubuntu<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Important safety warning<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Never assume the new disk is <code>\/dev\/sdc<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Depending on the VM size, Azure managed disks can appear through either a SCSI or NVMe interface. The operating-system disk, temporary disk and data disk can therefore have different device names. Formatting the wrong disk causes data loss.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 10.1: Install required utilities<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt-get update\nsudo apt-get install -y parted xfsprogs\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 10.2: List the block devices<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS,MODEL,SERIAL\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Look for a disk that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Matches the size selected in the portal.<\/li>\n\n\n\n<li>Has type <code>disk<\/code>.<\/li>\n\n\n\n<li>Has no filesystem.<\/li>\n\n\n\n<li>Has no partition.<\/li>\n\n\n\n<li>Has no mount point.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A typical SCSI result might be:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sda      30G disk\n\u251c\u2500sda1   29G part ext4 \/\nsdb      14G disk\n\u2514\u2500sdb1   14G part ext4 \/mnt\nsdc       4G disk\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In this example, <code>\/dev\/sdc<\/code> is the new disk. <code>\/dev\/sdb<\/code> is already mounted and must not be formatted.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A VM using NVMe might instead display a device such as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nvme0n2   4G disk\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 10.3: Set the correct device variable<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For a SCSI disk:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>DISK=\"\/dev\/sdc\"\nPARTITION=\"${DISK}1\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For an NVMe disk:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>DISK=\"\/dev\/nvme0n2\"\nPARTITION=\"${DISK}p1\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Inspect the selected device again:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>lsblk \"$DISK\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Continue only when it is unquestionably the new, empty data disk.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 10.4: Create a GPT partition<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo parted \"$DISK\" \\\n  --script \\\n  mklabel gpt \\\n  mkpart xfspart xfs 0% 100%\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Notify the kernel:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo partprobe \"$DISK\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Verify the partition:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>lsblk \"$DISK\"\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 10.5: Create an XFS filesystem<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mkfs.xfs \"$PARTITION\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Microsoft&#8217;s current managed-disk examples use GPT and XFS and provide separate partition naming examples for SCSI and NVMe devices.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 10.6: Mount the filesystem<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mkdir -p \/datadrive\nsudo mount \"$PARTITION\" \/datadrive\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Validate:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>findmnt \/datadrive\ndf -hT \/datadrive\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 10.7: Persist the mount in <code>\/etc\/fstab<\/code><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Back up the current file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo cp \/etc\/fstab \/etc\/fstab.before-managed-disk-lab\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Retrieve the filesystem UUID:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>DISK_UUID=$(sudo blkid -s UUID -o value \"$PARTITION\")\necho \"$DISK_UUID\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Add the entry only when it is not already present:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -q \"UUID=$DISK_UUID\" \/etc\/fstab \\\n  || echo \"UUID=$DISK_UUID \/datadrive xfs defaults,nofail 1 2\" \\\n  | sudo tee -a \/etc\/fstab\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Using the UUID is safer than using <code>\/dev\/sdc1<\/code> or an NVMe path because device names can change. The <code>nofail<\/code> option helps prevent a missing data disk from blocking VM startup.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 10.8: Test the persistent configuration<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \"$HOME\"\nsudo umount \/datadrive\nsudo mount -a\nfindmnt \/datadrive\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Create a test file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo \"Managed disk validation: $(date --iso-8601=seconds)\" \\\n  | sudo tee \/datadrive\/managed-disk-test.txt\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Validate:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo cat \/datadrive\/managed-disk-test.txt\ndf -hT \/datadrive\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Exercise 11: Integrate all three storage services<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">This exercise proves that the VM can use the managed disk, Azure Files and Blob Storage together.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 11.1: Create evidence on the managed disk<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tee \/datadrive\/storage-lab-evidence.txt &gt; \/dev\/null &lt;&lt;EOF\nAzure storage lab completed\nVM: $(hostname)\nTimestamp: $(date --iso-8601=seconds)\nSource location: Azure Managed Disk mounted at \/datadrive\nEOF\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Allow the current user to read it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo chmod 644 \/datadrive\/storage-lab-evidence.txt\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 11.2: Copy the file to Azure Files<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo cp \\\n  \/datadrive\/storage-lab-evidence.txt \\\n  \"$AZURE_FILES_MOUNT\/storage-lab-evidence.txt\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Validate:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat \"$AZURE_FILES_MOUNT\/storage-lab-evidence.txt\"\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 11.3: Upload the same file to Blob Storage<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>az storage blob upload \\\n  --account-name \"$STORAGE_ACCOUNT\" \\\n  --container-name \"$BLOB_CONTAINER\" \\\n  --name \"storage-lab-evidence.txt\" \\\n  --file \"\/datadrive\/storage-lab-evidence.txt\" \\\n  --auth-mode login\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 11.4: Validate all three copies<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Managed disk:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sha256sum \/datadrive\/storage-lab-evidence.txt\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Azure Files:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sha256sum \"$AZURE_FILES_MOUNT\/storage-lab-evidence.txt\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Download the blob:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>az storage blob download \\\n  --account-name \"$STORAGE_ACCOUNT\" \\\n  --container-name \"$BLOB_CONTAINER\" \\\n  --name \"storage-lab-evidence.txt\" \\\n  --file \"$HOME\/storage-lab-evidence-from-blob.txt\" \\\n  --auth-mode login\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Blob download:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sha256sum \"$HOME\/storage-lab-evidence-from-blob.txt\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">All three SHA-256 values must be identical.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Final validation checklist<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Blob Storage<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>blob-lab<\/code> exists.<\/li>\n\n\n\n<li>Anonymous access is private.<\/li>\n\n\n\n<li>VM system-assigned identity is enabled.<\/li>\n\n\n\n<li>VM has Storage Blob Data Contributor.<\/li>\n\n\n\n<li><code>az login --identity<\/code> succeeds.<\/li>\n\n\n\n<li>Blob upload succeeds.<\/li>\n\n\n\n<li>Blob list displays the uploaded file.<\/li>\n\n\n\n<li>Downloaded blob matches the original.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Azure Files<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>files-lab<\/code> exists.<\/li>\n\n\n\n<li>TCP 445 connectivity succeeds.<\/li>\n\n\n\n<li><code>cifs-utils<\/code> is installed.<\/li>\n\n\n\n<li><code>findmnt -t cifs<\/code> displays the share.<\/li>\n\n\n\n<li>Ubuntu can create a file on the share.<\/li>\n\n\n\n<li>The file appears in the portal.<\/li>\n\n\n\n<li><code>sudo mount -a<\/code> succeeds.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Managed Disk<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Managed disk is attached to the VM.<\/li>\n\n\n\n<li>Correct empty disk device was identified.<\/li>\n\n\n\n<li>GPT partition exists.<\/li>\n\n\n\n<li>XFS filesystem exists.<\/li>\n\n\n\n<li>Disk is mounted at <code>\/datadrive<\/code>.<\/li>\n\n\n\n<li><code>\/etc\/fstab<\/code> uses the filesystem UUID.<\/li>\n\n\n\n<li><code>\/etc\/fstab<\/code> includes <code>nofail<\/code>.<\/li>\n\n\n\n<li><code>sudo mount -a<\/code> succeeds.<\/li>\n\n\n\n<li>A file can be created and read on the disk.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Integrated validation<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The evidence file exists on the managed disk.<\/li>\n\n\n\n<li>The evidence file exists in Azure Files.<\/li>\n\n\n\n<li>The evidence file exists in Blob Storage.<\/li>\n\n\n\n<li>SHA-256 checksums match.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Troubleshooting<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Blob command returns <code>AuthorizationPermissionMismatch<\/code><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The VM&#8217;s system-assigned identity is enabled.<\/li>\n\n\n\n<li>The role was assigned to the VM managed identity, not to the student.<\/li>\n\n\n\n<li>The role is <strong>Storage Blob Data Contributor<\/strong>.<\/li>\n\n\n\n<li>The role scope includes the storage account.<\/li>\n\n\n\n<li>Several minutes have passed since assignment.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Retry:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>az logout\naz login --identity\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then rerun the blob command. Azure RBAC changes can take up to approximately 10 minutes to propagate.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Blob command returns network or 403 errors<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Storage account <strong>Networking<\/strong>.<\/li>\n\n\n\n<li>Public network access is enabled for the core lab.<\/li>\n\n\n\n<li>The VM has outbound HTTPS access.<\/li>\n\n\n\n<li>The correct storage account name is being used.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">TCP 445 test fails<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>nc -zvw3 \"${STORAGE_ACCOUNT}.file.core.windows.net\" 445\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>VM NSG outbound rules.<\/li>\n\n\n\n<li>Azure Firewall or third-party firewall rules.<\/li>\n\n\n\n<li>User-defined routes.<\/li>\n\n\n\n<li>DNS resolution.<\/li>\n\n\n\n<li>Storage account firewall rules.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">SMB Azure Files requires TCP 445.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Azure Files mount returns <code>Permission denied<\/code><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The storage account key has not been regenerated.<\/li>\n\n\n\n<li>Storage account key access remains enabled.<\/li>\n\n\n\n<li>The credential file contains the correct account name and current key.<\/li>\n\n\n\n<li>The credential file permissions are <code>600<\/code>.<\/li>\n\n\n\n<li>The share name is exactly <code>files-lab<\/code>.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The cleanest lab recovery is to reopen the file share&#8217;s <strong>Connect<\/strong> page and generate a fresh Linux script.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Managed disk does not appear<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>lsblk\nsudo udevadm settle\nlsblk\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For SCSI-based VMs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt-get install -y lsscsi\nlsscsi\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For NVMe-based VMs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt-get install -y nvme-cli\nsudo nvme list\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Do not format a device until its size, interface, existing partitions and mount status have been verified.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><code>\/etc\/fstab<\/code> validation fails<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Restore the appropriate backup:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo cp \/etc\/fstab.before-managed-disk-lab \/etc\/fstab\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Or, for the Azure Files backup:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo cp \/etc\/fstab.before-azure-files-lab \/etc\/fstab\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then test:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mount -a\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Never reboot after changing <code>\/etc\/fstab<\/code> until <code>sudo mount -a<\/code> completes successfully.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Cleanup<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Important<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Do not delete the resource group when it also contains the pre-existing VM or other shared classroom resources.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Remove the Azure Files mount<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \"$HOME\"\nsudo umount \"$AZURE_FILES_MOUNT\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Remove the Azure Files entry from <code>\/etc\/fstab<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nano \/etc\/fstab\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Delete only the line containing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.file.core.windows.net\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Remove the credentials file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo rm -f \"\/etc\/smbcredentials\/${STORAGE_ACCOUNT}.cred\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Optionally remove the mount directory:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo rmdir \"$AZURE_FILES_MOUNT\" 2&gt;\/dev\/null || true\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Remove the managed disk mount<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \"$HOME\"\nsudo umount \/datadrive\nsudo nano \/etc\/fstab\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Delete only the line that mounts the managed-disk UUID at <code>\/datadrive<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Validate:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo mount -a\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Detach the managed disk<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the VM in the Azure portal.<\/li>\n\n\n\n<li>Select <strong>Disks<\/strong>.<\/li>\n\n\n\n<li>Locate <code>disk-lab-data-01<\/code>.<\/li>\n\n\n\n<li>Select the detach option.<\/li>\n\n\n\n<li>Select <strong>Save<\/strong>.<\/li>\n\n\n\n<li>Search for <strong>Disks<\/strong> in the portal.<\/li>\n\n\n\n<li>Open <code>disk-lab-data-01<\/code>.<\/li>\n\n\n\n<li>Select <strong>Delete<\/strong>.<\/li>\n\n\n\n<li>Confirm deletion.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Delete storage resources<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Either delete individual resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Delete <code>blob-lab<\/code>.<\/li>\n\n\n\n<li>Delete <code>files-lab<\/code>.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Or delete the complete lab storage account:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the storage account.<\/li>\n\n\n\n<li>Select <strong>Delete<\/strong>.<\/li>\n\n\n\n<li>Enter the storage account name.<\/li>\n\n\n\n<li>Confirm deletion.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Review the managed identity<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The VM&#8217;s system-assigned identity may remain enabled for future exercises. If the instructor requires its removal:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the VM.<\/li>\n\n\n\n<li>Select <strong>Identity<\/strong>.<\/li>\n\n\n\n<li>Set <strong>System assigned<\/strong> to <strong>Off<\/strong>.<\/li>\n\n\n\n<li>Select <strong>Save<\/strong>.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Production-hardening discussion<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The core lab prioritizes repeatability. A production implementation should additionally evaluate:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Private endpoints or selected virtual-network access instead of allowing all networks.<\/li>\n\n\n\n<li>Separate storage accounts based on workload, security boundary and lifecycle.<\/li>\n\n\n\n<li>Provisioned v2 Azure Files for new production file-share deployments.<\/li>\n\n\n\n<li>Managed identity or another approved identity-based method for Azure Files instead of storage account keys.<\/li>\n\n\n\n<li>Storage-account key rotation when keys remain enabled.<\/li>\n\n\n\n<li>Azure Backup for important file shares.<\/li>\n\n\n\n<li>Blob soft delete, versioning and lifecycle-management policies.<\/li>\n\n\n\n<li>Zone-redundant or geo-redundant storage based on recovery requirements.<\/li>\n\n\n\n<li>Azure Monitor diagnostic settings, alerts and storage metrics.<\/li>\n\n\n\n<li>Least-privilege role assignments scoped to the required container or service.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Microsoft recommends managed identities over storage account keys where supported, and Azure Storage network controls can restrict storage endpoints to approved networks and resources.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Blob Storage, Azure Files and Managed Disks Interface: Azure portal for resource creation and configurationClient system: Existing Azure VM running Ubuntu Server 24.04 LTSValidation date: July 19,&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1036","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1036","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/comments?post=1036"}],"version-history":[{"count":1,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1036\/revisions"}],"predecessor-version":[{"id":1037,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1036\/revisions\/1037"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/media?parent=1036"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/categories?post=1036"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/tags?post=1036"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}