{"slug": "i-built-goliat-an-open-source-self-hosted-azure-inventory-and-finops-dashboard", "title": "I built Goliat: an open-source, self-hosted Azure inventory and FinOps dashboard", "summary": "A developer built and open-sourced Goliat Cloud Inventory, an MIT-licensed, self-hosted Azure inventory and FinOps dashboard that runs read-only inside a user's own tenant. The tool decouples collection from presentation: an Azure Function queries Azure Resource Graph and ARM on a timer, validates a versioned JSON document, and publishes it to Blob Storage, which a Next.js backend imports into PostgreSQL in a single transaction across 73 inventory views. It uses managed identities and least-privilege roles, fails closed on invalid auth configuration, and surfaces missing cost data explicitly rather than reporting zero spend.", "body_md": "If you manage more than a couple of Azure subscriptions, you know the drill: the portal is great for one resource at a time, but answering simple questions across everything gets painful. *Which VMs are running where? Which resources have no `Owner` tag? What did we actually spend on AKS last month?*\n\nI wanted one place to answer those questions, running in my own tenant with read-only access. So I built **Goliat Cloud Inventory** and released it as open source under the MIT license.\n\n## \n  \n  \n  What it does\n\n- \n**Inventory:** 73 views in 12 service groups: compute, containers, web and APIs, networking, storage, databases, security, integration, data and AI, observability, and tags. Each category has an overview with KPIs and charts. Every table supports subscription filters, search, column filters, grouping, sorting, pagination and export.\n- \n**Global search** (`Ctrl+K` /`⌘K` ) over resources, IDs, tags, subscriptions and views, with no extra cloud calls.\n- \n**FinOps:** actual and amortized costs from Azure Cost Management, with daily trends and breakdowns by service, subscription, resource group and resource. Missing data or permissions are shown explicitly,**never as zero cost** , and currencies are never mixed.\n- \n**Administration:** Function, PostgreSQL and Blob Storage health and metrics, the collector schedule, monitored tag keys, and a warning when the published inventory differs from the imported one.\n- \n**Roles:** sign-in with Microsoft Entra ID, plus an optional Members view to grant or revoke the Goliat admin role, with an audit trail.\n- \n**Bilingual UI** in English and Spanish.\n\n## \n  \n  \n  How it works\n\nCollection and presentation are fully decoupled. They communicate through a single versioned JSON document in Blob Storage.\n\n1. An **Azure Function** (Flex Consumption) runs on a timer or on demand. It queries**Azure Resource Graph** , fills in the gaps from**ARM** , validates the whole document and publishes it with an ETag condition. If any query fails, nothing is published.\n2. The **Next.js backend** downloads the blob, validates the contract and imports all 73 views into PostgreSQL in**a single transaction** . A failed import keeps the previous snapshot, and the same ETag is never imported twice.\n3. The **Refresh** button asks the Function for a new generation with an Entra token, waits for it, imports it and reloads the UI. A PostgreSQL advisory lock allows only one manual refresh at a time across all users and replicas.\n\n## \n  \n  \n  Security by design\n\nThis was the part I cared about most, since an inventory tool sees everything:\n\n- \n**Managed identities everywhere.** There are no secrets in the code, and credentials never reach the browser.\n- \n**Least privilege.** The collector only has**Reader** . The web gets blob read access,**Cost Management Reader** , and two small custom roles for metrics and Function management.\n- \n**Configuration only.** The collector never reads blob contents, database data, Key Vault secrets, account keys or connection strings.\n- \n**Fail closed.** If the auth configuration is invalid, access is blocked; Goliat never falls back to public mode. Roles are re-checked on the server on every request.\n- \n**Careful logging.** Request bodies, cookies, tokens, query strings and SQL are never logged.\n\n## \n  \n  \n  Deploying it\n\nEverything lives in one resource group, created with Bicep and a PowerShell wrapper:\n\nBy default this creates App Service F1, PostgreSQL Flexible Server B1ms, a Flex Consumption Function and a Storage account. To be clear: **it isn't free**, because PostgreSQL doesn't scale to zero. There are `stop`, `start` and `destroy-plan` commands to keep costs under control.\n\nPrefer containers? The Dockerfile has `runner`, `collector` and `migrator` targets.\n\nTo try it locally with fake data, you only need Node.js and PostgreSQL:\n\n## \n  \n  \n  Stack\n\nNext.js 16 · React · shadcn/ui · Tailwind CSS 4 · Recharts · Auth.js · PostgreSQL · Azure Functions (Node.js) · Bicep · PowerShell · Playwright · GitHub Actions\n\nThe project has unit tests, PostgreSQL integration tests and Playwright browser tests on desktop and mobile. They run on every push and need no cloud credentials.\n\n## \n  \n  \n  Try it\n\nYou don't need an Azure account to look around. The **[interactive demo](https://danieljsaldana.github.io/goliat-cloud-inventory/)** runs entirely in your browser with fictional data, including the inventory, FinOps, user management and admin views.\n\nIf you try it, I'd love to hear what you think. Feedback, issues and stars are all very welcome. ⭐\n\n👉 [https://github.com/danieljsaldana/goliat-cloud-inventory](https://github.com/danieljsaldana/goliat-cloud-inventory)", "url": "https://wpnews.pro/news/i-built-goliat-an-open-source-self-hosted-azure-inventory-and-finops-dashboard", "canonical_source": "https://dev.to/danieljsaldana/i-built-goliat-an-open-source-self-hosted-azure-inventory-and-finops-dashboard-2nlf", "published_at": "2026-10-29 22:01:27+00:00", "updated_at": "2026-10-29 22:17:54.128686+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "mlops"], "entities": ["Goliat Cloud Inventory", "Microsoft Azure", "Azure Resource Graph", "Azure Functions", "PostgreSQL", "Next.js", "Microsoft Entra ID"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/i-built-goliat-an-open-source-self-hosted-azure-inventory-and-finops-dashboard", "markdown": "https://wpnews.pro/news/i-built-goliat-an-open-source-self-hosted-azure-inventory-and-finops-dashboard.md", "text": "https://wpnews.pro/news/i-built-goliat-an-open-source-self-hosted-azure-inventory-and-finops-dashboard.txt", "jsonld": "https://wpnews.pro/news/i-built-goliat-an-open-source-self-hosted-azure-inventory-and-finops-dashboard.jsonld"}}