Install Script Hosting
The public install one-liners are served from Google Cloud, not GitHub Pages:
Install Script Hosting
The public install one-liners are served from Google Cloud, not GitHub Pages:
curl -fsSL https://install.wendy.dev/cli.sh | bash
curl -fsSL https://install.wendy.dev/agent.sh | bashWhy
install.wendy.dev was previously a GitHub Pages custom domain (deployed by the
now-removed .github/workflows/static.yml). GitHub Pages soft-throttles a single
IP and returns 403 when many people install at once from one network (e.g. a
workshop behind one NAT). The scripts also resolved their version from the
GitHub REST API (60 requests/hour per IP), which failed the same way. Both are
now served from GCS.
What is hosted
| Object | Served at | Content-Type |
|---|---|---|
agent.sh | https://install.wendy.dev/agent.sh | text/x-shellscript |
cli.sh | https://install.wendy.dev/cli.sh | text/x-shellscript |
manifest.json | https://install.wendy.dev/manifest.json | application/json |
manifest.json carries { "latest": "<version>", "latest_nightly": "<version>" }.
The scripts read latest to resolve the install version and fall back to the
GitHub API only if the manifest is unreachable.
Publishing
The publish-install-scripts job in .github/workflows/build.yml uploads the
two scripts and merges the channel pointer into manifest.json on every main
push and on stable release, using .github/scripts/publish-install-scripts.sh.
It authenticates with the same Workload Identity Federation identity as the docs
and agent-mirror publishers.
Objects are uploaded with Cache-Control: public, max-age=300, so changes take
effect within about five minutes.
Infrastructure
Static files live in the public bucket wendy-install-public and are served
through the same global external HTTP(S) load balancer that fronts
docs.wendy.dev (see docs-site.md). The load balancer terminates HTTPS; a host
rule routes install.wendy.dev to a backend bucket for wendy-install-public.
One-time maintainer runbook (LB + cert + DNS)
Provision before merge: the bucket and its IAM bindings (step 1 below) must exist BEFORE this branch merges to
main— thepublish-install-scriptsjob runs on everymainpush and will fail if the bucket or write IAM isn't in place yet.
Run these once, from a shell authenticated to the Wendy GCP project. Replace
<PROJECT> with the project id, <URL_MAP> / <TARGET_PROXY> / <CERT> with
the existing docs load-balancer resource names (find them with
gcloud compute url-maps list, gcloud compute target-https-proxies list,
gcloud compute ssl-certificates list).
# 1. Create the public bucket and make its objects world-readable.
gcloud storage buckets create gs://wendy-install-public \
--project=<PROJECT> --location=us --uniform-bucket-level-access
gcloud storage buckets add-iam-policy-binding gs://wendy-install-public \
--member=allUsers --role=roles/storage.objectViewer
# Grant the CI/WIF deploy service account (vars.GCP_SERVICE_ACCOUNT) write access
# so the publish-install-scripts job can upload objects and update the manifest.
gcloud storage buckets add-iam-policy-binding gs://wendy-install-public \
--member=serviceAccount:<SERVICE_ACCOUNT> --role=roles/storage.objectAdmin
# 2. Seed the bucket so the LB has objects to serve before DNS cutover.
# (CI republishes these on every build; this is just for verification.)
gcloud storage cp go/internal/cli/assets/docs/agent.sh gs://wendy-install-public/agent.sh \
--content-type=text/x-shellscript --cache-control="public, max-age=300"
gcloud storage cp go/internal/cli/assets/docs/cli.sh gs://wendy-install-public/cli.sh \
--content-type=text/x-shellscript --cache-control="public, max-age=300"
# 3. Back the bucket with a backend bucket and add a host rule to the docs LB.
gcloud compute backend-buckets create wendy-install-backend \
--gcs-bucket-name=wendy-install-public --enable-cdn --project=<PROJECT>
gcloud compute url-maps add-path-matcher <URL_MAP> \
--path-matcher-name=install \
--default-backend-bucket=wendy-install-backend \
--new-hosts=install.wendy.dev \
--global \
--project=<PROJECT>
# 4. Add install.wendy.dev to a Google-managed certificate and attach it.
# Managed certs take minutes-to-tens-of-minutes to become ACTIVE.
gcloud compute ssl-certificates create wendy-install-cert \
--domains=install.wendy.dev --global --project=<PROJECT>
gcloud compute target-https-proxies update <TARGET_PROXY> \
--ssl-certificates=<CERT>,wendy-install-cert --global --project=<PROJECT>
# 5. Find the LB's global anycast IP.
gcloud compute forwarding-rules list --global --project=<PROJECT>Then, in the DNS zone for wendy.dev:
- Remove the existing
install.wendy.devrecord pointing at GitHub Pages (CNAME -> wendylabsinc.github.io) and the GitHub Pages custom-domain binding in the repository's Pages settings. - Add
install.wendy.devA(andAAAAif the LB has IPv6) records → the load balancer's global IP from step 5.
Verify before announcing:
curl -fsSL https://install.wendy.dev/manifest.json
curl -fsSL https://install.wendy.dev/agent.sh | head -1 # -> #!/usr/bin/env bashAfter cutover
Once install.wendy.dev resolves to the load balancer, flip the
publish-install-scripts job's "Verify scripts are reachable" step in
.github/workflows/build.yml from
https://storage.googleapis.com/wendy-install-public/<name> back to
https://install.wendy.dev/<name> (a comment in that step already flags this).
Docs Site
The public WendyOS documentation site is built with Fumadocs and Next.js, then published as a static export to https://docs.wendy.dev.
Screencast Tooling
The screencast/ directory is developer-only repository tooling for producing narrated engineering screencasts. It is not part of WendyOS, the Wendy CLI, the device runtime, or publ