void 0.20.2 → 0.20.3

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.
Files changed (68) hide show
  1. package/dist/{auth-cmd-gniL2fNt.mjs → auth-cmd-CzwquNiP.mjs} +3 -3
  2. package/dist/{auth-link-NZdjCmSc.mjs → auth-link-ElDTgF7j.mjs} +3 -3
  3. package/dist/{build-cmd-sI18tX_O.mjs → build-cmd-BpJe6boP.mjs} +1 -1
  4. package/dist/{cache-IHn5MwBC.mjs → cache-D98YTqeE.mjs} +1 -1
  5. package/dist/{cancel-deploy-C5qTOdLi.mjs → cancel-deploy-CPbEQLMG.mjs} +1 -1
  6. package/dist/cli/cli.mjs +27 -26
  7. package/dist/{client-dHfSJvAN.mjs → client-BQBrZoCX.mjs} +143 -78
  8. package/dist/{connect-Bfk31O_8.mjs → connect-WCQZ_u3m.mjs} +3 -3
  9. package/dist/{create-project-Bk9Z0-Jg.mjs → create-project-D0oXA090.mjs} +2 -3
  10. package/dist/{db-BkRoptAt.mjs → db-DJ-9qs3S.mjs} +2 -2
  11. package/dist/{delete-DouASY9P.mjs → delete-BZ4-WaGm.mjs} +1 -1
  12. package/dist/{deploy-DTaWUS1S.mjs → deploy-BAhhcg5q.mjs} +17 -10
  13. package/dist/{domain-1RhhOVrC.mjs → domain-BxAyhxXN.mjs} +1 -1
  14. package/dist/{email-C-lGh51B.mjs → email-Bj7Cvdwp.mjs} +2 -2
  15. package/dist/{env-DJHsPE7Z.mjs → env-DP_EErve.mjs} +1 -1
  16. package/dist/{github-cmd-PW7ZnWTp.mjs → github-cmd-C-z_xRrQ.mjs} +13 -19
  17. package/dist/index.mjs +4 -4
  18. package/dist/{init-BWZ7q5Z4.mjs → init-BGktCXgA.mjs} +4 -4
  19. package/dist/{link-Rmvu2Wl_.mjs → link-D2kbqhWb.mjs} +2 -2
  20. package/dist/{list-DEE2S6mY.mjs → list-CvkK_G7k.mjs} +1 -1
  21. package/dist/{login-Uvferzmm.mjs → login-WIjNc77c.mjs} +2 -2
  22. package/dist/{logs-27FenuiC.mjs → logs-dLUFCapG.mjs} +1 -1
  23. package/dist/{operator-cmd-CjOTmAYE.mjs → operator-cmd-CKJ7xIRs.mjs} +2 -2
  24. package/dist/{platform-auth-config-DrbQXXiW.mjs → platform-auth-config-CdVWRRJr.mjs} +2 -2
  25. package/dist/{platform-auth-protection-Bhtvp0B_.mjs → platform-auth-protection-Drl0qhrn.mjs} +2 -2
  26. package/dist/{platform-auth-recovery-CeOKGVeJ.mjs → platform-auth-recovery-CmKEWpDo.mjs} +2 -2
  27. package/dist/{platform-cmd-BFhieCdV.mjs → platform-cmd-5q_k56xS.mjs} +3 -3
  28. package/dist/{platform-domain-C74PULqV.mjs → platform-domain-4GiDlcqx.mjs} +2 -2
  29. package/dist/{platform-lifecycle-BwAIgz-t.mjs → platform-lifecycle-R9xAxvtG.mjs} +61 -25
  30. package/dist/{platform-management-COogu_Se.mjs → platform-management-BfWsXHEW.mjs} +5 -3
  31. package/dist/{platform-recovery-ewqLefp1.mjs → platform-recovery-CbK-I1FB.mjs} +2 -2
  32. package/dist/{project-cmd-DmZK9Hxf.mjs → project-cmd-CTdmnzvc.mjs} +12 -12
  33. package/dist/{project-team-D8jOJMUJ.mjs → project-team-CGxsQe3_.mjs} +4 -2
  34. package/dist/{project-token-DA34bf-C.mjs → project-token-Cirx7uwZ.mjs} +1 -1
  35. package/dist/{requests-CUExwGQQ.mjs → requests-4Nq59hOr.mjs} +1 -1
  36. package/dist/{rollback-CDNGU1gr.mjs → rollback-Dr7u0Ljx.mjs} +1 -1
  37. package/dist/runtime/remote/index.mjs +49 -8
  38. package/dist/runtime/sandbox.d.mts +4 -56
  39. package/dist/runtime/sandbox.mjs +81 -220
  40. package/dist/{secret-Bzzi2e9E.mjs → secret-AcPi-FoA.mjs} +1 -1
  41. package/package.json +7 -7
  42. package/skills/void/SKILL.md +2 -2
  43. package/skills/void/docs/guide/deployment.md +14 -14
  44. package/skills/void/docs/guide/email.md +12 -10
  45. package/skills/void/docs/guide/platform/administration/access.md +163 -0
  46. package/skills/void/docs/guide/platform/administration/email.md +121 -0
  47. package/skills/void/docs/guide/platform/administration/operations.md +97 -0
  48. package/skills/void/docs/guide/platform/administration/projects.md +54 -0
  49. package/skills/void/docs/guide/platform/development/local.md +119 -0
  50. package/skills/void/docs/guide/platform/development/runtime.md +124 -0
  51. package/skills/void/docs/guide/platform/development/schema-ci.md +95 -0
  52. package/skills/void/docs/guide/platform/installation/ci.md +55 -0
  53. package/skills/void/docs/guide/platform/installation/credentials.md +80 -0
  54. package/skills/void/docs/guide/platform/installation/domains.md +68 -0
  55. package/skills/void/docs/guide/platform/installation/first-deployment.md +82 -0
  56. package/skills/void/docs/guide/platform/installation/maintenance.md +137 -0
  57. package/skills/void/docs/guide/platform/installation/prerequisites.md +86 -0
  58. package/skills/void/docs/guide/platform/installation/setup.md +169 -0
  59. package/skills/void/docs/guide/platform/installation/uninstall.md +54 -0
  60. package/skills/void/docs/guide/platform-administration.md +6 -414
  61. package/skills/void/docs/guide/platform-development.md +5 -316
  62. package/skills/void/docs/guide/project-collaboration.md +1 -1
  63. package/skills/void/docs/guide/sandboxes.md +9 -24
  64. package/skills/void/docs/guide/self-hosted-platform.md +11 -694
  65. package/skills/void/docs/reference/api.md +34 -34
  66. package/skills/void/docs/reference/cli.md +28 -11
  67. package/skills/void/docs/reference/config.md +1 -1
  68. package/skills/void/docs/reference/resource-inference.md +10 -10
@@ -6,702 +6,19 @@ outline: deep
6
6
 
7
7
  A Void platform lets your team deploy apps into a shared Cloudflare account. As an administrator, you install and maintain the platform. Developers connect the Void CLI to its URL, sign in through an enabled login method, and deploy their apps.
8
8
 
9
- If you're deploying an app for yourself, [deploy directly to Cloudflare](../integrations/cloudflare.md#deploy-to-your-own-cloudflare-account). You don't need to install a platform first.
9
+ If you're deploying an app for yourself, [deploy directly to Cloudflare](/integrations/cloudflare#deploy-to-your-own-cloudflare-account). You don't need to install a platform first.
10
10
 
11
11
  The core platform supports GitHub, Google, generic OIDC, and Cloudflare Access login, CLI deploys, D1, KV, R2, Queues, cron jobs, Workers AI, WebSockets, SSE, ISR, routing, logs, and rollback.
12
12
 
13
- The core installation includes an email gateway; email is enabled when you configure a shared mail domain and zone. The user dashboard, GitHub builds and webhooks, build Containers, custom project domains, and sandbox orchestration aren't part of the core installation. Source-built platforms that add the optional GitHub services should follow the [isolated webhook ingress setup](./platform-development.md#optional-github-webhook-ingress-for-access-protected-apis) when Access protects the API.
13
+ The core installation includes managed Sandboxes and an email gateway; email is enabled when you configure a shared mail domain and zone. The user dashboard, GitHub builds and webhooks, build Containers, and custom project domains aren't part of the core installation. Source-built platforms that add the optional GitHub services should follow the [isolated webhook ingress setup](/guide/platform/development/runtime#optional-github-webhook-ingress-for-access-protected-apis) when Access protects the API.
14
14
 
15
- ## Before You Start {#prerequisites}
15
+ ## Installation Guides
16
16
 
