feat(ops): replace Cloudflare Pages with Workers for frontend hosting
This commit is contained in:
1 parent
9ac1a8b79d
commit
9e56ff7859
16 files changed
+214
-283
No files matched your search
@@ -5,7 +5,7 @@ Purpose: execute and record all manual dashboard tasks that cannot be automated
|
||||
Recommended execution order:
|
||||
|
||||
1. Bind `media.linearvoid.tv` and confirm the HLS origin is separate from the app origin.
|
||||
2. Enable Pages, Tiered Cache, and cache behavior for the media zone.
|
||||
2. Enable Workers, Tiered Cache, and cache behavior for the media zone.
|
||||
3. Apply WAF, bot, rate limiting, HTTPS, and HSTS settings.
|
||||
4. Verify monitor targets and alert delivery in UptimeRobot.
|
||||
5. Capture evidence and fill in the sign-off block.
|
||||
@@ -15,18 +15,18 @@ Recommended execution order:
|
||||
- [ ] Pending
|
||||
- [x] Done
|
||||
|
||||
## 1) Cloudflare Pages Link and Build
|
||||
## 1) Cloudflare Workers Deploy and Custom Domain
|
||||
|
||||
- [ ] Connect repo to Cloudflare Pages project
|
||||
- [ ] Create a Cloudflare Worker for the SPA and bind the build output
|
||||
- [ ] Build command set to: `cd frontend && npm run build`
|
||||
- [ ] Output directory set to: `frontend/dist`
|
||||
- [ ] Production domain attached to `linearvoid.tv`
|
||||
|
||||
Evidence to capture:
|
||||
|
||||
- Screenshot of Pages deployment settings
|
||||
- Screenshot of Worker deployment settings
|
||||
- Deployment URL and latest deployment timestamp
|
||||
- Confirmed production build output path in the Pages project
|
||||
- Confirmed production build output path in the Worker
|
||||
|
||||
## 2) Tiered Cache Enablement and Validation
|
||||
|
||||
@@ -125,7 +125,7 @@ Evidence to capture:
|
||||
|
||||
Completion summary:
|
||||
|
||||
- Pages build URL:
|
||||
- Worker build URL:
|
||||
- Cache validation result:
|
||||
- WAF/rate-limit status:
|
||||
- HTTPS/HSTS status:
|
||||
|
||||
+13
-12
@@ -1,10 +1,10 @@
|
||||
# Cloudflare Pages & Workers Setup — Linear Void
|
||||
# Cloudflare Workers Setup — Linear Void
|
||||
|
||||
Linear Void uses two Cloudflare products:
|
||||
Linear Void uses Cloudflare Workers for two purposes:
|
||||
|
||||
| Product | Purpose | What |
|
||||
| ----------- | ------------------ | ------------------------------------------------------------------------------------ |
|
||||
| **Pages** | Static SPA hosting | Vite-built frontend (`frontend/dist`) deployed via Git integration or Direct Upload |
|
||||
| **Workers** | Static SPA hosting | Vite-built frontend (`frontend/dist`) served as Worker static assets |
|
||||
| **Workers** | Edge cache logic | `infrastructure/cloudflare/worker.js` — adds immutable cache headers to HLS segments |
|
||||
|
||||
Both are managed under **Workers & Pages** in the Cloudflare dashboard.
|
||||
@@ -15,7 +15,6 @@ Both are managed under **Workers & Pages** in the Cloudflare dashboard.
|
||||
| ------------------------ | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| Workers & Pages overview | `https://dash.cloudflare.com/deb11491c54ec53a24772e98ac6d8128/workers-and-pages` |
|
||||
| Worker: linearvoid | `https://dash.cloudflare.com/deb11491c54ec53a24772e98ac6d8128/workers/services/view/linearvoid/production/settings` |
|
||||
| Pages project | `https://dash.cloudflare.com/deb11491c54ec53a24772e98ac6d8128/pages/view/linearvoid` |
|
||||
| API tokens | <https://dash.cloudflare.com/profile/api-tokens> |
|
||||
|
||||
## Worker: `linearvoid` (edge cache headers)
|
||||
@@ -30,17 +29,19 @@ npx wrangler deploy infrastructure/cloudflare/worker.js
|
||||
|
||||
Or paste into the Workers dashboard at the URL above (Quick Edit).
|
||||
|
||||
## Pages: Static frontend
|
||||
## Worker: static frontend
|
||||
|
||||
### Direct Upload via Gitea Actions
|
||||
Serve the Vite-built SPA (`frontend/dist`) as Worker static assets:
|
||||
|
||||
Use `.gitea/workflows/pages-deploy.yml` to build in Gitea Actions and upload via the Cloudflare API.
|
||||
1. Build the frontend: `cd frontend && npm run build`.
|
||||
2. Bind `frontend/dist` to the Worker as static assets (Workers Static Assets / `assets` in `wrangler.toml`).
|
||||
3. Attach the `linearvoid.tv` custom domain to the Worker.
|
||||
|
||||
See [gitea-cloudflare-pages.md](./gitea-cloudflare-pages.md) for the workflow.
|
||||
See [gitea-cloudflare-workers.md](./gitea-cloudflare-workers.md) for the automated deployment workflow.
|
||||
|
||||
### Variables and secrets
|
||||
|
||||
On Cloudflare pages, set the following environment variables (needed to run the frontend)
|
||||
On the Worker, set the following environment variables (needed to run the frontend):
|
||||
|
||||
| Type | Name | Value |
|
||||
| --------- | -------------------------------------- | ----------------------------------------------- |
|
||||
@@ -59,11 +60,11 @@ On Cloudflare pages, set the following environment variables (needed to run the
|
||||
|
||||
## Custom domains
|
||||
|
||||
- `linearvoid.tv` → Pages project
|
||||
- `linearvoid.tv` → Worker (static SPA)
|
||||
- `www.linearvoid.tv` → redirect to `linearvoid.tv`
|
||||
- `media.linearvoid.tv` → R2 bucket (separate; not Pages)
|
||||
- `media.linearvoid.tv` → R2 bucket (separate; not a Worker)
|
||||
|
||||
## Related
|
||||
|
||||
- [Gitea to Cloudflare Pages deployment guide](./gitea-cloudflare-pages.md)
|
||||
- [Gitea to Cloudflare Workers deployment guide](./gitea-cloudflare-workers.md)
|
||||
- [Cloudflare & UptimeRobot checklist](./cloudflare-uptimerobot-checklist.md)
|
||||
@@ -1,144 +0,0 @@
|
||||
# Gitea to Cloudflare Pages — Linear Void
|
||||
|
||||
## Goal
|
||||
|
||||
Deploy the Linear Void frontend (Vite + TypeScript SPA) from Gitea to Cloudflare Pages using Gitea Actions.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
> **Important:** The Pages project must exist before the API deploy call works. You'll get error 8000007 ("Project not found") if you skip this step.
|
||||
|
||||
1. **Cloudflare Pages project** created first:
|
||||
- Dashboard → Workers & Pages → Create → Pages → Direct Upload
|
||||
- Name it `linearvoid` (or a different name if `linearvoid` is already taken by a Worker — see note below)
|
||||
- See [Cloudflare Pages Setup](./cloudflare-pages-setup.md) for full details.
|
||||
2. **Project name**: note the exact name (e.g., `linearvoid`).
|
||||
3. **API token** with Pages permissions:
|
||||
- Create at <https://dash.cloudflare.com/profile/api-tokens>
|
||||
- Permission: `Account → Cloudflare Pages → Edit`
|
||||
- Store in Gitea → Settings → Secrets as `CLOUDFLARE_API_TOKEN`
|
||||
4. **Account ID** from Cloudflare dashboard overview → store as `CLOUDFLARE_ACCOUNT_ID`
|
||||
|
||||
> **Naming conflict:** If a Worker already exists with the name `linearvoid`, the Pages project must use a different name (e.g., `linearvoid-site`). Update the `projectName` in the workflow accordingly. Workers and Pages share a namespace under "Workers & Pages".
|
||||
|
||||
## Project-specific values
|
||||
|
||||
| Setting | Value |
|
||||
| ------------------ | ---------------------------------------------------------- |
|
||||
| Framework | Vite + TypeScript |
|
||||
| Build command | `cd frontend && npm install && npm run build` |
|
||||
| Output directory | `frontend/dist` |
|
||||
| Node version | 20 |
|
||||
| Multi-page entries | `index.html`, `admin/index.html`, `admin/login/index.html` |
|
||||
|
||||
## Gitea Actions workflow
|
||||
|
||||
Create `.gitea/workflows/pages-deploy.yml`:
|
||||
|
||||
```yaml
|
||||
name: Deploy to Cloudflare Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: Install dependencies
|
||||
run: cd frontend && npm ci
|
||||
|
||||
- name: Build
|
||||
run: cd frontend && npm run build
|
||||
|
||||
- name: Deploy to Cloudflare Pages
|
||||
uses: cloudflare/pages-action@v1
|
||||
with:
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
projectName: linearvoid
|
||||
directory: frontend/dist
|
||||
gitHubToken: ${{ secrets.GITEA_TOKEN }}
|
||||
```
|
||||
|
||||
If the `cloudflare/pages-action@v1` action is unavailable from Gitea, use the direct Cloudflare Pages API (multipart/form-data with manifest):
|
||||
|
||||
Snippet to generate a manifest in format `-F manifest='{"index.html": "abc123", "style.css": "def456"}'`
|
||||
|
||||
```bash
|
||||
# Build manifest form argument from all files in frontend/dist
|
||||
form_args="-F manifest={"
|
||||
for file in $(find frontend/dist -type f | sed 's|^frontend/dist/||'); do
|
||||
hash=$(sha256sum "frontend/dist/$file" | awk '{print $1}')
|
||||
form_args="$form_args\"$file\":\"$hash\","
|
||||
done
|
||||
form_args="${form_args%,}}" # remove trailing comma and close JSON
|
||||
```
|
||||
|
||||
```yaml
|
||||
- name: Generate deployment manifest
|
||||
run: |
|
||||
cd frontend/dist
|
||||
form_args="-F manifest={"
|
||||
for file in $(find . -type f ! -name manifest.json | sed 's|^\./||'); do
|
||||
hash=$(sha256sum "$file" | awk '{print $1}')
|
||||
form_args="$form_args\"$file\":\"$hash\","
|
||||
done
|
||||
form_args="${form_args%,}}" # remove trailing comma and close JSON
|
||||
echo "Form arguments: $form_args"
|
||||
echo "FORM_ARGS=$form_args" >> $GITHUB_ENV
|
||||
|
||||
- name: Deploy to Cloudflare Pages
|
||||
env:
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
run: |
|
||||
cd frontend/dist
|
||||
form_args="$FORM_ARGS" # use form arguments generated in previous step
|
||||
COMMIT_HASH=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
||||
curl -sS -X POST \
|
||||
"https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/pages/projects/linearvoid/deployments" \
|
||||
-H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
|
||||
-F "commit_hash=${COMMIT_HASH}" \
|
||||
$form_args
|
||||
```
|
||||
|
||||
This matches the Cloudflare Pages Direct Upload API: `Content-Type: multipart/form-data`, each file as a separate form field, and a `manifest` JSON mapping filenames to SHA-256 hashes.
|
||||
|
||||
## Secrets to add in Gitea
|
||||
|
||||
| Secret | Value |
|
||||
| ----------------------- | ------------------------------------ |
|
||||
| `CLOUDFLARE_API_TOKEN` | API token with Pages:Edit permission |
|
||||
| `CLOUDFLARE_ACCOUNT_ID` | Cloudflare account ID from dashboard |
|
||||
|
||||
## Verify deployment
|
||||
|
||||
1. Push to `main` or trigger manually from Gitea Actions.
|
||||
2. Check **Gitea Actions** → job logs for the deploy step.
|
||||
3. Check **Cloudflare Pages** → Deployments for the new deployment.
|
||||
4. Visit the `.pages.dev` preview URL, then promote to `linearvoid.tv` when ready.
|
||||
|
||||
## Notes
|
||||
|
||||
- The existing `ci.yml` already builds the frontend; the Pages deploy workflow is additive and independent.
|
||||
- Multi-page SPA (`vite.config.ts`) produces three entry points — Cloudflare Pages serves them correctly.
|
||||
- For SPA fallback routing, add a `frontend/public/_redirects` file with `/* /index.html 200` before building.
|
||||
- If deployments fail with 403, verify the API token has `Account → Cloudflare Pages → Edit` permission.
|
||||
- If you get error **8000007** ("Project not found"), the Pages project hasn't been created yet. Create it via the Cloudflare dashboard (Workers & Pages → Create → Pages → Direct Upload) first, then re-run.
|
||||
- If `linearvoid` is already taken by a Worker, use a different project name like `linearvoid-site` and update the `projectName` and `PROJECT_NAME` values in the workflow.
|
||||
|
||||
## Related resources
|
||||
|
||||
- Cloudflare Workers dashboard: `https://dash.cloudflare.com/deb11491c54ec53a24772e98ac6d8128/workers/services/view/linearvoid/production/settings` — for managing the `infrastructure/cloudflare/worker.js` deployment
|
||||
- Cloudflare Pages project: `https://dash.cloudflare.com/deb11491c54ec53a24772e98ac6d8128/pages/view/linearvoid` — deployment history and custom domain settings
|
||||
@@ -0,0 +1,95 @@
|
||||
# Gitea to Cloudflare Workers — Linear Void
|
||||
|
||||
## Goal
|
||||
|
||||
Deploy the Linear Void frontend (Vite + TypeScript SPA) from Gitea to Cloudflare Workers using Gitea Actions and Wrangler.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. **Cloudflare Worker** for the SPA:
|
||||
- Dashboard → Workers & Pages → Create → Worker (or Workers Static Assets).
|
||||
- Name it `linearvoid-frontend` (the edge-cache Worker already uses the `linearvoid` name).
|
||||
2. **API token** with Workers permissions:
|
||||
- Create at <https://dash.cloudflare.com/profile/api-tokens>
|
||||
- Permission: `Account → Workers Scripts → Edit` and `Account → Workers Routes → Edit`
|
||||
- Store in Gitea → Settings → Secrets as `CLOUDFLARE_API_TOKEN`
|
||||
3. **Account ID** from Cloudflare dashboard overview → store as `CLOUDFLARE_ACCOUNT_ID`
|
||||
4. **Wrangler config** (`frontend/wrangler.toml`) binding the `frontend/dist` output as static assets.
|
||||
|
||||
> **Naming conflict:** Workers share a namespace under "Workers & Pages". The edge-cache Worker (`infrastructure/cloudflare/worker.js`) already uses the `linearvoid` name, so the SPA Worker is named `linearvoid-frontend` (see `frontend/wrangler.toml`).
|
||||
|
||||
## Project-specific values
|
||||
|
||||
| Setting | Value |
|
||||
| ------------------ | ---------------------------------------------------------- |
|
||||
| Framework | Vite + TypeScript |
|
||||
| Build command | `cd frontend && npm install && npm run build` |
|
||||
| Output directory | `frontend/dist` |
|
||||
| Node version | 22 |
|
||||
| Multi-page entries | `index.html`, `admin/index.html`, `admin/login/index.html` |
|
||||
|
||||
## Gitea Actions workflow
|
||||
|
||||
Build the SPA and deploy with Wrangler:
|
||||
|
||||
```yaml
|
||||
name: Deploy to Cloudflare Workers
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [CI]
|
||||
types: [completed]
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: Install dependencies
|
||||
run: cd frontend && npm ci
|
||||
|
||||
- name: Build
|
||||
run: cd frontend && npm run build
|
||||
|
||||
- name: Deploy to Cloudflare Workers
|
||||
env:
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
run: |
|
||||
cd frontend
|
||||
npx wrangler deploy
|
||||
```
|
||||
|
||||
## Secrets to add in Gitea
|
||||
|
||||
| Secret | Value |
|
||||
| ----------------------- | ------------------------------------ |
|
||||
| `CLOUDFLARE_API_TOKEN` | API token with Workers permissions |
|
||||
| `CLOUDFLARE_ACCOUNT_ID` | Cloudflare account ID from dashboard |
|
||||
|
||||
## Verify deployment
|
||||
|
||||
1. Push to `main` or trigger manually from Gitea Actions.
|
||||
2. Check **Gitea Actions** → job logs for the deploy step.
|
||||
3. Check **Cloudflare Workers** → `linearvoid-frontend` → Deployments for the new version.
|
||||
4. Visit `https://linearvoid-frontend.zwitschi82.workers.dev`, then attach `linearvoid.tv` when ready.
|
||||
|
||||
## Notes
|
||||
|
||||
- The existing `ci.yml` already builds the frontend; the Workers deploy workflow is additive and independent.
|
||||
- Multi-page SPA (`vite.config.ts`) produces three entry points — Workers static assets serve them correctly.
|
||||
- For SPA fallback routing, set Workers static assets `not_found_handling` to `single-page-application` (serve `index.html` for unknown paths).
|
||||
- The deploy workflow lives in `.gitea/workflows/workers-deploy.yml` (triggered after CI succeeds).
|
||||
|
||||
## Related resources
|
||||
|
||||
- Cloudflare Workers dashboard: `https://dash.cloudflare.com/deb11491c54ec53a24772e98ac6d8128/workers/services/view/linearvoid/production/settings` — for managing the `infrastructure/cloudflare/worker.js` deployment and the SPA Worker
|
||||
Reference in new issue
Block a user