/docs

Frugal documentation

Help documentation for Frugal, secret-less Azure Virtual Desktop management in your own tenant.

Frugal manages Azure Virtual Desktop and its cost from inside your own Azure tenant. It runs as a container on a managed identity — no secrets, no keys — and only ever touches what you explicitly grant it. These docs walk each feature and the access it needs.

Install & first run

Frugal installs with a single Cloud Shell command. It creates the sign-in app registration, the platform (database, key vault, container app), and the managed identity — then hands you the URL.

$ curl -sL https://frugal.run/install.sh | bash -s -- --region <azure-region>

Paste it into Azure Cloud Shell — open shell.azure.com (or the >_ icon in the Azure portal), choose Bash, and paste. Cloud Shell is already signed in as you and provides the shell itself, so nothing is installed on your machine and it runs the same from Windows, macOS or Linux.

Permissions to assume before installing

These are needed only for the one-time install — it registers a sign-in app and creates role assignments. Afterwards Frugal runs as a scoped, least-privilege managed identity; you don’t keep these rights for day-to-day use.

  • Owner on the target subscription (equivalently Contributor + User Access Administrator) — the install grants Frugal’s managed identity its scoped roles, which requires writing role assignments.
  • Global Administrator, or Application Administrator + Privileged Role Administrator, in Entra ID — to register the sign-in app, grant the managed identity read-only directory (Graph) permissions, and admin-consent them.
No standing admin neededIf one person can’t hold both, split it: an Entra admin runs the app-registration + consent steps once, and a subscription Owner runs the platform + role-assignment step. When you hold both, the one-liner does all three in order.

Install options

Append any of these flags to the command:

--region <azure-region>      # required, e.g. australiaeast
--subscription <id>          # target subscription (defaults to Cloud Shell's current)
--image-tag <version>        # pin a release, e.g. 0.6.55 (defaults to the latest)
--db-password <pw>           # DB admin password (a strong random one is generated if omitted)

When it finishes it prints your app URL, e.g. https://frugal-app.<region>.azurecontainerapps.io. Open it and sign in with your work account — one consent prompt, and you land as Admin.

Secret-less by designThe install never stores a client secret in the app. It authenticates as a user-assigned managed identity that lives in your tenant.

Sign in & roles

Frugal uses your Entra (Azure AD) work account to sign in. Two roles govern what you can do:

  • Admin full control — create/operate host pools, build images, run scripts, add subscriptions, change settings.
  • Viewer read-only — dashboards, costs, governance and posture, but no changes.

The first person to sign in lands as Admin. Admin-only controls are hidden (not just disabled) for Viewers, so the console stays uncluttered.

Subscriptions

Frugal only sees subscriptions whose access you have granted to its managed identity — it is least-privilege by design. The Subscriptions page is where you add, discover, enable and sync them.

Add a subscription

Open Subscriptions → Add a subscription, paste the subscription ID (there is a Find your subscription IDs link straight to the Azure portal), then choose what Frugal should do there:

  • View data — read-only cost, resources and governance. Grants Reader + Cost Management Reader.
  • Manage AVD — full lifecycle (host pools, session hosts, images). Deploys a scoped grant: Contributor plus a constrained RBAC Administrator limited to one resource group, plus the FSLogix, gallery and reader roles.

Frugal generates the exact command for the tier you pick. Run it in Cloud Shell as an Owner / User Access Administrator of that subscription, e.g. for View data:

# <mi-principal-id> is shown on the Subscriptions page
az role assignment create --assignee <mi-principal-id> --role "Reader" --scope /subscriptions/<sub-id>
az role assignment create --assignee <mi-principal-id> --role "Cost Management Reader" --scope /subscriptions/<sub-id>
Least privilegeFrugal never asks for Owner or User Access Administrator. The Manage tier uses a constrained RBAC Administrator scoped to a single resource group with ABAC conditions.

Discover

Once the grant is in place, click Discover. Frugal lists every subscription its identity can now see and adds any new ones disabled — so nothing is synced or managed by surprise. A prompt tells you exactly which subscriptions are off; flip the Enabled toggle on the ones you want.

Built for scaleCustomers run Frugal over tens of subscriptions. Discovery is opt-in, and enabled subscriptions sync in parallel, so a large estate refreshes in the time of its slowest few rather than one-at-a-time.

Sync data

Cost and AVD data refresh automatically (cost nightly; topology every minute). To pull fresh data on demand, click Sync data. Each subscription shows a live status — SYNCING then OK or FAILED with the reason — and the button reports how many are still in flight.

A FAILED badge usually means the identity can see the subscription but is missing a role there (for example, no Cost Management Reader). The error text names the fix.

Host pools

The Host Pools page lists every AVD host pool across your enabled subscriptions with its session-host count and active sessions. From here you create and operate pools without leaving Frugal.

  • Create pooled (shared, multi-session) or personal (one host per user) pools.
  • Add or drain session hosts; host removal deregisters the host and tears down its VM in the background.
  • Export as Bicep — generate infrastructure-as-code for a pool to version or reproduce it.
Needs Manage AVDCreating or operating pools requires the Manage AVD grant on that subscription. View-only subscriptions still show pool data.

Auto-scale

Auto-scale ramps session-host capacity to real demand and powers idle hosts down — the single biggest AVD cost lever. Define when capacity should be available and how aggressively to reclaim it; Frugal starts and deallocates hosts to match, so you stop paying for empty desktops overnight and on weekends.

Cost Explorer

