Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions docs/guide/ai.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@ npm run dev

When the app imports `void/ai`, Void enables a remote Workers AI binding during
development and preview. Requests use your Cloudflare account and its allowance;
Workers AI has no local simulator. Use your Cloudflare login or
`CLOUDFLARE_API_TOKEN` in an automated environment.
Workers AI has no local simulator. Development and preview use the same
Cloudflare login as `void connect`; sign in with `void cloudflare login`. A
`CLOUDFLARE_API_TOKEN` takes precedence; use one in an automated environment.

If development stops with a Cloudflare authentication error, run
`void cloudflare login` in a terminal as a user who can access the deployment
account shown by `void cloudflare status`, or set `CLOUDFLARE_API_TOKEN`.
`wrangler login` does not affect development.

For a team platform, use `void connect <platform-url>` and link your project.
Development requests use that platform's account and usage limits.
Expand Down
20 changes: 18 additions & 2 deletions docs/guide/platform/installation/credentials.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ outline: deep

Keep one password-manager entry for this platform. Paste the saved values into the installer when asked; most do not need shell environment variables.

| Credential | Created by | Why the platform needs it |
| -------------------------------------- | -------------------------------- | ---------------------------------------------------------------------------------------- |
| Management API token | You, in Cloudflare | Lets the CLI change DNS and Access for a domain installation or Access setup. |
| Runtime API token | You, in Cloudflare | Stored as a Worker secret so the platform can deploy apps after you close your terminal. |
| PostgreSQL URL | You, with your database provider | Stores platform users, projects, and deployments. |
| Login provider client ID and secret | You, or Void for Access login | Signs people in to the platform. |
| R2 Access Key ID and Secret Access Key | You, in Cloudflare | Lets the platform sign upload links so `void deploy` sends static files straight to R2. |
| Access setup and app-access tokens | You, in Cloudflare | Only with Cloudflare Access: create and manage Access applications. |
| JWT signing key | Void, on interactive installs | Signs platform login tokens. |
| Project encryption key | Void, on interactive installs | Encrypts app secrets stored by your platform. |
| Email signing key | Void, when email is enabled | Signs confirmation links and email requests. |

## Cloudflare API Tokens {#runtime-token-permissions}

For a domain installation or Cloudflare Access setup, the installer guides you through creating separate management and runtime tokens using Cloudflare's [API token setup](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/). Its links preselect the permissions and suggest names based on your platform's display name, but Cloudflare's form cannot preselect a zone: for a domain installation, change the zone policy from **All Domains** to **Specified Domains** and select your zone. If Void will create the zone, keep **All Domains** on both tokens: the zone does not exist yet, and the runtime token needs it to purge cache. Save the tokens in your password manager and paste them into the masked CLI prompts.
Expand Down Expand Up @@ -74,17 +86,21 @@ The installer deploys the email gateway, prepares the shared mail route, and ver

## R2 Upload Credentials

`void deploy --platform void` uploads your app's static files straight to R2 instead of through the platform API. The API signs short-lived upload links for them with an R2 key pair.

The installer opens the **R2 token creation** form with a token name based on your platform's display name, **Object Read & Write**, and **Apply to all buckets in this account (including newly created buckets)** preselected. Review the settings and create an account token, or a user token if your role requires it. Save its **Access Key ID** and **Secret Access Key** in your password manager, then paste both into the installer. These differ from the management and runtime API tokens. See [R2’s token instructions](https://developers.cloudflare.com/r2/api/tokens/).

## Signing and Encryption Keys {#signing-and-encryption-keys}

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:
The **JWT signing key** signs platform login tokens. The **Project encryption key** encrypts app secrets stored by your platform. An interactive install generates both and keeps them in this machine's encrypted recovery data. Lifecycle commands on this machine read them from there.

To keep your own copy, for example to repair the platform from CI or another machine, create both keys before installing and set `VOID_PLATFORM_JWT_SECRET` and `VOID_PLATFORM_PROJECT_SECRET_KEY`. Non-interactive installs must set both. Generate a separate key for each by running this command twice:

```sh
openssl rand -base64 32
```

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.
Save each result in your password manager. 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.

::: details Generate the keys without printing them to your terminal

