Technical case study / Azure platform operations

Private Secure AI Automation Platform & Personal Agent

I built a privately operated automation environment around n8n and an OpenClaw personal agent with scoped control of the Azure environment, then learned that technically correct cloud architecture can still be economically wrong. This is the build, the failure, and the evidence-backed recovery.

EUR 156.68 verified May platform cost Pre-tax cost across PersonalStuff and the Azure-managed Container Apps environment.
4 apps one shared environment n8n, the OpenClaw personal agent, PromptTriage UI, and PromptTriage API in Sweden Central.
9 paid categories cleared Post-teardown inventories verified each targeted runtime category as empty.
EUR 5 monthly guardrail New subscription budget with notifications at 80% and 100%.
01 / Executive summary

A capable private platform with the wrong idle-cost profile.

The platform successfully migrated a stateful automation workload, connected an AI operator to reusable workflows, and supported passwordless container delivery. Its failure was operational and economic rather than functional.

n8n began on a Google Cloud VM. I moved its data and configuration into Azure Files, rebuilt its PostgreSQL dependency, and ran n8n beside an OpenClaw personal agent in Azure Container Apps. Tailscale and Termius provided private remote access. Resource-group-scoped Azure access let the personal agent inspect and operate sibling services, while shared workflow storage let it create, trigger, and reuse n8n automations.

The same Container Apps environment also hosted the PromptTriage frontend and API. That consolidation worked, but VNet integration, always-on replicas, Premium services, private endpoints, and cross-resource-group ownership created a persistent monthly baseline that was disproportionate to actual use.

02 / Problem and requirements

Move stateful automation into a private, remotely operable container platform.

  • Preserve n8n workflows and configuration while migrating away from a directly managed VM.
  • Run n8n and OpenClaw as separate services with private ingress and durable shared storage.
  • Let OpenClaw reuse n8n workflow logic and inspect approved Azure resources without broad subscription access.
  • Support secure remote administration from a workstation or mobile device through Tailscale.
  • Build and deploy PromptTriage images from GitHub without storing Azure credentials in repository secrets.
  • Keep application services revisioned and independently deployable inside one managed environment.
03 / Architecture

Four applications, three resource groups, and one important hidden dependency.

The shared personalcontenv Consumption environment belonged to the Prompttriage resource group but used the Infastructure subnet from PersonalStuff. Azure then created a Standard Load Balancer and static public IP in the managed ME_personalcontenv_Prompttriage_swedencentral group.

Recovered pre-teardown resource map Migration, access, application, state, delivery, and recovery relationships captured before teardown.
  1. 01 Origin and access

    n8n on Google Cloud VM Stateful migration origin
    Tailscale + Termius Private workstation and mobile operation
  2. 02 Shared app environment

    openclaw-system / personal agent Internal ingress, scoped control, 1 CPU / 2 GiB, min 1
    n8n-worker Internal ingress, 0.5 CPU / 1 GiB, min 1
    PromptTriage UI + API External ingress, min 0
  3. 03 State and networking

    Azure Files shared mount OpenClaw root + n8n_data subpath
    PostgreSQL Flexible Server B1ms / 32 GiB
    VNet + private endpoints ACR, Files, DNS, managed LB/PIP
  4. 04 Delivery and identity

    GitHub Actions + Entra OIDC Passwordless main-branch federation
    ACR build and scan gates Commit-SHA images and managed-identity pulls
    Container Apps revisions Separate frontend and backend releases
  5. 05 Evidence and recovery

    Cost and resource exports CSV, JSON, ARM, activity, and topology
    Controlled teardown Before-and-after verification
    Lower-cost restore path Basic ACR, min 0, no default VNet integration
04 / Security and delivery

The security model was real, but cost was not treated as a security boundary.

  • Private runtime: n8n and OpenClaw used internal ingress, VNet integration, private DNS, and private endpoints for selected data paths.
  • Remote access: Tailscale limited administration to a private overlay; Termius provided the mobile shell client.
  • Personal-agent identity: OpenClaw used scoped Azure access to inspect and operate sibling services without receiving broad subscription control or embedding long-lived credentials.
  • CI/CD identity: GitHub Actions federated to Entra through an OIDC subject restricted to the PromptTriage main branch.
  • Delivery path: workflows ran build and security checks, pushed commit-SHA images into ACR, passed registry checks, and updated separate Container Apps revisions.
  • Missed control: resource locks, stronger deny boundaries, mandatory dry runs, and tested restore gates should have constrained destructive agent actions.
05 / Cost analysis

Idle architecture, not user traffic, explained the bill.

May exports attribute EUR 156.68 pre-tax to PersonalStuff and the managed Container Apps environment. Another EUR 3.97 came from scheduled query rules outside this platform subtotal.

