8 – πŸš€ Deploy Azure Functions with Terraform β€” QR Code Generator Mini Project (Step-by-Step)

In this post, I’ll walk you through a complete, working mini project where we deploy an Azure Linux Function App using Terraform and then deploy a Node.js QR Code Generator function using Azure Functions Core Tools.

This is not just theory β€” this is exactly what I built, debugged, fixed, and verified end-to-end. I’ll also call out the gotchas I hit (especially in Step 2), so you don’t lose hours troubleshooting the same issues.

Table of Contents

  1. πŸ”Ή What We Are Building
  2. 🧱 Step 1: Create Core Azure Infrastructure with Terraform
  3. βš™οΈ Step 2: Create the Linux Function App (Most Important Step)
  4. πŸ“¦ Step 3: Prepare the QR Code Generator App
  5. πŸ” Add local.settings.json (Local Only)
  6. 🚫 Add .funcignore
  7. πŸ›  Install Azure Functions Core Tools (Windows)
  8. πŸš€ Deploy the Function Code
  9. πŸ§ͺ Step 4: Test the Function End-to-End
  10. βœ… What This Demo Proves
  11. 🧠 Final Notes
  12. 🎯 Conclusion

πŸ”Ή What We Are Building

  • Azure Resource Group
  • Azure Storage Account
  • Azure App Service Plan (Linux)
  • Azure Linux Function App (Node.js 18)
  • A Node.js HTTP-triggered Azure Function that:
    • Accepts a URL
    • Generates a QR code
    • Stores the QR image in Azure Blob Storage
    • Returns the QR image URL as JSON

🧱 Step 1: Create Core Azure Infrastructure with Terraform

In this step, we create the base infrastructure required for Azure Functions.

Resource Group (rg.tf)

resource "azurerm_resource_group" "rg" {
  name     = "rgminipro767676233"
  location = "Central US"
}

Storage Account (sa.tf)

Azure Functions require a storage account for:

  • Function state
  • Logs
  • Triggers
  • Blob output (our QR codes)
resource "azurerm_storage_account" "sa" {
  name                     = "saminipro7833430909"
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

⚠️ Storage account names must be globally unique and lowercase.

App Service Plan (splan.tf)

This defines the compute for the Function App.

resource "azurerm_service_plan" "splan" {
  name                = "splanminipro8787"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  os_type             = "Linux"
  sku_name            = "B1"
}

Apply Terraform

terraform apply

βœ… Verify in Azure Portal:

  • Resource Group created
  • Storage Account exists
  • App Service Plan is Linux (B1)

βš™οΈ Step 2: Create the Linux Function App (Most Important Step)

This step required multiple fixes for the app to actually run, so pay close attention.

Linux Function App (linuxfa.tf)

resource "azurerm_linux_function_app" "linuxfa" {
  name                = "linuxfaminipro8932340"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location

  storage_account_name       = azurerm_storage_account.sa.name
  storage_account_access_key = azurerm_storage_account.sa.primary_access_key
  service_plan_id            = azurerm_service_plan.splan.id

  app_settings = {
    FUNCTIONS_WORKER_RUNTIME = "node"

    # Required by Azure Functions runtime
    AzureWebJobsStorage = azurerm_storage_account.sa.primary_connection_string

    # Used by our application code
    STORAGE_CONNECTION_STRING = azurerm_storage_account.sa.primary_connection_string

    # Ensures package-based deployment
    WEBSITE_RUN_FROM_PACKAGE = "1"
  }

  site_config {
    application_stack {
      node_version = 18
    }
  }
}

Why Each Setting Matters

  • FUNCTIONS_WORKER_RUNTIME
    • Tells Azure this is a Node.js function app
  • AzureWebJobsStorage
    • Mandatory for Azure Functions to start
  • STORAGE_CONNECTION_STRING
    • Used by our QR code logic to upload images
  • WEBSITE_RUN_FROM_PACKAGE
    • Ensures consistent zip/package deployment
  • node_version = 18
    • Must match your app runtime

Apply Terraform Again

terraform apply

βœ… Verify in Azure Portal:

  • Function App is Running
  • Runtime stack shows Node.js 18
  • No startup errors

πŸ“¦ Step 3: Prepare the QR Code Generator App

Download the App

Clone or download the QR code generator repository:

git clone https://github.com/rishabkumar7/azure-qr-code

Navigate to the function root directory (where host.json exists).

Run npm install

npm install

This creates the node_modules folder β€” without this, the function will fail at runtime.

Expected Folder Structure

qrCodeGenerator/
β”‚
β”œβ”€β”€ GenerateQRCode/
β”‚   β”œβ”€β”€ index.js
β”‚   └── function.json
β”‚
β”œβ”€β”€ host.json
β”œβ”€β”€ package.json
β”œβ”€β”€ package-lock.json
β”œβ”€β”€ node_modules/

πŸ” Add local.settings.json (Local Only)

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "<Storage Account Connection String>",
    "FUNCTIONS_WORKER_RUNTIME": "node"
  }
}

