Skip to content
You are reading dev: the documentation of main. The last release, 0.1.0, predates this site.

OpenTofu modules

Every module under opentofu/, generated by terraform-docs (CI fails when stale), consumed from oci://ghcr.io/do-now-io/socle/opentofu-modules//opentofu/<module>?tag=<socle_version>.

VPC, EKS with no CNI, bootstrap nodes, identities, Crossplane’s role. AWS.

NameVersion
terraform>= 1.13
aws>= 6.0, < 7.0
time>= 0.13, < 1.0

No modules.

NameType
aws_acm_certificate.gatewayresource
aws_acm_certificate_validation.gatewayresource
aws_cloudwatch_log_group.clusterresource
aws_cloudwatch_log_group.flow_logsresource
aws_eip.natresource
aws_eks_cluster.socleresource
aws_eks_node_group.bootstrapresource
aws_eks_pod_identity_association.crossplaneresource
aws_flow_log.socleresource
aws_iam_policy.crossplane_boundaryresource
aws_iam_role.clusterresource
aws_iam_role.crossplaneresource
aws_iam_role.flow_logsresource
aws_iam_role.noderesource
aws_iam_role_policy.crossplaneresource
aws_iam_role_policy.flow_logsresource
aws_iam_role_policy.node_cilium_operatorresource
aws_iam_role_policy.node_ecr_pullresource
aws_iam_role_policy_attachment.clusterresource
aws_iam_role_policy_attachment.noderesource
aws_internet_gateway.socleresource
aws_kms_key.logsresource
aws_kms_key.secretsresource
aws_launch_template.bootstrapresource
aws_nat_gateway.socleresource
aws_route53_record.gateway_certificate_validationresource
aws_route_table.privateresource
aws_route_table.publicresource
aws_route_table_association.privateresource
aws_route_table_association.publicresource
aws_security_group.vpc_endpointsresource
aws_subnet.privateresource
aws_subnet.publicresource
aws_vpc.socleresource
aws_vpc_endpoint.interfaceresource
aws_vpc_endpoint.s3resource
time_sleep.cluster_logs_drainresource
aws_caller_identity.currentdata source
aws_iam_policy_document.cilium_operatordata source
aws_iam_policy_document.node_ecr_pulldata source
aws_region.currentdata source
aws_route53_zone.gatewaydata source
NameDescriptionTypeDefaultRequired
availability_zonesAZs the VPC's public and private subnets are spread across. Every VPC
gets at least one public and one private subnet per AZ — never a flat,
all-public layout — to satisfy ISO 27001 A.8.22 and SOC 2 CC6 network
segregation. There is no all-public escape hatch: the private tier is
structural, whether or not a client's workloads use it.
list(string)n/ayes
cluster_endpoint_public_access_cidrsCIDRs allowed to reach the public EKS API endpoint. Required, no
default: the endpoint is restricted by CIDR rather than left open or
made fully private-only (AWS's own recommended pattern for this case),
and there is no globally correct default to authorize on a client's
behalf.
list(string)n/ayes
cluster_nameName shared by the VPC, the EKS cluster and every resource this module creates around them.stringn/ayes
environmentStamped on every billable resource. Also what the factory's upgrade rings (dev/staging/prod) key off.stringn/ayes
kubernetes_versionEKS control plane version. Required, no default: the module accepts
whatever version it is given rather than enforcing the policy ceiling
itself. The n-1 policy ceiling / n-2 compatibility floor is decided and
bumped by the socle Kargo pipelines, not by this module — a validation
block cannot call the AWS API to know what "current" is, and the
decoupled socle-release/Kubernetes-version pipelines are the actual
owners of that decision.
stringn/ayes
ownerStamped on every billable resource so cost can be attributed and orphans can be found.stringn/ayes
additional_tagsExtra tags merged onto every resource this module creates, on top of owner/environment/socle-version.map(string){}no
bootstrap_node_capacity_typeSPOT by default: the several instance types spread the two nodes over
independent pools, and EKS replaces a node at risk before draining it.
ON_DEMAND for a cluster that must not lose a bootstrap node to a
reclaim, at about two and a half times the price.
string"SPOT"no
bootstrap_node_countHow many bootstrap nodes, spread over the private subnets' AZs. Two by
default: when one is reclaimed or lost the other carries the whole socle
until it is replaced, CoreDNS keeps a replica, and Karpenter's chart
places its two replicas on different nodes in different zones.
One is accepted on a cluster that can live with neither. Nothing scales
this group, so it is one number rather than min, max and desired.
number2no
bootstrap_node_instance_typesInstance types of the bootstrap node group, which carries Cilium's
operator, CoreDNS, Flux and later Karpenter — not the client's
workloads, which Karpenter's nodes carry. Several on Spot, so the nodes
come from independent capacity pools; on demand, the first is used. The
default is six Graviton families of 4 vCPU and 8 to 32 GiB: each one
alone carries the whole socle, Karpenter included, with half its CPU
left, so losing a node to a reclaim is routine. All must share an
architecture, which the AMI follows.
list(string)
[
"t4g.xlarge",
"m7g.xlarge",
"m6g.xlarge",
"c7g.xlarge",
"c6g.xlarge",
"r6g.xlarge"
]
no
cluster_log_typesControl plane log types shipped to CloudWatch Logs. None by default:
ingestion is billed by the gigabyte, and the audit stream records every
request to the API server — one controller writing in a loop made it
about $40 a day on an idle cluster (#80). A client whose audit expects
the API server's record of who did what (ISO 27001 A.8.15, SOC 2 CC7)
turns on at least audit and authenticator; the log group, its retention
and its key exist either way, so the first line is already covered.
list(string)[]no
create_nat_gatewayCreate one NAT Gateway per AZ. One per AZ, never a single shared one, to
avoid cross-AZ data transfer charges — not a toggle for disabling NAT
outright, which the private-subnet decision above rules out. Exists
only for the create_vpc = false case, where the consumer's existing VPC
already manages its own NAT.
booltrueno
create_vpcCreate the VPC, or attach to one the consumer already manages.booltrueno
crossplaneGive the catalog's crossplane module its AWS identity — the one the socle
cannot make for itself: an IAM role, bound through EKS Pod Identity to
crossplane-system/provider-aws, allowed to create roles under
/socle/<cluster_name>/ only, and only carrying the permissions boundary
this module writes. allowed_services is that boundary: the AWS services
(IAM action prefixes, such as route53 or s3) any module's role may be
granted. Empty grants nothing; iam, sts, organizations, account, sso and
identitystore are refused. Which resources of those services a module
reaches is its own role's policy. Null, the default, creates nothing. The
client root passes the boundary's ARN into kube.crossplane.
object({
allowed_services = optional(list(string), [])
})
nullno
force_update_versionForce the control plane version update even if Upgrade Insights reports
blocking findings. Default false: Upgrade Insights is a mandatory
pre-check, never sufficient alone (it only sees the client's own
removed-API usage, over a rolling 30-day audit-log window that both
misses infrequent calls and over-reports fixed ones) — but AWS's own
blocking of update-cluster-version on ERROR findings is currently
rolled back, so this module does not assume AWS enforces the check
either.
boolfalseno
gateway_certificateThe ACM certificate the socle's two Gateways terminate TLS with, at the
load balancer: domain and *.domain, validated by DNS in the public
Route 53 zone named domain — found by name, no zone ID to copy. zone
names that zone instead when domain is a subdomain of it, such as
domain = "sbx.acme.example" in zone = "acme.example". Every route
published through a Gateway — ArgoCD's included — is then
<name>.<domain>. Null, the default, creates nothing, and the bootstrap
module creates no Gateway: the socle never serves a route in clear text.
object({
domain = string
zone = optional(string)
})
nullno
log_retention_daysRetention for the log groups this module creates — the control plane's and the VPC flow logs'. Set explicitly because a log group left to AWS never expires.number90no
private_subnet_idsExisting private subnet IDs, one per AZ in availability_zones. Required when create_vpc is false — this module carves its own subnets out of vpc_cidr only when it also creates the VPC.list(string)[]no
public_subnet_idsExisting public subnet IDs, one per AZ in availability_zones. Required when create_vpc is false — same reasoning as private_subnet_ids.list(string)[]no
secrets_encryption_enabledEnvelope-encrypt Kubernetes Secrets via KMS. On by default: essentially free (~$1/month per key, negligible per-request cost), and standard on Kubernetes 1.28+ already.booltrueno
secrets_encryption_kms_key_arnExisting KMS key for Secrets envelope encryption. Leave unset and the module creates its own key. Ignored when secrets_encryption_enabled is false.stringnullno
vpc_cidrCIDR for the VPC when this module creates it. Arbitrary default (not a research decision) — a /16 large enough for any socle estate.string"10.0.0.0/16"no
vpc_flow_logs_enabledRecord accepted and rejected traffic on the VPC this module creates. On by default, aggregated over ten-minute windows to keep the volume down: it is the only record of who talked to whom, and the segmentation this VPC is built around is unauditable without it.booltrueno
vpc_idExisting VPC to attach to. Required when create_vpc is false, and incoherent to set when create_vpc is true — this module cannot both create a VPC and attach to a different one.stringnullno
NameDescription
bootstrap_node_groupThe bootstrap node group, once its nodes have joined. node_count is what the bootstrap module checks before it installs anything that needs a node; referencing it is also what orders those releases after the group.
cilium_operator_policy_jsonIAM policy the Cilium operator needs in ENI mode — the bootstrap module installs Cilium on this cluster before Flux. The bootstrap nodes' role already carries it; any other node role the operator may be scheduled on needs it too.
cluster_ca_certificateBase64-encoded cluster CA certificate, for building a kubeconfig.
cluster_endpointThe control plane's API endpoint — the access path the socle and its automation use.
cluster_nameName of the EKS cluster.
crossplane_permissions_boundary_arnARN of the permissions boundary every role Crossplane creates must carry — what kube.crossplane.permissions_boundary takes, and what the client root passes for you. Null when crossplane is not set.
crossplane_role_arnARN of the IAM role the catalog's crossplane module's AWS providers run as, through Pod Identity. Null when crossplane is not set.
gateway_certificate_arnARN of the issued ACM certificate the socle's Gateways terminate TLS with — what the bootstrap module's gateway_certificate_arn takes, and what the client root passes for you. Null when gateway_certificate is not set.
helm_kubernetesDrop-in value for the helm provider's kubernetes attribute, so a root configures it in one line. Carries no credential: the exec plugin obtains a short-lived token from the caller's ambient AWS credentials at call time, exactly as the aws provider itself authenticates.
oidc_issuer_urlThe cluster's OIDC issuer. Checklist requirement, not this module's identity mechanism — Pod Identity is, IRSA is absent, and nothing here provisions an OIDC trust relationship against it. Null on an emulated cluster that reports no identity (floci), so an apply there still converges.
private_subnet_idsPrivate subnet IDs, one per AZ.
public_subnet_idsPublic subnet IDs, one per AZ.
regionRegion the cluster and VPC were created in, as resolved from the provider.
service_cidrThe Kubernetes service range EKS chose for this cluster (172.20.0.0/16 or 10.100.0.0/16, by VPC CIDR). The bootstrap module gives CoreDNS its .10 address, the one every node's kubelet is told to use. Null on an emulated cluster that reports none (floci).
tagsThe standard tag set applied to every billable resource this module creates.
vpc_idID of the VPC the cluster is attached to, whether this module created it or not.

A GKE Autopilot cluster in its own network, Crossplane’s bounded grants, the Gateways’ certificates. GCP.

NameVersion
terraform>= 1.13
google>= 8.0, < 9.0

No modules.

NameType
google_bigquery_dataset.billing_exportresource
google_certificate_manager_certificate.gatewayresource
google_certificate_manager_certificate.gateway_regionalresource
google_certificate_manager_certificate_map.gatewayresource
google_certificate_manager_certificate_map_entry.gatewayresource
google_certificate_manager_dns_authorization.gatewayresource
google_certificate_manager_dns_authorization.gateway_regionalresource
google_compute_network.socleresource
google_compute_router.socleresource
google_compute_router_nat.socleresource
google_compute_subnetwork.proxy_onlyresource
google_compute_subnetwork.socleresource
google_container_cluster.socleresource
google_dns_record_set.gateway_certificate_authorizationresource
google_project_iam_custom_role.crossplane_bucketsresource
google_project_iam_custom_role.dns_recordsresource
google_project_iam_member.crossplane_bucketsresource
google_project_iam_member.crossplane_project_grantsresource
google_project_iam_member.observability_readerresource
google_pubsub_topic.upgrade_notificationsresource
google_project.thisdata source
NameDescriptionTypeDefaultRequired
cluster_nameName of the GKE cluster. Also prefixes the network resources the module creates.stringn/ayes
environmentEnvironment this cluster serves. Stamped as a label, and the axis the upgrade ring order follows.stringn/ayes
maintenance_windowWhen GKE may touch this cluster. Required on purpose — a silent default
would mean nobody decided when production gets upgraded, and the day of
the week is what orders a dev/staging/prod ring.

start_time and end_time are RFC3339 timestamps whose difference is the
window length; recurrence is an RFC5545 RRULE. At least 48 hours of
maintenance availability must remain in any 92-day rolling window, and
only contiguous blocks of four hours or more count.
object({
start_time = string
end_time = string
recurrence = string
})
n/ayes
ownerTeam accountable for the cluster. Stamped as a label on every billable resource.stringn/ayes
project_idGoogle Cloud project that holds the cluster and its network.stringn/ayes
regionRegion of the cluster and its subnetwork. The cluster is regional; zonal clusters are not offered.stringn/ayes
additional_labelsExtra labels merged onto the standard set. Cannot override owner, environment or socle-version.map(string){}no
backup_agent_enabledInstall the Backup for GKE agent. Off by default: $9 per protected namespace per month, where Velero covers a Persistent-Disk-backed socle for a third of that.boolfalseno
billing_export_dataset_idWhen set, create a BigQuery dataset to receive the detailed billing export. Linking the billing account to it stays a Console step — Google exposes no API for it.stringnullno
billing_export_dataset_locationLocation of the billing export dataset. Ignored when billing_export_dataset_id is null.string"EU"no
control_plane_dns_allow_external_trafficAllow user traffic to the DNS-based control plane endpoint. True means the control plane is reachable wherever Google Cloud APIs are, gated by IAM; VPC Service Controls is the network boundary and is set outside this module.booltrueno
control_plane_ip_endpoints_enabledExpose the control plane on IP endpoints. Off: the DNS-based endpoint replaces them, and with it the authorized-networks maintenance problem.boolfalseno
cost_allocation_enabledAdd cluster, namespace and workload labels to the detailed billing export. On from day one because it does not backfill.booltrueno
create_natCreate a Cloud Router and Cloud NAT for egress. A cluster with private nodes and no NAT cannot pull an image from outside Google Cloud.booltrueno
create_networkCreate the VPC instead of using an existing one. The common case is a network the consumer already owns.boolfalseno
create_proxy_only_subnetCreate the proxy-only subnetwork. Set to false when another cluster in the same region and VPC already created it — the pool is shared.booltrueno
create_subnetworkCreate the cluster subnetwork. Set to false in a Shared VPC where the network team owns subnets, and supply subnetwork_name and pod_range_name instead.booltrueno
crossplaneGive the catalog's crossplane module its Google Cloud identity — the one
the socle cannot make for itself: grants to the federated principal of
crossplane-system/provider-gcp, no Google service account. allowed_roles
is the boundary: the roles (predefined, or custom by full name) Crossplane
may grant any module's principal on the project or on a bucket, through
Project IAM Admin under a modifiedGrantsByRole condition. Empty grants
nothing but the socle's own DNS records role; owner, editor, viewer,
iam.* and resourcemanager.* are refused, and Google caps the list at
nine. Predefined admin and owner roles (roles/storage.admin,
roles/bigquery.dataOwner, …) are refused too, roles/storage.objectAdmin
excepted: they grant roles on their resources, and Crossplane could give
one to itself. A custom role that carries a setIamPolicy permission must
not be listed, for the same reason. Buckets are reachable under the
<cluster_name>- prefix only, and never deletable. Nothing of Cloud DNS:
external-dns writes records through the socle's DNS records role,
granted on the project. Null, the default, creates nothing.
object({
allowed_roles = optional(list(string), [])
})
nullno
deletion_protectionRefuse to destroy the cluster. On by default; test fixtures turn it off.booltrueno
enable_private_nodesNodes get no external address. Flips the Autopilot default, which is public.booltrueno
enable_upgrade_notificationsCreate a Pub/Sub topic and publish cluster upgrade notifications to it, so automation can react instead of polling.booltrueno
gateway_api_enabledRun GKE's Gateway API controller and let GKE install and upgrade the standard-channel Gateway API CRDs. On by default and stated rather than assumed: the socle installs nothing for Gateway API on GKE because of it, and its templates target GKE's classes. Off leaves the cluster without Gateway API at all.booltrueno
gateway_certificateThe Certificate Manager certificates the socle's two Gateways terminate
TLS with, at the load balancer: every name in domains (wildcards
included, such as ["acme.example", "*.acme.example"]), authorised by DNS
in the Cloud DNS managed zone dns_zone (its name, in this project).
A global certificate in a certificate map serves the public Gateway; a
regional one serves the internal Gateway. Every route published through a
Gateway — ArgoCD's included — is then <name>.<domain>. The zone must
not already hold an _acme-challenge.<domain> record (one another ACME
client left behind): the global authorization writes that name. Null, the
default, creates nothing, and the bootstrap module creates no Gateway: the
socle never serves a route in clear text.
object({
dns_zone = string
domains = list(string)
})
nullno
kubernetes_min_versionFloor for the control plane version. Raise-only escape hatch for promoting a minor deliberately; leave null in steady state and let the channel decide.stringnullno
logging_componentsGKE log sources to send to Cloud Logging. SYSTEM_COMPONENTS cannot be removed; drop WORKLOADS when application logs are collected in-cluster.list(string)
[
"SYSTEM_COMPONENTS",
"WORKLOADS"
]
no
maintenance_exclusionsWindows during which GKE must not upgrade the cluster. The brake, not the routine: empty by default.
list(object({
name = string
start_time = string
end_time = string
scope = string
}))
[]no
monitoring_componentsGKE metric sources. SYSTEM_COMPONENTS is free and mandatory; every other component is billed per sample, so none is defaulted on.list(string)
[
"SYSTEM_COMPONENTS"
]
no
network_nameName of an existing custom-mode VPC to attach the cluster to. Mutually exclusive with create_network.stringnullno
node_range_cidrPrimary range of the cluster subnetwork, used by nodes and by internal load balancers. A /22 carries 1020 nodes, which is what the Pod range allows.string"10.0.0.0/22"no
observability_reader_membersPrincipals granted read-only access to this project's metrics — the central observability cluster's federated identity, never a key.list(string)[]no
pod_range_cidrSecondary range for Pod addresses. Autopilot fixes 32 Pods per node, so a /26 is consumed per node: a /16 carries 1024 nodes. Sized generously on purpose — a cluster's Pod range cannot be changed after creation, while the primary range can be expanded in place.string"10.4.0.0/16"no
pod_range_nameName of the secondary range that carries Pod addresses. Defaults to <cluster_name>-pods, which is what the module creates; set it when attaching to a subnetwork someone else owns.stringnullno
project_numberThe project's number, which every Workload Identity Federation principal names the project by. Null, the default, reads it from the project; set it only where that read cannot happen — the Cloud Billing call the provider makes alongside it is what an emulator lacks.stringnullno
proxy_only_range_cidrRange of the REGIONAL_MANAGED_PROXY subnetwork. Regional Application Load Balancers, and therefore Gateways, cannot exist without it.string"10.8.0.0/23"no
release_channelGKE release channel. REGULAR is Google's recommendation and the estate-wide default; RAPID is outside the GKE SLA and belongs in pre-production only.string"REGULAR"no
subnet_flow_logs_enabledEnable VPC flow logs on the cluster subnetwork, at half sampling over ten-minute windows. Vended network logs are billed at $0.25/GiB, which is a dollar or so a month at that sampling for a socle cluster.booltrueno
subnetwork_nameName of an existing subnetwork in var.region to place the cluster in. Required when create_subnetwork is false, ignored otherwise.stringnullno
NameDescription
billing_export_datasetReference of the BigQuery dataset waiting for the detailed billing export. Null when none was requested. The billing account still has to be linked to it by hand.
cluster_ca_certificateBase64-encoded cluster CA certificate, for building a kubeconfig.
cluster_dns_endpointThe control plane's DNS endpoint — the access path the socle and its automation use. Stable for the life of the cluster and authorised by IAM.
cluster_endpointIP endpoint of the control plane. Empty when IP endpoints are disabled, which is the default.
cluster_locationRegion of the cluster. Regional by default; there is no zonal option.
cluster_nameName of the GKE cluster.
crossplane_principalThe federated principal the catalog's crossplane module's GCP providers run as (crossplane-system/provider-gcp), read off its grants: whatever consumes it is applied after them and destroyed before them. Null when crossplane is not set.
dns_records_roleFull name of the custom role external-dns writes DNS records with: find the project's managed zones, read and change their record sets. Project-level, because a zone's IAM policy is never honoured when granted on the zone itself (measured 2026-10-07), so Crossplane binds it on the project, and --domain-filter bounds what external-dns writes. Always among the roles Crossplane may grant. Built from its ID, so known on the first plan. Empty when crossplane is not set.
gateway_certificate_mapName of the Certificate Manager map the public Gateway's networking.gke.io/certmap annotation takes — what the bootstrap module's gateway_certificate_map takes. Empty when gateway_certificate is not set.
gateway_regional_certificateName of the regional Certificate Manager certificate the internal Gateway's HTTPS listener takes, in its networking.gke.io/cert-manager-certs TLS option — what the bootstrap module's gateway_regional_certificate takes. Empty when gateway_certificate is not set.
helm_kubernetesDrop-in value for the helm provider's kubernetes attribute, so a root configures it in one line. Uses the DNS endpoint, the only one enabled by default, which serves a publicly trusted certificate: no cluster CA is carried (use cluster_ca_certificate with the IP endpoint). Carries no credential: gke-gcloud-auth-plugin obtains a short-lived token from the caller's ambient gcloud credentials at call time.
labelsThe standard label set applied to every billable resource this module creates.
network_nameName of the VPC the cluster is attached to, whether the module created it or not.
oidc_issuer_urlThe cluster's OIDC issuer, for federating an external identity provider against this cluster.
pod_range_nameName of the secondary range carrying Pod addresses.
project_idThe project the cluster lives in — half of every workload's principal, with project_number.
project_numberThe project's number, which a Workload Identity Federation principal names the project by.
proxy_only_subnetwork_nameThe REGIONAL_MANAGED_PROXY subnetwork regional Gateways draw their proxies from. Null when the module did not create it.
regionRegion of the cluster, and of the internal Gateway's regional certificate.
subnetwork_nameName of the cluster's subnetwork.
upgrade_notifications_topicPub/Sub topic carrying GKE upgrade and security bulletin notifications. Null when notifications are disabled.
workload_identity_poolThe Workload Identity Federation pool. Autopilot enforces it, so this is derived rather than configured. Grant IAM roles to principals in this pool to give a catalog workload direct resource access.
workload_identity_principal_prefixPrefix of a workload's IAM principal identifier, naming the project by its number as Workload Identity Federation requires. Append /ns/NAMESPACE/sa/SERVICEACCOUNT. Note that two clusters in one project produce identical principals for the same namespace and service account.

A VNet and an AKS cluster with no CNI. Azure.

NameVersion
terraform>= 1.13
azurerm>= 4.0, < 5.0

No modules.

NameType
azurerm_kubernetes_cluster.socleresource
azurerm_log_analytics_workspace.container_insightsresource
azurerm_monitor_data_collection_rule.prometheusresource
azurerm_monitor_data_collection_rule_association.prometheusresource
azurerm_monitor_workspace.socleresource
azurerm_nat_gateway.socleresource
azurerm_nat_gateway_public_ip_association.socleresource
azurerm_public_ip.natresource
azurerm_resource_group.socleresource
azurerm_subnet.noderesource
azurerm_subnet_nat_gateway_association.noderesource
azurerm_virtual_network.socleresource
NameDescriptionTypeDefaultRequired
cluster_nameName shared by the resource group (when created), the VNet, the AKS cluster and every resource this module creates around them.stringn/ayes
environmentStamped on every billable resource. Also what the factory's upgrade rings (dev/staging/prod) key off.stringn/ayes
kubernetes_versionAKS control plane version. Required, no default: the module accepts whatever version it is given rather than enforcing a version policy itself — that policy is decided and bumped by the socle Kargo pipelines, not by this module.stringn/ayes
locationAzure region for every resource this module creates. Required, no default — there is no globally correct region to pick on a client's behalf.stringn/ayes
maintenance_window_auto_upgradeWindow Kubernetes version auto-upgrades (stable channel) are allowed to run in. At least 4 hours, per AKS's own constraint.
object({
frequency = string
interval = number
duration = number
day_of_week = optional(string)
start_time = optional(string)
utc_offset = optional(string)
})
n/ayes
maintenance_window_node_osWindow node OS security patches are allowed to run in. Separate schedule from maintenance_window_auto_upgrade, so node patching and Kubernetes upgrades never have to share a window.
object({
frequency = string
interval = number
duration = number
day_of_week = optional(string)
start_time = optional(string)
utc_offset = optional(string)
})
n/ayes
ownerStamped on every billable resource so cost can be attributed and orphans can be found.stringn/ayes
resource_group_nameName of the resource group. Used as the name to create when create_resource_group is true, or the name of an existing one to attach to when false.stringn/ayes
additional_tagsExtra tags merged onto every resource this module creates, on top of owner/environment/socle-version.map(string){}no
create_nat_gatewayCreate one NAT Gateway for the VNet's node subnet. Not a toggle for
disabling egress outright — the node subnet has no public IP of its
own, so without this its nodes reach nothing. Exists only for the
create_vnet = false case, where the consumer's existing VNet already
manages its own NAT or an alternate egress path.
booltrueno
create_resource_groupCreate the resource group, or attach to one the consumer already manages.booltrueno
create_vnetCreate the VNet and its node subnet, or attach to a subnet the consumer already manages.booltrueno
dns_service_ipIP address within service_cidr used for cluster service discovery (kube-dns).string"10.1.0.10"no
log_retention_daysRetention for the Container Insights Log Analytics workspace this module creates.number90no
node_subnet_idExisting node subnet ID to attach to. Required when create_vnet is false — this module carves its own subnet out of vnet_cidr only when it also creates the VNet.stringnullno
pod_cidrRange Cilium allocates pod addresses from, as the cluster pool of the
Cilium the bootstrap module installs (docs/architecture/cilium-before-flux.md). Not set on
the cluster: azurerm refuses pod_cidr under network_plugin = "none" (see
cluster.tf), so this module only carries the value to the bootstrap
through its output. Must not overlap the VNet, service_cidr or any
connected network. The default is AKS's own pod range, which the chart's
default (10.0.0.0/8) would not be: that one contains the VNet.
string"10.244.0.0/16"no
service_cidrCIDR for Kubernetes service IPs. Must not overlap the VNet or any connected network, and be smaller than /12 — an AKS constraint independent of the BYO CNI choice below.string"10.1.0.0/16"no
system_node_pool_node_countNode count for the mandatory system node pool. Small and fixed rather than autoscaled: this pool exists to satisfy AKS's structural minimum, not to run workloads.number2no
system_node_pool_vm_sizeVM size for the mandatory system node pool. This is a structural AKS requirement, not a Karpenter/NAP-managed pool — kept small and tainted for-system-only by default (only_critical_addons_enabled), since NAP provisions everything workload-shaped.string"Standard_D2s_v5"no
vnet_cidrCIDR for the VNet — and its single node subnet, which covers the whole range — when this module creates it. Arbitrary default (not a research decision), sized generously since it only ever needs to fit nodes: Cilium's own IPAM owns pod addressing entirely, decoupled from the VNet.string"10.0.0.0/16"no
vnet_nameExisting VNet name to attach to. Required when create_vnet is false, and incoherent to set when create_vnet is true — this module cannot both create a VNet and attach to a different one.stringnullno
zonesAvailability zones the default system node pool spreads across. Azure subnets aren't zone-scoped — zone placement happens on the node pool itself.list(string)
[
"1",
"2",
"3"
]
no
NameDescription
cluster_ca_certificateBase64-encoded cluster CA certificate, for building a kubeconfig.
cluster_endpointThe control plane's private FQDN — the only reachable endpoint, since this module always disables the public one.
cluster_nameName of the AKS cluster.
helm_kubernetesDrop-in value for the helm provider's kubernetes attribute, so a root configures it in one line. Carries no credential: kubelogin obtains a short-lived Entra token from the caller's Azure CLI login at call time; the server ID is AKS's well-known Entra application. PRECONDITION NOT YET MET BY THIS MODULE: the exec only authenticates against a cluster with Entra ID authentication enabled (azure_active_directory_role_based_access_control), which this module does not configure yet — local accounts remain its auth path. Until it is enabled, this output is the shape a root will consume, not a working login (docs/clouds/azure/limits.md).
locationRegion the cluster and its resources were created in.
node_subnet_idID of the node subnet.
oidc_issuer_urlThe cluster's OIDC issuer — what a workload identity federation binding built by the layer above (Crossplane's provider, or anything else) will need.
pod_cidrRange the bootstrap module hands Cilium as its cluster pool. Passed through, never set on the cluster: azurerm refuses pod_cidr under BYO CNI.
resource_group_nameName of the resource group the cluster and its resources live in, whether this module created it or not.
tagsThe standard tag set applied to every billable resource this module creates.
vnet_nameName of the VNet the cluster is attached to, whether this module created it or not.

A private network and a Kapsule cluster. Scaleway.

NameVersion
terraform>= 1.13
scaleway>= 2.82, < 3.0

No modules.

NameType
scaleway_cockpit_token.observabilityresource
scaleway_iam_api_key.crossplaneresource
scaleway_iam_application.crossplaneresource
scaleway_iam_policy.crossplaneresource
scaleway_instance_placement_group.socleresource
scaleway_instance_security_group.socleresource
scaleway_ipam_ip.gatewayresource
scaleway_k8s_acl.socleresource
scaleway_k8s_cluster.socleresource
scaleway_k8s_pool.socleresource
scaleway_vpc.socleresource
scaleway_vpc_gateway_network.socleresource
scaleway_vpc_private_network.socleresource
scaleway_vpc_public_gateway.socleresource
scaleway_vpc_public_gateway_ip.socleresource
NameDescriptionTypeDefaultRequired
cluster_endpoint_public_access_cidrsCIDRs allowed to reach the Kubernetes API server. Required with no default: the control plane cannot be made private on Kapsule, so this list is the only boundary there is, and Kapsule ships 0.0.0.0/0.list(string)n/ayes
cluster_nameName of the Kapsule cluster. Also names the network resources the module creates.stringn/ayes
crossplane_permission_setsPermission sets granted to the in-cluster Crossplane identity, scoped to this Project. Required with no default: what Crossplane may provision is a per-client decision, and a default would either be uselessly narrow or dangerously wide.list(string)n/ayes
environmentEnvironment this cluster serves. Stamped as a tag, decides the default control plane offer, and is the axis the upgrade ring order follows.stringn/ayes
kubernetes_versionKubernetes minor or patch version. Required with no default: Scaleway has no release channel, auto-upgrade covers patches only, and a floating version would let the pipeline lose track of which minor is deployed.stringn/ayes
maintenance_windowWhen patch auto-upgrades may run. Required with no default: a silent default means nobody decided when production gets upgraded, and the window is what orders the upgrade rings across environments.
object({
day = string
start_hour = number
})
n/ayes
ownerTeam accountable for the cluster. Stamped as a tag on every resource that takes tags.stringn/ayes
project_idScaleway Project that holds the cluster and its network. One Project per environment: it is the only boundary Scaleway offers for both IAM and cost attribution.stringn/ayes
additional_tagsExtra tags merged onto the standard set, rendered as key=value. Cannot override owner, environment, cluster or socle-version.map(string){}no
autoscaler_expanderHow the cluster-autoscaler picks which pool to grow. least_waste strands the least capacity; Scaleway's own default is random, which is a coin flip once there is more than one pool.string"least_waste"no
availability_zonesZones the node pools span, one pool per zone. Two is the default because the current instance generation exists in only two zones of fr-par and nl-ams; only pl-waw offers three.list(string)
[
"fr-par-1",
"fr-par-2"
]
no
cockpit_token_enabledCreate a query-only Cockpit token so the central observability cluster can federate Scaleway's own metrics and logs. Reading is what the supervision plane does; pushing into Cockpit is billed per sample and is refused.booltrueno
control_plane_typeControl plane offer. Null derives it from environment — dedicated 4 in production for the SLA and the audit log, mutualized elsewhere. Kosmos offers are absent by decision.stringnullno
create_vpcCreate the VPC instead of attaching to an existing one. Routing is VPC-wide: by default each cluster gets its own VPC; pass an existing one to share it.booltrueno
crossplane_allowed_cidrsSource addresses the Crossplane key may be used from, as an IAM policy condition. Empty derives it from the Public Gateways' egress addresses, which is the only stable source a fully isolated node presents.list(string)[]no
crossplane_key_expires_atRFC 3339 expiry for the Crossplane API key. Null means no expiry. Scaleway has no workload identity federation, so this key is the credential — an expiry is what forces the rotation the factory owns.stringnullno
delete_additional_resourcesOn cluster deletion, also delete the Load Balancers and Block volumes Kubernetes created. False keeps client data when a cluster is torn down, at the price of orphaned billable resources someone has to clean up.boolfalseno
node_typeCommercial type of the pool nodes. COMPUTE3-X is the current generation: dedicated vCPU at 1 vCPU per 2 GiB. BASIC3-X is refused for nodes — shared vCPU and a 99% SLO.string"COMPUTE3-X8C-16G"no
pool_max_sizeMaximum nodes per pool, and therefore per zone.number5no
pool_min_sizeMinimum nodes per pool, and therefore per zone. Billed whether anything schedules on them or not, because the autoscaler never consolidates.number2no
private_network_cidrIPv4 subnet of the cluster's Private Network. Kapsule consumes a /22 per cluster, so anything larger is wasted and anything smaller is refused.string"10.10.0.0/22"no
public_gateway_typeOffer of the Public Gateways that carry node egress. VPC-GW-S handles 100 Mbps, which is ample for image pulls and API calls.string"VPC-GW-S"no
regionScaleway region for the cluster, its network and its pools.string"fr-par"no
root_volume_size_in_gbSystem volume of each node. Scaleway's own guidance is 20 GB minimum and 100 GB to hold images and system logs comfortably.number100no
scale_down_unneeded_timeHow long a node must sit below the utilisation threshold before the autoscaler removes it.string"10m"no
scale_down_utilization_thresholdRequested resources over allocatable capacity, below which a node becomes a scale-down candidate.number0.5no
vpc_idID of an existing VPC to attach the cluster's Private Network to. Mutually exclusive with create_vpc.stringnullno
NameDescription
cluster_ca_certificateBase64-encoded cluster CA certificate, for building a kubeconfig.
cluster_endpointURL of the Kubernetes API server. Always public on Kapsule — a fully private control plane does not exist — and reachable only from cluster_endpoint_public_access_cidrs.
cluster_idID of the Kapsule cluster, in region/uuid form.
cluster_nameName of the Kapsule cluster.
cluster_regionRegion of the cluster. A Kapsule cluster lives in exactly one.
cluster_typeThe control plane offer in force. Derived from environment unless control_plane_type overrides it: production gets a dedicated offer for the SLA and the audit log.
cockpit_token_secretQuery-only Cockpit token for the central observability cluster to federate Scaleway's metrics and logs. Null when cockpit_token_enabled is false.
crossplane_access_keyAccess key of the Crossplane API key. Not secret on its own, but pair it with crossplane_secret_key.
crossplane_application_idID of the IAM application the in-cluster Crossplane provider authenticates as.
crossplane_secret_keySecret key for the in-cluster Crossplane provider. This is a long-lived credential because Scaleway offers no alternative; it is bound to the source addresses in crossplane_allowed_cidrs and expires at crossplane_key_expires_at.
gateway_egress_cidrsPublic addresses the cluster's nodes egress from, one per zone, as /32 CIDRs. This is the estate's stable source address: allow-list it wherever a client needs to admit the cluster.
helm_kubernetesDrop-in value for the helm provider's kubernetes attribute, so a root configures it in one line. Kapsule has no exec credential plugin and accepts the IAM secret key as a bearer token, so the exec emits an ExecCredential from SCW_SECRET_KEY — the variable the scaleway provider already reads — at call time. No token is stored in state.
kubeconfigRaw kubeconfig for the cluster. Sensitive: it carries a bearer token.
oidc_issuer_urlAlways null. Kapsule exposes no OIDC issuer for workload identity, so nothing can federate against this cluster's ServiceAccount tokens.
private_network_idID of the cluster's Private Network.
security_group_idsThe cluster's own node security groups, keyed by zone. Not the shared Kapsule default, which is common to every cluster in the Project. One per zone because an Instance security group is a zoned resource.
tagsThe standard tag set applied to every resource this module creates that accepts tags.
vpc_idID of the VPC the cluster's Private Network sits in, whether the module created it or not.
wildcard_dnsDNS wildcard resolving to every ready node. Useful for reaching a NodePort before an ingress path exists.
workload_identity_poolAlways null. Scaleway has no workload identity federation — the in-cluster provider authenticates with the API key below instead.

What runs before the catalog, then Flux and the inputs. Its kube schema: Inputs.

NameVersion
terraform>= 1.13
aws>= 6.0, < 7.0
helm>= 3.0, < 4.0

No modules.

NameType
aws_eks_addon.ebs_csiresource
aws_eks_addon.efs_csiresource
aws_eks_addon.pod_identity_agentresource
aws_eks_addon.snapshot_controllerresource
aws_iam_role.ebs_csiresource
aws_iam_role.efs_csiresource
aws_iam_role_policy_attachment.ebs_csiresource
aws_iam_role_policy_attachment.efs_csiresource
helm_release.ciliumresource
helm_release.corednsresource
helm_release.instanceresource
helm_release.operatorresource
helm_release.socleresource
helm_release.storage_classresource
aws_caller_identity.currentdata source
NameDescriptionTypeDefaultRequired
cloudWhich cloud this cluster runs on. Selects the artifact's clusters/ overlay and the operator's workload identity wiring. Scaleway has no federation the operator knows, so it runs as a plain kubernetes cluster.stringn/ayes
cluster_nameCluster this socle serves. Stamped on every object the operator creates, and exposed to the catalog as inputs.cluster.name.stringn/ayes
environmentEnvironment this cluster serves. Stamped as a label, exposed as inputs.cluster.environment, and the axis the upgrade rings follow.stringn/ayes
ownerTeam accountable for the cluster. Stamped as a label on every object.stringn/ayes
artifact_pull_secretName of an existing kubernetes.io/dockerconfigjson Secret in flux-system that Flux uses to pull the artifact from a private registry. Empty for a public registry. The Secret is created outside this module — a credential never enters OpenTofu.string""no
artifact_urlOCI repository the socle artifact is pulled from. Override for a mirror; the tag is socle_version.string"oci://ghcr.io/do-now-io/socle/flux-modules"no
ciliumThe socle's Cilium, on the clouds whose foundations create a cluster with
no CNI — aws and azure — as { enabled, hubble, gateway_api }, every key
optional: enabled (true) installs it before Flux; false means the
cluster brings its own CNI and DNS, which only a test double does.
hubble (false) adds Hubble Relay and UI. gateway_api (true) makes
Cilium serve the cilium GatewayClass. values ({}) is any Cilium chart
value, merged over the socle's so the client wins; private keys are
refused there, and the chart's existingSecret fields name a Secret
instead. Refused on gcp and scaleway, where the cloud operates Cilium.
Typed any and validated like kube, so a misspelt key is an error at
plan. Chart versions are pinned in cilium.tf.
any{}no
cluster_networkWhat Cilium needs to know about the cluster, from the foundations'
outputs, never from the client: api_endpoint, the API server as EKS
returns it (https://host) or AKS does (a bare FQDN), for kube-proxy
replacement; service_cidr, the service range, whose .10 is CoreDNS's
address on aws; pod_cidr, Cilium's pool on azure, where the VNet holds
nodes only. Required wherever the socle installs Cilium, ignored
elsewhere.
object({
api_endpoint = string
service_cidr = optional(string)
pod_cidr = optional(string)
})
nullno
corednsThe CoreDNS the socle installs on aws, right after Cilium, as
{ values }: values ({}) is any CoreDNS chart value, merged over the
socle's so the client wins — extra zones, forwarders, plugins. The chart
has no value that takes secret material inline; a Secret is mounted by
name through extraSecrets, or read through env[].valueFrom. Refused
where the socle installs no CoreDNS: every cloud but aws, and aws with
cilium.enabled = false. Chart version pinned in cilium.tf.
any{}no
cosign_identityKeyless identity the artifact's signature must match, as issuer and subject regexes. Defaults to the socle's release workflow on main, so production never consumes a branch build by accident. Override on a dev cluster testing a branch. Null means this default. Verification cannot be disabled.
object({
issuer = string
subject = string
})
{
"issuer": "^https://token\\.actions\\.githubusercontent\\.com$",
"subject": "^https://github\\.com/do-now-io/socle/\\.github/workflows/publish-artifact\\.yaml@refs/heads/main$"
}
no
eks_addonsThe EKS-managed add-ons the socle installs on aws once the nodes run, as
{ pod_identity_agent, ebs_csi, efs_csi, snapshot_controller }, every
key optional:
pod_identity_agent (true) is what hands every Pod Identity association
its credentials — Crossplane's AWS providers included — and flux-operator
waits for it; ebs_csi (true) is the block-storage driver, with its own
role; efs_csi (false) the RWX one, with its own role. Both drivers need
the agent. snapshot_controller (true) is the CSI snapshot controller
and its CRDs, what the velero module's EBS snapshots need. Refused on
every cloud but aws. Versions pinned in eks_addons.tf.
any{}no
flux_componentsFlux controllers to install. The image automation pair is absent by default: the socle's version moves through a reviewed tfvars change, not through a controller rewriting tags.list(string)
[
"source-controller",
"kustomize-controller",
"helm-controller",
"notification-controller"
]
no
flux_versionFlux version the operator installs and keeps converged. 2.x tracks the latest 2 series the operator ships (its embedded distribution, so operator_version bounds it); 2.y.x the latest patch of 2.y; an exact 2.y.z pins it.string"2.x"no
gateway_certificate_arnOn aws, the ACM certificate the shared Gateways' load balancers terminate
TLS with — the foundations' gateway_certificate_arn output, never the
client's. Null or empty on aws means no shared Gateway, and no route
attached to one. Unknown at plan on the apply that issues it, which is
why nothing validates it here. Ignored elsewhere.
stringnullno
gateway_certificate_mapOn gcp, the Certificate Manager map the public shared Gateway's global
load balancer terminates TLS with — the foundations'
gateway_certificate_map output, never the client's. Null or empty on gcp
means no shared Gateway, and no route attached to one. Unknown at plan on
the apply that creates it, which is why nothing validates it here.
Ignored elsewhere.
stringnullno
gateway_regional_certificateOn gcp, the regional Certificate Manager certificate the private shared
Gateway's internal load balancer terminates TLS with — the foundations'
gateway_regional_certificate output, never the client's. Null or empty
on gcp means no shared Gateway either: a private listener without it
would never be programmed. Unknown at plan on the apply that creates it,
which is why nothing validates it here. Ignored elsewhere.
stringnullno
helm_timeout_secondsHow long to wait for each release to become ready. The instance release is the slow one: its health check waits for the operator to converge the controllers.number600no
instance_sizeResource profile the operator applies to the controllers. Empty is the operator's own default; small, medium and large scale requests and limits together.string""no
kubeThe catalog modules this cluster enables and their values, as
{ <module> = { <attribute> = <value> } }. List only what differs from
the catalog's defaults; an absent module is at its default. Module names
are snake_case. Typed any on purpose: a map(any) refuses two modules with
different attributes, and an object type silently drops a misspelt
attribute — the validations below are what makes a typo an error at plan.
The schema is catalog.tf; docs/reference/inputs.md lists it module by module.
any{}no
network_policyLet the operator install network policies isolating the Flux namespace. On by default; Cilium enforces them on every cloud we ship.booltrueno
operator_versionChart version of flux-operator, which is also the operator's own version. Pinned exactly: the operator is pre-1.0 and its minors are not a stable contract.string"0.60.0"no
projectOn gcp, the project the cluster runs in, as { id, number } — the
foundations' project_id and project_number outputs, never the client's.
Exposed to the catalog as inputs.cluster.projectId and projectNumber: a
module's Workload Identity principal names the project number, and the
pool named after the project id. Required on gcp, refused elsewhere.
object({
id = string
number = string
})
nullno
regionRegion the cluster runs in, exposed to the catalog as inputs.cluster.region. Regional cloud APIs need it — on AWS the Pod Identity associations the crossplane module creates. Empty when the caller does not know it; a module that needs it says so.string""no
schedulable_nodesHow many nodes the foundations give the cluster before this module
starts — on aws, the bootstrap node group's size. Everything but Cilium
waits for it: Cilium's DaemonSet is what makes those nodes Ready, so it
is installed beside them, and CoreDNS and the Flux operator, the first
releases that need a scheduled pod, come after. Zero fails the plan with
that reason, instead of Helm waiting helm_timeout_seconds for a node.
Null skips the check, on a cluster whose compute this module cannot see.
numbernullno
socle_versionTag of the socle artifact to pull. Null means this module's own version, so that one bump of the module tag moves module and artifact together. Set it only on a dev cluster testing a branch build, together with cosign_identity.stringnullno
storage_classStorage class for the source-controller's artifact cache. Empty uses the cluster default.string""no
NameDescription
artifactThe socle artifact, as OCI URL and tag.
ciliumWhether this module installed Cilium (aws, azure: the clouds whose foundations create a cluster with no CNI), with the chart versions it pinned. installed is false where the cloud operates Cilium, or when cilium.enabled is false.
cosign_identityKeyless identity the artifact's signature is verified against, on every reconciliation.
eks_addonsThe EKS-managed add-ons this module installed (aws only), each as its pinned version, and for the two storage drivers the ARN of the role their controller runs as. Null for an add-on not installed.
flux_versionFlux version the operator converges the controllers to.
inputsWhat this module ships into the cluster as the ResourceSetInputProvider's defaultValues, after normalisation against the catalog. The catalog's templates read exactly these paths.
namespaceNamespace holding the operator, the Flux controllers and the socle's inputs.
operator_versionVersion of flux-operator installed, which is also its chart version.
socle_versionTag of the socle artifact the cluster pulls.

The AWS root your main.tf calls: foundations and bootstrap in one apply.

NameVersion
terraform>= 1.13
aws>= 6.0, < 7.0
helm>= 3.0, < 4.0
NameSourceVersion
foundations../../awsn/a
socle../../bootstrapn/a

No resources.

NameDescriptionTypeDefaultRequired
awsThe foundations module's inputs, grouped, plus the region for the aws provider. Required keys are the ones the module leaves without a default; every other key is optional and passes through as-is.
object({
region = string
cluster_name = string
owner = string
environment = string
availability_zones = list(string)
cluster_endpoint_public_access_cidrs = list(string)
kubernetes_version = string
additional_tags = optional(map(string))
create_vpc = optional(bool)
vpc_id = optional(string)
private_subnet_ids = optional(list(string))
public_subnet_ids = optional(list(string))
vpc_cidr = optional(string)
create_nat_gateway = optional(bool)
vpc_flow_logs_enabled = optional(bool)
secrets_encryption_enabled = optional(bool)
secrets_encryption_kms_key_arn = optional(string)
cluster_log_types = optional(list(string))
log_retention_days = optional(number)
force_update_version = optional(bool)
bootstrap_node_instance_types = optional(list(string))
bootstrap_node_capacity_type = optional(string)
bootstrap_node_count = optional(number)
crossplane = optional(object({ allowed_services = optional(list(string), []) }))
gateway_certificate = optional(object({ domain = string, zone = optional(string) }))
})
n/ayes
socle_versionThe socle release this cluster runs. In a client's copy this variable is also in both module sources (?tag=), so this one line moves foundations, bootstrap and the artifact together.stringn/ayes
artifact_pull_secretName of an existing dockerconfigjson Secret in flux-system for a private registry. Empty for a public one; the Secret is created outside OpenTofu.string""no
artifact_urlOverride of the OCI repository the artifact is pulled from, for a mirror. Null keeps the socle registry.stringnullno
ciliumThe socle's Cilium, installed before Flux because EKS is created with no CNI: { enabled = true, hubble = false, gateway_api = true, values = {} }, every key optional. values is any Cilium chart value, the client's winning; private keys are refused, name a Secret instead. Validated by the bootstrap module. enabled = false is for a cluster that brings its own CNI and DNS — the e2e test double, never a real EKS.any{}no
corednsThe CoreDNS installed right after Cilium: { values = {} }. values is any CoreDNS chart value, the client's winning. Validated by the bootstrap module.any{}no
cosign_identityOverride of the signature identity the cluster trusts. Null keeps the bootstrap module's default, the release workflow on main. Set it only on a dev cluster testing a branch build.
object({
issuer = string
subject = string
})
nullno
eks_addonsThe EKS-managed add-ons installed once the nodes run: { pod_identity_agent = true, ebs_csi = true, efs_csi = false, snapshot_controller = true }, every key optional. The Pod Identity Agent is what every catalog module's AWS identity, Crossplane's included, gets its credentials from; the two storage drivers need it. The snapshot controller is what the velero module's EBS snapshots need. Versions pinned by the bootstrap module, which validates this.any{}no
kubeCatalog modules and their values, as { = { = } }. Only what differs from the defaults; validated against the catalog by the bootstrap module.any{}no
NameDescription
artifactThe socle artifact this cluster pulls, as URL and tag.
cluster_endpointThe control plane's API endpoint.
cluster_nameName of the EKS cluster.
inputsWhat the catalog renders from, after normalisation. Compare with kubectl -n flux-system get resourcesetinputprovider socle -o yaml.

The GCP root your main.tf calls: foundations and bootstrap in one apply.

NameVersion
terraform>= 1.13
aws>= 6.0, < 7.0
google>= 8.0, < 9.0
helm>= 3.0, < 4.0
NameSourceVersion
foundations../../gcpn/a
socle../../bootstrapn/a

No resources.

NameDescriptionTypeDefaultRequired
gcpThe foundations module's inputs, grouped; project_id and region also configure the google provider. Required keys are the ones the module leaves without a default; every other key is optional and passes through as-is.
object({
project_id = string
region = string
cluster_name = string
owner = string
environment = string
maintenance_window = object({ start_time = string, end_time = string, recurrence = string })
project_number = optional(string)
additional_labels = optional(map(string))
network_name = optional(string)
create_network = optional(bool)
create_subnetwork = optional(bool)
subnetwork_name = optional(string)
pod_range_name = optional(string)
node_range_cidr = optional(string)
pod_range_cidr = optional(string)
proxy_only_range_cidr = optional(string)
create_proxy_only_subnet = optional(bool)
create_nat = optional(bool)
subnet_flow_logs_enabled = optional(bool)
enable_private_nodes = optional(bool)
control_plane_ip_endpoints_enabled = optional(bool)
control_plane_dns_allow_external_traffic = optional(bool)
gateway_api_enabled = optional(bool)
release_channel = optional(string)
maintenance_exclusions = optional(list(object({ name = string, start_time = string, end_time = string, scope = string })))
kubernetes_min_version = optional(string)
enable_upgrade_notifications = optional(bool)
logging_components = optional(list(string))
monitoring_components = optional(list(string))
cost_allocation_enabled = optional(bool)
backup_agent_enabled = optional(bool)
billing_export_dataset_id = optional(string)
billing_export_dataset_location = optional(string)
observability_reader_members = optional(list(string))
deletion_protection = optional(bool)
crossplane = optional(object({ allowed_roles = optional(list(string), []) }))
gateway_certificate = optional(object({ dns_zone = string, domains = list(string) }))
})
n/ayes
socle_versionThe socle release this cluster runs. In a client's copy this variable is also in both module sources (?tag=), so this one line moves foundations, bootstrap and the artifact together.stringn/ayes
artifact_pull_secretName of an existing dockerconfigjson Secret in flux-system for a private registry. Empty for a public one; the Secret is created outside OpenTofu.string""no
artifact_urlOverride of the OCI repository the artifact is pulled from, for a mirror. Null keeps the socle registry.stringnullno
cosign_identityOverride of the signature identity the cluster trusts. Null keeps the bootstrap module's default, the release workflow on main. Set it only on a dev cluster testing a branch build.
object({
issuer = string
subject = string
})
nullno
kubeCatalog modules and their values, as { = { = } }. Only what differs from the defaults; validated against the catalog by the bootstrap module.any{}no
NameDescription
artifactThe socle artifact this cluster pulls, as URL and tag.
cluster_dns_endpointThe control plane's DNS endpoint, the access path the socle and its automation use.
cluster_nameName of the GKE cluster.
inputsWhat the catalog renders from, after normalisation. Compare with kubectl -n flux-system get resourcesetinputprovider socle -o yaml.