How to Configure an R2 Bucket as a Read-Only Mount in Cloudflare Workspace
Use the R2Bucket factory from @cloudflare/computer to create an eager mount that streams R2 objects into the workspace's virtual file system at startup, defaulting to read-only mode.
Cloudflare Computer's Mount Interface enables a Workspace to populate a subtree of its virtual file system from external data sources. The built-in R2Bucket provider creates an eager mount that lists and streams objects from an R2 bucket directly into the VFS when the workspace initializes. This guide explains how to configure a read-only R2 mount, which prevents any write operations under the mount root.
Understanding the R2Bucket Mount Provider
The R2Bucket provider lives in packages/computer/src/mounts/providers/r2.ts and implements eager materialization. According to the Cloudflare Computer source code, when mounting an R2 bucket, the provider performs three key operations at startup:
- Lists all objects under the specified prefix using
R2BucketBinding.list(), with pagination controlled bylistLimit - Fetches each object via
R2BucketBinding.get()and pipes the streaming body directly intoMountWriteAPI.writeFile()without intermediate buffering - Sets
mode: "read-only"by default, causing anyfs.writeFile,fs.rm, or other mutating operations to raiseEROFS
The high-level contract is documented in docs/06_mount_interface.md.
Step-by-Step Configuration
Follow these steps to configure a read-only R2 mount in your Cloudflare Workspace.
1. Import the R2Bucket Factory
Import the provider from the @cloudflare/computer package:
import { R2Bucket } from "@cloudflare/computer";
2. Declare the R2 Binding in wrangler.toml
Before using the mount, declare your R2 bucket binding in wrangler.toml:
[[r2_buckets]]
binding = "SHARED_FILES"
bucket_name = "my-bucket"
This makes the bucket available as env.SHARED_FILES in your worker.
3. Add the Mount to Workspace Options
Instantiate Workspace with a mounts configuration pointing to your R2 binding:
import { Workspace, R2Bucket } from "@cloudflare/computer";
const ws = new Workspace({
// ... other workspace options
mounts: {
"/workspace/r2": R2Bucket(env.SHARED_FILES, {
prefix: "public/",
}),
},
});
Key configuration points:
- Mount root: Must be an absolute path (e.g.,
/workspace/r2) - R2 binding: Pass the binding from your Worker environment
- prefix (optional): Scopes visible keys to a subdirectory
4. Leverage the Default Read-Only Mode
The mode option defaults to "read-only". No explicit flag is required. Attempting to write or delete files under /workspace/r2 will throw EROFS (read-only file system error).
Complete Working Example
Here's a minimal worker implementation from worker-shell/src/index.ts patterns:
import { Workspace, R2Bucket } from "@cloudflare/computer";
interface Env {
SHARED_FILES: R2Bucket;
}
export default {
async fetch(request: Request, env: Env) {
const ws = new Workspace({
mounts: {
"/workspace/r2": R2Bucket(env.SHARED_FILES, {
prefix: "public/",
// mode: "read-only" is implied
}),
},
});
// Reads from /workspace/r2 serve directly from R2
// Writes throw EROFS
const result = await ws.run(async (fs) => {
const content = await fs.readFile("/workspace/r2/data.json", "utf-8");
return JSON.parse(content);
});
return Response.json(result);
},
};
Key Files and References
| File | Purpose |
|---|---|
packages/computer/src/mounts/providers/r2.ts |
R2Bucket factory implementation and eager streaming logic |
docs/06_mount_interface.md |
Mount API documentation and read-only semantics |
examples/worker-shell/README.md |
Concrete worker examples with R2 mounts |
Summary
- Import
R2Bucketfrom@cloudflare/computerto create R2-backed mounts - Configure the mount with an absolute path, R2 binding, and optional
prefix - Rely on defaults: Read-only mode is automatic; omit
modeor set explicitly to"read-only" - Expect eager loading: All matching objects stream into VFS at workspace startup
- Handle
EROFS: Any write operations under the mount root will fail with read-only file system errors
Frequently Asked Questions
What happens if I try to write to a read-only R2 mount?
Any fs.writeFile, fs.rm, fs.mkdir, or similar operation under a read-only mount path throws EROFS (Error Read-Only File System). This is enforced by the VFS layer before reaching the R2 provider.
Can I switch from read-only to read-write mode?
Yes. Pass mode: "read-write" in the R2Bucket options. However, as noted in docs/06_mount_interface.md, read-write mounts require additional considerations for durability and consistency that read-only mounts avoid.
Does the R2Bucket mount cache data locally?
No. The R2Bucket provider streams object bodies directly from R2BucketBinding.get() into MountWriteAPI.writeFile() without intermediate buffering. Each object is fetched once at mount time, not on every read.
How do I limit which R2 objects appear in the mount?
Use the prefix option when calling R2Bucket(). Only keys beginning with that prefix are listed and mounted; everything else remains invisible to the workspace.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →