All docs

Direct downloads via Cloudflare Tunnel

Skip the Filestor backend for file downloads — bytes flow from the agent host through Cloudflare Tunnel straight to the browser. Filestor still authorizes every request, but never proxies the bytes.

Why it's worth doing

Every agent download today flows agent → Filestor backend → browser over the WebSocket connection. On metered hosts (Hetzner, low-tier VPS) that's two bandwidth-hits per file. With the tunnel handoff, the backend emits a 302 to a 5-minute presigned URL and Cloudflare ferries the bytes. Backend egress per download drops from to roughly one HTTP response.

This is opt-in per agent. Local + R2/S3 roots aren't affected.

Prerequisites

  • A Cloudflare account with a domain you control (free tier is fine).
  • cloudflared installed on the agent host.
  • The agent already enrolled — filestor-agent enroll … has finished and the agent shows up in Storage → Agent.

1. Create a tunnel on the agent host

cloudflared tunnel login
cloudflared tunnel create filestor-agent

The create command prints a UUID and writes a credentials JSON file like ~/.cloudflared/<uuid>.json. Keep it.

2. Point a hostname at the tunnel

Pick a hostname under your domain — e.g. agent-1.example.com.

cloudflared tunnel route dns filestor-agent agent-1.example.com

3. Configure cloudflared to forward to the agent

Create ~/.cloudflared/config.yml:

tunnel: <uuid-from-step-1>
credentials-file: /home/<you>/.cloudflared/<uuid>.json

ingress:
  - hostname: agent-1.example.com
    service: http://127.0.0.1:8443
  - service: http_status:404

The agent's HTTP server defaults to 127.0.0.1:8443 — loopback only, the public side is reachable solely through cloudflared.

4. Enable the tunnel in Filestor

In Filestor: Storage → Agent. Find your agent, click Tunnel. Enter your hostname and click Enable.

Important: A signing key is generated and shown exactly once. Copy it before closing the dialog.

5. Paste the signing key into the agent

filestor-agent configure-tunnel \
  --hostname agent-1.example.com \
  --key <paste-key-here>

This persists the key in ~/.config/filestor-agent/config.json. Restart the agent + cloudflared:

systemctl --user restart filestor-agent
cloudflared tunnel run filestor-agent

Verify it works

Download a file from the agent root in Filestor. In the browser network panel, the request to /api/file/content?path=… returns 302 with a Location header at your tunnel hostname. The byte stream that follows comes from Cloudflare, not Filestor.

How auth works

  • Filestor checks your cookie session + ACLs at /api/file/content.
  • It mints an HMAC-SHA256-signed URL using the per-agent signing key.
  • The token carries the file path, expiry (5 min), and agent ID — all covered by the signature.
  • Cloudflared forwards the request to the agent unchanged.
  • The agent verifies the signature, expiry, and that the path is inside its allowed roots.
  • Range requests work natively (resumable downloads, video seeking).

Rotate the signing key any time from the Tunnel dialog. Disabling the tunnel reverts to the WS proxy path automatically.

Troubleshooting

  • Cloudflare error page in the browser. Cloudflared isn't running or doesn't ingress to 127.0.0.1:8443. Check cloudflared tunnel info.
  • 401 "bad signature". Mismatched key. Use Rotate key in the Tunnel dialog and re-paste.
  • 401 "token expired". URL was older than 5 minutes when followed. Reload the file viewer.
  • 403 "path not allowed". The file lives outside the agent's --allowed-roots. Re-enroll with the broader set.
  • File viewer dialog hits CORS errors. Direct downloads work without CORS. For in-app preview via fetch().blob(), configure cloudflared to add CORS headers for your Filestor origin.