mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-10-03 09:05:17 -07:00
Integrate Cloudflare R2 for CUDA binary hosting
- Update CI workflow to upload CUDA binary to R2 instead of GitHub - Use custom domain: downloads.voicebox.sh - Update release notes with R2 download link - Add R2 setup documentation with GitHub secrets instructions - Add local test script for R2 uploads - Fixes GitHub 2GB release asset limit issue Required GitHub secrets: - R2_ACCESS_KEY_ID - R2_SECRET_ACCESS_KEY - R2_ENDPOINT Cost: ~$0.04/month (free bandwidth with R2)
This commit is contained in:
@@ -177,9 +177,9 @@ jobs:
|
|||||||
|
|
||||||
### NVIDIA GPU Acceleration (Windows)
|
### NVIDIA GPU Acceleration (Windows)
|
||||||
Windows users with NVIDIA GPUs can enable CUDA for 4-5x faster inference:
|
Windows users with NVIDIA GPUs can enable CUDA for 4-5x faster inference:
|
||||||
1. Install the app normally (CPU version)
|
1. Install the app normally (CPU version included in installer)
|
||||||
2. The app will detect your GPU and offer to download CUDA support
|
2. The app will detect your GPU and offer to download CUDA support automatically
|
||||||
3. Or manually download `voicebox-server-cuda-*.exe` (~3GB) from the assets below
|
3. Or manually download: [voicebox-server-cuda-x86_64-pc-windows-msvc.exe](https://downloads.voicebox.sh/cuda/__VERSION__/voicebox-server-cuda-x86_64-pc-windows-msvc.exe) (~2.4GB)
|
||||||
|
|
||||||
The app includes automatic updates - future updates will be installed automatically.
|
The app includes automatic updates - future updates will be installed automatically.
|
||||||
releaseDraft: true
|
releaseDraft: true
|
||||||
@@ -187,11 +187,26 @@ jobs:
|
|||||||
args: ${{ matrix.args }}
|
args: ${{ matrix.args }}
|
||||||
includeUpdaterJson: true
|
includeUpdaterJson: true
|
||||||
|
|
||||||
- name: Upload CUDA server binary (Windows only)
|
- name: Upload CUDA server to Cloudflare R2 (Windows only)
|
||||||
if: matrix.platform == 'windows-latest'
|
if: matrix.platform == 'windows-latest'
|
||||||
uses: softprops/action-gh-release@v1
|
|
||||||
with:
|
|
||||||
files: backend/cuda-release/voicebox-server-cuda-*.exe
|
|
||||||
draft: true
|
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||||
|
R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }}
|
||||||
|
run: |
|
||||||
|
# Install AWS CLI if not available
|
||||||
|
pip install awscli
|
||||||
|
|
||||||
|
# Get version from tag
|
||||||
|
VERSION=${GITHUB_REF#refs/tags/}
|
||||||
|
|
||||||
|
# Get platform tuple
|
||||||
|
PLATFORM=$(rustc --print host-tuple)
|
||||||
|
|
||||||
|
# Upload to R2
|
||||||
|
aws s3 cp backend/cuda-release/voicebox-server-cuda-${PLATFORM}.exe \
|
||||||
|
s3://voicebox-releases/cuda/${VERSION}/voicebox-server-cuda-${PLATFORM}.exe \
|
||||||
|
--endpoint-url $R2_ENDPOINT \
|
||||||
|
--acl public-read
|
||||||
|
|
||||||
|
echo "CUDA binary uploaded to: https://downloads.voicebox.sh/cuda/${VERSION}/voicebox-server-cuda-${PLATFORM}.exe"
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Test R2 upload locally before running in CI
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "============================================================"
|
||||||
|
echo "Cloudflare R2 Upload Test"
|
||||||
|
echo "============================================================"
|
||||||
|
|
||||||
|
# Check for required environment variables
|
||||||
|
if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ] || [ -z "$R2_ENDPOINT" ]; then
|
||||||
|
echo "ERROR: Missing required environment variables"
|
||||||
|
echo ""
|
||||||
|
echo "Please set:"
|
||||||
|
echo " export AWS_ACCESS_KEY_ID='your-r2-access-key-id'"
|
||||||
|
echo " export AWS_SECRET_ACCESS_KEY='your-r2-secret-access-key'"
|
||||||
|
echo " export R2_ENDPOINT='https://your-account-id.r2.cloudflarestorage.com'"
|
||||||
|
echo ""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for AWS CLI
|
||||||
|
if ! command -v aws &> /dev/null; then
|
||||||
|
echo "Installing AWS CLI..."
|
||||||
|
pip install awscli
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find CUDA binary
|
||||||
|
CUDA_BINARY=$(ls dist/voicebox-server-cuda*.exe 2>/dev/null | head -1)
|
||||||
|
|
||||||
|
if [ -z "$CUDA_BINARY" ]; then
|
||||||
|
echo "ERROR: CUDA binary not found in dist/"
|
||||||
|
echo "Run: bash build_cuda.bat"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Found CUDA binary: $CUDA_BINARY"
|
||||||
|
echo "Size: $(du -h "$CUDA_BINARY" | cut -f1)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test version
|
||||||
|
VERSION="v0.1.12-test"
|
||||||
|
PLATFORM="x86_64-pc-windows-msvc"
|
||||||
|
FILENAME="voicebox-server-cuda-${PLATFORM}.exe"
|
||||||
|
|
||||||
|
echo "Test upload configuration:"
|
||||||
|
echo " Version: $VERSION"
|
||||||
|
echo " Platform: $PLATFORM"
|
||||||
|
echo " Endpoint: $R2_ENDPOINT"
|
||||||
|
echo " Bucket: voicebox-releases"
|
||||||
|
echo " Path: cuda/$VERSION/$FILENAME"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Proceed with upload? (y/n) " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Aborted."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Uploading to R2..."
|
||||||
|
|
||||||
|
aws s3 cp "$CUDA_BINARY" \
|
||||||
|
"s3://voicebox-releases/cuda/${VERSION}/${FILENAME}" \
|
||||||
|
--endpoint-url "$R2_ENDPOINT" \
|
||||||
|
--acl public-read
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "============================================================"
|
||||||
|
echo "Upload successful!"
|
||||||
|
echo "============================================================"
|
||||||
|
echo ""
|
||||||
|
echo "Download URL:"
|
||||||
|
echo "https://downloads.voicebox.sh/cuda/${VERSION}/${FILENAME}"
|
||||||
|
echo ""
|
||||||
|
echo "Test with:"
|
||||||
|
echo "curl -I https://downloads.voicebox.sh/cuda/${VERSION}/${FILENAME}"
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "Upload failed!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -0,0 +1,274 @@
|
|||||||
|
# Cloudflare R2 Setup Guide
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The CUDA binary (2.4GB) is hosted on Cloudflare R2 at `downloads.voicebox.sh` instead of GitHub Releases (which has a 2GB limit).
|
||||||
|
|
||||||
|
## R2 Bucket Configuration
|
||||||
|
|
||||||
|
✅ **Completed:**
|
||||||
|
- Bucket created: `voicebox-releases`
|
||||||
|
- Custom domain configured: `downloads.voicebox.sh`
|
||||||
|
|
||||||
|
## GitHub Secrets Required
|
||||||
|
|
||||||
|
Add these secrets to your GitHub repository:
|
||||||
|
|
||||||
|
### 1. R2_ACCESS_KEY_ID
|
||||||
|
|
||||||
|
Your Cloudflare R2 API Access Key ID
|
||||||
|
|
||||||
|
**How to get it:**
|
||||||
|
1. Go to Cloudflare Dashboard → R2
|
||||||
|
2. Click "Manage R2 API Tokens"
|
||||||
|
3. Create API Token with "Object Read & Write" permissions
|
||||||
|
4. Copy the "Access Key ID"
|
||||||
|
|
||||||
|
**Add to GitHub:**
|
||||||
|
```
|
||||||
|
Repository Settings → Secrets and variables → Actions → New repository secret
|
||||||
|
Name: R2_ACCESS_KEY_ID
|
||||||
|
Value: <your-access-key-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. R2_SECRET_ACCESS_KEY
|
||||||
|
|
||||||
|
Your Cloudflare R2 Secret Access Key
|
||||||
|
|
||||||
|
**How to get it:**
|
||||||
|
- Same process as above
|
||||||
|
- Copy the "Secret Access Key" (shown only once!)
|
||||||
|
- Store it securely
|
||||||
|
|
||||||
|
**Add to GitHub:**
|
||||||
|
```
|
||||||
|
Name: R2_SECRET_ACCESS_KEY
|
||||||
|
Value: <your-secret-access-key>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. R2_ENDPOINT
|
||||||
|
|
||||||
|
Your Cloudflare R2 endpoint URL
|
||||||
|
|
||||||
|
**Format:**
|
||||||
|
```
|
||||||
|
https://<account-id>.r2.cloudflarestorage.com
|
||||||
|
```
|
||||||
|
|
||||||
|
**How to find your account ID:**
|
||||||
|
- Cloudflare Dashboard → R2
|
||||||
|
- Look at the URL or bucket settings
|
||||||
|
- Should be a string of letters/numbers
|
||||||
|
|
||||||
|
**Add to GitHub:**
|
||||||
|
```
|
||||||
|
Name: R2_ENDPOINT
|
||||||
|
Value: https://<your-account-id>.r2.cloudflarestorage.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bucket Structure
|
||||||
|
|
||||||
|
After CI uploads, the bucket will have this structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
voicebox-releases/
|
||||||
|
└── cuda/
|
||||||
|
├── v0.1.12/
|
||||||
|
│ └── voicebox-server-cuda-x86_64-pc-windows-msvc.exe
|
||||||
|
├── v0.1.13/
|
||||||
|
│ └── voicebox-server-cuda-x86_64-pc-windows-msvc.exe
|
||||||
|
└── v0.2.0/
|
||||||
|
└── voicebox-server-cuda-x86_64-pc-windows-msvc.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
## Public Access
|
||||||
|
|
||||||
|
Files are uploaded with `--acl public-read`, making them accessible at:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://downloads.voicebox.sh/cuda/v{VERSION}/voicebox-server-cuda-x86_64-pc-windows-msvc.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
https://downloads.voicebox.sh/cuda/v0.1.12/voicebox-server-cuda-x86_64-pc-windows-msvc.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing the Setup
|
||||||
|
|
||||||
|
### Local Test Upload
|
||||||
|
|
||||||
|
Before running the CI, test uploading locally:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set environment variables
|
||||||
|
export AWS_ACCESS_KEY_ID="your-r2-access-key-id"
|
||||||
|
export AWS_SECRET_ACCESS_KEY="your-r2-secret-access-key"
|
||||||
|
export R2_ENDPOINT="https://your-account-id.r2.cloudflarestorage.com"
|
||||||
|
|
||||||
|
# Install AWS CLI
|
||||||
|
pip install awscli
|
||||||
|
|
||||||
|
# Test upload (use a small test file first)
|
||||||
|
echo "test" > test.txt
|
||||||
|
aws s3 cp test.txt \
|
||||||
|
s3://voicebox-releases/test/test.txt \
|
||||||
|
--endpoint-url $R2_ENDPOINT \
|
||||||
|
--acl public-read
|
||||||
|
|
||||||
|
# Verify it's accessible
|
||||||
|
curl https://downloads.voicebox.sh/test/test.txt
|
||||||
|
|
||||||
|
# If successful, try the actual CUDA binary
|
||||||
|
aws s3 cp backend/dist/voicebox-server-cuda.exe \
|
||||||
|
s3://voicebox-releases/cuda/v0.1.12-test/voicebox-server-cuda-x86_64-pc-windows-msvc.exe \
|
||||||
|
--endpoint-url $R2_ENDPOINT \
|
||||||
|
--acl public-read
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verify Upload
|
||||||
|
|
||||||
|
Check if the file is accessible:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -I https://downloads.voicebox.sh/cuda/v0.1.12-test/voicebox-server-cuda-x86_64-pc-windows-msvc.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
Should return:
|
||||||
|
```
|
||||||
|
HTTP/2 200
|
||||||
|
content-length: 2545086396
|
||||||
|
content-type: application/x-msdownload
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## CI Workflow
|
||||||
|
|
||||||
|
The workflow now:
|
||||||
|
|
||||||
|
1. **Builds CPU binary** → Includes in installer
|
||||||
|
2. **Builds CUDA binary** → Uploads to R2
|
||||||
|
3. **Release notes** → Include R2 download link
|
||||||
|
|
||||||
|
### CI Steps (Windows)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Build CUDA Python server (Windows only)
|
||||||
|
# Builds the CUDA binary
|
||||||
|
|
||||||
|
- name: Upload CUDA server to Cloudflare R2 (Windows only)
|
||||||
|
env:
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||||
|
R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }}
|
||||||
|
run: |
|
||||||
|
aws s3 cp backend/cuda-release/voicebox-server-cuda-*.exe \
|
||||||
|
s3://voicebox-releases/cuda/${VERSION}/... \
|
||||||
|
--endpoint-url $R2_ENDPOINT \
|
||||||
|
--acl public-read
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cost Tracking
|
||||||
|
|
||||||
|
Monitor your R2 usage:
|
||||||
|
|
||||||
|
**Cloudflare Dashboard → R2 → voicebox-releases → Metrics**
|
||||||
|
|
||||||
|
Expected costs (per month):
|
||||||
|
- Storage: 2.4GB × $0.015/GB = **$0.036**
|
||||||
|
- Egress: **$0.00** (free!)
|
||||||
|
- Class A ops: ~100 × $4.50/million = **$0.00**
|
||||||
|
|
||||||
|
**Total: ~$0.04/month** (essentially free!)
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Upload fails: "Access Denied"
|
||||||
|
|
||||||
|
**Solution:** Check API token permissions
|
||||||
|
- Must have "Object Read & Write" on the bucket
|
||||||
|
- Regenerate token if needed
|
||||||
|
|
||||||
|
### File not accessible at downloads.voicebox.sh
|
||||||
|
|
||||||
|
**Solution:** Check custom domain configuration
|
||||||
|
- R2 Dashboard → Bucket → Settings → Custom Domains
|
||||||
|
- Ensure `downloads.voicebox.sh` is properly configured
|
||||||
|
- DNS may take time to propagate
|
||||||
|
|
||||||
|
### "endpoint-url" not recognized
|
||||||
|
|
||||||
|
**Solution:** Make sure AWS CLI is updated
|
||||||
|
```bash
|
||||||
|
pip install --upgrade awscli
|
||||||
|
```
|
||||||
|
|
||||||
|
### File uploaded but wrong permissions
|
||||||
|
|
||||||
|
**Solution:** Re-upload with `--acl public-read`
|
||||||
|
```bash
|
||||||
|
aws s3 cp ... --acl public-read
|
||||||
|
```
|
||||||
|
|
||||||
|
Or set bucket default permissions in R2 Dashboard.
|
||||||
|
|
||||||
|
## Security Notes
|
||||||
|
|
||||||
|
### API Token Permissions
|
||||||
|
|
||||||
|
✅ **Recommended:**
|
||||||
|
- Object Read & Write only
|
||||||
|
- No admin permissions needed
|
||||||
|
- Scoped to `voicebox-releases` bucket only
|
||||||
|
|
||||||
|
❌ **Avoid:**
|
||||||
|
- Account-wide permissions
|
||||||
|
- Account admin access
|
||||||
|
- Worker edit permissions
|
||||||
|
|
||||||
|
### Secret Rotation
|
||||||
|
|
||||||
|
Rotate API tokens every 6-12 months:
|
||||||
|
1. Create new API token
|
||||||
|
2. Update GitHub secrets
|
||||||
|
3. Verify CI still works
|
||||||
|
4. Delete old token
|
||||||
|
|
||||||
|
## Maintenance
|
||||||
|
|
||||||
|
### Cleaning Old Versions
|
||||||
|
|
||||||
|
Optional: Delete old CUDA binaries to save storage costs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all versions
|
||||||
|
aws s3 ls s3://voicebox-releases/cuda/ \
|
||||||
|
--endpoint-url $R2_ENDPOINT
|
||||||
|
|
||||||
|
# Delete old version
|
||||||
|
aws s3 rm s3://voicebox-releases/cuda/v0.1.0/ \
|
||||||
|
--recursive \
|
||||||
|
--endpoint-url $R2_ENDPOINT
|
||||||
|
```
|
||||||
|
|
||||||
|
### Monitoring
|
||||||
|
|
||||||
|
Set up Cloudflare notifications:
|
||||||
|
- Storage approaching limits
|
||||||
|
- Unusual traffic patterns
|
||||||
|
- High operation counts
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. ✅ Bucket configured
|
||||||
|
2. ⏳ Add GitHub secrets (R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_ENDPOINT)
|
||||||
|
3. ⏳ Test local upload
|
||||||
|
4. ⏳ Push branch and create test release
|
||||||
|
5. ⏳ Verify CUDA binary accessible from downloads.voicebox.sh
|
||||||
|
6. ⏳ Implement frontend download manager
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Status**: Ready for testing
|
||||||
|
**Cost**: ~$0.04/month
|
||||||
|
**Bandwidth**: Free (unlimited)
|
||||||
Reference in New Issue
Block a user