Skip to content

GitHub Environment Variables Reference

Each CampusCore client requires a GitHub Environment with the following secrets and variables. The environment name must match the client identifier used in deployment (e.g., vsu_pilot, howard).


Repo-Level Configuration (Set Once)

These are shared across all client environments.

Type Name Description
Secret ADMIN_AWS_ROLE_ARN Our admin account's IAM role ARN (for Terraform state access)
Secret SLACK_BOT_TOKEN Bot User OAuth Token (xoxb-...) for the CampusCore Slack app. Used by every tenant's deploy unless overridden at the env level. See Slack Setup. Leave unset to disable Slack workflow notifications across all envs.
Variable CAMPUSCORE_HOSTED_ZONE_ID Route53 hosted zone ID for campuscoreai.com (Z03938461UVED2L50LENJ)

Environment Variables (Per-Client, Non-Sensitive)

Variable Example Description
AWS_ROLE_ARN arn:aws:iam::123456789012:role/CampusCore-Deploy-Role Client's deploy role ARN (created by client via CloudFormation)
AWS_REGION us-east-1 AWS region for deployment (defaults to us-east-1 if omitted)
TF_STATE_BUCKET campuscore-tfstate-howard S3 bucket for this client's Terraform state
POSTGRES_MAJOR 17 Optional. Pins this client to an older PostgreSQL major; omit to inherit the current default (18). Changing it does not upgrade a running database - see PostgreSQL version upgrades
SSL_MODE managed HTTPS capability gate, defaults to off. off: no subdomain, no certificate, HTTP only. self_managed: provisions {env}.campuscoreai.com + ACM + HTTPS; the client terminates TLS for their own domain. managed: additionally issues and attaches certificates for client domains added in-app (Settings > Custom Domain)
CUSTOM_DOMAIN_WITH_PROTOCOL https://ai.howard.edu Only takes effect when SSL_MODE=off. In any other mode the app job substitutes https://{env}.campuscoreai.com (deploy-aws.yml), and the base layer prefers the subdomain module's output (infrastructure/base/main.tf - effective_custom_domain_with_protocol)

SSO Configuration

SSO providers (SAML, OIDC) are configured via the Django admin panel after deployment — no GitHub Environment variables needed. See Post-Deployment Step 4b.

Observability (Sentry)

All optional except SENTRY_DSN. Workflow defaults apply when a variable is unset. See Sentry Setup for the full operator playbook (creating the Sentry project, picking shared vs per-tenant, Slack/GitHub integration, troubleshooting).

Variable Example Description
SENTRY_ENVIRONMENT vsu-troy-pilot Sentry environment tag for filtering. Defaults to the GitHub Environment name via Terraform fallback if unset.
SENTRY_TRACES_SAMPLE_RATE 0.2 Fraction of transactions sampled for performance tracing. Workflow default: 0.2.
SENTRY_ENABLE_LOGS true Whether to ship logs to Sentry's Logs product. Workflow default: true. Set to false to send only errors + traces.
SENTRY_PROFILES_SAMPLE_RATE 0.0 CPU profiling sample rate. Workflow default: 0.0 (disabled).

RELEASE_SHA is auto-set from ${{ github.sha }} by the deploy workflow — no manual config required.

Notifications (Slack workflow_runs)

All optional. Setting them lights up start/complete/fail messages from the index health check, HNSW rebuild, and scrape pipelines. See Slack Setup for the operator playbook (creating the app, channel, inviting the bot, troubleshooting).

Variable Example Description
SLACK_CHANNEL_WORKFLOW_RUNS C0B4C4Q57HP Channel ID, not name. The Slack channel the bot posts to for this tenant. ⚠ Must be set as a variable, not a secret — the workflow reads ${{ vars.SLACK_CHANNEL_WORKFLOW_RUNS }}. Leaving empty disables Slack posts for this tenant only.

Alerting (CloudWatch alarms)

All optional; consumed by Terraform only - they never enter the container.

Type Name Description
Variable ALERT_EMAIL Email address subscribed to the alarm SNS topic (infrastructure/app/monitoring.tf). It is also the email on the AWS account's SECURITY alternate contact, which is set only when SECURITY_CONTACT_PHONE is set too. Empty means no email subscription and no contact.
Variable SECURITY_CONTACT_PHONE Phone number, in international format, for the AWS account's SECURITY alternate contact - the number AWS uses for abuse reports and vulnerability disclosures. AWS accepts a contact only with both an email and a phone, so this does nothing without ALERT_EMAIL, and the contact is only set where the security posture bundle is on. Empty leaves whatever contact the account already has.
Secret SLACK_ALERT_WEBHOOK_URL Slack incoming-webhook URL for alarm delivery. Empty means no Slack delivery. This is the alarm path, separate from the bot-token path above.

Index Maintenance Scheduling

All optional. The daily EventBridge schedule is on by default, so a deployment that sets neither variable gets automatic index health checks and rebuilds. Set the toggle to false to opt out. See Vector Index Observability.

