# Provisioned a second server from code on a second cloud provider, creating the firewall before the machine so it is born behind one, with both providers' firewalls written directly against their REST APIs to avoid a third‑party collection.

2025

**Situation.** A second machine was needed for an application tier, at a different provider from the first, and the first machine's own history was the argument for how to do it: it had been created by hand, and its firewall had been added afterwards, which leaves a window where a fresh host with a default password policy is reachable from the internet.

**Task.** The machine had to be created from the repository, and it had to be born behind its firewall rather than acquiring one shortly afterwards.

**Action.** Ordering carried the design. The firewall play runs before the server play, so the rule set exists before there is anything for it to protect; on the other provider, tagging runs before the cloud firewall because a firewall that targets tags needs the tags to exist first. Both providers' firewalls are written directly against their REST APIs through a generic HTTP task rather than through a vendor collection, which removes a dependency and its version drift at the cost of writing the request shapes by hand. The role that creates the machine adopts an existing one rather than duplicating it if it is already there, so re‑running is safe. It is also documented, in its own file, as the one role in the repository that spends money — the instance type, the region, the specification and the monthly cost in euros are all written down, because a play that bills someone should say so where they will read it. That play is also the one that cannot be rehearsed the usual way: the generic HTTP task declares no check‑mode support, so a dry run skips every task in it. The rehearsal is done against the firewall play instead, which is free and reversible.

**Result.** A second host can be created, or re‑adopted, from the repository, behind a firewall that already exists, at a cost the file states. The one thing dry‑run cannot cover is named in the same file rather than left as a surprise.

---

- Role: Infrastructure Automation Engineer
- Categories: [APIs & Integration](https://engineer.company/categories/api/), [Infrastructure](https://engineer.company/categories/infrastructure/), [Cloud](https://engineer.company/categories/cloud/), [Automation & CI/CD](https://engineer.company/categories/automation/), [Security](https://engineer.company/categories/security/), [Python](https://engineer.company/categories/python/)
- Services: [Cloud Infrastructure & Migration](https://engineer.company/services/cloud-infrastructure/), [Infrastructure as Code](https://engineer.company/services/infrastructure-as-code/), [Networking & VPN Setup](https://engineer.company/services/networking-vpn/), [Security & Access Management](https://engineer.company/services/security-access/)

<https://engineer.company/portfolio/provisioned-a-second-server-from-code-123/>
