Appearance
Deployment: Host, Services & Config
The whole platform runs on one OCI Ampere VM. This page covers what runs where, the services and their config, and how a release reaches the host. For the end-to-end story of how the web app gets from GitHub to a browser, read How the Web App Is Deployed first. The docs site you are reading is deployed separately; see Hosting These Docs.
Deployment diagram
What runs where
| Component | Unit / location | Bind | Notes |
|---|---|---|---|
| Provisioning API | user unit cyberrange-provision-api | 10.115.77.1:5000 | ~/cyberrange/.venv/bin/python provision_api_fastapi.py, WorkingDirectory ~/cyberrange/src/provisioning, EnvironmentFile ~/cyberrange/env/.env, log /tmp/provision-api.log |
| Portal | user unit cyberrange-portal | 10.115.77.1:3000 | next start, Node at ~/opt/node, EnvironmentFile portal/.env.local, log /tmp/portal.log |
| Terminal bridge | user unit cyberrange-ssh-bridge | 10.115.77.1:8765 | virtualenv Python, EnvironmentFile bridge-src/.env.bridge, log /tmp/ssh-bridge.log |
| Cloudflare Tunnel | system unit cloudflared | outbound 443 | token file /etc/cloudflared/token |
| nginx gateway | inside the guacamole container | 10.115.77.12:80 | routes / to portal, /auth/ to Keycloak, /api/ssh-websocket to the bridge |
| Keycloak | keycloak.service inside the guacamole container | 127.0.0.1:8083 | kc.sh start-dev, relative path /auth, EnvironmentFile /etc/keycloak/admin.env |
| Release puller | user unit cyberrange-pull-release.service + .timer | n/a | oneshot, MemoryMax 1G, timer OnBootSec 2min, every 5 min. PATH includes /usr/sbin and /snap/bin so the Wazuh certificate checks can find lxc (pull request 305) |
The user units run as llms_admin; manage them with systemctl --user. See Operations & Troubleshooting for the exact commands.
Configuration files (secrets stay on the host)
| File | Holds | Mode |
|---|---|---|
~/cyberrange/env/.env | API config: PROFILE, capacity values, DEFAULT_TTL_MINUTES, DB_PATH, bind addresses, Keycloak client and introspection, Wazuh users (WAZUH_SCORING_*, WAZUH_PROVISION_*), WAZUH_CA_BUNDLE, BROWSER_SCORE_SECRET, COHORT_FLAG_SECRET, telemetry salt, optional SCORING_DIAGNOSTICS_SCENARIOS and SCORING_DIAGNOSTICS_RETENTION_DAYS | 600 |
~/cyberrange/portal/.env.local | Portal config: Keycloak issuers, NEXTAUTH_SECRET, API_INTERNAL_URL, BROWSER_SCORE_SECRET | 600 |
~/cyberrange/bridge-src/.env.bridge | Bridge config: introspection, client id/secret, PROVISION_API_URL, bind host/port | 600 |
/etc/keycloak/admin.env (in the gateway container) | KEYCLOAK_ADMIN, KEYCLOAK_ADMIN_PASSWORD | root-only |
/etc/cloudflared/token | Cloudflare Tunnel token | mode 600, owned by llms_admin (the unit's user); root:root makes the tunnel fail with "permission denied" |
~/cyberrange/certs/wazuh-api-ca.crt | Public certificate of the Wazuh internal CA, written only by issue_wazuh_internal_ca.py --install after the manager verifies against it; not in the repository | public |
~/cyberrange-data/wazuh-ca/ | The internal CA's and the manager API certificate's private keys | directory 700, keys 600 |
~/cyberrange/secrets/wazuh-builtin-credentials.env | The rotated built-in wazuh and wazuh-wui passwords written by harden_wazuh_api.sh; not used at runtime. Move them to your secret store and delete the file | 600 |
The example templates are cyberrange/env/oci-12gib.env.example and .env.bridge.example. Real values live only on the host and never in the repository.
Config gotchas
COHORT_FLAG_SECRETis required by flag planting but is still not in the env template (D5). Without it, flag planting logsFLAGS_PLANTED_FAIL. For Scenario 1 that is now fatal: the lab is rolled back and never becomesACTIVE(plant_flags_during_provisioninprovision.py). Other scenarios still start, but Scenario 2's capture-the-flag task cannot be completed.- Wazuh
provisioneruser. WithoutWAZUH_PROVISION_USERandWAZUH_PROVISION_PWthe API cannot delete a lab's agents, so a student's second lab is refused withWAZUH_STALE_AGENT. Create the user once per host withdeploy/host/setup_wazuh_provisioner.sh(manual 06, Step 3b). Each release pull warns when the scoring user is set and this pair is not. - Wazuh host hardening is per host, not per release.
issue_wazuh_internal_ca.py --install(internal CA for the manager API),harden_wazuh_api.sh(API bound to loopback, built-in accounts rotated) andsetup_wazuh_provisioner.share run once by an operator. The live-evidence records for the first two (cyberrange/docs/ISSUE-296-tls-monitoring-evidence.md,cyberrange/docs/evidence/WAZUH-API-286-loopback-and-rotation.md) are still marked Pending, so whether a given host has them is Needs Verification. POD_TTL_HOURSis no longer read (lab limits are per scenario since pull request 167); the API logs a warning at startup if it is still set. Remove it fromenv/.env.- User management needs
setup_user_admin_client.shrun once per host (manual 04, Step 9). Without it the API logsADM-USER: user management is NOT configuredat startup and Admin → Users answers 503. - The API unit now runs from
~/cyberrange/.venv(D6 resolved). Releases do not install unit files: after an upgrade, rundeploy/systemd/install-user-units.shonce. - Keycloak realm settings (MFA, theme, password policy) are applied by their own scripts, not by releases. See Login, Sessions & Tokens.
Profiles
The PROFILE env var selects a resource profile (cyberrange/src/provisioning/profiles.py):
| Profile | Concurrent labs | RAM per lab + buffer | Wazuh | Keycloak |
|---|---|---|---|---|
oci_12gib | 1 | 4096 + 1536 MB | manager only | native |
onprem | 3 | 4096 + 2048 MB | full | docker |
The live host runs oci_12gib. What that memory buys per student, and how it adds up on the 12 GiB host, is broken down in Resources per Student.
First deploy and host setup
Standing up the host from scratch (OCI instance, disk, LXD, OVN, golden images, gateway, Keycloak, Wazuh, Cloudflare) is the operator manual's job, not this documentation's. Start at manual/README.md and follow chapters 00 to 08, then the OCI, SSH and Cloudflare guides. The Oracle Cloud (OCI) Setup page summarizes the host and network setup.
Sources
cyberrange/deploy/systemd/*.service, *.timer, cyberrange/deploy/keycloak/keycloak.service, cyberrange/deploy/guacamole/nginx-ampere.conf, cyberrange/deploy/host/pull_release.sh, issue_wazuh_internal_ca.py, harden_wazuh_api.sh, setup_wazuh_provisioner.sh, cyberrange/certs/README.md, cyberrange/env/oci-12gib.env.example, cyberrange/src/provisioning/profiles.py, config.py, provision.py, flag_planting.py, manual/06-scoring.md, manual/README.md.