---
title: Self-hosting
description: How hosted and self-hosted wgw-deploy differ, and what Cloudflare resources a self-hosted install needs.
---

# Self-hosting

Hosted wgw-deploy uses the public API at `https://deploy.wgw.lol`. The hosted service stores project metadata and deploy assets in the service operator's Cloudflare account and serves generated domains under `wgw.lol`.

Self-hosting runs the same deploy API and static Worker in your own Cloudflare account. You own the domain, tokens, storage, logs, limits, Cloudflare billing, and operational risk.

## Components

The current repository has two Cloudflare-facing apps:

- `apps/deploy.wgw.lol`: the deploy API and docs site. Its Worker name is configured as `wgw-deploy-api`.
- `apps/static-worker`: the static asset Worker. Its Worker name is configured as `wgw-static`.

The deploy API publishes assets and manifest updates into the configured static Worker.

## Required Cloudflare resources

A self-hosted install needs:

- A Cloudflare account id.
- A base domain served by Cloudflare, with routes for the base domain and wildcard subdomains.
- A KV namespace bound to the deploy API as `DEPLOYS`.
- A static Worker with Workers Assets enabled.
- A deploy API Worker running the Astro Cloudflare build.
- `PUBLIC_ORIGIN` set to the public base origin for generated deploy domains.
- `CLOUDFLARE_WORKER_NAME` set to the static Worker name.
- `CLOUDFLARE_ZONE_ID` when external custom domains are supported.

The checked-in hosted config uses `wgw.lol` and `*.wgw.lol` routes for the static Worker. A self-hosted install should replace those with your own base domain.

The static Worker is only the Workers Assets holder and final fallback. It does not route tenants in code. Configure Cloudflare URL Rewrite Rules before the static Worker so generated subdomains, revision subdomains, and custom-domain traffic resolve to the matching asset prefix, for example `<project>.<base>/*` to `/<project>/*` and external custom domains to `/<lowercase-host>/*`.

## API tokens

Use narrow Cloudflare API tokens and keep the two roles separate:

- `CLOUDFLARE_WORKERS_API_TOKEN`: account-scoped access for the deploy API to create Workers Assets upload sessions and publish the configured static Worker.
- `CLOUDFLARE_ZONE_API_TOKEN`: zone-scoped access for the deploy API to create, read, and delete Cloudflare Custom Hostnames in `CLOUDFLARE_ZONE_ID`.

The zone token is only needed for external custom-domain support. Generated subdomains under your base domain still require the static Worker routes.

Cloudflare's permission names can change. In the dashboard, choose the least-privilege permissions that cover the exact API calls above.

## Point the CLI at your install

The CLI defaults to hosted:

```sh
npx wgw-deploy
```

For self-hosting, point it at your deploy API:

```sh
WGW_API_URL=https://deploy.example.com npx wgw-deploy
```

Local project state still lives in the CLI config directory, and the project API token returned by your API is stored there.

## Hosted vs self-hosted

Hosted means:

- No Cloudflare account is required by the deployer.
- Deploys and metadata live in the hosted service's Cloudflare account.
- Generated domains use `wgw.lol`.
- Limits and availability are controlled by the hosted service and Cloudflare.

Self-hosted means:

- You supply the Cloudflare account, zone, routes, KV namespace, Workers, and API tokens.
- You control generated domains, DNS, retention, deletion, logs, and observability.
- You pay Cloudflare directly.
- You are responsible for securing the tokens and complying with the source license.

## License note

The repository is licensed under FSL-1.1-ALv2. Internal self-hosting is part of the license's permitted-purpose shape, but offering the same or substantially similar functionality as a commercial product or service can be a competing use. Read the license files for the controlling terms. This is not legal advice.