❗ This file is NOT deployed to Azure and should never be committed.


🚫 Add .funcignore

This controls what gets deployed.

.git*
.vscode
local.settings.json
test
getting_started.md
*.js.map
*.ts
node_modules/@types/
node_modules/azure-functions-core-tools/
node_modules/typescript/

βœ… We keep node_modules because this project depends on native Node packages.


πŸ›  Install Azure Functions Core Tools (Windows)

winget install Microsoft.Azure.FunctionsCoreTools

Restart PowerShell and verify:

func -v

πŸš€ Deploy the Function Code

Navigate to the directory where host.json exists:

cd path/to/qrCodeGenerator

Publish the function:

func azure functionapp publish linuxfaminipro8932340 --javascript --force

Successful Output Looks Like This

Upload completed successfully.
Deployment completed successfully.
Functions in linuxfaminipro8932340:
    GenerateQRCode - [httpTrigger]
        Invoke url: https://linuxfaminipro8932340.azurewebsites.net/api/generateqrcode

πŸ§ͺ Step 4: Test the Function End-to-End

Invoke the Function

https://linuxfaminipro8932340.azurewebsites.net/api/generateqrcode?url=https://example.com

Sample Response

{
  "qr_code_url": "https://saminipro7833430909.blob.core.windows.net/qr-codes/example.com.png"
}

Download the QR Code

Open the returned Blob URL in your browser:

https://saminipro7833430909.blob.core.windows.net/qr-codes/example.com.png

πŸŽ‰ You’ll see the QR code image stored in Azure Blob Storage.


βœ… What This Demo Proves

  • Terraform successfully provisions Azure Functions infrastructure
  • App settings are critical for runtime stability
  • Azure Functions Core Tools deploy code from the current directory
  • Missing npm install causes runtime failures
  • Blob Storage integration works end-to-end
  • Azure Functions can be tested via simple HTTP requests

🧠 Final Notes

  • Warnings about extension bundle versions were intentionally ignored
  • This demo focuses on learning Terraform + Azure Functions, not production hardening
  • In real projects, code deployment is usually handled via CI/CD pipelines

🎯 Conclusion

This mini project demonstrates how Infrastructure as Code (Terraform) and Serverless (Azure Functions) work together in a practical, real-world scenario.

If you can build and debug this, you’re well on your way to mastering Azure + Terraform.

Happy learning πŸš€

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

TechMilestoneHub

Build Skills, Unlock Milestones

Β© 2025 TechMilestoneHub


The content on TechMilestoneHub is for educational purposes only and may not always reflect the latest official guidance. Tutorials, quizzes, and examples do not guarantee certification success or specific results. We are not affiliated with certification vendors unless stated. Some pages may contain affiliate links, which may earn us a commission at no extra cost to you. By using this site, you agree to use the information at your own risk. See our Disclaimer, Terms & Conditions, and Privacy Policy for details.