# I built Goliat: an open-source, self-hosted Azure inventory and FinOps dashboard

> Source: <https://dev.to/danieljsaldana/i-built-goliat-an-open-source-self-hosted-azure-inventory-and-finops-dashboard-2nlf>
> Published: 2026-10-29 22:01:27+00:00

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?*

I 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.

## 
  
  
  What it does

- 
**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.
- 
**Global search** (`Ctrl+K` /`⌘K` ) over resources, IDs, tags, subscriptions and views, with no extra cloud calls.
- 
**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.
- 
**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.
- 
**Roles:** sign-in with Microsoft Entra ID, plus an optional Members view to grant or revoke the Goliat admin role, with an audit trail.
- 
**Bilingual UI** in English and Spanish.

## 
  
  
  How it works

Collection and presentation are fully decoupled. They communicate through a single versioned JSON document in Blob Storage.

1. 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.
2. 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.
3. 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.

## 
  
  
  Security by design

This was the part I cared about most, since an inventory tool sees everything:

- 
**Managed identities everywhere.** There are no secrets in the code, and credentials never reach the browser.
- 
**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.
- 
**Configuration only.** The collector never reads blob contents, database data, Key Vault secrets, account keys or connection strings.
- 
**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.
- 
**Careful logging.** Request bodies, cookies, tokens, query strings and SQL are never logged.

## 
  
  
  Deploying it

Everything lives in one resource group, created with Bicep and a PowerShell wrapper:

By 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.

Prefer containers? The Dockerfile has `runner`, `collector` and `migrator` targets.

To try it locally with fake data, you only need Node.js and PostgreSQL:

## 
  
  
  Stack

Next.js 16 · React · shadcn/ui · Tailwind CSS 4 · Recharts · Auth.js · PostgreSQL · Azure Functions (Node.js) · Bicep · PowerShell · Playwright · GitHub Actions

The 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.

## 
  
  
  Try it

You 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.

If you try it, I'd love to hear what you think. Feedback, issues and stars are all very welcome. ⭐

👉 [https://github.com/danieljsaldana/goliat-cloud-inventory](https://github.com/danieljsaldana/goliat-cloud-inventory)
