{"id":30017222,"url":"https://github.com/neckerfree/azure-fullstack-automation","last_synced_at":"2026-04-10T06:56:02.516Z","repository":{"id":303454286,"uuid":"1007223590","full_name":"NeckerFree/azure-fullstack-automation","owner":"NeckerFree","description":"This project automates the provisioning and deployment of a scalable cloud application on Microsoft Azure. It uses Terraform to create infrastructure, and Ansible to configure services like a backend API running on 2 VMs behind a Load Balancer, connected to an Azure MySQL database, along with a frontend deployed on Azure Web App.","archived":false,"fork":false,"pushed_at":"2025-07-30T01:43:57.000Z","size":2730,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-07-30T03:54:28.835Z","etag":null,"topics":["ansible","api","azure","ci-cd","mysql","nodejs","terraform"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NeckerFree.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-23T16:46:18.000Z","updated_at":"2025-07-30T01:44:01.000Z","dependencies_parsed_at":"2025-07-07T18:49:48.605Z","dependency_job_id":"5961f716-28e0-4629-8f44-0c6c99f3c71c","html_url":"https://github.com/NeckerFree/azure-fullstack-automation","commit_stats":null,"previous_names":["neckerfree/azure-fullstack-automation"],"tags_count":0,"template":false,"template_full_name":"microverseinc/readme-template","purl":"pkg:github/NeckerFree/azure-fullstack-automation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NeckerFree%2Fazure-fullstack-automation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NeckerFree%2Fazure-fullstack-automation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NeckerFree%2Fazure-fullstack-automation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NeckerFree%2Fazure-fullstack-automation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NeckerFree","download_url":"https://codeload.github.com/NeckerFree/azure-fullstack-automation/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NeckerFree%2Fazure-fullstack-automation/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268987347,"owners_count":24340661,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-05T02:00:12.334Z","response_time":2576,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansible","api","azure","ci-cd","mysql","nodejs","terraform"],"created_at":"2025-08-05T22:47:09.159Z","updated_at":"2025-12-30T21:49:25.859Z","avatar_url":"https://github.com/NeckerFree.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ca name=\"readme-top\"\u003e\u003c/a\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"azure_logo.png\" alt=\"Azure Cloud Logo\" width=\"120\" /\u003e\n  \u003ch3\u003e\u003cb\u003eCloud Web App Deployment on Azure\u003c/b\u003e\u003c/h3\u003e\n\u003c/div\u003e\n\n# 📗 Table of Contents\n\n- [📖 About the Project](#about-project)\n  - [🛠 Built With](#built-with)\n    - [Tech Stack](#tech-stack)\n    - [Key Features](#key-features)\n  - [🚀 Live Demo](#live-demo)\n- [💻 Getting Started](#getting-started)\n  - [Prerequisites](#prerequisites)\n  - [Setup](#setup)\n  - [Provision Infrastructure (Terraform)](#terraform)\n  - [Configure Services (Ansible)](#ansible)\n  - [Deployment](#deployment)\n- [🔧 Customizing Variables](#custom-variables)\n- [☁️ Remote Terraform State in Azure](#️remote-terraform-state-in-azure)\n- [👥 Authors](#authors)\n- [🔭 Future Features](#future-features)\n- [🤝 Contributing](#contributing)\n- [⭐️ Show your support](#support)\n- [🙏 Acknowledgements](#acknowledgements)\n- [❓ FAQ](#faq)\n- [📝 License](#license)\n\n---\n\n# 📖 Azure Cloud Web App Deployment \u003ca name=\"about-project\"\u003e\u003c/a\u003e\n\nThis project automates the provisioning and deployment of a scalable cloud application on Microsoft Azure. It uses **Terraform** to create infrastructure, and **Ansible** to configure services like a backend API running on 2 VMs behind a Load Balancer, connected to an **Azure MySQL** database, along with a frontend deployed on **Azure Web App**.\n\n\u003cimg width=\"1080\" height=\"503\" alt=\"architecture diagram\" src=\"https://github.com/user-attachments/assets/a66138ba-d8e5-48d2-9e0e-0f6b2160ce37\" /\u003e\n\u003cp align=\"center\"\u003eArchitecture Diagram\u003c/p\u003e\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n## 🛠 Built With \u003ca name=\"built-with\"\u003e\u003c/a\u003e\n\n### Tech Stack \u003ca name=\"tech-stack\"\u003e\u003c/a\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eInfrastructure as Code\u003c/summary\u003e\n  \u003cul\u003e\n    \u003cli\u003e\u003ca href=\"https://www.terraform.io/\"\u003eTerraform\u003c/a\u003e\u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eConfiguration Management\u003c/summary\u003e\n  \u003cul\u003e\n    \u003cli\u003e\u003ca href=\"https://www.ansible.com/\"\u003eAnsible\u003c/a\u003e\u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eCloud Platform\u003c/summary\u003e\n  \u003cul\u003e\n    \u003cli\u003e\u003ca href=\"https://azure.microsoft.com/\"\u003eMicrosoft Azure\u003c/a\u003e\u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eDatabase\u003c/summary\u003e\n  \u003cul\u003e\n    \u003cli\u003e\u003ca href=\"https://learn.microsoft.com/en-us/azure/mysql/\"\u003eAzure Database for MySQL\u003c/a\u003e\u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eDeployment Targets\u003c/summary\u003e\n  \u003cul\u003e\n    \u003cli\u003eAzure Virtual Machines\u003c/li\u003e\n    \u003cli\u003eAzure Load Balancer\u003c/li\u003e\n    \u003cli\u003eAzure App Service (Web App)\u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/details\u003e\n\n### Key Features \u003ca name=\"key-features\"\u003e\u003c/a\u003e\n\n- 🔧 Automated infrastructure provisioning with Terraform  \n- 📦 Service configuration and app deployment using Ansible  \n- 🐘 MySQL database initialized via Ansible using `ansible/files/mysql/movie_db.sql`\n- 🌐 Scalable API on 2 Azure VMs behind a Load Balancer  \n- 💾 Managed Azure MySQL integration  \n- 🚀 Web frontend deployed using Azure Web App  \n- 🔐 Service Principal authentication using Client Secret  \n- ⚙️ Fully automated deployment workflow with CI/CD integration  \n- 🏗️ End-to-end Terraform deployment from scratch included in workflow  \n- 🧹 Automated environment teardown using `terraform-destroy.yml`  \n- 💸 Uses Azure Web App **F1 Free Tier** for cost-effective deployment  \n\n\u003cdiv align=\"center\"\u003e\n\u003cimg width=\"1007\" height=\"877\" alt=\"Get Movies in Postman (Base Address LB IP)  \" src=\"https://github.com/user-attachments/assets/52775015-3816-484f-8efc-9a14546a8b1f\" /\u003e\n\u003cp align=\"center\"\u003eLoad Balancer API (Backend)\u003c/p\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg width=\"1001\" height=\"697\" alt=\"Azure secrets\" src=\"https://github.com/user-attachments/assets/6252116c-f71a-41cd-b4a7-5528cc219a3c\" /\u003e\n\u003cp align=\"center\"\u003eAzure Secrets\u003c/p\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg width=\"760\" height=\"647\" alt=\"SSH App Service\" src=\"https://github.com/user-attachments/assets/eeb418df-f4b8-4c9a-8a46-0f2f81600618\" /\u003e\n\u003cp align=\"center\"\u003eApp Service\u003c/p\u003e\n\u003c/div\u003e\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg width=\"970\" height=\"887\" alt=\"Workflow\" src=\"https://github.com/user-attachments/assets/b5112807-1e02-4558-a972-facba34dd5f0\" /\u003e\n\u003cp align=\"center\"\u003eGH Actions Workflow\u003c/p\u003e\n\u003c/div\u003e\n---\n\n## 🚀 Live Demo \u003ca name=\"live-demo\"\u003e\u003c/a\u003e\n\n- [Frontend Web App](https://softdefault-movies-app.azurewebsites.net/)\n- [API Endpoint (behind Load Balancer)](http://my-movie-analyst-lb.westus2.cloudapp.azure.com:8080/health)\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg width=\"778\" height=\"590\" alt=\"Movie Analyst main page\" src=\"https://github.com/user-attachments/assets/e804228f-3930-4fa1-bd6f-1106f811d83c\" /\u003e\n\u003cp align=\"center\"\u003eMovie Analyst main page\u003c/p\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg  width=\"773\" height=\"820\" alt=\"Our Movies Critics\" src=\"https://github.com/user-attachments/assets/1f495fae-c29d-4ce6-a87c-d0ec9636dbc9\" /\u003e\n\u003cp align=\"center\"\u003eOur Movies Critics\u003c/p\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg  width=\"917\" height=\"967\" alt=\"Latest Movie Reviews\" src=\"https://github.com/user-attachments/assets/c17f90c8-6720-4357-a275-639deecca0ed\" /\u003e\n\u003cp align=\"center\"\u003eLatest Movie Reviews\u003c/p\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg width=\"771\" height=\"827\" alt=\"Our Publication Partners\" src=\"https://github.com/user-attachments/assets/67478e8b-b0e5-4a5f-88ec-3de129e9bf6f\" /\u003e\n\u003cp align=\"center\"\u003eOur Publication Partners\u003c/p\u003e\n\u003c/div\u003e\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## 💻 Getting Started \u003ca name=\"getting-started\"\u003e\u003c/a\u003e\n\nTo get a local copy up and running, follow these instructions.\n\n### Prerequisites\n\nMost dependencies are installed automatically in the GitHub Actions workflow. However, for local development or debugging, ensure you have the following:\n\n- 🖥️ Azure CLI (`az`)\n- 📦 Terraform ≥ 1.5\n- ⚙️ Ansible ≥ 2.15\n- 🔐 SSH key pair for accessing virtual machines\n- 📦 Node.js ≥ 14 and npm (required for both frontend and backend)\n- 📚 `zip` utility (used to package the frontend app)\n- ☁️ Azure Service Principal credentials (used by the workflow):\n  - `ARM_CLIENT_ID`\n  - `ARM_CLIENT_SECRET`\n  - `ARM_TENANT_ID`\n  - `ARM_SUBSCRIPTION_ID`\n- 💡 *(Optional)* GitHub CLI (`gh`) – useful for managing secrets or manually triggering workflows\n\n\n### 🔧 Setup\n\n```bash\n# Clone this repository\ngit clone https://github.com/NeckerFree/azure-fullstack-automation.git\ncd azure-fullstack-automation\n```\ncreate a file \n## 📦 Provision Infrastructure (Terraform) \u003ca name=\"terraform\"\u003e\u003c/a\u003e\n\nInfrastructure provisioning is fully automated and triggered via **GitHub Actions** on every push or pull request to the `master` branch.\n\n- Terraform is initialized and executed within the workflow using predefined variables.\n- The deployment includes:\n  - A MySQL database on Azure\n  - A Load Balancer with 2 backend VMs\n  - Network and security resources\n- The entire infrastructure is provisioned from scratch via `terraform.yml`.\n\n## ⚙️ Configure Services (Ansible) \u003ca name=\"ansible\"\u003e\u003c/a\u003e\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n\u003cimg width=\"2216\" height=\"1205\" alt=\"Jumpbox NSG diagram\" src=\"https://github.com/user-attachments/assets/8a402bc6-5bb5-4070-98cc-6a13babf379a\" /\u003e\n\u003cp align=\"center\"\u003eAnsible Jumpbox Configuration\u003c/p\u003e\n\u003c/div\u003e\n\nOnce the infrastructure is up, **Ansible playbooks** are automatically triggered within the same CI/CD workflow to:\n\n- Configure the VMs with the required packages\n- Deploy the Node.js API to both backend nodes\n- Apply application settings\n- Validate MySQL schema creation and data population\n\nThis configuration is handled through the `deploy-api.yml` GitHub Actions workflow.\n\n## 🚢 Deployment \u003ca name=\"deployment\"\u003e\u003c/a\u003e\n\n- 🎯 **Trigger**: Every push or pull request to `master` kicks off a full deployment pipeline.\n- 🌐 **API** is publicly reachable via the Load Balancer’s IP address.\n- 💻 **Frontend** is deployed to Azure Web App using the **F1 Free Tier**.\n- 🔐 **Secure integration** between services via environment variables and Azure-managed credentials.\n- 🧨 A separate `terraform-destroy.yml` workflow is available to automatically destroy all infrastructure when needed.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n## 🔧 Customizing Variables \u003ca name=\"custom-variables\"\u003e\u003c/a\u003e\n\nYou can modify the following variables to adapt the deployment to your needs. These are defined in the Terraform configuration files:\n\n### infra/terraform.tfvars:\n\n```hcl\nallowed_ssh_ip        = \"xxx.xxx.xxx.xxx/32\"         # IP allowed to access VMs via SSH\nmysql_user            = \"mysqladmin\"                # MySQL admin user\nmysql_admin_password  = \"Sec#reP@ssword123!\"        # MySQL admin password\n```\n### infra\\variables.tf:\n```hcl\nvariable \"location\" {\n  default = \"westus2\"                               # Azure region to deploy resources\n}\n\nvariable \"admin_username\" {\n  default = \"myadminuser\"                                # Admin username for virtual machines\n}\n\nvariable \"lb_api_port\" {\n  default = 8080                                    # API port exposed by Load Balancer\n}\n```\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n---\n\n## ☁️ Remote Terraform State in Azure \u003ca name=\"remote-state\"\u003e\u003c/a\u003e\n\nTerraform uses remote state storage to persist infrastructure state across executions and team members.\n\nThis project stores the Terraform state file (`terraform.tfstate`) securely in an **Azure Storage Account** using a backend configuration like the following:\n\n```hcl\nterraform {\n  backend \"azurerm\" {\n    resource_group_name  = \"my-resource-group\"\n    storage_account_name = \"myterraformstate\"\n    container_name       = \"tfstate\"\n    key                  = \"infrastructure.tfstate\"\n  }\n}\n```\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n---\n\n## 👥 Authors \u003ca name=\"authors\"\u003e\u003c/a\u003e\n\n👤 **Elio Cortés**\n\n- GitHub: [@NeckerFree](https://github.com/NeckerFree)\n- Twitter: [@ElioCortesM](https://twitter.com/ElioCortesM)\n- LinkedIn: [elionelsoncortes](https://www.linkedin.com/in/elionelsoncortes/)\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## 🔭 Future Features \u003ca name=\"future-features\"\u003e\u003c/a\u003e\n- [ ] Enable autoscaling for the API tier\n- [ ] Implement managed identity-based DB auth\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## 🤝 Contributing \u003ca name=\"contributing\"\u003e\u003c/a\u003e\n\nContributions, issues, and feature requests are welcome!\n\nFeel free to open an issue, or request features.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## ⭐️ Show your support \u003ca name=\"support\"\u003e\u003c/a\u003e\n\nIf you like this project, please ⭐️ the repository and share it with others!\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## 🙏 Acknowledgements \u003ca name=\"acknowledgements\"\u003e\u003c/a\u003e\n\n- [Microsoft Azure documentation](https://learn.microsoft.com/en-us/azure/)\n- [Ansible Azure Collection](https://galaxy.ansible.com/azure/azcollection) contributors\n- [HashiCorp Terraform Modules](https://registry.terraform.io/)\n- [devops-rampup](https://github.com/aljoveza/devops-rampup) — Backend \u0026 frontend prototype used as base for this project\n- [EPAM DevOps Campus](https://campus.epam.com/en/training) — Cloud and DevOps learning program\n- [ChatGPT](https://chatgpt.com/) — Assistance in automation, CI/CD, and documentation\n- [DeepSeek](https://chat.deepseek.com/) — Assistance in automation, CI/CD, and documentation\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## ❓ FAQ \u003ca name=\"faq\"\u003e\u003c/a\u003e\n\n### 🔐 Where are secrets like passwords and keys stored?\nSecrets are securely stored as GitHub Actions secrets and injected at runtime into the workflows.\n\n### 🧪 Can I test changes before deploying to Azure?\nYes! You can test locally using `terraform plan` and `ansible-playbook` in dry-run mode before committing changes.\n\n### 🌎 Where is the infrastructure deployed?\nBy default, all resources are deployed to the `westus2` Azure region. You can change this in `infra/variables.tf`.\n\n### 🛠 What if I want to destroy all resources?\nYou can run the `terraform-destroy.yml` GitHub Actions workflow to safely destroy the provisioned infrastructure.\n\n### 🐘 How is the database created?\nThe Azure MySQL database is provisioned with Terraform and initialized using `movie_db.sql` from Ansible.\n\n### 🌐 What is the default URL for the frontend?\nThe frontend is hosted on Azure Web App. The exact URL depends on the generated Azure App Service name. Check the Azure Portal or output logs.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## 📝 License \u003ca name=\"license\"\u003e\u003c/a\u003e\n\nThis project is licensed under the [MIT License](./LICENSE).\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneckerfree%2Fazure-fullstack-automation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneckerfree%2Fazure-fullstack-automation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneckerfree%2Fazure-fullstack-automation/lists"}