Interactive CLI for provisioning and configuring the ibl.ai platform on AWS or GCP (single-server). End-to-end infrastructure with Terraform, full application setup with Ansible. Can also bootstrap existing servers (any cloud or bare metal) without Terraform.
Note: This repository contains the installation and infrastructure provisioning tooling. Access to the ibl.ai Docker images and platform codebase requires a license. To get started, reach out at ibl.ai/contact.
Five steps from zero to a running platform:
# 1. Install (needs Python 3.11+, Terraform on PATH)
git clone git@github.com:iblai/iblai-infra-ops.git && cd iblai-infra-ops
uv sync # AWS only
uv sync --extra gcp # AWS + GCP support
# 2. Verify your cloud credentials have what's needed
uv run iblai infra permissions --check # AWS
uv run iblai infra permissions --provider gcp --check --project <ID> # GCP
# 3. Provision the infrastructure (interactive wizard — pick AWS or GCP)
uv run iblai infra provision
# 4. Install the platform on the new VM (Ansible over SSH)
uv run iblai infra setup <project-name>
# 5. Open the app
# https://learn.<your-domain>Prefer no prompts? Steps 3–4 also run from a .env file — see Non-interactive.
Deploying on Google Cloud? The flow above is identical; read the short GCP guide first for GCP prerequisites (project, APIs, auth) and cert/DNS behavior.
| Requirement | |
|---|---|
| Always | Python 3.11+ · uv (or pip) · Terraform on PATH · a domain you control · GitHub access to the private ibl.ai packages (licensed) |
| AWS | An account with EC2, ELB, S3, ACM, Route53, IAM, STS permissions (iblai infra permissions prints the exact policy) |
| GCP | A project with billing; compute + dns APIs enabled; roles compute.admin, dns.admin, iam.serviceAccountUser; auth via gcloud auth application-default login or a service-account key. AWS S3 is still used for object storage — see the GCP guide |
Installed automatically as Python dependencies: ansible-core (runs the setup), boto3 (AWS SDK), and — with --extra gcp — the Google Cloud SDKs. Terraform is called as a subprocess and must be installed separately.
What setup installs on the target server: Docker Engine + compose, pyenv + Python 3.11.8, AWS CLI v2, and iblai-cli-ops (the platform management CLI — private repository; unauthenticated requests see a 404).
curl -LsSf https://astral.sh/uv/install.sh | sh # install uv if needed
git clone git@github.com:iblai/iblai-infra-ops.git
cd iblai-infra-ops
uv sync --extra gcp # or plain `uv sync` for AWS onlyVerify:
uv run iblai --version
terraform --versionEvery command below can be run as uv run iblai ..., or just iblai ... after source .venv/bin/activate.
Run iblai infra with no arguments for an interactive menu of all commands.
iblai infra permissions [--check] # AWS: IAM policy JSON + dry-run
iblai infra permissions --provider gcp [--check --project <ID>] # GCP: roles + APIs + probeiblai infra provisionThe wizard walks you through, validating as you go:
- Cloud — AWS or GCP
- Credentials — AWS: profile / keys / env vars · GCP: project ID, region/zone, ADC or key file
- Topology — AWS: single-server, multi-server, or call-server (LiveKit) · GCP: single-server
- Project & compute — name, environment, machine/instance type, disk (min 100 GB; a 32 GB-RAM pick prints a heads-up — 64 GB recommended when AI features are on)
- Network & SSH — CIDR, your IP for SSH access (auto-detected), SSH key (generate or provide)
- Domain & certificates — AWS: Route53 + ACM / upload / none · GCP: Cloud DNS + Google-managed cert (validates asynchronously, 10–60 min) / upload / none
- WAF (optional, AWS single-server) — AWS WAFv2 on the ALB; skippable, add later with
iblai infra waf enable - Review — full summary before anything is created
Terraform then runs with live per-resource progress. The results panel shows the VM IP, SSH command, and app URL.
iblai infra setup <name> # a Terraform-provisioned environment (IP/domain/key auto-filled)
iblai infra setup # any existing server (bare metal / other cloud) — prompts for everythingPrompts for: release tag of iblai-prod-images (the one version knob — the matching iblai-cli-ops version is resolved automatically from its pin), tenant platform name (blank = default), enable-AI toggle, optional integrations (SMTP / Stripe / Google SSO / Microsoft SSO — each off unless configured), GitHub PAT, AWS credentials (ECR + S3), OpenAI key (optional), and super admin credentials.
The playbook runs 16 roles in phases:
| Phase | Roles | What it does |
|---|---|---|
| Host setup | docker, awscli, python |
Docker + compose, AWS CLI v2, pyenv + Python 3.11.8 |
| Platform install | ibl_cli_ops, ibl_platform |
Installs the pinned platform packages; configures domain, gateway, defaults |
| Core services | ibl_dm, ibl_edx, ibl_spa |
Data Manager (Django/Postgres/Redis/Celery), Open edX (LMS/CMS/MySQL/Mongo/ES), and the Auth/Mentor/Skills SPAs |
| Finalization | integrations, admin_setup, data_seeding, ibl_tenant_platform |
OAuth/OIDC, edX↔DM sync, super admin, data seeding, optional tenant launch |
| Optional | smtp_config, stripe_config, google_sso_config, microsoft_sso_config |
Each no-ops unless its trigger key is set |
Same Terraform + Ansible, zero prompts. Single-server only.
# Provision — AWS
cp .env.provision.example .env && $EDITOR .env
iblai infra provision-env -f .env
# Provision — GCP (sets PROVIDER=gcp)
cp .env.provision.gcp.example .env && $EDITOR .env
iblai infra provision-env -f .env
# Set up the provisioned VM
cp .env.setup.example .env.setup && $EDITOR .env.setup
iblai infra setup-env <project-name> -f .env.setupFree-standing server (no Terraform): omit the project name and add TARGET_HOST, SSH_PRIVATE_KEY_PATH, BASE_DOMAIN, PROJECT_NAME to .env.setup.
Sample .env files (every key documented inline — copy, edit, run):
| Sample | Used by |
|---|---|
.env.provision.example |
provision-env — fresh AWS single-server |
.env.provision.gcp.example |
provision-env — fresh GCP single-server |
.env.setup.example |
setup-env — platform install on a provisioned or free-standing VM |
.env.example |
launch-env — one-shot AMI launch (AWS) |
Populated .env files are gitignored; secrets are never persisted to state.json — they ride --extra-vars into Ansible at run time only.
iblai infra resetup <name>Points a running environment at a new domain with fresh secrets: prompts for the new base domain, prod-images release tag, and credentials; rotates all secrets, syncs DB passwords, restarts services. No Terraform changes.
iblai infra waf enable [<name>] # AWS single-server only — WAFv2 on the ALB
iblai infra waf enable-env [<name>] -f .env # non-interactive (WAF_ALLOWED_IPS)
iblai infra waf disable <name> [--yes]
iblai infra waf status [<name>]One-shot Terraform + Ansible from a pre-built AMI:
iblai infra launch-env # .env-driven (cp .env.example .env first)
iblai infra launch \ # fully flag-driven
--ami-id $AMI_ID --domain $DOMAIN --hosted-zone-id $HOSTED_ZONE_ID \
--aws-key-id $AWS_ACCESS_KEY_ID --aws-secret-key $AWS_SECRET_ACCESS_KEY \
--ssh-public-key "$SSH_PUBLIC_KEY" --ssh-key $SSH_KEY_PATH \
--git-token $GIT_TOKEN --vpn-ip $VPN_IP \
--admin-email $ADMIN_EMAIL --admin-password $ADMIN_PASSWORDSee iblai infra launch --help for all options (instance type, --platform-name, SMTP/Stripe/SSO, --enable-ai, ...).
Update container images and restart services — no provisioning, no secret rotation:
iblai infra service-update --host <ip> --ssh-key ~/.ssh/key.pem --git-token $GIT_TOKENOr launch a fresh AMI and swap it into an ALB target group — see iblai infra service-update --help.
iblai infra list # all environments (cloud, type, status)
iblai infra status <name> # details + outputs for one
iblai infra auth # switch AWS credentials
iblai infra destroy <name> # tear everything downThe CLI never silently auto-detects credentials — you always choose, interactively on first use, and the session is reused across commands.
AWS — pick one in the wizard: profiles from ~/.aws/ (type to filter), environment variables, or manual access keys.
GCP — two options; the wizard asks which:
Option A — your Google account (local use):
gcloud auth application-default login # note: `gcloud auth login` alone is NOT enoughOption B — service-account key (CI, or if your org blocks the browser flow above):
PROJECT=<your-project-id>
gcloud iam service-accounts create infra-cli --project=$PROJECT
for R in roles/compute.admin roles/dns.admin roles/iam.serviceAccountUser; do
gcloud projects add-iam-policy-binding $PROJECT \
--member="serviceAccount:infra-cli@$PROJECT.iam.gserviceaccount.com" --role=$R --condition=None
done
gcloud iam service-accounts keys create ~/infra-cli-key.json \
--iam-account="infra-cli@$PROJECT.iam.gserviceaccount.com"Then choose "Service-account key file" in the wizard (or set GCP_CREDENTIALS_FILE=~/infra-cli-key.json in your .env). Keep the key file out of git; delete the service account when done.
AWS (Terraform): VPC with 2 public subnets · EC2 (Ubuntu 22.04, encrypted EBS) · Application Load Balancer (TLS 1.2/1.3) · ACM certificates (DNS-validated, auto-renewed) · security groups (SSH restricted to your IP) · 3 S3 buckets (backups, media, static) · Route53 A-records for all subdomains · optional WAFv2.
GCP (Terraform): VPC + regional subnet · Compute Engine VM (Ubuntu 22.04) · global external Application Load Balancer with a static IP · Google-managed SSL certificate (all subdomains, async validation) · firewall rules (SSH restricted to your IP, health-check ranges) · Cloud DNS A-records. Object storage stays on AWS S3 — details in the GCP guide.
Platform services (Ansible): Open edX (LMS/CMS + MySQL/Redis/MongoDB/Elasticsearch/Forum) · Data Manager (Django/ASGI/Celery + PostgreSQL 16/Redis/Flowise) · Auth/Mentor/Skills SPAs · monitoring (Prometheus/Grafana) · nginx reverse proxy.
Terraform state, generated SSH keys, and project configuration live at ~/.iblai-infra/projects/<project-name>/.
uv sync --extra dev --extra gcp
uv run pytest tests/ -v # 749 tests, ~2s
uv run pytest tests/ --cov=iblai_infra --cov-report=term-missingiblai-infra-ops/
├── src/iblai_infra/
│ ├── cli.py # Typer CLI commands
│ ├── app.py # Provision wizard orchestrator
│ ├── models.py # Pydantic models (the wizard ↔ Terraform contract)
│ ├── env_provision.py # .env → InfraConfig (provision-env, AWS)
│ ├── gcp_env_provision.py # .env → InfraConfig (provision-env, GCP)
│ ├── env_setup.py # .env → SetupConfig (setup-env)
│ ├── prompts/ # Interactive questionary prompts
│ ├── providers/ # aws.py + gcp.py — cloud SDK helpers
│ ├── features/ # Post-provision toggles (waf.py)
│ ├── terraform/ # Runner + templates
│ │ └── templates/
│ │ ├── aws/ # single-server (+ waf.tf), multi-server, call-server
│ │ └── gcp/ # single-server
│ └── ansible/ # Runner + playbooks + 16 roles
├── docs/ # GCP guide, development notes
├── tests/ # 749 tests
└── pyproject.toml
Released under the MIT License.
