Skip to main content
Everything an environment needs before the first command, mapped to the plan’s required inputs (plan section 3). An input that is missing blocks the steps named in its row; nothing in the repository substitutes a made-up value for one.

Owner inputs

Besides the inputs, the environment’s Ansible variables that are not secret go in infra/ansible/inventories/<env>/group_vars/all.yml (bootstrap.md step 1): sa_image_registry and sa_operator_github_ids. The file already holds the settings every Azure node shares (sa_tls: cloudflare, sa_public_bind_ipv4). PostgreSQL. Every environment runs PostgreSQL 18.7 (postgres:18.7-trixie, PGDG 18.7-1.pgdg13+2, pinned on 2026-11-13 in infra/ansible/vars/pins.yml and deploy/images/postgres-ha.Dockerfile).

Hosting: providers, cost and accounts for the 12-month service window

RFP section 3.4 makes the proposer host the service for 12 months. This section states what that costs and who holds what. Prices were read on 2026-11-13 from the Azure retail prices API (https://prices.azure.com/api/retail/prices, region swedencentral, pay as you go, USD excluding VAT) and change: check them again before ordering.

Providers

The probe runs on a host outside Azure that the owner already operates (probe.md); it adds no provider.

Monthly cost estimate per environment

Usage-based items come on top and have not been measured on a real environment yet: Traffic Manager DNS queries (0.54 per million), Blob Storage ZRS hot (0.023 per GB-month, writes 0.0625 per 10,000), Standard SSD transactions (0.002 per 10,000), internet egress (the first 100 GB a month free, then 0.087 per GB), and inter-zone traffic, which the price list meters at 0.01 per GB in each direction. With 1-year reserved instances for the five VMs (201.00 per year for Standard_B2als_v2 and 402.00 per year for Standard_B2as_v2, from the same API), the VMs cost 117.25 a month instead of 198.78 and the fixed total is 179.30. The 12-month service window matches the 1-year term. A staging environment that runs all month costs the same as production without the reservation; Azure bills VMs by the second, so staging destroyed between drills (make staging-destroy) costs only the time it ran, plus its public addresses while they exist.

Azure subscription

Checked on 2026-11-13 with read-only az commands against the owner’s subscription: OpenTofu registers no resource providers itself (resource_provider_registrations = "none"). A new subscription registers the five above once: az provider register --namespace Microsoft.Network (and the others), then checks az provider show -n Microsoft.Network --query registrationState. If a quota is lower in another subscription, raise it under Quotas in the Azure portal (Compute, region Sweden Central, family “Standard Basv2 Family vCPUs”).

Account holder, billing and renewal

Not decided: blocked on SCF. Who holds the domain, the Azure subscription, the Cloudflare account and the repository from day one is an open question to SCF (plan section 27, “Who owns the domain, cloud accounts and repository from day one?”). The answer sets who pays, who receives the providers’ billing and abuse mail, and what the handover moves (../handover/checklist.md). Until it is answered, this document states only the requirements any arrangement must meet:
  • Each provider is billed by card or invoice to the account holder monthly, for at least the 12-month window; both suspend unpaid accounts. The availability statement lists a billing failure as a single point of failure (../reference/availability.md), so the payment method needs an owner who is alerted to failed charges and a second person who can pay.
  • The domain must be renewed for the whole window plus the handover (input I4), with automatic renewal on.
  • Every provider account holds at least two administrators, so one person’s absence cannot lock the operator out.

Controller (the machine you deploy from)

A Linux or macOS machine with the repository checked out. Versions are the plan section 5 pins. The Makefile calls sops and tofu from PATH. The controller tools install SOPS under a versioned name, so either link it (ln -s ~/.local/share/veristar/tools/sops-3.13.3 ~/.local/bin/sops) or pass it per command (make SOPS=~/.local/share/veristar/tools/sops-3.13.3 staging-plan). Put age and age-keygen from ~/.local/share/veristar/tools/age/ on PATH the same way.

Steps

  1. Install the controller tools:
    Expected: uv creates the venv, installs the requirements, then the controller-tools play ends with failed=0.
  2. Check the local tooling works without any account:
    Expected (run 2026-11-13): for each of staging and production Success! The configuration is valid. and Success! 8 passed, 0 failed.; ansible-lint ends with Passed: 0 failure(s), 0 warning(s) ... Profile 'production' was required, and it passed.
  3. Collect the inputs in the table above that the environment needs: I2 to I6, I8 and I13 to I15 for a full staging, plus I1. Each person who will decrypt secrets makes an age identity (secrets.md section 4) and sends only the public key.
  4. Sign in to Azure on the controller and select the subscription:
    Expected: both lines show a limit of at least 12.
  5. Create the Cloudflare API token (input I6) in the Cloudflare dashboard under My Profile, API Tokens, Create Token, Custom token: permissions Zone Zone Read and Zone DNS Edit; zone resources Include Specific zone <input I4>; no account permissions; client IP filtering optional. Caddy’s DNS module looks the zone up by name, which needs Zone:Read besides Zone:DNS:Edit; OpenTofu’s zone lookup needs the same two. Store it only in the SOPS files (secrets.md). One token per environment keeps a rotation local.
Steps 1 and 2 were run on 2026-11-13 with the output quoted above. The quota check of step 4 was run on the owner’s Mac on 2026-11-13 (section “Azure subscription”), and the token of step 5 exists for veristar.app.