chore: update deployment process by integrating frontend into static assets

This commit is contained in:
qaz741wsd856 2025-12-02 13:05:57 +00:00
parent 00a1f0d5a8
commit 9ded40c67c
6 changed files with 162 additions and 89 deletions

View file

@ -26,6 +26,33 @@ jobs:
cargo install worker-build cargo install worker-build
fi fi
- name: Download and extract frontend (bw_web_builds)
run: |
# Get latest version tag from bw_web_builds
LATEST_TAG=$(curl -s https://api.github.com/repos/dani-garcia/bw_web_builds/releases/latest | jq -r .tag_name)
echo "📦 Downloading frontend version: $LATEST_TAG"
# Download the web vault release
wget -q "https://github.com/dani-garcia/bw_web_builds/releases/download/$LATEST_TAG/bw_web_${LATEST_TAG}.tar.gz"
# Create public directory and extract
mkdir -p public
tar -xzf bw_web_${LATEST_TAG}.tar.gz -C public/
# bw_web_builds extracts with a web-vault folder, move contents out
if [ -d "public/web-vault" ]; then
shopt -s dotglob
mv public/web-vault/* public/
shopt -u dotglob
rmdir public/web-vault
fi
# Cleanup
rm -f bw_web_${LATEST_TAG}.tar.gz
echo "✅ Frontend files extracted to ./public"
ls -la public/ | head -20
- name: Replace D1_DATABASE_ID_DEV in wrangler.toml - name: Replace D1_DATABASE_ID_DEV in wrangler.toml
run: sed -i "s/\${D1_DATABASE_ID_DEV}/${{ secrets.D1_DATABASE_ID_DEV }}/g" wrangler.toml run: sed -i "s/\${D1_DATABASE_ID_DEV}/${{ secrets.D1_DATABASE_ID_DEV }}/g" wrangler.toml

View file

@ -1,50 +0,0 @@
name: Deploy Frontend
on:
workflow_dispatch: # Manual trigger
# schedule:
# - cron: '0 2 * * 0' # Check for updates every Sunday
jobs:
deploy-pages:
runs-on: ubuntu-latest
name: Deploy to Cloudflare Pages
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download latest web-vault release
run: |
# Get latest version tag
LATEST_TAG=$(curl -s https://api.github.com/repos/dani-garcia/bw_web_builds/releases/latest | jq -r .tag_name)
echo "Downloading version: $LATEST_TAG"
# Download corresponding tar.gz package (Note: bw_web_builds releases are typically named bw_web_tag.tar.gz)
wget "https://github.com/dani-garcia/bw_web_builds/releases/download/$LATEST_TAG/bw_web_${LATEST_TAG}.tar.gz"
# Extract to public directory (Cloudflare Pages default deployment directory)
mkdir public
tar -xvf bw_web_${LATEST_TAG}.tar.gz -C public/
# Fix: bw_web_builds usually extracts with a web-vault folder, need to move contents out
# Adjust based on actual extraction structure, usually contains index.html etc.
if [ -d "public/web-vault" ]; then
shopt -s dotglob
mv public/web-vault/* public/
shopt -u dotglob
rmdir public/web-vault
fi
- name: Create Cloudflare Pages project (if it doesn't exist)
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
run: |
npx wrangler pages project create warden-frontend --production-branch=main --compatibility-date=2024-01-01 || true
- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy public --project-name=warden-frontend --branch=main

View file

@ -39,6 +39,33 @@ jobs:
cargo install worker-build cargo install worker-build
fi fi
- name: Download and extract frontend (bw_web_builds)
run: |
# Get latest version tag from bw_web_builds
LATEST_TAG=$(curl -s https://api.github.com/repos/dani-garcia/bw_web_builds/releases/latest | jq -r .tag_name)
echo "📦 Downloading frontend version: $LATEST_TAG"
# Download the web vault release
wget -q "https://github.com/dani-garcia/bw_web_builds/releases/download/$LATEST_TAG/bw_web_${LATEST_TAG}.tar.gz"
# Create public directory and extract
mkdir -p public
tar -xzf bw_web_${LATEST_TAG}.tar.gz -C public/
# bw_web_builds extracts with a web-vault folder, move contents out
if [ -d "public/web-vault" ]; then
shopt -s dotglob
mv public/web-vault/* public/
shopt -u dotglob
rmdir public/web-vault
fi
# Cleanup
rm -f bw_web_${LATEST_TAG}.tar.gz
echo "✅ Frontend files extracted to ./public"
ls -la public/ | head -20
- name: Replace D1_DATABASE_ID in wrangler.toml - name: Replace D1_DATABASE_ID in wrangler.toml
run: sed -i "s/\${D1_DATABASE_ID}/${{ secrets.D1_DATABASE_ID }}/g" wrangler.toml run: sed -i "s/\${D1_DATABASE_ID}/${{ secrets.D1_DATABASE_ID }}/g" wrangler.toml

3
.gitignore vendored
View file

@ -1,3 +1,6 @@
target target
node_modules node_modules
.wrangler .wrangler
.env
# Frontend files (downloaded during deployment/development)
public/

133
README.md
View file

@ -82,7 +82,26 @@ There are no immediate plans to implement these features. The primary goal of th
wrangler deploy wrangler deploy
``` ```
4. **Deploy the worker:** 4. **Download the frontend (Web Vault):**
```bash
# Get latest version tag
LATEST_TAG=$(curl -s https://api.github.com/repos/dani-garcia/bw_web_builds/releases/latest | jq -r .tag_name)
# Download and extract
wget "https://github.com/dani-garcia/bw_web_builds/releases/download/$LATEST_TAG/bw_web_${LATEST_TAG}.tar.gz"
mkdir -p public
tar -xzf bw_web_${LATEST_TAG}.tar.gz -C public/
# Move files from web-vault subfolder
shopt -s dotglob
mv public/web-vault/* public/
shopt -u dotglob
rmdir public/web-vault
rm bw_web_${LATEST_TAG}.tar.gz
```
5. **Deploy the worker:**
```bash ```bash
wrangler deploy wrangler deploy
@ -90,13 +109,13 @@ There are no immediate plans to implement these features. The primary goal of th
This will deploy the worker and set up the necessary database tables. This will deploy the worker and set up the necessary database tables.
5. **Set environment variables** as `Secret` 6. **Set environment variables** as `Secret`
- `ALLOWED_EMAILS` your-email@example.com - `ALLOWED_EMAILS` your-email@example.com
- `JWT_SECRET` a long random string - `JWT_SECRET` a long random string
- `JWT_REFRESH_SECRET` a long random string - `JWT_REFRESH_SECRET` a long random string
6. **Configure your Bitwarden client:** 7. **Configure your Bitwarden client:**
In your Bitwarden client, go to the self-hosted login screen and enter the URL of your deployed worker (e.g., `https://warden-worker.your-username.workers.dev`). In your Bitwarden client, go to the self-hosted login screen and enter the URL of your deployed worker (e.g., `https://warden-worker.your-username.workers.dev`).
@ -141,9 +160,17 @@ Add the following secrets to your GitHub repository (`Settings > Secrets and var
- `JWT_SECRET` a long random string - `JWT_SECRET` a long random string
- `JWT_REFRESH_SECRET` a long random string - `JWT_REFRESH_SECRET` a long random string
### Deploying the Frontend ### Frontend (Web Vault)
The Bitwarden web vault frontend can be deployed to Cloudflare Pages separately. This project uses [bw_web_builds](https://github.com/dani-garcia/bw_web_builds) (the Vaultwarden web vault builds) as the frontend. The frontend is automatically bundled with the Worker deployment using [Cloudflare Workers Static Assets](https://developers.cloudflare.com/workers/static-assets/). The GitHub Actions workflow automatically downloads the latest [bw_web_builds](https://github.com/dani-garcia/bw_web_builds) (Vaultwarden web vault) and deploys it together with the backend.
**How it works:**
- Static files (HTML, CSS, JS) are served directly by Cloudflare's edge network
- API requests (`/api/*`, `/identity/*`) are routed to the Rust Worker
- No separate Pages deployment or domain configuration needed
> [!NOTE]
> **Migrating from separate frontend deployment?** If you previously deployed the frontend separately to Cloudflare Pages (using the old `deploy-frontend.yml` workflow), you can now delete the `warden-frontend` Pages project from your Cloudflare Dashboard and re-setup the router for worker. The frontend is now bundled with the Worker and no longer requires a separate deployment.
> ⚠️ **Important:** The web vault frontend comes from Vaultwarden and therefore **exposes many advanced UI features**, but most of them are **non-functional** because Warden Worker's backend intentionally does **NOT** implement the corresponding APIs. In practice, it mainly provides bulk management capabilities that aren't available in browser extensions. The following features (among others) are not supported: > ⚠️ **Important:** The web vault frontend comes from Vaultwarden and therefore **exposes many advanced UI features**, but most of them are **non-functional** because Warden Worker's backend intentionally does **NOT** implement the corresponding APIs. In practice, it mainly provides bulk management capabilities that aren't available in browser extensions. The following features (among others) are not supported:
> - Sharing vaults > - Sharing vaults
@ -154,44 +181,37 @@ The Bitwarden web vault frontend can be deployed to Cloudflare Pages separately.
> - Admin console features > - Admin console features
> - And many other advanced Bitwarden features > - And many other advanced Bitwarden features
#### Step 1: Deploy to Cloudflare Pages ### Configure Custom Domain (Optional)
1. **Ensure the required secrets are configured** (same secrets as backend deployment): If you want to use a custom domain instead of the default `*.workers.dev` domain, follow these steps:
- `CLOUDFLARE_API_TOKEN`
- `CLOUDFLARE_ACCOUNT_ID`
2. **Manually trigger the deployment:** #### Step 1: Add DNS Record
- Go to your GitHub repository → **Actions** tab
- Find the **"Deploy Frontend"** workflow
- Click **"Run workflow"** → **"Run workflow"**
- The workflow will download the latest web vault release and deploy it to Cloudflare Pages with project name `warden-frontend`
#### Step 2: Configure Custom Domain in Cloudflare Console 1. Log in to [Cloudflare Dashboard](https://dash.cloudflare.com/)
2. Select your domain (e.g., `example.com`)
3. Go to **DNS** → **Records**
4. Click **Add record**:
- **Type:** `A` (or `AAAA` for IPv6)
- **Name:** your subdomain (e.g., `vault` for `vault.example.com`)
- **IPv4 address:** `192.0.2.1` (this is a placeholder, the actual routing is handled by Worker)
- **Proxy status:** **Proxied** (orange cloud icon - this is required!)
- **TTL:** Auto
5. Click **Save**
After deploying, you need to configure custom domains to connect the frontend (Pages) and backend (Worker): > ⚠️ **Important:** The **Proxy status must be "Proxied"** (orange cloud). If it shows "DNS only" (gray cloud), Worker routes will not work.
1. **Set a custom domain for the frontend (Cloudflare Pages):** #### Step 2: Add Worker Route
- Log in to [Cloudflare Dashboard](https://dash.cloudflare.com/)
- Go to **Workers & Pages** → Select your `warden-frontend` project
- Click **Custom domains** tab → **Set up a custom domain**
- Enter your desired domain (e.g., `vault.example.com`)
- Follow the prompts to add DNS records and verify the domain
2. **Add Worker routes for API endpoints:** 1. Go to **Workers & Pages** → Select your `warden-worker`
2. Click **Settings** → **Domains & Routes**
3. Click **Add** → **Route**
4. Configure the route:
- **Route:** `vault.example.com/*` (replace with your domain)
- **Zone:** Select your domain zone
- **Worker:** `warden-worker`
5. Click **Add route**
The frontend needs to communicate with the backend Worker via `/api/*` and `/identity/*` paths. You need to add routes to your Worker: ### Configure Rate Limiting (Recommended)
- Go to **Workers & Pages** → Select your `warden-worker` (backend Worker)
- Click **Settings** → **Domains & Routes**
- Click **Add** → **Route**
- Add the following routes (replace `vault.example.com` with your domain):
- Route: `vault.example.com/api/*` → Select your Worker
- Route: `vault.example.com/identity/*` → Select your Worker
- Make sure the **Zone** matches your domain's zone
> **Note:** The routes ensure that API requests from the frontend are handled by your Worker backend, while all other requests are served by Cloudflare Pages.
#### Step 3: Configure Rate Limiting (Recommended)
To protect your authentication endpoints from brute force attacks, it's highly recommended to configure rate limiting rules: To protect your authentication endpoints from brute force attacks, it's highly recommended to configure rate limiting rules:
@ -417,9 +437,46 @@ To use Time Travel:
You can run this Worker locally with full D1 database support using Wrangler. This is useful for development, testing, or as a temporary fallback when Cloudflare services are unavailable. You can run this Worker locally with full D1 database support using Wrangler. This is useful for development, testing, or as a temporary fallback when Cloudflare services are unavailable.
To run locally with your production data (useful as emergency fallback): #### Quick Start (API-only, no frontend)
1. **Download and decrypt your backup** (follow the steps above) ```bash
wrangler dev --persist
```
This starts the backend API at `http://localhost:8787`. You can use Bitwarden browser extensions or mobile apps directly.
#### Full Stack Development (with Web Vault frontend)
1. **Download the frontend:**
```bash
# Get latest version tag
LATEST_TAG=$(curl -s https://api.github.com/repos/dani-garcia/bw_web_builds/releases/latest | jq -r .tag_name)
# Download and extract
wget "https://github.com/dani-garcia/bw_web_builds/releases/download/$LATEST_TAG/bw_web_${LATEST_TAG}.tar.gz"
mkdir -p public
tar -xzf bw_web_${LATEST_TAG}.tar.gz -C public/
# Move files from web-vault subfolder
shopt -s dotglob
mv public/web-vault/* public/
shopt -u dotglob
rmdir public/web-vault
rm bw_web_${LATEST_TAG}.tar.gz
```
2. **Start the local server:**
```bash
wrangler dev --persist
```
3. **Access the Web Vault** at `http://localhost:8787`
#### Running with Production Data (Emergency Fallback)
1. **Download and decrypt your backup** (follow the backup restore steps above)
2. **Import the backup to local D1:** 2. **Import the backup to local D1:**

View file

@ -6,6 +6,15 @@ keep_vars = true
[build] [build]
command = "cargo install -q worker-build && worker-build --release" command = "cargo install -q worker-build && worker-build --release"
# Static assets configuration for serving frontend
# Frontend files should be placed in ./public directory before deployment
[assets]
directory = "./public"
not_found_handling = "404-page"
html_handling = "auto-trailing-slash"
# Only invoke Worker for API and Identity routes, serve static files directly for other routes
run_worker_first = ["/api/*", "/identity/*"]
[vars] [vars]
# Optional: Set the batch size for imports. Defaults to 30 if not set. # Optional: Set the batch size for imports. Defaults to 30 if not set.
# Set to 0 means no batching (all records imported in a single batch). # Set to 0 means no batching (all records imported in a single batch).