personalcontreg EUR 45.58
Premium ACR
openclaw-system EUR 39.93
Container App with minReplicas=1
capp-svc-lb + public IP EUR 19.69
VNet-integrated environment baseline
database-personal EUR 16.39
PostgreSQL Flexible Server
n8n-worker EUR 13.93
Container App with minReplicas=1
two private endpoints EUR 13.13
Private ACR and Files paths
gcpvmdata EUR 6.70
Premium Azure Files
Historical Azure Cost Analysis view showing accumulated subscription cost through May 2026
Historical subscription-wide screenshot. It establishes the broader cost trend but is not used to attribute the EUR 156.68 platform total; that figure comes from retained May resource-group and resource-meter exports.
06 / Failure modes and lessons learned

Where my judgment failed.

I confused elasticity with scale-to-zero

n8n and OpenClaw were configured with minReplicas=1. The platform could scale, but its two private automation services could never stop billing.

I selected production-grade isolation before validating the need

Premium ACR, Premium Files, private endpoints, private DNS, and VNet integration were defensible security controls, but they were not economically proportionate to an intermittently used personal platform.

I made ownership difficult to read

The Container Apps environment lived in Prompttriage, used a subnet in PersonalStuff, hosted apps from both groups, and created paid load-balancer infrastructure in a third Azure-managed group.

I monitored cost without enforcing a budget

Workbooks explained allocation after usage accumulated. There was no low monthly budget, action threshold, or teardown rule preventing the spend in the first place.

I allowed destructive automation before recovery was mature

Operational agents need least privilege, deny assignments or resource locks where appropriate, dry-run behavior, human approval, immutable evidence, and a tested restore boundary.

The central lesson is not that private networking or managed services are bad. It is that every control needs a threat model, an ownership model, and a cost model. For a low-traffic personal system, a simpler public Consumption environment with strong application authentication can be the more responsible default.

07 / Recovery and operations

Evidence first, teardown second, verification last.

  1. Exported May cost data by service, resource group, resource, and individual meter.
  2. Captured pre-teardown inventories, app settings, scaling limits, mounts, identities, networking, and the Azure-managed environment resources.
  3. Exported ARM snapshots for PersonalStuff, Prompttriage, the managed environment group, and gpumodels.
  4. Wrote the resource map, controlled teardown script, PromptTriage restore script, and lower-cost PersonalStuff rebuild notes.
  5. Removed the two main resource groups and paid monitoring rules, then queried every targeted resource category again.
  6. Created a EUR 5 monthly budget with notifications at 80% and 100%.

Recovery boundary: resource definitions and architecture were preserved. Secrets, database rows, Azure Files contents, historical images, DNS-provider records, and completed TLS state were intentionally excluded or treated as disposable.

08 / Results and outcome

The platform is archived, but it is not lost.

4 ARM exports

Original resource-group snapshots retained beside exact resource inventories.

2 rebuild paths

PromptTriage restore automation plus lower-cost n8n/OpenClaw reconstruction notes.

0 targeted runtime resources

Verified after teardown across nine paid categories rather than assumed from delete commands.

One reusable operating rule

No Premium SKU, private endpoint, VNet integration, or always-on replica without written justification.

A future restore would use Basic ACR, Container Apps with minReplicas=0, Standard storage, and no VNet integration by default. PostgreSQL would exist only while actively needed, and the teardown path would be tested before the runtime was considered complete.

09 / What I would improve next

Make cost and recoverability deployment gates.

  • Replace exported state as the primary rebuild mechanism with reviewed Bicep or Terraform modules and deployment tests.
  • Add policy checks that reject Premium SKUs, private endpoints, or minReplicas above zero unless an explicit exception is approved.
  • Separate product environments by lifecycle and ownership so one subnet or environment cannot silently couple unrelated applications.
  • Require budget creation, alerts, cost tags, an owner, an expiry date, and a teardown command before deployment.
  • Use least-privilege agent roles, protected resource groups, immutable activity exports, and human approval for destructive operations.
  • Run a restore drill from empty resource groups and record recovery time before calling the platform recoverable.
10 / Interview explanation

The concise technical version.

I migrated a stateful n8n workload from a VM into a private Azure Container Apps platform, integrated OpenClaw through shared workflow storage, and built a passwordless GitHub-to-ACR delivery path. The system worked, but I overbuilt the idle architecture.

When the cost evidence exposed that mistake, I mapped the exact topology and meter-level costs, exported recoverable state, removed the paid runtime, verified the result, and designed a cheaper restore path. The main lesson was that FinOps, blast-radius control, and recovery engineering belong in the initial platform design, not in cleanup work.

Resume bullets

  • Built a private Azure Container Apps automation platform for n8n and OpenClaw with PostgreSQL, shared Azure Files, Tailscale access, managed identity, and GitHub OIDC delivery.
  • Diagnosed EUR 156.68 in verified monthly platform cost to Premium services, always-on replicas, private endpoints, and VNet-managed networking.
  • Reduced the targeted paid runtime surface to zero while preserving four ARM exports, exact before-and-after inventories, resource maps, restore automation, and a EUR 5 budget guardrail.