You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: infrastructure/cloud-compose.mdx
+65-14Lines changed: 65 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -78,17 +78,30 @@ Prefer the module for the provider the caller already selected:
78
78
79
79
| Entry point | Modular source pattern | Infrastructure boundary | Identity and secrets |
80
80
| --- | --- | --- | --- |
81
-
| Google Cloud |`github.com/libops/cloud-compose//providers/gcp?ref=RELEASE_OR_FULL_SHA`| Compute, network, firewall, persistent disks, service accounts, and optional GCP integrations | Can use a consumer-configured Vault GCP IAM role; the operator owns the role, policy, and secret paths |
81
+
| Google Cloud, new deployment |`github.com/libops/cloud-compose//providers/gcp?ref=RELEASE_OR_FULL_SHA`| Compute, network, firewall, persistent disks, service accounts, and optional GCP integrations | Can use a consumer-configured Vault GCP IAM role; the operator owns the role, policy, and secret paths |
82
+
| Google Cloud, 1.x-compatible root |`github.com/libops/cloud-compose?ref=RELEASE_OR_FULL_SHA`| The same GCP boundary while preserving the historical indexed `module.gcp[0]` address | The root accepts only `cloud_provider = "gcp"` and has the same GCP identity boundary |
82
83
| DigitalOcean |`github.com/libops/cloud-compose//providers/do?ref=RELEASE_OR_FULL_SHA`| Droplet, network/firewall inputs, and persistent volumes exposed by the module | Consumer-managed provider token and secret authentication |
83
84
| Linode |`github.com/libops/cloud-compose//providers/linode?ref=RELEASE_OR_FULL_SHA`| Instance, firewall inputs, and persistent volumes exposed by the module | Consumer-managed provider token and secret authentication |
84
85
| Ansible |`ansible/` role from the pinned release | Bootstrap files and packages on an existing Debian or Ubuntu host | The existing-host owner supplies OS access, secrets, network, DNS, firewall, and storage |
85
86
| Salt |`salt/` formula from the pinned release | Bootstrap files and packages on an existing Debian or Ubuntu host | The existing-host owner supplies OS access, secrets, network, DNS, firewall, and storage |
86
87
87
-
Pin the source to the reviewed release or a full commit. The compatibility dispatcher at the repository root remains available, but a new caller should use one provider entrypoint so Terraform does not load unrelated providers. Do not source production infrastructure from a moving branch.
88
+
Pin the source to the reviewed release or a full commit. Since `1.3.0`, each
89
+
entrypoint statically declares only its target provider. The repository root is
90
+
not an all-provider dispatcher: it is a GCP-only compatibility entrypoint for
91
+
existing GCP state and intentionally has no DigitalOcean or Linode dependency.
92
+
New deployments should select one path under `providers/`. Do not source
93
+
production infrastructure from a moving branch.
88
94
89
95
Provider entrypoints should normalize the same runtime object before calling provider-specific resources. A template preset supplies repository, plugin, and package defaults only; an explicit caller value wins. Shared host behavior belongs in provider-neutral runtime modules so Google Cloud, DigitalOcean, Linode, Ansible, and Salt do not grow independent application lifecycles. Each adapter must reject an input it cannot support rather than silently ignore it.
90
96
91
-
Changing an existing deployment from the root dispatcher to a provider module changes module addresses even when the real infrastructure is identical. Preserve the addresses with release-provided `moved` blocks or an explicit, reviewed state migration. Do not let Terraform destroy and recreate a data-bearing host to make the module path look cleaner.
97
+
An existing GCP deployment can remain on the root source at `1.3.0` or later without
98
+
loading unrelated providers or moving `module.gcp[0]`. Moving it to
99
+
`providers/gcp` is an optional, separate state refactor. Existing DigitalOcean
100
+
and Linode callers must adopt their provider-specific source and place the
101
+
release-documented `moved` block in the caller's root module. In every case,
102
+
back up remote state and require a plan with address moves only—no VM, firewall,
103
+
or durable-volume replacement or deletion. Do not recreate a data-bearing host
104
+
merely to make a module path look cleaner.
92
105
93
106
## Pin the complete runtime contract
94
107
@@ -150,9 +163,9 @@ If the selected release does not contain that foundation module, follow its
150
163
release-specific IAM instructions. Do not copy an unpublished foundation
151
164
module from a development branch into an otherwise pinned production stack.
152
165
153
-
<Warning>
154
-
In the [July 13, 2026 release-status snapshot](/infrastructure/current-release-status), PPB `0.5.0`exists as a source/GitHub release but its versioned container is not published. The power-management paragraphs below define the contract a selected release must satisfy; they do not make `0.5.0` a consumable image or make the managed shared-router/private-PPB path available.
155
-
</Warning>
166
+
<Info>
167
+
The [July 17, 2026 release-status snapshot](/infrastructure/current-release-status) records cloud-compose `1.5.0`and the signed PPB `0.5.1` image as released self-hosted dependencies. That does not make the separate managed shared-router/private-PPB integration generally available; its API, edge, and end-to-end promotion gates remain independent.
168
+
</Info>
156
169
157
170
The optional Cloud Run power-management ingress reaches the VM's private
158
171
application port through [Direct VPC
@@ -166,10 +179,20 @@ Terraform identity needs authority to manage host-project and subnet IAM; the
166
179
application Terraform identity needs authority to inspect the selected network
167
180
and manage its per-stack firewall rule.
168
181
182
+
Do not assign the Direct VPC revision to a [Serverless VPC Access connector's
A connector requires its own otherwise-unused `/28`, while Direct VPC
185
+
requires capacity in the selected `/26` or larger application subnet. If an
186
+
unrelated workload still needs a connector, give that connector a separate
187
+
subnet and keep it outside this firewall source range unless it belongs in the
188
+
same trust boundary.
189
+
169
190
The word "ingress" here describes the proxy's application role, not a Direct
170
-
VPC ingress feature. Cloud Run services do not support Direct VPC ingress.
171
-
Public requests enter Cloud Run through its configured service/edge ingress;
172
-
Direct VPC egress is only the private hop from that service to the VM.
191
+
VPC ingress feature. Cloud Run services and jobs do not support Direct VPC
192
+
ingress; worker pools have a separate ingress capability that this architecture
193
+
does not use. Public requests enter Cloud Run through its configured
194
+
service/edge ingress; Direct VPC egress is only the private hop from that
195
+
service to the VM.
173
196
174
197
Cloud-compose configures this Cloud Run attachment with
175
198
`vpc_direct_egress = "PRIVATE_RANGES_ONLY"`. Only requests to private
@@ -199,13 +222,28 @@ the same trust boundary. Leave free capacity for `/28` allocation blocks,
199
222
roughly two addresses per running service instance, and overlapping revision
200
223
retention; an already occupied `/26` is not sufficient.
201
224
225
+
In a Shared VPC, also audit hierarchical firewall policies and every existing
226
+
host-project ingress rule that can reach the VM. The narrow rule owned by one
227
+
cloud-compose application state cannot cancel a broader rule owned elsewhere.
228
+
Record the subnet's other consumers and re-audit them before widening either
229
+
the source range or the application port.
230
+
202
231
A release that provides power management must declare bounded power-on, TCP
203
232
connection, and Cloud Run request budgets. Check the selected release for the
204
233
tested values. The proxy adds no application-level request or response-status
205
234
retry after a connection succeeds; Go may still retry requests it classifies
206
235
as replayable when a pooled connection is found stale. Operators and clients
207
236
must still tolerate occasional connection resets during network maintenance.
208
237
238
+
Cloud-compose `1.5.0` retains the tested direct public PPB path with a 240-second
239
+
power-on budget and a 300-second backend-dial budget inside the 600-second
240
+
Cloud Run request ceiling. Its hosted GCP gate sends one request, verifies the
241
+
VM reaches `RUNNING`, follows a changed ephemeral external address after a
242
+
stop/start, then performs host-level and application checks. Those direct-path
243
+
budgets do not fit behind non-Enterprise Cloudflare's 120-second read limit;
244
+
the managed router uses a separate pre-dispatch retry contract documented in
245
+
[Security and Operations](/platform/security-operations).
246
+
209
247
In releases that expose the hardened power-management contract, enabling it
210
248
requires explicit original-client CIDRs in
211
249
`gcp.network.power_button_allowed_ips`; cloud-compose does not silently trust
@@ -229,12 +267,16 @@ depth zero rather than trust the incoming `X-Forwarded-For` chain. See [Security
229
267
and Operations](/platform/security-operations) for that target managed request
230
268
path.
231
269
232
-
Google recommends an egress-aware startup probe for ordinary Direct VPC
233
-
services. The power-button proxy cannot use application reachability as its
234
-
startup gate because the application VM is intentionally allowed to be off;
270
+
Google warns that a new Direct VPC instance can take a minute or more to
271
+
establish a connection and recommends an egress-aware startup probe with
272
+
retries for ordinary services. The power-button proxy cannot use application
273
+
reachability as its startup gate because the application VM is intentionally
274
+
allowed to be off;
235
275
the proxy has to accept the first request before it can start that VM. Its
236
-
bounded backend dial loop is the retry boundary for this design. A generic
237
-
process-only probe would not prove VPC connectivity.
276
+
bounded backend dial loop is the retry boundary for this design. The selected
277
+
release therefore uses a process-only startup probe to avoid deadlocking the
278
+
wake path. That probe proves only that PPB can accept requests; the hosted
279
+
first-request smoke test is the evidence for Direct VPC connectivity.
238
280
239
281
Cloud Run can retain addresses for up to 20 minutes after a service revision
240
282
scales down. After a service is deleted or moved away, wait one to two hours
@@ -309,6 +351,15 @@ When opting in:
309
351
310
352
When a selected release advertises verified managed artifacts, it must verify downloaded Docker plugins, sitectl packages, rootfs archives, and optional rollout artifacts before atomic installation. Preserve those checks when replacing an installer or adding another managed artifact.
311
353
354
+
Automated Docker cleanup is disabled by default and must remain independent of
355
+
key rotation or application rollout. If an operator enables the dedicated
356
+
cleanup timer, preserve rollback-tagged images: prune old stopped containers,
357
+
unused networks, dangling images, and build cache explicitly, with an age
358
+
filter and a single host lock. Do not restore `docker system prune --all`; it
359
+
can remove the named image retained for a local rollback. The safer policy may
360
+
retain unused named images, so monitor disk use and remove an obsolete named
361
+
release only after its rollback window closes.
362
+
312
363
## Adopting the modular runtime contract
313
364
314
365
Use the `required_version` declared by the exact module source. A release that adopts the modular runtime contract changes power management and privileged internal services from implicit behavior to explicit opt-in. To preserve the earlier GCP behavior, configure the controls exposed by that release before advancing the module ref:
0 commit comments