rcf-lite 0.24.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/blueprints/application-account-settings/docs/topics.md +3 -0
- package/blueprints/application-admin-console/docs/topics.md +3 -0
- package/blueprints/application-api-rest/docs/topics.md +3 -0
- package/blueprints/application-charts/docs/topics.md +3 -0
- package/blueprints/application-dashboard/docs/topics.md +3 -0
- package/blueprints/application-datatable/docs/topics.md +3 -0
- package/blueprints/application-empty-error-states/docs/topics.md +3 -0
- package/blueprints/application-error-handling/docs/topics.md +3 -0
- package/blueprints/application-file-upload/docs/topics.md +3 -0
- package/blueprints/application-forms-wizard/docs/topics.md +3 -0
- package/blueprints/application-notifications-in-app/docs/topics.md +3 -0
- package/blueprints/application-onboarding-tour/docs/topics.md +3 -0
- package/blueprints/application-spa/docs/topics.md +3 -0
- package/blueprints/delivery-ci-workflows/docs/topics.md +3 -0
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +3 -0
- package/blueprints/deploy-hetzner-server/CHANGELOG.md +34 -0
- package/blueprints/deploy-hetzner-server/README.md +202 -0
- package/blueprints/deploy-hetzner-server/blueprint.json +233 -0
- package/blueprints/deploy-hetzner-server/contributions/adrs/adr-3801-deploy-hetzner-server-cloud-host-contract.json +14 -0
- package/blueprints/deploy-hetzner-server/contributions/adrs/adr-3802-deploy-hetzner-server-snapshot-cadence.json +14 -0
- package/blueprints/deploy-hetzner-server/contributions/adrs/adr-3803-deploy-hetzner-server-provisioning-tool.json +20 -0
- package/blueprints/deploy-hetzner-server/contributions/adrs/adr-3804-deploy-hetzner-server-hardening-baseline.json +14 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/cloud-init-render-lint.mjs +64 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/hcloud-dry-run-mock.mjs +116 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/manifest-schema-validate.mjs +180 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/probe-utils.mjs +106 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-cloud-init-hardened.mjs +63 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-snapshot-on-demand.mjs +60 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-throwaway-server-provision.mjs +58 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/run-cloud-init-render-lint.mjs +9 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/run-hcloud-dry-run-mock.mjs +9 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/run-manifest-schema-validate.mjs +9 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/run-real-account-cloud-init-hardened.mjs +9 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/run-real-account-snapshot-on-demand.mjs +9 -0
- package/blueprints/deploy-hetzner-server/contributions/probes/run-real-account-throwaway-server-provision.mjs +9 -0
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-001.json +18 -0
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-002.json +18 -0
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-003.json +18 -0
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-004.json +18 -0
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-005.json +18 -0
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-006.json +18 -0
- package/blueprints/deploy-hetzner-server/contributions/schemas/hetzner-server.schema.json +108 -0
- package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3801-deploy-hetzner-server-provisioner.json +27 -0
- package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3802-deploy-hetzner-server-manifest-schema.json +26 -0
- package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3803-deploy-hetzner-server-cloud-init-template.json +26 -0
- package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3804-deploy-hetzner-server-firewall-shape.json +25 -0
- package/blueprints/deploy-hetzner-server/contributions/templates/cloud-init.yaml.tmpl +93 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37101.json +24 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37102.json +24 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37103.json +25 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37104.json +24 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37105.json +24 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37106.json +25 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37107.json +24 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37108.json +24 -0
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37109.json +24 -0
- package/blueprints/deploy-hetzner-server/docs/topics.md +48 -0
- package/blueprints/deploy-hetzner-server/guide/deploy-hetzner-server.md +180 -0
- package/blueprints/edge-cloudflare-access/docs/topics.md +3 -0
- package/blueprints/edge-cloudflare-rate-limiting/docs/topics.md +3 -0
- package/blueprints/edge-cloudflare-tunnel/CHANGELOG.md +13 -0
- package/blueprints/edge-cloudflare-tunnel/README.md +257 -0
- package/blueprints/edge-cloudflare-tunnel/blueprint.json +168 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/adrs/adr-4001-edge-cloudflare-tunnel-ingress-bridge-contract.json +23 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/adrs/adr-4002-edge-cloudflare-tunnel-connector-runtime.json +19 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/adrs/adr-4003-edge-cloudflare-tunnel-hostname-mode.json +19 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/aud-presence-check.mjs +114 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/cloudflared-config-lint.mjs +80 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/manifest-schema-validate.mjs +234 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/probe-utils.mjs +231 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/real-account-connector-healthy.mjs +54 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/real-account-tunnel-hostname-routes.mjs +73 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-aud-presence-check.mjs +4 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-cloudflared-config-lint.mjs +4 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-manifest-schema-validate.mjs +4 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-real-account-connector-healthy.mjs +4 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/run-real-account-tunnel-hostname-routes.mjs +4 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/probes/tunnel-manifest.schema.json +55 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-001.json +18 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-002.json +18 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-003.json +18 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-004.json +18 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-005.json +18 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4001-edge-cloudflare-tunnel-connector-shape.json +26 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4002-edge-cloudflare-tunnel-manifest-schema.json +26 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4003-edge-cloudflare-tunnel-access-binding.json +25 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39101.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39102.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39103.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39104.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39105.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39106.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39107.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39108.json +24 -0
- package/blueprints/edge-cloudflare-tunnel/docs/topics.md +72 -0
- package/blueprints/edge-cloudflare-tunnel/guide/edge-cloudflare-tunnel.md +204 -0
- package/blueprints/edge-cloudflare-turnstile/docs/topics.md +3 -0
- package/blueprints/email-smtp-resend/docs/topics.md +3 -0
- package/blueprints/jobs-background/docs/topics.md +3 -0
- package/blueprints/messaging-queue-cloudflare/docs/topics.md +3 -0
- package/blueprints/object-storage-s3/docs/topics.md +3 -0
- package/blueprints/observability-essentials/docs/topics.md +3 -0
- package/blueprints/observability-logging/docs/topics.md +3 -0
- package/blueprints/observability-probe-endpoints/docs/topics.md +3 -0
- package/blueprints/persistence-data-d1/docs/topics.md +3 -0
- package/blueprints/persistence-data-postgres/docs/topics.md +3 -0
- package/blueprints/persistence-data-sqlite/docs/topics.md +3 -0
- package/blueprints/platform-cloudflare-cron-triggers/docs/topics.md +3 -0
- package/blueprints/platform-cloudflare-durable-objects/docs/topics.md +3 -0
- package/blueprints/platform-cloudflare-kv/docs/topics.md +3 -0
- package/blueprints/platform-docker-compose-host/CHANGELOG.md +12 -0
- package/blueprints/platform-docker-compose-host/README.md +76 -0
- package/blueprints/platform-docker-compose-host/blueprint.json +209 -0
- package/blueprints/platform-docker-compose-host/contributions/adrs/adr-3901-platform-docker-compose-host-contract.json +14 -0
- package/blueprints/platform-docker-compose-host/contributions/adrs/adr-3902-platform-docker-compose-host-reverse-proxy.json +14 -0
- package/blueprints/platform-docker-compose-host/contributions/adrs/adr-3903-platform-docker-compose-host-reject-coolify.json +14 -0
- package/blueprints/platform-docker-compose-host/contributions/adrs/adr-3904-platform-docker-compose-host-log-driver.json +14 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/caddyfile-validate.mjs +108 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/compose-config-lint.mjs +231 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/probe-utils.mjs +185 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-minimal-stack-up.mjs +41 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-reload-burst.mjs +36 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/run-caddyfile-validate.mjs +5 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/run-compose-config-lint.mjs +5 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/run-real-account-minimal-stack-up.mjs +5 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/run-real-account-reload-burst.mjs +5 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/run-secrets-as-files-scan.mjs +5 -0
- package/blueprints/platform-docker-compose-host/contributions/probes/secrets-as-files-scan.mjs +116 -0
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-001.json +18 -0
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-002.json +18 -0
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-003.json +18 -0
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-004.json +18 -0
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-005.json +18 -0
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-006.json +18 -0
- package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3901-platform-docker-compose-host-compose-layout.json +26 -0
- package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3902-platform-docker-compose-host-secrets-mount.json +26 -0
- package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3903-platform-docker-compose-host-healthcheck-lint.json +26 -0
- package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3904-platform-docker-compose-host-reverse-proxy-artefact.json +26 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38101.json +24 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38102.json +24 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38103.json +24 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38104.json +24 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38105.json +25 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38106.json +24 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38107.json +24 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38108.json +24 -0
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38109.json +24 -0
- package/blueprints/platform-docker-compose-host/docs/topics.md +71 -0
- package/blueprints/platform-docker-compose-host/guide/platform-docker-compose-host.md +94 -0
- package/blueprints/security-auth-clerk/docs/topics.md +3 -0
- package/blueprints/security-auth-keycloak/docs/topics.md +3 -0
- package/blueprints/security-auth-magic-link/docs/topics.md +3 -0
- package/blueprints/security-auth-oauth2/docs/topics.md +3 -0
- package/blueprints/security-secrets-management/docs/topics.md +3 -0
- package/fixtures/canary-manifest.json +9 -9
- package/package.json +1 -1
- package/rcf/adrs/adr-3801-deploy-hetzner-server-cloud-host-contract.json +13 -0
- package/rcf/adrs/adr-3802-deploy-hetzner-server-snapshot-cadence.json +13 -0
- package/rcf/adrs/adr-3803-deploy-hetzner-server-provisioning-tool.json +13 -0
- package/rcf/adrs/adr-3804-deploy-hetzner-server-hardening-baseline.json +13 -0
- package/rcf/adrs/adr-3901-platform-docker-compose-host-contract.json +13 -0
- package/rcf/adrs/adr-3902-platform-docker-compose-host-reverse-proxy.json +13 -0
- package/rcf/adrs/adr-3903-platform-docker-compose-host-reject-coolify.json +13 -0
- package/rcf/adrs/adr-3904-platform-docker-compose-host-log-driver.json +13 -0
- package/rcf/adrs/adr-4001-edge-cloudflare-tunnel-ingress-bridge-contract.json +13 -0
- package/rcf/adrs/adr-4002-edge-cloudflare-tunnel-connector-runtime.json +13 -0
- package/rcf/adrs/adr-4003-edge-cloudflare-tunnel-hostname-mode.json +13 -0
- package/rcf/code-nodes/cn-410.json +20 -0
- package/rcf/code-nodes/cn-440.json +20 -0
- package/rcf/code-nodes/cn-470.json +19 -0
- package/rcf/fbs/fbs-130.json +23 -0
- package/rcf/fbs/fbs-140.json +23 -0
- package/rcf/fbs/fbs-150.json +22 -0
- package/rcf/requirements/req-110.json +58 -0
- package/rcf/requirements/req-111.json +32 -0
- package/rcf/requirements/req-112.json +42 -0
- package/rcf/requirements/req-113.json +33 -0
- package/rcf/requirements/req-114.json +20 -0
- package/rcf/requirements/req-115.json +38 -0
- package/rcf/requirements/req-120.json +20 -0
- package/rcf/requirements/req-121.json +20 -0
- package/rcf/requirements/req-122.json +20 -0
- package/rcf/requirements/req-123.json +42 -0
- package/rcf/requirements/req-124.json +27 -0
- package/rcf/requirements/req-125.json +20 -0
- package/rcf/requirements/req-130.json +32 -0
- package/rcf/requirements/req-131.json +54 -0
- package/rcf/requirements/req-132.json +27 -0
- package/rcf/requirements/req-133.json +20 -0
- package/rcf/requirements/req-134.json +42 -0
- package/rcf/tacs/tac-3801-deploy-hetzner-server-provisioner.json +17 -0
- package/rcf/tacs/tac-3802-deploy-hetzner-server-manifest-schema.json +17 -0
- package/rcf/tacs/tac-3803-deploy-hetzner-server-cloud-init-template.json +17 -0
- package/rcf/tacs/tac-3804-deploy-hetzner-server-firewall-shape.json +16 -0
- package/rcf/tacs/tac-3901-platform-docker-compose-host-compose-layout.json +17 -0
- package/rcf/tacs/tac-3902-platform-docker-compose-host-secrets-mount.json +17 -0
- package/rcf/tacs/tac-3903-platform-docker-compose-host-healthcheck-lint.json +17 -0
- package/rcf/tacs/tac-3904-platform-docker-compose-host-reverse-proxy-artefact.json +17 -0
- package/rcf/tacs/tac-4001-edge-cloudflare-tunnel-connector-shape.json +17 -0
- package/rcf/tacs/tac-4002-edge-cloudflare-tunnel-manifest-schema.json +17 -0
- package/rcf/tacs/tac-4003-edge-cloudflare-tunnel-access-binding.json +16 -0
- package/rcf/test-suites/ts-140.json +86 -0
- package/rcf/test-suites/ts-150.json +86 -0
- package/rcf/test-suites/ts-160.json +78 -0
- package/rcf/user-stories/us-11001.json +23 -0
- package/rcf/user-stories/us-11101.json +23 -0
- package/rcf/user-stories/us-11102.json +24 -0
- package/rcf/user-stories/us-11201.json +23 -0
- package/rcf/user-stories/us-11202.json +23 -0
- package/rcf/user-stories/us-11301.json +24 -0
- package/rcf/user-stories/us-11401.json +23 -0
- package/rcf/user-stories/us-11402.json +23 -0
- package/rcf/user-stories/us-11501.json +23 -0
- package/rcf/user-stories/us-12001.json +23 -0
- package/rcf/user-stories/us-12101.json +23 -0
- package/rcf/user-stories/us-12102.json +23 -0
- package/rcf/user-stories/us-12201.json +23 -0
- package/rcf/user-stories/us-12202.json +24 -0
- package/rcf/user-stories/us-12301.json +23 -0
- package/rcf/user-stories/us-12401.json +23 -0
- package/rcf/user-stories/us-12402.json +23 -0
- package/rcf/user-stories/us-12501.json +23 -0
- package/rcf/user-stories/us-13001.json +23 -0
- package/rcf/user-stories/us-13002.json +23 -0
- package/rcf/user-stories/us-13101.json +23 -0
- package/rcf/user-stories/us-13102.json +23 -0
- package/rcf/user-stories/us-13201.json +23 -0
- package/rcf/user-stories/us-13301.json +23 -0
- package/rcf/user-stories/us-13302.json +23 -0
- package/rcf/user-stories/us-13401.json +23 -0
- package/releases/releases.yaml +11 -1
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Guide: edge-cloudflare-tunnel
|
|
2
|
+
|
|
3
|
+
The edge-cloudflare-tunnel blueprint bridges a service on a `cloudHost`
|
|
4
|
+
or a `containerHost` to the Cloudflare edge through a Cloudflare Tunnel,
|
|
5
|
+
with no public origin ports. This guide walks the shape end to end:
|
|
6
|
+
what the connector looks like, what the manifest looks like, how the
|
|
7
|
+
Access-gated shape composes on top of the public-hostname shape, and
|
|
8
|
+
how the credentials-file discipline stays honest on every reapply.
|
|
9
|
+
|
|
10
|
+
Ratifying spec: `projects/blueprint-library/specs/hetzner-round-7-spec-2026-09-07.md` section 5.3.
|
|
11
|
+
|
|
12
|
+
## When to reach for this blueprint
|
|
13
|
+
|
|
14
|
+
Reach when the applying project needs to expose a service on the public
|
|
15
|
+
internet without opening origin ports on the host and without standing
|
|
16
|
+
up a bespoke reverse proxy in front of the CDN. The tunnel connector
|
|
17
|
+
dials out to the Cloudflare edge and terminates ingress there; the host
|
|
18
|
+
firewall (T-1 deploy-hetzner-server) can stay closed on 80/443 unless a
|
|
19
|
+
reverse proxy is also applied.
|
|
20
|
+
|
|
21
|
+
Do not reach for this blueprint when the applying project runs on
|
|
22
|
+
Cloudflare Workers (`deploy-cloudflare-workers` handles ingress
|
|
23
|
+
directly), when the applying project runs behind a corporate VPN
|
|
24
|
+
(private connectivity has different tools), or when the ingress path
|
|
25
|
+
needs a non-Cloudflare bridge shape (Tailscale Funnel, Fly.io proxy;
|
|
26
|
+
those will mint on operator demand into their own reserved slots).
|
|
27
|
+
|
|
28
|
+
## Connector runtime: when to reach for compose-service vs systemd-unit
|
|
29
|
+
|
|
30
|
+
The connector runtime is elicited via `connector-runtime` per ADR-4002
|
|
31
|
+
with `recommendedDefault: compose-service`.
|
|
32
|
+
|
|
33
|
+
Reach for **compose-service** (the shipped default when `containerHost`
|
|
34
|
+
is applied) when the applying project already runs docker compose on
|
|
35
|
+
the host. The connector ships as another service in the same stack,
|
|
36
|
+
sharing the compose network, the log driver and the restart discipline.
|
|
37
|
+
The T-2 platform-docker-compose-host contract makes this the natural
|
|
38
|
+
home; the connector composes on `containerHost` from T-2.
|
|
39
|
+
|
|
40
|
+
Reach for **systemd-unit** when the host runs bare (only T-1 applied)
|
|
41
|
+
and there is no compose stack to add a service to. The connector runs
|
|
42
|
+
as a systemd unit per the vendor cloudflared as-a-service documented
|
|
43
|
+
systemd unit; the unit file lives at `/etc/systemd/system/cloudflared.service`
|
|
44
|
+
on the host and reads the local configuration file at
|
|
45
|
+
`/etc/cloudflared/<name>.yaml`. Boot ordering plays nicely with journald.
|
|
46
|
+
|
|
47
|
+
The fixture ships both variants under
|
|
48
|
+
`packages/rcf-lite/test/fixtures/hetzner-throwaway-server/cloudflared/{compose-service,systemd-unit}/`
|
|
49
|
+
and both pass `manifest-schema-validate`, `cloudflared-config-lint` and
|
|
50
|
+
`aud-presence-check` on every reviewer boot.
|
|
51
|
+
|
|
52
|
+
## Hostname mode: when to reach for Access-gated vs public-hostname
|
|
53
|
+
|
|
54
|
+
The hostname mode is not elicited. It is DISCOVERED from the applied
|
|
55
|
+
capability set (ADR-4003). When `zeroTrustGate` is applied (i.e.
|
|
56
|
+
edge-cloudflare-access v1.0.0 is applied on the same project), every
|
|
57
|
+
ingress rule attaches `originRequest.access.aud` with the AUD from the
|
|
58
|
+
sidecar. When `zeroTrustGate` is not applied, the block is omitted and
|
|
59
|
+
the tunnel serves in public-hostname mode.
|
|
60
|
+
|
|
61
|
+
Reach for **access-gated** when the service behind the tunnel needs an
|
|
62
|
+
authentication gate at the edge (any request without a valid Access
|
|
63
|
+
JWT is refused before it hits the origin). The Access side of the
|
|
64
|
+
composition is owned by edge-cloudflare-access; edge-cloudflare-tunnel
|
|
65
|
+
only reads the sidecar and attaches the AUD block. See the vendor
|
|
66
|
+
self-hosted-public-app documentation for the full AUD binding shape.
|
|
67
|
+
|
|
68
|
+
Reach for **public-hostname** when the service is deliberately public
|
|
69
|
+
(a marketing page, a documentation site, or a public API where
|
|
70
|
+
authorisation lives at the origin). The tunnel still terminates
|
|
71
|
+
ingress at the CF edge; no origin port is opened; the difference is
|
|
72
|
+
that cloudflared does not check for a JWT before forwarding.
|
|
73
|
+
|
|
74
|
+
Graceful degrade: when Access is not applied, the blueprint still ships
|
|
75
|
+
in public-hostname mode. The `aud-presence-check` probe runs on both
|
|
76
|
+
fixture variants and asserts the shape flips correctly.
|
|
77
|
+
|
|
78
|
+
## Tunnel manifest walkthrough
|
|
79
|
+
|
|
80
|
+
The applying project ships one tunnel manifest per named tunnel at
|
|
81
|
+
`cloudflare/tunnels/<name>.yaml`. A minimal public-hostname manifest:
|
|
82
|
+
|
|
83
|
+
```yaml
|
|
84
|
+
tunnel: 12345678-90ab-4cde-8f12-3456789abcde
|
|
85
|
+
credentialsFile:
|
|
86
|
+
secretRef: hq-estate/CLOUDFLARE_TUNNEL_CREDENTIALS_MY_PROJECT
|
|
87
|
+
ingress:
|
|
88
|
+
- hostname: my-app.example.com
|
|
89
|
+
service: http://web:8080
|
|
90
|
+
- service: http_status:404
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
An access-gated manifest adds one `originRequest.access` block per
|
|
94
|
+
non-catch-all rule:
|
|
95
|
+
|
|
96
|
+
```yaml
|
|
97
|
+
tunnel: 12345678-90ab-4cde-8f12-3456789abcde
|
|
98
|
+
credentialsFile:
|
|
99
|
+
secretRef: hq-estate/CLOUDFLARE_TUNNEL_CREDENTIALS_MY_PROJECT
|
|
100
|
+
ingress:
|
|
101
|
+
- hostname: my-app.example.com
|
|
102
|
+
service: http://web:8080
|
|
103
|
+
originRequest:
|
|
104
|
+
access:
|
|
105
|
+
aud: AUD-example-team
|
|
106
|
+
teamName: my-team
|
|
107
|
+
required: true
|
|
108
|
+
- service: http_status:404
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The shipped JSON schema at
|
|
112
|
+
`blueprints/edge-cloudflare-tunnel/contributions/probes/tunnel-manifest.schema.json`
|
|
113
|
+
requires: a uuid-shaped `tunnel` id, a `credentialsFile.secretRef`
|
|
114
|
+
reference (never a literal path or inline JSON body), and an ingress
|
|
115
|
+
rules array whose last entry is a catch-all `service: http_status:404`.
|
|
116
|
+
Every ingress service URL must bind to an internal address (a compose
|
|
117
|
+
service name or a loopback interface); binding to `0.0.0.0` or a
|
|
118
|
+
non-loopback numeric IP refuses at apply time.
|
|
119
|
+
|
|
120
|
+
## Credentials rotation pattern
|
|
121
|
+
|
|
122
|
+
The tunnel credentials JSON file lands on the host at mode 0o400 (owner
|
|
123
|
+
read only) and is referenced from the manifest as a
|
|
124
|
+
`credentialsFile.secretRef`. To rotate:
|
|
125
|
+
|
|
126
|
+
1. Regenerate the credentials via `cloudflared tunnel token <name>` or
|
|
127
|
+
the Cloudflare API against the tunnel id.
|
|
128
|
+
2. Update the secret named by the manifest's `secretRef` via
|
|
129
|
+
`security-secrets-management`.
|
|
130
|
+
3. Trigger a reapply on the applying project; the connector picks up
|
|
131
|
+
the new credentials on its next boot cycle.
|
|
132
|
+
|
|
133
|
+
The credentials file MUST NOT be committed to the applying tree; a
|
|
134
|
+
grep across the working tree for the tunnel id and account tag
|
|
135
|
+
literals refuses on any tracked file. Every `cloudflaredReady`,
|
|
136
|
+
`tunnelConnectorUp` and `ingressRuleReloaded` event body carries
|
|
137
|
+
metadata only; the event-secrecy scan refuses on a body that mentions
|
|
138
|
+
the credentials literal.
|
|
139
|
+
|
|
140
|
+
## Composition on the shelf
|
|
141
|
+
|
|
142
|
+
Consumes: `platform-docker-compose-host` (compose-service runtime),
|
|
143
|
+
`deploy-hetzner-server` (bare cloudHost systemd runtime),
|
|
144
|
+
`security-secrets-management` (credentials secretRef). Optionally
|
|
145
|
+
consumes `edge-cloudflare-access` (the Access-gated shape).
|
|
146
|
+
|
|
147
|
+
Provides: `tunnelBridge` capability; new global topic
|
|
148
|
+
`edgeIngressBridge` (ADR-4001 scope global).
|
|
149
|
+
|
|
150
|
+
The `deliver-ci-workflows` shelf blueprint invokes the two account-bound
|
|
151
|
+
probes on a scratch subdomain when the account tokens are present;
|
|
152
|
+
without them the probes record `accountBoundSkipped: true` and the
|
|
153
|
+
aggregate flips to pass per hetzner-round-7-spec section 3.5.
|
|
154
|
+
|
|
155
|
+
## Running the probes
|
|
156
|
+
|
|
157
|
+
Every reviewer boot exercises the three local probes on the fixture:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
cd packages/rcf-lite/test/fixtures/hetzner-throwaway-server
|
|
161
|
+
node ./run-tunnel-manifest-schema-validate.mjs
|
|
162
|
+
node ./run-cloudflared-config-lint.mjs
|
|
163
|
+
node ./run-aud-presence-check.mjs
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Every probe writes its report envelope to
|
|
167
|
+
`.rcf/reports/blueprints/edge-cloudflare-tunnel/<probe-name>.json`
|
|
168
|
+
under the repo root.
|
|
169
|
+
|
|
170
|
+
Mutations (fixture-side, one per switch; the probe modules never read
|
|
171
|
+
`SIMULATE_` env vars):
|
|
172
|
+
|
|
173
|
+
- `SIMULATE_MANIFEST_INVALID_TUNNEL_ID=true` on `run-tunnel-manifest-schema-validate.mjs`
|
|
174
|
+
- `SIMULATE_MANIFEST_CREDENTIALS_INLINE=true` on `run-tunnel-manifest-schema-validate.mjs`
|
|
175
|
+
- `SIMULATE_MANIFEST_MISSING_CATCHALL=true` on `run-tunnel-manifest-schema-validate.mjs`
|
|
176
|
+
- `SIMULATE_ORIGIN_PORT_OPEN=true` on `run-tunnel-manifest-schema-validate.mjs`
|
|
177
|
+
- `SIMULATE_EVENT_SECRECY_LEAK=true` on `run-tunnel-manifest-schema-validate.mjs`
|
|
178
|
+
- `SIMULATE_INGRESS_INVALID=true` on `run-cloudflared-config-lint.mjs`
|
|
179
|
+
- `SIMULATE_AUD_DROP=true` on `run-aud-presence-check.mjs`
|
|
180
|
+
|
|
181
|
+
Real-account probes need `CI_HAS_CLOUDFLARE_ACCOUNT=true` and
|
|
182
|
+
`CI_HAS_HETZNER_ACCOUNT=true` (plus `CI_HAS_CLOUDFLARE_ACCESS=true` for
|
|
183
|
+
the gated sub-case per the round-7 Q4 ratification):
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
CI_HAS_CLOUDFLARE_ACCOUNT=true CI_HAS_HETZNER_ACCOUNT=true \
|
|
187
|
+
node ./run-real-account-connector-healthy.mjs
|
|
188
|
+
CI_HAS_CLOUDFLARE_ACCOUNT=true CI_HAS_HETZNER_ACCOUNT=true CI_HAS_CLOUDFLARE_ACCESS=true \
|
|
189
|
+
node ./run-real-account-tunnel-hostname-routes.mjs
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Without the env vars the probes record `accountBoundSkipped: true` and
|
|
193
|
+
the aggregate flips to pass.
|
|
194
|
+
|
|
195
|
+
## Standards trace
|
|
196
|
+
|
|
197
|
+
- Cloudflare Tunnel overview: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/
|
|
198
|
+
- Get-started with Tunnel: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/get-started/
|
|
199
|
+
- cloudflared downloads: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/
|
|
200
|
+
- Routing to a tunnel: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/routing-to-tunnel/
|
|
201
|
+
- Local configuration file: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/configuration-file/
|
|
202
|
+
- cloudflared as-a-service: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/install-and-setup/tunnel-guide/local/as-a-service/
|
|
203
|
+
- Self-hosted app in front of a tunnel (Access): https://developers.cloudflare.com/cloudflare-one/applications/configure-apps/self-hosted-public-app/
|
|
204
|
+
- Cloudflare Access policies: https://developers.cloudflare.com/cloudflare-one/policies/access/
|
|
@@ -55,6 +55,9 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
55
55
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
56
56
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
57
57
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
58
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
59
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
60
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
58
61
|
|
|
59
62
|
US 35101-35108 sit at the LOW end of the 35101-35899 band on purpose (watchpost run-4 lesson). ADR/TAC suffixes for this blueprint use the 3601-3699 block, continuing the shelf pattern.
|
|
60
63
|
|
|
@@ -51,6 +51,9 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
51
51
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
52
52
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
53
53
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
54
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
55
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
56
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
54
57
|
|
|
55
58
|
US 4101-4106 sit at the LOW end of the 4101-4899 band on purpose. A project-side story that mechanically derives from an email-smtp-resend REQ id into the number `4106` (leading `4` + sequence `106`) would collide against email-smtp-resend-US-4106 in this package; the band leaves headroom at the HIGH end (US 4181-4899) so a project's own stories anchored to email-smtp-resend REQs can allocate without conflict. The watchpost run4 lesson applies here too.
|
|
56
59
|
|
|
@@ -52,6 +52,9 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
52
52
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
53
53
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
54
54
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
55
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
56
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
57
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
55
58
|
|
|
56
59
|
US 30101-30109 sit at the LOW end of the 30101-30899 band on purpose (watchpost run-4 lesson). A project-side story mechanically derived from a jobs-background REQ id into the number 30110 would collide against a shipped US-30110; band headroom (30110-30899) leaves that space.
|
|
57
60
|
|
|
@@ -52,6 +52,9 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
52
52
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
53
53
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
54
54
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
55
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
56
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
57
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
55
58
|
|
|
56
59
|
US 29101-29108 sit at the LOW end of the 29101-29899 band on purpose (watchpost run-4 lesson). A project-side story mechanically derived from a messaging-queue-cloudflare REQ id into the number 29110 would collide against a shipped US-29110; band headroom (29109-29899) leaves that space.
|
|
57
60
|
|
|
@@ -54,6 +54,9 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
54
54
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
55
55
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
56
56
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
57
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
58
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
59
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
57
60
|
|
|
58
61
|
US 28101-28108 sit at the LOW end of the 28101-28899 band on purpose (watchpost run-4 lesson). A project-side story mechanically derived from an object-storage-s3 REQ id into the number 28110 would collide against a shipped US-28110; band headroom (28109-28899) leaves that space.
|
|
59
62
|
|
|
@@ -70,6 +70,9 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
70
70
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
71
71
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
72
72
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
73
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
74
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
75
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
73
76
|
|
|
74
77
|
US 7101-7110 sit at the LOW end of the 7101-7899 band on purpose. A project-side story that mechanically derives from an observability-essentials REQs id into the number `7110` would collide against observability-essentials-US-7110 in this package; the band leaves headroom at the HIGH end (US 7181-7899) so a project's own stories anchored to observability-essentials REQs can allocate without conflict. The watchpost run4 lesson applies here too.
|
|
75
78
|
|
|
@@ -37,5 +37,8 @@
|
|
|
37
37
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
38
38
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
39
39
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
40
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
41
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
42
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
40
43
|
|
|
41
44
|
The shelf-wide band registry lives in `packages/rcf-lite/docs/blueprint-authoring.md` section 5.
|
|
@@ -60,6 +60,9 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
60
60
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
61
61
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
62
62
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
63
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
64
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
65
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
63
66
|
|
|
64
67
|
US 14101-14108 sit at the LOW end of the 14101-14899 band on purpose. A project-side story that mechanically derives from an observability-probe-endpoints REQ id into the number `14108` would collide against observability-probe-endpoints-US-14108 in this package; the band leaves headroom at the HIGH end (US 14181-14899) so a project's own stories anchored to observability-probe-endpoints REQs can allocate without conflict. The watchpost run4 lesson applies here too. Band spacing between the previous HQ-lane row (persistence-data-d1, 13101-13899, 14xx) and this one (14101-14899, 15xx) reflects the four-digit widening pattern opened by security-auth-clerk at 10xx and continued through the round-2 HQ lane.
|
|
65
68
|
|
|
@@ -58,6 +58,9 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
58
58
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
59
59
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
60
60
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
61
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
62
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
63
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
61
64
|
|
|
62
65
|
US 13101-13107 sit at the LOW end of the 13101-13899 band on purpose. A project-side story that mechanically derives from a persistence-data-d1 REQ id into the number `13107` would collide against persistence-data-d1-US-13107 in this package; the band leaves headroom at the HIGH end (US 13181-13899) so a project's own stories anchored to persistence-data-d1 REQs can allocate without conflict. The watchpost run4 lesson applies here too.
|
|
63
66
|
|
|
@@ -56,6 +56,9 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
56
56
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
57
57
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
58
58
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
59
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
60
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
61
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
59
62
|
|
|
60
63
|
US 27101-27110 sit at the LOW end of the 27101-27899 band on purpose (watchpost run-4 lesson). A project-side story mechanically derived from a persistence-data-postgres REQ id into the number 27110 would collide against the shipped US-27110; band headroom (27111-27899) leaves that space.
|
|
61
64
|
|
|
@@ -58,6 +58,9 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
58
58
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
59
59
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
60
60
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
61
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
62
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
63
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
61
64
|
|
|
62
65
|
US 5101-5111 sit at the LOW end of the 5101-5899 band on purpose. A project-side story that mechanically derives from `persistence-data-sqlite-REQ-011` into the number `5111` would collide against persistence-data-sqlite-US-5111 in this package; the band leaves headroom at the HIGH end (US 5181-5899) so a project's own stories anchored to persistence-data-sqlite REQs can allocate without conflict. The watchpost run4 lesson applies here too.
|
|
63
66
|
|
|
@@ -55,6 +55,9 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
55
55
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
56
56
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
57
57
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
58
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
59
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
60
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
58
61
|
|
|
59
62
|
US 32101-32107 sit at the LOW end of the 32101-32899 band on purpose (watchpost run-4 lesson). A project-side story mechanically derived from a platform-cloudflare-cron-triggers REQ id into the number 32110 would collide against a shipped US-32110; band headroom (32108-32899) leaves that space.
|
|
60
63
|
|
|
@@ -56,6 +56,9 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
56
56
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
57
57
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
58
58
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
59
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
60
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
61
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
59
62
|
|
|
60
63
|
US 33101-33112 sit at the LOW end of the 33101-33899 band on purpose (watchpost run-4 lesson). A project-side story mechanically derived from a platform-cloudflare-durable-objects REQ id into the number 33113 would collide against a shipped US-33113; band headroom (33113-33899) leaves that space.
|
|
61
64
|
|
|
@@ -55,6 +55,9 @@ This table is maintained shelf-wide across every blueprint's `docs/topics.md`. R
|
|
|
55
55
|
| edge-cloudflare-access | 34101-34899 | 35xx | shipped v1.0.0 | `edgeAuthenticationGate` |
|
|
56
56
|
| edge-cloudflare-turnstile | 35101-35899 | 36xx | shipped v1.0.0 | `humanVerificationGate` |
|
|
57
57
|
| edge-cloudflare-rate-limiting | 36101-36899 | 37xx | shipped v1.0.0 | `edgeThrottleContract` |
|
|
58
|
+
| deploy-hetzner-server | 37101-37899 | 38xx | shipped v1.0.0 | `linuxCloudHostContract`, `snapshotAndBackupCadence` |
|
|
59
|
+
| platform-docker-compose-host | 38101-38899 | 39xx | shipped v1.0.0 | `containerHostContract` |
|
|
60
|
+
| edge-cloudflare-tunnel | 39101-39899 | 40xx | shipped v1.0.0 | `edgeIngressBridge` |
|
|
58
61
|
|
|
59
62
|
US 31101-31108 sit at the LOW end of the 31101-31899 band on purpose (watchpost run-4 lesson). A project-side story mechanically derived from a platform-cloudflare-kv REQ id into the number 31110 would collide against a shipped US-31110; band headroom (31109-31899) leaves that space.
|
|
60
63
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# platform-docker-compose-host CHANGELOG
|
|
2
|
+
|
|
3
|
+
## 1.0.0 - 2026-09-08
|
|
4
|
+
|
|
5
|
+
Initial release. Round-7 T-2 of the Hetzner spec at `projects/blueprint-library/specs/hetzner-round-7-spec-2026-09-07.md`.
|
|
6
|
+
|
|
7
|
+
- Mints capability `containerHost` and global topic `containerHostContract`.
|
|
8
|
+
- Six REQs, nine USs, four TACs, four ADRs; five Node-only probes.
|
|
9
|
+
- Extends the shared throwaway-Hetzner-server fixture with a minimal compose stack (`compose.yaml`, `caddy/Caddyfile`, `secrets/web-token` file mount, `src/serve.mjs` healthchecked stub) plus five `run-<probe>.mjs` delegate shims.
|
|
10
|
+
- Compose-config-lint carries four mutation switches (`SIMULATE_MISSING_HEALTHCHECK`, `SIMULATE_UNCLASSIFIED_RESTART`, `SIMULATE_UNCLASSIFIED_LOG_DRIVER`, `SIMULATE_EVENT_SECRECY_LEAK`); secrets-as-files-scan carries `SIMULATE_PLAINTEXT_SECRET`; caddyfile-validate carries `SIMULATE_INVALID_CADDYFILE` and runs `caddy validate` via the `caddy:2` container when a local `caddy` binary is not on PATH.
|
|
11
|
+
- Reverse-proxy choice elicited via `reverse-proxy` (caddy default per Baz decision 19; traefik and none alternatives); Coolify rejected verbatim per Baz decision 20; log driver elicited via `log-driver` (journald default; loki opt-in).
|
|
12
|
+
- Consumers: `w-2026-09-07-dave-004` migrates the ops-01 remote-library compose stack onto this contract after 0.25.0 ships; blueprint acceptance never depends on that migration.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# platform-docker-compose-host v1.0.0
|
|
2
|
+
|
|
3
|
+
A container-orchestration facade over docker compose running on a Linux `cloudHost`. Provides `containerHost` for consumer blueprints that ship as containers.
|
|
4
|
+
|
|
5
|
+
## What it commits
|
|
6
|
+
|
|
7
|
+
Six REQs, nine USs, four TACs, four ADRs and five Node-only probes. Round-7 T-2 of the Hetzner spec at `projects/blueprint-library/specs/hetzner-round-7-spec-2026-09-07.md`.
|
|
8
|
+
|
|
9
|
+
| REQ | Contract |
|
|
10
|
+
|---|---|
|
|
11
|
+
| REQ-001 | `compose.yaml` at repo root is the single-source runtime topology (service-per-container, named networks and volumes, `.env` for non-secret config) |
|
|
12
|
+
| REQ-002 | Every secret injected via a docker compose secrets file mount; no plaintext literal in `compose.yaml` (grep-refuse); references `security-secrets-management` when applied |
|
|
13
|
+
| REQ-003 | Healthcheck contract on every HTTP-terminating service; `docker compose config` refuses on missing |
|
|
14
|
+
| REQ-004 | Restart discipline enforced at lint: `unless-stopped` on long-running, `on-failure` on jobs; unclassified value refuses |
|
|
15
|
+
| REQ-005 | Zero-downtime reverse-proxy reload via bind-mounted config; verb per proxy; no non-2xx or dropped connection inside the elicited window (10 s default) |
|
|
16
|
+
| REQ-006 | Log shipping to the elicited `observability-logging` sink: `journald` default matching Debian 12 / Ubuntu 24.04 baseline; `loki` opt-in when the project runs Grafana |
|
|
17
|
+
|
|
18
|
+
## Capability
|
|
19
|
+
|
|
20
|
+
- `containerHost` (extends `blueprint-authoring.md` section 6a).
|
|
21
|
+
|
|
22
|
+
## Suggested companions
|
|
23
|
+
|
|
24
|
+
- `logging`: every `composeStackReady`, `containerHealthy`, `containerCrashed` and `reverseProxyReloaded` event writes through the applied logger; a logging companion supplies the factory and the log-driver binding.
|
|
25
|
+
- `errorHandling`: a healthcheck timeout, a compose lint refusal, a secret-file-mode mismatch, a reload window overshoot constructs an internal error record; an error-handling companion supplies the record factory and the boundary.
|
|
26
|
+
|
|
27
|
+
## Elicits (via `elicits[]`)
|
|
28
|
+
|
|
29
|
+
- `reverse-proxy`: `caddy` (default per Baz decision 19, matches dev-01 and ops-01) | `traefik` (alternative for docker-label auto-discovery) | `none` (alternative for projects fronted only by the round-7 tunnel).
|
|
30
|
+
- `docker-engine-channel`: `stable` (default) | `test`.
|
|
31
|
+
- `compose-file-location`: `repo-root` (default) | `compose/compose.yaml`.
|
|
32
|
+
- `healthcheck-default-kind`: `http` (default) | `tcp` | `command`.
|
|
33
|
+
- `log-driver`: `journald` (default per ADR-3904) | `loki` (opt-in).
|
|
34
|
+
- `reload-window-seconds`: default `10`.
|
|
35
|
+
|
|
36
|
+
## ADR shape
|
|
37
|
+
|
|
38
|
+
- ADR-3901 container host contract: scope `global` on new topic `containerHostContract`; standards trace clause `Docker Compose file reference AND Docker Engine install-on-Ubuntu docs per hetzner-round-7-spec-2026-09-07.md`.
|
|
39
|
+
- ADR-3902 reverse proxy: elicited, `caddy` default; standards trace clause `Caddy docs AND Traefik docs per hetzner-round-7-spec-2026-09-07.md`.
|
|
40
|
+
- ADR-3903 reject Coolify: decision quoted verbatim from Baz ruling 20 ("reject; it shadows what the blueprints contract and adds its own DB and UI as a second source of state"); standards trace clause `generic enterprise practice`.
|
|
41
|
+
- ADR-3904 log driver: elicited, `journald` default; standards trace clause `generic enterprise practice`.
|
|
42
|
+
|
|
43
|
+
## Probes
|
|
44
|
+
|
|
45
|
+
Five modules under `contributions/probes/`, each writes an envelope to `.rcf/reports/blueprints/platform-docker-compose-host/<probe>.json`:
|
|
46
|
+
|
|
47
|
+
- `compose-config-lint` (accountBound: false; anchors AC-composeHost-healthcheckLint, AC-composeHost-restartClassification, AC-composeHost-logDriverClassification). Mutations: `SIMULATE_MISSING_HEALTHCHECK`, `SIMULATE_UNCLASSIFIED_RESTART`, `SIMULATE_UNCLASSIFIED_LOG_DRIVER`, `SIMULATE_EVENT_SECRECY_LEAK`.
|
|
48
|
+
- `secrets-as-files-scan` (accountBound: false; anchors AC-composeHost-secretsAreFiles, AC-composeHost-secretShape). Mutation: `SIMULATE_PLAINTEXT_SECRET`.
|
|
49
|
+
- `caddyfile-validate` (accountBound: false; anchors AC-composeHost-reverseProxyArtefactValid). Runs a local `caddy` binary when present, otherwise the `caddy:2` container via `docker run --rm`. Mutation: `SIMULATE_INVALID_CADDYFILE`. Skipped when `REVERSE_PROXY` is not `caddy`.
|
|
50
|
+
- `real-account-minimal-stack-up` (accountBound: true; anchors AC-composeHost-upClean). Provisions the throwaway server, `scp`s the compose stack, runs `docker compose up -d --wait`, asserts every declared service reaches healthy inside the elicited timeout, tears down in `always()`. Records `accountBoundSkipped: true` without `CI_HAS_HETZNER_ACCOUNT`.
|
|
51
|
+
- `real-account-reload-burst` (accountBound: true; anchors AC-composeHost-zeroDowntimeReload). Fires an `undici` burst against the caddy service while `docker compose exec caddy caddy reload` runs, asserts every request returns 2xx inside the elicited window with no dropped connection, tears down in `always()`. Records `accountBoundSkipped: true` without `CI_HAS_HETZNER_ACCOUNT`.
|
|
52
|
+
|
|
53
|
+
## Running the probes
|
|
54
|
+
|
|
55
|
+
From the shared throwaway-server fixture directory:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
cd packages/rcf-lite/test/fixtures/hetzner-throwaway-server
|
|
59
|
+
node ./run-compose-config-lint.mjs && node ./run-secrets-as-files-scan.mjs && node ./run-caddyfile-validate.mjs
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Real-account probes gate on `CI_HAS_HETZNER_ACCOUNT`:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
cd packages/rcf-lite/test/fixtures/hetzner-throwaway-server
|
|
66
|
+
CI_HAS_HETZNER_ACCOUNT=true HCLOUD_TOKEN=$HETZNER_ACCOUNT_API_KEY node ./run-real-account-minimal-stack-up.mjs && node ./run-real-account-reload-burst.mjs
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Fixture extension path
|
|
70
|
+
|
|
71
|
+
Round-7 T-1 (`deploy-hetzner-server`) minted the shared fixture at `packages/rcf-lite/test/fixtures/hetzner-throwaway-server/`. T-2 EXTENDS that fixture, never duplicates it: `compose.yaml`, `caddy/Caddyfile`, `secrets/web-token`, `src/serve.mjs` and five `run-<probe>.mjs` delegate shims land alongside T-1's `provision.mjs`/`destroy.mjs`/`sweep-orphans.mjs`. T-3 (`edge-cloudflare-tunnel`) extends the same fixture further; consumers of that fixture see one folder, one manifest, three tracks worth of runtime.
|
|
72
|
+
|
|
73
|
+
## When to reach for this blueprint
|
|
74
|
+
|
|
75
|
+
- Any project running a containerised stack on a `cloudHost` (T-1 `deploy-hetzner-server` provides the shipped v1.0.0 provider).
|
|
76
|
+
- Any project that wants secrets as file mounts (not environment literals), healthchecks that gate boot, a checked-in reverse-proxy artefact, and a log driver on the elicited sink.
|