Variable Example Description
ENABLE_INDEX_MAINTENANCE_SCHEDULE false Set to false to remove the daily EventBridge schedule that runs auto_rebuild_if_justified. Terraform default: true.
INDEX_MAINTENANCE_SCHEDULE_CRON cron(0 6 * * ? *) EventBridge cron expression for the schedule. Terraform default: cron(0 6 * * ? *) (06:00 UTC daily).

Database Sizing & Read Replica

All optional. An unset variable inherits the Terraform default (the value in parentheses), and these are declarative: removing a variable reverts that setting to its default on the next deploy. Deep doc: RDS Configuration.

Variable Example Description
RDS_ALLOCATED_STORAGE 100 Database storage in GB (default 20). Applies at deploy time with no downtime, but a large increase keeps that deploy running - RDS storage optimization can take hours. RDS only grows storage: a smaller value fails the deploy when autoscaling is off, and is ignored when autoscaling is on.
RDS_MAX_ALLOCATED_STORAGE 200 Storage-autoscaling ceiling in GB (default 0 = autoscaling off). Must be greater than RDS_ALLOCATED_STORAGE when set. No downtime.
RDS_INSTANCE_CLASS db.t3.medium Declared database instance class (default db.t3.large). A new environment is created on this class directly. A live database is not resized by the deploy - the deploy warns "class change pending", and an operator applies it with the db-upgrade workflow's Blue/Green run (seconds of switchover, no reboot). See PostgreSQL version upgrades.
RDS_BACKUP_RETENTION_DAYS 7 Automated backup retention in days (default 3, floor 1, max 35). Applies at deploy time with no downtime.
ENABLE_READ_REPLICA true Provision the RDS read replica for agent read traffic (default false). The application wiring (USE_READ_REPLICA, routing) follows automatically. Adds the replica instance's cost to the AWS bill.
REPLICA_INSTANCE_CLASS db.t3.medium Instance class for the read replica (default db.t3.medium). A change reboots only the replica for a few minutes; the primary is unaffected.

Network Resilience

Optional. An unset variable inherits the Terraform default, same as the database knobs above.

Variable Example Description
ENABLE_PER_AZ_NAT true One NAT gateway per availability zone instead of a single shared one (default false), so an AZ failure cannot take down the other AZ's outbound connectivity. Adds ~$37/month per extra AZ to the client's AWS bill. Flip it in a maintenance window: private-subnet egress is interrupted for a few minutes while routes move to the new gateways, and the deploy can fail once when the S3 endpoint update races the old route tables' teardown - re-running the deploy completes the switch.

AWS Security Services

One switch for the whole security posture bundle. Production client environments set it to true - that is a named step of the onboarding checklist, and the onboarding script asks for an explicit decision. Default false, so sandboxes carry none of the cost.

Variable Example Description
ENABLE_FULL_AWS_SECURITY_SERVICES true Provisions GuardDuty (threat detection with S3 Protection, RDS Protection, ECS Fargate Runtime Monitoring, and malware scanning of the upload bucket), AWS Config recording, Security Hub with the AWS Foundational Security Best Practices standard, and Inspector ECR image scanning. Roughly $50-120/month on the client's AWS bill, scaling with usage. The GuardDuty runtime agent runs as a sidecar inside each ECS task's existing CPU/memory allocation. Findings are viewed in the AWS consoles (GuardDuty, Security Hub).

Environment Secrets (Per-Client, Sensitive)

Generated by Us

The secrets section of the onboarding script generates and uploads these (./scripts/onboard-client.sh secrets <env>):

Secret Description
DB_USERNAME RDS PostgreSQL username
DB_PASSWORD RDS PostgreSQL password
DJANGO_SECRET_KEY Django SECRET_KEY for cryptographic signing
APP_FERNET_KEY Fernet key for encrypting connector credentials

Provided by Client

Secret Description
OPENAI_API_KEY OpenAI API key for embeddings and LLM
GEMINI_API_KEY Google Gemini API key for document OCR
COHERE_API_KEY Cohere API key for search reranking

Set by Us (Observability)

Secret Description
SENTRY_DSN Sentry project DSN. Required for Sentry error/trace/log reporting. Leave unset to disable Sentry (the SDK becomes a no-op). See Sentry Setup for how to obtain the value.
SLACK_BOT_TOKEN (optional override) Per-tenant Slack bot token. Defaults to the repo-level SLACK_BOT_TOKEN secret (one bot for all tenants). Set here only when a client requires their own isolated bot identity. See Slack Setup.

Hardcoded Environment Variables (Not Configurable)

These are set directly in the ECS task definition (infrastructure/app/ecs.tf) and do not need GitHub Environment configuration:

Variable Value Purpose
IS_CLOUD_ENV True Gates cloud-only behavior: DB TLS (sslmode=require), HTTPS redirect, HSTS, Secure cookies, JSON logging. Always True in deployed environments, False in local dev.

Triggering a Deployment

Option 1: Push to deploy branch

git push origin main:deploy/howard

Option 2: Manual dispatch

Go to Actions > Deploy to AWS > Run workflow > Enter the client name.

Option 3: GitHub CLI

gh workflow run deploy-aws.yml -f client=howard