Frugal syncs Azure Cost Management into its own store and attributes spend by tag, so you can see exactly where money goes — per subscription and per tag.

  • A rolling 3-day window is re-pulled each sync, because Cost Management data lags up to ~72 hours before it settles.
  • Tag attribution powers a coverage view — spend that is not tagged shows up as ungoverned (see Governance).
Needs Cost Management ReaderThe View-data grant is enough. No management permission is required to read cost.

Images

Build golden images for your pools without hand-crafting VMs.

  1. Build from a marketplace or gallery base image.
  2. Edit the running build VM over a secure Bastion RDP session — install apps, apply settings, copy files.
  3. Customise with scripted actions — drop in a ready-made Office or dev desktop, apply Essential Eight hardening, or run your own PowerShell.
  4. Capture — Frugal runs sysprep, generalises the VM and stores the image in your shared gallery, ready to roll to pools.
If a capture failsFrugal keeps the build VM running and surfaces the sysprep error, so you can inspect it rather than losing your work. Fix the cause, then re-capture.

Essential Eight

Frugal ships one-click hardening bundles aligned to the ACSC Essential Eight Maturity Model, with a live posture dashboard that scores a host pool against the controls it can verify.

  • Maturity Level 1 and Maturity Level 2 bundles: application control, Office macro hardening, ASR rules, PowerShell logging, removal of legacy components, and more.
  • Delivery is chosen per pool: pooled desktops are hardened in the image; personal desktops are steered to Intune policy.
  • The dashboard shows each control’s status, requirement and how Frugal delivers it.
  • Guidance, groundedControls map to the published ACSC model. Frugal automates the ones it can and tells you clearly where a control needs Entra / Intune configuration outside its reach.

Governance

The Governance page reads every resource Frugal can see and ranks the two things that drive hidden cost and risk:

  1. Untagged resources (highest priority) — can’t be attributed to an owner or cost centre. Newest untagged sorted to the top.
  2. Recently created resources — so new sprawl gets reviewed as it appears.
Reader is enoughGovernance needs no new grant beyond read access. It scans subscriptions in parallel and paces itself under Azure’s rate limits.

Scripted actions

Run PowerShell across your session hosts — built-in actions or your own scripts — for patching, configuration, hardening and cleanup, without RDP-ing into each host. The same actions can be picked as steps when you build an image, so a golden image bakes them in.

The built-in library spans host diagnostics & maintenance (health, disk report + cleanup, agent restart, diagnostics bundle, Group Policy / Intune sync, certificate import), image prep (multi-session optimisation via VDOT, AVD-optimised Teams, per-machine OneDrive with Known Folder Move, language packs, Windows updates, debloat), the desktop profiles below, and the Essential Eight hardening steps.

Write your own

Add your own on the Scripted actions page: give it a name and description, paste a PowerShell script, and optionally declare parameters the operator fills in at run time (text / number / boolean — each becomes a $variable in the script). Run it against a whole host pool or a single host, or select it as a step when you build an image. Built-in actions can’t be edited or deleted — duplicate one to start from a working example. Keep secrets out of the script text — put them in $SecureVars (below).

Injected variables

Frugal prepends a context block to every run, so scripts stay portable across pools and tenants with no hard-coded ids or paths. Available in every script:

  • $Frugal.HostPool — the host pool the run targets, and $Frugal.ResourceGroup its resource group.
  • $Frugal.SessionHost — the session host this run is executing on.
  • $Frugal.SubscriptionId / $Frugal.TenantId — the subscription and Entra tenant ids.
  • $Frugal.FslogixStorageAccount and $Frugal.FslogixUnc — the FSLogix storage account + profiles UNC path (blank if the pool has no FSLogix), e.g. \\acct.file.core.windows.net\profiles.
  • $Vars.<name> — your shared, plain-text variables (set on the Scripted actions page).
  • $SecureVars.<name> — secrets pulled from Key Vault at run time; never stored in the script.
  • $<parameter> — one variable per parameter you declared on the action, already typed.

Ready-made desktop profiles. Two of the most common images, one tick each when you build:

  • Office desktop — Microsoft 365 Apps. Silent install via the Office Deployment Tool (Word, Excel, PowerPoint, Outlook…). Shared Computer Activation is on by default — required on pooled / multi-session hosts, or Office licensing breaks. Change the update channel or trim apps inline, or set $Vars.officeChannel.
  • Dev desktop — VS Code + Azure. Installs VS Code, Git, Azure CLI, Windows Terminal, Node LTS, the .NET SDK and PowerShell 7, plus the Azure PowerShell Az module for all users. Adjust the package list with $Vars.devPackages.
Bake, don’t repeatPick a profile when building an image, so every host in the pool ships ready to use — rather than running it on each host after the fact. Office’s download + install adds ~10–20 min to a build.

Upgrades

Frugal upgrades in place. It rolls the container image only — your database and settings are preserved — and migrations run automatically.

$ curl -sL https://frugal.run/upgrade.sh | bash

Pin a specific build with --image-tag <version>. The upgrade waits for the new revision to become healthy before finishing.

Never re-run the installer to upgradeRe-running install.sh stands up a fresh stack (and a fresh database). Use upgrade.sh to keep your data.

Tear down

To remove everything and return to zero cost:

az stack sub delete --name frugal --action-on-unmanage deleteAll --yes
az ad app delete --id <sign-in-app-id>

Support

Frugal is $10 / month, on your honour — no feature gates, no license keys, no nagware. Every capability is on for everyone. If it saves you money, chip in here.

DisclaimerUse at your own risk. Frugal is provided as-is, with no warranty of any kind — the author is not responsible for any problems, data loss, or Azure costs arising from its use.