Terraform Provider
The Terraform provider for coreX Manager lets you manage coreX Platform resources as Terraform infrastructure-as-code. It covers HAProxy routing, SSL/TLS, security lists, security rules, WAF, traffic management, observability, MCP gateway, risk scoring, and HA configuration — everything exposed by the coreX REST API (/api/v1) that represents declarative desired state.
Why Use Terraform with coreX?
| Approach | Best for |
|---|---|
| Terraform | Version-controlled config, CI/CD pipelines, multi-environment promotion, drift detection, team collaboration |
| Web UI | Exploratory changes, one-off configuration, visual debugging |
| REST API | Scripts, automation, integration with existing tooling |
Terraform is ideal when you want your coreX configuration to live alongside your other infrastructure code (cloud resources, DNS, Kubernetes manifests) in a single versioned repository. Every terraform apply produces an audit trail via coreX’s audit system, and terraform plan shows exactly what will change before you commit.
Installation
From source
git clone https://github.com/ne4u/terraform-provider-corex.git
cd terraform-provider-corex
make install
This builds the provider and installs it to ~/.terraform.d/plugins/registry.terraform.io/ne4u/corex/dev/<os>_<arch>/.
Local development overrides
For local development (using a locally-built provider instead of the registry), add to ~/.terraformrc:
provider_installation {
dev_overrides {
"registry.terraform.io/ne4u/corex" = "~/.terraform.d/plugins/registry.terraform.io/ne4u/corex/dev/darwin_arm64"
}
direct {
exclude = ["registry.terraform.io/ne4u/*"]
}
}
When dev_overrides is active, terraform init will print a warning and the provider won’t be downloaded from the registry. This is expected — Terraform uses your locally-built binary instead. Remove the override when you want to use the published registry version.
Provider Configuration
terraform {
required_providers {
corex = {
source = "registry.terraform.io/ne4u/corex"
version = "~> 0.1"
}
}
}
provider "corex" {
host = "https://corex.example.com"
username = "admin"
password = var.corex_password
# Skip TLS verification (not recommended for production):
# insecure = true
}
Provider Attributes
| Attribute | Type | Env var | Description |
|---|---|---|---|
host | string | COREX_HOST | Base URL of coreX Manager. Required. |
username | string | COREX_USERNAME | OAuth2 username. Mutually exclusive with token. |
password | string | COREX_PASSWORD | OAuth2 password. Sensitive. |
totp_code | string | COREX_TOTP_CODE | TOTP code if 2FA is enabled. Sensitive. |
token | string | COREX_TOKEN | Pre-issued JWT bearer token. Sensitive. Mutually exclusive with username/password. |
insecure | bool | COREX_INSECURE | Skip TLS verification. Default false. |
Authentication
The provider supports two authentication modes:
Username + password (OAuth2 password flow):
provider "corex" {
host = "https://corex.example.com"
username = "admin"
password = var.corex_password
}
Static token (pre-issued JWT — useful for CI/CD):
provider "corex" {
host = "https://corex.example.com"
token = var.corex_token
}
For CI/CD pipelines, prefer the token method — it avoids storing passwords and supports long-lived service tokens. For 2FA-protected accounts, provide totp_code alongside username/password (note: TOTP codes expire every 30 seconds, so this is only practical for interactive use).
Never hardcode credentials in .tf files. Use environment variables (COREX_HOST, COREX_USERNAME, COREX_PASSWORD, COREX_TOKEN) or a secrets manager (Vault, AWS Secrets Manager, etc.) and pass them as variables.
Auto-Apply Behavior
After every Create/Update/Delete on HAProxy control-plane resources (backends, listeners, WAF rules, security rules, etc.), the provider automatically calls POST /config/apply and polls the async task until completion. This means your changes are immediately active in HAProxy after terraform apply — you don’t need to manually click “Apply Changes” in the UI.
MCP Gateway resources do not trigger config apply — they auto-regenerate the gateway config bundle server-side instead.
Each resource mutation triggers a full HAProxy config apply. If your Terraform run creates 20 resources, that’s 20 sequential applies. For large initial imports, consider using terraform import to adopt existing resources, or structure your Terraform runs to batch related resources together.
Resources
The provider manages 50+ resource types across all coreX Platform feature areas.
Core Routing
| Resource | Description |
|---|---|
corex_backend | Backend pool with servers, health checks, stick tables |
corex_server | Backend server (child of a backend) |
corex_backend_rule | Routing rule from listener to backend |
corex_listener | HAProxy listener (bind address/port, SSL, protocol) |
SSL/TLS
| Resource | Description |
|---|---|
corex_certificate | TLS certificate (ACME issuance or custom upload) |
corex_cipher_suite | Cipher suite configuration |
Security Lists
| Resource | Description |
|---|---|
corex_network_list / corex_network_list_entry | IP/CIDR lists |
corex_asn_list / corex_asn_list_entry | ASN lists |
corex_geo_list / corex_geo_list_entry | GeoIP country lists |
corex_ja4_list / corex_ja4_list_entry | JA4 TLS fingerprint lists |
corex_pattern_list / corex_pattern_list_entry | Pattern lists |
corex_dynamic_feed | Dynamic feed for security lists |
Security Rules & WAF
| Resource | Description |
|---|---|
corex_security_rule | Expression-based security rule |
corex_waf_rule | WAF rule (Coraza/ModSecurity) |
corex_waf_exception | WAF rule exception |
Traffic
| Resource | Description |
|---|---|
corex_rate_limit | Rate limiting rule |
corex_response_header | Response header manipulation |
corex_request_header | Request header manipulation |
corex_redirect | URL redirect |
corex_rewrite | URL rewrite |
corex_response_transform | Response body transformation |
corex_error_page | Custom error page |
corex_fcgi_app | FastCGI application |
Cache
| Resource | Description |
|---|---|
corex_cache_config | Cache configuration (per backend) |
corex_cache_rule | Cache rule (child of cache config) |
Observability
| Resource | Description |
|---|---|
corex_log_destination | Log destination (syslog/file) |
corex_logged_field | Custom logged field |
Management
| Resource | Description |
|---|---|
corex_user | User account |
corex_setting | Generic setting (key-value) |
corex_maxmind_license_key | MaxMind GeoIP license key (singleton) |
Page Protect
| Resource | Description |
|---|---|
corex_page_protect_policy | Page protection policy |
corex_page_protect_script | Page protection script |
corex_page_protect_settings | Page protect global settings (singleton) |
API Armor
| Resource | Description |
|---|---|
corex_api_armor_auth_policy | API authentication policy |
corex_api_armor_api_key_list | API key list |
corex_api_armor_openapi_spec | OpenAPI specification |
corex_api_armor_settings | API Armor global settings (singleton) |
Risk Scoring
| Resource | Description |
|---|---|
corex_risk_ruleset | Risk ruleset |
corex_risk_rule | Risk scoring rule |
High Availability
| Resource | Description |
|---|---|
corex_ha_config | High availability configuration (singleton) |
Singleton Settings
| Resource | Description |
|---|---|
corex_global_options | HAProxy global options (singleton) |
corex_captcha_settings | CAPTCHA settings (singleton) |
corex_captcha_key | CAPTCHA site key |
corex_ssl_labs_settings | SSL Labs scan settings (per certificate) |
MCP Gateway
| Resource | Description |
|---|---|
corex_mcp_team | MCP gateway team |
corex_mcp_team_member | Team membership |
corex_mcp_server | MCP server registration |
corex_mcp_server_replica | MCP server replica |
corex_mcp_identity | MCP identity (PAT/JWT) |
corex_mcp_policy | MCP access policy |
corex_mcp_dlp_rule | DLP rule |
corex_mcp_guardrail | LLM guardrail |
corex_mcp_skill | MCP skill |
corex_mcp_skill_version | MCP skill version (immutable) |
corex_mcp_alert_config | Alert configuration (singleton) |
Data Sources
Data sources let you read coreX Platform state without managing it — useful for wiring outputs into other Terraform resources or for drift detection.
| Data source | Description |
|---|---|
corex_config_status | HAProxy config apply status |
corex_config_preview | Generated HAProxy config text |
corex_config_diff | Diff between applied and pending config |
corex_config_snapshots | Config snapshot history |
corex_backend | Look up a backend by name |
corex_listener | Look up a listener by name |
corex_system_stats | HAProxy process stats |
corex_haproxy_stats | HAProxy frontend/backend metrics |
corex_health | System health |
corex_audit_events | Audit log events |
corex_recent_logs | Recent HAProxy logs |
corex_stick_tables | Stick table summaries |
corex_stick_table | Stick table entries |
corex_valkey_info | Valkey server info |
corex_valkey_namespaces | Valkey keyspace namespaces |
corex_geoip_status | GeoIP database status |
corex_asn_lookup | ASN/GeoIP lookup for an IP |
corex_ssl_labs_scans | SSL Labs scan results |
corex_mcp_gateway_status | MCP gateway status |
corex_mcp_config_status | MCP config bundle status |
corex_mcp_events | MCP gateway events |
corex_mcp_marketplace_search | MCP marketplace search |
Excluded API Endpoints
The following imperative/action endpoints are not managed by Terraform because they don’t represent declarative desired state. Use the coreX API or UI directly:
| Endpoint | Action |
|---|---|
POST /config/revert | Discard pending config changes |
POST /config/snapshots/{id}/rollback | Roll back to a previous config |
POST /cache/{backend_id}/clear | Clear cache |
POST /settings/geoip/download | Trigger GeoIP DB download |
POST /system/export / POST /system/restore | Backup/restore |
POST /mcp/config/regenerate | Regenerate MCP gateway config |
POST /mcp/skills/{id}/publish / POST /mcp/skills/{id}/rollback | Skill publishing |
POST /mcp/skills/import | Import skill from URL |
POST /mcp/servers/{id}/oauth/configure | OAuth setup |
POST /mcp/marketplace/install / POST /mcp/marketplace/uninstall | Marketplace management |
POST /risk-rules/seed-baseline | Seed risk rules |
POST /ha/apply | Apply HA config |
Examples
Backend with Servers and Listener
resource "corex_backend" "web" {
name = "web-pool"
mode = "http"
protocol = "http"
algorithm = "roundrobin"
health_check_enabled = true
health_check_interval = 5000
health_check_uri = "/health"
health_check_method = "GET"
retries = 3
redispatch = true
}
resource "corex_server" "web1" {
backend_id = corex_backend.web.id
name = "web-server-1"
address = "10.0.0.1"
port = 8080
weight = 100
check = true
}
resource "corex_server" "web2" {
backend_id = corex_backend.web.id
name = "web-server-2"
address = "10.0.0.2"
port = 8080
weight = 100
check = true
}
resource "corex_listener" "https" {
name = "https-listener"
bind_address = "0.0.0.0"
bind_port = 443
mode = "http"
protocol = "https"
ssl_enabled = true
http2 = true
default_backend_id = corex_backend.web.id
}
Security Lists
resource "corex_network_list" "blocked_ips" {
name = "blocked-ips"
description = "Known malicious IP addresses"
}
resource "corex_network_list_entry" "bad_ip_1" {
list_id = corex_network_list.blocked_ips.id
value = "10.0.0.0/24"
note = "Internal test range"
}
resource "corex_asn_list" "blocked_asns" {
name = "blocked-asns"
description = "Blocked autonomous systems"
}
resource "corex_asn_list_entry" "bad_asn" {
list_id = corex_asn_list.blocked_asns.id
value = "AS12345"
note = "Abuse provider"
}
resource "corex_geo_list" "blocked_countries" {
name = "blocked-countries"
description = "Blocked countries"
}
resource "corex_geo_list_entry" "blocked_country" {
list_id = corex_geo_list.blocked_countries.id
value = "CN"
note = "Geo-blocking"
}
MCP Gateway
resource "corex_mcp_team" "engineering" {
name = "Engineering"
slug = "engineering"
description = "Engineering team MCP gateway"
}
resource "corex_mcp_server" "github" {
team_id = corex_mcp_team.engineering.id
name = "github-mcp"
display_name = "GitHub MCP Server"
description = "GitHub tools via MCP"
url = "https://mcp.github.example.com/mcp"
enabled = true
verify_tls = true
auth_type = "bearer"
auth_secret = var.github_mcp_token
timeout_ms = 30000
}
resource "corex_mcp_policy" "allow_engineering" {
team_id = corex_mcp_team.engineering.id
name = "allow-engineering-tools"
enabled = true
expression = "team.name == \"engineering\""
action = "allow"
log = true
}
resource "corex_mcp_dlp_rule" "block_secrets" {
team_id = corex_mcp_team.engineering.id
name = "block-aws-keys"
enabled = true
direction = "both"
detector = "aws_key"
action = "block"
}
resource "corex_mcp_guardrail" "jailbreak" {
team_id = corex_mcp_team.engineering.id
name = "jailbreak-protection"
enabled = true
direction = "request"
pack = "builtin:jailbreak_v1"
action = "block"
}
Reading State with Data Sources
# Check if there are unapplied config changes
data "corex_config_status" "current" {}
output "has_pending_changes" {
value = data.corex_config_status.current.has_pending
}
# Get the generated HAProxy config for review
data "corex_config_preview" "current" {}
output "haproxy_config" {
value = data.corex_config_preview.current.config_text
sensitive = true
}
# Look up a backend by name to reference its ID
data "corex_backend" "web" {
name = "web-pool"
}
# Check system health before deploying
data "corex_health" "status" {}
output "system_healthy" {
value = data.corex_health.status.healthy
}
Importing Existing Resources
If you have an existing coreX deployment configured via the UI, you can adopt those resources into Terraform using terraform import:
# Import a backend by its coreX ID
terraform import corex_backend.web 5
# Import a listener
terraform import corex_listener.https 12
# Import a security rule
terraform import corex_security_rule.block_bots 8
After import, run terraform plan — Terraform will show the current state as the desired state. Add the corresponding resource blocks to your .tf files to match, then subsequent plans will show no changes.
For existing deployments, import first, then write resource blocks that match the imported state. This avoids Terraform trying to recreate resources that already exist. Use terraform show after import to see the exact attributes you need to replicate.
CI/CD Integration
For pipeline-based deployments, use a service token and environment variables:
# GitHub Actions example
- name: Terraform Apply
run: terraform apply -auto-approve
env:
COREX_HOST: ${{ secrets.COREX_HOST }}
COREX_TOKEN: ${{ secrets.COREX_TOKEN }}
# main.tf — no credentials in the file
provider "corex" {
# host and token come from COREX_HOST / COREX_TOKEN env vars
}
Each resource mutation triggers a HAProxy config apply. In CI, a large terraform apply will apply the config once per resource change. For initial deployments with many resources, expect the apply to take longer than a typical Terraform run. Subsequent runs with few changes are fast.
Development
The provider is written in Go and uses the Terraform Plugin Framework.
# Build the provider binary
make build
# Run the test suite
make test
# Format and lint
make fmt
make vet
# Install to the local Terraform plugin directory
make install
The source code is available at github.com/ne4u/terraform-provider-corex.
Next Steps
- Listeners & Backends — The resources the provider manages
- Security Rules — Expression-based rules you can define in Terraform
- MCP Gateway — MCP resources available via the provider
- Audit & Snapshots — Every Terraform apply is audited