PC Proxy Setup¶
Purpose: Offload upload/download bandwidth from Render to local PCs via Cloudflare Tunnel, reducing Render bandwidth costs to near-zero.
Architecture Overview¶
graph LR
Browser -->|"auth + metadata (tiny JSON)"| Render
Browser -->|"file bytes (10MB chunks)"| PC["PC Proxy (Cloudflare Tunnel)"]
PC -->|"upload"| GDrive["Google Drive API"]
PC -->|"upload"| Wasabi["Wasabi S3"]
PC -->|"download stream"| Browser
Render -.->|"fallback if PC down"| Browser
Key principle: Render handles only authentication, database operations, and returns metadata. All file bytes flow through the PC proxy. If the PC is down, the frontend automatically falls back to Render — transparent to the user.
Components¶
| Component | Location | Role |
|---|---|---|
| PC Proxy Flask app | LenzeyeProxyPC/ (separate repo) |
Handles file upload/download |
/api/proxy-config endpoint |
proxy_config_routes.py in main repo |
Tells frontend which PCs are healthy |
proxyHelper.js |
static/upload-app/proxyHelper.js |
Frontend module for upload proxy routing |
proxyDownloadFetch() |
Inline in DownloadUpload_manager.html |
Frontend function for download proxy routing |
Render Environment Variables¶
| Variable | Example | Description |
|---|---|---|
PC_PROXY_ENABLED |
true |
Master switch. false = everything uses Render as before |
PC_PROXY_URLS |
https://pc1.lenzeye.in,https://pc2.lenzeye.in |
Comma-separated list of PC proxy URLs (ordered by priority) |
PROXY_SHARED_SECRET |
a-long-random-string-64-chars |
Shared secret for X-Proxy-Secret header authentication |
Kill Switch
Setting PC_PROXY_ENABLED=false immediately routes everything back through Render. No redeployment needed — takes effect in ~30 seconds.
PC Proxy Setup (Per PC)¶
Prerequisites¶
- Windows 10/11 PC (always on, sleep disabled)
- Internet connection (40+ Mbps upload recommended)
- A Cloudflare account (free tier works)
- Two values from the Lenzeye admin:
PROXY_SHARED_SECRETandLENZEYE_MASTER_KEY
Option A: One-Click Setup (Recommended)¶
The fastest way — handles everything automatically:
- Copy the
LenzeyeProxyPC/folder to the PC - Right-click
setup.bat→ Run as administrator - Follow the on-screen prompts (it will ask for the shared secret and master key)
- The script will install Python dependencies, configure
.env, install the Windows service, download tools, and set up Cloudflare Tunnel - Tell the admin to add your PC URL to
PC_PROXY_URLSon Render
Setup Time
First PC: ~15 minutes. Additional PCs: ~10 minutes.
What You Need Ready
PROXY_SHARED_SECRET(from admin)LENZEYE_MASTER_KEY(from admin)- Cloudflare account credentials (email + password)
- A hostname for this PC (e.g.
pc1.lenzeye.in)
Option B: Manual Setup¶
If you prefer to set up each component manually:
Step 1: Install Python¶
Download and install Python 3.9+ from python.org. Check "Add Python to PATH" during install.
Step 2: Install Dependencies¶
powershell
cd LenzeyeProxyPC
pip install -r requirements.txt
Step 3: Configure Environment¶
Copy .env.example to .env and fill in:
```ini
Authentication¶
PROXY_SHARED_SECRET=same-secret-as-render-env-var
Wasabi S3 (pre-filled, no changes needed)¶
WASABI_ENDPOINT=https://s3.ap-southeast-1.wasabisys.com WASABI_ACCESS_KEY=your-wasabi-access-key WASABI_SECRET_KEY=your-wasabi-secret-key WASABI_BUCKET=your-bucket-name
Encryption (must match Render's LENZEYE_MASTER_KEY)¶
LENZEYE_MASTER_KEY=your-base64-or-hex-master-key
Render server URL (for HMAC forwarding on encrypted GDrive uploads)¶
RENDER_BASE_URL=https://www.lenzeye.in
Server¶
PORT=5050 THREADS=8 ```
Security
The .env file contains production secrets. Never commit it to git. The .gitignore already excludes it.
Step 4: Set Up Cloudflare Tunnel¶
Run the setup script as Administrator:
powershell
.\setup_cloudflare_tunnel.bat
This will:
- Download
cloudflared.exeif not present - Authenticate with Cloudflare (
cloudflared tunnel login) - Create a tunnel named
lenzeye-proxy - Route it to
localhost:5050 - Create a DNS entry (e.g.,
pc1.lenzeye.in) - Install cloudflared as a Windows service
After setup, your PC will be accessible at https://pc1.lenzeye.in.
Step 5: Install as Windows Service¶
```powershell
Run as Administrator¶
.\install_service.bat ```
This uses NSSM to register the Flask app as a Windows service that:
- Starts automatically on boot
- Runs without any user logged in
- Restarts automatically on crash
- Logs output to
logs/folder
Step 6: Verify¶
```powershell
Check service is running¶
nssm status LenzeyeProxyPC
Test health endpoint¶
curl https://pc1.lenzeye.in/health ```
Expected response:
json
{"status": "ok", "timestamp": "2026-07-14T06:00:00Z"}
Step 7: Register on Render¶
Add the PC URL to Render's PC_PROXY_URLS env var:
PC_PROXY_URLS=https://pc1.lenzeye.in,https://pc2.lenzeye.in
How Failover Works¶
Upload Flow¶
- Browser calls
GET /api/proxy-config→ gets{ enabled: true, proxies: ["https://pc1...", "https://pc2..."], secret: "..." } - For each chunk upload,
proxyHelper.jstries PC1 first - If PC1 returns 5xx or is unreachable → tries PC2
- If all PCs fail → falls back to Render (same URL, no proxy header)
- Failed PCs get a 60-second cooldown before retrying
Download Flow¶
- Browser fetches file metadata from Render (tiny JSON)
- Render returns a download URL (presigned Wasabi URL or relative GDrive proxy path)
proxyDownloadFetch()checks if URL is relative (GDrive/encrypted) or absolute (Wasabi)- Relative URLs → route through PC proxy with same failover logic
- Absolute Wasabi URLs → direct fetch (no proxy needed, zero Render bandwidth)
What Gets Proxied¶
| Route | Proxied? | Why |
|---|---|---|
| Wasabi encrypted upload-part | ✅ Yes | 10MB chunk goes through server for encryption |
| GDrive upload-part | ✅ Yes | 10MB chunk goes through server to Google API |
| GDrive encrypted upload-part | ✅ Yes | 10MB chunk encrypted + sent to Google |
| Wasabi unencrypted upload-part | ❌ No | Uses presigned URL (browser → Wasabi directly) |
| GDrive proxy download | ✅ Yes | Server streams from Google Drive |
| Encrypted stream-decrypt | ❌ No | Needs DB for OTP/token/key verification — stays on Render |
| Wasabi direct download | ❌ No | Presigned URL (browser → Wasabi directly) |
Monitoring & Troubleshooting¶
Health Check¶
The /api/proxy-config endpoint on Render pings each PC's /health endpoint every 30 seconds (cached). Unhealthy PCs are removed from the list returned to the frontend.
Logs¶
On the PC, check: ```powershell
Service logs¶
type C:\LenzeyeProxyPC\logs\stdout.log type C:\LenzeyeProxyPC\logs\stderr.log
Cloudflare tunnel logs¶
cloudflared tunnel info lenzeye-proxy ```
Common Issues¶
| Issue | Solution |
|---|---|
| PC offline / tunnel down | Frontend auto-falls back to Render. No user impact. |
X-Proxy-Secret mismatch |
Check .env on PC matches PROXY_SHARED_SECRET on Render |
| GDrive downloads failing | Check PROXY_SHARED_SECRET matches on both Render and PC (used to encrypt/decrypt proxy_token) |
| High RAM on PC | Check concurrent uploads; reduce THREADS in .env |
| Slow uploads | Check internet speed; consider adding a second PC |
GDrive Download Security (proxy_token)¶
GDrive downloads require a Google access token. To avoid exposing the raw token to the browser:
- Render generates the download URL and encrypts the access_token using
PROXY_SHARED_SECRET(AES-256-GCM) - The encrypted blob (
proxy_token) is embedded in the download URL as a query param - Browser sees only the opaque blob — cannot extract the real token
- PC Proxy decrypts the blob using its copy of
PROXY_SHARED_SECRETand uses the real token to call Google Drive API - If the token expires (1 hour), the next download request generates a fresh encrypted blob
This means even if someone intercepts the download URL, the proxy_token is useless without PROXY_SHARED_SECRET.
For GDrive uploads, no token is needed — Google's resumable session URI is self-authenticated for 1 week.
Adding a New PC¶
- Set up the new PC following Steps 1-5 above
- Use a different tunnel DNS name (e.g.,
pc2.lenzeye.in) - Append it to
PC_PROXY_URLSon Render:https://pc1.lenzeye.in,https://pc2.lenzeye.in - The frontend will automatically try PCs in order (left = highest priority)
Removing a PC¶
- Remove its URL from
PC_PROXY_URLSon Render - Optionally stop the service:
nssm stop LenzeyeProxyPC - Optionally remove the tunnel:
cloudflared tunnel delete lenzeye-proxy
Cost Savings¶
| Before | After |
|---|---|
| All upload/download bytes through Render ($15/100GB) | Only auth + metadata through Render (~0.1% of bytes) |
| ~500GB/month = ~$75/month bandwidth | ~$0.10/month bandwidth |
The PC proxy uses your home internet (already paid for) + Cloudflare Tunnel (free tier, unlimited bandwidth).