Expand Down
2 changes: 1 addition & 1 deletion docs/guide/platform/installation/domains.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,4 @@ New platform resources use deterministic `void-<installation-name>-<role>` names
| Proxied wildcard DNS records | 0 or 1 | Created only when an application domain is configured |
| Zones | 0 or 1 | Created only when the requested application zone is absent |

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.
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, which must be [enabled for the account](/guide/platform/installation/prerequisites#if-cloudflare-rejects-analytics-engine). The core installation doesn't create Container applications, a GitHub App, a dashboard Worker, or build Workers.
39 changes: 38 additions & 1 deletion docs/guide/platform/installation/maintenance.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,43 @@ For completed provisioning whose administrator setup is still pending, run
expired. Enter it at `/setup`, sign in, and confirm the displayed identity.
An installation that already has an administrator does not reopen setup.

### First administrator sign-in fails

If sign-in fails after you enter the setup code, the page shows the reason and an
error code. When a provider setting may be the cause, it also shows the callback
URL the provider must have.

| Error code | What to check |
| --------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| `github_incorrect_client_credentials`, `github_failed`, `oidc_token_failed` | The client ID and client secret, and that the provider has the callback URL |
| `github_redirect_uri_mismatch` | The callback URL registered in the GitHub OAuth app |
| `oidc_discovery_failed` | The issuer URL, exactly, including any trailing slash |
| `github_unverified_user_email` | Verify the primary email of the GitHub account |
| `google_domain_not_allowed`, `oidc_group_not_allowed` | Sign in with an allowed account, or change the allowed domains or groups |
| `login_denied`, `github_bad_verification_code` | Start a new sign-in |

If the provider shows its own error page instead, register exactly the callback
URL printed with your setup code.

To change the login settings, run repair on the computer that installed the
platform:

```sh
void platform repair <id>
void platform repair <id> --auth-config <path>
```

Interactive repair asks whether to change the login settings, with the saved
values filled in; leave the client secret blank to keep it. `--auth-config`
takes a file in the [install format](/guide/platform/installation/setup#finish-login-configuration)
and is the way to change OIDC allowed groups. Login methods and Access protection
stay as installed. Repair prints a new setup code and the callback URL.

A GitHub-only installation signs in with the GitHub OAuth App from its
installation settings. To replace its client ID and secret, set
`VOID_PLATFORM_GITHUB_CLIENT_ID` and `VOID_PLATFORM_GITHUB_CLIENT_SECRET` when
you run `void platform repair <id>`.

### Repair missing resources

Preview what needs repair, then apply it:
Expand Down Expand Up @@ -164,7 +201,7 @@ During a restore, keep platform and application traffic disabled before changing

### Where local state lives

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.
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. Signing and encryption keys that Void generated exist only in these files; to keep your own copy, [supply them when installing](/guide/platform/installation/credentials#signing-and-encryption-keys).

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.

Expand Down
8 changes: 6 additions & 2 deletions docs/guide/platform/installation/prerequisites.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ outline: deep

To run a Void platform, you need:

- A Cloudflare account with Workers for Platforms and R2 enabled.
- A Cloudflare account with Workers for Platforms, R2, and Analytics Engine enabled.
- An empty hosted PostgreSQL database.
- An account with your chosen login provider: GitHub, Google, OIDC, or Cloudflare Access.
- A domain for your apps, or `workers.dev` for testing. You can [add a domain later](/guide/platform/installation/domains#adding-a-domain).
Expand All @@ -28,6 +28,10 @@ If that domain is already in this Cloudflare account, use its existing zone. Oth

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.

### If Cloudflare rejects Analytics Engine

The platform stores request metrics and logs in Analytics Engine. If installation stops with "You need to enable Analytics Engine" (code 10089), add an Analytics Engine binding to a Worker that is not part of the platform under **Settings** > **Bindings**, and deploy it once from the dashboard. A new Hello World Worker works. Do not edit the platform's own Workers. Then run the printed `void platform install --resume` command.

## Install the CLI and Preview

With Node.js 24.21.0 or later, install the CLI:
Expand Down Expand Up @@ -78,7 +82,7 @@ Use any PostgreSQL provider that accepts connections from your computer and Clou
| [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`. |
| [Neon](https://neon.com/docs/get-started-with-neon/connect-neon) | Open **Connect**, select the database and owner role, and turn **connection pooling off**. |

Once installation claims the database, continue using that same database for resume and maintenance commands. Uninstall never deletes external PostgreSQL.
Once installation claims the database, continue using that same database for resume and maintenance commands. If installation stops because it cannot use the database, for example because the database is not empty, set `VOID_PLATFORM_DATABASE_URL` to another database's URL before you resume. Uninstall never deletes external PostgreSQL.

### Use a provider CLI

Expand Down
24 changes: 23 additions & 1 deletion docs/guide/platform/installation/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,28 @@ providers, and existing company policies. Void creates dedicated applications
and a scoped service token for protected installation checks. It preserves your
company policies, including device and MFA requirements.

If no policy fits, choose **Allow my company’s email domain** in the policy list
and enter your domains. Void creates that Allow policy in your account and keeps
it there for reuse; you can add MFA or device rules to it in Cloudflare later.
For identity-provider groups or other rules, choose **Create in Cloudflare** and
follow the printed steps.

An Allow policy must name who may sign in: emails, email domains or lists,
identity-provider groups (Okta, Microsoft Entra ID, Google Workspace, GitHub
organizations, or SAML), authentication contexts, members of a Cloudflare
account, or Access groups built from them. Microsoft Entra ID groups and
authentication contexts count only when they come from an identity provider you
select. A login method also counts when it is one of the identity providers you select and uses
Cloudflare's connector for a company directory: Microsoft Entra ID, Okta,
OneLogin, PingOne, Centrify, Google Workspace, or the Cloudflare login with
**Restrict to account members** turned on. Policies that allow everyone, any
service token, or bypass Access are rejected, and so are policies that rely
only on One-time PIN, a public login such as GitHub, or a login added with the
generic **OpenID Connect** or **SAML** option, even one that fronts your
company directory. Void cannot tell who can sign in through a generic login;
add a Require rule such as **Emails ending in** your company domain to that
policy.

The setup credential needs **Access: Apps and Policies Write** and
**Access: Organizations, Identity Providers, and Groups Read** in the identity
account. Creating protection also needs **Access: Service Tokens Write**.
Expand Down Expand Up @@ -212,7 +234,7 @@ This OAuth App handles sign-in.

## Finish installation

The installer collects your runtime token, PostgreSQL URL, login-provider credentials, R2 credentials, and signing and encryption keys. It masks secret values and saves setup progress encrypted through your system keychain. Keep a password-manager copy for recovery on another machine.
The installer collects your runtime token, PostgreSQL URL, login-provider credentials, and R2 credentials, and generates the [signing and encryption keys](/guide/platform/installation/credentials#signing-and-encryption-keys). It masks secret values and saves setup progress encrypted through your system keychain. Keep a password-manager copy for recovery on another machine.

Once installation finishes, open the printed admin dashboard link. For GitHub-only setup, sign in as the administrator selected during installation. For configurable login, use the one-time `/setup` code to confirm the administrator’s identity. Use the printed API URL to [connect and deploy an app](/guide/platform/installation/first-deployment).

Expand Down
7 changes: 6 additions & 1 deletion docs/guide/platform/installation/uninstall.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void platform uninstall [id] --plan
void platform uninstall [id]
```

Uninstall blocks platform traffic, removes Queues that no remaining platform Worker uses, and lists the resources left for you to review. Use `--plan` to review deletions and retained resources before making changes. By default, Workers, the Queues they use, KV, R2, Hyperdrive, the dispatch namespace, and AI Gateway remain in your account. Adopted resources, external PostgreSQL, and zones are always retained. Email Routing settings are retained; `--purge-resources` removes only the rules that send mail to the platform. DNS records, routes, custom domains, and Cloudflare Access resources are retained unless you use `--purge-resources`.
Uninstall blocks platform traffic, removes Queues that no remaining platform Worker uses, and lists the resources left for you to review. Use `--plan` to review deletions and retained resources before making changes. By default, Workers, the Queues they use, KV, R2, Hyperdrive, the dispatch namespace, and AI Gateway remain in your account. Adopted resources, external PostgreSQL, and zones are always retained. To install a platform again, use a new empty PostgreSQL database. Email Routing settings are retained; `--purge-resources` removes only the rules that send mail to the platform. DNS records, routes, custom domains, and Cloudflare Access resources are retained unless you use `--purge-resources`.

When uninstall finishes, the record of what was kept stays at `~/.void/platforms/<account-id>/<installation-id>.json`. Without `--purge-data`, the encrypted credentials file `<installation-id>.recovery.enc` next to it is kept too. Delete both once you have finished the manual cleanup below.

Expand Down Expand Up @@ -91,6 +91,11 @@ If installation configured Cloudflare Access, the uninstall plan lists its recor

Uninstall does not remove the applications created for [project Zero Trust](/guide/platform/administration/zero-trust). While Zero Trust is enabled or still has Access applications, uninstall and `--plan` stop before any change and list those applications. Run `void platform zero-trust disable` first. Uninstall reads this from the installation database, so it also stops when the database cannot be reached.

If no platform user exists yet, for example because first administrator setup did
not finish, nobody can run `zero-trust disable`. Uninstall then turns off project
Zero Trust and deletes its applications itself. Run it on the computer that installed
the platform. If the uninstall asks you to, update an older platform runtime first.

::: details Why some resources require manual cleanup

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.
Expand Down
Loading
Loading