17
- Start with a Cloudflare account you can administer, an account with your chosen login provider, and an empty hosted PostgreSQL database. GitHub is the default and is optional when another method is selected. A domain is recommended. If yours is not ready, choose **Use workers.dev for testing** during installation and [add a domain later](#add-a-domain-later). The steps below explain how to get the credentials the installer asks for.
18
-
19
- Void creates the Workers, storage, queues, routing, and database tables through the CLI.
20
-
21
- This setup has costs: Workers for Platforms requires a paid plan, and your database and Cloudflare usage have their own pricing. External PostgreSQL is required in either mode. Native single-app deployments remain Workers Free-compatible unless the app uses a paid-only product.
22
-
23
- ## 1. Prepare Your Cloudflare Account and Domain
24
-
25
- In the [Cloudflare dashboard](https://dash.cloudflare.com/), select the account where you want the platform to live:
26
-
27
- 1. Open **Workers for Platforms** and enable its plan. Review [Workers for Platforms pricing](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/platform/pricing/) before confirming.
28
- 2. Open **R2 Object Storage** and complete its activation. Void creates the bucket later.
29
- 3. For a domain installation, choose a domain you own, such as `example.app`. If you need one, register it with your preferred registrar. Use a spare domain's root: apps will be served at `my-app.example.app`. For workers.dev testing, skip this step and the DNS setup below.
30
-
31
- If that domain is already in this Cloudflare account, use its existing zone. Otherwise, [add the domain to Cloudflare](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/) and follow the nameserver instructions until the zone is active. A zone is Cloudflare's DNS configuration for a domain; creating one does not buy the domain.
32
-
33
- You can also let Void create the zone during installation. Setting it up now lets you scope the API tokens to that zone and finish installation without a DNS pause. The platform API uses `workers.dev` by default, so it needs no additional domain.
34
-
35
- ## 2. Install the CLI and Preview {#preview-the-installation}
36
-
37
- With Node.js 24.21.0 or later, install the CLI:
38
-
39
- ```sh
40
- pnpm add --global void
41
- void platform install --plan
42
- ```
43
-
44
- Void checks your saved Cloudflare login while you enter the installation name. If sign-in is needed, it opens your browser after you submit the name; press Ctrl+C to cancel. The plan command then asks for the account and basic configuration and shows the resources it would create. It does not require the database or runtime secrets and does not change Cloudflare resources.
45
-
46
- The installer first offers these choices, with the domain option selected:
47
-
48
- ```text
49
- Where should your apps live?
50
- Use a domain — recommended
51
- Use workers.dev for testing — add a domain later
52
- ```
53
-
54
- For a domain installation, use these answers. Testing mode skips the application domain, zone, and catch-all questions:
55
-
56
- | Prompt | Answer |
57
- | --------------------------------------- | --------------------------------------------------- |
58
- | Installation name | A short name, such as `team` |
59
- | Application base domain | Your domain, such as `example.app` |
60
- | Cloudflare zone | The same domain |
61
- | Platform display name | Any name your team will recognize |
62
- | Optional custom API hostname | Leave empty to use `workers.dev` |
63
- | Dedicate all unmatched traffic to Void? | Yes only if this whole zone belongs to the platform |
64
-
65
- Platform resources use your installation name: `team` creates names such as `void-team-api`, `void-team-proxy`, and `void-team-routing`, with no random suffix. Use a different installation name for another platform in the same account. If a required resource already exists and belongs to another installation, Void stops without overwriting it. Existing installations keep their recorded resource names.
66
-
67
- The preview shows the actual resource names and GitHub callback URL that installation will use with the same configuration. It also links directly to the runtime-token form, the account's R2 token page, and GitHub OAuth registration. It does not open credential setup pages or save an installation draft; Cloudflare browser login still opens when needed.
68
-
69
- You can select either path directly:
70
-
71
- ```sh
72
- void platform install --application-domain example.app --plan
73
- void platform install --workers-dev --plan
74
- ```
75
-
76
- `--workers-dev` cannot be combined with `--application-domain`, `--zone`, or `--dedicated-zone`.
77
-
78
- ## 3. Create the Platform Database {#platform-database}
79
-
80
- Use an empty PostgreSQL database dedicated to this platform. It stores users, projects, and deployments; individual apps can still use D1. Void creates the tables and the Hyperdrive connection, but does not provision the PostgreSQL server.
81
-
82
- Void does not require a particular database provider. Use an existing PostgreSQL host or choose a service such as **Neon**, **PlanetScale Postgres**, **Supabase**, or others.
83
-
84
- 1. Create a fresh database or project dedicated to the platform, with no existing application tables. Use a database role that can create and manage its tables and schemas.
85
- 2. Open the provider's connection details and select the primary database. Use a direct connection or a session-mode pooler, not transaction pooling. The connection must work from both your computer and Cloudflare.
86
- 3. Copy the PostgreSQL connection URL, including the password and SSL settings, into your password manager. Paste only the URL—not a surrounding `psql` command—into Void's `PostgreSQL DATABASE_URL` prompt.
87
-
88
- | Provider | Connection setup |
89
- | ---------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
90
- | [Neon](https://neon.com/docs/get-started-with-neon/connect-neon) | Open **Connect**, select the database and owner role, and turn **connection pooling off**. |
91
- | [PlanetScale Postgres](https://planetscale.com/docs/postgres/connecting) | Choose **Postgres**, not Vitess/MySQL. Open **Connect**, create role credentials, and use the direct primary connection on port `5432`, not PgBouncer on `6432`. |
92
- | [Supabase](https://supabase.com/docs/guides/database/connecting-to-postgres) | Open **Connect** and use the direct connection where IPv6 is available, or the **Session pooler** on port `5432` for IPv4 connectivity. Do not select the transaction pooler on `6543`. Replace the password placeholder with your database password. |
93
-
94
- For a dedicated Supabase project, [disable the Data API](https://supabase.com/docs/guides/api/securing-your-api#disable-the-data-api) so the platform's tables are not exposed through Supabase's auto-generated endpoints. Void uses the PostgreSQL connection, not Supabase API keys.
95
-
96
- Once installation claims the database, continue using that same database for resume and maintenance commands. Uninstall never deletes external PostgreSQL.
97
-
98
- ## 4. Prepare Credentials
99
-
100
- Keep one password-manager entry for this platform. Paste the saved values into the installer when asked; most do not need shell environment variables.
101
-
102
- ### Cloudflare API Tokens {#runtime-token-permissions}
103
-
104
- For a domain installation, create two custom tokens using Cloudflare's [API token setup](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/). Name them **Void Platform Management** and **Void Platform Runtime**. Scope them to your selected account and application zone.
105
-
106
- For workers.dev testing with the default API hostname, browser login can authorize installation: you only need to create the runtime token and R2 credentials below. Skip the zone permissions until you add a domain.
107
-
108
- Browser login does not grant AI Gateway access. A preview can therefore show **inspect ai-gateway**: Void verifies that resource with the runtime token after you confirm installation, before creating any resources. Include **Account → AI Gateway → Edit** on that token. Other infrastructure continues using your browser login, and a normal API-token installation keeps using its management token when that token already has access.
109
-
110
- The management token lets your CLI install and maintain the platform. The runtime token is stored as a Worker secret so the platform can deploy apps after you close your terminal. They are separate credentials.
111
-
112
- The runtime-token link preselects all required account permissions, including Workers Tail, Hyperdrive, and AI Gateway when needed. Review them against the short summary beside the link before creating the token. If the form differs, use that summary to correct it. For a domain installation, also select the indicated zone. See [Cloudflare's token template documentation](https://developers.cloudflare.com/fundamentals/api/how-to/account-owned-token-template/).
113
-
114
- ::: details Permissions to select for each token
115
-
116
- Use the following permissions for the core platform. Cloudflare may label write access as **Edit** or **Write**, depending on the token screen; see its [permission reference](https://developers.cloudflare.com/fundamentals/api/reference/permissions/).
117
-
118
- | Scope | Permission | Management | Runtime |
119
- | ------- | ------------------ | ---------- | --------------------------------------- |
120
- | Account | Account Settings | Read | Read |
121
- | Account | Workers Scripts | Edit | Edit |
122
- | Account | Workers Tail | Read | Read |
123
- | Account | D1 | Edit | Edit |
124
- | Account | Workers KV Storage | Edit | Edit |
125
- | Account | Workers R2 Storage | Edit | Edit |
126
- | Account | Queues | Edit | Edit |
127
- | Account | Hyperdrive | Write | Write |
128
- | Account | Account Analytics | Read | Read |
129
- | Account | AI Gateway | Edit | Edit when installing with browser login |
130
- | Zone | Zone | Read | — |
131
- | Zone | DNS | Edit | — |
132
- | Zone | Workers Routes | Edit | — |
133
- | Zone | Cache Purge | — | Purge |
134
-
135
- The management token also needs **Zone Edit** with authority to create zones if you ask Void to create the zone. If it already exists, use the selected zone with Zone Read and DNS Edit. Nested application domains additionally need **SSL and Certificates: Read** on the management token. A custom runtime that enables custom project domains needs **SSL and Certificates: Edit** on the runtime token; the core runtime does not enable that feature.
136
-
137
- Enabling email lets administrators [register email domains for projects](./platform-administration.md#registering-email-domains-for-projects) and lets projects register destination addresses through the runtime token. That needs **Email Routing Addresses: Edit** and **Email Sending: Edit** on the account, plus **Zone: Read**, **Zone Settings: Edit** and **Email Routing Rules: Edit** on the zones that will carry mail; the token link preselects them when email is enabled. Email Sending onboarding itself needs Workers Paid on the account.
138
-
139
- To enable email, set `VOID_EMAIL_SENDER_DOMAIN` to the shared sender domain and `VOID_EMAIL_SHARED_ZONE_ID` to its Cloudflare zone ID when installing or upgrading. Void records both values for later upgrades and rejects attempts to replace them during an ordinary upgrade. The mail zone can differ from the application zone, but it must belong to the selected platform Cloudflare account; without an explicit mail-zone identity, shared inbound delivery stays unavailable. The dedicated email gateway is deployed in the platform account. Each customer zone uses its own ingress Worker to forward mail to that gateway.
140
-
141
- The installer prepares the shared mail route and verifies inbound readiness before it opens platform traffic. If that setup fails, the installation remains disabled. Correct the reported Cloudflare permission, mail-zone configuration, or routing conflict, then rerun the same install or upgrade command; a fresh install resumes with `void platform install --resume --name <installation-id>`.
142
-
143
- Void checks access before provisioning. If it reports a missing permission, update the token's permissions for the selected account or zone and retry.
144
-
145
- :::
146
-
147
- ### R2 Upload Credentials
148
-
149
- The installer opens the **R2 token creation** form directly, requesting an account token (or a user token if your role cannot create account tokens). Select **Object Read & Write**—the form starts with read-only access—and keep **Apply to all buckets in this account (including newly created buckets)** selected. This lets the token access the buckets Void creates afterward. Create the token and save its **Access Key ID** and **Secret Access Key**. These are different from the management/runtime tokens above. See [R2's token instructions](https://developers.cloudflare.com/r2/api/tokens/).
150
-
151
- ### Signing and Encryption Keys {#signing-and-encryption-keys}
152
-
153
- The **JWT signing key** signs platform login tokens. The **Project encryption key** encrypts app secrets stored by your platform. Generate a separate key for each by running this command twice:
154
-
155
- ```sh
156
- openssl rand -base64 32
157
- ```
158
-
159
- Save each result in your password manager, then paste it into the corresponding installer prompt. The command generates 32 random bytes encoded as base64, suitable for either field. Keep the two original keys for recovery; do not regenerate them when resuming or upgrading.
160
-
161
- ::: details Generate the keys without printing them to your terminal
162
-
163
- On macOS, this copies a suitable random value to the clipboard:
164
-
165
- ```sh
166
- openssl rand -base64 32 | pbcopy
167
- ```
168
-
169
- Paste it into your password manager as **JWT signing key**. Run the command again and save the second value as **Project encryption key**. On PowerShell, use `Set-Clipboard` instead of `pbcopy`. If OpenSSL is unavailable, use your secret manager's secure generator for 32 random bytes in base64, or `node -e 'process.stdout.write(require("node:crypto").randomBytes(32).toString("base64"))'`.
170
-
171
- :::
172
-
173
- When email is enabled, Void also creates an independent **Email signing key** for confirmation links and service-to-service email requests. The installer keeps it in encrypted recovery state. Set `VOID_PLATFORM_EMAIL_SIGNING_SECRET` to a separate value of at least 32 random bytes when you need an externally custodied copy, including a headless installation whose local recovery files will not persist.
174
-
175
- ## 5. Install and Connect GitHub {#install}
176
-
177
- For workers.dev testing, start the interactive install and continue to the GitHub setup below:
178
-
179
- ```sh
180
- void platform install --workers-dev
181
- ```
182
-
183
- For a domain installation, the management token is the one value the interactive installer needs in the shell. Browser login cannot create the application's DNS record. In Bash or zsh, read the token without displaying it or putting its value in command history:
184
-
185
- ```sh
186
- printf 'Cloudflare management API token: '
187
- read -rs CLOUDFLARE_API_TOKEN
188
- printf '\n'
189
- export CLOUDFLARE_API_TOKEN
190
- void platform install
191
- ```
192
-
193
- ::: details PowerShell equivalent
194
-
195
- ```powershell
196
- $env:CLOUDFLARE_API_TOKEN = [System.Net.NetworkCredential]::new('', (Read-Host 'Cloudflare management API token' -AsSecureString)).Password
197
- void platform install
198
- ```
199
-
200
- :::
201
-
202
- Use the same name, account, and domain as the preview, then confirm the installation plan. Void saves a local setup draft and opens the runtime-token page when that token is missing. Paste the token into the masked prompt. As you continue, it opens GitHub and R2 at their respective steps. Each page has a short checklist and a clickable fallback link in the terminal. Values already supplied through the environment or saved setup are reused without opening their pages again.
203
-
204
- ### Choose login methods {#configure-github-oauth}
205
-
206
- The installer offers GitHub, Google, generic OIDC, and Cloudflare Access login.
207
- Cloudflare Access protection is a separate choice from Access login. The
208
- GitHub-only setup below retains the existing workflow.
209
-
210
- For Google, create an OAuth client and register the printed callback URL. You
211
- can restrict it to named Google Workspace domains. For OIDC or Access login,
212
- provide the issuer URL, client ID, and client secret. Select **Company-approved
213
- users** when the configured company policy should allow colleagues to create
214
- accounts automatically without individual invitations.
215
-
216
- When using the configurable setup, installation prints a one-time setup code
217
- and a `/setup` URL. Enter the code, authenticate with the chosen administrator
218
- method, and review the identity before confirming its administrator role. That
219
- method becomes enabled; additional selected methods are saved as pending
220
- configurations to test and enable in Settings. No GitHub account is required
221
- for a Google-only or OIDC-only installation.
222
-
223
- For scripts, pass `--auth-config <path>` with nonsecret configuration and
224
- environment-variable references for secrets. For example:
225
-
226
- ```json
227
- {
228
- "connections": [
229
- {
230
- "configuration": {
231
- "id": "google",
232
- "kind": "google",
233
- "label": "Company Google",
234
- "clientId": "your-google-client-id",
235
- "allowedDomains": ["example.com"]
236
- },
237
- "clientSecretEnv": "GOOGLE_CLIENT_SECRET"
238
- }
239
- ],
240
- "administratorConnectionId": "google",
241
- "admission": {
242
- "mode": "company",
243
- "connections": ["google"],
244
- "access": false
245
- }
246
- }
247
- ```
248
-
249
- `--plan` reads this configuration without requiring the referenced secret.
250
- Supply the secret through your secret manager when applying the installation.
251
-
252
- #### Cloudflare Access {#cloudflare-access-setup}
253
-
254
- Choose Access login, platform protection, or both. Protection can also be used
255
- with GitHub or another login method. With company-approved signup, a colleague
256
- who passes the company gate can create an ordinary account using GitHub even
257
- when their GitHub email differs from their company email.
258
-
259
- Automatic setup uses an existing Zero Trust organization, selected identity
260
- providers, and existing company policies. Void creates dedicated applications
261
- and a scoped service token for protected installation checks. It preserves your
262
- company policies, including device and MFA requirements.
263
-
264
- The setup credential needs **Access: Apps and Policies Write** and
265
- **Access: Organizations, Identity Providers, and Groups Read** in the identity
266
- account. Creating protection also needs **Access: Service Tokens Write**.
267
- Provide a separate setup token through `VOID_PLATFORM_ACCESS_SETUP_TOKEN` if
268
- your Cloudflare management credential lacks these permissions. These permissions
269
- are not required by the platform's runtime token. See Cloudflare's
270
- [Access API](https://developers.cloudflare.com/api/resources/zero_trust/subresources/access/subresources/applications/)
271
- and [service-token permissions](https://developers.cloudflare.com/api/resources/zero_trust/subresources/access/subresources/service_tokens/methods/create/).
272
-
273
- To automate Access setup, add this to the authentication configuration file:
274
-
275
- ```json
276
- {
277
- "protection": true,
278
- "cloudflareAccess": {
279
- "mode": "create",
280
- "identityProviderIds": ["your-company-identity-provider-id"],
281
- "policyIds": ["your-company-allow-policy-id"]
282
- }
283
- }
284
- ```
285
-
286
- Keep the file's `connections` list from the example above, or use a connection
287
- with `{"id":"access","kind":"cloudflare-access","label":"Company Access"}`
288
- to create Access login as well. Omit `protection` for login-only setup.
289
-
290
- To connect applications managed elsewhere, select **Connect existing applications**.
291
- Scripts use `mode: "existing"`, optional `accountId`, and `loginApplicationId`
292
- and/or `protectionApplicationId`. For login, set `loginClientSecretEnv`. For
293
- protection, supply `serviceToken` with `id`, `clientIdEnv`, and `clientSecretEnv`
294
- for a token already admitted by the application. The selected policies must
295
- cover both printed API and proxy origins. Connecting existing resources needs
296
- read access to their applications, policies, organization, identity providers,
297
- groups, and service tokens; Void leaves their policies unchanged.
298
-
299
- Access login alone can connect to another account using only its issuer, client
300
- ID, and secret, without a `cloudflareAccess` block or Cloudflare management token.
301
- Follow Cloudflare's [OIDC application guide](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/saas-apps/generic-oidc-saas/)
302
- and register the exact callback printed by Void.
303
-
304
- For the default GitHub-only setup:
305
-
306
- 1. The installer opens [GitHub's new OAuth App form](https://github.com/settings/applications/new) when it needs OAuth credentials. Sign in as the account that will own the login integration.
307
- 2. Set **Application name** to your platform's display name and **Homepage URL** to the API URL Void just printed.
308
- 3. Set the **Redirect URI** (also called **Authorization callback URL**) to the exact printed URL ending in `/auth/callback`, then register the application. This URL is now pinned in your saved draft and remains the same if credential setup is interrupted.
309
- 4. Save the **Client ID**, generate a **Client Secret**, and save that too. GitHub's [registration guide](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app) describes the form.
310
-
311
- This OAuth App handles sign-in. A GitHub App with repository access and build webhooks is not required for the core platform.
312
-
313
- The prompts collect the runtime token, administrator GitHub username, PostgreSQL URL, GitHub client ID and secret, R2 credentials, and signing/encryption keys. Secret values are masked and setup progress is encrypted locally using the system keychain. Keep a password-manager copy for recovery on another machine.
314
-
315
- Void shows installation progress while it prepares the database, provisions Cloudflare resources, deploys the services, and verifies platform health. Progress is checkpointed for recovery. When installation finishes, open the printed admin dashboard link and sign in with the GitHub account you selected as administrator. This creates your first admin user; no app or CLI login is required. Void also prints the API URL to use when you [connect and deploy an app](#connect-and-deploy-an-app).
316
-
317
- Remove the management token from the shell when finished:
318
-
319
- ```sh
320
- unset CLOUDFLARE_API_TOKEN
321
- ```
322
-
323
- In PowerShell, use `Remove-Item Env:CLOUDFLARE_API_TOKEN`. Keep the saved token for future maintenance.
324
-
325
- ::: details If setup pauses for DNS or is interrupted
326
-
327
- If Void created a zone, it stops in `waiting-for-dns` and prints nameservers. Set those at your registrar, wait for the zone to become active, then resume using the installation ID printed by Void:
328
-
329
- ```sh
330
- void platform install --resume --name <installation-id>
331
- ```
332
-
333
- Keep the management token available for any remaining DNS changes. When using a source build, also pass the same `--runtime` directory. Resume uses the saved checkpoint and original secrets; do not start a second installation or generate replacement keys. If setup failed before a checkpoint was saved, rerun the original command.
334
-
335
- If setup stops or fails, rerun `void platform install`. It lists unfinished installations, including those that reached provisioning, and offers **Continue setup** or **Start a new platform install**. Entering an existing unfinished name also asks whether to resume it; declining lets you enter another name. Continuing restores your saved answers and checkpoints. Starting new does not reuse or delete previous credentials or resources. `--resume --name <id>` continues directly and is required for non-interactive recovery. Read-only `--plan` runs do not save drafts. Completed platforms are managed with `platform status`, `repair`, or `upgrade`, not reinstalled.
336
-
337
- If Cloudflare rejects a saved runtime token during continued credential setup, Void opens the token page and asks for a replacement in the same run. Network or service failures do not discard saved tokens. Tokens supplied through the environment must be corrected there instead.
338
-
339
- :::
340
-
341
- ## 6. Verify and Deploy Your First App {#connect-and-deploy-an-app}
342
-
343
- First verify the new platform and sign in as the GitHub administrator you chose:
344
-
345
- ```sh
346
- void platform status
347
- void platform auth login
348
- void platform system health
349
- ```
350
-
351
- Administrator login is separate from the credentials used to deploy apps. In a new or unlinked Void app directory, connect using the installed API URL and deploy your first project:
352
-
353
- ```sh
354
- void connect https://void-company-api.example.workers.dev
355
- void deploy --platform void --project my-first-app
356
- ```
357
-
358
- `void connect` validates the platform and signs you in when needed. Confirm project creation when deploy asks. To use a project that already exists, run `void project link` instead. An app already linked to another platform keeps its existing destination; use a fresh app directory for your first test.
359
-
360
- The CLI stores login credentials in your system keychain, separately for each platform URL. With no URL, `void connect` offers Cloudflare or a Void platform; `void connect --platform void` offers saved platforms and an option to enter another URL.
361
-
362
- For CI, create a bounded, project-scoped deploy credential while signed in as
363
- the project owner:
364
-
365
- ```sh
366
- void project token create --name ci --expires-in 30
367
- ```
368
-
369
- Store the printed `VOID_TOKEN` and `VOID_API_URL` in the CI secret manager, then
370
- use `void connect <url> --no-login` in a fresh checkout if connection metadata
371
- is not committed. Rotate with `void project token renew <id>` and revoke with
372
- `void project token revoke <id>`. A human login token is not a CI credential.
373
-
374
- If Cloudflare Access protects the platform, Access proof and the project
375
- credential are both required; the service token does not grant Void user or
376
- operator authority. A deploy that uses prerendering or remote bindings calls
377
- both the API and proxy, so store `VOID_ACCESS_CREDENTIALS` in the CI secret
378
- manager with entries for both exact HTTPS origins. Include both entries even
379
- when the same admitted service-token pair is used for both origins:
380
-
381
- ```json
382
- {
383
- "https://void-company-api.example.workers.dev": {
384
- "CF_ACCESS_CLIENT_ID": "<service-token client ID>",
385
- "CF_ACCESS_CLIENT_SECRET": "<service-token client secret>"
386
- },
387
- "https://void-company-proxy.example.workers.dev": {
388
- "CF_ACCESS_CLIENT_ID": "<service-token client ID>",
389
- "CF_ACCESS_CLIENT_SECRET": "<service-token client secret>"
390
- }
391
- }
392
- ```
393
-
394
- `VOID_ACCESS_ORIGIN` can scope credentials to one origin only; setting it to
395
- the API origin does not authorize proxy requests.
396
-
397
- Use these commands to inspect connections and installations:
398
-
399
- ```sh
400
- void platform list
401
- void platform use [id]
402
- void platform status [id]
403
- ```
404
-
405
- ## Managing Access
406
-
407
- After installation, sign in with the GitHub account you chose as the first administrator:
408
-
409
- ```sh
410
- void platform auth login
411
- void platform signup allow github teammate
412
- ```
413
-
414
- Void shows the proposed access change and asks you to confirm it. Once approved, `teammate` can connect to the platform's API URL and sign in with GitHub.
415
-
416
- To see who can join, run `void platform signup show`. You can also allow an email address or a domain such as `*@example.com`. For an OIDC user without verified email, use `void platform signup allow identity <connection-id> <subject>`; the subject match is exact and the provider's domain or group restrictions still apply. Remove that grant with `void platform signup disallow identity <connection-id> <subject>`. `void platform signup open` permits public signup; `void platform signup restrict` requires an allowlist match again.
417
-
418
- Your administrator session lasts for one hour. Use it to inspect users, projects, logs, and platform health. The [Platform Administration guide](./platform-administration.md) walks through those workflows, previews, and automation. You can also open `<API origin>/admin/login` to use the browser admin UI.
419
-
420
- ## Add a Domain Later
421
-
422
- When your domain is ready, run:
423
-
424
- ```sh
425
- void platform domain set example.app --plan
426
- void platform domain set example.app
427
- ```
428
-
429
- The command selects your installed platform (or offers a picker), finds or creates its zone, sets up DNS and routing, and verifies HTTPS before publishing the new application URLs. Set the management token as described [above](#install) when creating DNS or a zone. Grant the existing runtime token **Cache Purge: Purge** on the new zone; Void checks that permission through the running platform without asking you to paste its token again.
430
-
431
- If nameservers or certificates are pending, follow the printed guidance and rerun the same command. Your workers.dev app URLs continue working during and after setup. Projects, deployments, secrets, and the platform API URL stay the same, so developers do not reconnect and the platform's GitHub OAuth callback does not change. DNS and configuration changes may take time to propagate.
432
-
433
- Use `--installation <id>` to select an installation explicitly, `--zone example.com` for an app domain such as `apps.example.com`, or `--dedicated-zone` for catch-all routing on a dedicated zone. Nested domains still need the wildcard certificate described below. This command adds the first domain; replacing an existing application domain is not currently supported. It uses the installed runtime and does not require `--runtime` or an app redeploy.
434
-
435
- Browser login sessions are specific to each origin. Apps using their own OAuth providers may need to register their new callback URLs. Void's built-in auth uses the request origin automatically unless the app overrides that configuration.
436
-
437
- ### What Changes in Testing Mode?
438
-
439
- Each deployed app gets a small forwarding Worker and its own `workers.dev` origin. It forwards requests, including WebSockets and SSE, through the same platform router. Names include installation and project IDs; a later project with the same slug cannot inherit a deleted project's test URL.
440
-
441
- Testing origins use shared ISR storage but bypass the extra edge response cache because you cannot use your zone's purge API for `workers.dev`. Custom-domain requests use the normal edge cache after activation. Existing test URLs and forwarding Workers are retained when you add a domain; new apps then use the domain without creating more forwarding Workers. Like other platform Workers, forwarders are retained for manual cleanup on uninstall; platform disablement and project suspension still apply to their traffic.
442
-
443
- ## Other Domain Options
444
-
445
- ::: details Custom API hostname
446
-
447
- Pass `--control-plane-domain platform.example.net` during installation. The hostname must belong to a zone the selected account and management token can manage. Omitting it keeps the API on `workers.dev`.
448
-
449
- :::
450
-
451
- ### Using a Nested Application Domain
452
-
453
- ::: details Use apps.example.com within an existing company zone
454
-
455
- An app at `my-app.apps.example.com` needs a certificate for `*.apps.example.com`. Universal SSL for `example.com` only covers first-level hostnames. Configure an active wildcard certificate with [Advanced Certificate Manager](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/), a paid add-on, or use an existing custom wildcard certificate before installation:
456
-
457
- ```sh
458
- void platform install --application-domain apps.example.com --zone example.com --plan
459
- ```
460
-
461
- The management token needs **SSL and Certificates: Read** (or Edit) on that zone for the certificate check. Void does not order certificates or enable paid products automatically. Leave `--dedicated-zone` off: that flag is only for installations whose application domain is the entire zone and adds catch-all routes for otherwise unmatched traffic.
462
-
463
- :::
464
-
465
- ## Cloudflare footprint
466
-
467
- Resources use a `void-<installation-name>-<random-suffix>-*` prefix where Cloudflare allows names. This keeps installations recognizable and avoids predictable Worker names colliding during setup.
468
-
469
- | Resource | Count | Purpose |
470
- | ----------------------------------------- | ------------------------------------: | --------------------------------------------------------------------------------------------- |
471
- | Workers | 5, plus one per app using workers.dev | API/control plane, proxy, tail ingestion, dispatch, email gateway, and test-origin forwarders |
472
- | KV namespaces | 3 | Routing, ISR cache, and static asset storage |
473
- | R2 buckets | 1 | Static and deployment assets |
474
- | Queues | 2 | Usage events and cron firing |
475
- | Workers for Platforms dispatch namespaces | 1 | User application Workers |
476
- | Hyperdrive configurations | 1 | External platform PostgreSQL |
477
- | AI Gateways | 1 | Installation-isolated AI routing and metering |
478
- | Proxied wildcard DNS records | 0 or 1 | Created only when an application domain is configured |
479
- | Zones | 0 or 1 | Created only when the requested application zone is absent |
480
-
481
- The API Worker uses four Durable Object classes for usage, cron scheduling, error monitoring, and concurrency. Worker bindings create the request and log datasets in Analytics Engine. The core installation doesn't create Container applications, a GitHub App, a dashboard Worker, or build Workers.
482
-
483
- ## Resume, repair, recover, and upgrade
484
-
485
- You can omit an installation ID when only one is configured. With several installations, choose one interactively or pass its ID in CI.
486
-
487
- ### Resume an installation
488
-
489
- If setup stops or fails, continue from the saved progress:
490
-
491
- ```sh
492
- void platform install --resume --name <id>
493
- ```
494
-
495
- You can correct the database URL if the initial connection failed. Once Void has claimed the database or provisioned Hyperdrive, that database is fixed for the installation. A later command with a different URL stops before making changes.
496
-
497
- ### Cloudflare Access blocks the health check {#cloudflare-access}
498
-
499
- If installation reports **Default-Deny (error 1050)**, Cloudflare blocked the HTTP health check before it reached Void. This is separate from the API token used to deploy the Workers.
500
-
501
- Keep the company protection in place. Automatic Access setup saves its scoped
502
- service credentials with the installation's encrypted recovery material. For an
503
- existing gate, verify that its service policy admits the installation token and
504
- that the application covers the printed API and proxy origins. A Cloudflare
505
- management API token does not authenticate an Access-protected HTTP request.
506
-
507
- For externally supplied credentials, set `VOID_ACCESS_CREDENTIALS` from your
508
- secret manager to an object keyed by each exact API/proxy origin, with
509
- `CF_ACCESS_CLIENT_ID` and `CF_ACCESS_CLIENT_SECRET` in each entry. Then rerun
510
- `void platform install --resume --name <id>`. Void retains the saved resources
511
- and stops if the gate still rejects its checks. Account-wide Default-Deny and
512
- deployed-application policies remain your responsibility.
513
-
514
- ### Expired administrator setup code
515
-
516
- Resume an unfinished installation with `void platform install --resume --name <id>`.
517
- For completed provisioning whose administrator setup is still pending, run
518
- `void platform repair <id>`. Void prints a fresh setup code if the earlier code
519
- expired. Enter it at `/setup`, sign in, and confirm the displayed identity.
520
- An installation that already has an administrator does not reopen setup.
521
-
522
- ### Repair missing resources
523
-
524
- Preview what needs repair, then apply it:
525
-
526
- ```sh
527
- void platform repair [id] --plan
528
- void platform repair [id]
529
- ```
530
-
531
- Repair recreates missing infrastructure that the installer owns. It does not restore PostgreSQL rows or data stored in provider resources. If an adopted or external resource is missing, restore it yourself before continuing. A disabled platform stays disabled through repair and upgrade.
532
-
533
- ### Upgrade the platform
534
-
535
- Use the installed CLI's packaged runtime to upgrade:
536
-
537
- ```sh
538
- void platform upgrade [id] --plan
539
- void platform upgrade [id]
540
- ```
541
-
542
- An upgrade validates the runtime, applies supported pending migrations, deploys the Workers, and checks their health. Existing Worker secrets are preserved.
543
-
544
- ::: details Migration safety, credential rotation, and interrupted upgrades
545
-
546
- Some upgrades briefly put the platform into maintenance mode. Traffic resumes after the new version passes health checks. If an upgrade is interrupted during maintenance, rerun the same command to complete it.
547
-
548
- To update the runtime Cloudflare token, GitHub OAuth credentials, or R2 credentials,
549
- provide their `VOID_PLATFORM_*` environment variables when running the upgrade.
550
- Only the supplied values replace live credentials. Recovery data from an older
551
- workstation does not overwrite them, and upgrades preserve the live signing keys
552
- and complete project-encryption keyring. Keep current credentials in your secret
553
- manager so they can also restore a missing Worker during repair.
554
-
555
- Database migrations only move forward. Void checks compatibility before upgrading and tells you if an intermediate release is needed. If deployment fails, it attempts to restore the previous Workers against the compatible database schema. Retrying does not repeat completed migrations.
556
-
557
- If an upgrade asks you to finish Sandbox cleanup, follow the [`sandbox-drain` instructions](../reference/cli.md#operator-system), then rerun the upgrade. Administrator login remains available during that maintenance step.
558
-
559
- After a successful upgrade, you can restore a declared-compatible earlier runtime without reversing migrations:
560
-
561
- ```sh
562
- void platform rollback [id] --runtime /path/to/earlier/runtime --plan
563
- void platform rollback [id] --runtime /path/to/earlier/runtime
564
- ```
565
-
566
- Keep the earlier runtime files if you need rollback. If the installed version is a custom build, also pass its files with `--from-runtime /path/to/current/runtime`. Void checks that the earlier version can run against your current database and refuses incompatible rollbacks. A later `upgrade` can move forward again. See [Platform Development](./platform-development.md#deploying-your-runtime) for working with custom builds.
567
-
568
- :::
569
-
570
- ### Manage an installation from another machine
571
-
572
- Use `discover` to restore the administrator's local installation records:
573
-
574
- ```sh
575
- void platform discover --account <account-id> --installation <id-or-name>
576
- ```
577
-
578
- Discovery restores local installation records after verifying the resources belong to your platform. It also works for interrupted or disabled installations. If infrastructure is missing, run `void platform repair [id]` after discovery. If ownership cannot be verified, the command stops without changing resources.
579
-
580
- After discovery, provide `VOID_PLATFORM_DATABASE_URL` for migrations and to coordinate administrator commands. You don't need to re-enter the other secrets for an upgrade that preserves every deployed Worker. For an email-enabled installation without its encrypted recovery file, restore `VOID_PLATFORM_EMAIL_SIGNING_SECRET`; recreating only the email gateway needs that key and no Cloudflare runtime token or JWT signing key. Recreating the API or proxy also requires the email key when email is enabled, in addition to their normal secrets. Recreating the API requires its original runtime token (`VOID_PLATFORM_RUNTIME_CLOUDFLARE_API_TOKEN`), GitHub, R2, JWT, and project-encryption values through the `VOID_PLATFORM_*` variables; recreating the proxy requires the runtime token and JWT signing key. Cloudflare can't return these values, so keep them in your organization's secret manager.
581
-
582
- If you have not rotated the project-encryption key, restore it with `VOID_PLATFORM_PROJECT_SECRET_KEY`. After rotation, supply `VOID_PLATFORM_PROJECT_SECRET_KEYS_JSON` with all retained keys and `VOID_PLATFORM_PROJECT_SECRET_ACTIVE_KEY_VERSION` with the active key's name. Keep older keys needed to decrypt existing project secrets. These values are used to recreate a missing API Worker; they do not replace the live keys during an ordinary upgrade. Supply them from your secret manager.
583
-
584
- ### Prepare for disaster recovery
585
-
586
- `discover` reconstructs verified installation metadata on another machine. It does not download credentials, key material, or backed-up data. `repair` can then recreate missing installer-owned infrastructure, but it does not recover the data that infrastructure previously held.
587
-
588
- Keep a coordinated recovery set for each installation:
589
-
590
- - a PostgreSQL backup;
591
- - the installation identity—the JWT signing secret, the email signing secret when email is enabled, and the complete project-encryption keyring—in a secret manager;
592
- - provider-supported backups or exports for every data-bearing provider resource;
593
- - the immutable runtime artifacts and manifest for the installed version or custom source revision.
594
-
595
- Capture and label these items as one recovery point so PostgreSQL, provider data, identity, and encryption keys match. Backup and retention capabilities vary by provider and resource; choose and test the supported recovery process for each resource you use.
596
-
597
- During a restore, keep platform and application traffic disabled before changing resources. Restore the matching PostgreSQL and provider data with their supported recovery tools, supply the original identity and keyring, and use the preserved runtime artifact. Then run `discover`, preview `repair` with `--plan`, and review every ownership decision and proposed resource change before applying it. Enable traffic only after the restored data and platform health have been verified. Discovery and repair are not substitutes for those backups and do not provide a recovery bypass when required secrets or data are unavailable.
598
-
599
- ### Where local state lives
600
-
601
- Installation records live in `~/.void/platforms/`. Credentials are stored separately in encrypted recovery files, with the encryption key in your operating system's keychain. Keep your original secrets in a password manager for recovery on another machine.
602
-
603
- If the keychain isn't available, Void stops before writing secrets. Headless environments can supply `VOID_PLATFORM_RECOVERY_KEY`: a canonical base64-encoded 32-byte key from a secret manager. A temporary CI runner can use a new recovery-encryption key for each run only when every original credential remains available in protected CI secrets, including `VOID_PLATFORM_JWT_SECRET`, `VOID_PLATFORM_EMAIL_SIGNING_SECRET` for an email-enabled installation, and either the original `VOID_PLATFORM_PROJECT_SECRET_KEY` or the complete rotated keyring and active-version pair.
604
-
605
- ::: details Ownership and interrupted maintenance
606
-
607
- Void checks resource ownership and the configured database before making changes. Concurrent maintenance commands are coordinated so one administrator cannot overwrite another's work.
608
-
609
- If maintenance is interrupted, rerun the same command. Traffic may stay paused until verification succeeds. Existing routes, domains, and data are preserved.
610
-
611
- :::
612
-
613
- ## Install from CI {#install-from-ci}
614
-
615
- For your first installation, follow the interactive walkthrough above. Use this section when automating a configured installation.
616
-
617
- ::: details Non-interactive inputs
618
-
619
- Inject the following values from protected CI secrets. Do not commit them in a workflow or a plaintext secrets file.
620
-
621
- | Environment variable | Value from the interactive setup |
622
- | -------------------------------------------- | ------------------------------------------------------------------------------------------- |
623
- | `CLOUDFLARE_API_TOKEN` | Management API token |
624
- | `VOID_PLATFORM_RUNTIME_CLOUDFLARE_API_TOKEN` | Runtime API token |
625
- | `VOID_PLATFORM_DATABASE_URL` | Dedicated PostgreSQL URL |
626
- | `VOID_PLATFORM_GITHUB_CLIENT_ID` | OAuth App client ID |
627
- | `VOID_PLATFORM_GITHUB_CLIENT_SECRET` | OAuth App client secret |
628
- | `VOID_PLATFORM_ADMIN_GITHUB_LOGIN` | Initial administrator's GitHub username |
629
- | `VOID_PLATFORM_R2_ACCESS_KEY_ID` | R2 Access Key ID |
630
- | `VOID_PLATFORM_R2_SECRET_ACCESS_KEY` | R2 Secret Access Key |
631
- | `VOID_PLATFORM_JWT_SECRET` | Original JWT signing secret |
632
- | `VOID_PLATFORM_EMAIL_SIGNING_SECRET` | Dedicated email signing secret when email is enabled |
633
- | `VOID_PLATFORM_PROJECT_SECRET_KEY` | Original base64-encoded project-encryption key |
634
- | `VOID_PLATFORM_RECOVERY_KEY` | Base64-encoded 32-byte key for local encrypted recovery state when no keychain is available |
635
- | `VOID_EMAIL_SENDER_DOMAIN` | Optional shared mail domain; requires `VOID_EMAIL_SHARED_ZONE_ID` |
636
- | `VOID_EMAIL_SHARED_ZONE_ID` | Cloudflare zone ID for that mail domain; requires `VOID_EMAIL_SENDER_DOMAIN` |
637
-
638
- Use that installation's saved signing and encryption keys on every resume or repair that needs them. After a keyring rotation, use the [complete keyring recovery inputs](#manage-an-installation-from-another-machine). The database claim and tables remain after uninstall; use a fresh database for a different installation.
639
-
640
- Set both email values to enable email during install or upgrade. Later upgrades reuse the recorded values. If an email-enabled installation has no recorded values, supply both before upgrading.
641
-
642
- ```sh
643
- void platform install \
644
- --name team \
645
- --display-name "Team Void" \
646
- --account <account-id> \
647
- --application-domain example.app \
648
- --zone example.app \
649
- --yes
650
- ```
651
-
652
- Mutations require `--yes` in CI; a read-only `--plan` does not. Custom runtimes also require `--runtime <directory>`. For a new installation, register the GitHub callback shown by `--plan` before running the unattended install with the same account, name, and domain options. A custom API hostname is optional.
653
-
654
- :::
655
-
656
- ## Customize the Platform {#continuously-deploy-a-source-build}
657
-
658
- To change the platform's implementation or deploy your own build, follow [Platform Development](./platform-development.md). It covers local development, source builds, and CI for a fork.
659
-
660
- ## Disable and safely uninstall
661
-
662
- To pause a platform without removing its data:
663
-
664
- ```sh
665
- void platform disable [id] --plan
666
- void platform disable [id]
667
- ```
668
-
669
- Disabled platforms reject application traffic while retaining domains and routes. Repair and upgrade preserve that state. Restore traffic with:
670
-
671
- ```sh
672
- void platform enable [id] --plan
673
- void platform enable [id]
674
- ```
675
-
676
- Add `--yes` to commands that make changes in a non-interactive shell.
677
-
678
- While disabled, the platform retries queue batches after five minutes instead of delivering them to apps. Queue retention and retry limits still apply. For a long pause, plan a dead-letter queue or another way to recover messages.
679
-
680
- ### Uninstall
681
-
682
- Preview removal before applying it:
683
-
684
- ```sh
685
- void platform uninstall [id] --plan
686
- void platform uninstall [id]
687
- ```
688
-
689
- Uninstall blocks platform traffic, removes transient Queues, and records the resources left for you to review. By default, Workers, KV, R2, Hyperdrive, the dispatch namespace, and AI Gateway remain in your account. Adopted resources, external PostgreSQL, zones, DNS records, routes, and custom domains are always retained.
690
-
691
- To also remove eligible data resources owned by the installer:
692
-
693
- ```sh
694
- void platform uninstall [id] --purge-data
695
- ```
696
-
697
- Even with `--purge-data`, Void retains Workers, R2, AI Gateway, DNS records, routes, custom domains, adopted resources, external PostgreSQL, and zones. Review those in the Cloudflare dashboard if you want to remove them.
698
-
699
- ::: details Why some resources require manual cleanup
700
-
701
- Resources that may have been shared or repurposed require manual review before deletion. Void verifies ownership, keeps those resources in place, and blocks platform traffic.
702
-
703
- If removal is interrupted, rerun the command to continue. If a resource has changed ownership, resolve the reported conflict before retrying.
704
-
705
- External PostgreSQL and its data always remain under your control.
706
-
707
- :::
17
+ - [Prerequisites](/guide/platform/installation/prerequisites)
18
+ - [Credentials](/guide/platform/installation/credentials)
19
+ - [Install and Configure Login](/guide/platform/installation/setup)
20
+ - [First Deployment](/guide/platform/installation/first-deployment)
21
+ - [Domains and Resources](/guide/platform/installation/domains)
22
+ - [Maintenance and Recovery](/guide/platform/installation/maintenance)
23
+ - [Install from CI](/guide/platform/installation/ci)
24
+ - [Disable and Uninstall](/guide/platform/installation/uninstall)