PS Bootcamp App Security Lab

Manual setup: bring your own lab environment

You picked the manual path. Arrive at class with your own pre-built lab environment instead of using the automated launcher that deploys to a fresh AWS sandbox account. This page covers the environment used by the Cloudflare PS Bootcamp Application Security course.

The automated path (go back) is the recommended path. Building three correctly-isolated VMs with the right firewall rules, user accounts, web content, the public-api service, and SSH configuration by hand takes a couple of hours and is easy to get wrong. The manual path exists for students who cannot use a fresh AWS account. Choose this path only if you really need to.

What you need

An Ubuntu workstation, two Ubuntu origin servers, a domain, and a Cloudflare Enterprise account with the right Application Security add-ons.

These add-ons enable every Application Security feature the labs use:

You do not need the Zero Trust Premier Bundle, Magic Transit, Magic WAN, or Email Security for this course.

Virtual machine specifications

Ubuntu 24.04 LTS workstation

The workstation is the box you run every lab command from. It needs no web server; it just needs a full toolbelt and outbound internet.

RequirementValue
Operating systemUbuntu 24.04 LTS (Server or Desktop)
CPU2 vCPU minimum
RAM2 GB minimum
Disk20 GB minimum
Internet accessRequired throughout the class. You browse proxied lab hostnames and run curl/dig/openssl against Cloudflare's edge from here.

Local user account: cloudflare with password #Savetheinternet, member of sudo, with PasswordAuthentication yes enabled in /etc/ssh/sshd_config.

Pre-installed software: curl, dig (dnsutils), openssl, jq, python3, node, docker, git, and nmap.

Ubuntu 24.04 LTS origin servers (Origin A and Origin B)

Build two Ubuntu origins with identical specs and configuration. The only behavioral differences are the identity signals covered below: Origin A reports "origin":"primary" on /status and sets X-Origin: origin-1 on the public-api; Origin B reports "origin":"backup" and sets X-Origin: origin-2. Origin B is the second pool member for the Load Balancer lab.

RequirementValue
Operating systemUbuntu 24.04 LTS (Server)
CPU2 vCPU minimum
RAM2 GB minimum
Disk20 GB minimum
Internet accessRequired. Needed to install nginx and Node, and to pull the AcmeCorp content and public-api at build time. The origin-to-origin isolation the labs assume comes from the no-route-between-subnets topology, not from blocking egress.

Local user account: cloudflare with password #Savetheinternet, member of sudo, with PasswordAuthentication yes enabled in /etc/ssh/sshd_config. Same on both origins.

Pre-installed software: nginx, Node.js (for the public-api), OpenSSH Server, OpenSSL, curl, and dig (dnsutils). Same on both origins.

Services running before class (each origin):

ServicePortPurpose
AcmeCorp website80/tcpnginx serving the static AcmeCorp site. Both origins serve identical content.
/admin80/tcpnginx location protected with HTTP Basic auth (admin / AcmeAdmin123). Returns 401 when unauthenticated. Target for the WAF / Access exercises.
/status80/tcpnginx location returning {"status":"healthy","origin":"primary"} on Origin A and {"status":"healthy","origin":"backup"} on Origin B. The Load Balancer health check matches "status":"healthy" on both pool members; the "origin" field is the visible curl-level signal of which member served the request.
Cache-test assets80/tcpA few static files under a known path so the Caching lab can observe cf-cache-status HIT/MISS behavior.
Node public-api443/tcpA dependency-free Node service over self-signed TLS (use curl -k). Implements the lab API contract (/status, /v1/orders, /order, /api/v1/auth, /api/v1/register, /api/v1/checkout, /api/products, /v1/partners, a shadow endpoint, and a static /openapi.json). Sets X-Origin, a strict CSP, X-Content-Type-Options: nosniff, and a random session-id header.

The simplest build is a single nginx vhost on :80 with location blocks for /, /admin (Basic auth), /status (returns application/json), and the cache-test assets, plus a systemd unit that runs the Node public-api on :443 with a self-signed certificate. curl http://localhost must return the AcmeCorp homepage, curl http://localhost/status the correct JSON for that VM, curl -o /dev/null -w "%{http_code}" http://localhost/admin a 401, and curl -k https://localhost/status the public-api health JSON.

Network architecture

All three VMs must be on separate subnets with no direct route between any pair. All three VMs need outbound internet access. In the labs, all traffic to the origins flows through Cloudflare's edge (the proxied lab hostnames); the origins never talk to each other directly. If the workstation can reach the origins directly across your network, or the origins can reach each other, the labs lose their purpose.

+-------------------------+   +-------------------------+   +-------------------------+
|   Ubuntu workstation    |   |   Origin A (primary)    |   |   Origin B (backup)     |
|   Subnet A              |   |   Subnet B              |   |   Subnet C              |
|   (e.g. 10.90.0.0/24)   |   |   (e.g. 10.91.0.0/24)   |   |   (e.g. 10.92.0.0/24)   |
|   Has internet          |   |   nginx :80 + api :443  |   |   nginx :80 + api :443  |
+-------------------------+   +-------------------------+   +-------------------------+
       NO direct route between any pair. Traffic reaches the origins via Cloudflare.

For the simplest path that matches the lab guides verbatim, use workstation private IP 10.90.0.90, Origin A (primary) private IP 10.91.0.91, and Origin B (backup) private IP 10.92.0.92. If you use different IPs, substitute your actual values wherever the lab guides reference specific IPs.

Cloudflare account: what to request

Tell your Cloudflare account team or partner manager you need:

SubscriptionScopeNotes
Enterprise accountAccountRequired account type. Includes WAF managed rules and custom rules.
Bot ManagementZoneBot score, managed and custom bot rules
API ShieldZoneEndpoint management, schema validation, JWT validation, sequences
Advanced Rate LimitingZoneRate-limit rules keyed on response code and request attributes
Load BalancingAccount/ZonePools, health-check monitors, and steering across the two origins
Advanced Certificate ManagerZoneCustom edge certificates and SSL/TLS controls
Enterprise DNS zoneZoneYour registered domain added on the Enterprise plan

You must own a registered public domain and add it to the account as the Enterprise DNS zone. The labs proxy the AcmeCorp site and public-api through Cloudflare on hostnames like www.yourdomain.com and api.yourdomain.com. The domain name does not matter (a cheap TLD from any registrar works); it must be a real, publicly resolvable domain with its nameservers pointed to Cloudflare on the Enterprise plan.

The account should be provisioned but otherwise clean -- no existing WAF custom rules, rate-limit rules, API Shield operations, load balancers, or bot rules on the lab zone.

Pre-class verification checklist

Run through this a week before class. Fix anything that fails before Day 1.

Virtual machines

Cloudflare account

FAQ

Can I use a cloud provider for the VMs?
Yes. Any platform works: cloud VMs, VMware, Hyper-V, VirtualBox. Just meet the OS version, software requirements, and network isolation.

Can two students share one Cloudflare account?
No. Each student needs their own account and lab zone. Shared zones cause rule conflicts and analytics confusion.

What if I cannot get an Enterprise account in time?
You will not be able to complete the labs. Bot Management, API Shield, Load Balancing, Advanced Rate Limiting, and Advanced Certificate Manager all require Enterprise plus the add-ons. Start the provisioning request as early as possible.

Why is the automated path the recommended path?
Because creating three correctly-isolated VMs with the right firewall rules, local user accounts, web content, the public-api service, and SSH configuration by hand takes a couple of hours and is easy to get wrong. A fresh AWS sandbox account costs a few dollars and the bootstrap script gets you to a verified starting point in under 10 minutes.